From e4f7c92cff0badd6c40b47bd90b1fc1b35456a1a Mon Sep 17 00:00:00 2001
From: est31 <MTest31@outlook.com>
Date: Sun, 15 Mar 2015 07:25:22 +0100
Subject: Finer progress bar updates when initializing nodes

The bar is only drawn when the user will notice a change, which prevents time overheads that this commit would cause, resulting from useless draws.
---
 src/client.cpp  | 47 +++++++++++++++++++++++++++++++++++++++++++----
 src/client.h    |  2 +-
 src/game.cpp    |  2 +-
 src/nodedef.cpp | 14 +++++++++++---
 src/nodedef.h   |  4 +++-
 5 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/src/client.cpp b/src/client.cpp
index 7d2fab179..8a9d62d29 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -1553,7 +1553,39 @@ float Client::mediaReceiveProgress()
 		return 1.0; // downloader only exists when not yet done
 }
 
-void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
+typedef struct TextureUpdateArgs {
+	IrrlichtDevice *device;
+	gui::IGUIEnvironment *guienv;
+	u32 last_time_ms;
+	u16 last_percent;
+	const wchar_t* text_base;
+} TextureUpdateArgs;
+
+void texture_update_progress(void *args, u32 progress, u32 max_progress)
+{
+		TextureUpdateArgs* targs = (TextureUpdateArgs*) args;
+		u16 cur_percent = ceil(progress / (double) max_progress * 100.);
+
+		// update the loading menu -- if neccessary
+		bool do_draw = false;
+		u32 time_ms = targs->last_time_ms;
+		if (cur_percent != targs->last_percent) {
+			targs->last_percent = cur_percent;
+			time_ms = getTimeMs();
+			// only draw when the user will notice something:
+			do_draw = (time_ms - targs->last_time_ms > 100);
+		}
+
+		if (do_draw) {
+			targs->last_time_ms = time_ms;
+			std::basic_stringstream<wchar_t> strm;
+			strm << targs->text_base << " " << targs->last_percent << "%...";
+			draw_load_screen(strm.str(), targs->device, targs->guienv, 0,
+				72 + (u16) ((18. / 100.) * (double) targs->last_percent));
+		}
+}
+
+void Client::afterContentReceived(IrrlichtDevice *device)
 {
 	infostream<<"Client::afterContentReceived() started"<<std::endl;
 	assert(m_itemdef_received); // pre-condition
@@ -1571,14 +1603,14 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
 	// Rebuild shaders
 	infostream<<"- Rebuilding shaders"<<std::endl;
 	text = wgettext("Rebuilding shaders...");
-	draw_load_screen(text, device, guienv, 0, 75);
+	draw_load_screen(text, device, guienv, 0, 71);
 	m_shsrc->rebuildShaders();
 	delete[] text;
 
 	// Update node aliases
 	infostream<<"- Updating node aliases"<<std::endl;
 	text = wgettext("Initializing nodes...");
-	draw_load_screen(text, device, guienv, 0, 80);
+	draw_load_screen(text, device, guienv, 0, 72);
 	m_nodedef->updateAliases(m_itemdef);
 	m_nodedef->setNodeRegistrationStatus(true);
 	m_nodedef->runNodeResolverCallbacks();
@@ -1586,7 +1618,14 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
 
 	// Update node textures and assign shaders to each tile
 	infostream<<"- Updating node textures"<<std::endl;
-	m_nodedef->updateTextures(this);
+	TextureUpdateArgs tu_args;
+	tu_args.device = device;
+	tu_args.guienv = guienv;
+	tu_args.last_time_ms = getTimeMs();
+	tu_args.last_percent = 0;
+	tu_args.text_base =  wgettext("Initializing nodes");
+	m_nodedef->updateTextures(this, texture_update_progress, &tu_args);
+	delete[] tu_args.text_base;
 
 	// Preload item textures and meshes if configured to
 	if(g_settings->getBool("preload_item_visuals"))
diff --git a/src/client.h b/src/client.h
index 9baa034de..a455213e9 100644
--- a/src/client.h
+++ b/src/client.h
@@ -492,7 +492,7 @@ public:
 
 	float mediaReceiveProgress();
 
-	void afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font);
+	void afterContentReceived(IrrlichtDevice *device);
 
 	float getRTT(void);
 	float getCurRate(void);
diff --git a/src/game.cpp b/src/game.cpp
index 7b6d2a3c1..937f6cb23 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -1998,7 +1998,7 @@ bool Game::createClient(const std::string &playername,
 	}
 
 	// Update cached textures, meshes and materials
-	client->afterContentReceived(device, g_fontengine->getFont());
+	client->afterContentReceived(device);
 
 	/* Camera
 	 */
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index a0dcf6b71..4aee1b1c6 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -398,7 +398,9 @@ public:
 	virtual content_t set(const std::string &name, const ContentFeatures &def);
 	virtual content_t allocateDummy(const std::string &name);
 	virtual void updateAliases(IItemDefManager *idef);
-	virtual void updateTextures(IGameDef *gamedef);
+	virtual void updateTextures(IGameDef *gamedef,
+	/*argument: */void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
+	/*argument: */void *progress_callback_args);
 	void serialize(std::ostream &os, u16 protocol_version);
 	void deSerialize(std::istream &is);
 
@@ -715,7 +717,9 @@ void CNodeDefManager::updateAliases(IItemDefManager *idef)
 }
 
 
-void CNodeDefManager::updateTextures(IGameDef *gamedef)
+void CNodeDefManager::updateTextures(IGameDef *gamedef,
+	void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
+	void *progress_callback_args)
 {
 #ifndef SERVER
 	infostream << "CNodeDefManager::updateTextures(): Updating "
@@ -738,7 +742,9 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef)
 	bool use_normal_texture = enable_shaders &&
 		(enable_bumpmapping || enable_parallax_occlusion);
 
-	for (u32 i = 0; i < m_content_features.size(); i++) {
+	u32 size = m_content_features.size();
+
+	for (u32 i = 0; i < size; i++) {
 		ContentFeatures *f = &m_content_features[i];
 
 		// Figure out the actual tiles to use
@@ -911,6 +917,8 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef)
 			recalculateBoundingBox(f->mesh_ptr[0]);
 			meshmanip->recalculateNormals(f->mesh_ptr[0], true, false);
 		}
+
+		progress_callback(progress_callback_args, i, size);
 	}
 #endif
 }
diff --git a/src/nodedef.h b/src/nodedef.h
index a1c2e1b53..bd13a7bb2 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -378,7 +378,9 @@ public:
 	/*
 		Update tile textures to latest return values of TextueSource.
 	*/
-	virtual void updateTextures(IGameDef *gamedef)=0;
+	virtual void updateTextures(IGameDef *gamedef,
+	/*argument: */void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
+	/*argument: */void *progress_callback_args)=0;
 
 	virtual void serialize(std::ostream &os, u16 protocol_version)=0;
 	virtual void deSerialize(std::istream &is)=0;
-- 
cgit v1.2.3