Same shape as fence — thin renderer + system re-export, capabilities declared, panel slider-drag fix recipe applied. Pure geometry + floor-plan ports are later milestones. Files added (packages/nodes/src/slab/): - schema.ts: re-exports SlabNode from core. - parametrics.ts: elevation slider only. Polygon + holes edited via floor-plan boundary / hole editors, not number inputs. - definition.ts: capabilities (no `movable` — slab move is bespoke whole-translation through MoveSlabTool that integrates with the boundary editor; capability-driven dispatch keeps the legacy mover), surfaces.top with elevation-as-height for stacked items, relations (hosts: ['item'], cascadeDelete: 'descendants'), toolHints (trace / finish / cancel for the placement tool). - renderer.tsx: thin placeholder mesh + markDirty on mount + node events + cached material via the same getSlabMaterial pattern as the legacy renderer (preset apply on shared material instance). - system.tsx: re-exports the legacy SlabSystem from viewer. - index.ts: barrel. Files changed: - packages/viewer/src/index.ts: exports SlabSystem (already had DEFAULT_SLAB_MATERIAL, applyMaterialPresetToMaterials, createMaterial from earlier exports). - packages/nodes/src/index.ts: appends slabDefinition unconditionally to builtinPlugin.nodes. - packages/editor/src/components/ui/panels/slab-panel.tsx: applied the panel slider-drag fix recipe from plans/editor-node-registry.md prophylactically (nodeRef pattern, useScene.getState().updateNode inside handler, drop subscribed updateNode dep). Slab's elevation slider is the only drag-driven control in the panel — would have triggered the same Maximum update depth cascade as wall/fence. No behavior change. Slab now mounts via the registry path, but the legacy SlabSystem still does the actual polygon triangulation + hole CSG work (re-exported, not duplicated). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
43 lines
1.7 KiB
TypeScript
43 lines
1.7 KiB
TypeScript
import type { AnyNodeDefinition, Plugin } from '@pascal-app/core'
|
|
import { fenceDefinition } from './fence'
|
|
import { shelfDefinition } from './shelf'
|
|
import { slabDefinition } from './slab'
|
|
import { spawnDefinition } from './spawn'
|
|
import { wallDefinition } from './wall'
|
|
|
|
/**
|
|
* Built-in plugin bundling every node kind shipped with the Pascal editor.
|
|
*
|
|
* Apps load this once at bootstrap (`loadPlugin(builtinPlugin)`) before
|
|
* mounting the viewer. New built-in nodes are added by creating a folder
|
|
* here under `src/<kind>/` and appending its `NodeDefinition` below.
|
|
*
|
|
* External plugins follow the exact same shape — same `Plugin` type, same
|
|
* `loadPlugin` call path. This is intentional: the API is stress-tested
|
|
* by built-ins before any third-party plugin lands.
|
|
*
|
|
* All four current kinds are registered unconditionally. Parity is
|
|
* verified by comparing against deployed production rather than an
|
|
* in-app env-var flag toggle. Legacy paths still exist in `viewer/` and
|
|
* `editor/` for kinds undergoing migration; they short-circuit via the
|
|
* Phase 0 `<LegacySystem>` wrapper + `NodeRenderer`'s registry-first
|
|
* dispatch. Phase 6 deletes the legacy paths.
|
|
*/
|
|
export const builtinPlugin: Plugin = {
|
|
id: 'pascal:core',
|
|
apiVersion: 1,
|
|
nodes: [
|
|
shelfDefinition as unknown as AnyNodeDefinition,
|
|
spawnDefinition as unknown as AnyNodeDefinition,
|
|
wallDefinition as unknown as AnyNodeDefinition,
|
|
fenceDefinition as unknown as AnyNodeDefinition,
|
|
slabDefinition as unknown as AnyNodeDefinition,
|
|
],
|
|
}
|
|
|
|
export { fenceDefinition } from './fence'
|
|
export { shelfDefinition } from './shelf'
|
|
export { slabDefinition } from './slab'
|
|
export { spawnDefinition } from './spawn'
|
|
export { wallDefinition } from './wall'
|