Add two-sided wall material targeting

This commit is contained in:
sudhir
2026-04-20 11:18:20 +05:30
parent 783b2e0c33
commit 71ddb7052b
14 changed files with 824 additions and 292 deletions
+14 -9
View File
@@ -4,6 +4,13 @@ export { BaseNode, generateId, Material, nodeType, objectId } from './base'
export { CameraSchema } from './camera'
// Collections
export { type Collection, type CollectionId, generateCollectionId } from './collections'
export type {
MaterialMapProperties,
MaterialMaps,
MaterialPresetPayload,
MaterialTarget as MaterialTargetValue,
TextureWrapMode as TextureWrapModeValue,
} from './material'
// Material
export {
DEFAULT_MATERIALS,
@@ -14,15 +21,8 @@ export {
MaterialProperties,
MaterialSchema,
MaterialTarget,
TextureWrapMode,
resolveMaterial,
} from './material'
export type {
MaterialMapProperties,
MaterialMaps,
MaterialPresetPayload,
MaterialTarget as MaterialTargetValue,
TextureWrapMode as TextureWrapModeValue,
TextureWrapMode,
} from './material'
export { BuildingNode } from './nodes/building'
export { CeilingNode } from './nodes/ceiling'
@@ -58,7 +58,12 @@ export {
} from './nodes/stair'
export { AttachmentSide, StairSegmentNode, StairSegmentType } from './nodes/stair-segment'
export { SurfaceHoleMetadata } from './nodes/surface-hole-metadata'
export { WallNode } from './nodes/wall'
export type { WallSurfaceMaterialSpec, WallSurfaceSide } from './nodes/wall'
export {
getEffectiveWallSurfaceMaterial,
getWallSurfaceMaterialSignature,
WallNode,
} from './nodes/wall'
export { WindowNode } from './nodes/window'
export { ZoneNode } from './nodes/zone'
export type { AnyNodeId, AnyNodeType } from './types'
+65
View File
@@ -12,8 +12,14 @@ export const WallNode = BaseNode.extend({
children: z
.array(z.union([ItemNode.shape.id, DoorNode.shape.id, WindowNode.shape.id]))
.default([]),
// Legacy single-material wall finish. Read for backward compatibility only.
material: MaterialSchema.optional(),
// Legacy single-material wall finish preset. Read for backward compatibility only.
materialPreset: z.string().optional(),
interiorMaterial: MaterialSchema.optional(),
interiorMaterialPreset: z.string().optional(),
exteriorMaterial: MaterialSchema.optional(),
exteriorMaterialPreset: z.string().optional(),
thickness: z.number().optional(),
height: z.number().optional(),
curveOffset: z.number().optional(),
@@ -37,3 +43,62 @@ export const WallNode = BaseNode.extend({
`,
)
export type WallNode = z.infer<typeof WallNode>
export type WallSurfaceSide = 'interior' | 'exterior'
export type WallSurfaceMaterialSpec = {
material?: z.infer<typeof MaterialSchema>
materialPreset?: string
}
type WallSurfaceMaterialSource = {
material?: z.infer<typeof MaterialSchema>
materialPreset?: string
interiorMaterial?: z.infer<typeof MaterialSchema>
interiorMaterialPreset?: string
exteriorMaterial?: z.infer<typeof MaterialSchema>
exteriorMaterialPreset?: string
}
function getConfiguredWallSurfaceMaterial(
wall: WallSurfaceMaterialSource,
side: WallSurfaceSide,
): WallSurfaceMaterialSpec {
if (side === 'interior') {
return {
material: wall.interiorMaterial,
materialPreset: wall.interiorMaterialPreset,
}
}
return {
material: wall.exteriorMaterial,
materialPreset: wall.exteriorMaterialPreset,
}
}
function hasSurfaceMaterial(spec: WallSurfaceMaterialSpec): boolean {
return spec.material !== undefined || typeof spec.materialPreset === 'string'
}
export function getEffectiveWallSurfaceMaterial(
wall: WallSurfaceMaterialSource,
side: WallSurfaceSide,
): WallSurfaceMaterialSpec {
const configured = getConfiguredWallSurfaceMaterial(wall, side)
if (hasSurfaceMaterial(configured)) {
return configured
}
return {
material: wall.material,
materialPreset: wall.materialPreset,
}
}
export function getWallSurfaceMaterialSignature(spec: WallSurfaceMaterialSpec): string {
return JSON.stringify({
material: spec.material ?? null,
materialPreset: spec.materialPreset ?? null,
})
}