@pascal-app/viewer 1.0.0-beta.4 → 1.0.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.
Files changed (265) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +107 -0
  3. package/dist/capture/asset-url.d.ts +2 -0
  4. package/dist/capture/asset-url.d.ts.map +1 -0
  5. package/dist/capture/asset-url.js +13 -0
  6. package/dist/capture/capture-runtime.d.ts +43 -0
  7. package/dist/capture/capture-runtime.d.ts.map +1 -0
  8. package/dist/capture/capture-runtime.js +228 -0
  9. package/dist/capture/frame.d.ts +4 -0
  10. package/dist/capture/frame.d.ts.map +1 -0
  11. package/dist/capture/frame.js +21 -0
  12. package/dist/capture/index.d.ts +12 -0
  13. package/dist/capture/index.d.ts.map +1 -0
  14. package/dist/capture/index.js +11 -0
  15. package/dist/capture/layer-visibility.d.ts +5 -0
  16. package/dist/capture/layer-visibility.d.ts.map +1 -0
  17. package/dist/capture/layer-visibility.js +11 -0
  18. package/dist/capture/layers/clay-matcap.d.ts +3 -0
  19. package/dist/capture/layers/clay-matcap.d.ts.map +1 -0
  20. package/dist/capture/layers/clay-matcap.js +26 -0
  21. package/dist/capture/layers/device-motion-layer.d.ts +7 -0
  22. package/dist/capture/layers/device-motion-layer.d.ts.map +1 -0
  23. package/dist/capture/layers/device-motion-layer.js +78 -0
  24. package/dist/capture/layers/point-cloud-layer.d.ts +15 -0
  25. package/dist/capture/layers/point-cloud-layer.d.ts.map +1 -0
  26. package/dist/capture/layers/point-cloud-layer.js +106 -0
  27. package/dist/capture/layers/room-model-layer.d.ts +9 -0
  28. package/dist/capture/layers/room-model-layer.d.ts.map +1 -0
  29. package/dist/capture/layers/room-model-layer.js +71 -0
  30. package/dist/capture/layers/surface-mesh-data.d.ts +9 -0
  31. package/dist/capture/layers/surface-mesh-data.d.ts.map +1 -0
  32. package/dist/capture/layers/surface-mesh-data.js +74 -0
  33. package/dist/capture/layers/surface-mesh-layer.d.ts +7 -0
  34. package/dist/capture/layers/surface-mesh-layer.d.ts.map +1 -0
  35. package/dist/capture/layers/surface-mesh-layer.js +16 -0
  36. package/dist/capture/preview.d.ts +3 -0
  37. package/dist/capture/preview.d.ts.map +1 -0
  38. package/dist/capture/preview.js +2 -0
  39. package/dist/capture/source-state.d.ts +22 -0
  40. package/dist/capture/source-state.d.ts.map +1 -0
  41. package/dist/capture/source-state.js +182 -0
  42. package/dist/capture/stream-rendering.d.ts +14 -0
  43. package/dist/capture/stream-rendering.d.ts.map +1 -0
  44. package/dist/capture/stream-rendering.js +69 -0
  45. package/dist/capture/trajectory.d.ts +20 -0
  46. package/dist/capture/trajectory.d.ts.map +1 -0
  47. package/dist/capture/trajectory.js +77 -0
  48. package/dist/components/viewer/batched-mesh-spike.d.ts +14 -0
  49. package/dist/components/viewer/batched-mesh-spike.d.ts.map +1 -0
  50. package/dist/components/viewer/batched-mesh-spike.js +64 -0
  51. package/dist/components/viewer/frame-limiter.d.ts +11 -0
  52. package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
  53. package/dist/components/viewer/frame-limiter.js +59 -18
  54. package/dist/components/viewer/index.d.ts +15 -0
  55. package/dist/components/viewer/index.d.ts.map +1 -1
  56. package/dist/components/viewer/index.js +74 -82
  57. package/dist/components/viewer/lights.d.ts.map +1 -1
  58. package/dist/components/viewer/lights.js +123 -89
  59. package/dist/components/viewer/perf-monitor.d.ts +6 -1
  60. package/dist/components/viewer/perf-monitor.d.ts.map +1 -1
  61. package/dist/components/viewer/perf-monitor.js +306 -115
  62. package/dist/components/viewer/perf-panel.d.ts +3 -0
  63. package/dist/components/viewer/perf-panel.d.ts.map +1 -0
  64. package/dist/components/viewer/perf-panel.js +178 -0
  65. package/dist/components/viewer/pointer-raycast-layers.d.ts +15 -0
  66. package/dist/components/viewer/pointer-raycast-layers.d.ts.map +1 -0
  67. package/dist/components/viewer/pointer-raycast-layers.js +28 -0
  68. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  69. package/dist/components/viewer/post-processing.js +124 -83
  70. package/dist/components/viewer/registered-systems.d.ts +14 -5
  71. package/dist/components/viewer/registered-systems.d.ts.map +1 -1
  72. package/dist/components/viewer/registered-systems.js +22 -10
  73. package/dist/components/viewer/scene-atmosphere.d.ts +30 -0
  74. package/dist/components/viewer/scene-atmosphere.d.ts.map +1 -0
  75. package/dist/components/viewer/scene-atmosphere.js +89 -0
  76. package/dist/components/viewer/scene-environment.d.ts.map +1 -1
  77. package/dist/components/viewer/scene-environment.js +19 -5
  78. package/dist/components/viewer/scene-ground-replacement.d.ts +5 -0
  79. package/dist/components/viewer/scene-ground-replacement.d.ts.map +1 -0
  80. package/dist/components/viewer/scene-ground-replacement.js +35 -0
  81. package/dist/components/viewer/selection-manager.d.ts.map +1 -1
  82. package/dist/components/viewer/selection-manager.js +7 -2
  83. package/dist/components/viewer/unsupported-gpu-fallback.d.ts +2 -0
  84. package/dist/components/viewer/unsupported-gpu-fallback.d.ts.map +1 -0
  85. package/dist/components/viewer/unsupported-gpu-fallback.js +4 -0
  86. package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
  87. package/dist/components/viewer/viewer-camera.js +4 -1
  88. package/dist/components/viewer/viewer-presentations.d.ts +67 -0
  89. package/dist/components/viewer/viewer-presentations.d.ts.map +1 -0
  90. package/dist/components/viewer/viewer-presentations.js +120 -0
  91. package/dist/hooks/use-library-materials-version.d.ts +7 -0
  92. package/dist/hooks/use-library-materials-version.d.ts.map +1 -0
  93. package/dist/hooks/use-library-materials-version.js +10 -0
  94. package/dist/hooks/use-node-events.d.ts.map +1 -1
  95. package/dist/hooks/use-node-events.js +1 -0
  96. package/dist/index.d.ts +20 -8
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +19 -7
  99. package/dist/lib/csg-utils.d.ts +1 -0
  100. package/dist/lib/csg-utils.d.ts.map +1 -1
  101. package/dist/lib/csg-utils.js +6 -1
  102. package/dist/lib/dispose-object3d.d.ts +4 -0
  103. package/dist/lib/dispose-object3d.d.ts.map +1 -0
  104. package/dist/lib/dispose-object3d.js +27 -0
  105. package/dist/lib/geometry-groups.d.ts +17 -0
  106. package/dist/lib/geometry-groups.d.ts.map +1 -0
  107. package/dist/lib/geometry-groups.js +53 -0
  108. package/dist/lib/gpu-perf.d.ts +0 -2
  109. package/dist/lib/gpu-perf.d.ts.map +1 -1
  110. package/dist/lib/gpu-perf.js +7 -21
  111. package/dist/lib/isolation.d.ts +8 -8
  112. package/dist/lib/isolation.d.ts.map +1 -1
  113. package/dist/lib/isolation.js +18 -30
  114. package/dist/lib/layer-pass.d.ts +28 -0
  115. package/dist/lib/layer-pass.d.ts.map +1 -0
  116. package/dist/lib/layer-pass.js +254 -0
  117. package/dist/lib/layers.d.ts +16 -0
  118. package/dist/lib/layers.d.ts.map +1 -1
  119. package/dist/lib/layers.js +18 -0
  120. package/dist/lib/materials.d.ts +12 -0
  121. package/dist/lib/materials.d.ts.map +1 -1
  122. package/dist/lib/materials.js +51 -17
  123. package/dist/lib/merged-outline-node.d.ts +17 -8
  124. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  125. package/dist/lib/merged-outline-node.js +194 -52
  126. package/dist/lib/perf-actions.d.ts +55 -0
  127. package/dist/lib/perf-actions.d.ts.map +1 -0
  128. package/dist/lib/perf-actions.js +211 -0
  129. package/dist/lib/perf-observers.d.ts +2 -0
  130. package/dist/lib/perf-observers.d.ts.map +1 -0
  131. package/dist/lib/perf-observers.js +17 -0
  132. package/dist/lib/perf-panel-store.d.ts +71 -0
  133. package/dist/lib/perf-panel-store.d.ts.map +1 -0
  134. package/dist/lib/perf-panel-store.js +29 -0
  135. package/dist/lib/perf-tracks.d.ts +43 -0
  136. package/dist/lib/perf-tracks.d.ts.map +1 -0
  137. package/dist/lib/perf-tracks.js +113 -0
  138. package/dist/lib/pointer-events.d.ts +7 -0
  139. package/dist/lib/pointer-events.d.ts.map +1 -0
  140. package/dist/lib/pointer-events.js +680 -0
  141. package/dist/lib/post-processing-resources.d.ts +12 -0
  142. package/dist/lib/post-processing-resources.d.ts.map +1 -0
  143. package/dist/lib/post-processing-resources.js +19 -0
  144. package/dist/lib/renderer-capability.d.ts +56 -0
  145. package/dist/lib/renderer-capability.d.ts.map +1 -0
  146. package/dist/lib/renderer-capability.js +116 -0
  147. package/dist/lib/scene-visibility.d.ts +15 -0
  148. package/dist/lib/scene-visibility.d.ts.map +1 -0
  149. package/dist/lib/scene-visibility.js +69 -0
  150. package/dist/lib/shadow-only.d.ts +16 -0
  151. package/dist/lib/shadow-only.d.ts.map +1 -1
  152. package/dist/lib/shadow-only.js +8 -17
  153. package/dist/lib/snapshot-pipeline.d.ts +9 -0
  154. package/dist/lib/snapshot-pipeline.d.ts.map +1 -1
  155. package/dist/lib/snapshot-pipeline.js +33 -9
  156. package/dist/store/use-viewer.d.ts +7 -6
  157. package/dist/store/use-viewer.d.ts.map +1 -1
  158. package/dist/systems/ceiling/ceiling-system.js +1 -1
  159. package/dist/systems/door/door-animation-system.d.ts.map +1 -1
  160. package/dist/systems/door/door-animation-system.js +6 -9
  161. package/dist/systems/door/door-system.d.ts.map +1 -1
  162. package/dist/systems/door/door-system.js +13 -2
  163. package/dist/systems/floor-elevation/floor-elevation-system.d.ts.map +1 -1
  164. package/dist/systems/floor-elevation/floor-elevation-system.js +9 -0
  165. package/dist/systems/geometry/geometry-system.d.ts.map +1 -1
  166. package/dist/systems/geometry/geometry-system.js +5 -28
  167. package/dist/systems/level/level-system.d.ts.map +1 -1
  168. package/dist/systems/level/level-system.js +8 -2
  169. package/dist/systems/level/level-utils.d.ts +9 -0
  170. package/dist/systems/level/level-utils.d.ts.map +1 -1
  171. package/dist/systems/level/level-utils.js +14 -0
  172. package/dist/systems/perf-action-settle/perf-action-settle-system.d.ts +8 -0
  173. package/dist/systems/perf-action-settle/perf-action-settle-system.d.ts.map +1 -0
  174. package/dist/systems/perf-action-settle/perf-action-settle-system.js +32 -0
  175. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  176. package/dist/systems/roof/roof-system.js +1196 -58
  177. package/dist/systems/scan/scan-system.js +6 -5
  178. package/dist/systems/slab/slab-system.d.ts.map +1 -1
  179. package/dist/systems/slab/slab-system.js +1 -2
  180. package/dist/systems/stair/stair-system.d.ts.map +1 -1
  181. package/dist/systems/stair/stair-system.js +9 -8
  182. package/dist/systems/surface-hole-geometry.d.ts +1 -1
  183. package/dist/systems/surface-hole-geometry.d.ts.map +1 -1
  184. package/dist/systems/surface-hole-geometry.js +1 -1
  185. package/dist/systems/wall/level-miter-cache.d.ts +10 -0
  186. package/dist/systems/wall/level-miter-cache.d.ts.map +1 -0
  187. package/dist/systems/wall/level-miter-cache.js +40 -0
  188. package/dist/systems/wall/wall-build-lifecycle.d.ts +9 -0
  189. package/dist/systems/wall/wall-build-lifecycle.d.ts.map +1 -0
  190. package/dist/systems/wall/wall-build-lifecycle.js +74 -0
  191. package/dist/systems/wall/wall-cutout-cache.d.ts +57 -0
  192. package/dist/systems/wall/wall-cutout-cache.d.ts.map +1 -0
  193. package/dist/systems/wall/wall-cutout-cache.js +304 -0
  194. package/dist/systems/wall/wall-cutout.d.ts +24 -1
  195. package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
  196. package/dist/systems/wall/wall-cutout.js +33 -140
  197. package/dist/systems/wall/wall-material-variant.d.ts +31 -0
  198. package/dist/systems/wall/wall-material-variant.d.ts.map +1 -0
  199. package/dist/systems/wall/wall-material-variant.js +10 -0
  200. package/dist/systems/wall/wall-materials.d.ts +6 -0
  201. package/dist/systems/wall/wall-materials.d.ts.map +1 -1
  202. package/dist/systems/wall/wall-materials.js +29 -13
  203. package/dist/systems/wall/wall-placeholder-sweep.d.ts +50 -0
  204. package/dist/systems/wall/wall-placeholder-sweep.d.ts.map +1 -0
  205. package/dist/systems/wall/wall-placeholder-sweep.js +51 -0
  206. package/dist/systems/wall/wall-rebuild-notifications.d.ts +5 -0
  207. package/dist/systems/wall/wall-rebuild-notifications.d.ts.map +1 -0
  208. package/dist/systems/wall/wall-rebuild-notifications.js +23 -0
  209. package/dist/systems/wall/wall-system.d.ts +13 -2
  210. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  211. package/dist/systems/wall/wall-system.js +413 -148
  212. package/dist/systems/window/window-animation-system.d.ts.map +1 -1
  213. package/dist/systems/window/window-animation-system.js +9 -8
  214. package/dist/systems/window/window-system.d.ts +1 -0
  215. package/dist/systems/window/window-system.d.ts.map +1 -1
  216. package/dist/systems/window/window-system.js +16 -2
  217. package/package.json +18 -3
  218. package/dist/components/viewer/scene-bvh.test.d.ts +0 -2
  219. package/dist/components/viewer/scene-bvh.test.d.ts.map +0 -1
  220. package/dist/components/viewer/scene-bvh.test.js +0 -13
  221. package/dist/lib/csg-utils.test.d.ts +0 -2
  222. package/dist/lib/csg-utils.test.d.ts.map +0 -1
  223. package/dist/lib/csg-utils.test.js +0 -45
  224. package/dist/lib/materials.test.d.ts +0 -2
  225. package/dist/lib/materials.test.d.ts.map +0 -1
  226. package/dist/lib/materials.test.js +0 -25
  227. package/dist/lib/merged-outline-node.test.d.ts +0 -2
  228. package/dist/lib/merged-outline-node.test.d.ts.map +0 -1
  229. package/dist/lib/merged-outline-node.test.js +0 -22
  230. package/dist/lib/polygon-union.d.ts +0 -4
  231. package/dist/lib/polygon-union.d.ts.map +0 -1
  232. package/dist/lib/polygon-union.js +0 -289
  233. package/dist/lib/polygon-union.test.d.ts +0 -2
  234. package/dist/lib/polygon-union.test.d.ts.map +0 -1
  235. package/dist/lib/polygon-union.test.js +0 -105
  236. package/dist/lib/texture-reference.test.d.ts +0 -2
  237. package/dist/lib/texture-reference.test.d.ts.map +0 -1
  238. package/dist/lib/texture-reference.test.js +0 -86
  239. package/dist/store/use-viewer.test.d.ts +0 -2
  240. package/dist/store/use-viewer.test.d.ts.map +0 -1
  241. package/dist/store/use-viewer.test.js +0 -61
  242. package/dist/systems/door/door-animation.test.d.ts +0 -2
  243. package/dist/systems/door/door-animation.test.d.ts.map +0 -1
  244. package/dist/systems/door/door-animation.test.js +0 -51
  245. package/dist/systems/door/door-floor-alignment.test.d.ts +0 -2
  246. package/dist/systems/door/door-floor-alignment.test.d.ts.map +0 -1
  247. package/dist/systems/door/door-floor-alignment.test.js +0 -50
  248. package/dist/systems/geometry/geometry-system.test.d.ts +0 -2
  249. package/dist/systems/geometry/geometry-system.test.d.ts.map +0 -1
  250. package/dist/systems/geometry/geometry-system.test.js +0 -30
  251. package/dist/systems/slab/slab-system.test.d.ts +0 -2
  252. package/dist/systems/slab/slab-system.test.d.ts.map +0 -1
  253. package/dist/systems/slab/slab-system.test.js +0 -102
  254. package/dist/systems/wall/opening-cutout-geometry.test.d.ts +0 -2
  255. package/dist/systems/wall/opening-cutout-geometry.test.d.ts.map +0 -1
  256. package/dist/systems/wall/opening-cutout-geometry.test.js +0 -172
  257. package/dist/systems/wall/wall-opening-cutout.test.d.ts +0 -2
  258. package/dist/systems/wall/wall-opening-cutout.test.d.ts.map +0 -1
  259. package/dist/systems/wall/wall-opening-cutout.test.js +0 -59
  260. package/dist/systems/wall/wall-support-extension.test.d.ts +0 -2
  261. package/dist/systems/wall/wall-support-extension.test.d.ts.map +0 -1
  262. package/dist/systems/wall/wall-support-extension.test.js +0 -116
  263. package/dist/systems/wall/wall-terrain-bottom.test.d.ts +0 -2
  264. package/dist/systems/wall/wall-terrain-bottom.test.d.ts.map +0 -1
  265. package/dist/systems/wall/wall-terrain-bottom.test.js +0 -34
@@ -4,6 +4,7 @@ import { useEffect, useRef } from 'react';
4
4
  import * as THREE from 'three';
5
5
  import { applyWorldScaleBoxUVs } from '../../lib/box-uv';
6
6
  import { createDefaultMaterial, createSurfaceRoleMaterial, glassMaterial as defaultGlassMaterial, baseMaterial as getBaseMaterial, resolveMaterialRef, } from '../../lib/materials';
7
+ import { timeSpan } from '../../lib/perf-tracks';
7
8
  import useViewer from '../../store/use-viewer';
8
9
  import { getOpeningCutoutProxyDepth } from '../wall/opening-cutout-geometry';
9
10
  // Invisible material for root mesh — used as selection hitbox only
@@ -94,7 +95,11 @@ export const DoorSystem = () => {
94
95
  }
95
96
  }, [sceneMaterials]);
96
97
  useFrame(() => {
97
- if (dirtyNodes.size === 0)
98
+ // Doors mid-swing rebuild every tick via their `doorAnimations` entry —
99
+ // the tween is a needs-frame signal, not dirty-set work (the set must be
100
+ // able to reach zero while an animation runs).
101
+ const animatingDoorIds = Object.keys(useInteractive.getState().doorAnimations);
102
+ if (dirtyNodes.size === 0 && animatingDoorIds.length === 0)
98
103
  return;
99
104
  const frameJoineryMaterial = createSurfaceRoleMaterial('joinery', colorPreset);
100
105
  baseMaterial = textures ? getBaseMaterial(shading) : frameJoineryMaterial;
@@ -114,6 +119,10 @@ export const DoorSystem = () => {
114
119
  return;
115
120
  dirtyDoorIds.push(id);
116
121
  });
122
+ for (const id of animatingDoorIds) {
123
+ if (nodes[id]?.type === 'door' && !dirtyDoorIds.includes(id))
124
+ dirtyDoorIds.push(id);
125
+ }
117
126
  const useProgressiveDoorRebuilds = dirtyDoorIds.length > DOOR_PROGRESSIVE_DIRTY_THRESHOLD;
118
127
  const frameStartedAt = performance.now();
119
128
  let rebuiltDoorsThisFrame = 0;
@@ -137,7 +146,9 @@ export const DoorSystem = () => {
137
146
  // rebuild reflects the in-flight drag without zustand churn. When
138
147
  // no override is set this returns the scene node unchanged.
139
148
  const effectiveNode = getEffectiveNode(node);
140
- updateDoorMesh(effectiveNode, mesh);
149
+ timeSpan('door', () => updateDoorMesh(effectiveNode, mesh), {
150
+ properties: [['node', id]],
151
+ });
141
152
  clearDirty(id);
142
153
  rebuiltDoorsThisFrame += 1;
143
154
  // Rebuild the parent wall so its cutout reflects the updated door geometry
@@ -1 +1 @@
1
- {"version":3,"file":"floor-elevation-system.d.ts","sourceRoot":"","sources":["../../../src/systems/floor-elevation/floor-elevation-system.tsx"],"names":[],"mappings":"AAyCA;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,oBAAoB,YAoEhC,CAAA"}
1
+ {"version":3,"file":"floor-elevation-system.d.ts","sourceRoot":"","sources":["../../../src/systems/floor-elevation/floor-elevation-system.tsx"],"names":[],"mappings":"AAyCA;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,oBAAoB,YA6EhC,CAAA"}
@@ -64,6 +64,15 @@ export const FloorElevationSystem = () => {
64
64
  const position = effectiveNode.position;
65
65
  if (!position)
66
66
  return;
67
+ // `applies === false` means the kind opts OUT of floor stacking for this
68
+ // node: its Y belongs to a host frame (a wall/ceiling-mounted item, a
69
+ // cabinet module inside a run, a wall duct terminal). `getFloorPlacedElevation`
70
+ // already returns 0 for them, so the write below would degenerate to
71
+ // copying `position[1]` into the mesh — and tools publish live transforms
72
+ // in WORLD space, so during a drag that lifts the ghost off its host by
73
+ // the host frame's own elevation.
74
+ if (floorPlaced.applies && !floorPlaced.applies(effectiveNode))
75
+ return;
67
76
  // This system is the single drag-time authority for floor-stack mesh Y:
68
77
  // tools publish base positions to live stores, renderers may
69
78
  // reconcile that base Y onto the group, then this presentation system
@@ -1 +1 @@
1
- {"version":3,"file":"geometry-system.d.ts","sourceRoot":"","sources":["../../../src/systems/geometry/geometry-system.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAa,KAAK,KAAK,EAA4B,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAA;AAQtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,cAAc,YA8L1B,CAAA;AAoKD,eAAe,cAAc,CAAA;AAE7B,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,KAAK,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAU7D;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAC3C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,OAAO,CAKT"}
1
+ {"version":3,"file":"geometry-system.d.ts","sourceRoot":"","sources":["../../../src/systems/geometry/geometry-system.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAa,KAAK,KAAK,EAA4B,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAA;AAUtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,cAAc,YAuM1B,CAAA;AA8ID,eAAe,cAAc,CAAA;AAE7B,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,KAAK,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAU7D;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAC3C,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,GACV,OAAO,CAKT"}
@@ -3,7 +3,9 @@ import { findLevelAncestorId, getEffectiveNode, levelBaseElevationAt, nodeRegist
3
3
  import { useFrame } from '@react-three/fiber';
4
4
  import { useEffect, useRef } from 'react';
5
5
  import { FrontSide } from 'three';
6
+ import { disposeObject3DResources } from '../../lib/dispose-object3d';
6
7
  import { createSurfaceRoleMaterial, } from '../../lib/materials';
8
+ import { timeSpan } from '../../lib/perf-tracks';
7
9
  import useViewer from '../../store/use-viewer';
8
10
  /**
9
11
  * Generic geometry system.
@@ -137,7 +139,7 @@ export const GeometrySystem = () => {
137
139
  siblings.push(node);
138
140
  }
139
141
  }
140
- levelDataByBatch.set(key, def.computeLevelData(siblings));
142
+ levelDataByBatch.set(key, timeSpan('geometry', () => def.computeLevelData(siblings), { name: 'geometry:levelData' }));
141
143
  }
142
144
  // Phase 3 — per-node rebuild. Each node receives its batch's
143
145
  // precomputed `levelData` in ctx.
@@ -179,7 +181,7 @@ export const GeometrySystem = () => {
179
181
  // The builder is typed against the kind's specific node — at the
180
182
  // generic system level we lose that refinement, so the cast lands
181
183
  // here. Builders are responsible for trusting their schema.
182
- const built = builder(effectiveNode, ctx, shading, textures, colorPreset, sceneTheme);
184
+ const built = timeSpan('geometry', () => builder(effectiveNode, ctx, shading, textures, colorPreset, sceneTheme), { name: `geometry:${node.type}`, properties: [['node', id]] });
183
185
  if (!textures && def.surfaceRole) {
184
186
  applyDefaultSurfaceRole(built, def.surfaceRole, colorPreset, sceneTheme);
185
187
  }
@@ -289,28 +291,7 @@ function disposeChildren(group) {
289
291
  if (!fromGeometry)
290
292
  continue;
291
293
  group.remove(child);
292
- const mesh = child;
293
- if (mesh.geometry?.dispose)
294
- mesh.geometry.dispose();
295
- if ('material' in mesh) {
296
- const m = mesh.material;
297
- if (Array.isArray(m)) {
298
- for (const mat of m) {
299
- if (isCachedMaterial(mat))
300
- continue;
301
- if (mat && typeof mat.dispose === 'function') {
302
- ;
303
- mat.dispose();
304
- }
305
- }
306
- }
307
- else if (isCachedMaterial(m)) {
308
- }
309
- else if (m && typeof m.dispose === 'function') {
310
- ;
311
- m.dispose();
312
- }
313
- }
294
+ disposeObject3DResources(child);
314
295
  }
315
296
  }
316
297
  function applyDefaultSurfaceRole(root, defaultRole, colorPreset, sceneTheme) {
@@ -339,10 +320,6 @@ function getMaterialSide(material) {
339
320
  const source = Array.isArray(material) ? material[0] : material;
340
321
  return source?.side ?? FrontSide;
341
322
  }
342
- function isCachedMaterial(value) {
343
- return Boolean(value?.userData
344
- ?.__pascalCachedMaterial);
345
- }
346
323
  export default GeometrySystem;
347
324
  export function markGeometryBuildOutput(child) {
348
325
  // Tag the builder subtree so paint previews can reach nested meshes (for
@@ -1 +1 @@
1
- {"version":3,"file":"level-system.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-system.tsx"],"names":[],"mappings":"AAeA,eAAO,MAAM,WAAW,YAuDvB,CAAA"}
1
+ {"version":3,"file":"level-system.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-system.tsx"],"names":[],"mappings":"AAcA,eAAO,MAAM,WAAW,YA6DvB,CAAA"}
@@ -3,7 +3,7 @@ import { useFrame } from '@react-three/fiber';
3
3
  import { lerp } from 'three/src/math/MathUtils.js';
4
4
  import { applyShadowOnly, clearShadowOnly } from '../../lib/shadow-only';
5
5
  import useViewer from '../../store/use-viewer';
6
- const EXPLODED_GAP = 5;
6
+ import { EXPLODED_GAP } from './level-utils';
7
7
  // Levels currently in shadow-caster-only mode (solo hides them from the color
8
8
  // passes but keeps their sun shadows). Tracked so we can restore layer masks
9
9
  // exactly once on transition; apply re-runs every frame so meshes rebuilt
@@ -35,7 +35,13 @@ export const LevelSystem = () => {
35
35
  const baseY = levelElevations.get(levelId)?.baseY ?? 0;
36
36
  const explodedExtra = levelMode === 'exploded' ? index * EXPLODED_GAP : 0;
37
37
  const targetY = baseY + explodedExtra;
38
- obj.position.y = lerp(obj.position.y, targetY, delta * 12); // Smoothly animate to new Y position
38
+ // Clamped smoothing. The naive `lerp(y, target, delta*12)` multiplies
39
+ // the error by |1 - 12*delta| per frame — DIVERGENT once a frame
40
+ // exceeds ~166 ms (slow machines, headless GL, heavy scenes): levels
41
+ // oscillated kilometers off-screen and the level-fit camera followed
42
+ // (blank viewport). Clamping keeps every step a contraction: identical
43
+ // feel at 60 fps, exact snap instead of overshoot on slow frames.
44
+ obj.position.y = lerp(obj.position.y, targetY, Math.min(1, delta * 12));
39
45
  // Solo: hidden levels ABOVE the soloed one stay in the shadow map
40
46
  // (shadow-caster-only) so the sun still shadows the soloed floor through
41
47
  // them; levels below can't block the sun, so they plain-hide.
@@ -1,3 +1,12 @@
1
+ export declare const EXPLODED_GAP = 5;
2
+ /**
3
+ * The Y a level settles at under the given presentation mode — its stacked
4
+ * elevation plus the exploded gap. Analytic (scene store + mode), never a
5
+ * mesh read: a level created this frame has its Object3D at y=0 until
6
+ * LevelSystem lerps it, and a mode switch leaves meshes mid-lerp — camera
7
+ * code framing a level must aim at the destination, not the moving target.
8
+ */
9
+ export declare function getLevelPresentationY(levelId: string, nodes: Record<string, unknown>, levelMode: 'stacked' | 'exploded' | 'solo' | 'manual'): number;
1
10
  /**
2
11
  * Instantly snaps all level Objects3D to their true stacked Y positions
3
12
  * (ignores levelMode — always uses stacked, no exploded gap).
@@ -1 +1 @@
1
- {"version":3,"file":"level-utils.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-utils.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,IAAI,CAyCtD"}
1
+ {"version":3,"file":"level-utils.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-utils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,IAAI,CAAA;AAE7B;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GACpD,MAAM,CAKR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,IAAI,CAyCtD"}
@@ -1,4 +1,18 @@
1
1
  import { getLevelElevations, sceneRegistry, useScene } from '@pascal-app/core';
2
+ export const EXPLODED_GAP = 5;
3
+ /**
4
+ * The Y a level settles at under the given presentation mode — its stacked
5
+ * elevation plus the exploded gap. Analytic (scene store + mode), never a
6
+ * mesh read: a level created this frame has its Object3D at y=0 until
7
+ * LevelSystem lerps it, and a mode switch leaves meshes mid-lerp — camera
8
+ * code framing a level must aim at the destination, not the moving target.
9
+ */
10
+ export function getLevelPresentationY(levelId, nodes, levelMode) {
11
+ const level = nodes[levelId];
12
+ const baseY = getLevelElevations(nodes).get(levelId)?.baseY ?? 0;
13
+ const explodedExtra = levelMode === 'exploded' && level ? level.level * EXPLODED_GAP : 0;
14
+ return baseY + explodedExtra;
15
+ }
2
16
  /**
3
17
  * Instantly snaps all level Objects3D to their true stacked Y positions
4
18
  * (ignores levelMode — always uses stacked, no exploded gap).
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Feeds the action-cost ledger (lib/perf-actions.ts) the per-frame settle
3
+ * state: how much of the scene is still dirty and how many wall neighbour
4
+ * rebuilds the wall system still owes. Without `?perf` the inner component
5
+ * never mounts, so no useFrame subscriber is registered at all.
6
+ */
7
+ export declare const PerfActionSettleSystem: () => import("react").JSX.Element | null;
8
+ //# sourceMappingURL=perf-action-settle-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perf-action-settle-system.d.ts","sourceRoot":"","sources":["../../../src/systems/perf-action-settle/perf-action-settle-system.tsx"],"names":[],"mappings":"AAuBA;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,0CAGlC,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useScene } from '@pascal-app/core';
3
+ import { useFrame } from '@react-three/fiber';
4
+ import { PERF_OVERLAY_ENABLED } from '../../lib/gpu-perf';
5
+ import { notifyPerfActionFrame } from '../../lib/perf-actions';
6
+ import { getPendingWallRebuildCount } from '../wall/wall-system';
7
+ // Later than every other viewer system (the highest in the tree is 10) and
8
+ // later than the render call in post-processing (priority 1), so the counts
9
+ // reported are what the frame actually left behind.
10
+ const SETTLE_PRIORITY = 100;
11
+ const PerfActionSettleFrame = () => {
12
+ useFrame(() => {
13
+ // The raw set size, deliberately: the dirty lifecycle now guarantees marks
14
+ // are cleared when their node goes away (undo sweep) and never added for
15
+ // consumerless kinds (GuardedDirtySet), so any lingering mark is a leak
16
+ // that SHOULD fail settle instead of being filtered out here.
17
+ const { dirtyNodes } = useScene.getState();
18
+ notifyPerfActionFrame(dirtyNodes.size, getPendingWallRebuildCount());
19
+ }, SETTLE_PRIORITY);
20
+ return null;
21
+ };
22
+ /**
23
+ * Feeds the action-cost ledger (lib/perf-actions.ts) the per-frame settle
24
+ * state: how much of the scene is still dirty and how many wall neighbour
25
+ * rebuilds the wall system still owes. Without `?perf` the inner component
26
+ * never mounts, so no useFrame subscriber is registered at all.
27
+ */
28
+ export const PerfActionSettleSystem = () => {
29
+ if (!PERF_OVERLAY_ENABLED)
30
+ return null;
31
+ return _jsx(PerfActionSettleFrame, {});
32
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAcZ,KAAK,eAAe,EAKrB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,KAAK,EAA0B,MAAM,eAAe,CAAA;AAwIvE,eAAO,MAAM,UAAU,YAuItB,CAAA;AAmXD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE;IAC7B,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;CAMxB,CAAA;AAID,eAAO,MAAM,wBAAwB,IAAI,CAAA;AAEzC,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,KAAK,CAAA;IACf,QAAQ,EAAE,KAAK,CAAA;IACf,SAAS,EAAE,KAAK,CAAA;IAChB,UAAU,EAAE,KAAK,CAAA;IACjB,UAAU,EAAE,KAAK,CAAC,cAAc,GAAG,IAAI,CAAA;CACxC,CAAA;AA0FD,wBAAgB,yBAAyB,CACvC,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,YAAY,EAAE,KAAK,CAAC,QAAQ,EAAE,EAC9B,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,GACtC,MAAM,CAuBR;AAgUD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,KAAK,CAAC,cAAc,GAAG,IAAI,EACrC,OAAO,EAAE,eAAe,GACvB,KAAK,CAAC,cAAc,GAAG,IAAI,CAyB7B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,eAAe,GAAG,mBAAmB,GAAG,IAAI,CA+SvF;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,eAAe,EACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,KAAK,CAAC,cAAc,CAsFtB;AAsLD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,eAAe,QA2ExF;AAijBD,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAA;IACpB,MAAM,EAAE,KAAK,CAAC,OAAO,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,eAAe,EACxB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,YAAY,CAqLd"}
1
+ {"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAoBZ,KAAK,eAAe,EAQrB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,KAAK,EAA0B,MAAM,eAAe,CAAA;AAkMvE,eAAO,MAAM,UAAU,YAwItB,CAAA;AAgbD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE;IAC7B,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;IACvB,KAAK,CAAC,iBAAiB;CAMxB,CAAA;AAID,eAAO,MAAM,wBAAwB,IAAI,CAAA;AAEzC,KAAK,mBAAmB,GAAG;IACzB,QAAQ,EAAE,KAAK,CAAA;IACf,QAAQ,EAAE,KAAK,CAAA;IACf,SAAS,EAAE,KAAK,CAAA;IAChB,UAAU,EAAE,KAAK,CAAA;IACjB,UAAU,EAAE,KAAK,CAAC,cAAc,GAAG,IAAI,CAAA;CACxC,CAAA;AA0FD,wBAAgB,yBAAyB,CACvC,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,YAAY,EAAE,KAAK,CAAC,QAAQ,EAAE,EAC9B,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,GACtC,MAAM,CAuBR;AAoWD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,KAAK,CAAC,cAAc,GAAG,IAAI,EACrC,OAAO,EAAE,eAAe,GACvB,KAAK,CAAC,cAAc,GAAG,IAAI,CAyB7B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,eAAe,GAAG,mBAAmB,GAAG,IAAI,CA8TvF;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,eAAe,EACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,KAAK,CAAC,cAAc,CA2GtB;AAuyCD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,eAAe,QA0ExF;AA+qBD,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAA;IACpB,MAAM,EAAE,KAAK,CAAC,OAAO,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,eAAe,EACxB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,YAAY,CAqLd"}