feat(paint-slots): unified slot defaults + paint for slab, ceiling, wall (phase 5)
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>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
b0f4e1b8ee
commit
967a905e3b
@@ -2,7 +2,9 @@ import {
|
||||
getEffectiveWallSurfaceMaterial,
|
||||
getMaterialPresetByRef,
|
||||
getWallSurfaceMaterialSignature,
|
||||
parseMaterialRef,
|
||||
resolveMaterial,
|
||||
WALL_SLOT_DEFAULT,
|
||||
type WallNode,
|
||||
type WallSurfaceMaterialSpec,
|
||||
} from '@pascal-app/core'
|
||||
@@ -12,6 +14,7 @@ import { MeshLambertNodeMaterial, MeshStandardNodeMaterial } from 'three/webgpu'
|
||||
import {
|
||||
baseMaterial,
|
||||
type ColorPreset,
|
||||
createDefaultMaterial,
|
||||
createMaterial,
|
||||
createMaterialFromPresetRef,
|
||||
createSurfaceRoleMaterial,
|
||||
@@ -88,6 +91,15 @@ function hasExplicitMaterial(spec: WallSurfaceMaterialSpec): boolean {
|
||||
return Boolean(spec.materialPreset || spec.material)
|
||||
}
|
||||
|
||||
// Resolve a wall face's declared default — a catalog `library:` finish or a
|
||||
// flat colour — to a renderable material.
|
||||
function resolveWallSlotDefault(slotDefault: string, shading: RenderShading): Material {
|
||||
if (parseMaterialRef(slotDefault)?.kind === 'library') {
|
||||
return createMaterialFromPresetRef(slotDefault, shading) ?? baseMaterial(shading)
|
||||
}
|
||||
return createDefaultMaterial(slotDefault, 0.9, shading)
|
||||
}
|
||||
|
||||
function getSurfaceColor(spec: WallSurfaceMaterialSpec, fallback = DEFAULT_WALL_COLOR): string {
|
||||
const preset = getMaterialPresetByRef(spec.materialPreset)
|
||||
if (preset?.mapProperties?.color) {
|
||||
@@ -216,17 +228,19 @@ export function getMaterialsForWall(
|
||||
const exteriorSpec = getEffectiveWallSurfaceMaterial(wallNode, 'exterior')
|
||||
const wallRoleMaterial = createSurfaceRoleMaterial('wall', colorPreset, undefined, sceneTheme)
|
||||
|
||||
// Untextured surfaces take the themed wall role colour even with textures on;
|
||||
// only surfaces with an explicit preset/material keep their texture.
|
||||
// Colored mode: an unpainted face takes its declared slot default (parity
|
||||
// with the retired DEFAULT_WALL_MATERIAL); only an explicit preset/material
|
||||
// keeps a texture. Textures-off collapses every face to the themed wall role
|
||||
// (the guaranteed escape hatch). The edge/cap slot (index 0) stays role-based.
|
||||
const visible: WallMaterialArray = textures
|
||||
? [
|
||||
wallRoleMaterial,
|
||||
hasExplicitMaterial(interiorSpec)
|
||||
? getSurfaceVisibleMaterial(interiorSpec, shading)
|
||||
: wallRoleMaterial,
|
||||
: resolveWallSlotDefault(WALL_SLOT_DEFAULT.interior, shading),
|
||||
hasExplicitMaterial(exteriorSpec)
|
||||
? getSurfaceVisibleMaterial(exteriorSpec, shading)
|
||||
: wallRoleMaterial,
|
||||
: resolveWallSlotDefault(WALL_SLOT_DEFAULT.exterior, shading),
|
||||
]
|
||||
: [wallRoleMaterial, wallRoleMaterial, wallRoleMaterial]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user