diff --git a/src/slic3r/GUI/DesignPanel.cpp b/src/slic3r/GUI/DesignPanel.cpp index b04da78a77..e5022b5ca3 100644 --- a/src/slic3r/GUI/DesignPanel.cpp +++ b/src/slic3r/GUI/DesignPanel.cpp @@ -5694,7 +5694,20 @@ void DesignPanel::refresh_cs_body_choice() m_cs_body->Append(_L("(all)")); for (size_t b = 0; b < m_doc.bodies.size(); ++b) m_cs_body->Append(wxString::Format(_L("Body %d"), int(b) + 1)); - m_cs_body->SetSelection(keep > 0 && keep < int(m_cs_body->GetCount()) ? keep : 0); + const int sel = (keep > 0 && keep < int(m_cs_body->GetCount())) ? keep : 0; + m_cs_body->SetSelection(sel); + // The combo and the viewport focus are ONE state, so they must not be written separately. + // When the body list shrinks, `keep` falls out of range and the selection silently drops to + // "(all)" — while the viewport stayed focused on the old index, leaving every other body at + // 25% alpha and picking locked to a body that may no longer exist. That is the exact mirror + // of the open_tool ordering bug (combo says Body N, viewport opaque); this one says "(all)" + // and stays dimmed. + // + // Guarded on the CoordSys card being the ACTIVE tool because it is the only card that owns + // this focus. In the edit path this function runs BEFORE open_tool, with the previous tool + // still active, so the guard is false and the caller's explicit set_xray_focus still wins. + if (m_viewport != nullptr && m_active == Tool::CoordSys) + m_viewport->set_xray_focus(sel - 1); } void DesignPanel::reset_coordsys_refs() diff --git a/src/slic3r/GUI/DesignSketchTool.cpp b/src/slic3r/GUI/DesignSketchTool.cpp index 93653bcc4c..6402c7d19e 100644 --- a/src/slic3r/GUI/DesignSketchTool.cpp +++ b/src/slic3r/GUI/DesignSketchTool.cpp @@ -2847,7 +2847,15 @@ Vec3d DesignSketchTool::body_xform_pt(int body, const Vec3d& p) const bool DesignSketchTool::body_pickable(int b) const { if (b < 0) return false; - if (m_pick_only_body >= 0 && b != m_pick_only_body) return false; // body-focus mode + // Body-focus mode. The focus is an INDEX held by the panel across recomputes, so it can + // outlive the body it names — delete a body and the stored index may point past the end. + // A restriction to a body that no longer exists rejects EVERY body, which is a viewport + // that silently accepts no clicks at all: the worst possible failure for a picking mode, + // because nothing on screen says why. Out of range therefore means NO restriction — fail + // open, never dead. + const bool focus_live = m_pick_only_body >= 0 && m_solid_bodies != nullptr + && m_pick_only_body < int(m_solid_bodies->size()); + if (focus_live && b != m_pick_only_body) return false; if (m_solid_visible == nullptr || b >= int(m_solid_visible->size())) return true; return (*m_solid_visible)[b]; }