perf+fix(editor): gate 2D scene in 3D mode; wall-endpoint move via live overrides

Two changes from the split-view / wall-endpoint perf + UX pass.

floorplan-panel: render the heavy 2D <svg> scene only when the panel is visible
(`isFloorplanOpen`, i.e. viewMode !== '3d'). The panel stays mounted in 3D
(display:none) to keep the portalled compass + viewport state warm, but the
registry layer / per-node InteractiveGeometry / handle layers no longer
reconcile on every scene change while invisible. Renders fully in 2D and split;
viewport pan/zoom is preserved across the toggle.

wall move-endpoint-tool: preview via `useLiveNodeOverrides` instead of writing
`useScene.updateNodes` every grid:move tick. The per-tick store write handed a
fresh `nodes` ref to every `useScene(s => s.nodes)` subscriber (WallPanel, the
contextual HUD, tooltips, floor plan), rebuilding them all each frame. Overrides
are merged by the wall system, wall panel, and 2D floor plan, so the preview
still tracks live with no store churn; the store is written once on commit, and
one Ctrl-Z reverts to the original endpoint. Also swallow the click that follows
every endpoint-tool release so it can't fall through to the wall body and arm
the wall move tool (no-drag tap or post-commit).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Wassim SAMAD
2026-06-27 19:39:10 -04:00
co-authored by Claude Opus 4.8
parent b384bc8178
commit eeadec11a7
2 changed files with 84 additions and 29 deletions
@@ -10797,7 +10797,16 @@ export function FloorplanPanel({
<div className="flex h-full items-center justify-center px-6 text-center text-muted-foreground text-sm">
Switch to a building level to view and edit the floorplan.
</div>
) : (
) : isFloorplanOpen ? (
// The panel stays mounted in 3D mode (display:none) to keep the
// portalled compass + viewport state warm, but the heavy 2D scene
// (registry layer → one InteractiveGeometry per node, geometry
// renderer, handle layers) must NOT render/reconcile while hidden —
// otherwise every scene/selection change in pure 3D re-rendered the
// whole floorplan tree (profiler: 150200ms on a wall-endpoint drag).
// `isFloorplanOpen` is `viewMode !== '3d'`, so this still renders fully
// in both 2D and split. Viewport state lives on the still-mounted
// panel, so pan/zoom is preserved across the toggle.
<svg
className="h-full w-full touch-none"
onClick={isMarqueeSelectionToolActive ? undefined : handleSvgClick}
@@ -11137,7 +11146,7 @@ export function FloorplanPanel({
/>
)}
</svg>
)}
) : null}
</div>
</div>
)