mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 09:15:29 +01:00 
			
		
		
		
	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:
		@@ -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),
 | 
			
		||||
				((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);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************************************/
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user