From 3f62d4d58df04d59b8d3aab5eb9245b1d8bf2d73 Mon Sep 17 00:00:00 2001 From: Tommaso Bianchi Date: Wed, 12 Aug 2026 19:57:14 +0200 Subject: [PATCH] Bodies: colour that survives selection, hide that toggles twice, Delete that acts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three defects behind one report ("bodies cannot be moved or hidden/shown or deleted, colour does not work"). They are unrelated to each other; only the symptom was shared. 1. The Color tool wrote a per-body override that was correct end to end — stored on CadBody, carried across recompute (CadDocument.cpp:3381), read back by DesignCanvas::body_color() — and then overpainted every frame. m_body_selected is a DOCUMENT-WIDE flag raised whenever a non-Sketch feature row is selected, which is the resting state after any modelling operation, and while it was true every body rendered gold. An explicit colour now outranks the selection tint; unpainted bodies still tint, which is all the tint was ever for. 2. The eye toggle re-selected the body row through m_tree, using item ids that belong to m_parts. The row came back unselected, so the second press found tree_body_selection() == -1 and fell through to the feature-level branch instead of un-hiding. Hide worked exactly once. The sibling call in refresh_parts() had it right. 3. The tree card's Delete button answered a selected body row with "select the FEATURE that created this body" — an instruction the user cannot act on, because the tree does not say which feature that is. on_delete_body() already resolves CadBody::source_feature and confirms by name; it was reachable only from the right-click offer. The button now routes to it. Reviewed and compiled (libslic3r_gui, RC=0); not exercised — needs a session at the machine to confirm all three in the viewport. snaporca-zjvg. --- src/slic3r/GUI/DesignCanvas.cpp | 14 +++++++++++--- src/slic3r/GUI/DesignPanel.cpp | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/DesignCanvas.cpp b/src/slic3r/GUI/DesignCanvas.cpp index baa15ad167..f17445f8ec 100644 --- a/src/slic3r/GUI/DesignCanvas.cpp +++ b/src/slic3r/GUI/DesignCanvas.cpp @@ -290,9 +290,17 @@ void DesignCanvas::reload(bool keep_view) if (m_body_hidden) hidden = true; v->is_active = !hidden; // per-body visibility toggle if (!hidden) { - // Selection tint wins; otherwise the per-body override (Color tool) or the - // auto palette via body_color(). - ColorRGBA c = m_body_selected ? sel_gold : body_color(b); + // An EXPLICIT colour outranks the selection tint. m_body_selected is a + // document-wide flag raised whenever a non-Sketch feature row is selected — + // the normal resting state after any modelling operation — so painting every + // body gold on it made the Color tool look broken: the override was written, + // carried across recompute and read back correctly, and then overpainted here + // every single frame. A body the user deliberately coloured keeps its colour; + // the rest still tint, which is all the tint was ever for. + const bool overridden = m_color_bodies != nullptr && b >= 0 + && b < int(m_color_bodies->size()) + && (*m_color_bodies)[b].has_color; + ColorRGBA c = (m_body_selected && !overridden) ? sel_gold : body_color(b); if (b == m_hl_body_target) c = ColorRGBA(0.30f, 0.90f, 0.70f, 1.0f); // target = teal-green else if (b == m_hl_body_tool) c = ColorRGBA(1.00f, 0.55f, 0.15f, 1.0f); // tool = orange if (m_body_translucent) c.a(0.30f); diff --git a/src/slic3r/GUI/DesignPanel.cpp b/src/slic3r/GUI/DesignPanel.cpp index d430f713cf..f20efde754 100644 --- a/src/slic3r/GUI/DesignPanel.cpp +++ b/src/slic3r/GUI/DesignPanel.cpp @@ -2966,7 +2966,15 @@ DesignPanel::DesignPanel(wxWindow* parent) auto* vis = edit_btn("design_eye", _L("Show / hide")); vis->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_toggle_visibility(); }); auto* del = edit_btn("design_delete", _L("Delete")); - del->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_delete_feature(); }); + del->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + // A body row deletes the feature that made it. on_delete_body() already resolves + // CadBody::source_feature and asks for confirmation by name; it was reachable only + // from the right-click offer, so this button answered a selected body row with + // "select the FEATURE that created this body" — an instruction the user cannot act + // on, since the tree does not say which feature that is. It does now. + if (tree_body_selection() >= 0) on_delete_body(); + else on_delete_feature(); + }); auto* up = edit_btn("design_moveup", _L("Move up")); up->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_move_feature(-1); }); auto* down = edit_btn("design_movedown", _L("Move down")); @@ -6302,8 +6310,12 @@ void DesignPanel::on_toggle_visibility() &m_body_visible, &m_body_xform); } refresh_tree(); - if (bsel < int(m_tree_body_items.size())) // keep the row selected for repeat toggles - m_tree->SelectItem(m_tree_body_items[bsel]); + // Keep the row selected for repeat toggles. m_parts, NOT m_tree: these ids belong + // to the Bodies list, and handing a foreign item to the feature tree left the row + // unselected — so the second press of the eye found tree_body_selection() == -1 and + // fell through to the FEATURE-level branch below instead of un-hiding the body. + if (m_parts != nullptr && bsel < int(m_tree_body_items.size())) + m_parts->SelectItem(m_tree_body_items[bsel]); m_status->SetForegroundColour(wxNullColour); set_status(wxString::Format(now_visible ? _L("Body %d shown") : _L("Body %d hidden"), bsel + 1));