Delete the sketch plane dropdown; the viewport decides

The plane combo is gone. A sketch takes its plane from what is picked in
the viewport: a face on a solid, or one of the reference-plane ghosts,
clicked in 3D. The card is now a single line of instruction instead of a
control.

The combo had become worse than redundant. Once a picked face could be
the plane it displayed a row that CONTRADICTED the actual target — it
still said XY while the sketch went onto the face — so the one place a
user could look to confirm where they were drawing was the one place
guaranteed to be wrong.

What replaces it is state, not UI: m_ref_plane records which reference
plane was last clicked in 3D (0/1/2 = XY/XZ/YZ, >=3 indexes the datums)
and ref_plane_name() turns it into text for the on-geometry hint. Clicking
a ghost plane while a session is live re-planes it immediately, which the
combo's own handler used to do; that behaviour is kept, just driven from
the geometry instead of the widget. A plane click also drops a stale face
pick, so last pick wins in both directions.

populate_plane_choices() stays — seven other pickers use it (Plane base,
Axis A/B, Helix, Project, Mirror, Cut). Those are the next candidates,
tracked on snaporca-e1p; this commit only removes the one that had become
actively misleading.

Also: tessellation now matches Orca's OWN STEP importer, linear deflection
0.003 instead of 0.01 (Format/STEP.hpp default; angular was already 0.5
rad and unchanged). The Design viewport was never using a different
rendering technique — it hosts a real GLCanvas3D, builds a real
Model/ModelVolume and goes through the same reload/GLVolume path and the
same shaders as Prepare and Preview. What differed was the mesh handed to
it: 3.3x coarser than anything else in the application, which is why a
curved face read as faceted beside an imported part. Suite unaffected at
154 cases / 2125 assertions, so nothing depended on the old density.

Verified on :10: the card shows no dropdown, one click on a face then a
sketch tool still reports "on the picked face", and the circle is drawn in
that face's plane (artifacts/shots/h3a2-02-sketch.png, h3a2-03-drawn.png).

snaporca-e1p, snaporca-3a2.
This commit is contained in:
Tommaso Bianchi
2026-07-30 14:24:29 +02:00
parent 3c0843c68c
commit 3f8f46f93f
3 changed files with 44 additions and 31 deletions
+7 -1
View File
@@ -424,7 +424,13 @@ public:
// world 0). Not serialized — the GUI re-applies it from the live bed on every tab show.
Vec3d modeling_origin{Vec3d::Zero()};
double linear_deflection{0.01};
// Tessellation quality, matched to Orca's OWN STEP importer (Format/STEP.hpp defaults:
// linear 0.003, angular 0.5 rad) so a body modelled here reaches the screen at the same
// density as the identical body imported through Prepare. It was 0.01 linear — 3.3x coarser
// than anything else in the app, which is why curved faces read as faceted next to an
// imported part. Angular already matched. Same BRepMesh_IncrementalMesh call, same GLVolume
// path, same shaders: the renderer was never the difference, the mesh fed to it was.
double linear_deflection{0.003};
double angular_deflection{0.5};
int add_sketch(SketchShape shape, const SketchPlane& plane,
+32 -29
View File
@@ -511,10 +511,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
auto* b_sketch = icon_btn("design_sketch", _L("Sketch"));
std::function<void()> act_sketch = [this] {
populate_plane_choices(m_draw_plane); // surface datum planes in the picker
set_ui_mode(UiMode::Sketch);
m_status->SetForegroundColour(wxNullColour);
m_status->SetLabel(_L("Pick a plane and a sketch tool, then draw"));
m_status->SetLabel(_L("Click a face or a reference plane in the viewport, then a sketch tool"));
m_status->Refresh();
};
b_sketch->Bind(wxEVT_BUTTON, [act_sketch](wxCommandEvent&) { act_sketch(); });
@@ -2669,24 +2668,13 @@ DesignPanel::DesignPanel(wxWindow* parent)
0, wxLEFT | wxRIGHT | wxTOP, 12);
m_box_sketch_session->Add(new wxStaticLine(m_cards), 0, wxEXPAND | wxALL, 8);
{
auto* prow = new wxBoxSizer(wxHORIZONTAL);
prow->Add(new wxStaticText(m_cards, wxID_ANY, _L("Plane")), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 8);
m_draw_plane = make_combo(m_cards);
m_draw_plane->Append(_L("XY")); m_draw_plane->Append(_L("XZ")); m_draw_plane->Append(_L("YZ"));
m_draw_plane->SetSelection(0);
// Live re-plane: begin_sketch captures the plane only at first-tool-pick, so changing the
// dropdown afterwards used to be inert (sketch stayed on its original plane while the
// committed feature would silently land on the new one). Honour the change immediately —
// the 2D entities are re-lifted through the chosen plane, matching what Finish commits.
m_draw_plane->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) {
if (m_viewport && m_viewport->is_sketching())
m_viewport->set_sketch_plane(plane_from_choice(m_draw_plane->GetSelection()));
});
prow->AddStretchSpacer(); // label left, control right — same row idiom as the grids
prow->Add(m_draw_plane, 0, wxALIGN_CENTER_VERTICAL);
m_box_sketch_session->Add(prow, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 12);
// NO plane dropdown. The sketch plane comes from what is picked in the VIEWPORT — a face
// on a solid, or one of the reference-plane ghosts — because that is where the user is
// looking and pointing. A combo duplicated that decision somewhere the geometry could not
// see it, and once a face could be picked it went further and displayed a stale row that
// contradicted the real target. snaporca-e1p.
auto* hint = new wxStaticText(m_cards, wxID_ANY,
_L("Pick a plane, then draw. Finish (✓) when done."));
_L("Click a face or a reference plane, then a sketch tool."));
hint->SetForegroundColour(dp_sec_text());
m_box_sketch_session->Add(hint, 0, wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, 12);
}
@@ -3296,9 +3284,16 @@ DesignPanel::DesignPanel(wxWindow* parent)
refresh_plane_labels();
refresh_preview(); // re-resolve the frame + move the gizmo/ghosts to the new base
} else {
// Fallback (no object yet): clicking a reference plane selects it as the sketch plane.
if (m_draw_plane && base >= 0 && base < int(m_draw_plane->GetCount()))
m_draw_plane->SetSelection(base);
// Clicking a reference plane in 3D IS how a sketch plane is chosen now. Record it and,
// when a session is already live, re-plane it immediately: begin_sketch captures the
// plane at first-tool-pick, so without this the entities would stay on the old plane
// while the committed feature landed on the new one.
if (base >= 0) {
m_ref_plane = base;
m_pick_face = m_pick_face_body = -1; // last pick wins: a plane beats a stale face
if (m_viewport && m_viewport->is_sketching())
m_viewport->set_sketch_plane(plane_from_choice(m_ref_plane));
}
const char* nm = (base == 0) ? "XY" : (base == 1) ? "XZ" : (base == 2) ? "YZ" : "datum";
m_status->SetForegroundColour(wxColour(120, 210, 120));
// The "press Sketch" half is only true in Feature mode, where that button exists.
@@ -3967,8 +3962,7 @@ void DesignPanel::add_imported_sketch(
}
}
if (!on_face) {
if (m_draw_plane) f.plane = plane_from_choice(m_draw_plane->GetSelection());
else { f.plane = SketchPlane::XY(); f.plane.origin += m_doc.modeling_origin; }
f.plane = plane_from_choice(m_ref_plane);
}
// Drop the live face selection (its body is now remembered on import_face_body): otherwise
@@ -4840,6 +4834,18 @@ void DesignPanel::populate_plane_choices(ComboBox* c) const
c->SetSelection((keep >= 0 && keep < int(c->GetCount())) ? keep : 0);
}
wxString DesignPanel::ref_plane_name(int row) const
{
if (row == 1) return "XZ";
if (row == 2) return "YZ";
if (row >= 3) {
const auto datums = m_doc.resolve_datum_planes();
const int di = row - 3;
if (di < int(datums.size())) return wxString::FromUTF8(datums[di].first);
}
return "XY";
}
SketchPlane DesignPanel::plane_from_choice(int row) const
{
if (row < 3) { // 0=XY,1=XZ,2=YZ through the modeling origin
@@ -4875,11 +4881,8 @@ SketchPlane DesignPanel::sketch_plane_from_selection(wxString& what) const
: _L("the picked face");
return p;
}
const int row = m_draw_plane ? m_draw_plane->GetSelection() : 0;
what = (m_draw_plane && row >= 0 && row < int(m_draw_plane->GetCount()))
? m_draw_plane->GetString(unsigned(row))
: wxString("XY");
return plane_from_choice(row);
what = ref_plane_name(m_ref_plane);
return plane_from_choice(m_ref_plane);
}
void DesignPanel::apply_plane_refs(CadFeature& f) const
+5 -1
View File
@@ -229,6 +229,7 @@ private:
// Plane pickers: fill a choice with XY/XZ/YZ + the document's datum planes, and
// map a choice row back to the actual SketchPlane (rows 0-2 base, 3+ datum).
void populate_plane_choices(ComboBox* c) const;
wxString ref_plane_name(int row) const; // "XY" / a datum's name, for the on-geometry hint
SketchPlane plane_from_choice(int row) const;
// Where a new sketch goes, resolved from what is SELECTED IN THE VIEWPORT rather than from a
// list: a picked planar face wins, otherwise the reference plane last clicked in 3D. `what`
@@ -392,7 +393,10 @@ private:
wxSpinCtrl* m_sides{nullptr}; // polygon sides
CheckBox* m_poly_circ{nullptr}; // polygon circumscribed toggle (Orca teal check)
ComboBox* m_draw_plane{nullptr};
// Which reference plane a sketch falls back to when no face is picked: 0/1/2 = XY/XZ/YZ,
// >=3 indexes resolve_datum_planes(). Set by CLICKING a ghost plane in the viewport — there is
// deliberately no dropdown for it. snaporca-e1p.
int m_ref_plane{0};
ComboBox* m_shape{nullptr};
ComboBox* m_plane{nullptr};
ComboBox* m_mode{nullptr};