Design: a body tool acts on the body you picked, not on the first one

Mirror of snaporca e5e223a794 (DesignPanel.cpp applied as a patch; parity 30, hpp
byte-identical).

Every body combo opened on index 0, so picking a body and pressing Mirror acted on a
different solid while the card showed that other body as the target. Nine sites now read
the viewport selection; Boolean takes the picked body as target and a different one as
tool, since defaulting both to the same body is a no-op.

Verified functionally on the rig: picked the 20x20 body, mirrored, and the new body
measures 20x20 — not the 80x50 one it would have used before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LyRwbuq6fjn3VV9U9UvhBM
This commit is contained in:
Tommaso Bianchi
2026-08-01 12:15:46 +02:00
co-authored by Claude Opus 5
parent 273cf067e8
commit d5c5d5675e
2 changed files with 36 additions and 9 deletions
+31 -9
View File
@@ -622,7 +622,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
const std::string& n = m_doc.bodies[i].name;
m_thicken_body->Append(n.empty() ? wxString::Format(_L("Body %zu"), i + 1) : wxString::FromUTF8(n));
}
if (m_thicken_body->GetCount() > 0) m_thicken_body->SetSelection(0);
if (m_thicken_body->GetCount() > 0)
m_thicken_body->SetSelection(std::min(selected_body_default(),
int(m_thicken_body->GetCount()) - 1));
}
m_sel_solid_face = -1;
m_thicken_face_label->SetLabel(_L("(pick a solid face)"));
@@ -642,7 +644,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
const std::string& n = m_doc.bodies[i].name;
m_rib_body->Append(n.empty() ? wxString::Format(_L("Body %zu"), i + 1) : wxString::FromUTF8(n));
}
if (m_rib_body->GetCount() > 0) m_rib_body->SetSelection(0);
if (m_rib_body->GetCount() > 0)
m_rib_body->SetSelection(std::min(selected_body_default(),
int(m_rib_body->GetCount()) - 1));
}
{
m_rib_sketch->Clear();
@@ -798,7 +802,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
const std::string& n = m_doc.bodies[i].name;
m_proj_source_body->Append(n.empty() ? wxString::Format(_L("Body %zu"), i + 1) : wxString::FromUTF8(n));
}
if (m_proj_source_body->GetCount() > 0) m_proj_source_body->SetSelection(0);
if (m_proj_source_body->GetCount() > 0)
m_proj_source_body->SetSelection(std::min(selected_body_default(),
int(m_proj_source_body->GetCount()) - 1));
}
populate_plane_choices(m_proj_plane);
m_sel_solid_face = -1;
@@ -829,7 +835,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
const std::string& n = m_doc.bodies[i].name;
m_xf_body->Append(n.empty() ? wxString::Format(_L("Body %zu"), i + 1) : wxString::FromUTF8(n));
}
if (m_xf_body->GetCount() > 0) m_xf_body->SetSelection(0);
if (m_xf_body->GetCount() > 0)
m_xf_body->SetSelection(std::min(selected_body_default(),
int(m_xf_body->GetCount()) - 1));
}
open_tool(Tool::Transform);
}, SHIFT('Y')},
@@ -847,7 +855,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
const std::string& n = m_doc.bodies[i].name;
m_mirror_body->Append(n.empty() ? wxString::Format(_L("Body %zu"), i + 1) : wxString::FromUTF8(n));
}
if (m_mirror_body->GetCount() > 0) m_mirror_body->SetSelection(0);
if (m_mirror_body->GetCount() > 0)
m_mirror_body->SetSelection(std::min(selected_body_default(),
int(m_mirror_body->GetCount()) - 1));
}
populate_plane_choices(m_mirror_plane);
open_tool(Tool::Mirror);
@@ -923,7 +933,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
const std::string& n = m_doc.bodies[i].name;
m_del_face_body->Append(n.empty() ? wxString::Format(_L("Body %zu"), i + 1) : wxString::FromUTF8(n));
}
if (m_del_face_body->GetCount() > 0) m_del_face_body->SetSelection(0);
if (m_del_face_body->GetCount() > 0)
m_del_face_body->SetSelection(std::min(selected_body_default(),
int(m_del_face_body->GetCount()) - 1));
}
m_del_faces.clear();
m_del_face_list->SetLabel(_L("(none)"));
@@ -4850,6 +4862,13 @@ void DesignPanel::on_add_pattern()
refresh_tree();
}
int DesignPanel::selected_body_default() const
{
const int n = int(m_doc.bodies.size());
if (n <= 0) return 0;
return (m_sel_solid_body >= 0 && m_sel_solid_body < n) ? m_sel_solid_body : 0;
}
void DesignPanel::populate_body_choices(int as_of_feature)
{
// Re-editing a Boolean: list the bodies as they existed just before it ran, so a tool body
@@ -4873,9 +4892,12 @@ void DesignPanel::populate_body_choices(int as_of_feature)
if (c->GetCount() > 0)
c->SetSelection(std::min(def, int(c->GetCount()) - 1)); // selection index == body index
};
fill(m_bool_target, 0);
fill(m_bool_tool, 1); // default: combine body 0 (target) with body 1 (tool)
fill(m_cut_target, 0); // Cut tool: default to the first body
const int picked = selected_body_default();
fill(m_bool_target, picked);
// …and the tool body is a DIFFERENT one: defaulting both to the same body is a no-op the
// user has to notice and undo. Fall back to the neighbour of whatever was picked.
fill(m_bool_tool, picked == 0 ? 1 : 0);
fill(m_cut_target, picked);
}
void DesignPanel::fill_body_choice(ComboBox* c, int as_of_feature, int want)
+5
View File
@@ -131,6 +131,11 @@ private:
// Fill m_bool_target / m_bool_tool / m_cut_target. as_of_feature < 0 = current bodies (add);
// >= 0 = the bodies as they existed just before that feature index (Boolean re-edit, so a
// consumed tool body still appears and its saved selection round-trips).
// Which body a tool should act on when it opens: the one picked in the VIEWPORT, else
// the first. Selection comes first and the tool consumes it — every body combo used to
// default to index 0, so picking body 3 and opening Mirror silently mirrored body 1.
// Clamped to the list, so it is safe to hand straight to SetSelection. snaporca-e1p.
int selected_body_default() const;
void populate_body_choices(int as_of_feature = -1);
// Fill `c` with the bodies as they existed just before `as_of_feature` and select
// `want`. Re-editing any feature that stores a body index needs this: the index was