@pascal-app/viewer 1.0.4 → 1.0.6

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.
Files changed (183) hide show
  1. package/dist/capture/capture-runtime.js +1 -1
  2. package/dist/components/error-boundary.d.ts.map +1 -1
  3. package/dist/components/renderers/node-renderer.d.ts +1 -1
  4. package/dist/components/renderers/node-renderer.d.ts.map +1 -1
  5. package/dist/components/renderers/node-renderer.js +4 -1
  6. package/dist/components/renderers/parametric-node-renderer.d.ts.map +1 -1
  7. package/dist/components/viewer/bvh-ecctrl.d.ts.map +1 -1
  8. package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
  9. package/dist/components/viewer/glb-interactive.js +1 -1
  10. package/dist/components/viewer/glb-reference-nodes.js +1 -1
  11. package/dist/components/viewer/glb-replace-instances.js +1 -1
  12. package/dist/components/viewer/glb-scene.d.ts.map +1 -1
  13. package/dist/components/viewer/glb-scene.js +2 -3
  14. package/dist/components/viewer/glb-walkthrough-controller.js +1 -1
  15. package/dist/components/viewer/index.d.ts +10 -1
  16. package/dist/components/viewer/index.d.ts.map +1 -1
  17. package/dist/components/viewer/index.js +28 -12
  18. package/dist/components/viewer/lights.d.ts.map +1 -1
  19. package/dist/components/viewer/lights.js +107 -21
  20. package/dist/components/viewer/perf-panel.d.ts.map +1 -1
  21. package/dist/components/viewer/perf-panel.js +1 -1
  22. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  23. package/dist/components/viewer/post-processing.js +96 -33
  24. package/dist/components/viewer/registered-systems.js +1 -1
  25. package/dist/components/viewer/scene-bvh.d.ts.map +1 -1
  26. package/dist/components/viewer/scene-bvh.js +1 -1
  27. package/dist/components/viewer/scene-environment.d.ts.map +1 -1
  28. package/dist/components/viewer/scene-environment.js +31 -11
  29. package/dist/components/viewer/selection-manager.js +15 -7
  30. package/dist/components/viewer/underground-ambiance.d.ts +9 -0
  31. package/dist/components/viewer/underground-ambiance.d.ts.map +1 -0
  32. package/dist/components/viewer/underground-ambiance.js +105 -0
  33. package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
  34. package/dist/components/viewer/viewer-camera.js +1 -1
  35. package/dist/components/viewer/viewer-presentations.d.ts.map +1 -1
  36. package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
  37. package/dist/hooks/use-gltf-ktx2.js +2 -0
  38. package/dist/hooks/use-node-events.d.ts.map +1 -1
  39. package/dist/index.d.ts +16 -7
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +16 -7
  42. package/dist/lib/backdrop.d.ts +17 -0
  43. package/dist/lib/backdrop.d.ts.map +1 -1
  44. package/dist/lib/backdrop.js +18 -1
  45. package/dist/lib/construction-dust.d.ts +57 -0
  46. package/dist/lib/construction-dust.d.ts.map +1 -0
  47. package/dist/lib/construction-dust.js +187 -0
  48. package/dist/lib/csg-utils.js +1 -1
  49. package/dist/lib/foundation-materials.d.ts +26 -0
  50. package/dist/lib/foundation-materials.d.ts.map +1 -0
  51. package/dist/lib/foundation-materials.js +65 -0
  52. package/dist/lib/gltf-unlit.d.ts +10 -0
  53. package/dist/lib/gltf-unlit.d.ts.map +1 -0
  54. package/dist/lib/gltf-unlit.js +23 -0
  55. package/dist/lib/ground-window.d.ts +33 -0
  56. package/dist/lib/ground-window.d.ts.map +1 -0
  57. package/dist/lib/ground-window.js +114 -0
  58. package/dist/lib/hero-pose.d.ts +1 -1
  59. package/dist/lib/hero-pose.d.ts.map +1 -1
  60. package/dist/lib/ink-edges.d.ts +2 -1
  61. package/dist/lib/ink-edges.d.ts.map +1 -1
  62. package/dist/lib/ktx2-loader.d.ts +7 -0
  63. package/dist/lib/ktx2-loader.d.ts.map +1 -1
  64. package/dist/lib/ktx2-loader.js +35 -0
  65. package/dist/lib/layer-pass.d.ts.map +1 -1
  66. package/dist/lib/layers.d.ts +11 -7
  67. package/dist/lib/layers.d.ts.map +1 -1
  68. package/dist/lib/layers.js +16 -6
  69. package/dist/lib/materials.d.ts +5 -0
  70. package/dist/lib/materials.d.ts.map +1 -1
  71. package/dist/lib/materials.js +34 -4
  72. package/dist/lib/merged-outline-node.d.ts +5 -0
  73. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  74. package/dist/lib/merged-outline-node.js +80 -2
  75. package/dist/lib/pointer-events.d.ts +20 -4
  76. package/dist/lib/pointer-events.d.ts.map +1 -1
  77. package/dist/lib/pointer-events.js +78 -14
  78. package/dist/lib/post-processing-resources.d.ts.map +1 -1
  79. package/dist/lib/reveal-candidates.d.ts +80 -0
  80. package/dist/lib/reveal-candidates.d.ts.map +1 -0
  81. package/dist/lib/reveal-candidates.js +524 -0
  82. package/dist/lib/reveal-ghost.d.ts +9 -0
  83. package/dist/lib/reveal-ghost.d.ts.map +1 -0
  84. package/dist/lib/reveal-ghost.js +62 -0
  85. package/dist/lib/reveal-pending.d.ts +12 -0
  86. package/dist/lib/reveal-pending.d.ts.map +1 -0
  87. package/dist/lib/reveal-pending.js +12 -0
  88. package/dist/lib/reveal-pose.d.ts +70 -0
  89. package/dist/lib/reveal-pose.d.ts.map +1 -0
  90. package/dist/lib/reveal-pose.js +248 -0
  91. package/dist/lib/reveal-schedule.d.ts +208 -0
  92. package/dist/lib/reveal-schedule.d.ts.map +1 -0
  93. package/dist/lib/reveal-schedule.js +410 -0
  94. package/dist/lib/reveal-texture-scale.d.ts +5 -0
  95. package/dist/lib/reveal-texture-scale.d.ts.map +1 -0
  96. package/dist/lib/reveal-texture-scale.js +113 -0
  97. package/dist/lib/reveal-windows.d.ts +23 -0
  98. package/dist/lib/reveal-windows.d.ts.map +1 -0
  99. package/dist/lib/reveal-windows.js +31 -0
  100. package/dist/lib/reveal-wipe.d.ts +71 -0
  101. package/dist/lib/reveal-wipe.d.ts.map +1 -0
  102. package/dist/lib/reveal-wipe.js +105 -0
  103. package/dist/lib/scene-pass-mrt.d.ts +12 -0
  104. package/dist/lib/scene-pass-mrt.d.ts.map +1 -0
  105. package/dist/lib/scene-pass-mrt.js +23 -0
  106. package/dist/lib/scene-themes.d.ts +30 -8
  107. package/dist/lib/scene-themes.d.ts.map +1 -1
  108. package/dist/lib/scene-themes.js +36 -0
  109. package/dist/lib/scene-visibility.d.ts +11 -1
  110. package/dist/lib/scene-visibility.d.ts.map +1 -1
  111. package/dist/lib/scene-visibility.js +38 -0
  112. package/dist/lib/site-surfaces.d.ts +32 -0
  113. package/dist/lib/site-surfaces.d.ts.map +1 -0
  114. package/dist/lib/site-surfaces.js +70 -0
  115. package/dist/lib/snapshot-pipeline.d.ts +2 -1
  116. package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
  117. package/dist/lib/snapshot-pipeline.js +35 -15
  118. package/dist/lib/tsl-compat.d.ts +2 -2
  119. package/dist/lib/tsl-compat.d.ts.map +1 -1
  120. package/dist/lib/underground-ambiance.d.ts +168 -0
  121. package/dist/lib/underground-ambiance.d.ts.map +1 -0
  122. package/dist/lib/underground-ambiance.js +334 -0
  123. package/dist/store/use-viewer.d.ts +184 -27
  124. package/dist/store/use-viewer.d.ts.map +1 -1
  125. package/dist/store/use-viewer.js +155 -19
  126. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  127. package/dist/systems/ceiling/ceiling-system.js +2 -0
  128. package/dist/systems/construction-reveal/construction-dust.d.ts +16 -0
  129. package/dist/systems/construction-reveal/construction-dust.d.ts.map +1 -0
  130. package/dist/systems/construction-reveal/construction-dust.js +92 -0
  131. package/dist/systems/construction-reveal/construction-reveal.d.ts +276 -0
  132. package/dist/systems/construction-reveal/construction-reveal.d.ts.map +1 -0
  133. package/dist/systems/construction-reveal/construction-reveal.js +2383 -0
  134. package/dist/systems/construction-reveal/dust-material.d.ts +10 -0
  135. package/dist/systems/construction-reveal/dust-material.d.ts.map +1 -0
  136. package/dist/systems/construction-reveal/dust-material.js +17 -0
  137. package/dist/systems/construction-reveal/ghost-dress.d.ts +10 -0
  138. package/dist/systems/construction-reveal/ghost-dress.d.ts.map +1 -0
  139. package/dist/systems/construction-reveal/ghost-dress.js +24 -0
  140. package/dist/systems/elevator/elevator-interaction-system.d.ts +7 -0
  141. package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -1
  142. package/dist/systems/elevator/elevator-interaction-system.js +18 -1
  143. package/dist/systems/geometry/geometry-system.d.ts.map +1 -1
  144. package/dist/systems/interactive/control-widget.d.ts.map +1 -1
  145. package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
  146. package/dist/systems/interactive/interactive-system.js +16 -6
  147. package/dist/systems/interactive/scripted-clips.js +1 -1
  148. package/dist/systems/item-light/item-light-system.js +1 -1
  149. package/dist/systems/level/level-hold.d.ts +4 -0
  150. package/dist/systems/level/level-hold.d.ts.map +1 -0
  151. package/dist/systems/level/level-hold.js +14 -0
  152. package/dist/systems/level/level-system.d.ts.map +1 -1
  153. package/dist/systems/level/level-system.js +16 -1
  154. package/dist/systems/level/level-utils.d.ts +13 -3
  155. package/dist/systems/level/level-utils.d.ts.map +1 -1
  156. package/dist/systems/level/level-utils.js +56 -8
  157. package/dist/systems/roof/__fixtures__/roof-plane-cases.d.ts +103 -0
  158. package/dist/systems/roof/__fixtures__/roof-plane-cases.d.ts.map +1 -0
  159. package/dist/systems/roof/__fixtures__/roof-plane-cases.js +317 -0
  160. package/dist/systems/roof/roof-materials.d.ts +4 -2
  161. package/dist/systems/roof/roof-materials.d.ts.map +1 -1
  162. package/dist/systems/roof/roof-materials.js +18 -24
  163. package/dist/systems/roof/roof-system.d.ts +8 -1
  164. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  165. package/dist/systems/roof/roof-system.js +195 -45
  166. package/dist/systems/wall/wall-cutout-cache.d.ts +32 -3
  167. package/dist/systems/wall/wall-cutout-cache.d.ts.map +1 -1
  168. package/dist/systems/wall/wall-cutout-cache.js +95 -2
  169. package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
  170. package/dist/systems/wall/wall-material-variant.d.ts.map +1 -1
  171. package/dist/systems/wall/wall-materials.d.ts.map +1 -1
  172. package/dist/systems/wall/wall-materials.js +39 -4
  173. package/dist/systems/wall/wall-placeholder-sweep.d.ts.map +1 -1
  174. package/dist/systems/wall/wall-system.d.ts +5 -0
  175. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  176. package/dist/systems/wall/wall-system.js +42 -19
  177. package/dist/systems/window/corner-frame.d.ts +10 -0
  178. package/dist/systems/window/corner-frame.d.ts.map +1 -0
  179. package/dist/systems/window/corner-frame.js +17 -0
  180. package/dist/systems/window/window-system.d.ts +1 -1
  181. package/dist/systems/window/window-system.d.ts.map +1 -1
  182. package/dist/systems/window/window-system.js +31 -6
  183. package/package.json +8 -8
@@ -124,6 +124,10 @@ export class MergedOutlineNode extends TempNode {
124
124
  _proxiesA = new Map();
125
125
  _proxiesB = new Map();
126
126
  _proxyMaskMaterials = new WeakMap();
127
+ _cutoutMasksA = new Map();
128
+ _cutoutMasksB = new Map();
129
+ _usedCutoutMasksA = new Set();
130
+ _usedCutoutMasksB = new Set();
127
131
  _maskSceneA = new Scene();
128
132
  _maskSceneB = new Scene();
129
133
  // Tracks whether either group rendered last frame. We use this to decide
@@ -267,7 +271,23 @@ export class MergedOutlineNode extends TempNode {
267
271
  this._buildCache(this.secondaryObjects, this._cacheB);
268
272
  const useProxiesA = this._syncProxies(this._cacheA, this._proxiesA, this._maskSceneA);
269
273
  const useProxiesB = this._syncProxies(this._cacheB, this._proxiesB, this._maskSceneB);
274
+ this._usedCutoutMasksA.clear();
275
+ this._usedCutoutMasksB.clear();
276
+ for (const [cache, used] of [
277
+ [this._cacheA, this._usedCutoutMasksA],
278
+ [this._cacheB, this._usedCutoutMasksB],
279
+ ]) {
280
+ for (const object of cache) {
281
+ if (!(object instanceof Mesh))
282
+ continue;
283
+ const materials = Array.isArray(object.material) ? object.material : [object.material];
284
+ for (const source of materials)
285
+ if (source?.alphaTest > 0)
286
+ used.add(source);
287
+ }
288
+ }
270
289
  if (!hasAny) {
290
+ this._pruneCutoutMasks();
271
291
  RendererUtils.restoreRendererAndSceneState(renderer, scene, _rendererState);
272
292
  return;
273
293
  }
@@ -300,6 +320,7 @@ export class MergedOutlineNode extends TempNode {
300
320
  this._runEdgePipeline(renderer, 'A');
301
321
  if (hasSecondary)
302
322
  this._runEdgePipeline(renderer, 'B');
323
+ this._pruneCutoutMasks();
303
324
  RendererUtils.restoreRendererAndSceneState(renderer, scene, _rendererState);
304
325
  }
305
326
  _renderMask(renderer, group, useProxies) {
@@ -309,6 +330,8 @@ export class MergedOutlineNode extends TempNode {
309
330
  const maskScene = isA ? this._maskSceneA : this._maskSceneB;
310
331
  const material = isA ? this._prepareMaskMatA : this._prepareMaskMatB;
311
332
  const spriteMaterial = isA ? this._prepareMaskSpriteMatA : this._prepareMaskSpriteMatB;
333
+ const cutoutMasks = isA ? this._cutoutMasksA : this._cutoutMasksB;
334
+ const usedCutoutMasks = isA ? this._usedCutoutMasksA : this._usedCutoutMasksB;
312
335
  if (useProxies) {
313
336
  for (const [source, proxy] of proxies)
314
337
  proxy.matrixWorld.copy(source.matrixWorld);
@@ -316,11 +339,39 @@ export class MergedOutlineNode extends TempNode {
316
339
  renderer.setRenderTarget((isA ? this._groupA : this._groupB).maskBuffer);
317
340
  // Keep source materials on proxies for material visibility and geometry
318
341
  // groups; substitute only at submission, just like the full-scene path.
319
- renderer.setRenderObjectFunction((obj, sc, cam, geo, _mat, grp, lights, clip) => {
342
+ renderer.setRenderObjectFunction((obj, sc, cam, geo, sourceMaterial, grp, lights, clip) => {
320
343
  if (!hasDrawableGeometry(geo))
321
344
  return;
322
345
  if (useProxies || cache.has(obj)) {
323
346
  let maskMaterial = obj.isSprite ? spriteMaterial : material;
347
+ if (!obj.isSprite && sourceMaterial?.alphaTest > 0) {
348
+ let cutoutMask = cutoutMasks.get(sourceMaterial);
349
+ const opacityNode = sourceMaterial.opacityNode ??
350
+ (sourceMaterial.map
351
+ ? cutoutMask?.userData.sourceMap === sourceMaterial.map
352
+ ? cutoutMask.opacityNode
353
+ : texture(sourceMaterial.map).a
354
+ : null);
355
+ if (opacityNode) {
356
+ if (!cutoutMask) {
357
+ cutoutMask = material.clone();
358
+ cutoutMasks.set(sourceMaterial, cutoutMask);
359
+ }
360
+ const positionNode = sourceMaterial.positionNode ?? null;
361
+ const changed = cutoutMask.opacityNode !== opacityNode ||
362
+ cutoutMask.positionNode !== positionNode ||
363
+ cutoutMask.side !== sourceMaterial.side;
364
+ cutoutMask.opacityNode = opacityNode;
365
+ cutoutMask.positionNode = positionNode;
366
+ cutoutMask.alphaTest = sourceMaterial.alphaTest;
367
+ cutoutMask.side = sourceMaterial.side;
368
+ cutoutMask.userData.sourceMap = sourceMaterial.map;
369
+ if (changed)
370
+ cutoutMask.needsUpdate = true;
371
+ maskMaterial = cutoutMask;
372
+ usedCutoutMasks.add(sourceMaterial);
373
+ }
374
+ }
324
375
  if (useProxies) {
325
376
  let ownedMaterial = this._proxyMaskMaterials.get(obj);
326
377
  if (!ownedMaterial) {
@@ -329,8 +380,16 @@ export class MergedOutlineNode extends TempNode {
329
380
  ownedMaterial = maskMaterial.clone();
330
381
  this._proxyMaskMaterials.set(obj, ownedMaterial);
331
382
  }
332
- if (ownedMaterial.colorNode !== maskMaterial.colorNode) {
383
+ if (ownedMaterial.colorNode !== maskMaterial.colorNode ||
384
+ ownedMaterial.opacityNode !== maskMaterial.opacityNode ||
385
+ ownedMaterial.positionNode !== maskMaterial.positionNode ||
386
+ ownedMaterial.alphaTest !== maskMaterial.alphaTest ||
387
+ ownedMaterial.side !== maskMaterial.side) {
333
388
  ownedMaterial.colorNode = maskMaterial.colorNode;
389
+ ownedMaterial.opacityNode = maskMaterial.opacityNode;
390
+ ownedMaterial.positionNode = maskMaterial.positionNode;
391
+ ownedMaterial.alphaTest = maskMaterial.alphaTest;
392
+ ownedMaterial.side = maskMaterial.side;
334
393
  ownedMaterial.needsUpdate = true;
335
394
  }
336
395
  maskMaterial = ownedMaterial;
@@ -413,6 +472,19 @@ export class MergedOutlineNode extends TempNode {
413
472
  this._proxyMaskMaterials.get(proxy)?.dispose();
414
473
  this._proxyMaskMaterials.delete(proxy);
415
474
  }
475
+ _pruneCutoutMasks() {
476
+ for (const [materials, used] of [
477
+ [this._cutoutMasksA, this._usedCutoutMasksA],
478
+ [this._cutoutMasksB, this._usedCutoutMasksB],
479
+ ]) {
480
+ for (const [source, mask] of materials) {
481
+ if (used.has(source))
482
+ continue;
483
+ mask.dispose();
484
+ materials.delete(source);
485
+ }
486
+ }
487
+ }
416
488
  _runEdgePipeline(renderer, group) {
417
489
  const isA = group === 'A';
418
490
  const g = isA ? this._groupA : this._groupB;
@@ -586,6 +658,12 @@ export class MergedOutlineNode extends TempNode {
586
658
  this._proxiesB.clear();
587
659
  this._cacheA.clear();
588
660
  this._cacheB.clear();
661
+ for (const mask of this._cutoutMasksA.values())
662
+ mask.dispose();
663
+ for (const mask of this._cutoutMasksB.values())
664
+ mask.dispose();
665
+ this._cutoutMasksA.clear();
666
+ this._cutoutMasksB.clear();
589
667
  this._depthRT.dispose();
590
668
  this._groupA.dispose();
591
669
  this._groupB.dispose();
@@ -1,15 +1,31 @@
1
1
  import { events as createWebEvents, type EventManager, type RootStore } from '@react-three/fiber';
2
2
  import * as THREE from 'three';
3
+ /** A diagnostic the viewer hands its host, shaped for an error reporter's breadcrumb trail. */
4
+ export type ViewerBreadcrumb = {
5
+ category: string;
6
+ message: string;
7
+ level: 'info' | 'warning';
8
+ data?: Record<string, unknown>;
9
+ };
10
+ export type ViewerBreadcrumbHandler = (breadcrumb: ViewerBreadcrumb) => void;
3
11
  /** Opt in only when the raycast appends hits without reading prior hits or mutating scene/query state. */
4
12
  export declare function markPureRaycast<T extends THREE.Object3D['raycast']>(raycast: T): T;
5
- export declare function choosePointerEvents(search?: string): typeof createWebEvents;
13
+ export declare function choosePointerEvents(search?: string, onBreadcrumb?: ViewerBreadcrumbHandler): typeof createWebEvents;
6
14
  /**
7
15
  * Whether a mesh has a material for everything a raycast reads: three indexes
8
16
  * a material array by each geometry group, and one with no entry throws on
9
17
  * `material.side`. A mesh caught mid-swap (a preview restored an older array
10
18
  * over a rebuilt geometry) is skipped for this move instead of taking the whole
11
- * pointer event down; its children are still tested.
19
+ * pointer event down; its children are still tested. `material` asks the same of
20
+ * an array the mesh would wear.
12
21
  */
13
- export declare function hasMaterialsForGroups(object: THREE.Object3D): boolean;
14
- export declare function createPascalPointerEvents(store: RootStore): EventManager<HTMLElement>;
22
+ export declare function hasMaterialsForGroups(object: THREE.Object3D, material?: THREE.Material | THREE.Material[] | undefined): boolean;
23
+ type SkipInvalidMaterial = (object: THREE.Object3D) => void;
24
+ /**
25
+ * Three's recursive `intersectObject`, skipping meshes `hasMaterialsForGroups`
26
+ * rejects. A raycaster with its own `intersectObject` is asked directly.
27
+ */
28
+ export declare function intersectDrawable(raycaster: THREE.Raycaster, object: THREE.Object3D, skip: SkipInvalidMaterial): THREE.Intersection[];
29
+ export declare function createPascalPointerEvents(store: RootStore, onBreadcrumb?: ViewerBreadcrumbHandler): EventManager<HTMLElement>;
30
+ export {};
15
31
  //# sourceMappingURL=pointer-events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pointer-events.d.ts","sourceRoot":"","sources":["../../src/lib/pointer-events.ts"],"names":[],"mappings":"AA6BA,OAAO,EACL,MAAM,IAAI,eAAe,EAGzB,KAAK,YAAY,EAMjB,KAAK,SAAS,EAEf,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqC9B,0GAA0G;AAC1G,wBAAgB,eAAe,CAAC,CAAC,SAAS,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAGlF;AAYD,wBAAgB,mBAAmB,CACjC,MAAM,SAA8D,GACnE,OAAO,eAAe,CAIxB;AAiED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,GAAG,OAAO,CAUrE;AAkHD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,GAAG,YAAY,CAAC,WAAW,CAAC,CAmBrF"}
1
+ {"version":3,"file":"pointer-events.d.ts","sourceRoot":"","sources":["../../src/lib/pointer-events.ts"],"names":[],"mappings":"AA8BA,OAAO,EACL,MAAM,IAAI,eAAe,EAGzB,KAAK,YAAY,EAMjB,KAAK,SAAS,EAEf,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,+FAA+F;AAC/F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAA;AAmC5E,0GAA0G;AAC1G,wBAAgB,eAAe,CAAC,CAAC,SAAS,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAGlF;AAYD,wBAAgB,mBAAmB,CACjC,MAAM,SAA8D,EACpE,YAAY,CAAC,EAAE,uBAAuB,GACrC,OAAO,eAAe,CAIxB;AAiED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,KAAK,CAAC,QAAQ,EACtB,QAAQ,GAAE,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE,GAAG,SAA2C,GACxF,OAAO,CAST;AAMD,KAAK,mBAAmB,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAA;AAmC3D;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,MAAM,EAAE,KAAK,CAAC,QAAQ,EACtB,IAAI,EAAE,mBAAmB,GACxB,KAAK,CAAC,YAAY,EAAE,CAiBtB;AA+GD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,EAChB,YAAY,CAAC,EAAE,uBAAuB,GACrC,YAAY,CAAC,WAAW,CAAC,CAmB3B"}
@@ -21,11 +21,12 @@
21
21
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
22
  * SOFTWARE.
23
23
  *
24
- * Vendored from R3F 9.8.1:
25
- * https://raw.githubusercontent.com/pmndrs/react-three-fiber/v9.8.1/packages/fiber/src/core/events.ts
24
+ * Vendored from R3F 9.8.2:
25
+ * https://raw.githubusercontent.com/pmndrs/react-three-fiber/v9.8.2/packages/fiber/src/core/events.ts
26
26
  * Ray collection is cached; camera-drag moves are throttled before stock dispatch.
27
27
  * The throttle is a vendored-manager policy; dev ?stockEvents uses untouched R3F.
28
28
  */
29
+ import { sceneRegistry, useScene } from '@pascal-app/core';
29
30
  import { events as createWebEvents, getRootState, } from '@react-three/fiber';
30
31
  import * as THREE from 'three';
31
32
  import { acceleratedRaycast } from 'three-mesh-bvh';
@@ -61,10 +62,10 @@ function isSupportedRaycast(raycast) {
61
62
  supportedRaycasts.has(raycast) ||
62
63
  raycast[pureRaycast] === true);
63
64
  }
64
- export function choosePointerEvents(search = typeof window !== 'undefined' ? window.location.search : '') {
65
+ export function choosePointerEvents(search = typeof window !== 'undefined' ? window.location.search : '', onBreadcrumb) {
65
66
  return process.env.NODE_ENV !== 'production' && new URLSearchParams(search).has('stockEvents')
66
67
  ? createWebEvents
67
- : createPascalPointerEvents;
68
+ : (store) => createPascalPointerEvents(store, onBreadcrumb);
68
69
  }
69
70
  function querySnapshot(raycaster) {
70
71
  if (Object.getPrototypeOf(raycaster) !== THREE.Raycaster.prototype ||
@@ -117,13 +118,13 @@ function querySnapshot(raycaster) {
117
118
  * a material array by each geometry group, and one with no entry throws on
118
119
  * `material.side`. A mesh caught mid-swap (a preview restored an older array
119
120
  * over a rebuilt geometry) is skipped for this move instead of taking the whole
120
- * pointer event down; its children are still tested.
121
+ * pointer event down; its children are still tested. `material` asks the same of
122
+ * an array the mesh would wear.
121
123
  */
122
- export function hasMaterialsForGroups(object) {
124
+ export function hasMaterialsForGroups(object, material = object.material) {
123
125
  const mesh = object;
124
126
  if (!mesh.isMesh)
125
127
  return true;
126
- const material = mesh.material;
127
128
  if (!material)
128
129
  return false;
129
130
  if (!Array.isArray(material))
@@ -137,7 +138,67 @@ export function hasMaterialsForGroups(object) {
137
138
  function distanceOrder(a, b) {
138
139
  return a.distance - b.distance;
139
140
  }
140
- function createCachedRaycast() {
141
+ /** The scene node `object` draws for: itself or its nearest registered ancestor. */
142
+ function owningNode(object) {
143
+ const owners = new Map();
144
+ for (const [id, registered] of sceneRegistry.nodes)
145
+ owners.set(registered, id);
146
+ for (let at = object; at; at = at.parent) {
147
+ const id = owners.get(at);
148
+ if (id === undefined)
149
+ continue;
150
+ const node = useScene.getState().nodes[id];
151
+ return { id, type: node?.type ?? null };
152
+ }
153
+ return null;
154
+ }
155
+ /**
156
+ * Reports each mesh a pointer raycast skips for groups with no material, once
157
+ * per material it wears: pointer moves would otherwise repeat it every frame.
158
+ */
159
+ function createInvalidMaterialReporter(onBreadcrumb) {
160
+ const reported = new WeakMap();
161
+ return (object) => {
162
+ const material = object.material;
163
+ if (!onBreadcrumb || (reported.has(object) && reported.get(object) === material))
164
+ return;
165
+ reported.set(object, material);
166
+ const node = owningNode(object);
167
+ onBreadcrumb({
168
+ category: 'raycast_invalid_material',
169
+ message: 'Pointer raycast skipped a mesh whose geometry groups have no material',
170
+ level: 'warning',
171
+ data: { nodeType: node?.type ?? null, nodeId: node?.id ?? null, objectName: object.name },
172
+ });
173
+ };
174
+ }
175
+ /**
176
+ * Three's recursive `intersectObject`, skipping meshes `hasMaterialsForGroups`
177
+ * rejects. A raycaster with its own `intersectObject` is asked directly.
178
+ */
179
+ export function intersectDrawable(raycaster, object, skip) {
180
+ if (raycaster.intersectObject !== stockIntersectObject) {
181
+ return raycaster.intersectObject(object, true);
182
+ }
183
+ const hits = [];
184
+ const visit = (current) => {
185
+ let result;
186
+ if (current.layers.test(raycaster.layers)) {
187
+ if (hasMaterialsForGroups(current))
188
+ result = current.raycast(raycaster, hits);
189
+ else
190
+ skip(current);
191
+ }
192
+ if (result === false)
193
+ return;
194
+ const children = current.children;
195
+ for (let i = 0, length = children.length; i < length; i++)
196
+ visit(children[i]);
197
+ };
198
+ visit(object);
199
+ return hits.sort(distanceOrder);
200
+ }
201
+ function createCachedRaycast(skip) {
141
202
  const queries = new WeakMap();
142
203
  const activeQueries = [];
143
204
  const rootHits = [];
@@ -164,6 +225,8 @@ function createCachedRaycast() {
164
225
  }
165
226
  if (hasMaterialsForGroups(object))
166
227
  result = object.raycast(raycaster, hits);
228
+ else
229
+ skip(object);
167
230
  }
168
231
  if (result !== false) {
169
232
  const children = object.children;
@@ -246,9 +309,9 @@ function createCachedRaycast() {
246
309
  },
247
310
  };
248
311
  }
249
- export function createPascalPointerEvents(store) {
312
+ export function createPascalPointerEvents(store, onBreadcrumb) {
250
313
  const manager = createWebEvents(store);
251
- const { handlePointer } = createEvents(store);
314
+ const { handlePointer } = createEvents(store, onBreadcrumb);
252
315
  for (const name of Object.keys(manager.handlers)) {
253
316
  manager.handlers[name] = handlePointer(name);
254
317
  }
@@ -269,7 +332,7 @@ export function createPascalPointerEvents(store) {
269
332
  return manager;
270
333
  }
271
334
  function makeId(event) {
272
- // biome-ignore lint/style/useTemplate: Keep the vendored dispatch identical to R3F 9.8.1.
335
+ // biome-ignore lint/style/useTemplate: Keep the vendored dispatch identical to R3F 9.8.2.
273
336
  return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
274
337
  }
275
338
  /**
@@ -287,7 +350,8 @@ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
287
350
  }
288
351
  }
289
352
  }
290
- function createEvents(store) {
353
+ function createEvents(store, onBreadcrumb) {
354
+ const skipInvalidMaterial = createInvalidMaterialReporter(onBreadcrumb);
291
355
  const stats = {
292
356
  events: 0,
293
357
  cachedEvents: 0,
@@ -343,7 +407,7 @@ function createEvents(store) {
343
407
  // Make sure root-level pointer and ray are set up
344
408
  state.events.compute?.(event, state);
345
409
  }
346
- collectors[collectionDepth] ??= createCachedRaycast();
410
+ collectors[collectionDepth] ??= createCachedRaycast(skipInvalidMaterial);
347
411
  const collector = collectors[collectionDepth++];
348
412
  let hits = [];
349
413
  let stock = false;
@@ -365,7 +429,7 @@ function createEvents(store) {
365
429
  }
366
430
  if (layer.raycaster.camera) {
367
431
  const rootHits = stock
368
- ? layer.raycaster.intersectObject(obj, true)
432
+ ? intersectDrawable(layer.raycaster, obj, skipInvalidMaterial)
369
433
  : collector.intersectObject(obj, layer);
370
434
  if (!rootHits) {
371
435
  const unsupported = collector.unsupportedObject;
@@ -1 +1 @@
1
- {"version":3,"file":"post-processing-resources.d.ts","sourceRoot":"","sources":["../../src/lib/post-processing-resources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAIlD,qBAAa,uBAAuB;IAClC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAO;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAK;IAChC,OAAO,EAAE;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,GAAG,IAAI,CAAO;IAC1C,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAO;IAEtC,OAAO;CAUR"}
1
+ {"version":3,"file":"post-processing-resources.d.ts","sourceRoot":"","sources":["../../src/lib/post-processing-resources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAIlD,qBAAa,uBAAuB;IAClC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAO;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAK;IAChC,OAAO,EAAE;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,GAAG,IAAI,CAAO;IAC1C,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAO;IAEtC,OAAO,SASN;CACF"}
@@ -0,0 +1,80 @@
1
+ import { type AnyNode, type AnyNodeId, type RevealStyle, type SceneCommit } from '@pascal-app/core';
2
+ import type { RevealCandidate } from './reveal-schedule';
3
+ import type { PlayedStyle } from './reveal-wipe';
4
+ /**
5
+ * How much of the construction plays. `off` shows a build at once; `simple`
6
+ * keeps the scattered order with only `rise` and `scale`; `full` adds the
7
+ * falls, settles, cuts, assembled roofs and the dust. `framing` plays the
8
+ * same motions on the lazy, nested schedule (floor by floor, room by room,
9
+ * piece by piece; `planLazyReveal`), overdone a little, and plugins that stage
10
+ * their own members (the framing) read it and play them in the prerolls.
11
+ */
12
+ export type ConstructionRevealLevel = 'off' | 'simple' | 'full' | 'framing';
13
+ /** A candidate; for an assembled node's part, also the node it assembles. */
14
+ export type StagedCandidate = RevealCandidate & {
15
+ host?: string;
16
+ };
17
+ /** A roof piece lifts this share of its drop before it falls: a hair, 20 cm of 4 m. */
18
+ export declare const PART_LEAD = 0.05;
19
+ /** `simple` keeps the stagger with only the two slice-one motions. */
20
+ export declare function styleAt(style: RevealStyle, at: ConstructionRevealLevel): PlayedStyle;
21
+ /** Kinds that hold the others: staging one would unmount everything under it. */
22
+ export declare const CONTAINERS: ReadonlySet<string>;
23
+ /**
24
+ * What `commit` stages at `at`: each node it creates whose kind declares a
25
+ * reveal, and the new parts (children declaring none) of each one that
26
+ * assembles. A new node of a kind that declares none comes in with a default
27
+ * reveal when what holds it was already there (under a new host, it comes in
28
+ * with the host). `seq` counts on from `firstSeq` in arrival order. Each
29
+ * candidate carries its room and its place in it (`layoutRevealCandidates`).
30
+ */
31
+ export declare function commitRevealCandidates({ before, current, author }: SceneCommit, at: ConstructionRevealLevel, firstSeq?: number): StagedCandidate[];
32
+ /**
33
+ * Gives each candidate its room for the lazy schedule: the room it stands in (a node on a line, the
34
+ * room on either side of its middle), else, for a node on a line, a run of the lines it meets end to
35
+ * end (`capabilities.revealLayout`); its room's
36
+ * sweep across the floor; and its place in the room (around the room's centre, or along the run).
37
+ * What stands in no room keeps none: it belongs to the floor.
38
+ */
39
+ export declare function layoutRevealCandidates(candidates: StagedCandidate[], nodes: Record<AnyNodeId, AnyNode>): void;
40
+ /** Where a piece stood in its level: its position, and its turn about the vertical. */
41
+ export type Placement = {
42
+ position: [number, number, number];
43
+ yaw: number;
44
+ };
45
+ /**
46
+ * A piece changed by a commit. `from` is where a moved piece stood when it can glide from there, else
47
+ * null; `edited` marks a piece whose picture was edited (a wall bent, a slab resized), which plays its
48
+ * reveal again, quickly (`commitEditCandidates`).
49
+ */
50
+ export type ChangeCandidate = StagedCandidate & {
51
+ from: Placement | null;
52
+ edited?: true;
53
+ };
54
+ /**
55
+ * What `commit` moves: each piece of furniture it finds already there that is placed differently
56
+ * (another position, turn or parent). Furniture only, for now: walls and openings move with the
57
+ * rooms and walls that hold them.
58
+ */
59
+ export declare function commitChangeCandidates({ before, current, author }: SceneCommit, at: ConstructionRevealLevel, firstSeq?: number): ChangeCandidate[];
60
+ /**
61
+ * What taking `ids` back reveals: each of them, and everything under them (a wall's openings, a
62
+ * room's furniture), as the build would have staged it: by what its kind declares, or the default
63
+ * reveal a kind that declares none came in with. What stands in a host that goes (a segment of a
64
+ * stair, a part of a pool) goes with it; an assembled node (a roof) goes whole, not part by part.
65
+ */
66
+ export declare function nodeRevealCandidates(ids: Iterable<string>, nodes: Record<AnyNodeId, AnyNode>, at: ConstructionRevealLevel): RevealCandidate[];
67
+ /**
68
+ * What `commit` edits: each node already there whose kind lists `capabilities.revealOnEdit` and one of
69
+ * those fields (the ones that make its picture) changed. A change to any other field stays instant, and
70
+ * so does what the structure reconciler derived from an edit (`derivedWrites`: the plates and ceilings it
71
+ * owns, the fields it wrote on a node): a wall moved does not make its room's floor rise again.
72
+ */
73
+ export declare function commitEditCandidates({ before, current, author, derivedWrites }: SceneCommit, at: ConstructionRevealLevel, firstSeq?: number): ChangeCandidate[];
74
+ /**
75
+ * What `commit` deletes that the picture can play out: each node that was there and is gone whose kind
76
+ * stages a reveal, as it was staged when built (a node standing in a host that goes with it goes with
77
+ * its host). Derived construction the reconciler retires is not a deletion the person or the agent made.
78
+ */
79
+ export declare function commitDeleteCandidates({ before, current, author, derivedWrites }: SceneCommit, at: ConstructionRevealLevel, firstSeq?: number): StagedCandidate[];
80
+ //# sourceMappingURL=reveal-candidates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reveal-candidates.d.ts","sourceRoot":"","sources":["../../src/lib/reveal-candidates.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EAMd,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAA;AAE3E,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjE,uFAAuF;AACvF,eAAO,MAAM,SAAS,OAAO,CAAA;AAE7B,sEAAsE;AACtE,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,uBAAuB,GAAG,WAAW,CAKpF;AAED,iFAAiF;AACjF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,MAAM,CAA0C,CAAA;AAiFrF;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,WAAW,EACxC,EAAE,EAAE,uBAAuB,EAC3B,QAAQ,SAAI,GACX,eAAe,EAAE,CA0CnB;AA2FD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,eAAe,EAAE,EAC7B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAChC,IAAI,CAqEN;AAoED,uFAAuF;AACvF,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3E;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AAmCzF;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,WAAW,EACxC,EAAE,EAAE,uBAAuB,EAC3B,QAAQ,SAAI,GACX,eAAe,EAAE,CAoBnB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,EACrB,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,EAAE,EAAE,uBAAuB,GAC1B,eAAe,EAAE,CAsBnB;AAgBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EACvD,EAAE,EAAE,uBAAuB,EAC3B,QAAQ,SAAI,GACX,eAAe,EAAE,CA4BnB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,WAAW,EACvD,EAAE,EAAE,uBAAuB,EAC3B,QAAQ,SAAI,GACX,eAAe,EAAE,CA4BnB"}