mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-18 14:32:36 +00:00
CoordSys: pick a body first, x-ray the rest
In an assembly the face you want for a mate connector is nearly always behind another body, and a click only ever returns the frontmost hit. Hiding the occluder from the Parts list works but means leaving the tool mid-pick. The CoordSys card now carries a Body chooser. Pick a body and every other one drops to 0.25 alpha AND stops catching clicks, so the wanted face is both visible and reachable in one gesture. "(all)" restores normal picking. Deliberately NOT hit cycling: repeated-click cycling was removed from solid picking as a charter L5/§10 violation (DesignSketchTool.cpp, "NO CYCLE"), and re-introducing it here would make "click a face" a multi-click gesture again. Mechanics: DesignSketchTool::set_pick_only_body() gates body_pickable(), which every pick path already consults; DesignCanvas::set_xray_focus() drives both it and the per-body alpha in reload(). The chooser stays a pick FILTER only -- coordsys_body still comes from the actual pick, so nothing in the kernel moves. Body focus follows the CoordSys card: open_tool() reads it back from the combo rather than clearing outright, because editing a CoordSys feature loads the card (and its body) before open_tool runs. snaporca-bgvk. NOT COMPILED: deps/build lacks OpenVDB so the GUI tree will not configure here; reviewed by diff only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8ff7ba440d
commit
3eec65f2bd
@@ -296,6 +296,7 @@ void DesignCanvas::reload(bool keep_view)
|
||||
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);
|
||||
else if (m_xray_focus >= 0 && b != m_xray_focus) c.a(0.25f);
|
||||
v->set_color(c);
|
||||
}
|
||||
} else if (obj_idx == 1) {
|
||||
@@ -1050,6 +1051,14 @@ void DesignCanvas::set_body_translucent(bool on)
|
||||
reload(true); // re-applies object-0 alpha so the solid fades for the fillet preview
|
||||
}
|
||||
|
||||
void DesignCanvas::set_xray_focus(int body)
|
||||
{
|
||||
if (m_xray_focus == body) return;
|
||||
m_xray_focus = body;
|
||||
m_sketch_tool.set_pick_only_body(body);
|
||||
reload(true); // re-applies per-body alpha so the non-focused bodies fade
|
||||
}
|
||||
|
||||
void DesignCanvas::set_body_hidden(bool on)
|
||||
{
|
||||
if (m_body_hidden == on) return;
|
||||
|
||||
@@ -194,6 +194,7 @@ public:
|
||||
void show_status_hud(bool on);
|
||||
void set_operand_bodies(int target_body, int tool_body); // -1,-1 clears
|
||||
void set_body_translucent(bool on); // render the solid see-through (fillet/chamfer preview)
|
||||
void set_xray_focus(int body); // >=0: fade+lock out every other body (CoordSys picking)
|
||||
void set_body_hidden(bool on); // preview-only: hide base bodies, show only the result ghost
|
||||
void set_on_move_exit(std::function<void()> cb); // right-click finished the move-body gizmo
|
||||
// Right-click (or its platform equivalent) on the viewport with no tool running: open the
|
||||
@@ -292,6 +293,7 @@ private:
|
||||
int m_hl_body_target{-1};
|
||||
int m_hl_body_tool{-1};
|
||||
bool m_body_translucent{false};// fillet/chamfer preview → render the body see-through
|
||||
int m_xray_focus{-1}; // >=0: only this body is opaque+clickable (CoordSys picking)
|
||||
bool m_body_hidden{false}; // preview-only mode → hide base bodies, ghost = the result
|
||||
std::vector<bool> m_body_visible; // per-body visibility (empty => all visible)
|
||||
// Live pointer to the document's bodies (stable address: m_doc.bodies), stashed by
|
||||
|
||||
@@ -2614,6 +2614,19 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
m_box_coordsys->Add(new wxStaticText(m_cards, wxID_ANY, _L("Type")), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_coordsys->Add(m_coordsys_type, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
|
||||
m_cs_body = make_combo(m_cards);
|
||||
m_cs_body->Append(_L("(all)"));
|
||||
m_cs_body->SetSelection(0);
|
||||
m_cs_body->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) {
|
||||
if (m_viewport) m_viewport->set_xray_focus(m_cs_body->GetSelection() - 1);
|
||||
});
|
||||
m_box_coordsys->Add(new wxStaticText(m_cards, wxID_ANY, _L("Body")), 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
m_box_coordsys->Add(m_cs_body, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
auto* body_hint = new wxStaticText(m_cards, wxID_ANY,
|
||||
_L("Restrict picking to one body — the others go see-through and stop catching clicks"));
|
||||
body_hint->SetForegroundColour(dp_sec_text());
|
||||
m_box_coordsys->Add(body_hint, 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
|
||||
auto* csform = two_col_form();
|
||||
|
||||
m_cs_x = make_spin(m_cards, 0.0, -100000.0, 100000.0);
|
||||
@@ -5589,12 +5602,26 @@ void DesignPanel::refresh_coordsys_labels()
|
||||
if (m_cs_edge_lbl) m_cs_edge_lbl->SetLabel(txt(m_cs_edge));
|
||||
}
|
||||
|
||||
void DesignPanel::refresh_cs_body_choice()
|
||||
{
|
||||
if (!m_cs_body) return;
|
||||
const int keep = m_cs_body->GetSelection();
|
||||
m_cs_body->Clear();
|
||||
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);
|
||||
}
|
||||
|
||||
void DesignPanel::reset_coordsys_refs()
|
||||
{
|
||||
m_cs_face_body = m_cs_face = -1;
|
||||
m_cs_edge = -1;
|
||||
m_coordsys_pick = CoordSysPick::None;
|
||||
refresh_coordsys_labels();
|
||||
if (m_cs_body) m_cs_body->SetSelection(0);
|
||||
if (m_viewport) m_viewport->set_xray_focus(-1);
|
||||
refresh_cs_body_choice();
|
||||
}
|
||||
|
||||
void DesignPanel::arm_coordsys_pick(CoordSysPick target)
|
||||
@@ -7749,6 +7776,11 @@ void DesignPanel::load_feature_into_dialog(const CadFeature& f)
|
||||
m_cs_hz->SetValue(f.coordsys_x_hint.z());
|
||||
m_coordsys_pick = CoordSysPick::None;
|
||||
refresh_coordsys_labels();
|
||||
refresh_cs_body_choice();
|
||||
if (m_cs_body && f.coordsys_body >= 0) {
|
||||
m_cs_body->SetSelection(f.coordsys_body + 1);
|
||||
if (m_viewport) m_viewport->set_xray_focus(f.coordsys_body);
|
||||
}
|
||||
break;
|
||||
case CadFeatureType::Boolean:
|
||||
// List the bodies available to the boolean (as-of its timeline slot), so the consumed
|
||||
@@ -9142,7 +9174,12 @@ void DesignPanel::open_tool(Tool t)
|
||||
// Fillet/Chamfer/Draft no longer fade the body see-through; instead, once a valid target
|
||||
// is picked, refresh_preview hides the base bodies entirely (preview-only). Keep it opaque
|
||||
// here so the body is fully visible for picking the edge/face.
|
||||
if (m_viewport) { m_viewport->set_body_translucent(false); m_viewport->set_body_hidden(false); }
|
||||
// Body focus follows the CoordSys card: entering any other tool drops it. Read it back
|
||||
// from the combo rather than clearing outright — editing a CoordSys feature loads the
|
||||
// card (and its body) BEFORE open_tool runs, and a blind clear would strand the viewport
|
||||
// showing "Body N" while picking stayed unrestricted.
|
||||
if (m_viewport) { m_viewport->set_body_translucent(false); m_viewport->set_body_hidden(false);
|
||||
m_viewport->set_xray_focus(t == Tool::CoordSys && m_cs_body ? m_cs_body->GetSelection() - 1 : -1); }
|
||||
wxSizer* s = m_cards->GetSizer();
|
||||
s->Show(m_box_sketch, t == Tool::Sketch, true);
|
||||
s->Show(m_box_extrude, t == Tool::Extrude, true);
|
||||
@@ -9405,7 +9442,7 @@ void DesignPanel::close_tool()
|
||||
{
|
||||
m_active = Tool::None;
|
||||
set_active_tool_btn(nullptr); // clear the active-tool teal highlight
|
||||
if (m_viewport) { m_viewport->set_body_translucent(false); m_viewport->set_body_hidden(false); } // restore the opaque solid
|
||||
if (m_viewport) { m_viewport->set_body_translucent(false); m_viewport->set_body_hidden(false); m_viewport->set_xray_focus(-1); } // restore the opaque solid
|
||||
wxSizer* s = m_cards->GetSizer();
|
||||
s->Show(m_box_sketch, false, true);
|
||||
s->Show(m_box_extrude, false, true);
|
||||
|
||||
@@ -112,6 +112,7 @@ private:
|
||||
void arm_coordsys_pick(CoordSysPick target);
|
||||
void apply_coordsys_refs(CadFeature& f) const;
|
||||
void refresh_coordsys_labels();
|
||||
void refresh_cs_body_choice(); // fill the CoordSys body chooser from current document
|
||||
void reset_coordsys_refs();
|
||||
void on_add_surface_extrude();
|
||||
void on_add_surface_revolve();
|
||||
@@ -721,6 +722,7 @@ private:
|
||||
|
||||
// CoordSys controls (datum coordinate system: point + orthonormal frame).
|
||||
ComboBox* m_coordsys_type{nullptr}; // CoordSysType: PointWorld/FaceAndDirection
|
||||
ComboBox* m_cs_body{nullptr}; // body-focus chooser: restrict picking to one body
|
||||
wxSpinCtrlDouble* m_cs_x{nullptr}; wxSpinCtrlDouble* m_cs_y{nullptr}; wxSpinCtrlDouble* m_cs_z{nullptr};
|
||||
wxButton* m_cs_pick_face{nullptr}; wxStaticText* m_cs_face_lbl{nullptr};
|
||||
wxButton* m_cs_pick_edge{nullptr}; wxStaticText* m_cs_edge_lbl{nullptr};
|
||||
|
||||
@@ -2847,6 +2847,7 @@ 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
|
||||
if (m_solid_visible == nullptr || b >= int(m_solid_visible->size())) return true;
|
||||
return (*m_solid_visible)[b];
|
||||
}
|
||||
|
||||
@@ -141,6 +141,10 @@ public:
|
||||
const std::vector<int>* tri_face, const std::vector<int>* tri_body,
|
||||
const std::vector<bool>* visible = nullptr,
|
||||
const std::vector<Transform3d>* xform = nullptr);
|
||||
// Body-focus picking: >=0 restricts every pick to that one body, so a face behind
|
||||
// another solid is reachable without hiding anything. -1 = no restriction.
|
||||
// Survives set_solid_pick() — it is owned by the panel, not by the mesh feed.
|
||||
void set_pick_only_body(int b) { m_pick_only_body = b; }
|
||||
void clear_solid_selection();
|
||||
// Select a whole body by index (from the Parts list) — Whole-level highlight, no face/edge.
|
||||
// body < 0 or out of range clears the selection.
|
||||
@@ -941,6 +945,7 @@ private:
|
||||
const std::vector<int>* m_solid_tri_face{nullptr};
|
||||
const std::vector<int>* m_solid_tri_body{nullptr};
|
||||
const std::vector<bool>* m_solid_visible{nullptr}; // per-body visibility; hidden bodies aren't pickable
|
||||
int m_pick_only_body{-1}; // >=0: only this body catches clicks (body-focus x-ray for CoordSys picking)
|
||||
const std::vector<Transform3d>* m_solid_xform{nullptr}; // per-body display transform (for edge sampling)
|
||||
Vec3d body_xform_pt(int body, const Vec3d& p) const; // map an OCCT-shape point through the body xform
|
||||
bool body_pickable(int b) const; // false when the body is explicitly hidden
|
||||
|
||||
Reference in New Issue
Block a user