@pascal-app/viewer 1.0.1 → 1.0.4
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/node-renderer.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.js +8 -3
- package/dist/components/viewer/frame-limiter.d.ts +1 -0
- package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
- package/dist/components/viewer/frame-limiter.js +22 -3
- package/dist/components/viewer/glb-interactive.d.ts +25 -1
- package/dist/components/viewer/glb-interactive.d.ts.map +1 -1
- package/dist/components/viewer/glb-interactive.js +252 -85
- package/dist/components/viewer/glb-mechanisms.d.ts +10 -0
- package/dist/components/viewer/glb-mechanisms.d.ts.map +1 -0
- package/dist/components/viewer/glb-mechanisms.js +19 -0
- package/dist/components/viewer/glb-scene.d.ts +45 -27
- package/dist/components/viewer/glb-scene.d.ts.map +1 -1
- package/dist/components/viewer/glb-scene.js +420 -506
- package/dist/components/viewer/glb-walkthrough-controller.d.ts +1 -1
- package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -1
- package/dist/components/viewer/glb-walkthrough-controller.js +12 -1
- package/dist/components/viewer/index.d.ts +26 -0
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +108 -29
- package/dist/components/viewer/lights.d.ts.map +1 -1
- package/dist/components/viewer/lights.js +6 -1
- package/dist/components/viewer/perf-monitor.d.ts.map +1 -1
- package/dist/components/viewer/perf-monitor.js +6 -0
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +8 -3
- package/dist/components/viewer/registered-systems.d.ts.map +1 -1
- package/dist/components/viewer/registered-systems.js +16 -2
- package/dist/components/viewer/render-error.d.ts +18 -0
- package/dist/components/viewer/render-error.d.ts.map +1 -0
- package/dist/components/viewer/render-error.js +29 -0
- package/dist/components/viewer/scene-ground-replacement.d.ts +6 -0
- package/dist/components/viewer/scene-ground-replacement.d.ts.map +1 -1
- package/dist/components/viewer/scene-ground-replacement.js +15 -0
- package/dist/components/viewer/selection-manager.d.ts.map +1 -1
- package/dist/components/viewer/selection-manager.js +10 -0
- package/dist/components/viewer/viewer-camera.d.ts +19 -1
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
- package/dist/components/viewer/viewer-camera.js +53 -5
- package/dist/index.d.ts +28 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -18
- package/dist/lib/asset-url.d.ts.map +1 -1
- package/dist/lib/asset-url.js +7 -1
- package/dist/lib/csg-utils.d.ts +1 -1
- package/dist/lib/csg-utils.d.ts.map +1 -1
- package/dist/lib/csg-utils.js +1 -1
- package/dist/lib/display-state.d.ts +25 -0
- package/dist/lib/display-state.d.ts.map +1 -0
- package/dist/lib/display-state.js +1 -0
- package/dist/lib/hero-pose.d.ts +12 -2
- package/dist/lib/hero-pose.d.ts.map +1 -1
- package/dist/lib/hero-pose.js +72 -5
- package/dist/lib/ink-edges.d.ts +4 -2
- package/dist/lib/ink-edges.d.ts.map +1 -1
- package/dist/lib/ink-edges.js +17 -7
- package/dist/lib/key-light-override.d.ts +11 -0
- package/dist/lib/key-light-override.d.ts.map +1 -0
- package/dist/lib/key-light-override.js +14 -0
- package/dist/lib/live-frame-hold.d.ts +14 -0
- package/dist/lib/live-frame-hold.d.ts.map +1 -0
- package/dist/lib/live-frame-hold.js +28 -0
- package/dist/lib/materials.d.ts +14 -7
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +31 -5
- package/dist/lib/node-top-surface-height.d.ts +6 -0
- package/dist/lib/node-top-surface-height.d.ts.map +1 -0
- package/dist/lib/node-top-surface-height.js +74 -0
- package/dist/lib/perf-probe-state.d.ts +39 -0
- package/dist/lib/perf-probe-state.d.ts.map +1 -0
- package/dist/lib/perf-probe-state.js +17 -0
- package/dist/lib/pointer-events.d.ts +8 -0
- package/dist/lib/pointer-events.d.ts.map +1 -1
- package/dist/lib/pointer-events.js +27 -4
- package/dist/lib/procedural-emission.d.ts +7 -0
- package/dist/lib/procedural-emission.d.ts.map +1 -0
- package/dist/lib/procedural-emission.js +54 -0
- package/dist/lib/renderer-capability.d.ts +2 -1
- package/dist/lib/renderer-capability.d.ts.map +1 -1
- package/dist/lib/renderer-capability.js +2 -2
- package/dist/lib/scene-support-height.d.ts +4 -0
- package/dist/lib/scene-support-height.d.ts.map +1 -0
- package/dist/lib/scene-support-height.js +34 -0
- package/dist/lib/scene-visibility.d.ts +6 -0
- package/dist/lib/scene-visibility.d.ts.map +1 -1
- package/dist/lib/scene-visibility.js +15 -3
- package/dist/lib/scripted-opening.d.ts +11 -0
- package/dist/lib/scripted-opening.d.ts.map +1 -0
- package/dist/lib/scripted-opening.js +20 -0
- package/dist/lib/snapshot-pipeline.d.ts +32 -2
- package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
- package/dist/lib/snapshot-pipeline.js +215 -105
- package/dist/lib/terrain-perimeter-fill.d.ts.map +1 -1
- package/dist/lib/terrain-perimeter-fill.js +22 -14
- package/dist/lib/zone-geometry.d.ts +11 -0
- package/dist/lib/zone-geometry.d.ts.map +1 -0
- package/dist/lib/zone-geometry.js +46 -0
- package/dist/store/use-item-light-pool.d.ts +14 -10
- package/dist/store/use-item-light-pool.d.ts.map +1 -1
- package/dist/store/use-item-light-pool.js +52 -26
- package/dist/store/use-viewer.d.ts +11 -0
- package/dist/store/use-viewer.d.ts.map +1 -1
- package/dist/store/use-viewer.js +13 -6
- package/dist/systems/ceiling/ceiling-system.d.ts +15 -1
- package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
- package/dist/systems/ceiling/ceiling-system.js +86 -6
- package/dist/systems/door/door-system.d.ts.map +1 -1
- package/dist/systems/door/door-system.js +73 -22
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts +3 -1
- package/dist/systems/floor-elevation/floor-elevation-system.d.ts.map +1 -1
- package/dist/systems/floor-elevation/floor-elevation-system.js +148 -5
- package/dist/systems/geometry/geometry-system.d.ts.map +1 -1
- package/dist/systems/geometry/geometry-system.js +71 -11
- package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
- package/dist/systems/interactive/interactive-system.js +40 -15
- package/dist/systems/interactive/procedural-controls.d.ts +13 -0
- package/dist/systems/interactive/procedural-controls.d.ts.map +1 -0
- package/dist/systems/interactive/procedural-controls.js +17 -0
- package/dist/systems/interactive/scripted-clips.d.ts +19 -0
- package/dist/systems/interactive/scripted-clips.d.ts.map +1 -0
- package/dist/systems/interactive/scripted-clips.js +134 -0
- package/dist/systems/item/item-system.d.ts.map +1 -1
- package/dist/systems/item/item-system.js +9 -3
- package/dist/systems/item/object-cut-invalidation.d.ts +3 -0
- package/dist/systems/item/object-cut-invalidation.d.ts.map +1 -0
- package/dist/systems/item/object-cut-invalidation.js +68 -0
- package/dist/systems/item-light/item-light-system.d.ts +1 -1
- package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
- package/dist/systems/item-light/item-light-system.js +47 -52
- package/dist/systems/level/level-system.d.ts.map +1 -1
- package/dist/systems/level/level-system.js +17 -19
- package/dist/systems/level/level-utils.d.ts +28 -1
- package/dist/systems/level/level-utils.d.ts.map +1 -1
- package/dist/systems/level/level-utils.js +36 -4
- package/dist/systems/level/shadow-only-levels.d.ts +9 -0
- package/dist/systems/level/shadow-only-levels.d.ts.map +1 -0
- package/dist/systems/level/shadow-only-levels.js +7 -0
- package/dist/systems/roof/roof-materials.d.ts +14 -2
- package/dist/systems/roof/roof-materials.d.ts.map +1 -1
- package/dist/systems/roof/roof-materials.js +54 -15
- package/dist/systems/roof/roof-system.d.ts +13 -3
- package/dist/systems/roof/roof-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-system.js +188 -13
- package/dist/systems/slab/slab-system.d.ts +1 -1
- package/dist/systems/slab/slab-system.d.ts.map +1 -1
- package/dist/systems/slab/slab-system.js +49 -19
- package/dist/systems/stair/stair-system.d.ts.map +1 -1
- package/dist/systems/stair/stair-system.js +133 -354
- package/dist/systems/wall/wall-cutout-cache.d.ts +11 -1
- package/dist/systems/wall/wall-cutout-cache.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout-cache.js +58 -20
- package/dist/systems/wall/wall-cutout.d.ts +9 -1
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout.js +46 -32
- package/dist/systems/wall/wall-finish-data.d.ts +22 -0
- package/dist/systems/wall/wall-finish-data.d.ts.map +1 -0
- package/dist/systems/wall/wall-finish-data.js +17 -0
- package/dist/systems/wall/wall-materials.d.ts +17 -3
- package/dist/systems/wall/wall-materials.d.ts.map +1 -1
- package/dist/systems/wall/wall-materials.js +109 -156
- package/dist/systems/wall/wall-system.d.ts +43 -4
- package/dist/systems/wall/wall-system.d.ts.map +1 -1
- package/dist/systems/wall/wall-system.js +601 -163
- package/dist/systems/window/window-system.d.ts +1 -1
- package/dist/systems/window/window-system.d.ts.map +1 -1
- package/dist/systems/window/window-system.js +44 -24
- package/dist/xr/presentation-context.d.ts +7 -0
- package/dist/xr/presentation-context.d.ts.map +1 -0
- package/dist/xr/presentation-context.js +10 -0
- package/package.json +6 -6
- package/dist/systems/fence/fence-system.d.ts +0 -22
- package/dist/systems/fence/fence-system.d.ts.map +0 -1
- package/dist/systems/fence/fence-system.js +0 -357
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// New kind-specific modules belong in nodes; viewer must not depend on nodes.
|
|
2
2
|
// This extends the existing viewer-owned wall cutout and material implementation.
|
|
3
|
-
import {
|
|
3
|
+
import { getEffectiveNode, getLibraryMaterialsVersion, sceneRegistry, useLiveNodeOverrides, useLiveTransforms, useScene, } from '@pascal-app/core';
|
|
4
4
|
import { Matrix4, Vector3 } from 'three';
|
|
5
5
|
import { getMaterialTextureVersion } from '../../lib/materials';
|
|
6
|
+
import { hasMaterialsForGroups } from '../../lib/pointer-events';
|
|
6
7
|
import useViewer, {} from '../../store/use-viewer';
|
|
8
|
+
import { getWallFinishRefs } from './wall-finish-data';
|
|
7
9
|
import { resolveWallMaterialVariant } from './wall-material-variant';
|
|
8
10
|
import { getHoverHighlightMaterials, getMaterialsForWall, getSelectionHighlightMaterials, } from './wall-materials';
|
|
9
11
|
export function sameMaterialArray(a, b) {
|
|
@@ -38,6 +40,9 @@ function materialsForVariant(variant, materials) {
|
|
|
38
40
|
}
|
|
39
41
|
}
|
|
40
42
|
}
|
|
43
|
+
function wallPaletteKey(mesh) {
|
|
44
|
+
return getWallFinishRefs(mesh.geometry).join('|');
|
|
45
|
+
}
|
|
41
46
|
// About 0.06 degrees: retain the previous side at edge-on poses without
|
|
42
47
|
// introducing a perceptible delay when an orbit crosses a wall's plane.
|
|
43
48
|
export const WALL_FACING_HYSTERESIS = 0.001;
|
|
@@ -59,6 +64,7 @@ export function wallFacingNegative(dot, previous) {
|
|
|
59
64
|
}
|
|
60
65
|
export class WallCutoutCache {
|
|
61
66
|
viewerStore;
|
|
67
|
+
materialResolver;
|
|
62
68
|
walls = new Map();
|
|
63
69
|
rebuilt = new Set();
|
|
64
70
|
viewer;
|
|
@@ -76,8 +82,10 @@ export class WallCutoutCache {
|
|
|
76
82
|
selected = new Set();
|
|
77
83
|
highlightKey = '';
|
|
78
84
|
transformed = new Set();
|
|
79
|
-
|
|
85
|
+
overrides = useLiveNodeOverrides.getState().overrides;
|
|
86
|
+
constructor(viewerStore = useViewer, materialResolver = getMaterialsForWall) {
|
|
80
87
|
this.viewerStore = viewerStore;
|
|
88
|
+
this.materialResolver = materialResolver;
|
|
81
89
|
}
|
|
82
90
|
subscribeLiveTransforms() {
|
|
83
91
|
return useLiveTransforms.subscribe((state, previous) => {
|
|
@@ -98,6 +106,8 @@ export class WallCutoutCache {
|
|
|
98
106
|
const libraryVersion = getLibraryMaterialsVersion();
|
|
99
107
|
const textureVersion = getMaterialTextureVersion();
|
|
100
108
|
const previous = this.viewer;
|
|
109
|
+
const overrides = useLiveNodeOverrides.getState().overrides;
|
|
110
|
+
const overridesChanged = this.overrides !== overrides;
|
|
101
111
|
const nodesChanged = this.nodes !== scene.nodes;
|
|
102
112
|
const registryChanged = this.registryRevision !== sceneRegistry.revision || this.wallCount !== wallIds.size;
|
|
103
113
|
let highlightChanged = false;
|
|
@@ -126,23 +136,25 @@ export class WallCutoutCache {
|
|
|
126
136
|
const previewId = (state) => state && state.hoverHighlightMode !== 'default' && state.hoverHighlightMode !== 'delete'
|
|
127
137
|
? state.hoveredId
|
|
128
138
|
: null;
|
|
129
|
-
const releasedPreview = previewId(previous)
|
|
139
|
+
const releasedPreview = previewId(previous) === previewId(viewer) ? null : previewId(previous);
|
|
130
140
|
this.viewer = viewer;
|
|
131
|
-
const invalidated =
|
|
141
|
+
const invalidated = overridesChanged ||
|
|
142
|
+
appearanceChanged ||
|
|
132
143
|
nodesChanged ||
|
|
133
144
|
registryChanged ||
|
|
134
145
|
this.rebuilt.size > 0 ||
|
|
135
146
|
this.transformed.size > 0 ||
|
|
136
147
|
releasedPreview !== null;
|
|
137
|
-
|
|
148
|
+
const cutaway = viewer.wallMode === 'cutaway';
|
|
149
|
+
if (!invalidated && !cutaway)
|
|
138
150
|
return;
|
|
139
151
|
camera.getWorldDirection(this.cameraDirection);
|
|
140
152
|
this.cameraTarget.copy(this.cameraDirection).add(camera.position);
|
|
141
|
-
const cameraChanged =
|
|
153
|
+
const cameraChanged = cutaway &&
|
|
142
154
|
time - this.lastUpdateTime > 0.1 &&
|
|
143
155
|
(camera.position.distanceTo(this.lastCameraPosition) > 0.5 ||
|
|
144
156
|
this.cameraTarget.distanceTo(this.lastCameraTarget) > 0.3);
|
|
145
|
-
if (!invalidated
|
|
157
|
+
if (!(invalidated || cameraChanged))
|
|
146
158
|
return;
|
|
147
159
|
if (registryChanged || nodesChanged) {
|
|
148
160
|
for (const [id, wall] of this.walls) {
|
|
@@ -188,6 +200,7 @@ export class WallCutoutCache {
|
|
|
188
200
|
assignedMaterials: undefined,
|
|
189
201
|
visibleVariant: { key: 'visible', materials: [] },
|
|
190
202
|
hiddenVariant: { key: 'invisible', materials: [] },
|
|
203
|
+
paletteKey: '',
|
|
191
204
|
};
|
|
192
205
|
this.walls.set(id, wall);
|
|
193
206
|
}
|
|
@@ -195,16 +208,20 @@ export class WallCutoutCache {
|
|
|
195
208
|
const rebuilt = this.rebuilt.has(id);
|
|
196
209
|
if (added || changed || rebuilt)
|
|
197
210
|
this.refreshNormal(wall, visited);
|
|
198
|
-
|
|
199
|
-
|
|
211
|
+
const overrideChanged = this.overrides.get(id) !== overrides.get(id);
|
|
212
|
+
wall.node = getEffectiveNode(node);
|
|
213
|
+
const repaletted = rebuilt && wallPaletteKey(wall.mesh) !== wall.paletteKey;
|
|
214
|
+
const refresh = added || appearanceChanged || overrideChanged || (nodesChanged && changed) || repaletted;
|
|
215
|
+
if (refresh)
|
|
200
216
|
this.refreshAppearance(wall);
|
|
201
217
|
if (added ||
|
|
202
218
|
appearanceChanged ||
|
|
219
|
+
overrideChanged ||
|
|
203
220
|
changed ||
|
|
204
221
|
rebuilt ||
|
|
205
222
|
releasedPreview === id ||
|
|
206
223
|
cameraChanged) {
|
|
207
|
-
this.apply(wall, viewer.wallMode,
|
|
224
|
+
this.apply(wall, viewer.wallMode, refresh);
|
|
208
225
|
}
|
|
209
226
|
}
|
|
210
227
|
}
|
|
@@ -214,6 +231,7 @@ export class WallCutoutCache {
|
|
|
214
231
|
}
|
|
215
232
|
this.rebuilt.clear();
|
|
216
233
|
this.transformed.clear();
|
|
234
|
+
this.overrides = overrides;
|
|
217
235
|
this.nodes = scene.nodes;
|
|
218
236
|
this.materials = scene.materials;
|
|
219
237
|
this.registryRevision = sceneRegistry.revision;
|
|
@@ -226,19 +244,35 @@ export class WallCutoutCache {
|
|
|
226
244
|
this.lastUpdateTime = time;
|
|
227
245
|
}
|
|
228
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* A rebuilt wall whose finish palette changed must swap materials in the same
|
|
249
|
+
* frame: its new groups already index the new palette.
|
|
250
|
+
*/
|
|
251
|
+
handleRebuilt(id) {
|
|
252
|
+
this.rebuilt.add(id);
|
|
253
|
+
const wall = this.walls.get(id);
|
|
254
|
+
const viewer = this.viewer;
|
|
255
|
+
if (!(wall && viewer) || wall.mesh !== sceneRegistry.nodes.get(id))
|
|
256
|
+
return;
|
|
257
|
+
if (wallPaletteKey(wall.mesh) === wall.paletteKey)
|
|
258
|
+
return;
|
|
259
|
+
const node = useScene.getState().nodes[id];
|
|
260
|
+
if (node?.type !== 'wall')
|
|
261
|
+
return;
|
|
262
|
+
wall.node = getEffectiveNode(node);
|
|
263
|
+
this.refreshAppearance(wall);
|
|
264
|
+
this.apply(wall, viewer.wallMode, true);
|
|
265
|
+
}
|
|
229
266
|
refreshAppearance(wall) {
|
|
230
267
|
const viewer = this.viewer;
|
|
231
268
|
const scene = useScene.getState();
|
|
232
269
|
const node = wall.node;
|
|
233
270
|
const deleted = viewer.hoverHighlightMode === 'delete' && viewer.hoveredId === node.id;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
selectionHighlighted = !getWallFaceBandConfig(node, height).enabled;
|
|
240
|
-
}
|
|
241
|
-
const materials = getMaterialsForWall(node, viewer.shading, viewer.textures, viewer.colorPreset, viewer.sceneTheme, scene.materials);
|
|
271
|
+
// Painted parts stay readable while their wall is selected for editing.
|
|
272
|
+
const selectionHighlighted = !deleted && this.selected.has(node.id) && !(node.faceRegions?.length ?? 0);
|
|
273
|
+
const finishRefs = getWallFinishRefs(wall.mesh.geometry);
|
|
274
|
+
wall.paletteKey = finishRefs.join('|');
|
|
275
|
+
const materials = this.materialResolver(node, viewer.shading, viewer.textures, viewer.colorPreset, viewer.sceneTheme, scene.materials, finishRefs);
|
|
242
276
|
const variant = (hidden) => {
|
|
243
277
|
const key = resolveWallMaterialVariant({
|
|
244
278
|
translucentMode: viewer.wallMode === 'translucent',
|
|
@@ -280,11 +314,15 @@ export class WallCutoutCache {
|
|
|
280
314
|
if (wall.mesh.userData.wallHidden !== stamp)
|
|
281
315
|
wall.mesh.userData.wallHidden = stamp;
|
|
282
316
|
const variant = hidden ? wall.hiddenVariant : wall.visibleVariant;
|
|
283
|
-
// Non-highlight hover owns a temporary material until its
|
|
317
|
+
// Non-highlight hover (a paint preview) owns a temporary material until its
|
|
318
|
+
// restore callback runs — unless the rebuilt geometry now draws a finish that
|
|
319
|
+
// array has no entry for (a click just added one): then the new palette goes
|
|
320
|
+
// on and the preview is dropped, rather than leaving groups with no material.
|
|
284
321
|
const viewer = this.viewer;
|
|
285
322
|
if (viewer.hoveredId === wall.node.id &&
|
|
286
323
|
viewer.hoverHighlightMode !== 'default' &&
|
|
287
|
-
viewer.hoverHighlightMode !== 'delete'
|
|
324
|
+
viewer.hoverHighlightMode !== 'delete' &&
|
|
325
|
+
hasMaterialsForGroups(wall.mesh)) {
|
|
288
326
|
if (refresh)
|
|
289
327
|
wall.variantKey = undefined;
|
|
290
328
|
return;
|
|
@@ -3,6 +3,7 @@ import type { Camera } from 'three';
|
|
|
3
3
|
import { type Mesh, Vector3 } from 'three/webgpu';
|
|
4
4
|
import { type WallMode } from '../../store/use-viewer';
|
|
5
5
|
import { WallCutoutCache, type WallCutoutViewerStore } from './wall-cutout-cache';
|
|
6
|
+
import { type WallMaterialsResolver } from './wall-materials';
|
|
6
7
|
export declare const WALL_CUTOUT_FRAME_PRIORITY = 0;
|
|
7
8
|
export declare function runWallCutoutFrame(cache: WallCutoutCache, { camera, clock }: {
|
|
8
9
|
camera: Camera;
|
|
@@ -19,7 +20,14 @@ export declare function runWallCutoutFrame(cache: WallCutoutCache, { camera, clo
|
|
|
19
20
|
* from the assigned material variant.
|
|
20
21
|
*/
|
|
21
22
|
export declare function getWallHideState(wallNode: WallNode, wallMesh: Mesh, wallMode: WallMode, cameraDir: Vector3): boolean;
|
|
22
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The walls as a capture draws them, until the returned function puts them back: a delete or a
|
|
25
|
+
* selection highlight taken off and, with `wholeWalls`, every wall whole whatever the wall mode.
|
|
26
|
+
* The palettes come from the renderer's own resolver, so a curtain wall keeps its glass.
|
|
27
|
+
*/
|
|
28
|
+
export declare function wallsForCapture(materialResolver: WallMaterialsResolver, viewerStore: WallCutoutViewerStore, wholeWalls: boolean): () => void;
|
|
29
|
+
export declare const WallCutout: ({ viewerStore, materialResolver, }: {
|
|
23
30
|
viewerStore?: WallCutoutViewerStore;
|
|
31
|
+
materialResolver?: WallMaterialsResolver;
|
|
24
32
|
}) => null;
|
|
25
33
|
//# sourceMappingURL=wall-cutout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wall-cutout.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-cutout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoD,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGlG,OAAO,KAAK,EAAE,MAAM,EAAY,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACjD,OAAkB,EAAE,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAEL,eAAe,EACf,KAAK,qBAAqB,EAE3B,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"wall-cutout.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-cutout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoD,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAGlG,OAAO,KAAK,EAAE,MAAM,EAAY,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACjD,OAAkB,EAAE,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAEL,eAAe,EACf,KAAK,qBAAqB,EAE3B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,kBAAkB,CAAA;AAKzB,eAAO,MAAM,0BAA0B,IAAI,CAAA;AAE3C,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EACtB,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,QAGtE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,OAAO,GACjB,OAAO,CAKT;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,gBAAgB,EAAE,qBAAqB,EACvC,WAAW,EAAE,qBAAqB,EAClC,UAAU,EAAE,OAAO,GAClB,MAAM,IAAI,CAmCZ;AAED,eAAO,MAAM,UAAU,GAAI,oCAGxB;IACD,WAAW,CAAC,EAAE,qBAAqB,CAAA;IACnC,gBAAgB,CAAC,EAAE,qBAAqB,CAAA;CACzC,SAiCA,CAAA"}
|
|
@@ -4,7 +4,8 @@ import { useEffect, useMemo } from 'react';
|
|
|
4
4
|
import { Vector3 } from 'three/webgpu';
|
|
5
5
|
import useViewer, {} from '../../store/use-viewer';
|
|
6
6
|
import { sameMaterialArray, WallCutoutCache, wallHiddenFromFacing, } from './wall-cutout-cache';
|
|
7
|
-
import {
|
|
7
|
+
import { getWallFinishRefs } from './wall-finish-data';
|
|
8
|
+
import { getMaterialsForWall, getSelectionHighlightMaterials, } from './wall-materials';
|
|
8
9
|
import { subscribeWallRebuilds } from './wall-rebuild-notifications';
|
|
9
10
|
const v = new Vector3();
|
|
10
11
|
export const WALL_CUTOUT_FRAME_PRIORITY = 0;
|
|
@@ -27,43 +28,56 @@ export function getWallHideState(wallNode, wallMesh, wallMode, cameraDir) {
|
|
|
27
28
|
wallMesh.getWorldDirection(v);
|
|
28
29
|
return wallHiddenFromFacing(wallNode, wallMode, v.dot(cameraDir) < 0);
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* The walls as a capture draws them, until the returned function puts them back: a delete or a
|
|
33
|
+
* selection highlight taken off and, with `wholeWalls`, every wall whole whatever the wall mode.
|
|
34
|
+
* The palettes come from the renderer's own resolver, so a curtain wall keeps its glass.
|
|
35
|
+
*/
|
|
36
|
+
export function wallsForCapture(materialResolver, viewerStore, wholeWalls) {
|
|
37
|
+
const snapshot = new Map();
|
|
38
|
+
const viewer = viewerStore.getState();
|
|
39
|
+
sceneRegistry.byType.wall.forEach((wallId) => {
|
|
40
|
+
const wallMesh = sceneRegistry.nodes.get(wallId);
|
|
41
|
+
if (!wallMesh)
|
|
42
|
+
return;
|
|
43
|
+
const wallNode = useScene.getState().nodes[wallId];
|
|
44
|
+
if (wallNode?.type !== 'wall')
|
|
45
|
+
return;
|
|
46
|
+
const mats = materialResolver(wallNode, viewer.shading, viewer.textures, viewer.colorPreset, viewer.sceneTheme, useScene.getState().materials, getWallFinishRefs(wallMesh.geometry));
|
|
47
|
+
const current = wallMesh.material;
|
|
48
|
+
snapshot.set(wallMesh, current);
|
|
49
|
+
if (wholeWalls || current === mats.deleteVisible) {
|
|
50
|
+
wallMesh.material = mats.visible;
|
|
51
|
+
}
|
|
52
|
+
else if (current === mats.deleteInvisible) {
|
|
53
|
+
wallMesh.material = mats.invisible;
|
|
54
|
+
}
|
|
55
|
+
else if (current === mats.deleteTranslucent ||
|
|
56
|
+
sameMaterialArray(current, getSelectionHighlightMaterials(mats.translucent))) {
|
|
57
|
+
wallMesh.material = mats.translucent;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return () => {
|
|
61
|
+
snapshot.forEach((material, mesh) => {
|
|
62
|
+
mesh.material = material;
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export const WallCutout = ({ viewerStore = useViewer, materialResolver = getMaterialsForWall, }) => {
|
|
67
|
+
const cache = useMemo(() => new WallCutoutCache(viewerStore, materialResolver), [viewerStore, materialResolver]);
|
|
68
|
+
useEffect(() => subscribeWallRebuilds((id) => cache.handleRebuilt(id)), [cache]);
|
|
33
69
|
useEffect(() => cache.subscribeLiveTransforms(), [cache]);
|
|
34
70
|
// Camera changes reach PostProcessing (1) in this frame. WallSystem (4)
|
|
35
71
|
// notifies the next frame; WallBatchSystem (5) reads this frame's stamps.
|
|
36
72
|
useFrame((state) => runWallCutoutFrame(cache, state), WALL_CUTOUT_FRAME_PRIORITY);
|
|
37
73
|
useEffect(() => {
|
|
38
|
-
|
|
39
|
-
const restoreForCapture = () => {
|
|
40
|
-
|
|
41
|
-
const wallMesh = sceneRegistry.nodes.get(wallId);
|
|
42
|
-
if (!wallMesh)
|
|
43
|
-
return;
|
|
44
|
-
const wallNode = useScene.getState().nodes[wallId];
|
|
45
|
-
if (wallNode?.type !== 'wall')
|
|
46
|
-
return;
|
|
47
|
-
const mats = getMaterialsForWall(wallNode, viewerStore.getState().shading, viewerStore.getState().textures, viewerStore.getState().colorPreset, viewerStore.getState().sceneTheme, useScene.getState().materials);
|
|
48
|
-
const current = wallMesh.material;
|
|
49
|
-
snapshot.set(wallMesh, current);
|
|
50
|
-
if (current === mats.deleteVisible) {
|
|
51
|
-
wallMesh.material = mats.visible;
|
|
52
|
-
}
|
|
53
|
-
else if (current === mats.deleteInvisible) {
|
|
54
|
-
wallMesh.material = mats.invisible;
|
|
55
|
-
}
|
|
56
|
-
else if (current === mats.deleteTranslucent ||
|
|
57
|
-
sameMaterialArray(current, getSelectionHighlightMaterials(mats.translucent))) {
|
|
58
|
-
wallMesh.material = mats.translucent;
|
|
59
|
-
}
|
|
60
|
-
});
|
|
74
|
+
let restore = null;
|
|
75
|
+
const restoreForCapture = (event) => {
|
|
76
|
+
restore = wallsForCapture(materialResolver, viewerStore, event?.wholeWalls === true);
|
|
61
77
|
};
|
|
62
78
|
const reapplyAfterCapture = () => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
});
|
|
66
|
-
snapshot.clear();
|
|
79
|
+
restore?.();
|
|
80
|
+
restore = null;
|
|
67
81
|
};
|
|
68
82
|
emitter.on('thumbnail:before-capture', restoreForCapture);
|
|
69
83
|
emitter.on('thumbnail:after-capture', reapplyAfterCapture);
|
|
@@ -71,6 +85,6 @@ export const WallCutout = ({ viewerStore = useViewer, }) => {
|
|
|
71
85
|
emitter.off('thumbnail:before-capture', restoreForCapture);
|
|
72
86
|
emitter.off('thumbnail:after-capture', reapplyAfterCapture);
|
|
73
87
|
};
|
|
74
|
-
}, [viewerStore]);
|
|
88
|
+
}, [viewerStore, materialResolver]);
|
|
75
89
|
return null;
|
|
76
90
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BufferGeometry } from 'three';
|
|
2
|
+
/** A run of one face's base, in wall-local x (m) and local y. */
|
|
3
|
+
export type WallFaceBaseRun = {
|
|
4
|
+
start: number;
|
|
5
|
+
end: number;
|
|
6
|
+
y: number;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* What the wall's material array and the paint resolver need from a build: the
|
|
10
|
+
* finish refs behind material indices 3.. and each face's base runs (null when
|
|
11
|
+
* both faces stand on the wall's own base).
|
|
12
|
+
*/
|
|
13
|
+
export type WallFinishGeometryData = {
|
|
14
|
+
refs: readonly string[];
|
|
15
|
+
faceBase: Record<'a' | 'b', WallFaceBaseRun[]> | null;
|
|
16
|
+
};
|
|
17
|
+
export declare function getWallFinishData(geometry: BufferGeometry | undefined | null): WallFinishGeometryData | undefined;
|
|
18
|
+
/** Finish refs a built wall geometry's material indices 3.. point at. */
|
|
19
|
+
export declare function getWallFinishRefs(geometry: BufferGeometry | undefined | null): readonly string[];
|
|
20
|
+
/** Local y of a face's base at wall-local station `x` (0 when the faces share the wall base). */
|
|
21
|
+
export declare function getWallFaceBaseAt(data: Pick<WallFinishGeometryData, 'faceBase'> | undefined, face: 'a' | 'b', x: number): number;
|
|
22
|
+
//# sourceMappingURL=wall-finish-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wall-finish-data.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-finish-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAE3C,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvE;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAC,GAAG,GAAG,GAAG,EAAE,eAAe,EAAE,CAAC,GAAG,IAAI,CAAA;CACtD,CAAA;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,GAC1C,sBAAsB,GAAG,SAAS,CAEpC;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,MAAM,EAAE,CAEhG;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,CAAC,sBAAsB,EAAE,UAAU,CAAC,GAAG,SAAS,EAC1D,IAAI,EAAE,GAAG,GAAG,GAAG,EACf,CAAC,EAAE,MAAM,GACR,MAAM,CAKR"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function getWallFinishData(geometry) {
|
|
2
|
+
return geometry?.userData.wallFinish;
|
|
3
|
+
}
|
|
4
|
+
/** Finish refs a built wall geometry's material indices 3.. point at. */
|
|
5
|
+
export function getWallFinishRefs(geometry) {
|
|
6
|
+
return getWallFinishData(geometry)?.refs ?? [];
|
|
7
|
+
}
|
|
8
|
+
/** Local y of a face's base at wall-local station `x` (0 when the faces share the wall base). */
|
|
9
|
+
export function getWallFaceBaseAt(data, face, x) {
|
|
10
|
+
const runs = data?.faceBase?.[face];
|
|
11
|
+
if (!runs?.length)
|
|
12
|
+
return 0;
|
|
13
|
+
for (const run of runs)
|
|
14
|
+
if (x >= run.start && x < run.end)
|
|
15
|
+
return run.y;
|
|
16
|
+
return x < runs[0].start ? runs[0].y : runs.at(-1).y;
|
|
17
|
+
}
|
|
@@ -11,7 +11,16 @@ export interface WallMaterials {
|
|
|
11
11
|
deleteInvisible: WallMaterialArray;
|
|
12
12
|
deleteTranslucent: WallMaterialArray;
|
|
13
13
|
materialHash: string;
|
|
14
|
+
ownedVisible?: Material[];
|
|
14
15
|
}
|
|
16
|
+
export type WallMaterialOverride = {
|
|
17
|
+
hash: string;
|
|
18
|
+
create: () => {
|
|
19
|
+
visible: WallMaterialArray;
|
|
20
|
+
owned?: Material[];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export type WallMaterialsResolver = (wallNode: WallNode, shading?: RenderShading, textures?: boolean, colorPreset?: ColorPreset, sceneTheme?: string, sceneMaterials?: SceneMaterials, finishRefs?: readonly string[]) => WallMaterials;
|
|
15
24
|
/** Lazy light-emissive selection variant of a wall's material array (keeps texture). */
|
|
16
25
|
export declare function getSelectionHighlightMaterials(materials: WallMaterialArray): WallMaterialArray;
|
|
17
26
|
/**
|
|
@@ -20,8 +29,13 @@ export declare function getSelectionHighlightMaterials(materials: WallMaterialAr
|
|
|
20
29
|
* film so the wall the click would select reads under the cursor).
|
|
21
30
|
*/
|
|
22
31
|
export declare function getHoverHighlightMaterials(materials: WallMaterialArray): WallMaterialArray;
|
|
23
|
-
export declare function getWallMaterialHash(wallNode: WallNode, shading: RenderShading, sceneMaterials?: SceneMaterials): string;
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
export declare function getWallMaterialHash(wallNode: WallNode, shading: RenderShading, sceneMaterials?: SceneMaterials, finishRefs?: readonly string[], overrideHash?: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* A wall's material palette: 0 caps/edges (themed role), 1 face a, 2 face b,
|
|
35
|
+
* then one entry per `finishRefs` — the region and room finishes the built
|
|
36
|
+
* geometry's groups point at (`getWallFinishRefs(mesh.geometry)`).
|
|
37
|
+
*/
|
|
38
|
+
export declare function getMaterialsForWall(wallNode: WallNode, shading?: RenderShading, textures?: boolean, colorPreset?: ColorPreset, sceneTheme?: string, sceneMaterials?: SceneMaterials, finishRefs?: readonly string[], override?: WallMaterialOverride): WallMaterials;
|
|
39
|
+
export declare function getVisibleWallMaterials(wallNode: WallNode, shading?: RenderShading, textures?: boolean, colorPreset?: ColorPreset, sceneTheme?: string, sceneMaterials?: SceneMaterials, finishRefs?: readonly string[]): WallMaterialArray;
|
|
26
40
|
export {};
|
|
27
41
|
//# sourceMappingURL=wall-materials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wall-materials.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-materials.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"wall-materials.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-materials.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,aAAa,EAClB,KAAK,eAAe,EAGpB,KAAK,QAAQ,EAGd,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAA;AAG5C,OAAO,EAEL,KAAK,WAAW,EAMhB,KAAK,aAAa,EAInB,MAAM,qBAAqB,CAAA;AAE5B,KAAK,cAAc,GAAG,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,GAAG,SAAS,CAAA;AAexE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,EAAE,CAAA;AAE1C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,iBAAiB,CAAA;IAC1B,SAAS,EAAE,iBAAiB,CAAA;IAC5B,WAAW,EAAE,iBAAiB,CAAA;IAC9B,aAAa,EAAE,iBAAiB,CAAA;IAChC,eAAe,EAAE,iBAAiB,CAAA;IAClC,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAA;CAC1B;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM;QAAE,OAAO,EAAE,iBAAiB,CAAC;QAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;KAAE,CAAA;CACjE,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,CAClC,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,aAAa,EACvB,QAAQ,CAAC,EAAE,OAAO,EAClB,WAAW,CAAC,EAAE,WAAW,EACzB,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,cAAc,EAC/B,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,KAC3B,aAAa,CAAA;AA2QlB,wFAAwF;AACxF,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,iBAAiB,GAAG,iBAAiB,CAS9F;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,iBAAiB,GAAG,iBAAiB,CAS1F;AA4DD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,aAAa,EACtB,cAAc,CAAC,EAAE,cAAc,EAC/B,UAAU,GAAE,SAAS,MAAM,EAAO,EAClC,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAQR;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,aAA0B,EACnC,QAAQ,UAAO,EACf,WAAW,GAAE,WAAoB,EACjC,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,cAAc,EAC/B,UAAU,GAAE,SAAS,MAAM,EAAO,EAClC,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,aAAa,CAmFf;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,aAA0B,EACnC,QAAQ,UAAO,EACf,WAAW,GAAE,WAAoB,EACjC,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,cAAc,EAC/B,UAAU,GAAE,SAAS,MAAM,EAAO,GACjC,iBAAiB,CAUnB"}
|