mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-18 14:32:36 +00:00
CAD: an armed face/edge pick must not lose its click to the body escalation
A card that asks for a face ("Click a solid FACE in the viewport") could not be
satisfied. Clicking the same sub-element twice deliberately escalates to the
whole body — right for free picking, wrong here: the user clicks the very face
the card is pointing at, the escalation turns it into a whole-body pick, and the
armed capture rejects it and leaves "(none)". Both orders failed, so a
face-based Coord Sys was reachable only by accident of ordering. That mattered
beyond the card: a mate needs a connector with an owning body, and a face or
edge pick is the only thing that sets one.
Adds DesignSketchTool::set_escalate_on_repick, off while the Plane, Axis or
CoordSys card has a pick armed and back on as soon as it is captured or
abandoned. While armed, clicking a face means "this face", which is what the
prompt already says.
Verified on the rig: arm Pick Face, click the face, and it reads "#5" on the
first click. With nothing armed the escalation still alternates whole <-> face
as before.
This commit is contained in:
@@ -604,6 +604,11 @@ void DesignCanvas::set_loop_pick(int feature, int region)
|
||||
request_repaint();
|
||||
}
|
||||
|
||||
void DesignCanvas::set_escalate_on_repick(bool on)
|
||||
{
|
||||
m_sketch_tool.set_escalate_on_repick(on);
|
||||
}
|
||||
|
||||
void DesignCanvas::set_solid_pick(const std::vector<CadBody>* bodies, const TriangleMesh* mesh,
|
||||
const std::vector<int>* tri_face, const std::vector<int>* tri_body,
|
||||
const std::vector<bool>* visible,
|
||||
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
std::vector<std::vector<int>> region_entity_indices(const std::vector<SketchEntity>& ents) const;
|
||||
void clear_loop_pick(); // drop the click-selected loop highlight (e.g. after extrude)
|
||||
void set_loop_pick(int feature, int region); // adopt a loop pick made before the commit
|
||||
void set_escalate_on_repick(bool on); // off while a card has armed a face/edge pick
|
||||
// Solid whole/face/edge selection: point the tool at the bodies + concatenated
|
||||
// tessellation (with per-triangle face & body ids), and a callback fired on each
|
||||
// whole->face->edge cycle (level, body index, face id, edge id).
|
||||
|
||||
@@ -3493,6 +3493,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
default: break;
|
||||
}
|
||||
if (got) { m_plane_pick = PlanePick::None; refresh_plane_labels(); }
|
||||
if (got && m_viewport) m_viewport->set_escalate_on_repick(true);
|
||||
}
|
||||
// Axis tool with a pick armed: face or edge.
|
||||
if (m_active == Tool::Axis && m_axis_pick != AxisPick::None) {
|
||||
@@ -3503,6 +3504,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
default: break;
|
||||
}
|
||||
if (got) { m_axis_pick = AxisPick::None; refresh_axis_labels(); }
|
||||
if (got && m_viewport) m_viewport->set_escalate_on_repick(true);
|
||||
}
|
||||
// CoordSys tool with a pick armed: face or edge.
|
||||
if (m_active == Tool::CoordSys && m_coordsys_pick != CoordSysPick::None) {
|
||||
@@ -3513,6 +3515,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
default: break;
|
||||
}
|
||||
if (got) { m_coordsys_pick = CoordSysPick::None; refresh_coordsys_labels(); }
|
||||
if (got && m_viewport) m_viewport->set_escalate_on_repick(true);
|
||||
}
|
||||
m_status->SetForegroundColour(wxNullColour);
|
||||
const int nb = int(m_doc.bodies.size());
|
||||
@@ -5843,6 +5846,7 @@ void DesignPanel::reset_plane_refs()
|
||||
m_pl_faceA_body = m_pl_faceA = -1; m_pl_faceB_body = m_pl_faceB = -1;
|
||||
m_pl_edgeA_body = m_pl_edgeA = -1; m_pl_edgeB_body = m_pl_edgeB = -1;
|
||||
m_plane_pick = PlanePick::None;
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
refresh_plane_labels();
|
||||
}
|
||||
|
||||
@@ -5882,6 +5886,7 @@ void DesignPanel::reset_axis_refs()
|
||||
m_ax_face_body = m_ax_face = -1;
|
||||
m_ax_edge = -1;
|
||||
m_axis_pick = AxisPick::None;
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
refresh_axis_labels();
|
||||
}
|
||||
|
||||
@@ -5942,6 +5947,7 @@ void DesignPanel::reset_coordsys_refs()
|
||||
m_cs_face_body = m_cs_face = -1;
|
||||
m_cs_edge = -1;
|
||||
m_coordsys_pick = CoordSysPick::None;
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
refresh_coordsys_labels();
|
||||
if (m_cs_body) m_cs_body->SetSelection(0);
|
||||
if (m_viewport) m_viewport->set_xray_focus(-1);
|
||||
@@ -5951,6 +5957,10 @@ void DesignPanel::reset_coordsys_refs()
|
||||
void DesignPanel::arm_coordsys_pick(CoordSysPick target)
|
||||
{
|
||||
m_coordsys_pick = target;
|
||||
// While this pick is armed the click the card asked for must reach it, so the whole-body
|
||||
// escalation is off: clicking the face the card is pointing at is the ANSWER here, not a
|
||||
// request for its body.
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(false);
|
||||
m_status->SetForegroundColour(wxNullColour);
|
||||
set_status(target == CoordSysPick::Face ? _L("Click a solid FACE in the viewport")
|
||||
: _L("Click a solid EDGE in the viewport"));
|
||||
@@ -8163,6 +8173,8 @@ void DesignPanel::load_feature_into_dialog(const CadFeature& f)
|
||||
m_plane_usize->SetValue(f.plane_u_size);
|
||||
m_plane_vsize->SetValue(f.plane_v_size);
|
||||
m_plane_pick = PlanePick::None;
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
refresh_plane_labels();
|
||||
break;
|
||||
case CadFeatureType::Loft:
|
||||
@@ -8188,6 +8200,8 @@ void DesignPanel::load_feature_into_dialog(const CadFeature& f)
|
||||
m_axis_p1x->SetValue(f.axis_p1.x()); m_axis_p1y->SetValue(f.axis_p1.y()); m_axis_p1z->SetValue(f.axis_p1.z());
|
||||
m_axis_p2x->SetValue(f.axis_p2.x()); m_axis_p2y->SetValue(f.axis_p2.y()); m_axis_p2z->SetValue(f.axis_p2.z());
|
||||
m_axis_pick = AxisPick::None;
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
refresh_axis_labels();
|
||||
break;
|
||||
case CadFeatureType::CoordSys:
|
||||
@@ -8201,6 +8215,8 @@ void DesignPanel::load_feature_into_dialog(const CadFeature& f)
|
||||
m_cs_hy->SetValue(f.coordsys_x_hint.y());
|
||||
m_cs_hz->SetValue(f.coordsys_x_hint.z());
|
||||
m_coordsys_pick = CoordSysPick::None;
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
if (m_viewport) m_viewport->set_escalate_on_repick(true); // pick abandoned
|
||||
refresh_coordsys_labels();
|
||||
refresh_cs_body_choice();
|
||||
if (m_cs_body && f.coordsys_body >= 0) {
|
||||
|
||||
@@ -3159,7 +3159,7 @@ bool DesignSketchTool::handle_solid_click(GLCanvas3D& canvas, const wxMouseEvent
|
||||
: m_solid_sel == SolidSel::Edge ? m_sel_edge == prev_edge
|
||||
: m_solid_sel == SolidSel::Face ? m_sel_face == prev_face
|
||||
: true);
|
||||
if (same_pick) {
|
||||
if (same_pick && m_escalate_repick) {
|
||||
select_body(m_sel_body); // clears face/edge/vertex, tints the whole body
|
||||
dp_pick_trace("re-pick -> escalated to whole body %d", m_sel_body);
|
||||
}
|
||||
|
||||
@@ -90,6 +90,13 @@ public:
|
||||
// Does the live session hold anything a cancel would throw away? Escape must not silently
|
||||
// destroy drawn geometry; the panel asks this before treating Escape as "discard sketch".
|
||||
bool live_sketch_has_work() const { return !m_entities.empty(); }
|
||||
|
||||
// Clicking the same sub-element again escalates to the whole body. That is right for free
|
||||
// picking and WRONG while a card has armed a face/edge pick: the card says "click a FACE",
|
||||
// the user clicks the face it is already showing, and the escalation turns it into a
|
||||
// whole-body pick that the armed capture then rejects. The host turns this off for as long
|
||||
// as a pick is armed.
|
||||
void set_escalate_on_repick(bool on) { m_escalate_repick = on; }
|
||||
bool constrain_value_anchor(wxPoint& out) const; // screen anchor over the picked constrain geometry
|
||||
|
||||
void begin(const SketchPlane& plane, Mode mode = Mode::Polyline);
|
||||
@@ -1043,6 +1050,7 @@ private:
|
||||
int& edge_feat, int& edge_reg, int& edge_ent,
|
||||
double& edge_d, int& face_feat, int& face_reg) const;
|
||||
bool m_right_consumed{false}; // last RightDown was a gesture terminator, not a menu
|
||||
bool m_escalate_repick{true}; // re-picking the same sub-element takes the whole body
|
||||
void render_solid_highlight();
|
||||
// The shared body of the above: one highlight from explicit arguments, so the committed
|
||||
// selection and the hover pre-highlight cannot drift apart in how they look.
|
||||
|
||||
Reference in New Issue
Block a user