@pascal-app/viewer 0.6.0 → 0.7.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/error-boundary.d.ts +7 -3
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/error-boundary.js +3 -1
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +1 -1
- package/dist/components/renderers/ceiling/ceiling-renderer.js +19 -3
- package/dist/components/renderers/column/column-renderer.d.ts +5 -0
- package/dist/components/renderers/column/column-renderer.d.ts.map +1 -0
- package/dist/components/renderers/column/column-renderer.js +594 -0
- package/dist/components/renderers/door/door-renderer.d.ts.map +1 -1
- package/dist/components/renderers/door/door-renderer.js +4 -9
- package/dist/components/renderers/fence/fence-renderer.d.ts.map +1 -1
- package/dist/components/renderers/guide/guide-renderer.js +1 -1
- package/dist/components/renderers/item/item-renderer.d.ts.map +1 -1
- package/dist/components/renderers/item/item-renderer.js +2 -1
- package/dist/components/renderers/node-renderer.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.js +3 -1
- package/dist/components/renderers/roof/roof-renderer.d.ts.map +1 -1
- package/dist/components/renderers/roof/roof-renderer.js +1 -13
- package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts.map +1 -1
- package/dist/components/renderers/roof-segment/roof-segment-renderer.js +5 -20
- package/dist/components/renderers/slab/slab-renderer.d.ts.map +1 -1
- package/dist/components/renderers/slab/slab-renderer.js +39 -27
- package/dist/components/renderers/spawn/spawn-renderer.d.ts +5 -0
- package/dist/components/renderers/spawn/spawn-renderer.d.ts.map +1 -0
- package/dist/components/renderers/spawn/spawn-renderer.js +32 -0
- package/dist/components/renderers/stair/stair-renderer.d.ts.map +1 -1
- package/dist/components/renderers/stair/stair-renderer.js +5 -23
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +1 -1
- package/dist/components/renderers/stair-segment/stair-segment-renderer.js +5 -22
- package/dist/components/viewer/index.d.ts +2 -0
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +88 -18
- package/dist/components/viewer/post-processing.d.ts +13 -1
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +71 -14
- package/dist/components/viewer/selection-manager.d.ts.map +1 -1
- package/dist/components/viewer/selection-manager.js +19 -2
- 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 +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/lib/materials.d.ts +3 -0
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +14 -0
- package/dist/lib/merged-outline-node.d.ts +2 -0
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +25 -5
- package/dist/store/use-viewer.d.ts +4 -4
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +2 -2
- package/dist/systems/ceiling/ceiling-system.d.ts +8 -0
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -0
- package/dist/systems/ceiling/ceiling-system.js +91 -0
- package/dist/systems/column/column-geometry.d.ts +22 -0
- package/dist/systems/column/column-geometry.d.ts.map +1 -0
- package/dist/systems/column/column-geometry.js +108 -0
- package/dist/systems/door/door-animation-system.d.ts +2 -0
- package/dist/systems/door/door-animation-system.d.ts.map +1 -0
- package/dist/systems/door/door-animation-system.js +53 -0
- package/dist/systems/door/door-system.d.ts +2 -0
- package/dist/systems/door/door-system.d.ts.map +1 -0
- package/dist/systems/door/door-system.js +867 -0
- package/dist/systems/fence/fence-system.d.ts +2 -0
- package/dist/systems/fence/fence-system.d.ts.map +1 -0
- package/dist/systems/fence/fence-system.js +185 -0
- package/dist/systems/item/item-system.d.ts +2 -0
- package/dist/systems/item/item-system.d.ts.map +1 -0
- package/dist/systems/item/item-system.js +44 -0
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts +14 -0
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts.map +1 -0
- package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.js +155 -0
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts +6 -0
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts.map +1 -0
- package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.js +75 -0
- package/dist/systems/item-mesh-metadata/sync-request.d.ts +7 -0
- package/dist/systems/item-mesh-metadata/sync-request.d.ts.map +1 -0
- package/dist/systems/item-mesh-metadata/sync-request.js +25 -0
- package/dist/systems/roof/roof-materials.d.ts.map +1 -1
- package/dist/systems/roof/roof-materials.js +18 -1
- package/dist/systems/roof/roof-system.d.ts +16 -0
- package/dist/systems/roof/roof-system.d.ts.map +1 -0
- package/dist/systems/roof/roof-system.js +797 -0
- package/dist/systems/slab/slab-system.d.ts +8 -0
- package/dist/systems/slab/slab-system.d.ts.map +1 -0
- package/dist/systems/slab/slab-system.js +155 -0
- package/dist/systems/stair/stair-materials.d.ts.map +1 -1
- package/dist/systems/stair/stair-materials.js +25 -2
- package/dist/systems/stair/stair-system.d.ts +2 -0
- package/dist/systems/stair/stair-system.d.ts.map +1 -0
- package/dist/systems/stair/stair-system.js +772 -0
- package/dist/systems/wall/wall-materials.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.js +2 -2
- package/dist/systems/wall/wall-system.d.ts +11 -0
- package/dist/systems/wall/wall-system.d.ts.map +1 -0
- package/dist/systems/wall/wall-system.js +592 -0
- package/dist/systems/window/window-animation-system.d.ts +2 -0
- package/dist/systems/window/window-animation-system.d.ts.map +1 -0
- package/dist/systems/window/window-animation-system.js +135 -0
- package/dist/systems/window/window-system.d.ts +12 -0
- package/dist/systems/window/window-system.d.ts.map +1 -0
- package/dist/systems/window/window-system.js +1430 -0
- package/package.json +4 -2
|
@@ -27,6 +27,15 @@ const MAX_PIPELINE_RETRIES = 3;
|
|
|
27
27
|
const RETRY_DELAY_MS = 500;
|
|
28
28
|
const DARK_BG = '#1f2433';
|
|
29
29
|
const LIGHT_BG = '#ffffff';
|
|
30
|
+
const DEFAULT_HOVER_STYLE = {
|
|
31
|
+
visibleColor: 0x00_aa_ff,
|
|
32
|
+
hiddenColor: 0xf3_ff_47,
|
|
33
|
+
strength: 5,
|
|
34
|
+
pulse: true,
|
|
35
|
+
};
|
|
36
|
+
export const DEFAULT_HOVER_STYLES = {
|
|
37
|
+
default: DEFAULT_HOVER_STYLE,
|
|
38
|
+
};
|
|
30
39
|
function sanitizeOutlineObjects(objects) {
|
|
31
40
|
let nextIndex = 0;
|
|
32
41
|
for (const object of objects) {
|
|
@@ -38,8 +47,8 @@ function sanitizeOutlineObjects(objects) {
|
|
|
38
47
|
}
|
|
39
48
|
objects.length = nextIndex;
|
|
40
49
|
}
|
|
41
|
-
const PostProcessingPasses = () => {
|
|
42
|
-
const { gl: renderer, scene, camera } = useThree();
|
|
50
|
+
const PostProcessingPasses = ({ hoverStyles = DEFAULT_HOVER_STYLES, }) => {
|
|
51
|
+
const { gl: renderer, invalidate, scene, camera } = useThree();
|
|
43
52
|
const renderPipelineRef = useRef(null);
|
|
44
53
|
const hasPipelineErrorRef = useRef(false);
|
|
45
54
|
const retryCountRef = useRef(0);
|
|
@@ -57,6 +66,10 @@ const PostProcessingPasses = () => {
|
|
|
57
66
|
return l;
|
|
58
67
|
}, []);
|
|
59
68
|
const hoverHighlightMode = useViewer((s) => s.hoverHighlightMode);
|
|
69
|
+
const hoverVisibleColor = useMemo(() => uniform(new Color(DEFAULT_HOVER_STYLE.visibleColor)), []);
|
|
70
|
+
const hoverHiddenColor = useMemo(() => uniform(new Color(DEFAULT_HOVER_STYLE.hiddenColor)), []);
|
|
71
|
+
const hoverStrength = useMemo(() => uniform(DEFAULT_HOVER_STYLE.strength), []);
|
|
72
|
+
const hoverPulseMix = useMemo(() => uniform(DEFAULT_HOVER_STYLE.pulse ? 0 : 1), []);
|
|
60
73
|
// Subscribe to projectId so the pipeline rebuilds on project switch
|
|
61
74
|
const projectId = useViewer((s) => s.projectId);
|
|
62
75
|
// Bump this to force a pipeline rebuild (used by retry logic)
|
|
@@ -86,6 +99,22 @@ const PostProcessingPasses = () => {
|
|
|
86
99
|
}
|
|
87
100
|
};
|
|
88
101
|
}, []);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
const style = hoverStyles[hoverHighlightMode] ?? hoverStyles.default;
|
|
104
|
+
hoverVisibleColor.value.setHex(style.visibleColor);
|
|
105
|
+
hoverHiddenColor.value.setHex(style.hiddenColor);
|
|
106
|
+
hoverStrength.value = style.strength;
|
|
107
|
+
hoverPulseMix.value = style.pulse ? 0 : 1;
|
|
108
|
+
invalidate();
|
|
109
|
+
}, [
|
|
110
|
+
hoverHiddenColor,
|
|
111
|
+
hoverHighlightMode,
|
|
112
|
+
hoverPulseMix,
|
|
113
|
+
hoverStrength,
|
|
114
|
+
hoverStyles,
|
|
115
|
+
hoverVisibleColor,
|
|
116
|
+
invalidate,
|
|
117
|
+
]);
|
|
89
118
|
// Build / rebuild the post-processing pipeline
|
|
90
119
|
useEffect(() => {
|
|
91
120
|
// Intentionally touch these so React/biome treat project switches and retry bumps
|
|
@@ -93,8 +122,20 @@ const PostProcessingPasses = () => {
|
|
|
93
122
|
void projectId;
|
|
94
123
|
void pipelineVersion;
|
|
95
124
|
if (!(renderer && scene && camera)) {
|
|
125
|
+
console.warn('[viewer/post-processing] Skipping pipeline build — missing dependency.', {
|
|
126
|
+
hasRenderer: !!renderer,
|
|
127
|
+
hasScene: !!scene,
|
|
128
|
+
hasCamera: !!camera,
|
|
129
|
+
});
|
|
96
130
|
return;
|
|
97
131
|
}
|
|
132
|
+
console.log('[viewer/post-processing] Building pipeline', {
|
|
133
|
+
version: pipelineVersion,
|
|
134
|
+
ssgi: SSGI_PARAMS.enabled,
|
|
135
|
+
hoverHighlightMode,
|
|
136
|
+
projectId,
|
|
137
|
+
rendererCtor: renderer.constructor?.name,
|
|
138
|
+
});
|
|
98
139
|
hasPipelineErrorRef.current = false;
|
|
99
140
|
// WebGPU availability check: SSGI, denoise, and RenderPipeline are all
|
|
100
141
|
// WebGPU-only APIs. When the browser falls back to WebGL2 (no
|
|
@@ -188,13 +229,9 @@ const PostProcessingPasses = () => {
|
|
|
188
229
|
.add(outlineNode.primaryHiddenEdge.mul(selectedHiddenColor))
|
|
189
230
|
.mul(selectedStrength);
|
|
190
231
|
// Hovered: blue visible, yellow hidden, pulsing
|
|
191
|
-
const hoverVisibleColor = uniform(new Color(hoverHighlightMode === 'delete' ? 0xef_44_44 : 0x00_aa_ff));
|
|
192
|
-
const hoverHiddenColor = uniform(new Color(hoverHighlightMode === 'delete' ? 0x99_1b_1b : 0xf3_ff_47));
|
|
193
|
-
const hoverStrength = uniform(hoverHighlightMode === 'delete' ? 6 : 5);
|
|
194
232
|
const pulsePeriod = uniform(3);
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
: oscSine(time.div(pulsePeriod).mul(2)).mul(0.5).add(0.5); // [ 0.5, 1.0 ]
|
|
233
|
+
const oscillating = oscSine(time.div(pulsePeriod).mul(2)).mul(0.5).add(0.5);
|
|
234
|
+
const osc = mix(oscillating, float(1), hoverPulseMix);
|
|
198
235
|
const hoverOutline = outlineNode.secondaryVisibleEdge
|
|
199
236
|
.mul(hoverVisibleColor)
|
|
200
237
|
.add(outlineNode.secondaryHiddenEdge.mul(hoverHiddenColor))
|
|
@@ -206,10 +243,15 @@ const PostProcessingPasses = () => {
|
|
|
206
243
|
renderPipeline.outputNode = finalOutput;
|
|
207
244
|
renderPipelineRef.current = renderPipeline;
|
|
208
245
|
retryCountRef.current = 0;
|
|
246
|
+
console.log('[viewer/post-processing] Pipeline built OK', { version: pipelineVersion });
|
|
209
247
|
}
|
|
210
248
|
catch (error) {
|
|
211
249
|
hasPipelineErrorRef.current = true;
|
|
212
|
-
console.error('[viewer] Failed to set up post-processing pipeline. Rendering without post FX.',
|
|
250
|
+
console.error('[viewer/post-processing] Failed to set up post-processing pipeline. Rendering without post FX.', {
|
|
251
|
+
version: pipelineVersion,
|
|
252
|
+
ssgi: SSGI_PARAMS.enabled,
|
|
253
|
+
rendererCtor: renderer.constructor?.name,
|
|
254
|
+
}, error);
|
|
213
255
|
if (renderPipelineRef.current) {
|
|
214
256
|
renderPipelineRef.current.dispose();
|
|
215
257
|
}
|
|
@@ -221,7 +263,18 @@ const PostProcessingPasses = () => {
|
|
|
221
263
|
}
|
|
222
264
|
renderPipelineRef.current = null;
|
|
223
265
|
};
|
|
224
|
-
}, [
|
|
266
|
+
}, [
|
|
267
|
+
camera,
|
|
268
|
+
hoverHiddenColor,
|
|
269
|
+
hoverPulseMix,
|
|
270
|
+
hoverStrength,
|
|
271
|
+
hoverVisibleColor,
|
|
272
|
+
pipelineVersion,
|
|
273
|
+
projectId,
|
|
274
|
+
renderer,
|
|
275
|
+
scene,
|
|
276
|
+
zoneLayers,
|
|
277
|
+
]);
|
|
225
278
|
useFrame((_, delta) => {
|
|
226
279
|
// Animate background colour toward the current theme target (same lerp as AnimatedBackground)
|
|
227
280
|
bgTarget.current.set(useViewer.getState().theme === 'dark' ? DARK_BG : LIGHT_BG);
|
|
@@ -240,7 +293,7 @@ const PostProcessingPasses = () => {
|
|
|
240
293
|
renderer.render(scene, camera);
|
|
241
294
|
}
|
|
242
295
|
catch (fallbackError) {
|
|
243
|
-
console.error('[viewer] Fallback render failed.', fallbackError);
|
|
296
|
+
console.error('[viewer/post-processing] Fallback render failed.', fallbackError);
|
|
244
297
|
}
|
|
245
298
|
return;
|
|
246
299
|
}
|
|
@@ -253,7 +306,11 @@ const PostProcessingPasses = () => {
|
|
|
253
306
|
}
|
|
254
307
|
catch (error) {
|
|
255
308
|
hasPipelineErrorRef.current = true;
|
|
256
|
-
console.error('[viewer
|
|
309
|
+
console.error('[viewer/post-processing] Render pass failed.', {
|
|
310
|
+
retryCount: retryCountRef.current,
|
|
311
|
+
rendererCtor: renderer.constructor?.name,
|
|
312
|
+
error,
|
|
313
|
+
});
|
|
257
314
|
if (renderPipelineRef.current) {
|
|
258
315
|
renderPipelineRef.current.dispose();
|
|
259
316
|
}
|
|
@@ -261,14 +318,14 @@ const PostProcessingPasses = () => {
|
|
|
261
318
|
if (retryCountRef.current < MAX_PIPELINE_RETRIES) {
|
|
262
319
|
// Auto-retry: schedule a pipeline rebuild if we haven't exceeded the retry limit
|
|
263
320
|
retryCountRef.current++;
|
|
264
|
-
console.warn(`[viewer] Scheduling
|
|
321
|
+
console.warn(`[viewer/post-processing] Scheduling pipeline rebuild (attempt ${retryCountRef.current}/${MAX_PIPELINE_RETRIES})`);
|
|
265
322
|
if (rebuildTimeoutRef.current !== null) {
|
|
266
323
|
clearTimeout(rebuildTimeoutRef.current);
|
|
267
324
|
}
|
|
268
325
|
rebuildTimeoutRef.current = setTimeout(requestPipelineRebuild, RETRY_DELAY_MS);
|
|
269
326
|
}
|
|
270
327
|
else {
|
|
271
|
-
console.error('[viewer
|
|
328
|
+
console.error('[viewer/post-processing] Retries exhausted. Rendering without post FX for this session.');
|
|
272
329
|
}
|
|
273
330
|
}
|
|
274
331
|
}, 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection-manager.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/selection-manager.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"selection-manager.d.ts","sourceRoot":"","sources":["../../../src/components/viewer/selection-manager.tsx"],"names":[],"mappings":"AAoSA,eAAO,MAAM,gBAAgB,+CA4E5B,CAAA"}
|
|
@@ -82,6 +82,10 @@ const isNodeInZone = (node, levelId, zoneId) => {
|
|
|
82
82
|
const item = node;
|
|
83
83
|
return pointInPolygonWithTolerance(item.position[0], item.position[2], zone.polygon);
|
|
84
84
|
}
|
|
85
|
+
if (node.type === 'column') {
|
|
86
|
+
const column = node;
|
|
87
|
+
return pointInPolygonWithTolerance(column.position[0], column.position[2], zone.polygon);
|
|
88
|
+
}
|
|
85
89
|
if (node.type === 'wall') {
|
|
86
90
|
const wall = node;
|
|
87
91
|
const startIn = pointInPolygonWithTolerance(wall.start[0], wall.start[1], zone.polygon);
|
|
@@ -168,9 +172,20 @@ const getStrategy = () => {
|
|
|
168
172
|
isValid: (node) => node.type === 'zone' && node.parentId === levelId,
|
|
169
173
|
};
|
|
170
174
|
}
|
|
171
|
-
// Zone selected -> can select/hover contents (walls, items, slabs, ceilings, roofs, windows, doors)
|
|
175
|
+
// Zone selected -> can select/hover contents (walls, items, columns, slabs, ceilings, roofs, windows, doors)
|
|
172
176
|
return {
|
|
173
|
-
types: [
|
|
177
|
+
types: [
|
|
178
|
+
'wall',
|
|
179
|
+
'fence',
|
|
180
|
+
'item',
|
|
181
|
+
'column',
|
|
182
|
+
'slab',
|
|
183
|
+
'ceiling',
|
|
184
|
+
'roof',
|
|
185
|
+
'roof-segment',
|
|
186
|
+
'window',
|
|
187
|
+
'door',
|
|
188
|
+
],
|
|
174
189
|
handleClick: (node, nativeEvent) => {
|
|
175
190
|
let nodeToSelect = node;
|
|
176
191
|
if (node.type === 'roof-segment' && node.parentId) {
|
|
@@ -199,6 +214,7 @@ const getStrategy = () => {
|
|
|
199
214
|
'wall',
|
|
200
215
|
'fence',
|
|
201
216
|
'item',
|
|
217
|
+
'column',
|
|
202
218
|
'slab',
|
|
203
219
|
'ceiling',
|
|
204
220
|
'roof',
|
|
@@ -258,6 +274,7 @@ export const SelectionManager = () => {
|
|
|
258
274
|
'wall',
|
|
259
275
|
'fence',
|
|
260
276
|
'item',
|
|
277
|
+
'column',
|
|
261
278
|
'slab',
|
|
262
279
|
'ceiling',
|
|
263
280
|
'roof',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type BuildingEvent, type BuildingNode, type CeilingEvent, type CeilingNode, type DoorEvent, type DoorNode, type FenceEvent, type FenceNode, type ItemEvent, type ItemNode, type LevelEvent, type LevelNode, type RoofEvent, type RoofNode, type RoofSegmentEvent, type RoofSegmentNode, type SiteEvent, type SiteNode, type SlabEvent, type SlabNode, type StairEvent, type StairNode, type StairSegmentEvent, type StairSegmentNode, type WallEvent, type WallNode, type WindowEvent, type WindowNode, type ZoneEvent, type ZoneNode } from '@pascal-app/core';
|
|
1
|
+
import { type BuildingEvent, type BuildingNode, type CeilingEvent, type CeilingNode, type ColumnEvent, type ColumnNode, type DoorEvent, type DoorNode, type FenceEvent, type FenceNode, type ItemEvent, type ItemNode, type LevelEvent, type LevelNode, type RoofEvent, type RoofNode, type RoofSegmentEvent, type RoofSegmentNode, type SiteEvent, type SiteNode, type SlabEvent, type SlabNode, type SpawnEvent, type SpawnNode, type StairEvent, type StairNode, type StairSegmentEvent, type StairSegmentNode, type WallEvent, type WallNode, type WindowEvent, type WindowNode, type ZoneEvent, type ZoneNode } from '@pascal-app/core';
|
|
2
2
|
import type { ThreeEvent } from '@react-three/fiber';
|
|
3
3
|
type NodeConfig = {
|
|
4
4
|
site: {
|
|
@@ -33,10 +33,18 @@ type NodeConfig = {
|
|
|
33
33
|
node: SlabNode;
|
|
34
34
|
event: SlabEvent;
|
|
35
35
|
};
|
|
36
|
+
spawn: {
|
|
37
|
+
node: SpawnNode;
|
|
38
|
+
event: SpawnEvent;
|
|
39
|
+
};
|
|
36
40
|
ceiling: {
|
|
37
41
|
node: CeilingNode;
|
|
38
42
|
event: CeilingEvent;
|
|
39
43
|
};
|
|
44
|
+
column: {
|
|
45
|
+
node: ColumnNode;
|
|
46
|
+
event: ColumnEvent;
|
|
47
|
+
};
|
|
40
48
|
roof: {
|
|
41
49
|
node: RoofNode;
|
|
42
50
|
event: RoofEvent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-node-events.d.ts","sourceRoot":"","sources":["../../src/hooks/use-node-events.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-node-events.d.ts","sourceRoot":"","sources":["../../src/hooks/use-node-events.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,QAAQ,EAGb,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAGpD,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,CAAA;IAC1C,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,CAAA;IAC1C,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,CAAA;IAC1C,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAA;IAC7C,QAAQ,EAAE;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,aAAa,CAAA;KAAE,CAAA;IACtD,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAA;IAC7C,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,CAAA;IAC1C,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,CAAA;IAC1C,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAA;IAC7C,OAAO,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,YAAY,CAAA;KAAE,CAAA;IACnD,MAAM,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,WAAW,CAAA;KAAE,CAAA;IAChD,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,CAAA;IAC1C,cAAc,EAAE;QAAE,IAAI,EAAE,eAAe,CAAC;QAAC,KAAK,EAAE,gBAAgB,CAAA;KAAE,CAAA;IAClE,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAA;IAC7C,eAAe,EAAE;QAAE,IAAI,EAAE,gBAAgB,CAAC;QAAC,KAAK,EAAE,iBAAiB,CAAA;KAAE,CAAA;IACrE,MAAM,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,WAAW,CAAA;KAAE,CAAA;IAChD,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,CAAA;CAC3C,CAAA;AAED,KAAK,QAAQ,GAAG,MAAM,UAAU,CAAA;AAEhC,wBAAgB,aAAa,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;uBAmB/D,UAAU,CAAC,YAAY,CAAC;qBAK1B,UAAU,CAAC,YAAY,CAAC;iBAQ5B,UAAU,CAAC,YAAY,CAAC;wBAIjB,UAAU,CAAC,YAAY,CAAC;wBAIxB,UAAU,CAAC,YAAY,CAAC;uBAIzB,UAAU,CAAC,YAAY,CAAC;uBAIxB,UAAU,CAAC,YAAY,CAAC;uBAIxB,UAAU,CAAC,YAAY,CAAC;EAK9C"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
export { default as Viewer } from './components/viewer';
|
|
2
|
-
export {
|
|
2
|
+
export type { HoverStyle, HoverStyles } from './components/viewer/post-processing';
|
|
3
|
+
export { DEFAULT_HOVER_STYLES, SSGI_PARAMS, } from './components/viewer/post-processing';
|
|
3
4
|
export { WalkthroughControls } from './components/viewer/walkthrough-controls';
|
|
4
5
|
export { ASSETS_CDN_URL, resolveAssetUrl, resolveCdnUrl } from './lib/asset-url';
|
|
5
6
|
export { SCENE_LAYER, ZONE_LAYER } from './lib/layers';
|
|
6
|
-
export { clearMaterialCache, createDefaultMaterial, createMaterial, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, } from './lib/materials';
|
|
7
|
+
export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, } from './lib/materials';
|
|
7
8
|
export { mergedOutline } from './lib/merged-outline-node';
|
|
8
9
|
export { default as useViewer } from './store/use-viewer';
|
|
9
10
|
export { InteractiveSystem } from './systems/interactive/interactive-system';
|
|
10
11
|
export { snapLevelsToTruePositions } from './systems/level/level-utils';
|
|
12
|
+
export { getRoofMaterialArray } from './systems/roof/roof-materials';
|
|
13
|
+
export { getStairBodyMaterials, getStairRailingMaterial } from './systems/stair/stair-materials';
|
|
14
|
+
export { getVisibleWallMaterials } from './systems/wall/wall-materials';
|
|
11
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACvD,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAA;AAClF,OAAO,EACL,oBAAoB,EACpB,WAAW,GACZ,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACtD,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,qBAAqB,EACrB,cAAc,EACd,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAC5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAChG,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
export { default as Viewer } from './components/viewer';
|
|
2
|
-
export { SSGI_PARAMS } from './components/viewer/post-processing';
|
|
2
|
+
export { DEFAULT_HOVER_STYLES, SSGI_PARAMS, } from './components/viewer/post-processing';
|
|
3
3
|
export { WalkthroughControls } from './components/viewer/walkthrough-controls';
|
|
4
4
|
export { ASSETS_CDN_URL, resolveAssetUrl, resolveCdnUrl } from './lib/asset-url';
|
|
5
5
|
export { SCENE_LAYER, ZONE_LAYER } from './lib/layers';
|
|
6
|
-
export { clearMaterialCache, createDefaultMaterial, createMaterial, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, } from './lib/materials';
|
|
6
|
+
export { applyMaterialPresetToMaterials, clearMaterialCache, createDefaultMaterial, createMaterial, createMaterialFromPresetRef, DEFAULT_CEILING_MATERIAL, DEFAULT_DOOR_MATERIAL, DEFAULT_ROOF_MATERIAL, DEFAULT_SLAB_MATERIAL, DEFAULT_WALL_MATERIAL, DEFAULT_WINDOW_MATERIAL, disposeMaterial, } from './lib/materials';
|
|
7
7
|
export { mergedOutline } from './lib/merged-outline-node';
|
|
8
8
|
export { default as useViewer } from './store/use-viewer';
|
|
9
9
|
export { InteractiveSystem } from './systems/interactive/interactive-system';
|
|
10
10
|
export { snapLevelsToTruePositions } from './systems/level/level-utils';
|
|
11
|
+
export { getRoofMaterialArray } from './systems/roof/roof-materials';
|
|
12
|
+
export { getStairBodyMaterials, getStairRailingMaterial } from './systems/stair/stair-materials';
|
|
13
|
+
export { getVisibleWallMaterials } from './systems/wall/wall-materials';
|
package/dist/lib/materials.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { type MaterialPresetPayload, type MaterialSchema } from '@pascal-app/core';
|
|
2
2
|
import * as THREE from 'three';
|
|
3
|
+
import { MeshStandardNodeMaterial } from 'three/webgpu';
|
|
4
|
+
export declare const baseMaterial: MeshStandardNodeMaterial;
|
|
5
|
+
export declare const glassMaterial: MeshStandardNodeMaterial;
|
|
3
6
|
export declare function applyMaterialPresetToMaterials(materialInput: THREE.Material | THREE.Material[], preset: MaterialPresetPayload | null | undefined): void;
|
|
4
7
|
export declare function createMaterialFromPreset(preset: MaterialPresetPayload): THREE.MeshStandardMaterial;
|
|
5
8
|
export declare function createMaterialFromPresetRef(materialPreset?: string): THREE.MeshStandardMaterial | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/lib/materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EAGpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"materials.d.ts","sourceRoot":"","sources":["../../src/lib/materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAE1B,KAAK,cAAc,EAGpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAEvD,eAAO,MAAM,YAAY,0BAIvB,CAAA;AAEF,eAAO,MAAM,aAAa,0BAOxB,CAAA;AA2MF,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,EAChD,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,QAcjD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,KAAK,CAAC,oBAAoB,CAWlG;AAED,wBAAgB,2BAA2B,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAItG;AAED,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC,oBAAoB,CAsBpF;AAED,wBAAgB,qBAAqB,CACnC,KAAK,SAAY,EACjB,SAAS,SAAM,GACd,KAAK,CAAC,oBAAoB,CAO5B;AAED,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,qBAAqB,4BAAwC,CAAA;AAC1E,eAAO,MAAM,uBAAuB,4BAOlC,CAAA;AACF,eAAO,MAAM,wBAAwB,4BAAyC,CAAA;AAC9E,eAAO,MAAM,qBAAqB,4BAAyC,CAAA;AAC3E,eAAO,MAAM,sBAAsB,4BAAwC,CAAA;AAE3E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,CAE9D;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAWzC"}
|
package/dist/lib/materials.js
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { getMaterialPresetByRef, resolveMaterial, } from '@pascal-app/core';
|
|
2
2
|
import * as THREE from 'three';
|
|
3
|
+
import { MeshStandardNodeMaterial } from 'three/webgpu';
|
|
4
|
+
export const baseMaterial = new MeshStandardNodeMaterial({
|
|
5
|
+
color: '#f2f0ed',
|
|
6
|
+
roughness: 0.5,
|
|
7
|
+
metalness: 0.0,
|
|
8
|
+
});
|
|
9
|
+
export const glassMaterial = new MeshStandardNodeMaterial({
|
|
10
|
+
color: '#e0f2fe',
|
|
11
|
+
roughness: 0.05,
|
|
12
|
+
metalness: 0.0,
|
|
13
|
+
transparent: true,
|
|
14
|
+
opacity: 0.35,
|
|
15
|
+
side: THREE.DoubleSide,
|
|
16
|
+
});
|
|
3
17
|
const sideMap = {
|
|
4
18
|
front: THREE.FrontSide,
|
|
5
19
|
back: THREE.BackSide,
|
|
@@ -62,6 +62,8 @@ export declare class MergedOutlineNode extends TempNode {
|
|
|
62
62
|
private readonly _compositeMatB;
|
|
63
63
|
private readonly _cacheA;
|
|
64
64
|
private readonly _cacheB;
|
|
65
|
+
private _wroteGroupALastFrame;
|
|
66
|
+
private _wroteGroupBLastFrame;
|
|
65
67
|
private readonly _textureNodeA;
|
|
66
68
|
private readonly _textureNodeB;
|
|
67
69
|
constructor(scene: any, camera: any, params?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merged-outline-node.d.ts","sourceRoot":"","sources":["../../src/lib/merged-outline-node.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAA2B,KAAK,QAAQ,EAAyB,MAAM,OAAO,CAAA;AAyBrF,OAAO,EAML,QAAQ,EACT,MAAM,cAAc,CAAA;AA8DrB,qBAAa,iBAAkB,SAAQ,QAAQ;IAC7C,MAAM,KAAK,IAAI,WAEd;IAED,KAAK,EAAE,GAAG,CAAA;IACV,MAAM,EAAE,GAAG,CAAA;IACX,cAAc,EAAE,QAAQ,EAAE,CAAA;IAC1B,gBAAgB,EAAE,QAAQ,EAAE,CAAA;IAC5B,wBAAwB,EAAE,GAAG,CAAA;IAC7B,0BAA0B,EAAE,GAAG,CAAA;IAC/B,mBAAmB,EAAE,GAAG,CAAA;IACxB,qBAAqB,EAAE,GAAG,CAAA;IAC1B,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IAExB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAK;IAEtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAK;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAK;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAK;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAK;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAK;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAK;IACpC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAK;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAK;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAK;IAEhC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAC7C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAoB;IACzD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAc;IAC/C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAc;IAC/C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAE7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;
|
|
1
|
+
{"version":3,"file":"merged-outline-node.d.ts","sourceRoot":"","sources":["../../src/lib/merged-outline-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -120,6 +120,13 @@ export class MergedOutlineNode extends TempNode {
|
|
|
120
120
|
_compositeMatB;
|
|
121
121
|
_cacheA = new Set();
|
|
122
122
|
_cacheB = new Set();
|
|
123
|
+
// Tracks whether either group rendered last frame. We use this to decide
|
|
124
|
+
// when it's safe to skip renderer state manipulation entirely — touching
|
|
125
|
+
// the renderer (resetRendererAndSceneState + setRenderTarget + clearColor)
|
|
126
|
+
// corrupts the FBO state on the WebGL2 backend (iOS Chrome fallback) and
|
|
127
|
+
// the subsequent scene render comes out blank.
|
|
128
|
+
_wroteGroupALastFrame = false;
|
|
129
|
+
_wroteGroupBLastFrame = false;
|
|
123
130
|
_textureNodeA;
|
|
124
131
|
_textureNodeB;
|
|
125
132
|
constructor(scene, camera, params = {}) {
|
|
@@ -213,27 +220,40 @@ export class MergedOutlineNode extends TempNode {
|
|
|
213
220
|
updateBefore(frame) {
|
|
214
221
|
const hasPrimary = this.primaryObjects.length > 0;
|
|
215
222
|
const hasSecondary = this.secondaryObjects.length > 0;
|
|
223
|
+
const hasAny = hasPrimary || hasSecondary;
|
|
224
|
+
// Fast-path: nothing to render and nothing was rendered last frame either,
|
|
225
|
+
// so there are no stale composites to clear. Touch nothing — on the WebGL2
|
|
226
|
+
// backend (iOS Chrome fallback) even an empty reset/setRenderTarget cycle
|
|
227
|
+
// corrupts the framebuffer state and the next scene render goes blank.
|
|
228
|
+
const needsCleanupA = !hasPrimary && this._wroteGroupALastFrame;
|
|
229
|
+
const needsCleanupB = !hasSecondary && this._wroteGroupBLastFrame;
|
|
230
|
+
if (!(hasAny || needsCleanupA || needsCleanupB)) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
216
233
|
const { renderer } = frame;
|
|
217
234
|
const { camera, scene } = this;
|
|
218
235
|
_rendererState = RendererUtils.resetRendererAndSceneState(renderer, scene, _rendererState);
|
|
219
236
|
const size = renderer.getDrawingBufferSize(_size);
|
|
220
237
|
this.setSize(size.width, size.height);
|
|
221
|
-
// Clear composites for
|
|
222
|
-
//
|
|
223
|
-
if (
|
|
238
|
+
// Clear composites for groups that just transitioned from "has content"
|
|
239
|
+
// to "empty" — without this, the previous outline lingers on the GPU.
|
|
240
|
+
if (needsCleanupA) {
|
|
224
241
|
renderer.setRenderTarget(this._groupA.composite);
|
|
225
242
|
renderer.clearColor();
|
|
243
|
+
this._wroteGroupALastFrame = false;
|
|
226
244
|
}
|
|
227
|
-
if (
|
|
245
|
+
if (needsCleanupB) {
|
|
228
246
|
renderer.setRenderTarget(this._groupB.composite);
|
|
229
247
|
renderer.clearColor();
|
|
248
|
+
this._wroteGroupBLastFrame = false;
|
|
230
249
|
}
|
|
231
|
-
const hasAny = hasPrimary || hasSecondary;
|
|
232
250
|
if (!hasAny) {
|
|
233
251
|
RendererUtils.restoreRendererAndSceneState(renderer, scene, _rendererState);
|
|
234
252
|
return;
|
|
235
253
|
}
|
|
236
254
|
renderer.setClearColor(0xff_ff_ff, 1);
|
|
255
|
+
this._wroteGroupALastFrame = hasPrimary;
|
|
256
|
+
this._wroteGroupBLastFrame = hasSecondary;
|
|
237
257
|
if (hasPrimary)
|
|
238
258
|
this._buildCache(this.primaryObjects, this._cacheA);
|
|
239
259
|
if (hasSecondary)
|
|
@@ -14,8 +14,8 @@ type ViewerState = {
|
|
|
14
14
|
selection: SelectionPath;
|
|
15
15
|
previewSelectedIds: BaseNode['id'][];
|
|
16
16
|
setPreviewSelectedIds: (ids: BaseNode['id'][]) => void;
|
|
17
|
-
hoverHighlightMode:
|
|
18
|
-
setHoverHighlightMode: (mode:
|
|
17
|
+
hoverHighlightMode: string;
|
|
18
|
+
setHoverHighlightMode: (mode: string) => void;
|
|
19
19
|
hoveredId: AnyNode['id'] | ZoneNode['id'] | null;
|
|
20
20
|
setHoveredId: (id: AnyNode['id'] | ZoneNode['id'] | null) => void;
|
|
21
21
|
cameraMode: 'perspective' | 'orthographic';
|
|
@@ -62,7 +62,7 @@ declare const useViewer: import("zustand").UseBoundStore<Omit<import("zustand").
|
|
|
62
62
|
theme: "light" | "dark";
|
|
63
63
|
unit: "metric" | "imperial";
|
|
64
64
|
levelMode: "manual" | "stacked" | "exploded" | "solo";
|
|
65
|
-
wallMode: "up" | "
|
|
65
|
+
wallMode: "up" | "down" | "cutaway";
|
|
66
66
|
projectPreferences: Record<string, {
|
|
67
67
|
showScans?: boolean;
|
|
68
68
|
showGuides?: boolean;
|
|
@@ -79,7 +79,7 @@ declare const useViewer: import("zustand").UseBoundStore<Omit<import("zustand").
|
|
|
79
79
|
theme: "light" | "dark";
|
|
80
80
|
unit: "metric" | "imperial";
|
|
81
81
|
levelMode: "manual" | "stacked" | "exploded" | "solo";
|
|
82
|
-
wallMode: "up" | "
|
|
82
|
+
wallMode: "up" | "down" | "cutaway";
|
|
83
83
|
projectPreferences: Record<string, {
|
|
84
84
|
showScans?: boolean;
|
|
85
85
|
showGuides?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC5F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAKrC,KAAK,aAAa,GAAG;IACnB,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACrC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC/B,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC7B,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAA;CAC9B,CAAA;AAED,KAAK,QAAQ,GAAG;IACd,eAAe,EAAE,QAAQ,EAAE,CAAA;IAC3B,cAAc,EAAE,QAAQ,EAAE,CAAA;CAC3B,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,aAAa,CAAA;IACxB,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAA;IACpC,qBAAqB,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAA;IACtD,kBAAkB,EAAE,
|
|
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
|
@@ -6,9 +6,9 @@ const useViewer = create()(persist((set) => ({
|
|
|
6
6
|
previewSelectedIds: [],
|
|
7
7
|
setPreviewSelectedIds: (ids) => set({ previewSelectedIds: ids }),
|
|
8
8
|
hoverHighlightMode: 'default',
|
|
9
|
-
setHoverHighlightMode: (mode) => set({ hoverHighlightMode: mode }),
|
|
9
|
+
setHoverHighlightMode: (mode) => set((state) => (state.hoverHighlightMode === mode ? state : { hoverHighlightMode: mode })),
|
|
10
10
|
hoveredId: null,
|
|
11
|
-
setHoveredId: (id) => set({ hoveredId: id }),
|
|
11
|
+
setHoveredId: (id) => set((state) => (state.hoveredId === id ? state : { hoveredId: id })),
|
|
12
12
|
cameraMode: 'perspective',
|
|
13
13
|
setCameraMode: (mode) => set({ cameraMode: mode }),
|
|
14
14
|
theme: 'light',
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type CeilingNode } from '@pascal-app/core';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
export declare const CeilingSystem: () => null;
|
|
4
|
+
/**
|
|
5
|
+
* Generates flat ceiling geometry from polygon (no extrusion)
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateCeilingGeometry(ceilingNode: CeilingNode): THREE.BufferGeometry;
|
|
8
|
+
//# sourceMappingURL=ceiling-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ceiling-system.d.ts","sourceRoot":"","sources":["../../../src/systems/ceiling/ceiling-system.tsx"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,WAAW,EAA2B,MAAM,kBAAkB,CAAA;AAC5F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,eAAO,MAAM,aAAa,YAuBzB,CAAA;AAqBD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,WAAW,GAAG,KAAK,CAAC,cAAc,CAgDtF"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { useFrame } from '@react-three/fiber';
|
|
2
|
+
import { sceneRegistry, useScene } from '@pascal-app/core';
|
|
3
|
+
import * as THREE from 'three';
|
|
4
|
+
function ensureUv2Attribute(geometry) {
|
|
5
|
+
const uv = geometry.getAttribute('uv');
|
|
6
|
+
if (!uv)
|
|
7
|
+
return;
|
|
8
|
+
geometry.setAttribute('uv2', new THREE.Float32BufferAttribute(Array.from(uv.array), 2));
|
|
9
|
+
}
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// CEILING SYSTEM
|
|
12
|
+
// ============================================================================
|
|
13
|
+
export const CeilingSystem = () => {
|
|
14
|
+
const dirtyNodes = useScene((state) => state.dirtyNodes);
|
|
15
|
+
const clearDirty = useScene((state) => state.clearDirty);
|
|
16
|
+
useFrame(() => {
|
|
17
|
+
if (dirtyNodes.size === 0)
|
|
18
|
+
return;
|
|
19
|
+
const nodes = useScene.getState().nodes;
|
|
20
|
+
// Process dirty ceilings
|
|
21
|
+
dirtyNodes.forEach((id) => {
|
|
22
|
+
const node = nodes[id];
|
|
23
|
+
if (!node || node.type !== 'ceiling')
|
|
24
|
+
return;
|
|
25
|
+
const mesh = sceneRegistry.nodes.get(id);
|
|
26
|
+
if (mesh) {
|
|
27
|
+
updateCeilingGeometry(node, mesh);
|
|
28
|
+
clearDirty(id);
|
|
29
|
+
}
|
|
30
|
+
// If mesh not found, keep it dirty for next frame
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Updates the geometry for a single ceiling
|
|
37
|
+
*/
|
|
38
|
+
function updateCeilingGeometry(node, mesh) {
|
|
39
|
+
const newGeo = generateCeilingGeometry(node);
|
|
40
|
+
mesh.geometry.dispose();
|
|
41
|
+
mesh.geometry = newGeo;
|
|
42
|
+
const gridMesh = mesh.getObjectByName('ceiling-grid');
|
|
43
|
+
if (gridMesh) {
|
|
44
|
+
gridMesh.geometry.dispose();
|
|
45
|
+
gridMesh.geometry = newGeo;
|
|
46
|
+
}
|
|
47
|
+
// Position at the ceiling height
|
|
48
|
+
mesh.position.y = (node.height ?? 2.5) - 0.01; // Slight offset to avoid z-fighting with upper-level slabs
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Generates flat ceiling geometry from polygon (no extrusion)
|
|
52
|
+
*/
|
|
53
|
+
export function generateCeilingGeometry(ceilingNode) {
|
|
54
|
+
const polygon = ceilingNode.polygon;
|
|
55
|
+
if (polygon.length < 3) {
|
|
56
|
+
return new THREE.BufferGeometry();
|
|
57
|
+
}
|
|
58
|
+
// Create shape from polygon
|
|
59
|
+
// Shape is in X-Y plane, we'll rotate to X-Z plane
|
|
60
|
+
const shape = new THREE.Shape();
|
|
61
|
+
const firstPt = polygon[0];
|
|
62
|
+
// Negate Y (which becomes Z) to get correct orientation after rotation
|
|
63
|
+
shape.moveTo(firstPt[0], -firstPt[1]);
|
|
64
|
+
for (let i = 1; i < polygon.length; i++) {
|
|
65
|
+
const pt = polygon[i];
|
|
66
|
+
shape.lineTo(pt[0], -pt[1]);
|
|
67
|
+
}
|
|
68
|
+
shape.closePath();
|
|
69
|
+
// Add holes to the shape
|
|
70
|
+
const holes = ceilingNode.holes || [];
|
|
71
|
+
for (const holePolygon of holes) {
|
|
72
|
+
if (holePolygon.length < 3)
|
|
73
|
+
continue;
|
|
74
|
+
const holePath = new THREE.Path();
|
|
75
|
+
const holeFirstPt = holePolygon[0];
|
|
76
|
+
holePath.moveTo(holeFirstPt[0], -holeFirstPt[1]);
|
|
77
|
+
for (let i = 1; i < holePolygon.length; i++) {
|
|
78
|
+
const pt = holePolygon[i];
|
|
79
|
+
holePath.lineTo(pt[0], -pt[1]);
|
|
80
|
+
}
|
|
81
|
+
holePath.closePath();
|
|
82
|
+
shape.holes.push(holePath);
|
|
83
|
+
}
|
|
84
|
+
// Create flat shape geometry (no extrusion)
|
|
85
|
+
const geometry = new THREE.ShapeGeometry(shape);
|
|
86
|
+
// Rotate so the shape lies flat in X-Z plane
|
|
87
|
+
geometry.rotateX(-Math.PI / 2);
|
|
88
|
+
geometry.computeVertexNormals();
|
|
89
|
+
ensureUv2Attribute(geometry);
|
|
90
|
+
return geometry;
|
|
91
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type BufferGeometry } from 'three';
|
|
2
|
+
export declare function createColumnBoxGeometry(width: number, height: number, depth: number, bevelRadius?: number): BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>;
|
|
3
|
+
export declare function createColumnCylinderGeometry({ height, radiusBottom, radiusTop, radiusX, radiusZ, segments, }: {
|
|
4
|
+
height: number;
|
|
5
|
+
radiusBottom: number;
|
|
6
|
+
radiusTop?: number;
|
|
7
|
+
radiusX?: number;
|
|
8
|
+
radiusZ?: number;
|
|
9
|
+
segments?: number;
|
|
10
|
+
}): BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>;
|
|
11
|
+
export declare function createColumnSphereGeometry(radius: number, widthSegments?: number, heightSegments?: number): BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>;
|
|
12
|
+
export declare function createColumnTorusGeometry({ arc, radialSegments, ringRadius, scaleX, scaleY, scaleZ, tubeRadius, tubularSegments, }: {
|
|
13
|
+
arc?: number;
|
|
14
|
+
radialSegments?: number;
|
|
15
|
+
ringRadius: number;
|
|
16
|
+
scaleX?: number;
|
|
17
|
+
scaleY?: number;
|
|
18
|
+
scaleZ?: number;
|
|
19
|
+
tubeRadius: number;
|
|
20
|
+
tubularSegments?: number;
|
|
21
|
+
}): BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>;
|
|
22
|
+
//# sourceMappingURL=column-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"column-geometry.d.ts","sourceRoot":"","sources":["../../../src/systems/column/column-geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EAKpB,MAAM,OAAO,CAAA;AAkHd,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,WAAW,SAAI,kGAOhB;AAED,wBAAgB,4BAA4B,CAAC,EAC3C,MAAM,EACN,YAAY,EACZ,SAAwB,EACxB,OAAW,EACX,OAAW,EACX,QAAa,GACd,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,kGASA;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,SAAK,EAAE,cAAc,SAAI,kGAEhG;AAED,wBAAgB,yBAAyB,CAAC,EACxC,GAAiB,EACjB,cAAmB,EACnB,UAAU,EACV,MAAmB,EACnB,MAAmB,EACnB,MAAU,EACV,UAAU,EACV,eAAoB,GACrB,EAAE;IACD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,kGAIA"}
|