@pascal-app/viewer 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/renderers/item/item-renderer.d.ts.map +1 -1
- package/dist/components/renderers/item/item-renderer.js +14 -19
- package/dist/components/renderers/node-renderer.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.js +3 -1
- package/dist/components/renderers/site/site-renderer.d.ts.map +1 -1
- package/dist/components/renderers/site/site-renderer.js +59 -15
- package/dist/components/renderers/slab/slab-renderer.js +1 -1
- package/dist/components/renderers/stair/stair-renderer.d.ts +5 -0
- package/dist/components/renderers/stair/stair-renderer.d.ts.map +1 -0
- package/dist/components/renderers/stair/stair-renderer.js +21 -0
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts +5 -0
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +1 -0
- package/dist/components/renderers/stair-segment/stair-segment-renderer.js +20 -0
- package/dist/components/renderers/wall/wall-renderer.js +1 -1
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +2 -3
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +33 -45
- package/dist/components/viewer/walkthrough-controls.d.ts +2 -0
- package/dist/components/viewer/walkthrough-controls.d.ts.map +1 -0
- package/dist/components/viewer/walkthrough-controls.js +131 -0
- package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
- package/dist/hooks/use-node-events.d.ts +9 -1
- package/dist/hooks/use-node-events.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/lib/materials.d.ts +1 -0
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +1 -0
- package/dist/lib/merged-outline-node.d.ts +88 -0
- package/dist/lib/merged-outline-node.d.ts.map +1 -0
- package/dist/lib/merged-outline-node.js +450 -0
- package/dist/lib/suppress-three-clock-warning.d.ts +25 -0
- package/dist/lib/suppress-three-clock-warning.d.ts.map +1 -0
- package/dist/lib/suppress-three-clock-warning.js +51 -0
- package/dist/store/use-viewer.d.ts +6 -0
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +8 -1
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout.js +110 -61
- package/package.json +1 -1
|
@@ -12,6 +12,10 @@ type Outliner = {
|
|
|
12
12
|
};
|
|
13
13
|
type ViewerState = {
|
|
14
14
|
selection: SelectionPath;
|
|
15
|
+
previewSelectedIds: BaseNode['id'][];
|
|
16
|
+
setPreviewSelectedIds: (ids: BaseNode['id'][]) => void;
|
|
17
|
+
hoverHighlightMode: 'default' | 'delete';
|
|
18
|
+
setHoverHighlightMode: (mode: 'default' | 'delete') => void;
|
|
15
19
|
hoveredId: AnyNode['id'] | ZoneNode['id'] | null;
|
|
16
20
|
setHoveredId: (id: AnyNode['id'] | ZoneNode['id'] | null) => void;
|
|
17
21
|
cameraMode: 'perspective' | 'orthographic';
|
|
@@ -44,6 +48,8 @@ type ViewerState = {
|
|
|
44
48
|
setExportScene: (fn: ((format?: 'glb' | 'stl' | 'obj') => Promise<void>) | null) => void;
|
|
45
49
|
debugColors: boolean;
|
|
46
50
|
setDebugColors: (enabled: boolean) => void;
|
|
51
|
+
walkthroughMode: boolean;
|
|
52
|
+
setWalkthroughMode: (mode: boolean) => void;
|
|
47
53
|
cameraDragging: boolean;
|
|
48
54
|
setCameraDragging: (dragging: boolean) => void;
|
|
49
55
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"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"}
|
package/dist/store/use-viewer.js
CHANGED
|
@@ -3,6 +3,10 @@ import { create } from 'zustand';
|
|
|
3
3
|
import { persist } from 'zustand/middleware';
|
|
4
4
|
const useViewer = create()(persist((set) => ({
|
|
5
5
|
selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [] },
|
|
6
|
+
previewSelectedIds: [],
|
|
7
|
+
setPreviewSelectedIds: (ids) => set({ previewSelectedIds: ids }),
|
|
8
|
+
hoverHighlightMode: 'default',
|
|
9
|
+
setHoverHighlightMode: (mode) => set({ hoverHighlightMode: mode }),
|
|
6
10
|
hoveredId: null,
|
|
7
11
|
setHoveredId: (id) => set({ hoveredId: id }),
|
|
8
12
|
cameraMode: 'perspective',
|
|
@@ -82,7 +86,7 @@ const useViewer = create()(persist((set) => ({
|
|
|
82
86
|
if (updates.selectedIds === undefined)
|
|
83
87
|
newSelection.selectedIds = [];
|
|
84
88
|
}
|
|
85
|
-
return { selection: newSelection };
|
|
89
|
+
return { selection: newSelection, previewSelectedIds: [] };
|
|
86
90
|
}),
|
|
87
91
|
resetSelection: () => set({
|
|
88
92
|
selection: {
|
|
@@ -91,12 +95,15 @@ const useViewer = create()(persist((set) => ({
|
|
|
91
95
|
zoneId: null,
|
|
92
96
|
selectedIds: [],
|
|
93
97
|
},
|
|
98
|
+
previewSelectedIds: [],
|
|
94
99
|
}),
|
|
95
100
|
outliner: { selectedObjects: [], hoveredObjects: [] },
|
|
96
101
|
exportScene: null,
|
|
97
102
|
setExportScene: (fn) => set({ exportScene: fn }),
|
|
98
103
|
debugColors: false,
|
|
99
104
|
setDebugColors: (enabled) => set({ debugColors: enabled }),
|
|
105
|
+
walkthroughMode: false,
|
|
106
|
+
setWalkthroughMode: (mode) => set({ walkthroughMode: mode }),
|
|
100
107
|
cameraDragging: false,
|
|
101
108
|
setCameraDragging: (dragging) => set({ cameraDragging: dragging }),
|
|
102
109
|
}), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wall-cutout.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-cutout.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wall-cutout.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-cutout.tsx"],"names":[],"mappings":"AAoMA,eAAO,MAAM,UAAU,YAgFtB,CAAA"}
|
|
@@ -1,12 +1,26 @@
|
|
|
1
|
-
import { sceneRegistry, useScene } from '@pascal-app/core';
|
|
1
|
+
import { baseMaterial, sceneRegistry, useScene, } from '@pascal-app/core';
|
|
2
2
|
import { useFrame } from '@react-three/fiber';
|
|
3
3
|
import { useRef } from 'react';
|
|
4
|
+
import { Color } from 'three';
|
|
4
5
|
import { Fn, float, fract, length, mix, positionLocal, smoothstep, step, vec2 } from 'three/tsl';
|
|
5
6
|
import { MeshStandardNodeMaterial, Vector3 } from 'three/webgpu';
|
|
6
7
|
import useViewer from '../../store/use-viewer';
|
|
7
8
|
const tmpVec = new Vector3();
|
|
8
9
|
const u = new Vector3();
|
|
9
10
|
const v = new Vector3();
|
|
11
|
+
const DEFAULT_WALL_COLOR = '#f2f0ed';
|
|
12
|
+
const WALL_HIGHLIGHT_PROFILES = {
|
|
13
|
+
delete: {
|
|
14
|
+
color: new Color('#dc2626'),
|
|
15
|
+
blend: 0.78,
|
|
16
|
+
emissiveIntensity: 0.46,
|
|
17
|
+
},
|
|
18
|
+
selection: {
|
|
19
|
+
color: new Color('#818cf8'),
|
|
20
|
+
blend: 0.32,
|
|
21
|
+
emissiveIntensity: 0.42,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
10
24
|
const dotPattern = Fn(() => {
|
|
11
25
|
const scale = float(0.1);
|
|
12
26
|
const dotSize = float(0.3);
|
|
@@ -19,6 +33,17 @@ const dotPattern = Fn(() => {
|
|
|
19
33
|
return dots.mul(yFade);
|
|
20
34
|
});
|
|
21
35
|
const wallMaterialCache = new Map();
|
|
36
|
+
const presetColors = {
|
|
37
|
+
white: '#ffffff',
|
|
38
|
+
brick: '#8b4513',
|
|
39
|
+
concrete: '#808080',
|
|
40
|
+
wood: '#deb887',
|
|
41
|
+
glass: '#87ceeb',
|
|
42
|
+
metal: '#c0c0c0',
|
|
43
|
+
plaster: '#f5f5dc',
|
|
44
|
+
tile: '#dcdcdc',
|
|
45
|
+
marble: '#f5f5f5',
|
|
46
|
+
};
|
|
22
47
|
function getMaterialHash(wallNode) {
|
|
23
48
|
if (!wallNode.material)
|
|
24
49
|
return 'none';
|
|
@@ -31,20 +56,22 @@ function getMaterialHash(wallNode) {
|
|
|
31
56
|
}
|
|
32
57
|
return 'default';
|
|
33
58
|
}
|
|
34
|
-
const presetColors = {
|
|
35
|
-
white: '#ffffff',
|
|
36
|
-
brick: '#8b4513',
|
|
37
|
-
concrete: '#808080',
|
|
38
|
-
wood: '#deb887',
|
|
39
|
-
glass: '#87ceeb',
|
|
40
|
-
metal: '#c0c0c0',
|
|
41
|
-
plaster: '#f5f5dc',
|
|
42
|
-
tile: '#dcdcdc',
|
|
43
|
-
marble: '#f5f5f5',
|
|
44
|
-
};
|
|
45
59
|
function getPresetColor(preset) {
|
|
46
60
|
return presetColors[preset] ?? '#ffffff';
|
|
47
61
|
}
|
|
62
|
+
function getHighlightedColor(color, kind) {
|
|
63
|
+
const profile = WALL_HIGHLIGHT_PROFILES[kind];
|
|
64
|
+
return new Color(color).lerp(profile.color, profile.blend);
|
|
65
|
+
}
|
|
66
|
+
function createHighlightedWallMaterial(material, baseColor, kind) {
|
|
67
|
+
const highlightedMaterial = material.clone();
|
|
68
|
+
const highlightedColor = getHighlightedColor(baseColor, kind);
|
|
69
|
+
const profile = WALL_HIGHLIGHT_PROFILES[kind];
|
|
70
|
+
highlightedMaterial.color = highlightedColor;
|
|
71
|
+
highlightedMaterial.emissive = highlightedColor.clone();
|
|
72
|
+
highlightedMaterial.emissiveIntensity = profile.emissiveIntensity;
|
|
73
|
+
return highlightedMaterial;
|
|
74
|
+
}
|
|
48
75
|
function getMaterialsForWall(wallNode) {
|
|
49
76
|
const cacheKey = wallNode.id;
|
|
50
77
|
const materialHash = getMaterialHash(wallNode);
|
|
@@ -55,19 +82,25 @@ function getMaterialsForWall(wallNode) {
|
|
|
55
82
|
if (existing) {
|
|
56
83
|
existing.visible.dispose();
|
|
57
84
|
existing.invisible.dispose();
|
|
85
|
+
existing.deleteVisible.dispose();
|
|
86
|
+
existing.deleteInvisible.dispose();
|
|
87
|
+
existing.highlightedVisible.dispose();
|
|
88
|
+
existing.highlightedInvisible.dispose();
|
|
58
89
|
}
|
|
59
|
-
let userColor =
|
|
90
|
+
let userColor = DEFAULT_WALL_COLOR;
|
|
60
91
|
if (wallNode.material?.properties?.color) {
|
|
61
92
|
userColor = wallNode.material.properties.color;
|
|
62
93
|
}
|
|
63
94
|
else if (wallNode.material?.preset && wallNode.material.preset !== 'custom') {
|
|
64
95
|
userColor = getPresetColor(wallNode.material.preset);
|
|
65
96
|
}
|
|
66
|
-
const visibleMat =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
97
|
+
const visibleMat = wallNode.material
|
|
98
|
+
? new MeshStandardNodeMaterial({
|
|
99
|
+
color: userColor,
|
|
100
|
+
roughness: 1,
|
|
101
|
+
metalness: 0,
|
|
102
|
+
})
|
|
103
|
+
: baseMaterial.clone();
|
|
71
104
|
const invisibleMat = new MeshStandardNodeMaterial({
|
|
72
105
|
transparent: true,
|
|
73
106
|
opacityNode: mix(float(0.0), float(0.24), dotPattern()),
|
|
@@ -75,7 +108,19 @@ function getMaterialsForWall(wallNode) {
|
|
|
75
108
|
depthWrite: false,
|
|
76
109
|
emissive: userColor,
|
|
77
110
|
});
|
|
78
|
-
const
|
|
111
|
+
const highlightedVisible = createHighlightedWallMaterial(visibleMat, userColor, 'selection');
|
|
112
|
+
const highlightedInvisible = createHighlightedWallMaterial(invisibleMat, userColor, 'selection');
|
|
113
|
+
const deleteVisible = createHighlightedWallMaterial(visibleMat, userColor, 'delete');
|
|
114
|
+
const deleteInvisible = createHighlightedWallMaterial(invisibleMat, userColor, 'delete');
|
|
115
|
+
const result = {
|
|
116
|
+
visible: visibleMat,
|
|
117
|
+
invisible: invisibleMat,
|
|
118
|
+
deleteVisible,
|
|
119
|
+
deleteInvisible,
|
|
120
|
+
highlightedVisible,
|
|
121
|
+
highlightedInvisible,
|
|
122
|
+
materialHash,
|
|
123
|
+
};
|
|
79
124
|
wallMaterialCache.set(cacheKey, result);
|
|
80
125
|
return result;
|
|
81
126
|
}
|
|
@@ -106,65 +151,69 @@ export const WallCutout = () => {
|
|
|
106
151
|
const lastUpdateTime = useRef(0);
|
|
107
152
|
const lastWallMode = useRef(useViewer.getState().wallMode);
|
|
108
153
|
const lastNumberOfWalls = useRef(0);
|
|
109
|
-
const
|
|
154
|
+
const lastHighlightKey = useRef('');
|
|
110
155
|
useFrame(({ camera, clock }) => {
|
|
111
156
|
const wallMode = useViewer.getState().wallMode;
|
|
157
|
+
const selectedIds = useViewer.getState().selection.selectedIds;
|
|
158
|
+
const previewSelectedIds = useViewer.getState().previewSelectedIds;
|
|
159
|
+
const hoveredId = useViewer.getState().hoveredId;
|
|
160
|
+
const hoverHighlightMode = useViewer.getState().hoverHighlightMode;
|
|
112
161
|
const currentTime = clock.elapsedTime;
|
|
113
162
|
const currentCameraPosition = camera.position;
|
|
114
163
|
camera.getWorldDirection(tmpVec);
|
|
115
164
|
tmpVec.add(currentCameraPosition);
|
|
165
|
+
const highlightedWallIds = new Set([...selectedIds, ...previewSelectedIds].filter((id) => useScene.getState().nodes[id]?.type === 'wall'));
|
|
166
|
+
const deleteHoveredWallId = hoverHighlightMode === 'delete' &&
|
|
167
|
+
hoveredId &&
|
|
168
|
+
useScene.getState().nodes[hoveredId]?.type === 'wall'
|
|
169
|
+
? hoveredId
|
|
170
|
+
: null;
|
|
171
|
+
const highlightKey = `${Array.from(highlightedWallIds).sort().join('|')}::${deleteHoveredWallId ?? ''}`;
|
|
116
172
|
const distanceMoved = currentCameraPosition.distanceTo(lastCameraPosition.current);
|
|
117
173
|
const directionChanged = tmpVec.distanceTo(lastCameraTarget.current);
|
|
118
174
|
const timeSinceUpdate = currentTime - lastUpdateTime.current;
|
|
119
|
-
|
|
175
|
+
if (((distanceMoved > 0.5 || directionChanged > 0.3) && timeSinceUpdate > 0.1) ||
|
|
120
176
|
lastWallMode.current !== wallMode ||
|
|
121
|
-
sceneRegistry.byType.wall.size !== lastNumberOfWalls.current
|
|
122
|
-
|
|
123
|
-
const currentWallIds = new Set();
|
|
124
|
-
walls.forEach((wallId) => {
|
|
125
|
-
const wallMesh = sceneRegistry.nodes.get(wallId);
|
|
126
|
-
if (!wallMesh)
|
|
127
|
-
return;
|
|
128
|
-
const wallNode = useScene.getState().nodes[wallId];
|
|
129
|
-
if (!wallNode || wallNode.type !== 'wall')
|
|
130
|
-
return;
|
|
131
|
-
currentWallIds.add(wallId);
|
|
132
|
-
const hideWall = getWallHideState(wallNode, wallMesh, wallMode, u);
|
|
133
|
-
if (shouldUpdate) {
|
|
134
|
-
const materials = getMaterialsForWall(wallNode);
|
|
135
|
-
wallMesh.material = hideWall ? materials.invisible : materials.visible;
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
const currentMaterial = wallMesh.material;
|
|
139
|
-
const materials = wallMaterialCache.get(wallId);
|
|
140
|
-
if (!materials ||
|
|
141
|
-
currentMaterial !== (hideWall ? materials.invisible : materials.visible)) {
|
|
142
|
-
const newMaterials = getMaterialsForWall(wallNode);
|
|
143
|
-
wallMesh.material = hideWall ? newMaterials.invisible : newMaterials.visible;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
if (shouldUpdate) {
|
|
177
|
+
sceneRegistry.byType.wall.size !== lastNumberOfWalls.current ||
|
|
178
|
+
lastHighlightKey.current !== highlightKey) {
|
|
148
179
|
lastCameraPosition.current.copy(currentCameraPosition);
|
|
149
180
|
lastCameraTarget.current.copy(tmpVec);
|
|
150
181
|
lastUpdateTime.current = currentTime;
|
|
151
182
|
camera.getWorldDirection(u);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
183
|
+
const walls = sceneRegistry.byType.wall;
|
|
184
|
+
walls.forEach((wallId) => {
|
|
185
|
+
const wallMesh = sceneRegistry.nodes.get(wallId);
|
|
186
|
+
if (!wallMesh)
|
|
187
|
+
return;
|
|
188
|
+
const wallNode = useScene.getState().nodes[wallId];
|
|
189
|
+
if (!wallNode || wallNode.type !== 'wall')
|
|
190
|
+
return;
|
|
191
|
+
const hideWall = getWallHideState(wallNode, wallMesh, wallMode, u);
|
|
192
|
+
const isDeleteHighlighted = deleteHoveredWallId === wallId;
|
|
193
|
+
const isSelectionHighlighted = !isDeleteHighlighted && highlightedWallIds.has(wallId);
|
|
194
|
+
const materials = getMaterialsForWall(wallNode);
|
|
195
|
+
if (hideWall) {
|
|
196
|
+
;
|
|
197
|
+
wallMesh.material = isDeleteHighlighted
|
|
198
|
+
? materials.deleteInvisible
|
|
199
|
+
: isSelectionHighlighted
|
|
200
|
+
? materials.highlightedInvisible
|
|
201
|
+
: materials.invisible;
|
|
160
202
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
203
|
+
else {
|
|
204
|
+
;
|
|
205
|
+
wallMesh.material = isDeleteHighlighted
|
|
206
|
+
? materials.deleteVisible
|
|
207
|
+
: isSelectionHighlighted
|
|
208
|
+
? materials.highlightedVisible
|
|
209
|
+
: wallNode.material
|
|
210
|
+
? materials.visible
|
|
211
|
+
: baseMaterial;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
166
214
|
lastWallMode.current = wallMode;
|
|
167
215
|
lastNumberOfWalls.current = sceneRegistry.byType.wall.size;
|
|
216
|
+
lastHighlightKey.current = highlightKey;
|
|
168
217
|
}
|
|
169
218
|
});
|
|
170
219
|
return null;
|