From 58e6d25e033c76dc91aaac18fdeda92ac23fe0e1 Mon Sep 17 00:00:00 2001
From: RealBadAngel <maciej.kasatkin@o2.pl>
Date: Tue, 16 Sep 2014 12:38:37 +0200
Subject: [PATCH] Node highlighting.

---
 minetest.conf.example       |   2 +
 src/client.cpp              |  18 ++++++--
 src/client.h                |   5 +++
 src/content_mapblock.cpp    |  63 +++++++++++++++++++++++----
 src/defaultsettings.cpp     |   1 +
 src/game.cpp                |  28 +++++++-----
 src/mapblock_mesh.cpp       |  82 +++++++++++++++++++++++++-----------
 src/mapblock_mesh.h         |  15 +++++++
 src/tile.h                  |   1 +
 textures/base/pack/halo.png | Bin 0 -> 177 bytes
 10 files changed, 167 insertions(+), 48 deletions(-)
 create mode 100644 textures/base/pack/halo.png

diff --git a/minetest.conf.example b/minetest.conf.example
index fe62b0f7e..8609281e8 100644
--- a/minetest.conf.example
+++ b/minetest.conf.example
@@ -160,6 +160,8 @@
 # maximum percentage of current window to be used for hotbar
 # (usefull if you've there's something to be displayed right or left of hotbar)
 #hud_hotbar_max_width = 1.0
+# Enable highlighting for nodes (disables selectionboxes)
+#enable_node_highlighting = false
 # Texture filtering settings
 #mip_map = false
 #anisotropic_filter = false
diff --git a/src/client.cpp b/src/client.cpp
index 459d371c2..30280369f 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -2475,6 +2475,15 @@ int Client::getCrackLevel()
 	return m_crack_level;
 }
 
+void Client::setHighlighted(v3s16 pos, bool show_hud)
+{
+	m_show_hud = show_hud;
+	v3s16 old_highlighted_pos = m_highlighted_pos;
+	m_highlighted_pos = pos;
+	addUpdateMeshTaskForNode(old_highlighted_pos, false, true);
+	addUpdateMeshTaskForNode(m_highlighted_pos, false, true);
+}
+
 void Client::setCrack(int level, v3s16 pos)
 {
 	int old_crack_level = m_crack_level;
@@ -2547,22 +2556,23 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent)
 	MapBlock *b = m_env.getMap().getBlockNoCreateNoEx(p);
 	if(b == NULL)
 		return;
-	
+
 	/*
 		Create a task to update the mesh of the block
 	*/
-	
+
 	MeshMakeData *data = new MeshMakeData(this);
-	
+
 	{
 		//TimeTaker timer("data fill");
 		// Release: ~0ms
 		// Debug: 1-6ms, avg=2ms
 		data->fill(b);
 		data->setCrack(m_crack_level, m_crack_pos);
+		data->setHighlighted(m_highlighted_pos, m_show_hud);
 		data->setSmoothLighting(g_settings->getBool("smooth_lighting"));
 	}
-	
+
 	// Add task to queue
 	m_mesh_update_thread.m_queue_in.addBlock(p, data, ack_to_server, urgent);
 }
diff --git a/src/client.h b/src/client.h
index 51ce5b8f2..8bffbd1db 100644
--- a/src/client.h
+++ b/src/client.h
@@ -395,6 +395,9 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
 	int getCrackLevel();
 	void setCrack(int level, v3s16 pos);
 
+	void setHighlighted(v3s16 pos, bool show_hud);
+	v3s16 getHighlighted(){ return m_highlighted_pos; }
+
 	u16 getHP();
 	u16 getBreath();
 
@@ -500,10 +503,12 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
 	float m_inventory_from_server_age;
 	std::set<v3s16> m_active_blocks;
 	PacketCounter m_packetcounter;
+	bool m_show_hud;
 	// Block mesh animation parameters
 	float m_animation_time;
 	int m_crack_level;
 	v3s16 m_crack_pos;
+	v3s16 m_highlighted_pos;
 	// 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
 	//s32 m_daynight_i;
 	//u32 m_daynight_ratio;
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index baa97a987..0b4b7fd0a 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -169,6 +169,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 		MeshCollector &collector)
 {
 	INodeDefManager *nodedef = data->m_gamedef->ndef();
+	ITextureSource *tsrc = data->m_gamedef->tsrc();
 
 	// 0ms
 	//TimeTaker timer("mapblock_mesh_generate_special()");
@@ -177,26 +178,72 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 		Some settings
 	*/
 	bool new_style_water = g_settings->getBool("new_style_water");
-	
+
 	float node_liquid_level = 1.0;
-	if(new_style_water)
+	if (new_style_water)
 		node_liquid_level = 0.85;
-	
+
 	v3s16 blockpos_nodes = data->m_blockpos*MAP_BLOCKSIZE;
 
-	for(s16 z=0; z<MAP_BLOCKSIZE; z++)
-	for(s16 y=0; y<MAP_BLOCKSIZE; y++)
-	for(s16 x=0; x<MAP_BLOCKSIZE; x++)
+	// Create selection mesh
+	v3s16 p = data->m_highlighted_pos_relative;
+	if (data->m_show_hud & 
+			(p.X >= 0) & (p.X < MAP_BLOCKSIZE) &
+			(p.Y >= 0) & (p.Y < MAP_BLOCKSIZE) &
+			(p.Z >= 0) & (p.Z < MAP_BLOCKSIZE)) {
+
+		MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p);
+		// Get selection mesh light level
+		static const v3s16 dirs[7] = {
+				v3s16( 0, 0, 0),
+				v3s16( 0, 1, 0),
+				v3s16( 0,-1, 0),
+				v3s16( 1, 0, 0),
+				v3s16(-1, 0, 0),
+				v3s16( 0, 0, 1),
+				v3s16( 0, 0,-1)
+		};
+
+		u16 l = 0;
+		u16 l1 = 0;
+		for (u8 i = 0; i < 7; i++) {
+			MapNode n1 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dirs[i]);	
+			l1 = getInteriorLight(n1, -4, nodedef);
+			if (l1 > l) 
+				l = l1;
+		}
+		video::SColor c = MapBlock_LightColor(255, l, 0);
+		data->m_highlight_mesh_color = c;	
+		std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
+		TileSpec h_tile;			
+		h_tile.material_flags |= MATERIAL_FLAG_HIGHLIGHTED;
+		h_tile.texture = tsrc->getTexture("halo.png",&h_tile.texture_id);
+		v3f pos = intToFloat(p, BS);
+		f32 d = 0.05 * BS;
+		for(std::vector<aabb3f>::iterator
+				i = boxes.begin();
+				i != boxes.end(); i++)
+		{
+			aabb3f box = *i;
+			box.MinEdge += v3f(-d, -d, -d) + pos;
+			box.MaxEdge += v3f(d, d, d) + pos;
+			makeCuboid(&collector, box, &h_tile, 1, c, NULL);
+		}
+	}
+
+	for(s16 z = 0; z < MAP_BLOCKSIZE; z++)
+	for(s16 y = 0; y < MAP_BLOCKSIZE; y++)
+	for(s16 x = 0; x < MAP_BLOCKSIZE; x++)
 	{
 		v3s16 p(x,y,z);
 
-		MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes+p);
+		MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p);
 		const ContentFeatures &f = nodedef->get(n);
 
 		// Only solidness=0 stuff is drawn here
 		if(f.solidness != 0)
 			continue;
-		
+
 		switch(f.drawtype){
 		default:
 			infostream<<"Got "<<f.drawtype<<std::endl;
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 9cd17ac91..f3cb69e4b 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -120,6 +120,7 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("console_color", "(0,0,0)");
 	settings->setDefault("console_alpha", "200");
 	settings->setDefault("selectionbox_color", "(0,0,0)");
+	settings->setDefault("enable_node_highlighting", "false");
 	settings->setDefault("crosshair_color", "(255,255,255)");
 	settings->setDefault("crosshair_alpha", "255");
 	settings->setDefault("gui_scaling", "1.0");
diff --git a/src/game.cpp b/src/game.cpp
index cb5fe8046..bae946f28 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -407,14 +407,16 @@ PointedThing getPointedThing(Client *client, v3f player_position,
 				mindistance = distance;
 
 				hilightboxes.clear();
-				for(std::vector<aabb3f>::const_iterator
-						i2 = boxes.begin();
-						i2 != boxes.end(); i2++)
-				{
-					aabb3f box = *i2;
-					box.MinEdge += npf + v3f(-d,-d,-d) - intToFloat(camera_offset, BS);
-					box.MaxEdge += npf + v3f(d,d,d) - intToFloat(camera_offset, BS);
-					hilightboxes.push_back(box);
+				if (!g_settings->getBool("enable_node_highlighting")) {
+					for(std::vector<aabb3f>::const_iterator
+							i2 = boxes.begin();
+							i2 != boxes.end(); i2++)
+					{
+						aabb3f box = *i2;
+						box.MinEdge += npf + v3f(-d,-d,-d) - intToFloat(camera_offset, BS);
+						box.MaxEdge += npf + v3f(d,d,d) - intToFloat(camera_offset, BS);
+						hilightboxes.push_back(box);
+					}
 				}
 			}
 		}
@@ -2096,10 +2098,13 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 		else if(input->wasKeyDown(getKeySetting("keymap_toggle_hud")))
 		{
 			show_hud = !show_hud;
-			if(show_hud)
+			if(show_hud) {
 				statustext = L"HUD shown";
-			else
+				client.setHighlighted(client.getHighlighted(), true);
+			} else {
 				statustext = L"HUD hidden";
+				client.setHighlighted(client.getHighlighted(), false);
+			}
 			statustext_time = 0;
 		}
 		else if(input->wasKeyDown(getKeySetting("keymap_toggle_chat")))
@@ -2796,7 +2801,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
 		if(pointed != pointed_old)
 		{
 			infostream<<"Pointing at "<<pointed.dump()<<std::endl;
-			//dstream<<"Pointing at "<<pointed.dump()<<std::endl;
+			if (g_settings->getBool("enable_node_highlighting"))
+				client.setHighlighted(pointed.node_undersurface, show_hud);
 		}
 
 		/*
diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp
index d3f7c2f39..d75d3e148 100644
--- a/src/mapblock_mesh.cpp
+++ b/src/mapblock_mesh.cpp
@@ -46,6 +46,7 @@ MeshMakeData::MeshMakeData(IGameDef *gamedef):
 	m_vmanip(),
 	m_blockpos(-1337,-1337,-1337),
 	m_crack_pos_relative(-1337, -1337, -1337),
+	m_highlighted_pos_relative(-1337, -1337, -1337),
 	m_smooth_lighting(false),
 	m_gamedef(gamedef)
 {}
@@ -132,6 +133,12 @@ void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos)
 		m_crack_pos_relative = crack_pos - m_blockpos*MAP_BLOCKSIZE;
 }
 
+void MeshMakeData::setHighlighted(v3s16 highlighted_pos, bool show_hud)
+{
+	m_show_hud = show_hud;
+	m_highlighted_pos_relative = highlighted_pos - m_blockpos*MAP_BLOCKSIZE;
+}
+
 void MeshMakeData::setSmoothLighting(bool smooth_lighting)
 {
 	m_smooth_lighting = smooth_lighting;
@@ -651,10 +658,8 @@ TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data)
 	INodeDefManager *ndef = data->m_gamedef->ndef();
 	TileSpec spec = ndef->get(mn).tiles[tileindex];
 	// Apply temporary crack
-	if(p == data->m_crack_pos_relative)
-	{
+	if (p == data->m_crack_pos_relative)
 		spec.material_flags |= MATERIAL_FLAG_CRACK;
-	}
 	return spec;
 }
 
@@ -1008,9 +1013,13 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 	m_animation_force_timer(0), // force initial animation
 	m_last_crack(-1),
 	m_crack_materials(),
+	m_highlighted_materials(),
 	m_last_daynight_ratio((u32) -1),
 	m_daynight_diffs()
 {
+	m_enable_shaders = g_settings->getBool("enable_shaders");
+	m_enable_highlighting = g_settings->getBool("enable_node_highlighting");
+
 	// 4-21ms for MAP_BLOCKSIZE=16  (NOTE: probably outdated)
 	// 24-155ms for MAP_BLOCKSIZE=32  (NOTE: probably outdated)
 	//TimeTaker timer1("MapBlockMesh()");
@@ -1077,6 +1086,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 
 	mapblock_mesh_generate_special(data, collector);
 
+	m_highlight_mesh_color = data->m_highlight_mesh_color; 
 
 	/*
 		Convert MeshCollector to SMesh
@@ -1084,14 +1094,9 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 	ITextureSource *tsrc = m_gamedef->tsrc();
 	IShaderSource *shdrsrc = m_gamedef->getShaderSource();
 
-	bool enable_shaders     = g_settings->getBool("enable_shaders");
-
 	for(u32 i = 0; i < collector.prebuffers.size(); i++)
 	{
 		PreMeshBuffer &p = collector.prebuffers[i];
-		/*dstream<<"p.vertices.size()="<<p.vertices.size()
-				<<", p.indices.size()="<<p.indices.size()
-				<<std::endl;*/
 
 		// Generate animation data
 		// - Cracks
@@ -1129,6 +1134,9 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 			p.tile.texture = animation_frame.texture;
 		}
 
+		if(m_enable_highlighting && p.tile.material_flags & MATERIAL_FLAG_HIGHLIGHTED)
+			m_highlighted_materials.push_back(i);	
+
 		for(u32 j = 0; j < p.vertices.size(); j++)
 		{
 			// Note applyFacesShading second parameter is precalculated sqrt
@@ -1153,8 +1161,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 			u8 day = vc.getRed();
 			u8 night = vc.getGreen();
 			finalColorBlend(vc, day, night, 1000);
-			if(day != night)
-				m_daynight_diffs[i][j] = std::make_pair(day, night);
+			m_daynight_diffs[i][j] = std::make_pair(day, night);
 		}
 
 		// Create material
@@ -1163,22 +1170,23 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 		material.setFlag(video::EMF_BACK_FACE_CULLING, true);
 		material.setFlag(video::EMF_BILINEAR_FILTER, false);
 		material.setFlag(video::EMF_FOG_ENABLE, true);
-		//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF);
-		//material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE);
-		//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
 		material.setTexture(0, p.tile.texture);
 
-		if (enable_shaders) {
-			material.MaterialType = shdrsrc->getShaderInfo(p.tile.shader_id).material;
-			p.tile.applyMaterialOptionsWithShaders(material);
-			if (p.tile.normal_texture) {
-				material.setTexture(1, p.tile.normal_texture);
-				material.setTexture(2, tsrc->getTexture("enable_img.png"));
+		if (p.tile.material_flags & MATERIAL_FLAG_HIGHLIGHTED) {
+			material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
+		} else {
+			if (m_enable_shaders) {
+				material.MaterialType = shdrsrc->getShaderInfo(p.tile.shader_id).material;
+				p.tile.applyMaterialOptionsWithShaders(material);
+				if (p.tile.normal_texture) {
+					material.setTexture(1, p.tile.normal_texture);
+					material.setTexture(2, tsrc->getTexture("enable_img.png"));
+				} else {
+					material.setTexture(2, tsrc->getTexture("disable_img.png"));
+				}
 			} else {
-				material.setTexture(2, tsrc->getTexture("disable_img.png"));
+				p.tile.applyMaterialOptions(material);
 			}
-		} else {
-			p.tile.applyMaterialOptions(material);
 		}
 
 		// Create meshbuffer
@@ -1229,7 +1237,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 	m_has_animation =
 		!m_crack_materials.empty() ||
 		!m_daynight_diffs.empty() ||
-		!m_animation_tiles.empty();
+		!m_animation_tiles.empty() ||
+		!m_highlighted_materials.empty();
 }
 
 MapBlockMesh::~MapBlockMesh()
@@ -1240,7 +1249,6 @@ MapBlockMesh::~MapBlockMesh()
 
 bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_ratio)
 {
-	bool enable_shaders = g_settings->getBool("enable_shaders");
 
 	if(!m_has_animation)
 	{
@@ -1306,7 +1314,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
 
 		FrameSpec animation_frame = tile.frames.find(frame)->second;
 		buf->getMaterial().setTexture(0, animation_frame.texture);
-		if (enable_shaders) {
+		if (m_enable_shaders) {
 			if (animation_frame.normal_texture) {
 				buf->getMaterial().setTexture(1, animation_frame.normal_texture);
 				buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png"));
@@ -1339,6 +1347,30 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
 		m_last_daynight_ratio = daynight_ratio;
 	}
 
+	// Node highlighting
+	if (m_enable_highlighting) {
+		u8 day = m_highlight_mesh_color.getRed();
+		u8 night = m_highlight_mesh_color.getGreen();	
+		video::SColor hc;
+		finalColorBlend(hc, day, night, daynight_ratio);
+		float sin_r = 0.07 * sin(1.5 * time);
+		float sin_g = 0.07 * sin(1.5 * time + irr::core::PI * 0.5);
+		float sin_b = 0.07 * sin(1.5 * time + irr::core::PI);
+		hc.setRed(core::clamp(core::round32(hc.getRed() * (0.8 + sin_r)), 0, 255));
+		hc.setGreen(core::clamp(core::round32(hc.getGreen() * (0.8 + sin_g)), 0, 255));
+		hc.setBlue(core::clamp(core::round32(hc.getBlue() * (0.8 + sin_b)), 0, 255));
+
+		for(std::list<u32>::iterator
+			i = m_highlighted_materials.begin();
+			i != m_highlighted_materials.end(); i++)
+		{
+			scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(*i);
+			video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
+			for (u32 j = 0; j < buf->getVertexCount() ;j++)
+				vertices[j].Color = hc;
+		}
+	}
+
 	return true;
 }
 
diff --git a/src/mapblock_mesh.h b/src/mapblock_mesh.h
index 7f5231738..c52954998 100644
--- a/src/mapblock_mesh.h
+++ b/src/mapblock_mesh.h
@@ -39,7 +39,11 @@ struct MeshMakeData
 	VoxelManipulator m_vmanip;
 	v3s16 m_blockpos;
 	v3s16 m_crack_pos_relative;
+	v3s16 m_highlighted_pos_relative;
 	bool m_smooth_lighting;
+	bool m_show_hud;
+	video::SColor m_highlight_mesh_color;
+
 	IGameDef *m_gamedef;
 
 	MeshMakeData(IGameDef *gamedef);
@@ -60,6 +64,11 @@ struct MeshMakeData
 	*/
 	void setCrack(int crack_level, v3s16 crack_pos);
 
+	/*
+		Set the highlighted node position
+	*/
+
+	void setHighlighted(v3s16 highlighted_pos, bool show_hud);
 	/*
 		Enable or disable smooth lighting
 	*/
@@ -114,6 +123,11 @@ class MapBlockMesh
 	scene::SMesh *m_mesh;
 	IGameDef *m_gamedef;
 
+	bool m_enable_shaders;
+	bool m_enable_highlighting;
+
+	video::SColor m_highlight_mesh_color;
+	
 	// Must animate() be called before rendering?
 	bool m_has_animation;
 	int m_animation_force_timer;
@@ -123,6 +137,7 @@ class MapBlockMesh
 	int m_last_crack;
 	// Maps mesh buffer (i.e. material) indices to base texture names
 	std::map<u32, std::string> m_crack_materials;
+	std::list<u32> m_highlighted_materials;
 
 	// Animation info: texture animationi
 	// Maps meshbuffers to TileSpecs
diff --git a/src/tile.h b/src/tile.h
index 0ac7c96c0..78aaef00e 100644
--- a/src/tile.h
+++ b/src/tile.h
@@ -171,6 +171,7 @@ enum MaterialType{
 // Animation made up by splitting the texture to vertical frames, as
 // defined by extra parameters
 #define MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES 0x08
+#define MATERIAL_FLAG_HIGHLIGHTED 0x10
 
 /*
 	This fully defines the looks of a tile.
diff --git a/textures/base/pack/halo.png b/textures/base/pack/halo.png
new file mode 100644
index 0000000000000000000000000000000000000000..c3b803cd33ff88426634a84c4414875dcf1213a7
GIT binary patch
literal 177
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0WW
zg+Z8+Vb&Z8pdfpRr>`sfJx&2mR+Cr1Z{`7oBuiW)N}Tg^b5rw57@Uhz6H8K46v{J8
zG8EiBeFMT9`NV;W<UCy*Lo7}w$85>Cn8L=zAk5sFaHS!T*^O612j~EAIi{K2HgP&Y
Ol?<M)elF{r5}E+Qsw-gt

literal 0
HcmV?d00001

-- 
GitLab