From 00f55639d3588951dd73a31be63076ae876ea984 Mon Sep 17 00:00:00 2001 From: ExPikaPaka Date: Thu, 16 Jul 2026 08:52:00 +0200 Subject: [PATCH] Add new icons --- .../images/texture_displacement_checker.svg | 165 +++++++++++++++ .../texture_displacement_connected_area.svg | 115 ++++++++++ .../texture_displacement_distortion.svg | 197 ++++++++++++++++++ .../texture_displacement_fast_preview.svg | 132 ++++++++++++ .../texture_displacement_real_preview.svg | 150 +++++++++++++ .../images/texture_displacement_wireframe.svg | 163 +++++++++++++++ resources/images/toolbar_big_brush.svg | 60 ++++++ resources/images/toolbar_face.svg | 97 +++++++++ .../GUI/Gizmos/GLGizmoTextureDisplacement.cpp | 93 +++++---- .../GUI/Gizmos/GLGizmoTextureDisplacement.hpp | 6 + 10 files changed, 1143 insertions(+), 35 deletions(-) create mode 100644 resources/images/texture_displacement_checker.svg create mode 100644 resources/images/texture_displacement_connected_area.svg create mode 100644 resources/images/texture_displacement_distortion.svg create mode 100644 resources/images/texture_displacement_fast_preview.svg create mode 100644 resources/images/texture_displacement_real_preview.svg create mode 100644 resources/images/texture_displacement_wireframe.svg create mode 100644 resources/images/toolbar_big_brush.svg create mode 100644 resources/images/toolbar_face.svg diff --git a/resources/images/texture_displacement_checker.svg b/resources/images/texture_displacement_checker.svg new file mode 100644 index 0000000000..4631116379 --- /dev/null +++ b/resources/images/texture_displacement_checker.svg @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + diff --git a/resources/images/texture_displacement_connected_area.svg b/resources/images/texture_displacement_connected_area.svg new file mode 100644 index 0000000000..b57e96d951 --- /dev/null +++ b/resources/images/texture_displacement_connected_area.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + diff --git a/resources/images/texture_displacement_distortion.svg b/resources/images/texture_displacement_distortion.svg new file mode 100644 index 0000000000..833a34f0cf --- /dev/null +++ b/resources/images/texture_displacement_distortion.svg @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/texture_displacement_fast_preview.svg b/resources/images/texture_displacement_fast_preview.svg new file mode 100644 index 0000000000..9e13fb68de --- /dev/null +++ b/resources/images/texture_displacement_fast_preview.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + diff --git a/resources/images/texture_displacement_real_preview.svg b/resources/images/texture_displacement_real_preview.svg new file mode 100644 index 0000000000..f3ebdaa53d --- /dev/null +++ b/resources/images/texture_displacement_real_preview.svg @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + diff --git a/resources/images/texture_displacement_wireframe.svg b/resources/images/texture_displacement_wireframe.svg new file mode 100644 index 0000000000..20ac8c1b03 --- /dev/null +++ b/resources/images/texture_displacement_wireframe.svg @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + diff --git a/resources/images/toolbar_big_brush.svg b/resources/images/toolbar_big_brush.svg new file mode 100644 index 0000000000..20be9ec53b --- /dev/null +++ b/resources/images/toolbar_big_brush.svg @@ -0,0 +1,60 @@ + + + + + + + + + + diff --git a/resources/images/toolbar_face.svg b/resources/images/toolbar_face.svg new file mode 100644 index 0000000000..6975e0f6e4 --- /dev/null +++ b/resources/images/toolbar_face.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + diff --git a/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp b/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp index a8dcbaf7c4..426521f04d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp @@ -2093,6 +2093,19 @@ unsigned int GLGizmoTextureDisplacement::tool_icon_id() return m_tool_icon.get_id(); } +unsigned int GLGizmoTextureDisplacement::icon_id(const std::string &filename) +{ + auto it = m_icon_cache.find(filename); + if (it == m_icon_cache.end()) { + // First request for this icon: default-construct the texture in place and load it once (with a + // GL context current, since this runs from the panel render). A failed load leaves id 0 and is + // not retried. + it = m_icon_cache.try_emplace(filename).first; + it->second.load_from_svg_file(resources_dir() + "/images/" + filename, false, false, false, 32); + } + return it->second.get_id(); +} + void GLGizmoTextureDisplacement::add_texture_layer() { ModelVolume *mv = texture_volume(); @@ -2552,6 +2565,28 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float return changed; }; + // Icon toggle button shared by the selection-mode and view-mode rows: an SVG button with a teal + // backing and full-brightness icon when active, dimmed otherwise. Falls back to a text checkbox if + // its icon could not be loaded, so the control is never lost. + const float icon_btn_sz = m_imgui->scaled(1.5f); + const ImVec4 icon_active_bg(0.0f, 0.59f, 0.53f, 1.0f); + const auto icon_toggle = [&](int uid, unsigned int ic, bool active, const wxString &label, const wxString &tip) -> bool { + bool clicked; + ImGui::PushID(uid); + if (ic != 0) + clicked = m_imgui->image_button((ImTextureID) (intptr_t) ic, ImVec2(icon_btn_sz, icon_btn_sz), ImVec2(0, 0), + ImVec2(1, 1), -1, active ? icon_active_bg : ImVec4(0, 0, 0, 0), + active ? ImVec4(1, 1, 1, 1) : ImVec4(0.65f, 0.65f, 0.65f, 1.f)); + else { + bool v = active; + clicked = ImGui::Checkbox(label.ToUTF8().data(), &v); + } + ImGui::PopID(); + if (ImGui::IsItemHovered()) + m_imgui->tooltip(tip, m_imgui->scaled(18.f)); + return clicked; + }; + if (m_imgui->button(m_undocked ? _L("Dock panel") : _L("Undock panel"))) m_undocked = !m_undocked; if (ImGui::IsItemHovered()) @@ -2568,17 +2603,22 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float const bool is_brush_mode = m_tool_type == ToolType::BRUSH && m_cursor_type != TriangleSelector::CursorType::POINTER; const bool is_face_mode = m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER; const bool is_area_mode = m_tool_type == ToolType::SMART_FILL; - if (ImGui::RadioButton(_u8L("Brush").c_str(), is_brush_mode)) { + ImGui::SameLine(); + if (icon_toggle(801, icon_id("toolbar_big_brush.svg"), is_brush_mode, _L("Brush"), + _L("Brush - paint over the surface by dragging"))) { m_tool_type = ToolType::BRUSH; m_cursor_type = TriangleSelector::CursorType::CIRCLE; } ImGui::SameLine(); - if (ImGui::RadioButton(_u8L("Face").c_str(), is_face_mode)) { + if (icon_toggle(802, icon_id("toolbar_face.svg"), is_face_mode, _L("Face"), + _L("Face - click individual triangles"))) { m_tool_type = ToolType::BRUSH; m_cursor_type = TriangleSelector::CursorType::POINTER; } ImGui::SameLine(); - if (ImGui::RadioButton(_u8L("Connected area").c_str(), is_area_mode)) { + if (icon_toggle(803, icon_id("texture_displacement_connected_area.svg"), is_area_mode, _L("Connected area"), + _L("Connected area - flood-fill the region reachable without crossing an edge sharper than the " + "angle threshold"))) { m_tool_type = ToolType::SMART_FILL; m_cursor_type = TriangleSelector::CursorType::POINTER; } @@ -2606,50 +2646,33 @@ void GLGizmoTextureDisplacement::on_render_input_window(float x, float y, float select_whole_model(); // View mode (#: "make View Mode with just icons"): Normal / Fast / Checker / Distortion behave as - // one radio group, Wireframe as an independent toggle. All reuse the one tool icon for now, so the - // tooltip carries the meaning. The underlying state stays m_use_bump_preview + m_uv_check_mode. + // one radio group, Wireframe as an independent toggle. Each has its own icon; the tooltip carries + // the meaning. The underlying state stays m_use_bump_preview + m_uv_check_mode. { - const unsigned int icon = tool_icon_id(); - const float vsz = m_imgui->scaled(1.5f); - const ImVec4 teal(0.0f, 0.59f, 0.53f, 1.0f); - const int cur_mode = m_use_bump_preview ? 1 : - (m_uv_check_mode == UVCheckMode::Checker ? 2 : - m_uv_check_mode == UVCheckMode::Distortion ? 3 : 0); + const int cur_mode = m_use_bump_preview ? 1 : + (m_uv_check_mode == UVCheckMode::Checker ? 2 : + m_uv_check_mode == UVCheckMode::Distortion ? 3 : 0); int new_mode = cur_mode; bool wf_toggle = false; - // One icon button; active state shown by a teal backing and a full-brightness (vs dimmed) icon. - // Falls back to a text toggle if the icon can't load. - const auto icon_toggle = [&](int uid, bool active, const wxString &label, const wxString &tip) -> bool { - bool clicked; - ImGui::PushID(uid); - if (icon != 0) - clicked = m_imgui->image_button((ImTextureID) (intptr_t) icon, ImVec2(vsz, vsz), ImVec2(0, 0), ImVec2(1, 1), - -1, active ? teal : ImVec4(0, 0, 0, 0), - active ? ImVec4(1, 1, 1, 1) : ImVec4(0.65f, 0.65f, 0.65f, 1.f)); - else { - bool v = active; - clicked = ImGui::Checkbox(label.ToUTF8().data(), &v); - } - ImGui::PopID(); - if (ImGui::IsItemHovered()) - m_imgui->tooltip(tip, m_imgui->scaled(18.f)); - return clicked; - }; - m_imgui->text(_L("View")); ImGui::SameLine(); - if (icon_toggle(701, cur_mode == 0, _L("Normal"), _L("Normal - the true displaced geometry (what Bake produces)"))) new_mode = 0; + if (icon_toggle(701, icon_id("texture_displacement_real_preview.svg"), cur_mode == 0, _L("Normal"), + _L("Normal - the true displaced geometry (what Bake produces)"))) new_mode = 0; ImGui::SameLine(); - if (icon_toggle(702, cur_mode == 1, _L("Fast"), _L("Fast - a bump-shaded approximation of the active layer only; quick to update, not exact"))) new_mode = 1; + if (icon_toggle(702, icon_id("texture_displacement_fast_preview.svg"), cur_mode == 1, _L("Fast"), + _L("Fast - a bump-shaded approximation of the active layer only; quick to update, not exact"))) new_mode = 1; ImGui::SameLine(); - if (icon_toggle(703, cur_mode == 2, _L("Checker"), _L("Checker - a test grid over the unwrap; squares stay square where it does not stretch"))) new_mode = 2; + if (icon_toggle(703, icon_id("texture_displacement_checker.svg"), cur_mode == 2, _L("Checker"), + _L("Checker - a test grid over the unwrap; squares stay square where it does not stretch"))) new_mode = 2; ImGui::SameLine(); - if (icon_toggle(704, cur_mode == 3, _L("Distortion"), _L("Distortion - blue-to-red stretch heatmap over the unwrap (needs the Unwrap/LSCM projection)"))) new_mode = 3; + if (icon_toggle(704, icon_id("texture_displacement_distortion.svg"), cur_mode == 3, _L("Distortion"), + _L("Distortion - blue-to-red stretch heatmap over the unwrap (needs the Unwrap/LSCM projection)"))) new_mode = 3; ImGui::SameLine(); ImGui::Dummy(ImVec2(m_imgui->scaled(0.6f), 0.f)); ImGui::SameLine(); - if (icon_toggle(705, m_wireframe_overlay, _L("Wireframe"), _L("Wireframe - overlay the mesh edges; independent of the view above"))) wf_toggle = true; + if (icon_toggle(705, icon_id("texture_displacement_wireframe.svg"), m_wireframe_overlay, _L("Wireframe"), + _L("Wireframe - overlay the mesh edges; independent of the view above"))) wf_toggle = true; if (new_mode != cur_mode) { m_use_bump_preview = (new_mode == 1); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp b/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp index f81c6bc08a..bce96e89b9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp @@ -449,6 +449,12 @@ private: GLTexture m_tool_icon; bool m_tool_icon_tried = false; unsigned int tool_icon_id(); // 0 if the icon could not be loaded + + // The panel's icon-button rows (selection mode, view mode) each need their own small SVG. Loaded and + // uploaded once on first use and cached by file name (under resources/images/). Returns 0 if an icon + // could not be loaded, in which case the button falls back to a text control. + std::map m_icon_cache; + unsigned int icon_id(const std::string &filename); }; } // namespace Slic3r::GUI