Brings slab, ceiling, and wall onto the unified slot contract the shelf established, so each declares its paintable slots with a declarative default and (slab/ceiling) is painted through the registry capabilities.paint dispatch. - Shared helper packages/nodes/src/shared/slot-paint.ts: a node.slots-based PaintCapability factory (commit/resolve/effective generic; preview injected). Distinct from surface-paint.ts, which writes the legacy inline node.material. - slab: schema slots; def.geometry resolves node.slots.surface -> legacy material -> declared default, tags the mesh userData.slotId; slabPaint + capabilities.slots. Retires DEFAULT_SLAB_MATERIAL in the slab path. - ceiling: schema slots; material builders extracted to ceiling/materials.ts (shared by renderer + paint preview, built BackSide so the hover preview is visible from below); renderer resolves the slot; ceilingPaint + slots. - wall: WALL_SLOT_DEFAULT in core; the viewer's getMaterialsForWall renders an unpainted face with its declared default instead of the themed wall role; capabilities.slots (interior/exterior). wallPaint's inline interior/exterior fields are unchanged (node.slots migration is a later step). - selection-manager + material-paint: drop slab/ceiling from the legacy single-surface arms (now registry-driven). Behavior change (intended, matches the shelf precedent + the phase-5 plan): colored-mode UNPAINTED slab/ceiling/wall surfaces now render their fixed slot default (#e5e5e5 / #f5f5dc / #ffffff) instead of the theme role colour. The textures-off (monochrome) role collapse is unchanged — the escape hatch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
20 lines
727 B
TypeScript
20 lines
727 B
TypeScript
import type { AnyNode, SlabNode } from '@pascal-app/core'
|
|
import { createSlotPaintCapability, previewGeometrySlot } from '../shared/slot-paint'
|
|
|
|
/**
|
|
* Slab paint on the unified slot model. A slab has one paintable surface, so
|
|
* every face resolves to the `surface` slot; commit writes `node.slots.surface`
|
|
* (a shared scene-material or `library:` ref) like the shelf.
|
|
*/
|
|
export const slabPaint = createSlotPaintCapability({
|
|
resolveRole: () => 'surface',
|
|
applyPreview: previewGeometrySlot,
|
|
legacyEffective: (node: AnyNode) => {
|
|
const slab = node as SlabNode
|
|
if (slab.materialPreset || slab.material) {
|
|
return { material: slab.material, materialPreset: slab.materialPreset }
|
|
}
|
|
return null
|
|
},
|
|
})
|