Files
editor/packages/core
ed6ed3f018 fix(editor): release scene singletons on Editor unmount (#214)
The spatial-grid manager, scene-store subscriptions, and the viewer
outliner's Object3D arrays are module-level singletons that previously
lived for the whole page lifetime. When an app unmounted the Editor
(e.g. navigating away from the 3D editor and back in an SPA host) they
retained references to the disposed Three.js scene graph, which caused
the app to freeze on re-entry as the stale data was replayed against a
fresh scene.

- initSpatialGridSync now returns the unsubscribe handle from its
  scene-store subscription so callers can detach it.
- initializeEditorRuntime becomes reversible: it wires up the spatial
  grid, space detection and SFX bus on mount and returns a teardown
  closure that detaches both store subscriptions, clears the spatial
  grid manager, and truncates the viewer outliner's selected/hovered
  arrays in place.
- The Editor component's runtime-init effect now returns that teardown,
  so the singletons are reset cleanly every time the Editor unmounts.
- initSFXBus is now idempotent via an internal guard so repeated
  Editor mounts do not stack duplicate mitt listeners.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-05 23:37:30 -04:00
..
2026-02-05 08:22:19 +09:00
2026-03-13 09:07:46 +01:00

@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 container
  • BuildingNode - Building within a site
  • LevelNode - Floor level
  • WallNode - Vertical wall with optional openings
  • SlabNode - Floor slab
  • CeilingNode - Ceiling surface
  • RoofNode - Roof geometry
  • ZoneNode - Spatial zone/room
  • ItemNode - Furniture, fixtures, appliances
  • ScanNode - 3D scan reference
  • GuideNode - 2D guide image reference

Systems

Systems process dirty nodes each frame to update geometry:

  • WallSystem - Wall geometry with mitering and CSG cutouts
  • SlabSystem - Floor polygon generation
  • CeilingSystem - Ceiling geometry
  • RoofSystem - Roof generation
  • ItemSystem - Item positioning on walls/ceilings/floors

License

MIT