forked from Mirrorlandia_minetest/minetest
Mainmenu: Avoid the header being displayed behind the formspec (#13924)
This change keeps the current header placement code, but adds additional code to make sure the header doesn't end up behind the formspec.
This commit is contained in:
parent
6783734612
commit
4255ac3022
@ -283,11 +283,16 @@ void GUIEngine::run()
|
||||
else
|
||||
drawBackground(driver);
|
||||
|
||||
drawHeader(driver);
|
||||
drawFooter(driver);
|
||||
|
||||
m_rendering_engine->get_gui_env()->drawAll();
|
||||
|
||||
// The header *must* be drawn after the menu because it uses
|
||||
// GUIFormspecMenu::getAbsoluteRect().
|
||||
// The header *can* be drawn after the menu because it never intersects
|
||||
// the menu.
|
||||
drawHeader(driver);
|
||||
|
||||
driver->endScene();
|
||||
|
||||
IrrlichtDevice *device = m_rendering_engine->get_raw_device();
|
||||
@ -478,30 +483,57 @@ void GUIEngine::drawHeader(video::IVideoDriver *driver)
|
||||
|
||||
video::ITexture* texture = m_textures[TEX_LAYER_HEADER].texture;
|
||||
|
||||
/* If no texture, draw nothing */
|
||||
// If no texture, draw nothing
|
||||
if (!texture)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Calculate the maximum rectangle
|
||||
*/
|
||||
core::rect<s32> formspec_rect = m_menu->getAbsoluteRect();
|
||||
// 4 px of padding on each side
|
||||
core::rect<s32> max_rect(4, 4, screensize.Width - 8, formspec_rect.UpperLeftCorner.Y - 8);
|
||||
|
||||
// If no space (less than 16x16 px), draw nothing
|
||||
if (max_rect.getWidth() < 16 || max_rect.getHeight() < 16)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Calculate the preferred rectangle
|
||||
*/
|
||||
f32 mult = (((f32)screensize.Width / 2.0)) /
|
||||
((f32)texture->getOriginalSize().Width);
|
||||
|
||||
v2s32 splashsize(((f32)texture->getOriginalSize().Width) * mult,
|
||||
((f32)texture->getOriginalSize().Height) * mult);
|
||||
|
||||
// Don't draw the header if there isn't enough room
|
||||
s32 free_space = (((s32)screensize.Height)-320)/2;
|
||||
|
||||
if (free_space > splashsize.Y) {
|
||||
core::rect<s32> splashrect(0, 0, splashsize.X, splashsize.Y);
|
||||
splashrect += v2s32((screensize.Width/2)-(splashsize.X/2),
|
||||
core::rect<s32> desired_rect(0, 0, splashsize.X, splashsize.Y);
|
||||
desired_rect += v2s32((screensize.Width/2)-(splashsize.X/2),
|
||||
((free_space/2)-splashsize.Y/2)+10);
|
||||
|
||||
draw2DImageFilterScaled(driver, texture, splashrect,
|
||||
/*
|
||||
* Make the preferred rectangle fit into the maximum rectangle
|
||||
*/
|
||||
// 1. Scale
|
||||
f32 scale = std::min((f32)max_rect.getWidth() / (f32)desired_rect.getWidth(),
|
||||
(f32)max_rect.getHeight() / (f32)desired_rect.getHeight());
|
||||
if (scale < 1.0f) {
|
||||
v2s32 old_center = desired_rect.getCenter();
|
||||
desired_rect.LowerRightCorner.X = desired_rect.UpperLeftCorner.X + desired_rect.getWidth() * scale;
|
||||
desired_rect.LowerRightCorner.Y = desired_rect.UpperLeftCorner.Y + desired_rect.getHeight() * scale;
|
||||
desired_rect += old_center - desired_rect.getCenter();
|
||||
}
|
||||
|
||||
// 2. Move
|
||||
desired_rect.constrainTo(max_rect);
|
||||
|
||||
draw2DImageFilterScaled(driver, texture, desired_rect,
|
||||
core::rect<s32>(core::position2d<s32>(0,0),
|
||||
core::dimension2di(texture->getOriginalSize())),
|
||||
NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void GUIEngine::drawFooter(video::IVideoDriver *driver)
|
||||
|
@ -247,6 +247,14 @@ std::vector<std::string>* GUIFormSpecMenu::getDropDownValues(const std::string &
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This will only return a meaningful value if called after drawMenu().
|
||||
core::rect<s32> GUIFormSpecMenu::getAbsoluteRect()
|
||||
{
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
rect.UpperLeftCorner.Y += m_tabheader_upper_edge;
|
||||
return rect;
|
||||
}
|
||||
|
||||
v2s32 GUIFormSpecMenu::getElementBasePos(const std::vector<std::string> *v_pos)
|
||||
{
|
||||
v2f32 pos_f = v2f32(padding.X, padding.Y) + pos_offset * spacing;
|
||||
@ -2104,6 +2112,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen
|
||||
e->setActiveTab(tab_index);
|
||||
|
||||
m_fields.push_back(spec);
|
||||
m_tabheader_upper_edge = MYMIN(m_tabheader_upper_edge, rect.UpperLeftCorner.Y);
|
||||
}
|
||||
|
||||
void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &element)
|
||||
@ -3105,6 +3114,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||
|
||||
m_formspec_version = 1;
|
||||
m_bgcolor = video::SColor(140, 0, 0, 0);
|
||||
m_tabheader_upper_edge = 0;
|
||||
|
||||
{
|
||||
v3f formspec_bgcolor = g_settings->getV3F("formspec_fullscreen_bg_color");
|
||||
|
@ -282,6 +282,9 @@ public:
|
||||
GUITable* getTable(const std::string &tablename);
|
||||
std::vector<std::string>* getDropDownValues(const std::string &name);
|
||||
|
||||
// This will only return a meaningful value if called after drawMenu().
|
||||
core::rect<s32> getAbsoluteRect();
|
||||
|
||||
#ifdef __ANDROID__
|
||||
bool getAndroidUIInput();
|
||||
#endif
|
||||
@ -499,6 +502,9 @@ private:
|
||||
|
||||
int m_btn_height;
|
||||
gui::IGUIFont *m_font = nullptr;
|
||||
|
||||
// used by getAbsoluteRect
|
||||
s32 m_tabheader_upper_edge = 0;
|
||||
};
|
||||
|
||||
class FormspecFormSource: public IFormSource
|
||||
|
Loading…
Reference in New Issue
Block a user