Add paint hover previews to viewer

This commit is contained in:
sudhir
2026-04-22 10:52:35 +05:30
parent 65399731f7
commit 87dfdf1b38
15 changed files with 638 additions and 156 deletions
+69 -1
View File
@@ -1,6 +1,17 @@
'use client'
import type { AnyNode, BaseNode, BuildingNode, LevelNode, ZoneNode } from '@pascal-app/core'
import type {
AnyNode,
AnyNodeId,
BaseNode,
BuildingNode,
LevelNode,
MaterialSchema,
RoofSurfaceMaterialRole,
StairSurfaceMaterialRole,
WallSurfaceSide,
ZoneNode,
} from '@pascal-app/core'
import type { Object3D } from 'three'
import { create } from 'zustand'
@@ -18,10 +29,57 @@ type Outliner = {
hoveredObjects: Object3D[]
}
type MaterialPreview =
| {
nodeId: AnyNodeId
target: 'wall'
role: WallSurfaceSide
material?: MaterialSchema
materialPreset?: string
}
| {
nodeId: AnyNodeId
target: 'roof'
role: RoofSurfaceMaterialRole
material?: MaterialSchema
materialPreset?: string
}
| {
nodeId: AnyNodeId
target: 'stair'
role: StairSurfaceMaterialRole
material?: MaterialSchema
materialPreset?: string
}
| {
nodeId: AnyNodeId
target: 'fence' | 'slab' | 'ceiling'
role: 'surface'
material?: MaterialSchema
materialPreset?: string
}
| null
function isSameMaterialPreview(left: MaterialPreview, right: MaterialPreview) {
if (left === right) return true
if (!left || !right) return false
return (
left.nodeId === right.nodeId &&
left.target === right.target &&
left.role === right.role &&
left.material === right.material &&
left.materialPreset === right.materialPreset
)
}
type ViewerState = {
selection: SelectionPath
previewSelectedIds: BaseNode['id'][]
setPreviewSelectedIds: (ids: BaseNode['id'][]) => void
materialPreview: MaterialPreview
setMaterialPreview: (preview: MaterialPreview) => void
clearMaterialPreview: () => void
hoverHighlightMode: 'default' | 'delete' | 'paint-ready' | 'paint-disabled'
setHoverHighlightMode: (mode: 'default' | 'delete' | 'paint-ready' | 'paint-disabled') => void
hoveredId: AnyNode['id'] | ZoneNode['id'] | null
@@ -84,6 +142,15 @@ const useViewer = create<ViewerState>()(
selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [] },
previewSelectedIds: [],
setPreviewSelectedIds: (ids) => set({ previewSelectedIds: ids }),
materialPreview: null,
setMaterialPreview: (materialPreview) =>
set((state) =>
isSameMaterialPreview(state.materialPreview, materialPreview)
? state
: { materialPreview },
),
clearMaterialPreview: () =>
set((state) => (state.materialPreview === null ? state : { materialPreview: null })),
hoverHighlightMode: 'default',
setHoverHighlightMode: (mode) =>
set((state) => (state.hoverHighlightMode === mode ? state : { hoverHighlightMode: mode })),
@@ -188,6 +255,7 @@ const useViewer = create<ViewerState>()(
selectedIds: [],
},
previewSelectedIds: [],
materialPreview: null,
}),
outliner: { selectedObjects: [], hoveredObjects: [] },