Skip to content

[feat] roadmap 13 batch D - VR fix pack (D1-D7) - #34

Merged
AlexZ005 merged 10 commits into
mainfrom
feature/roadmap-13-vr-fixes
Jul 23, 2026
Merged

[feat] roadmap 13 batch D - VR fix pack (D1-D7)#34
AlexZ005 merged 10 commits into
mainfrom
feature/roadmap-13-vr-fixes

Conversation

@AlexZ005

Copy link
Copy Markdown
Collaborator

Roadmap #13 Batch D - the VR fix pack (D1-D7), one commit per phase.

Fixes

  • D1 teleport handedness: the arc resolved its controller via raw sources.indexOf(source) - the last raw-slot holdout of the 194/210 class. Now teleportArcPose() resolves by the handedness stamp (caller-session fallback for unstamped slots).
  • D2 vertex-handle raycast bounds: refreshHandleMatrix never invalidated the InstancedMesh boundingSphere, so handles re-posed outside the entry-time bounds silently stopped picking. Bounds are nulled on every re-pose (covers tickMeshEdit / applyVerts / undo).
  • D6 ping accuracy: radial Ping used to fire while the pointer ray was parked on the radial itself - it now ARMS a one-shot (beam+reticle tint to your ping color, next trigger pings the exact pointed x,y,z, sky-miss keeps the arm, reopening the radial cancels). The right-stick ping resolves the POINTER hand instead of a raw right slot.

Features

  • D3 multi Save Prefab: the radial obj:prefab saves a multi-selection as ONE layout-preserving prefab (savePrefabSelection, desktop parity).
  • D4 multi-select-aware Edit ring: counted labels act on the SET (Duplicate/Delete/Save prefab), Make Group replaces Edit Mesh for 2+ selected (one-undo groupSelection), Properties greys out (new disabled() entry predicate, activation blocked), and the VR palette paints the whole selection with ONE composite undo entry.
  • D5 reticle v2: beams terminate on OPEN floating panels (nearest hit wins, panel clears the object hover) and the reticle ring lays onto the hit surface via the world normal (viewer-flipped, z-fight nudge) - full circle visible on curved faces.
  • D7 editable mesh-edit caps: defaults raised (face 300->1000 tris, vertex 500->800 verts) so the default sphere edits out of the box; both limits are Settings > VR number rows (localStorage). Over-limit warns with counted toasts deep-linking to the setting; a blocking GROUP says Ungroup first.

Verification

  • New e2e suites: vr-teleport-handedness, vr-vertex-handle-bounds, vr-multi-prefab, vr-multiselect-ring, vr-reticle-v2, vr-ping-accuracy, vr-edit-caps - all green, plus the neighboring suites (teleport/vertex/face/palette/radial/ping/settings) re-run green.
  • Two pre-existing stale expectations fixed along the way: vr-radial-menu exact Edit-ring join (avatar:possess from the default-on avatar module) and vr-face-edit's meshgeo positions.length (the Feature/scene-lights #12 raw-bytes wire format).
  • npm run build green after every phase; npx svelte-check holds the 501/77 baseline.
  • Headless math/state verification only - on-device VR feel (teleport arc, reticle lay-flat, ping arming, greyed sectors) is the user's manual check.

🤖 Generated with Claude Code

AlexZ005 and others added 7 commits July 21, 2026 20:49
- updateTeleport was the last raw sources.indexOf(source) holdout (194/210
  class): after a hands<->controllers swap the inputSources order diverges
  from the three.js controller slots, so the arc rode the wrong controller
- new teleportArcPose(session) resolves the slot via controllerIndexFor
  with a caller-session fallback for unstamped slots (fake-session tests)
- e2e vr-teleport-handedness: arc pose follows the stamp across a slot
  swap; no right hand -> no arc; existing teleport suites stay green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- three caches an InstancedMesh boundingSphere for its raycast pre-check;
  refreshHandleMatrix never invalidated it, so handles re-posed outside the
  entry-time bounds (object moved, far vertex drag, undo swap) silently
  stopped ray-picking in VR and on desktop
- null boundingSphere/boundingBox on every handle re-pose so the next
  raycast lazily recomputes; covers tickMeshEdit, applyVerts and undo paths
- e2e vr-vertex-handle-bounds: corner handle picks at spawn, still picks
  after the object moves 50 units, old spot no longer picks

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- obj:prefab now saves the WHOLE selection as one layout-preserving prefab
  via savePrefabSelection (the U-2 op desktop already uses); single
  selection keeps the single-object savePrefab path
- e2e vr-multi-prefab: two selected objects -> ONE Group prefab with both
  members; single selection still snapshots a Mesh
- known pre-existing: vr-radial-menu exact Edit-ring expectation fails on
  main too (avatar:possess from the default-on avatar module) - the D4
  Edit-ring rework updates that suite

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- counted labels act on the SET: Duplicate/Delete/Save prefab show (N) and
  run duplicateSelection/deleteSelection/savePrefabSelection (desktop
  objectMenu parity, U-2)
- Make Group takes the Edit Mesh slot for 2+ selected (one-undo
  groupSelection); Edit Mesh/Ungroup gate on a single selection
- entry schema gains disabled(): greyed sector + label, activation blocked
  at the top of executeVRMenuAction; Properties greys out when multi
  (primary-only panel would silently edit one member)
- the VR palette paints the whole selection set: per-object before map,
  one composite history entry via the batch API, throttled live colors
- VRMenu re-derives sectors on selectedObjects; disabled styling
- e2e vr-multiselect-ring (ring swap, counted labels, set duplicate,
  one-undo group, disabled props); vr-radial-menu expectation now allows
  module-registered entries (avatar:possess made the exact-join check fail
  on main - pre-existing)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rface

- beamTarget: the beam/reticle now ends on the NEAREST hit among scene
  objects and any OPEN floating panel (menu/objects/props/prefabs/chat/
  settings/approve/edit/snap/keyboard/palette) so navigating menus shows
  the beam ending in a circle on the hovered control; a panel in front
  clears the object hover behind it
- reticlePose: the ring lays onto the hit surface via the world-space face
  normal (flipped toward the viewer, nudged 0.004*scale off the surface so
  it never z-fights), beam-aligned fallback when the hit has no normal -
  a full circle is visible on spheres/curved faces telling the user
  exactly where they point
- e2e vr-reticle-v2: pose math (flat fallback, floor lay-flat, backface
  flip, min scale) + nearest-wins panel termination round-trip

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- radial Ping used to fire IMMEDIATELY from the pointer hand, but on a
  trigger activation that ray is parked on the radial itself, so the ping
  landed wherever the menu floated. The sector now ARMS a one-shot
  (vrPingArmed): the ring closes, beam+reticle tint to your ping color,
  and the NEXT trigger pings the exact pointed x,y,z from the firing
  controller (firePingIfArmed in Scene's trigger path, before the prefab
  ghost). A sky miss keeps the arm; reopening the radial cancels it
- right-stick ping resolves the POINTER hand (pointerHandIndex) - with
  the menu on the right hand it pinged where the MENU hand pointed
- pingFromController reports whether a ping landed and refuses index -1
- e2e vr-ping-accuracy: arm/fire/miss/cancel round-trip + pointer-hand
  resolution; ping/ping-v2/ping-highlights suites stay green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- caps raised: face 300 -> 1000 tris, vertex 500 -> 800 verts, so the
  default sphere (960 tris / 561 verts) is editable out of the box
- both limits are live user-editable stores (vrFaceCap/vrVertexCap,
  localStorage-persisted) with number rows in Settings > VR; the section
  now binds settingsSection=vr for deep links
- over-limit attempts warn with COUNTED toasts (N of limit) carrying an
  Open Settings action that lands on the VR section (editCapToast) - all
  three block sites: enterFaceEdit, the Edit side-menu vertices mode, and
  the obj:editmesh dense fallback
- a GROUP blocking mesh edit now says Ungroup it first / edit each mesh
  (the common imported-model blocker) in both edit modes
- e2e vr-edit-caps (defaults, counted toasts, deep link, persistence,
  group hint, settings row round-trip); vr-face-edit/vr-vertex-edit
  updated for the new defaults (+ the face suite meshgeo check now
  accepts the 12 raw-bytes wire format it had drifted from)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AlexZ005 added a commit that referenced this pull request Jul 22, 2026
…itions, modules repo

- CLAUDE.md map rewritten for flow v2: flowGraphs source-of-truth + editor-view
  mirror (and WHY it lives in the leaf store), flowGraphs.js/objectFlow.js libs,
  graph-routed nodesHandler, implicit-owner runtime rule, embed inject/harvest,
  resolvedInputType/replaceableInputEdges socket rules
- new gotchas: the history.js TDZ-cycle family (flowRuntime imports must not
  reach history/shortcuts statically), NodeWrapper flex-ROW slot + padded-box
  handle anchoring, autosave GLTF restore re-uuid (userData.__uuid stamp),
  deselect clears only the selectedObjects SET
- Module SDK section: registerNodeDefs + pointerRay (drag recipe) + the
  theprototype-app/modules repo (flow-toolkit, untangle)
- status 2026-07-22: PR #36 + #37 merged, 190 untangle shipped as-built,
  svelte-check baseline now 499/77, remaining H4 + open PRs #33/#34
- e2e skill: npx vite dev (npm eats --port flags), __stores additions
  (flowGraphs/flowGraphsCtl/objectFlow/pointerRayNow/applyModuleMessage),
  repo-external module verification recipe (manager zip install)
- peer-feature skill: per-object graph replication rules (graphId, allNodes,
  prune invariants, flowgraph history kind, single-connection inputs) + SDK
  additions + untangle as the worked game example

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AlexZ005 and others added 2 commits July 23, 2026 07:37
- the blue wireframe overlay is a LineSegments CHILD of the edited object;
  three raycasts lines with a 1-WORLD-UNIT threshold, so every
  objectsGroup raycast (beam/reticle, selection, ping) hit invisible fat
  lines up to a metre off the surface while vertex-editing. Faces mode was
  immune because its overlay lives at the scene root - exactly the
  on-device report. The overlay is now non-raycastable (decorative)
- the scene-root vertex HANDLE dots join beamTarget while editing, so the
  beam/reticle terminate ON the handle you point at (parity with faces
  mode); a handle hit never highlights an object
- e2e vr-vertex-ray: near-miss ray no longer phantom-hits, face ray lands
  at the true surface distance on the MESH, corner ray terminates on the
  handle, exit removes the targets

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- new vrNavigationSuppressed() predicate: true while world pan (right grip
  on air), two-grip world grab, two-hand object scale, vertex carry
  (grip or trigger), face rigid grab, live extrude/inset adjust, a stretch
  slider drag or a box-select marquee is active; with {grips:true} it also
  covers ANY held grip
- updateVRControls gates teleport + snap-turn on it (grips included - a
  held grip always means manipulation) and DISARMS on suppression so a
  gesture released mid-stick-deflection cannot fire a queued teleport or
  an instant snap; the stick must return to center first
- VRControls.svelte gates left-stick locomotion on the plain predicate;
  left-grip + left-stick pan/elevate deliberately stays (it is itself a
  locomotion mode), world pan/grab and mesh gestures never also move you
- e2e vr-nav-suppression drives the reachable gestures through their real
  entry points (face live-adjust, hold-style vertex carry); grips and
  world-pan need a live squeeze loop, so their feel is the on-device check
- test infra: helpers.cjs gains opt-in PEER_CONFIG env (seeds the
  peer-server Settings per context) - localhost-origin lanes resolve to a
  local :9001 signaling server that is not running, which broke every
  two-peer suite; vr-box-select Tools-ring expectation now tolerates the
  U-1 Ping entry (stale on main)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AlexZ005

Copy link
Copy Markdown
Collaborator Author

Three on-device follow-ups pushed (D8-D10), from VR testing feedback:

  • D8 vertex-mode ray (5f3fc95): the blue wireframe overlay is a LineSegments CHILD of the edited object and three raycasts lines with a 1-world-unit threshold, so beams/selection/pings hit invisible fat lines up to a metre off the surface in VERTEX mode (faces mode was immune - its overlay is scene-root). Overlay is now non-raycastable; the vertex handle dots join beamTarget so the reticle terminates on the dot you point at.
  • D9 navigation suppression (d466be4): new vrNavigationSuppressed() predicate - teleport/snap-turn suppress while ANY grip is held or a manipulation gesture is active (world pan, two-grip world grab, two-hand scale, vertex carry, face grab/live-adjust, stretch slider, box select); left-stick locomotion suppresses on the gesture set (left-grip pan/elevate deliberately kept - it IS a locomotion mode). Suppression also disarms mid-deflection so releasing a gesture can't fire a queued teleport.
  • D10 stick ping hand (7ed3368): right-stick ping now fires from the hand that CLICKED the stick - the D6 pointer-hand routing sent it down the LEFT ray whenever the menu sat on the right hand.

Also in D9: tests/e2e/helpers.cjs gains an opt-in PEER_CONFIG env (localhost-origin lanes resolve the peer server to a local :9001 that isn't running, which broke every two-peer suite in the worktree), and vr-box-select's Tools-ring expectation now tolerates the U-1 Ping entry (stale on main). Build green + svelte-check 501/77 on each commit; on-device feel of the suppression/ray fixes is the user's check.

- the stick-click ping routed through the POINTER hand (opposite the menu
  hand), so with the menu on the right hand a right-stick click sent the
  ping down the LEFT ray - the on-device report. Pings now always fire
  from the ACTING hand: the clicked stick hand here, the firing trigger
  hand for the armed radial ping (already the case)
- pointerHandIndex stays for hover targeting; doc updated
- e2e vr-ping-accuracy gains an acting-hand check (armed fire from slot 0
  follows slot 0 ray even though the pointer hand is slot 1)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AlexZ005
AlexZ005 merged commit a049c11 into main Jul 23, 2026
@AlexZ005
AlexZ005 deleted the feature/roadmap-13-vr-fixes branch August 5, 2026 20:24
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