Files
editor/packages/nodes/src/shelf/floorplan.ts
T
Wassim SAMADandClaude Opus 4.7 ac36297e7e Phase 4 follow-on: registry-driven floor-plan rendering + shelf port
Adds the floor-plan side of the three-checkbox composition model
documented in wiki/architecture/node-definitions.md. Mirrors the 3D
side (def.geometry → <GeometrySystem> → <ParametricNodeRenderer>) but
emits SVG primitives instead of three.js Object3Ds, and runs inside
the floor-plan panel.

Type-side (packages/core/src/registry/types.ts):
 - New FloorplanGeometry tagged union covering path / polygon /
   polyline / rect / circle / line / group. FloorplanStyle props map
   straight to SVG attributes. Coordinates are level-local meters;
   rotations are radians (three.js convention).
 - New `def.floorplan?: (node, ctx) => FloorplanGeometry | null` field
   on NodeDefinition, independent of `geometry` and `renderer`. Re-
   exported via packages/core/src/registry/index.ts.

Runtime (packages/editor):
 - <FloorplanGeometryRenderer> walks the FloorplanGeometry tree and
   emits the matching React-SVG elements. Pure data → DOM; no per-kind
   logic.
 - <FloorplanRegistryLayer> reads the active levelId, walks the level
   subtree, looks up each node's def.floorplan, builds a
   GeometryContext, calls the builder, and renders the output via
   FloorplanGeometryRenderer.
 - Mounted in floorplan-panel.tsx just before <FloorplanMarqueeLayer>
   so registry-driven kinds layer above legacy inline content.

Shelf migration (proof port):
 - New nodes/src/shelf/floorplan.ts — buildShelfFloorplan(node) emits
   a group with the rotation/translation transform and a width × depth
   rectangle in the shelf's color. Brackets omitted (hidden under top
   board from above).
 - Wired to shelfDefinition.floorplan. Shelf now appears in the floor
   plan view for the first time (was missing from the legacy panel's
   inline switch).

Pattern proven; every future kind migrating in Phase 5 follows the
same shape: a pure (node, ctx) => FloorplanGeometry function. As kinds
register their floor-plan builders, the corresponding inline branches
in floorplan-panel.tsx become dead code and can be deleted in the
same PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 10:34:42 -04:00

44 lines
1.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { FloorplanGeometry } from '@pascal-app/core'
import type { ShelfNode } from './schema'
/**
* 2D floor-plan representation of a shelf. The top board (the largest
* visible surface from above) projects to a rectangle of `width × depth`
* centered on `(position.x, position.z)`, rotated by the shelf's Y angle.
*
* Brackets are intentionally omitted — they're hidden under the top
* board from a top-down view, and adding them as separate rects clutters
* the plan without conveying useful information at typical zoom levels.
*
* Coordinates are level-local meters; the floor-plan panel applies the
* world→SVG transform via its viewBox. Rotation is radians (three.js
* convention); the renderer converts to SVG degrees.
*
* Pairs with `buildShelfGeometry(node)` — the 3D builder. Same shape,
* different output projection.
*/
export function buildShelfFloorplan(node: ShelfNode): FloorplanGeometry {
const [px, , pz] = node.position
const ry = node.rotation[1] ?? 0
const halfW = node.width / 2
const halfD = node.depth / 2
return {
kind: 'group',
transform: { translate: [px, pz], rotate: ry },
children: [
{
kind: 'rect',
x: -halfW,
y: -halfD,
width: node.width,
height: node.depth,
fill: node.color,
stroke: '#1f2937',
strokeWidth: 0.015,
opacity: 0.9,
},
],
}
}