Lands the three-checkbox composition runtime documented in wiki/architecture/node-definitions.md. A kind with only a pure geometry function now needs zero per-kind React or system code. Type-side additions (packages/core/src/registry/types.ts): - New `GeometryContext` (resolve / children / siblings / parent) — read- only scene access for builders that reference other nodes by ID (wall miters, door cutouts). Most kinds ignore it. - New `geometry?: (node, ctx) => Object3D` field on NodeDefinition, independent of renderer/system. Three orthogonal opt-ins replace the v0 RendererSource union. - Re-exported via packages/core/src/registry/index.ts (consumed by nodes packages through `export * from './registry'`). Runtime (packages/viewer): - New <GeometrySystem> (systems/geometry/geometry-system.tsx) walks dirtyNodes, builds a GeometryContext per dirty node, calls def.geometry, disposes old children, attaches new ones, clearDirty. Frame priority 2 (matches the priority shelf's per-kind system had). Mounted in viewer/index.tsx alongside <RegisteredSystems>. - New <ParametricNodeRenderer> (components/renderers/parametric-node- renderer.tsx) — empty <group> + useRegistry + useNodeEvents + markDirty-on-mount + useLiveTransforms. Mounts hosted children via <NodeRenderer> recursively. The default renderer for any registered kind without a custom def.renderer. - <NodeRenderer> dispatch updated: custom renderer wins, else geometry-only kinds fall through to ParametricNodeRenderer, else null (legacy switch fallback). Documented inline. Shelf migration (proof of the boilerplate collapse): - Deleted nodes/src/shelf/renderer.tsx (was 45 lines of registry + handler boilerplate). - Deleted nodes/src/shelf/system.tsx (was 60 lines of dirty-loop + dispose plumbing). - shelfDefinition now: `geometry: buildShelfGeometry`. One line. buildShelfGeometry is the pure function from geometry.ts that already existed. End-to-end effect: registry-driven shelf now mounts via the framework's generic renderer + system. Parametric edits flow through the same dirty-driven rebuild path, but the kind ships ~100 fewer lines of boilerplate. Every future kind that fits the same shape (item, fence segment, column, etc. as they migrate in Phase 5) follows the same "one line, one pure function" pattern. Wall stays on its dedicated def.renderer + def.system — its mitering needs level-batch context (`ctx.levelData?.miters`, future extension) that the generic system doesn't yet provide. Decided at Phase 3+, not blocking Phase 4 acceptance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pascal-app/core
Core library for Pascal 3D building editor.
Installation
npm install @pascal-app/core
Peer Dependencies
npm install react three @react-three/fiber @react-three/drei
What's Included
- Node Schemas - Zod schemas for all building primitives (walls, slabs, items, etc.)
- Scene State - Zustand store with IndexedDB persistence and undo/redo
- Systems - Geometry generation for walls, floors, ceilings, roofs
- Scene Registry - Fast lookup from node IDs to Three.js objects
- Spatial Grid - Collision detection and placement validation
- Event Bus - Typed event emitter for inter-component communication
- Asset Storage - IndexedDB-based file storage for user-uploaded assets
Usage
import { useScene, WallNode, ItemNode } from '@pascal-app/core'
// Create a wall
const wall = WallNode.parse({
points: [[0, 0], [5, 0]],
height: 3,
thickness: 0.2,
})
useScene.getState().createNode(wall, parentLevelId)
// Subscribe to scene changes
function MyComponent() {
const nodes = useScene((state) => state.nodes)
const walls = Object.values(nodes).filter(n => n.type === 'wall')
return <div>Total walls: {walls.length}</div>
}
Node Types
SiteNode- Root containerBuildingNode- Building within a siteLevelNode- Floor levelWallNode- Vertical wall with optional openingsSlabNode- Floor slabCeilingNode- Ceiling surfaceRoofNode- Roof geometryZoneNode- Spatial zone/roomItemNode- Furniture, fixtures, appliancesScanNode- 3D scan referenceGuideNode- 2D guide image reference
Systems
Systems process dirty nodes each frame to update geometry:
WallSystem- Wall geometry with mitering and CSG cutoutsSlabSystem- Floor polygon generationCeilingSystem- Ceiling geometryRoofSystem- Roof generationItemSystem- Item positioning on walls/ceilings/floors
License
MIT