Skip to content

feat(editor): live floor-stacking previews, unified handle system + hit areas, NaN-safe node mutations#375

Merged
Aymericr merged 4 commits into
mainfrom
fix/placement-bbox-and-shelf-nan
Jun 5, 2026
Merged

feat(editor): live floor-stacking previews, unified handle system + hit areas, NaN-safe node mutations#375
Aymericr merged 4 commits into
mainfrom
fix/placement-bbox-and-shelf-nan

Conversation

@Aymericr
Copy link
Copy Markdown
Contributor

@Aymericr Aymericr commented Jun 5, 2026

Summary

Builds on #373. Three coordinated improvements to editor interaction and robustness.

1. Live floor-stacking previews for every floor-placed kind

Item, shelf, spawn, column, and stair now preview their slab-stacking Y offset live during placement and both move pathways (cursor-follow move and the 3D move grip) — previously only the GLB item did this. A single core resolver (getFloorPlacedElevation / getFloorStackedPosition, with composite footprints for stairs) is consumed by the placement/move tools and the viewer FloorElevationSystem.

Canonical node positions stay at base Y — the offset is presentation-only, so undo/redo, the 2D floor-plan mirror, and live transforms never double-apply it.

Composes cleanly with #373: #373 owns X/Z alignment snapping, this owns the Y floor-stack preview.

2. Unified handle system + forgiving hit areas

  • Collapses the duplicated 3D-handle drag lifecycle into one hook (handles/use-handle-drag) and the duplicated arrow rendering into one primitive (handles/handle-arrow). The descriptor renderers and the bespoke group-rotate / wall handles delegate to them (node-arrow-handles.tsx drops ~800 lines).
  • Every handle (cross / chevron / curved / tracker / endpoint) gains a slightly-larger invisible hit area, so the visible arrow stays a crisp indicator while the grab target is forgiving.

3. NaN-safe node mutations

  • Store mutations sanitize non-finite / out-of-range numeric fields before they enter scene state (root cause of a shelf thickness = NaN that produced a NaN BoxGeometry). Unrelated schema mismatches no longer drop the whole update.
  • The viewer's shadow-light bounds guard against non-finite values, so a single bad node can't black out the whole scene.

Files

  • New (9): floor-placed-elevation.ts (+test), node-mutation-sanitize.test.ts, handles/handle-arrow.tsx, handles/use-handle-drag.ts, floor-stack-preview.ts, shelf/dimensions.ts, stair/floor-stack.ts (+test)
  • Modified: core 8 · editor 10 · nodes 13 · viewer 3

Testing

🤖 Generated with Claude Code

…it areas, NaN-safe node mutations

Floor-placed kinds (item, shelf, spawn, column, stair) preview their slab-stacking Y offset live during placement and both move pathways, via a shared core resolver (getFloorPlacedElevation/getFloorStackedPosition; composite footprints for stairs) consumed by the tools and the viewer FloorElevationSystem. Committed positions stay canonical (no double-apply via store/live-transforms/overrides).

Unifies the 3D handle system behind one drag pipeline (handles/use-handle-drag) and one visual primitive (handles/handle-arrow); the descriptor renderers and the bespoke group-rotate/wall handles delegate to them, and every handle gains a forgiving invisible hit area.

Validates node mutations at the store boundary (sanitizing non-finite/out-of-range numeric fields, incl. the shelf-NaN that produced NaN geometry) and guards the viewer's shadow-light bounds against non-finite values so one bad node can't black out the scene. Composes cleanly with #373: #373 owns X/Z alignment, this owns Y floor-stack preview.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mintlify
Copy link
Copy Markdown

mintlify Bot commented Jun 5, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
pascal 🔴 Failed Jun 5, 2026, 1:05 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Aymericr and others added 3 commits June 5, 2026 10:00
… MRT scene pass

The forgiving invisible hit-areas added with the unified handle system used a colorWrite:false + DoubleSide MeshBasicNodeMaterial with no layer, so they defaulted to SCENE_LAYER and entered the post-processing MRT scene pass — unsafe for such NodeMaterials (no color outputs for the 3-target MRT). That poisoned front/back rendering for FrontSide scene geometry, making floor-slab side walls (and other FrontSide meshes) render see-through. Setting the hit mesh to EDITOR_LAYER inside the shared InvisibleHandleHitArea covers all call sites; raycasting is unaffected (the raycaster already enables EDITOR_LAYER). Visible indicators stay on SCENE_LAYER by design.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Selecting a slab highlights its hole cutouts (indigo, matching wall openings); hovering a hole emphasizes it and clicking it opens the hole editor for manual holes or selects the owning stair/elevator for auto holes. The SlabHoleHighlights overlay portals into the slab's object (so R3F delivers pointer events and the holes inherit the slab transform). Hover/edit state lives in useEditor (hoveredHole alongside editingHole); ToolManager only opens the hole editor for manual holes.

The hit box caps its top at the slab surface so the centre thickness handle keeps click priority, and the visible fill/outline render in the scene pass (SCENE_LAYER) so handles sort in front while the invisible hit mesh stays on EDITOR_LAYER (out of the MRT scene pass).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…olygon move + hole click-out

PolygonEditor (slab boundary/edge, slab + ceiling hole, zone/site editors) handles now use the generic indigo interaction states (ARROW_COLOR idle / ARROW_HOVER_COLOR on hover+drag) instead of bespoke green/blue, matching the descriptor, wall, and group handles.

The whole-polygon move grip is now the generic cross-arrow with an invisible cylinder hit area (was a sphere).

Clicking any node (e.g. the slab surface outside a hole) now clears editingHole, so clicking off a hole onto the slab deselects the hole and keeps the slab selected — the hole's handles/hit mesh stopPropagation, so genuine hole interactions are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Aymericr Aymericr marked this pull request as ready for review June 5, 2026 20:24
@Aymericr Aymericr merged commit 0b338cf into main Jun 5, 2026
1 of 2 checks passed
@Aymericr Aymericr deleted the fix/placement-bbox-and-shelf-nan branch June 5, 2026 20:36
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