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
@@ -1,4 +1,5 @@
|
||||
import type { NodeDefinition } from '@pascal-app/core'
|
||||
import { buildShelfFloorplan } from './floorplan'
|
||||
import { buildShelfGeometry } from './geometry'
|
||||
import { shelfParametrics } from './parametrics'
|
||||
import { ShelfNode } from './schema'
|
||||
@@ -43,14 +44,15 @@ export const shelfDefinition: NodeDefinition<typeof ShelfNode> = {
|
||||
|
||||
parametrics: shelfParametrics,
|
||||
|
||||
// Three-checkbox composition: shelf needs only a pure geometry function.
|
||||
// The framework's <ParametricNodeRenderer> mounts an empty group + wires
|
||||
// events / registry / dirty-on-mount; the global <GeometrySystem> calls
|
||||
// `buildShelfGeometry(node)` on every dirty mark and swaps the group's
|
||||
// children. No `renderer.tsx`, no `system.tsx` — see
|
||||
// Three-checkbox composition: shelf needs only pure builder functions.
|
||||
// The framework's <ParametricNodeRenderer> + <GeometrySystem> handle 3D
|
||||
// mount and rebuild on dirty; the <FloorplanRegistryLayer> calls
|
||||
// buildShelfFloorplan for the 2D top-down view. No renderer.tsx, no
|
||||
// system.tsx, no inline floor-plan SVG — see
|
||||
// `wiki/architecture/node-definitions.md`. Shelf is the reference port
|
||||
// proving Phase 4's boilerplate collapse end-to-end.
|
||||
// proving Phase 4's boilerplate collapse for both 3D and 2D.
|
||||
geometry: buildShelfGeometry,
|
||||
floorplan: buildShelfFloorplan,
|
||||
|
||||
preview: () => import('./preview'),
|
||||
tool: () => import('./tool'),
|
||||
|
||||
@@ -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