Transform: drag the body, the numbers follow

The Placement > Transform verb opened a card of spin controls — dx/dy/dz, an
axis combo, an angle — with nothing on the geometry. The 3-axis drag gizmo the
charter asks for already existed and was fully implemented (arrows, rotation
rings, click-to-type per axis), reachable only from a small icon button in the
tree card header. The prominent verb opened the form; the geometry-first
control was hidden behind an icon. That was backwards.

Transform now arms that same gizmo on the target body. The card stays as L2's
typed half: the drag writes dx/dy/dz, the axis and the angle, and the pivot is
seeded from the body's centroid so the parametric feature reproduces exactly
what was dragged.

Decomposition is exact for the interaction that matters — the gizmo's rings are
per-world-axis, so a ring drag is an axial rotation. A pose composed from two
rings is not axial and the card can only name one axis, so it reports the
dominant one rather than refusing to answer.

Three things this had to get right:

- The gizmo bakes its drag into the display transform so the body follows the
  cursor, and the feature performs the same motion parametrically. Committing
  without reverting first would move the body twice.
- tool_confirm() and tool_cancel() both tested moving_body() BEFORE the active
  tool, so with the gizmo armed Confirm would have dropped the gizmo and never
  created the feature. Both are now guarded on Tool::None.
- close_tool() is the single revert point. Esc, Cancel and switching tools all
  pass through it, so a Transform that was never committed cannot leave the body
  displaced.

Edit mode is untouched: re-seeding the gizmo from a stored feature is a separate
problem, so editing an existing Transform still gets the card alone.

Reviewed and compiled (libslic3r_gui, RC=0); not exercised. snaporca-qtf4.
This commit is contained in:
Tommaso Bianchi
2026-08-12 20:04:45 +02:00
parent 3f62d4d58d
commit b7397b48bd
2 changed files with 91 additions and 2 deletions
+5
View File
@@ -336,6 +336,10 @@ private:
// Cancel reverts to the pose captured when the move started.
int m_move_body{-1};
Transform3d m_move_prev{Transform3d::Identity()};
// Set while the move gizmo is serving the Transform CARD rather than the Move button.
// Both use the same gizmo; only this says which card owns the numbers it reports.
int m_xf_gizmo_body{-1};
Transform3d m_xf_gizmo_base{Transform3d::Identity()}; // pose when Transform armed it
// Onshape-style dialog-card title rows (icon + bold feature name), retitled
// per tool in open_tool() (edit-mode shows the feature's actual name).
@@ -783,6 +787,7 @@ private:
void rebuild_disp_meshes(); // recompute m_disp_* from m_doc + m_body_xform
void feed_bodies(); // push m_disp_* + visibility/xform to the viewport
void on_move_body(); // start the move gizmo on the selected body
void arm_transform_gizmo(); // arm the move gizmo on the Transform card's body (add mode only)
void on_set_body_color(); // Color tool: pick a per-body display colour override
int tree_selection() const; // selected feature row, or wxNOT_FOUND
int tree_body_selection() const; // selected Parts-list body index, or -1