Three remaining kinds at Stage C this session:
wall → C
- buildWallFloorplan: uses ctx.siblings to gather other walls in the
level, runs calculateLevelMiters, computes plan footprint via
getWallPlanFootprint. Same visual output as legacy.
- getFloorplanWall thickness exaggeration inlined (~25 lines from
editor/lib/floorplan/walls.ts) to keep nodes/wall self-contained.
- floorplan-panel.tsx's wallPolygons short-circuits to [] when wall
is registered.
- Performance note: recomputes level miter data per wall (O(N²) for N
walls in a level). Acceptable for typical scenes; ctx.levelData?.
miters optimization deferred to Stage B's wall design pass.
door → C
- buildDoorFloorplan: inlines getOpeningFootprint math from
floorplan-panel.tsx (40 lines, pure math). Uses ctx.parent as the
wall to compute direction + perpendicular for the cutout footprint.
- Returns null when parent isn't a wall (orphaned doors during
placement).
window → C
- buildWindowFloorplan: same shape as door, glass-blue tint to
distinguish visually.
Both share the legacy openingsPolygons gating:
- floorplan-panel.tsx's openingsPolygons useMemo filters per kind so
a partial migration still works (e.g., if only door registers, only
doors get skipped). When both registered, returns [] entirely.
Item C intentionally deferred — needs parent-chain transform helpers
(buildFloorplanItemEntry / getItemFloorplanTransform from editor/lib/
floorplan/items.ts) exposed publicly or moved into core. A focused
session is the right place to design that boundary.
Stage B for door / window / wall still pending — each is a focused
session per kind (large geometry math extractions, wall needs ctx.
levelData design).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both kinds share traits — hosted on walls, cuttable, animated open/
close state via a geometry system + animation system. Stage A
migration: register + wrap-export the legacy renderer + bundle both
per-kind systems. Pure geometry + floor-plan ports are later
milestones.
Files added (packages/nodes/src/door/, packages/nodes/src/window/):
- schema.ts: re-export from core.
- parametrics.ts: minimal — dimensions only. Door has 29 sliders +
segmented controls + presets in its legacy panel; window has 15+
sliders. Auto-inspector can't cover them at Stage A — legacy
panel keeps rendering via panel-manager.tsx case fall-through.
Stage E may extend parametrics or use parametrics.customPanel
escape hatch.
- definition.ts: capabilities (no `movable` — wall-bound drag is
bespoke; capability-driven dispatch keeps legacy MoveDoorTool /
MoveWindowTool), parametrics, renderer, system. defaults() uses
`DoorNode.parse({...stub})` to leverage zod's schema-level
`.default()` annotations — door has 40+ fields, window has 20+;
listing them inline duplicates the schema.
- renderer.tsx: wrap-export of legacy DoorRenderer / WindowRenderer
(thin 33-36 lines each).
- system.tsx: bundles each kind's TWO systems — DoorSystem +
DoorAnimationSystem, WindowSystem + WindowAnimationSystem. Both
per-kind systems mount via RegisteredSystems when the kind is
registry-driven; `<LegacySystem kind="door|window">` wrappers
around each individual system short-circuit.
- index.ts: barrel.
Files changed:
- packages/viewer/src/index.ts: new public exports for DoorRenderer,
DoorSystem, DoorAnimationSystem, WindowRenderer, WindowSystem,
WindowAnimationSystem.
- packages/nodes/src/index.ts: appends doorDefinition + windowDefinition.
- packages/editor/src/components/ui/panels/door-panel.tsx + window-
panel.tsx: panel slider-drag fix recipe applied. Drop the
subscribed `updateNode` action, drop the `node` dep from
handleUpdate / previewDoorUpdate / commitDoorPreview useCallbacks.
Use useScene.getState() inside. Door panel has 29 SliderControls,
window 15+ — both at high risk of the Maximum update depth
cascade without the fix.
Phase 5 progress: shelf ✅, spawn ✅, wall ✅, fence ✅, slab ✅, ceiling ✅,
door ✅, window ✅. Eight kinds on the registry. Item / stair / roof /
zone / containers remain.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>