From 2e883189c102b07ad5b051878949ec77ef530bf0 Mon Sep 17 00:00:00 2001 From: Desour Date: Sat, 24 Aug 2024 13:32:39 +0200 Subject: [PATCH] Improve block bounds HUD feature * Use different material than selection box, so it doesn't break for non-default `node_highlighting` values. * Add `show_block_bounds_radius_near` setting. * Draw mesh chunk edges in a different color (red vs yellow). --- builtin/settingtypes.txt | 9 ++++-- src/client/hud.cpp | 68 +++++++++++++++++++++++++++++++--------- src/client/hud.h | 1 + src/defaultsettings.cpp | 1 + 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 8828fc1df..229d920d5 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -735,6 +735,12 @@ hud_scaling (HUD scaling) float 1.0 0.5 20 # Mods may still set a background. show_nametag_backgrounds (Show name tag backgrounds by default) bool true +# Whether to show the client debug info (has the same effect as hitting F5). +show_debug (Show debug info) bool false + +# Radius to use when the block bounds HUD feature is set to near blocks. +show_block_bounds_radius_near (Block bounds HUD radius) int 4 0 1000 + [**Chat] # Maximum number of recent chat messages to show @@ -2009,9 +2015,6 @@ client_unload_unused_data_timeout (Mapblock unload timeout) float 600.0 0.0 # Set to -1 for unlimited amount. client_mapblock_limit (Mapblock limit) int 7500 -1 2147483647 -# Whether to show the client debug info (has the same effect as hitting F5). -show_debug (Show debug info) bool false - # Maximum number of blocks that are simultaneously sent per client. # The maximum total count is calculated dynamically: # max_total = ceil((#clients + max_users) * per_client / 4) diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 962818b8f..3f9672f3d 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -97,6 +97,8 @@ Hud::Hud(Client *client, LocalPlayer *player, m_mode = HIGHLIGHT_BOX; } + // Initialize m_selection_material + m_selection_material.Lighting = false; if (g_settings->getBool("enable_shaders")) { @@ -118,6 +120,18 @@ Hud::Hud(Client *client, LocalPlayer *player, m_selection_material.MaterialType = video::EMT_SOLID; } + // Initialize m_block_bounds_material + m_block_bounds_material.Lighting = false; + if (g_settings->getBool("enable_shaders")) { + IShaderSource *shdrsrc = client->getShaderSource(); + auto shader_id = shdrsrc->getShader("default_shader", TILE_MATERIAL_ALPHA); + m_block_bounds_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material; + } else { + m_block_bounds_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + } + m_block_bounds_material.Thickness = + rangelim(g_settings->getS16("selectionbox_width"), 1, 5); + // Prepare mesh for compass drawing auto &b = m_rotation_mesh_buffer; b.Vertices.resize(4); @@ -934,33 +948,57 @@ void Hud::drawBlockBounds() } video::SMaterial old_material = driver->getMaterial2D(); - driver->setMaterial(m_selection_material); + driver->setMaterial(m_block_bounds_material); + + u16 mesh_chunk_size = std::max(1, g_settings->getU16("client_mesh_chunk")); v3s16 pos = player->getStandingNodePos(); - - v3s16 blockPos( + v3s16 block_pos( floorf((float) pos.X / MAP_BLOCKSIZE), floorf((float) pos.Y / MAP_BLOCKSIZE), floorf((float) pos.Z / MAP_BLOCKSIZE) ); - v3f offset = intToFloat(client->getCamera()->getOffset(), BS); + v3f cam_offset = intToFloat(client->getCamera()->getOffset(), BS); - s8 radius = m_block_bounds_mode == BLOCK_BOUNDS_NEAR ? 2 : 0; + v3f half_node = v3f(BS, BS, BS) / 2.0f; + v3f base_corner = intToFloat(block_pos * MAP_BLOCKSIZE, BS) - cam_offset - half_node; - v3f halfNode = v3f(BS, BS, BS) / 2.0f; + s16 radius = m_block_bounds_mode == BLOCK_BOUNDS_NEAR ? + rangelim(g_settings->getU16("show_block_bounds_radius_near"), 0, 1000) : 0; - for (s8 x = -radius; x <= radius; x++) - for (s8 y = -radius; y <= radius; y++) - for (s8 z = -radius; z <= radius; z++) { - v3s16 blockOffset(x, y, z); + for (s16 x = -radius; x <= radius + 1; x++) + for (s16 y = -radius; y <= radius + 1; y++) { + // Red for mesh chunk edges, yellow for other block edges. + auto choose_color = [&](s16 x_base, s16 y_base) { + // See also MeshGrid::isMeshPos(). + // If the block is mesh pos, it means it's at the (-,-,-) corner of + // the mesh. And we're drawing a (-,-) edge of this block. Hence, + // it is an edge of the mesh grid. + return (x + x_base) % mesh_chunk_size == 0 + && (y + y_base) % mesh_chunk_size == 0 ? + video::SColor(255, 255, 0, 0) : + video::SColor(255, 255, 255, 0); + }; - aabb3f box( - intToFloat((blockPos + blockOffset) * MAP_BLOCKSIZE, BS) - offset - halfNode, - intToFloat(((blockPos + blockOffset) * MAP_BLOCKSIZE) + (MAP_BLOCKSIZE - 1), BS) - offset + halfNode + v3f pmin = v3f(x, y, -radius) * MAP_BLOCKSIZE * BS; + v3f pmax = v3f(x, y, 1 + radius) * MAP_BLOCKSIZE * BS; + + driver->draw3DLine( + base_corner + v3f(pmin.X, pmin.Y, pmin.Z), + base_corner + v3f(pmax.X, pmax.Y, pmax.Z), + choose_color(block_pos.X, block_pos.Y) + ); + driver->draw3DLine( + base_corner + v3f(pmin.X, pmin.Z, pmin.Y), + base_corner + v3f(pmax.X, pmax.Z, pmax.Y), + choose_color(block_pos.X, block_pos.Z) + ); + driver->draw3DLine( + base_corner + v3f(pmin.Z, pmin.X, pmin.Y), + base_corner + v3f(pmax.Z, pmax.X, pmax.Y), + choose_color(block_pos.Y, block_pos.Z) ); - - driver->draw3DBox(box, video::SColor(255, 255, 0, 0)); } driver->setMaterial(old_material); diff --git a/src/client/hud.h b/src/client/hud.h index b2b5dd09c..3a9d27022 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -137,6 +137,7 @@ private: v3f m_selected_face_normal; video::SMaterial m_selection_material; + video::SMaterial m_block_bounds_material; scene::SMeshBuffer m_rotation_mesh_buffer; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 7d3273271..ccfb12971 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -302,6 +302,7 @@ void set_default_settings() settings->setDefault("enable_particles", "true"); settings->setDefault("arm_inertia", "true"); settings->setDefault("show_nametag_backgrounds", "true"); + settings->setDefault("show_block_bounds_radius_near", "4"); settings->setDefault("transparency_sorting_distance", "16"); settings->setDefault("enable_minimap", "true");