Wassim SAMAD 0cdaf8b1b9 feat(paint-slots): migrate column onto the unified slot model
Column exposes shaft / base / capital / frame slots on node.slots (base when
baseStyle!=none, capital when capitalStyle!=none, frame only for non-vertical
support styles). The single material context is widened to a per-slot map plus
a ColumnSlotContext; each part subtree is wrapped in <ColumnSlot> so every
mesh primitive resolves its material AND stamps userData.slotId from the same
context. Decorative shaft parts inherit shaft, base/capital carvings inherit
their parent slot. Resolution: textures-off wall role -> node.slots ref ->
legacy material/preset -> declared default (shaft/base/capital concrete-plaster,
frame metal-steel). Monochrome unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 15:34:39 -04:00

30 lines
996 B
TypeScript

import type { SlotDeclaration } from '@pascal-app/core'
import type { ColumnNode } from './schema'
export type ColumnSlotId = 'shaft' | 'base' | 'capital' | 'frame'
export const COLUMN_SHAFT_DEFAULT = 'library:concrete-plaster'
export const COLUMN_BASE_DEFAULT = 'library:concrete-plaster'
export const COLUMN_CAPITAL_DEFAULT = 'library:concrete-plaster'
export const COLUMN_FRAME_DEFAULT = 'library:metal-steel'
export function columnSlots(node: ColumnNode): SlotDeclaration[] {
const slots: SlotDeclaration[] = [
{ slotId: 'shaft', label: 'Shaft', default: COLUMN_SHAFT_DEFAULT },
]
if (node.baseStyle !== 'none') {
slots.push({ slotId: 'base', label: 'Base', default: COLUMN_BASE_DEFAULT })
}
if (node.capitalStyle !== 'none') {
slots.push({ slotId: 'capital', label: 'Capital', default: COLUMN_CAPITAL_DEFAULT })
}
if (node.supportStyle !== 'vertical') {
slots.push({ slotId: 'frame', label: 'Frame', default: COLUMN_FRAME_DEFAULT })
}
return slots
}