Mainmenu: Avoid the header being displayed behind the formspec ()

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:
grorp 2023-11-25 17:04:33 +01:00 committed by GitHub
parent 6783734612
commit 4255ac3022
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 10 deletions

View file

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

View file

@ -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");

View file

@ -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