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 @@ public: 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 @@ private: float m_inventory_from_server_age; std::set 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; zm_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 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::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 "<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::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::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 "<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()="<getTexture("disable_img.png")); - } + if (p.tile.material_flags & MATERIAL_FLAG_HIGHLIGHTED) { + material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; } else { - p.tile.applyMaterialOptions(material); + 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 { + 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::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 @@ private: 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 @@ private: int m_last_crack; // Maps mesh buffer (i.e. material) indices to base texture names std::map m_crack_materials; + std::list 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 000000000..c3b803cd3 Binary files /dev/null and b/textures/base/pack/halo.png differ