Skip to content

[feat] 15-E selection & gizmo rework (+ weld-wireframe fix) - #94

Merged
AlexZ005 merged 2 commits into
release/nextfrom
feat/roadmap15-e-selection-gizmo
Aug 9, 2026
Merged

[feat] 15-E selection & gizmo rework (+ weld-wireframe fix)#94
AlexZ005 merged 2 commits into
release/nextfrom
feat/roadmap15-e-selection-gizmo

Conversation

@AlexZ005

@AlexZ005 AlexZ005 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Roadmap #15 mesh lane, batch E (plan: cloud plans-core/pending/15-e-selection-gizmo.md). Second of D → E → F. Two commits:

Commit 1 — [fix] weld/create-face refresh the session in place (user report)

The edit wireframe stayed stale after a weld: weld/create-face still did a pre-D1 exit→enter dance, so the overlay rebuild depended on re-entry succeeding. They now ride applyMeshGeo's D1 session refresher — ONE refresh path shared with undo and remote commits. Also fixes a latent size-cap bug: a too-large weld mutated the position attribute, then failed the commit without reverting (mesh/wire/peers silently diverged); the raw attribute is now restored.

Commit 2 — [feat] 15-E (E10 → E6 → E7 → E9 → E8)

Unifying rule: the selection IS the op target whenever non-empty; hover/highlight is the fallback.

  • E10 — ctrl/shift-click adds to the face selection on desktop (there was NO ctrl path); Multi button retired (store + toggleFaceMulti kept for VR); plain click = pickFaceUnit (granularity-aware replace); stale-selection auto-heal in highlightFaceByTriangle (VR-per-frame safe; additive clicks skip it); live counts segment — N faces · M tris, plus boundary-edge counts when exactly 2 faces are selected (mismatch tinted red, so a bridge mismatch is visible before clicking).
  • E6 — inset/extrude/move keep the CAP selected (indices survive the op) + highlight re-derived. Fixes the root complaint: an inset cap re-merges coplanarly with its ring in groupFaces, so "inset, then Move just the cap" was impossible. Move (commit or gizmo) is selection-aware; welded ring verts follow, the rest of the plane stays.
  • E7 — the gizmo comes back seated on the new cap after inset/extrude/move commits; never on arm (B1 assertions stay green).
  • E9 — face-basis gizmo (Z = face world normal, deterministic tangents); persisted Local/World toggle (#mesh-gizmo-space); setSpace leak fixed'local' used to stick to the shared TransformControls after any face session; rotation deltas conjugated through R = objQuat⁻¹·proxyStartQuat (rotate-about-normal keeps the cap coplanar).
  • E8 — per-axis face scale: applyFaceGrab takes scale: Vector3|number + scaleQuat (R·S·R⁻¹ sandwich); numbers stay uniform so all VR callers are untouched.
  • attachFaceGizmo never seats in VR (isVRMode guard — VR commits share commitFaceOp now).

Verification

  • NEW mesh-inset-move 6/6 (cap selected, gizmo re-seat, selection-aware move w/ outer plane fixed, gizmo grab parity)
  • desktop-face-gizmo 14/14 (+7: proxy Z = normal, live space toggle, exit restores world, (2,1,1) tangential scale with normal extent unchanged, 90°-about-normal coplanar, committed 25° rotation watertight)
  • faces-toolbar 11/11 (+5: Multi gone, counts, equal vs mismatched edge tints)
  • Regressions green: mesh-ops (35, incl. the B1 inset-interception block), mesh-edit-popup (22), novr-inset, vr-face-edit, vr-face-polygon, vr-face-live-adjust, plus commit 1's vertices-create-face, vr-face-weld, vr-mesh-undo
  • npm run build green; svelte-check 419/62 (gate, unchanged)

🤖 Generated with Claude Code

AlexZ005 and others added 2 commits August 8, 2026 21:41
…frame gone

User report: the edit wireframe overlay stayed unchanged after a weld. Weld
(and create-face) still did a pre-D1 exit->enter dance to regroup handles,
so the overlay rebuild depended on re-entry succeeding; any early-out left
the old wireframe on screen. Since D1, applyMeshGeo refreshes a live vertex
session in place (handles + overlay + selection) - weld and create-face now
ride that same path, one refresh route shared with undo and remote commits.

- also fixes a latent size-cap bug the trace surfaced: a too-large weld
  mutated the position attribute in place, then failed the commit WITHOUT
  reverting (and never set needsUpdate) - mesh, wire and peers silently
  diverged; the raw attribute is now restored on a failed commit
- e2e: mesh-ops +2 (overlay fingerprint tracks the welded geometry; the
  session survives the weld with no exit/enter); regressions green
  (mesh-edit-popup, vertices-create-face, vr-face-weld, vr-face-edit,
  vr-mesh-undo, faces-toolbar); build green; 419/62 held

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… cap + selection-aware move, gizmo re-seat, face-basis local/world gizmo, per-axis face scale

Roadmap 15-E (E10 -> E6 -> E7 -> E9 -> E8), the unifying rule: the selection
IS the op target whenever non-empty; hover/highlight is the fallback.

- E10: ctrl/shift-click ADDS to the face selection everywhere (desktop had
  no ctrl path at all); the Multi toolbar button is retired (the store +
  toggleFaceMulti stay - VR drives them); pickFaceUnit = plain click
  replaces the selection with the granularity-aware unit; stale-selection
  auto-heal in highlightFaceByTriangle (aiming outside the selection
  dissolves it; additive clicks skip the heal or it would wipe what they
  add to); live counts segment #mesh-sel-counts (N faces . M tris + the
  boundary-edge counts of exactly-2 faces, mismatch tinted red - bridge
  mismatches visible BEFORE clicking)
- E6: inset/extrude/move KEEP the cap selected (indices survive: cloneTris
  keeps order, ring/walls append) + highlight re-derived - groupFaces
  re-merges a coplanar inset cap with its ring, so "inset then Move the
  cap" was impossible; the gizmo drag path reads the same selection-first
  target (the CL-B stash)
- E7: the gizmo comes back seated on the new cap after an inset/extrude/
  move commit; NEVER on arm (the B1 fix holds - mesh-ops B1 assertions
  stay green); Scene's tail only re-seats armed Move on non-commit clicks
- E9: face-basis gizmo - Z = the face WORLD normal, X/Y deterministic
  tangents (least-aligned world axis seed); persisted faceGizmoSpace pref +
  [Local|World] toolbar segment; setSpace LEAK fixed (detach/exit restore
  'world' - it used to stick to the shared TransformControls); rotation
  deltas conjugated through R = objQuat^-1 * proxyStartQuat (identity
  pre-E9, so the old path is a special case)
- E8: per-axis face scale - applyFaceGrab takes scale: Vector3|number +
  scaleQuat, diagonal scale sandwiched in the proxy frame (R*S*R^-1);
  a number stays uniform so every VR caller is untouched
- attachFaceGizmo never seats in VR (isVRMode guard - commitFaceOp now
  calls it, and VR commits ride the same code)
- e2e: NEW mesh-inset-move (6); desktop-face-gizmo +7 (proxy Z = normal,
  space toggle + leak fix, tangential (2,1,1) scale w/ normal extent
  unchanged, rotate-about-normal coplanar, committed rotation watertight);
  faces-toolbar +5 (Multi gone, counts, equal/mismatch edge tints);
  regressions green: mesh-ops, mesh-edit-popup, novr-inset, vr-face-edit,
  vr-face-polygon, vr-face-live-adjust. Build green; svelte-check 419/62.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AlexZ005
AlexZ005 merged commit 2ab5c32 into release/next Aug 9, 2026
@AlexZ005
AlexZ005 deleted the feat/roadmap15-e-selection-gizmo branch August 9, 2026 06:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant