Browse Source

FormspecMenu: make drawing of backgrounds less hacky (#9517)

DS 2 years ago
parent
commit
633e23bd65

+ 28 - 1
games/devtest/mods/testformspec/formspec.lua

@@ -430,6 +430,33 @@ mouse control = true]
 			checkbox[0.5,5.5.5;snd_chk;Sound;]
 			tabheader[0.5,7;8,0.65;snd_tab;Soundtab1,Soundtab2,Soundtab3;1;false;false]
 		]],
+
+	-- Background
+		[[
+			formspec_version[3]
+			size[12,13]
+			box[0,0;12,13;#f0f1]
+			background[0,0;0,0;testformspec_bg.png;true]
+			box[3.9,2.9;6.2,4.2;#d00f]
+			scroll_container[4,3;6,4;scrbar;vertical]
+				background9[1,0.5;0,0;testformspec_bg_9slice.png;true;4,6]
+				label[0,0.2;Backgrounds are not be applied to scroll containers,]
+				label[0,0.5;but to the whole form.]
+			scroll_container_end[]
+			scrollbar[3.5,3;0.3,4;vertical;scrbar;0]
+			container[2,11]
+				box[-0.1,0.5;3.2,1;#fff5]
+				background[0,0;2,3;testformspec_bg.png;false]
+				background9[1,0;2,3;testformspec_bg_9slice.png;false;4,6]
+			container_end[]
+		]],
+
+	-- Unsized
+		[[
+			formspec_version[3]
+			background9[0,0;0,0;testformspec_bg_9slice.png;true;4,6]
+			background[1,1;0,0;testformspec_bg.png;true]
+		]],
 }
 
 local page_id = 2
@@ -439,7 +466,7 @@ local function show_test_formspec(pname)
 		page = page()
 	end
 
-	local fs = page .. "tabheader[0,0;8,0.65;maintabs;Real Coord,Styles,Noclip,Hypertext,Tabs,Invs,Window,Anim,Model,ScrollC,Sound;" .. page_id .. ";false;false]"
+	local fs = page .. "tabheader[0,0;11,0.65;maintabs;Real Coord,Styles,Noclip,Hypertext,Tabs,Invs,Window,Anim,Model,ScrollC,Sound,Background,Unsized;" .. page_id .. ";false;false]"
 
 	minetest.show_formspec(pname, "testformspec:formspec", fs)
 end

+ 1 - 1
src/gui/guiBackgroundImage.cpp

@@ -44,7 +44,7 @@ void GUIBackgroundImage::draw()
 
 	core::rect<s32> rect = AbsoluteRect;
 	if (m_autoclip)
-		rect.LowerRightCorner += Parent->getAbsolutePosition().getSize();
+		rect.LowerRightCorner += Parent->getAbsoluteClippingRect().getSize();
 
 	video::IVideoDriver *driver = Environment->getVideoDriver();
 

+ 12 - 19
src/gui/guiFormSpecMenu.cpp

@@ -137,8 +137,6 @@ GUIFormSpecMenu::~GUIFormSpecMenu()
 		checkbox_it.second->drop();
 	for (auto &scrollbar_it : m_scrollbars)
 		scrollbar_it.second->drop();
-	for (auto &background_it : m_backgrounds)
-		background_it->drop();
 	for (auto &tooltip_rect_it : m_tooltip_rects)
 		tooltip_rect_it.first->drop();
 	for (auto &clickthrough_it : m_clickthrough_elements)
@@ -1124,17 +1122,15 @@ void GUIFormSpecMenu::parseBackground(parserData* data, const std::string &eleme
 		rect = core::rect<s32>(-pos, pos);
 	}
 
-	GUIBackgroundImage *e = new GUIBackgroundImage(Environment, this, spec.fid,
-			rect, name, middle, m_tsrc, clip);
+	GUIBackgroundImage *e = new GUIBackgroundImage(Environment, data->background_parent.get(),
+			spec.fid, rect, name, middle, m_tsrc, clip);
 
 	FATAL_ERROR_IF(!e, "Failed to create background formspec element");
 
 	e->setNotClipped(true);
 
-	e->setVisible(false); // the element is drawn manually before all others
-
-	m_backgrounds.push_back(e);
 	m_fields.push_back(spec);
+	e->drop();
 }
 
 void GUIFormSpecMenu::parseTableOptions(parserData* data, const std::string &element)
@@ -3059,8 +3055,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 		checkbox_it.second->drop();
 	for (auto &scrollbar_it : m_scrollbars)
 		scrollbar_it.second->drop();
-	for (auto &background_it : m_backgrounds)
-		background_it->drop();
 	for (auto &tooltip_rect_it : m_tooltip_rects)
 		tooltip_rect_it.first->drop();
 	for (auto &clickthrough_it : m_clickthrough_elements)
@@ -3082,7 +3076,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 	mydata.current_parent = this;
 
 	m_inventorylists.clear();
-	m_backgrounds.clear();
 	m_tables.clear();
 	m_checkboxes.clear();
 	m_scrollbars.clear();
@@ -3336,6 +3329,15 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 	gui::IGUIFont *old_font = skin->getFont();
 	skin->setFont(m_font);
 
+	// Add a new element that will hold all the background elements as its children.
+	// Because it is the first added element, all backgrounds will be behind all
+	// the other elements.
+	// (We use an arbitrarily big rect. The actual size is determined later by
+	// clipping to `this`.)
+	core::rect<s32> background_parent_rect(0, 0, 100000, 100000);
+	mydata.background_parent.reset(new gui::IGUIElement(EGUIET_ELEMENT, Environment,
+			this, -1, background_parent_rect));
+
 	pos_offset = v2f32();
 
 	// used for formspec versions < 3
@@ -3591,15 +3593,6 @@ void GUIFormSpecMenu::drawMenu()
 		}
 	}
 
-	/*
-		Draw backgrounds
-	*/
-	for (gui::IGUIElement *e : m_backgrounds) {
-		e->setVisible(true);
-		e->draw();
-		e->setVisible(false);
-	}
-
 	// Some elements are only visible while being drawn
 	for (gui::IGUIElement *e : m_clickthrough_elements)
 		e->setVisible(true);

+ 2 - 1
src/gui/guiFormSpecMenu.h

@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <unordered_set>
 
 #include "irrlichttypes_extrabloated.h"
+#include "irr_ptr.h"
 #include "inventorymanager.h"
 #include "modalMenu.h"
 #include "guiInventoryList.h"
@@ -313,7 +314,6 @@ protected:
 
 	std::vector<GUIInventoryList *> m_inventorylists;
 	std::vector<ListRingSpec> m_inventory_rings;
-	std::vector<gui::IGUIElement *> m_backgrounds;
 	std::unordered_map<std::string, bool> field_close_on_enter;
 	std::unordered_map<std::string, bool> m_dropdown_index_event;
 	std::vector<FieldSpec> m_fields;
@@ -375,6 +375,7 @@ private:
 		GUITable::TableOptions table_options;
 		GUITable::TableColumns table_columns;
 		gui::IGUIElement *current_parent = nullptr;
+		irr_ptr<gui::IGUIElement> background_parent;
 
 		GUIInventoryList::Options inventorylist_options;