feat(paint-slots): concrete-plate finish + try defaults (wall=concrete, slab=wood plank 48, ceiling=soft white)

- material-library: add 'concrete-plate' KTX2 finish (512, fabric/leather-style
  pipeline) + editor-app texture mirror.
- viewer: shared resolveSlotDefaultMaterial(colour|library ref) so a kind's slot
  default can be a catalog finish, not just a flat colour.
- wall default -> library:concrete-plate (interior + exterior).
- slab default -> library:wood-woodplank48 (slab geometry resolves it via the
  shared helper).
- ceiling default -> soft white #f2eee6 (ceiling renders flat-tinted).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Wassim SAMAD
2026-06-17 08:25:48 -04:00
co-authored by Claude Opus 4.8
parent 967a905e3b
commit 737c4e9d1d
12 changed files with 74 additions and 11 deletions
+3 -2
View File
@@ -2,8 +2,9 @@ import type { SlotDeclaration } from '@pascal-app/core'
export type CeilingSlotId = 'surface'
// Visual parity with the retired DEFAULT_CEILING_MATERIAL (warm beige).
export const CEILING_SLOT_DEFAULT_COLOR = '#f5f5dc'
// Soft white — the default underside colour for an unpainted ceiling. (A
// ceiling renders flat-tinted, so this is a colour, not a `library:` finish.)
export const CEILING_SLOT_DEFAULT_COLOR = '#f2eee6'
/** A ceiling exposes a single paintable underside surface. */
export function ceilingSlots(): SlotDeclaration[] {
+5 -4
View File
@@ -8,9 +8,10 @@ import {
generateSlabGeometry,
type RenderShading,
resolveMaterialRef,
resolveSlotDefaultMaterial,
} from '@pascal-app/viewer'
import { FrontSide, Group, type Material, Mesh, type Texture } from 'three'
import { SLAB_SLOT_DEFAULT_COLOR } from './slots'
import { SLAB_SLOT_DEFAULT } from './slots'
/**
* Stage B builder for slab. Reuses `generateSlabGeometry` (pure
@@ -62,8 +63,8 @@ function getSlabMaterial(
return getLegacySlabMaterial(node, shading)
}
// Declared slot default (visual parity with the retired DEFAULT_SLAB_MATERIAL).
return createDefaultMaterial(SLAB_SLOT_DEFAULT_COLOR, 0.8, shading)
// Declared slot default — a catalog `library:` finish or a flat colour.
return resolveSlotDefaultMaterial(SLAB_SLOT_DEFAULT, shading, 0.8)
}
function getLegacySlabMaterial(node: SlabNode, shading: RenderShading): Material {
@@ -83,7 +84,7 @@ function getLegacySlabMaterial(node: SlabNode, shading: RenderShading): Material
? createDefaultMaterial('#ffffff', 0.5, shading)
: node.material
? createMaterial(node.material, shading).clone()
: createDefaultMaterial(SLAB_SLOT_DEFAULT_COLOR, 0.8, shading)
: createDefaultMaterial('#e5e5e5', 0.8, shading)
if (preset) {
applyMaterialPresetToMaterials(material, preset)
+5 -3
View File
@@ -2,10 +2,12 @@ import type { SlotDeclaration } from '@pascal-app/core'
export type SlabSlotId = 'surface'
// Visual parity with the retired DEFAULT_SLAB_MATERIAL (light grey).
export const SLAB_SLOT_DEFAULT_COLOR = '#e5e5e5'
// Declared default appearance for an unpainted slab surface in colored mode —
// a catalog `library:<id>` finish or a `#rrggbb` colour. Textures-off collapses
// to the themed floor role (the escape hatch).
export const SLAB_SLOT_DEFAULT = 'library:wood-woodplank48'
/** A slab exposes a single paintable floor surface. */
export function slabSlots(): SlotDeclaration[] {
return [{ slotId: 'surface', label: 'Surface', default: SLAB_SLOT_DEFAULT_COLOR }]
return [{ slotId: 'surface', label: 'Surface', default: SLAB_SLOT_DEFAULT }]
}