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>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
3f3818f3b0
commit
ac36297e7e
@@ -0,0 +1,43 @@
|
||||
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,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user