Rib: the thickness gets its handle, so the whole tool is draggable

Rib's depth already reused the Extrude arrow. Its thickness could not: the arrow
points along the plane normal, and thickness is an offset either side of the rib
line, IN the plane. Different direction, different handle.

Two square handles at mid ± perp·half, plus the slab's actual footprint drawn as
a thin closed rectangle — the footprint matters more than the dots, because what
a rib thickness means is how wide that slab lands on the body, and until now
there was no way to see it before committing.

A drag on either handle sets the FULL thickness, twice the perpendicular distance
from the line, because the slab is centred on the line and the handle sits at
half. Both handles behave identically for the same reason, so they share one
colour rather than pretending to be two different actions.

A zero-length line has no direction to grow a slab perpendicular to, so the
shared rib_frame() helper returns false and render and drag both draw nothing
rather than dividing by zero. Non-Line entities clear the gizmo instead of
guessing: the kernel is line-only and a gizmo that guesses would be lying about
what Confirm will build.

Unlike the helix callback this one goes through refresh_preview(), because Rib
builds a real solid ghost that has to rebuild. The helix has none and skips it
deliberately.

Both gizmos coexist and resolve the sketch and entity the same way, so the depth
arrow and the thickness handles can never disagree about which line they are on.

Reviewed and compiled (libslic3r_gui, RC=0); not exercised. snaporca-plew.
This commit is contained in:
Tommaso Bianchi
2026-08-12 21:34:59 +02:00
parent b9d6b59f90
commit e6a14b39c9
6 changed files with 221 additions and 1 deletions
+23 -1
View File
@@ -119,7 +119,7 @@ public:
|| m_show_planes || m_show_axes
|| m_ex_active || m_mv_active || m_fl_active
|| m_hl_active || m_th_active || m_sh_active
|| m_dr_active || m_ct_active || m_dz_active || m_dbp_active || m_hx_active; }
|| m_dr_active || m_ct_active || m_dz_active || m_dbp_active || m_hx_active || m_rb_active; }
// View helpers: the 3 world origin planes (XY/XZ/YZ) and the world axis triad, each
// shown/hidden by a toggle (keys P / A). Off by default so the idle scene stays clean.
@@ -214,6 +214,15 @@ public:
void clear_helix_gizmo();
std::function<void(double radius, double pitch, double height)> on_helix_changed;
// Visual Rib thickness gizmo. The rib is a thin slab grown either side of an open sketch
// line, so its thickness is an IN-PLANE offset perpendicular to that line — the depth arrow
// (which points along the plane normal) cannot express it. Two handles, one per side,
// dragged symmetrically: the slab is centred on the line, so a drag on either side sets the
// full thickness rather than one half.
void set_rib_gizmo(const SketchPlane& plane, const Vec2d& p0, const Vec2d& p1, double thickness);
void clear_rib_gizmo();
std::function<void(double thickness)> on_rib_thickness_changed;
// Graphical base/origin pick: while the Plane card is open, the candidate base planes
// (XY/XZ/YZ origin planes + existing datums) draw as translucent clickable ghosts. A click
// on one fires on_datum_base_picked(base) with that plane's base index (0/1/2 or 3+N).
@@ -1039,6 +1048,19 @@ private:
void render_helix_gizmo();
bool hit_test_helix_handle(GLCanvas3D& canvas, const wxMouseEvent& evt, int& which) const;
void drag_helix_handle(GLCanvas3D& canvas, const wxMouseEvent& evt, int which);
// Rib thickness gizmo state (plane-anchored slab footprint + 2 drag handles). Fed by the
// panel while the Rib card is open (sketch tool NOT active); the tool draws the rib's
// footprint outline and a handle on each side of the line at half-thickness. Dragging either
// handle sets the full thickness (the slab is centred on the line).
bool m_rb_active{false};
SketchPlane m_rb_plane;
Vec2d m_rb_p0{Vec2d::Zero()}; // rib line endpoints, in plane coords
Vec2d m_rb_p1{Vec2d::Zero()};
double m_rb_thickness{2.0};
int m_rb_drag{-1}; // 0 = +perp handle, 1 = -perp handle, -1 none
void render_rib_gizmo();
bool hit_test_rib_handle(GLCanvas3D& canvas, const wxMouseEvent& evt, int& which) const;
void drag_rib_handle(GLCanvas3D& canvas, const wxMouseEvent& evt, int which);
// Datum base picker (translucent clickable origin/datum planes)
bool m_dbp_active{false};
std::vector<SketchPlane> m_dbp_planes;