From a09d86dd3cc3fd31404e6403cfc5d9c7020f944f Mon Sep 17 00:00:00 2001
From: Perttu Ahola <celeron55@gmail.com>
Date: Sun, 3 Jun 2012 18:30:34 +0300
Subject: [PATCH] Update inventory menu from formspec on-the-fly

---
 src/game.cpp             | 24 ++++++++++++++++++++++++
 src/guiInventoryMenu.cpp | 27 +++++++++++++++++----------
 src/guiInventoryMenu.h   | 14 ++++++++++++++
 3 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/src/game.cpp b/src/game.cpp
index 768bb5602..69b3c321a 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -132,6 +132,28 @@ class MainRespawnInitiator: public IRespawnInitiator
 	Client *m_client;
 };
 
+/* Form update callback */
+
+class NodeMetadataFormSource: public IFormSource
+{
+public:
+	NodeMetadataFormSource(ClientMap *map, v3s16 p):
+		m_map(map),
+		m_p(p)
+	{
+	}
+	std::string getForm()
+	{
+		NodeMetadata *meta = m_map->getNodeMetadata(m_p);
+		if(!meta)
+			return "";
+		return meta->getString("formspec");
+	}
+
+	ClientMap *m_map;
+	v3s16 m_p;
+};
+
 /*
 	Hotbar draw routine
 */
@@ -2348,6 +2370,8 @@ void the_game(
 							&client, gamedef);
 					menu->setFormSpec(meta->getString("formspec"),
 							inventoryloc);
+					menu->setFormSource(new NodeMetadataFormSource(
+							&client.getEnv().getClientMap(), nodepos));
 					menu->drop();
 				}
 				// Otherwise report right click to server
diff --git a/src/guiInventoryMenu.cpp b/src/guiInventoryMenu.cpp
index 492ea1c19..9898fd5aa 100644
--- a/src/guiInventoryMenu.cpp
+++ b/src/guiInventoryMenu.cpp
@@ -126,23 +126,24 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
 		IMenuManager *menumgr,
 		InventoryManager *invmgr,
 		IGameDef *gamedef
-		):
+):
 	GUIModalMenu(env, parent, id, menumgr),
 	m_invmgr(invmgr),
-	m_gamedef(gamedef)
+	m_gamedef(gamedef),
+	m_form_src(NULL),
+	m_selected_item(NULL),
+	m_selected_amount(0),
+	m_selected_dragging(false),
+	m_tooltip_element(NULL)
 {
-	m_selected_item = NULL;
-	m_selected_amount = 0;
-	m_selected_dragging = false;
-	m_tooltip_element = NULL;
 }
 
 GUIInventoryMenu::~GUIInventoryMenu()
 {
 	removeChildren();
 
-	if(m_selected_item)
-		delete m_selected_item;
+	delete m_selected_item;
+	delete m_form_src;
 }
 
 void GUIInventoryMenu::removeChildren()
@@ -244,8 +245,6 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize)
 			pos.X += stof(f.next(",")) * (float)spacing.X;
 			pos.Y += stof(f.next(";")) * (float)spacing.Y;
 			v2s32 geom;
-			/*geom.X = imgsize.X + ((stoi(f.next(","))-1) * spacing.X);
-			geom.Y = imgsize.Y + ((stoi(f.next(";"))-1) * spacing.Y);*/
 			geom.X = stof(f.next(",")) * (float)imgsize.X;
 			geom.Y = stof(f.next(";")) * (float)imgsize.Y;
 			std::string name = f.next("]");
@@ -430,6 +429,14 @@ void GUIInventoryMenu::drawSelectedItem()
 
 void GUIInventoryMenu::drawMenu()
 {
+	if(m_form_src){
+		std::string newform = m_form_src->getForm();
+		if(newform != m_formspec_string){
+			m_formspec_string = newform;
+			regenerateGui(m_screensize_old);
+		}
+	}
+
 	updateSelectedItem();
 
 	gui::IGUISkin* skin = Environment->getSkin();
diff --git a/src/guiInventoryMenu.h b/src/guiInventoryMenu.h
index beb6ef2e8..3f03064df 100644
--- a/src/guiInventoryMenu.h
+++ b/src/guiInventoryMenu.h
@@ -30,6 +30,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 class IGameDef;
 class InventoryManager;
 
+class IFormSource
+{
+public:
+	virtual ~IFormSource(){}
+	virtual std::string getForm() = 0;
+};
+
 void drawItemStack(video::IVideoDriver *driver,
 		gui::IGUIFont *font,
 		const ItemStack &item,
@@ -117,6 +124,12 @@ class GUIInventoryMenu : public GUIModalMenu
 		m_current_inventory_location = current_inventory_location;
 		regenerateGui(m_screensize_old);
 	}
+	
+	// form_src is deleted by this GUIInventoryMenu
+	void setFormSource(IFormSource *form_src)
+	{
+		m_form_src = form_src;
+	}
 
 	void removeChildren();
 	/*
@@ -147,6 +160,7 @@ class GUIInventoryMenu : public GUIModalMenu
 
 	std::string m_formspec_string;
 	InventoryLocation m_current_inventory_location;
+	IFormSource *m_form_src;
 
 	core::array<ListDrawSpec> m_inventorylists;
 	core::array<ImageDrawSpec> m_images;
-- 
GitLab