shelf: v2 — cubby default, withBottom, item hosting, paintable surface
Schema v2 adds style/rows/columns/withBack/withSides/withBottom/bracketStyle and a `children: ItemNode[]` field for item hosting. Schema-level defaults preserve the v1 wall-shelf visual so existing scenes load unchanged; the placement tool spreads `shelfDefinition.defaults()` for fresh shelves (cubby 3x2 at 1m × 0.5m × 1.8m, thickness 0.05m, back/sides/bottom on). Four style geometries (wall-shelf / bookshelf / open-rack / cubby) share the dimensional schema. `shelfRowSurfaceYs` exposes one host surface per row, plus the bottom-board top when `withBottom` is on for cubby / bookshelf. Material is a single paintable surface (same shape walls / slabs / stairs use); `DEFAULT_SHELF_MATERIAL` aligned with `DEFAULT_WALL_MATERIAL` so unpainted shelves read as the canonical off-white. Preview clones each cached material before mutating `transparent / opacity` on the ghost — without the clone the mutation leaked into the cached `getShelfMaterial` instance every committed shelf was using, rendering them all see-through after the first placement preview rendered. Store hardening: `migrateNodes` patches missing `children: []` on v1 shelves, and `updateNodesAction` reparenting tolerates a missing children array on the new parent. `MaterialTarget` enum adds `'shelf'` so paint mode picks up the kind. 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
56e022a093
commit
924567293a
@@ -2,12 +2,71 @@ import type { ParametricDescriptor } from '@pascal-app/core'
|
||||
import type { ShelfNode } from './schema'
|
||||
|
||||
/**
|
||||
* Inspector descriptor for the parametric shelf. Drives both the auto-derived
|
||||
* inspector UI (Phase 4) and the AI/MCP `create_shelf` / `update_shelf` tools
|
||||
* with bounded JSON-schema parameters (also Phase 4).
|
||||
* Inspector descriptor for the parametric shelf. Drives both the
|
||||
* auto-derived inspector UI and the AI/MCP `create_shelf` /
|
||||
* `update_shelf` tools with bounded JSON-schema parameters.
|
||||
*
|
||||
* Fields are grouped by intent: Style first (what kind of shelf), then
|
||||
* Topology (rows / columns / back / sides / bottom + wall-shelf bracket
|
||||
* style), then Dimensions. Surface material is paint-tray driven (same
|
||||
* flow as walls / slabs / stairs) and intentionally not surfaced here.
|
||||
*/
|
||||
export const shelfParametrics: ParametricDescriptor<ShelfNode> = {
|
||||
groups: [
|
||||
{
|
||||
label: 'Style',
|
||||
fields: [
|
||||
{
|
||||
key: 'style',
|
||||
kind: 'enum',
|
||||
options: ['wall-shelf', 'bookshelf', 'open-rack', 'cubby'],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Topology',
|
||||
fields: [
|
||||
{ key: 'rows', kind: 'number', min: 1, max: 8, step: 1 },
|
||||
// Columns only meaningful for kinds with vertical dividers.
|
||||
{
|
||||
key: 'columns',
|
||||
kind: 'number',
|
||||
min: 1,
|
||||
max: 6,
|
||||
step: 1,
|
||||
visibleIf: (n) => n.style === 'bookshelf' || n.style === 'cubby',
|
||||
},
|
||||
// Sides toggle only applies to bookshelf (cubby always on, the
|
||||
// others use their own post structure).
|
||||
{
|
||||
key: 'withSides',
|
||||
kind: 'boolean',
|
||||
visibleIf: (n) => n.style === 'bookshelf',
|
||||
},
|
||||
// Back toggle only applies to bookshelf and open-rack (cubby
|
||||
// always has a back, wall-shelf has no back).
|
||||
{
|
||||
key: 'withBack',
|
||||
kind: 'boolean',
|
||||
visibleIf: (n) => n.style === 'bookshelf' || n.style === 'open-rack',
|
||||
},
|
||||
// Bottom toggle only applies to bookshelf and cubby — closes
|
||||
// the lowest cell with a floor board so items can host there.
|
||||
{
|
||||
key: 'withBottom',
|
||||
kind: 'boolean',
|
||||
visibleIf: (n) => n.style === 'bookshelf' || n.style === 'cubby',
|
||||
},
|
||||
// Bracket style only matters for wall-shelf — the other styles
|
||||
// structure themselves through sides / posts / dividers.
|
||||
{
|
||||
key: 'bracketStyle',
|
||||
kind: 'enum',
|
||||
options: ['minimal', 'industrial', 'hidden'],
|
||||
visibleIf: (n) => n.style === 'wall-shelf',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Dimensions',
|
||||
fields: [
|
||||
@@ -17,12 +76,5 @@ export const shelfParametrics: ParametricDescriptor<ShelfNode> = {
|
||||
{ key: 'height', kind: 'number', unit: 'm', min: 0.05, max: 2.5, step: 0.05 },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Style',
|
||||
fields: [
|
||||
{ key: 'bracketStyle', kind: 'enum', options: ['minimal', 'industrial', 'hidden'] },
|
||||
{ key: 'color', kind: 'color' },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user