Skip to content

Commit

Permalink
Mainmenu: Avoid the header being displayed behind the formspec (#13924)
Browse files Browse the repository at this point in the history
This change keeps the current header placement code, but adds additional code to make sure the header doesn't end up behind the formspec.
  • Loading branch information
grorp committed Nov 25, 2023
1 parent 6783734 commit 4255ac3
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 10 deletions.
52 changes: 42 additions & 10 deletions src/gui/guiEngine.cpp
Expand Up @@ -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();
Expand Down Expand Up @@ -478,29 +483,56 @@ void GUIEngine::drawHeader(video::IVideoDriver *driver)

video::ITexture* texture = m_textures[TEX_LAYER_HEADER].texture;

/* If no texture, draw nothing */
if(!texture)
// 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),
((free_space/2)-splashsize.Y/2)+10);
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);

/*
* 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();
}

draw2DImageFilterScaled(driver, texture, splashrect,
// 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);
}
}

/******************************************************************************/
Expand Down
10 changes: 10 additions & 0 deletions src/gui/guiFormSpecMenu.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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");
Expand Down
6 changes: 6 additions & 0 deletions src/gui/guiFormSpecMenu.h
Expand Up @@ -282,6 +282,9 @@ class GUIFormSpecMenu : public GUIModalMenu
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
Expand Down Expand Up @@ -499,6 +502,9 @@ class GUIFormSpecMenu : public GUIModalMenu

int m_btn_height;
gui::IGUIFont *m_font = nullptr;

// used by getAbsoluteRect
s32 m_tabheader_upper_edge = 0;
};

class FormspecFormSource: public IFormSource
Expand Down

0 comments on commit 4255ac3

Please sign in to comment.