@pascal-app/viewer 0.8.0 → 0.9.2

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 (284) hide show
  1. package/dist/components/error-boundary.d.ts +6 -0
  2. package/dist/components/error-boundary.d.ts.map +1 -1
  3. package/dist/components/error-boundary.js +6 -0
  4. package/dist/components/renderers/node-renderer.d.ts +6 -2
  5. package/dist/components/renderers/node-renderer.d.ts.map +1 -1
  6. package/dist/components/renderers/node-renderer.js +41 -22
  7. package/dist/components/renderers/parametric-node-renderer.d.ts +5 -0
  8. package/dist/components/renderers/parametric-node-renderer.d.ts.map +1 -0
  9. package/dist/components/renderers/parametric-node-renderer.js +37 -0
  10. package/dist/components/renderers/scene-renderer.d.ts +1 -1
  11. package/dist/components/renderers/scene-renderer.d.ts.map +1 -1
  12. package/dist/components/viewer/bvh-ecctrl.d.ts +77 -0
  13. package/dist/components/viewer/bvh-ecctrl.d.ts.map +1 -0
  14. package/dist/components/viewer/bvh-ecctrl.js +552 -0
  15. package/dist/components/viewer/frame-limiter.d.ts.map +1 -1
  16. package/dist/components/viewer/frame-limiter.js +39 -4
  17. package/dist/components/viewer/glb-interactive.d.ts +41 -0
  18. package/dist/components/viewer/glb-interactive.d.ts.map +1 -0
  19. package/dist/components/viewer/glb-interactive.js +394 -0
  20. package/dist/components/viewer/glb-reference-nodes.d.ts +29 -0
  21. package/dist/components/viewer/glb-reference-nodes.d.ts.map +1 -0
  22. package/dist/components/viewer/glb-reference-nodes.js +80 -0
  23. package/dist/components/viewer/glb-replace-instances.d.ts +18 -0
  24. package/dist/components/viewer/glb-replace-instances.d.ts.map +1 -0
  25. package/dist/components/viewer/glb-replace-instances.js +61 -0
  26. package/dist/components/viewer/glb-scene.d.ts +54 -0
  27. package/dist/components/viewer/glb-scene.d.ts.map +1 -0
  28. package/dist/components/viewer/glb-scene.js +920 -0
  29. package/dist/components/viewer/glb-walkthrough-controller.d.ts +12 -0
  30. package/dist/components/viewer/glb-walkthrough-controller.d.ts.map +1 -0
  31. package/dist/components/viewer/glb-walkthrough-controller.js +357 -0
  32. package/dist/components/viewer/index.d.ts +56 -3
  33. package/dist/components/viewer/index.d.ts.map +1 -1
  34. package/dist/components/viewer/index.js +280 -65
  35. package/dist/components/viewer/lights.d.ts +1 -1
  36. package/dist/components/viewer/lights.d.ts.map +1 -1
  37. package/dist/components/viewer/lights.js +201 -43
  38. package/dist/components/viewer/perf-monitor.d.ts +1 -1
  39. package/dist/components/viewer/perf-monitor.d.ts.map +1 -1
  40. package/dist/components/viewer/perf-monitor.js +115 -12
  41. package/dist/components/viewer/post-processing.d.ts +7 -1
  42. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  43. package/dist/components/viewer/post-processing.js +395 -63
  44. package/dist/components/viewer/registered-systems.d.ts +12 -0
  45. package/dist/components/viewer/registered-systems.d.ts.map +1 -0
  46. package/dist/components/viewer/registered-systems.js +49 -0
  47. package/dist/components/viewer/scene-bvh.d.ts +18 -0
  48. package/dist/components/viewer/scene-bvh.d.ts.map +1 -0
  49. package/dist/components/viewer/scene-bvh.js +97 -0
  50. package/dist/components/viewer/scene-bvh.test.d.ts +2 -0
  51. package/dist/components/viewer/scene-bvh.test.d.ts.map +1 -0
  52. package/dist/components/viewer/scene-bvh.test.js +13 -0
  53. package/dist/components/viewer/scene-environment.d.ts +2 -0
  54. package/dist/components/viewer/scene-environment.d.ts.map +1 -0
  55. package/dist/components/viewer/scene-environment.js +79 -0
  56. package/dist/components/viewer/selection-manager.d.ts +1 -1
  57. package/dist/components/viewer/selection-manager.d.ts.map +1 -1
  58. package/dist/components/viewer/selection-manager.js +37 -14
  59. package/dist/components/viewer/viewer-camera.d.ts +1 -1
  60. package/dist/components/viewer/viewer-camera.d.ts.map +1 -1
  61. package/dist/components/viewer/walkthrough-controls.d.ts +2 -1
  62. package/dist/components/viewer/walkthrough-controls.d.ts.map +1 -1
  63. package/dist/components/viewer/walkthrough-controls.js +20 -0
  64. package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -1
  65. package/dist/hooks/use-gltf-ktx2.js +3 -22
  66. package/dist/hooks/use-node-events.d.ts +6 -74
  67. package/dist/hooks/use-node-events.d.ts.map +1 -1
  68. package/dist/hooks/use-node-events.js +28 -8
  69. package/dist/index.d.ts +48 -5
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +82 -4
  72. package/dist/lib/backdrop.d.ts +33 -0
  73. package/dist/lib/backdrop.d.ts.map +1 -0
  74. package/dist/lib/backdrop.js +92 -0
  75. package/dist/lib/box-uv.d.ts +13 -0
  76. package/dist/lib/box-uv.d.ts.map +1 -0
  77. package/dist/lib/box-uv.js +32 -0
  78. package/dist/lib/csg-utils.d.ts +10 -0
  79. package/dist/lib/csg-utils.d.ts.map +1 -0
  80. package/dist/lib/csg-utils.js +93 -0
  81. package/dist/lib/csg-utils.test.d.ts +2 -0
  82. package/dist/lib/csg-utils.test.d.ts.map +1 -0
  83. package/dist/lib/csg-utils.test.js +45 -0
  84. package/dist/lib/drawable-geometry.d.ts +21 -0
  85. package/dist/lib/drawable-geometry.d.ts.map +1 -0
  86. package/dist/lib/drawable-geometry.js +22 -0
  87. package/dist/lib/edge-style.d.ts +4 -0
  88. package/dist/lib/edge-style.d.ts.map +1 -0
  89. package/dist/lib/edge-style.js +31 -0
  90. package/dist/lib/gpu-perf.d.ts +4 -0
  91. package/dist/lib/gpu-perf.d.ts.map +1 -0
  92. package/dist/lib/gpu-perf.js +23 -0
  93. package/dist/lib/ink-edges.d.ts +9 -0
  94. package/dist/lib/ink-edges.d.ts.map +1 -0
  95. package/dist/lib/ink-edges.js +49 -0
  96. package/dist/lib/isolation.d.ts +39 -0
  97. package/dist/lib/isolation.d.ts.map +1 -0
  98. package/dist/lib/isolation.js +103 -0
  99. package/dist/lib/ktx2-loader.d.ts +43 -0
  100. package/dist/lib/ktx2-loader.d.ts.map +1 -0
  101. package/dist/lib/ktx2-loader.js +136 -0
  102. package/dist/lib/layers.d.ts +28 -0
  103. package/dist/lib/layers.d.ts.map +1 -1
  104. package/dist/lib/layers.js +28 -0
  105. package/dist/lib/materials.d.ts +38 -15
  106. package/dist/lib/materials.d.ts.map +1 -1
  107. package/dist/lib/materials.js +364 -72
  108. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  109. package/dist/lib/merged-outline-node.js +7 -0
  110. package/dist/lib/polygon-union.d.ts +4 -0
  111. package/dist/lib/polygon-union.d.ts.map +1 -0
  112. package/dist/lib/polygon-union.js +289 -0
  113. package/dist/lib/polygon-union.test.d.ts +2 -0
  114. package/dist/lib/polygon-union.test.d.ts.map +1 -0
  115. package/dist/lib/polygon-union.test.js +105 -0
  116. package/dist/lib/scene-themes.d.ts +30 -0
  117. package/dist/lib/scene-themes.d.ts.map +1 -0
  118. package/dist/lib/scene-themes.js +202 -0
  119. package/dist/lib/shadow-only.d.ts +4 -0
  120. package/dist/lib/shadow-only.d.ts.map +1 -0
  121. package/dist/lib/shadow-only.js +36 -0
  122. package/dist/lib/tsl-compat.d.ts +12 -0
  123. package/dist/lib/tsl-compat.d.ts.map +1 -0
  124. package/dist/lib/tsl-compat.js +13 -0
  125. package/dist/store/use-viewer.d.ts +92 -12
  126. package/dist/store/use-viewer.d.ts.map +1 -1
  127. package/dist/store/use-viewer.js +201 -6
  128. package/dist/store/use-viewer.test.d.ts +2 -0
  129. package/dist/store/use-viewer.test.d.ts.map +1 -0
  130. package/dist/store/use-viewer.test.js +42 -0
  131. package/dist/systems/ceiling/ceiling-system.d.ts +6 -2
  132. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  133. package/dist/systems/ceiling/ceiling-system.js +66 -13
  134. package/dist/systems/door/door-animation.test.d.ts +2 -0
  135. package/dist/systems/door/door-animation.test.d.ts.map +1 -0
  136. package/dist/systems/door/door-animation.test.js +51 -0
  137. package/dist/systems/door/door-floor-alignment.test.d.ts +2 -0
  138. package/dist/systems/door/door-floor-alignment.test.d.ts.map +1 -0
  139. package/dist/systems/door/door-floor-alignment.test.js +50 -0
  140. package/dist/systems/door/door-system.d.ts +24 -0
  141. package/dist/systems/door/door-system.d.ts.map +1 -1
  142. package/dist/systems/door/door-system.js +864 -180
  143. package/dist/systems/elevator/elevator-interaction-system.d.ts +2 -0
  144. package/dist/systems/elevator/elevator-interaction-system.d.ts.map +1 -0
  145. package/dist/systems/elevator/elevator-interaction-system.js +62 -0
  146. package/dist/systems/fence/fence-system.d.ts +20 -0
  147. package/dist/systems/fence/fence-system.d.ts.map +1 -1
  148. package/dist/systems/fence/fence-system.js +229 -57
  149. package/dist/systems/floor-elevation/floor-elevation-system.d.ts +20 -0
  150. package/dist/systems/floor-elevation/floor-elevation-system.d.ts.map +1 -0
  151. package/dist/systems/floor-elevation/floor-elevation-system.js +78 -0
  152. package/dist/systems/geometry/geometry-system.d.ts +41 -0
  153. package/dist/systems/geometry/geometry-system.d.ts.map +1 -0
  154. package/dist/systems/geometry/geometry-system.js +348 -0
  155. package/dist/systems/geometry/geometry-system.test.d.ts +2 -0
  156. package/dist/systems/geometry/geometry-system.test.d.ts.map +1 -0
  157. package/dist/systems/geometry/geometry-system.test.js +30 -0
  158. package/dist/systems/interactive/control-widget.d.ts +10 -0
  159. package/dist/systems/interactive/control-widget.d.ts.map +1 -0
  160. package/dist/systems/interactive/control-widget.js +35 -0
  161. package/dist/systems/interactive/interactive-system.d.ts +1 -1
  162. package/dist/systems/interactive/interactive-system.d.ts.map +1 -1
  163. package/dist/systems/interactive/interactive-system.js +55 -56
  164. package/dist/systems/item/item-system.d.ts +7 -0
  165. package/dist/systems/item/item-system.d.ts.map +1 -1
  166. package/dist/systems/item/item-system.js +28 -17
  167. package/dist/systems/item-light/item-light-system.d.ts +1 -1
  168. package/dist/systems/item-light/item-light-system.d.ts.map +1 -1
  169. package/dist/systems/item-light/item-light-system.js +18 -5
  170. package/dist/systems/level/level-system.d.ts.map +1 -1
  171. package/dist/systems/level/level-system.js +28 -4
  172. package/dist/systems/level/level-utils.d.ts +0 -3
  173. package/dist/systems/level/level-utils.d.ts.map +1 -1
  174. package/dist/systems/level/level-utils.js +2 -41
  175. package/dist/systems/roof/roof-materials.d.ts +3 -2
  176. package/dist/systems/roof/roof-materials.d.ts.map +1 -1
  177. package/dist/systems/roof/roof-materials.js +59 -14
  178. package/dist/systems/roof/roof-system.d.ts +46 -6
  179. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  180. package/dist/systems/roof/roof-system.js +1365 -170
  181. package/dist/systems/slab/slab-system.d.ts +5 -3
  182. package/dist/systems/slab/slab-system.d.ts.map +1 -1
  183. package/dist/systems/slab/slab-system.js +204 -68
  184. package/dist/systems/slab/slab-system.test.d.ts +2 -0
  185. package/dist/systems/slab/slab-system.test.d.ts.map +1 -0
  186. package/dist/systems/slab/slab-system.test.js +63 -0
  187. package/dist/systems/stair/stair-materials.d.ts +4 -3
  188. package/dist/systems/stair/stair-materials.d.ts.map +1 -1
  189. package/dist/systems/stair/stair-materials.js +30 -15
  190. package/dist/systems/stair/stair-system.d.ts.map +1 -1
  191. package/dist/systems/stair/stair-system.js +55 -63
  192. package/dist/systems/surface-hole-geometry.d.ts +3 -0
  193. package/dist/systems/surface-hole-geometry.d.ts.map +1 -0
  194. package/dist/systems/surface-hole-geometry.js +4 -0
  195. package/dist/systems/wall/opening-cutout-geometry.d.ts +31 -0
  196. package/dist/systems/wall/opening-cutout-geometry.d.ts.map +1 -0
  197. package/dist/systems/wall/opening-cutout-geometry.js +167 -0
  198. package/dist/systems/wall/opening-cutout-geometry.test.d.ts +2 -0
  199. package/dist/systems/wall/opening-cutout-geometry.test.d.ts.map +1 -0
  200. package/dist/systems/wall/opening-cutout-geometry.test.js +172 -0
  201. package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
  202. package/dist/systems/wall/wall-cutout.js +62 -17
  203. package/dist/systems/wall/wall-materials.d.ts +12 -7
  204. package/dist/systems/wall/wall-materials.d.ts.map +1 -1
  205. package/dist/systems/wall/wall-materials.js +279 -46
  206. package/dist/systems/wall/wall-opening-cutout.test.d.ts +2 -0
  207. package/dist/systems/wall/wall-opening-cutout.test.d.ts.map +1 -0
  208. package/dist/systems/wall/wall-opening-cutout.test.js +59 -0
  209. package/dist/systems/wall/wall-support-extension.test.d.ts +2 -0
  210. package/dist/systems/wall/wall-support-extension.test.d.ts.map +1 -0
  211. package/dist/systems/wall/wall-support-extension.test.js +48 -0
  212. package/dist/systems/wall/wall-system.d.ts +2 -2
  213. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  214. package/dist/systems/wall/wall-system.js +493 -193
  215. package/dist/systems/window/window-animation-system.d.ts +12 -0
  216. package/dist/systems/window/window-animation-system.d.ts.map +1 -1
  217. package/dist/systems/window/window-animation-system.js +16 -5
  218. package/dist/systems/window/window-system.d.ts +7 -0
  219. package/dist/systems/window/window-system.d.ts.map +1 -1
  220. package/dist/systems/window/window-system.js +308 -18
  221. package/package.json +5 -6
  222. package/dist/components/renderers/building/building-renderer.d.ts +0 -5
  223. package/dist/components/renderers/building/building-renderer.d.ts.map +0 -1
  224. package/dist/components/renderers/building/building-renderer.js +0 -11
  225. package/dist/components/renderers/ceiling/ceiling-renderer.d.ts +0 -5
  226. package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +0 -1
  227. package/dist/components/renderers/ceiling/ceiling-renderer.js +0 -58
  228. package/dist/components/renderers/column/column-renderer.d.ts +0 -5
  229. package/dist/components/renderers/column/column-renderer.d.ts.map +0 -1
  230. package/dist/components/renderers/column/column-renderer.js +0 -597
  231. package/dist/components/renderers/door/door-renderer.d.ts +0 -5
  232. package/dist/components/renderers/door/door-renderer.d.ts.map +0 -1
  233. package/dist/components/renderers/door/door-renderer.js +0 -16
  234. package/dist/components/renderers/fence/fence-renderer.d.ts +0 -5
  235. package/dist/components/renderers/fence/fence-renderer.d.ts.map +0 -1
  236. package/dist/components/renderers/fence/fence-renderer.js +0 -15
  237. package/dist/components/renderers/guide/guide-renderer.d.ts +0 -5
  238. package/dist/components/renderers/guide/guide-renderer.d.ts.map +0 -1
  239. package/dist/components/renderers/guide/guide-renderer.js +0 -38
  240. package/dist/components/renderers/item/item-renderer.d.ts +0 -5
  241. package/dist/components/renderers/item/item-renderer.d.ts.map +0 -1
  242. package/dist/components/renderers/item/item-renderer.js +0 -172
  243. package/dist/components/renderers/level/level-renderer.d.ts +0 -5
  244. package/dist/components/renderers/level/level-renderer.d.ts.map +0 -1
  245. package/dist/components/renderers/level/level-renderer.js +0 -11
  246. package/dist/components/renderers/roof/roof-materials.d.ts +0 -4
  247. package/dist/components/renderers/roof/roof-materials.d.ts.map +0 -1
  248. package/dist/components/renderers/roof/roof-materials.js +0 -16
  249. package/dist/components/renderers/roof/roof-renderer.d.ts +0 -5
  250. package/dist/components/renderers/roof/roof-renderer.d.ts.map +0 -1
  251. package/dist/components/renderers/roof/roof-renderer.js +0 -32
  252. package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts +0 -5
  253. package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts.map +0 -1
  254. package/dist/components/renderers/roof-segment/roof-segment-renderer.js +0 -40
  255. package/dist/components/renderers/scan/scan-renderer.d.ts +0 -5
  256. package/dist/components/renderers/scan/scan-renderer.d.ts.map +0 -1
  257. package/dist/components/renderers/scan/scan-renderer.js +0 -54
  258. package/dist/components/renderers/site/site-renderer.d.ts +0 -5
  259. package/dist/components/renderers/site/site-renderer.d.ts.map +0 -1
  260. package/dist/components/renderers/site/site-renderer.js +0 -106
  261. package/dist/components/renderers/slab/slab-renderer.d.ts +0 -5
  262. package/dist/components/renderers/slab/slab-renderer.d.ts.map +0 -1
  263. package/dist/components/renderers/slab/slab-renderer.js +0 -58
  264. package/dist/components/renderers/spawn/spawn-renderer.d.ts +0 -5
  265. package/dist/components/renderers/spawn/spawn-renderer.d.ts.map +0 -1
  266. package/dist/components/renderers/spawn/spawn-renderer.js +0 -32
  267. package/dist/components/renderers/stair/stair-renderer.d.ts +0 -5
  268. package/dist/components/renderers/stair/stair-renderer.d.ts.map +0 -1
  269. package/dist/components/renderers/stair/stair-renderer.js +0 -603
  270. package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts +0 -5
  271. package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +0 -1
  272. package/dist/components/renderers/stair-segment/stair-segment-renderer.js +0 -51
  273. package/dist/components/renderers/wall/wall-renderer.d.ts +0 -5
  274. package/dist/components/renderers/wall/wall-renderer.d.ts.map +0 -1
  275. package/dist/components/renderers/wall/wall-renderer.js +0 -16
  276. package/dist/components/renderers/window/window-renderer.d.ts +0 -5
  277. package/dist/components/renderers/window/window-renderer.d.ts.map +0 -1
  278. package/dist/components/renderers/window/window-renderer.js +0 -21
  279. package/dist/components/renderers/zone/zone-renderer.d.ts +0 -5
  280. package/dist/components/renderers/zone/zone-renderer.d.ts.map +0 -1
  281. package/dist/components/renderers/zone/zone-renderer.js +0 -181
  282. package/dist/components/viewer/ground-occluder.d.ts +0 -2
  283. package/dist/components/viewer/ground-occluder.d.ts.map +0 -1
  284. package/dist/components/viewer/ground-occluder.js +0 -79
@@ -1,8 +1,15 @@
1
- import { getScaledDimensions, resolveLevelId, sceneRegistry, spatialGridManager, useScene, } from '@pascal-app/core';
1
+ import { sceneRegistry, useScene, } from '@pascal-app/core';
2
2
  import { useFrame } from '@react-three/fiber';
3
3
  // ============================================================================
4
4
  // ITEM SYSTEM
5
5
  // ============================================================================
6
+ /**
7
+ * Per-frame wall-side offset for items mounted to wall faces. The slab-
8
+ * elevation lift for floor items lives in the generic
9
+ * `<FloorElevationSystem>` and runs at priority 1 — it has already
10
+ * landed `mesh.position.y` by the time this system clears the dirty
11
+ * mark at priority 2.
12
+ */
6
13
  export const ItemSystem = () => {
7
14
  const dirtyNodes = useScene((state) => state.dirtyNodes);
8
15
  const clearDirty = useScene((state) => state.clearDirty);
@@ -12,31 +19,35 @@ export const ItemSystem = () => {
12
19
  const nodes = useScene.getState().nodes;
13
20
  dirtyNodes.forEach((id) => {
14
21
  const node = nodes[id];
15
- if (!node || node.type !== 'item')
22
+ if (node?.type !== 'item')
16
23
  return;
17
24
  const item = node;
18
25
  const mesh = sceneRegistry.nodes.get(id);
19
26
  if (!mesh)
20
27
  return;
21
28
  if (item.asset.attachTo === 'wall-side') {
22
- // Wall-attached item: offset Z by half the parent wall's thickness
23
- const parentWall = item.parentId ? nodes[item.parentId] : undefined;
24
- if (parentWall && parentWall.type === 'wall') {
25
- const wallThickness = parentWall.thickness ?? 0.1;
29
+ // Wall-attached item: offset Z by half the host wall's thickness.
30
+ // Roof-segment wall faces share the convention — the face frame's
31
+ // z = 0 is the wall mid-plane, so the same push lands the item on
32
+ // the outer surface.
33
+ const parent = item.parentId ? nodes[item.parentId] : undefined;
34
+ const thickness = parent?.type === 'wall'
35
+ ? (parent.thickness ?? 0.1)
36
+ : parent?.type === 'roof-segment'
37
+ ? (parent.wallThickness ?? 0.1)
38
+ : undefined;
39
+ if (thickness !== undefined) {
26
40
  const side = item.side === 'front' ? 1 : -1;
27
- mesh.position.z = (wallThickness / 2) * side;
28
- }
29
- }
30
- else if (!item.asset.attachTo) {
31
- // If parented to another item (surface placement), R3F handles positioning via the hierarchy
32
- const parentNode = item.parentId ? nodes[item.parentId] : undefined;
33
- if (parentNode?.type !== 'item') {
34
- // Floor item: elevate by slab height (using full footprint overlap)
35
- const levelId = resolveLevelId(item, nodes);
36
- const slabElevation = spatialGridManager.getSlabElevationForItem(levelId, item.position, getScaledDimensions(item), item.rotation);
37
- mesh.position.y = slabElevation + item.position[1];
41
+ mesh.position.z = (thickness / 2) * side;
38
42
  }
39
43
  }
44
+ // Hold the mark until the model settles (loaded, terminally failed, or
45
+ // never expected — see ItemRenderer.markSettled). Registration alone
46
+ // isn't "built": clearing then would let scene-ready fire while GLBs are
47
+ // still downloading and a bake would export loading placeholders.
48
+ const settled = mesh.userData.itemModelSettled;
49
+ if (!settled)
50
+ return;
40
51
  clearDirty(id);
41
52
  });
42
53
  }, 2);
@@ -1,2 +1,2 @@
1
- export declare function ItemLightSystem(): import("react/jsx-runtime").JSX.Element;
1
+ export declare function ItemLightSystem(): import("react").JSX.Element;
2
2
  //# sourceMappingURL=item-light-system.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"item-light-system.d.ts","sourceRoot":"","sources":["../../../src/systems/item-light/item-light-system.tsx"],"names":[],"mappings":"AAwFA,wBAAgB,eAAe,4CA+M9B"}
1
+ {"version":3,"file":"item-light-system.d.ts","sourceRoot":"","sources":["../../../src/systems/item-light/item-light-system.tsx"],"names":[],"mappings":"AAuFA,wBAAgB,eAAe,gCA8N9B"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { sceneRegistry, useInteractive, useScene } from '@pascal-app/core';
2
+ import { findLevelAncestorId, sceneRegistry, useInteractive, useScene } from '@pascal-app/core';
3
3
  import { useFrame } from '@react-three/fiber';
4
4
  import { useRef } from 'react';
5
5
  import { MathUtils, Vector3 } from 'three';
@@ -42,8 +42,7 @@ function scoreRegistration(reg, nodes, selectedLevelId, levelMode, interactiveSt
42
42
  // Normalised distance component (assumes scenes < 200 units)
43
43
  const dist = _camPos.distanceTo(_itemPos) / 200;
44
44
  // ── Level factor ──────────────────────────────────────────────────────────
45
- const node = nodes[nodeId];
46
- const itemLevelId = node?.parentId ?? null;
45
+ const itemLevelId = findLevelAncestorId(nodeId, nodes);
47
46
  let levelPenalty = 0;
48
47
  if (selectedLevelId) {
49
48
  if (itemLevelId !== selectedLevelId) {
@@ -97,7 +96,10 @@ export function ItemLightSystem() {
97
96
  }
98
97
  scored.sort((a, b) => a.score - b.score);
99
98
  // Build the desired assignment (top POOL_SIZE keys)
100
- const desired = scored.slice(0, POOL_SIZE).map((s) => s.key);
99
+ const desired = scored
100
+ .filter((s) => Number.isFinite(s.score))
101
+ .slice(0, POOL_SIZE)
102
+ .map((s) => s.key);
101
103
  // Build a map of currently-assigned keys → slot index for hysteresis
102
104
  const currentlyAssigned = new Map();
103
105
  for (let i = 0; i < POOL_SIZE; i++) {
@@ -181,9 +183,11 @@ export function ItemLightSystem() {
181
183
  continue;
182
184
  // Fade-out phase: lerp intensity → 0, then complete the transition
183
185
  if (slot.isFadingOut) {
186
+ light.visible = true;
184
187
  light.intensity = MathUtils.lerp(light.intensity, 0, dt * 12);
185
188
  if (light.intensity < 0.01) {
186
189
  light.intensity = 0;
190
+ light.visible = false;
187
191
  slot.isFadingOut = false;
188
192
  slot.key = slot.pendingKey;
189
193
  slot.pendingKey = null;
@@ -200,12 +204,14 @@ export function ItemLightSystem() {
200
204
  if (!slot.key) {
201
205
  // Idle slot — keep dark
202
206
  light.intensity = 0;
207
+ light.visible = false;
203
208
  continue;
204
209
  }
205
210
  const reg = registrations.get(slot.key);
206
211
  if (!reg) {
207
212
  slot.key = null;
208
213
  light.intensity = 0;
214
+ light.visible = false;
209
215
  continue;
210
216
  }
211
217
  // Snap world position each frame
@@ -226,10 +232,17 @@ export function ItemLightSystem() {
226
232
  const targetIntensity = isOn
227
233
  ? MathUtils.lerp(reg.effect.intensityRange[0], reg.effect.intensityRange[1], t)
228
234
  : reg.effect.intensityRange[0];
235
+ if (targetIntensity > 0) {
236
+ light.visible = true;
237
+ }
229
238
  light.intensity = MathUtils.lerp(light.intensity, targetIntensity, dt * 12);
239
+ if (targetIntensity <= 0 && light.intensity < 0.01) {
240
+ light.intensity = 0;
241
+ light.visible = false;
242
+ }
230
243
  }
231
244
  });
232
- return (_jsx(_Fragment, { children: Array.from({ length: POOL_SIZE }, (_, i) => (_jsx("pointLight", { castShadow: false, intensity: 0, ref: (el) => {
245
+ return (_jsx(_Fragment, { children: Array.from({ length: POOL_SIZE }, (_, i) => (_jsx("pointLight", { castShadow: false, intensity: 0, visible: false, ref: (el) => {
233
246
  lightRefs.current[i] = el;
234
247
  } }, i))) }));
235
248
  }
@@ -1 +1 @@
1
- {"version":3,"file":"level-system.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-system.tsx"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,YAsCvB,CAAA"}
1
+ {"version":3,"file":"level-system.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-system.tsx"],"names":[],"mappings":"AAeA,eAAO,MAAM,WAAW,YA6DvB,CAAA"}
@@ -1,9 +1,14 @@
1
- import { sceneRegistry, useScene } from '@pascal-app/core';
1
+ import { getLevelHeight, sceneRegistry, useScene } from '@pascal-app/core';
2
2
  import { useFrame } from '@react-three/fiber';
3
3
  import { lerp } from 'three/src/math/MathUtils.js';
4
+ import { applyShadowOnly, clearShadowOnly } from '../../lib/shadow-only';
4
5
  import useViewer from '../../store/use-viewer';
5
- import { getLevelHeight } from './level-utils';
6
6
  const EXPLODED_GAP = 5;
7
+ // Levels currently in shadow-caster-only mode (solo hides them from the color
8
+ // passes but keeps their sun shadows). Tracked so we can restore layer masks
9
+ // exactly once on transition; apply re-runs every frame so meshes rebuilt
10
+ // while hidden (theme/texture changes) get re-hidden.
11
+ const shadowOnlyLevels = new WeakSet();
7
12
  export const LevelSystem = () => {
8
13
  useFrame((_, delta) => {
9
14
  const nodes = useScene.getState().nodes;
@@ -19,6 +24,9 @@ export const LevelSystem = () => {
19
24
  });
20
25
  entries.sort((a, b) => a.index - b.index);
21
26
  // Walk sorted levels, accumulating base Y offsets
27
+ const selectedIndex = selectedLevel
28
+ ? entries.find((e) => e.levelId === selectedLevel)?.index
29
+ : undefined;
22
30
  let cumulativeY = 0;
23
31
  for (const { levelId, index, obj } of entries) {
24
32
  const level = nodes[levelId];
@@ -26,8 +34,24 @@ export const LevelSystem = () => {
26
34
  const explodedExtra = levelMode === 'exploded' ? index * EXPLODED_GAP : 0;
27
35
  const targetY = baseY + explodedExtra;
28
36
  obj.position.y = lerp(obj.position.y, targetY, delta * 12); // Smoothly animate to new Y position
29
- obj.visible = levelMode !== 'solo' || level?.id === selectedLevel || !selectedLevel;
30
- cumulativeY += getLevelHeight(levelId, nodes);
37
+ // Solo: hidden levels ABOVE the soloed one stay in the shadow map
38
+ // (shadow-caster-only) so the sun still shadows the soloed floor through
39
+ // them; levels below can't block the sun, so they plain-hide.
40
+ const hidden = levelMode === 'solo' && Boolean(selectedLevel) && level?.id !== selectedLevel;
41
+ const castsWhileHidden = hidden && selectedIndex !== undefined && index > selectedIndex;
42
+ if (castsWhileHidden) {
43
+ applyShadowOnly(obj);
44
+ shadowOnlyLevels.add(obj);
45
+ obj.visible = true;
46
+ }
47
+ else {
48
+ if (shadowOnlyLevels.has(obj)) {
49
+ clearShadowOnly(obj);
50
+ shadowOnlyLevels.delete(obj);
51
+ }
52
+ obj.visible = !hidden;
53
+ }
54
+ cumulativeY += getLevelHeight(levelId, nodes, (wallId) => sceneRegistry.nodes.get(wallId)?.position.y);
31
55
  }
32
56
  }, 5); // Using a lower priority so it runs after transforms from other systems have settled
33
57
  return null;
@@ -1,6 +1,3 @@
1
- import { useScene } from '@pascal-app/core';
2
- export declare const DEFAULT_LEVEL_HEIGHT = 2.5;
3
- export declare function getLevelHeight(levelId: string, nodes: ReturnType<typeof useScene.getState>['nodes']): number;
4
1
  /**
5
2
  * Instantly snaps all level Objects3D to their true stacked Y positions
6
3
  * (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":"AAAA,OAAO,EAIL,QAAQ,EAET,MAAM,kBAAkB,CAAA;AAEzB,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAQvC,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GACnD,MAAM,CA8BR;AAED;;;;;;;;;;;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;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,IAAI,CA6CtD"}
@@ -1,43 +1,4 @@
1
- import { sceneRegistry, useScene, } from '@pascal-app/core';
2
- export const DEFAULT_LEVEL_HEIGHT = 2.5;
3
- // Cache: levelId → computed height. Invalidated when the nodes reference changes.
4
- // Zustand produces a new `nodes` object on every mutation, so reference equality
5
- // is a zero-cost way to detect stale data without any subscription overhead.
6
- const heightCache = new Map();
7
- let lastNodesRef = null;
8
- export function getLevelHeight(levelId, nodes) {
9
- if (nodes !== lastNodesRef) {
10
- heightCache.clear();
11
- lastNodesRef = nodes;
12
- }
13
- if (heightCache.has(levelId))
14
- return heightCache.get(levelId);
15
- const level = nodes[levelId];
16
- if (!level)
17
- return DEFAULT_LEVEL_HEIGHT;
18
- let maxTop = 0;
19
- for (const childId of level.children) {
20
- const child = nodes[childId];
21
- if (!child)
22
- continue;
23
- if (child.type === 'ceiling') {
24
- const ch = child.height ?? DEFAULT_LEVEL_HEIGHT;
25
- if (ch > maxTop)
26
- maxTop = ch;
27
- }
28
- else if (child.type === 'wall') {
29
- let meshY = sceneRegistry.nodes.get(childId)?.position.y ?? 0;
30
- if (meshY < 0)
31
- meshY = 0;
32
- const top = meshY + (child.height ?? DEFAULT_LEVEL_HEIGHT);
33
- if (top > maxTop)
34
- maxTop = top;
35
- }
36
- }
37
- const height = maxTop > 0 ? maxTop : DEFAULT_LEVEL_HEIGHT;
38
- heightCache.set(levelId, height);
39
- return height;
40
- }
1
+ import { getLevelHeight, sceneRegistry, useScene } from '@pascal-app/core';
41
2
  /**
42
3
  * Instantly snaps all level Objects3D to their true stacked Y positions
43
4
  * (ignores levelMode — always uses stacked, no exploded gap).
@@ -68,7 +29,7 @@ export function snapLevelsToTruePositions() {
68
29
  for (const { levelId, obj } of entries) {
69
30
  obj.position.y = cumulativeY;
70
31
  obj.visible = true;
71
- cumulativeY += getLevelHeight(levelId, nodes);
32
+ cumulativeY += getLevelHeight(levelId, nodes, (wallId) => sceneRegistry.nodes.get(wallId)?.position.y);
72
33
  }
73
34
  return () => {
74
35
  for (const { levelId, obj } of entries) {
@@ -1,5 +1,6 @@
1
1
  import { type RoofNode } from '@pascal-app/core';
2
- import * as THREE from 'three';
2
+ import type * as THREE from 'three';
3
+ import { type ColorPreset, type RenderShading } from '../../lib/materials';
3
4
  export type RoofMaterialArray = [THREE.Material, THREE.Material, THREE.Material, THREE.Material];
4
- export declare function getRoofMaterialArray(node: RoofNode): RoofMaterialArray | null;
5
+ export declare function getRoofMaterialArray(node: RoofNode, shading?: RenderShading, textures?: boolean, colorPreset?: ColorPreset, sceneTheme?: string): RoofMaterialArray | null;
5
6
  //# sourceMappingURL=roof-materials.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"roof-materials.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;AA4BhG,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,iBAAiB,GAAG,IAAI,CA8B7E"}
1
+ {"version":3,"file":"roof-materials.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AACnC,OAAO,EACL,KAAK,WAAW,EAIhB,KAAK,aAAa,EAEnB,MAAM,qBAAqB,CAAA;AAa5B,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;AA6BhG,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,EACd,OAAO,GAAE,aAA0B,EACnC,QAAQ,UAAO,EACf,WAAW,GAAE,WAAoB,EACjC,UAAU,CAAC,EAAE,MAAM,GAClB,iBAAiB,GAAG,IAAI,CAsE1B"}
@@ -1,6 +1,15 @@
1
1
  import { getEffectiveRoofSurfaceMaterial, } from '@pascal-app/core';
2
- import * as THREE from 'three';
3
- import { createMaterial, createMaterialFromPresetRef } from '../../lib/materials';
2
+ import { createMaterial, createMaterialFromPresetRef, createSurfaceRoleMaterial, resolveSlotDefaultMaterial, } from '../../lib/materials';
3
+ // Declared catalog defaults for an unpainted roof, per the 4-slot layout
4
+ // (0 wall/trim · 1 deck · 2 interior soffit · 3 shingle top). The wall/trim
5
+ // band mirrors the wall kind's default (WALL_SLOT_DEFAULT = concrete-drywall)
6
+ // so a roof reads as continuous with the walls below it.
7
+ const ROOF_DEFAULT_REFS = [
8
+ 'library:concrete-drywall',
9
+ 'library:preset-softwhite',
10
+ 'library:preset-softwhite',
11
+ 'library:roof-terracottatiles',
12
+ ];
4
13
  const roofMaterialArrayCache = new Map();
5
14
  function getSurfaceMaterialSignature(spec) {
6
15
  return JSON.stringify({
@@ -8,20 +17,24 @@ function getSurfaceMaterialSignature(spec) {
8
17
  materialPreset: spec.materialPreset ?? null,
9
18
  });
10
19
  }
11
- function createResolvedMaterial(material, materialPreset) {
20
+ function createResolvedMaterial(material, materialPreset, shading) {
12
21
  if (materialPreset) {
13
- return createMaterialFromPresetRef(materialPreset);
22
+ return createMaterialFromPresetRef(materialPreset, shading);
14
23
  }
15
24
  if (material) {
16
- return createMaterial(material);
25
+ return createMaterial(material, shading);
17
26
  }
18
27
  return null;
19
28
  }
20
- export function getRoofMaterialArray(node) {
29
+ export function getRoofMaterialArray(node, shading = 'rendered', textures = true, colorPreset = 'clay', sceneTheme) {
21
30
  const top = getEffectiveRoofSurfaceMaterial(node, 'top');
22
31
  const edge = getEffectiveRoofSurfaceMaterial(node, 'edge');
23
32
  const wall = getEffectiveRoofSurfaceMaterial(node, 'wall');
24
33
  const cacheKey = JSON.stringify({
34
+ shading,
35
+ textures,
36
+ colorPreset,
37
+ sceneTheme,
25
38
  top: getSurfaceMaterialSignature(top),
26
39
  edge: getSurfaceMaterialSignature(edge),
27
40
  wall: getSurfaceMaterialSignature(wall),
@@ -29,17 +42,49 @@ export function getRoofMaterialArray(node) {
29
42
  const cached = roofMaterialArrayCache.get(cacheKey);
30
43
  if (cached)
31
44
  return cached;
32
- const topMaterial = createResolvedMaterial(top.material, top.materialPreset);
33
- const edgeMaterial = createResolvedMaterial(edge.material, edge.materialPreset);
34
- const wallMaterial = createResolvedMaterial(wall.material, wall.materialPreset);
45
+ // Themed role colours: roof top/edge use the 'roof' role, the soffit/underside
46
+ // uses 'ceiling'. These also fill any untextured slot so an untextured roof is
47
+ // theme-coloured regardless of the textures toggle (no more white default).
48
+ const roofMaterial = createSurfaceRoleMaterial('roof', colorPreset, undefined, sceneTheme);
49
+ const ceilingMaterial = createSurfaceRoleMaterial('ceiling', colorPreset, undefined, sceneTheme);
50
+ const roleArray = [
51
+ roofMaterial,
52
+ ceilingMaterial,
53
+ ceilingMaterial,
54
+ roofMaterial,
55
+ ];
56
+ // Textures-off (monochrome) is the guaranteed escape hatch: themed role
57
+ // colours, no catalog finishes.
58
+ if (!textures) {
59
+ roofMaterialArrayCache.set(cacheKey, roleArray);
60
+ return roleArray;
61
+ }
62
+ // Textures-on default appearance: catalog finishes per slot (terracotta
63
+ // shingle, soft-white deck/soffit, wall-coloured trim). Used both when the
64
+ // roof is unpainted and to fill any individual unpainted slot below.
65
+ const defaultArray = [
66
+ resolveSlotDefaultMaterial(ROOF_DEFAULT_REFS[0], shading),
67
+ resolveSlotDefaultMaterial(ROOF_DEFAULT_REFS[1], shading),
68
+ resolveSlotDefaultMaterial(ROOF_DEFAULT_REFS[2], shading),
69
+ resolveSlotDefaultMaterial(ROOF_DEFAULT_REFS[3], shading),
70
+ ];
71
+ const topMaterial = createResolvedMaterial(top.material, top.materialPreset, shading);
72
+ const edgeMaterial = createResolvedMaterial(edge.material, edge.materialPreset, shading);
73
+ const wallMaterial = createResolvedMaterial(wall.material, wall.materialPreset, shading);
35
74
  if (!(topMaterial || edgeMaterial || wallMaterial)) {
36
- return null;
75
+ roofMaterialArrayCache.set(cacheKey, defaultArray);
76
+ return defaultArray;
37
77
  }
78
+ // Each slot resolves to its own role only, then the declared default — never
79
+ // another role. Cross-role fallback here used to splatter a single painted
80
+ // surface (e.g. the edge) across the shingle and soffit slots. The legacy
81
+ // catch-all still fills every role because `getEffectiveRoofSurfaceMaterial`
82
+ // returns it for top/edge/wall alike.
38
83
  const materialArray = [
39
- edgeMaterial ?? wallMaterial ?? topMaterial ?? new THREE.MeshStandardMaterial(),
40
- wallMaterial ?? edgeMaterial ?? topMaterial ?? new THREE.MeshStandardMaterial(),
41
- wallMaterial ?? edgeMaterial ?? topMaterial ?? new THREE.MeshStandardMaterial(),
42
- topMaterial ?? wallMaterial ?? edgeMaterial ?? new THREE.MeshStandardMaterial(),
84
+ edgeMaterial ?? defaultArray[0],
85
+ wallMaterial ?? defaultArray[1],
86
+ wallMaterial ?? defaultArray[2],
87
+ topMaterial ?? defaultArray[3],
43
88
  ];
44
89
  roofMaterialArrayCache.set(cacheKey, materialArray);
45
90
  return materialArray;
@@ -1,16 +1,56 @@
1
- import { type RoofSegmentNode } from '@pascal-app/core';
1
+ import { type AnyNode, type RoofSegmentNode } from '@pascal-app/core';
2
2
  import * as THREE from 'three';
3
3
  import { Brush } from 'three-bvh-csg';
4
4
  export declare const RoofSystem: () => null;
5
5
  /**
6
- * Generate complete hollow-shell geometry for a roof segment.
7
- * Ports the prototype's CSG approach using three-bvh-csg.
6
+ * Four dummy materials used as identity placeholders during CSG. Shared
7
+ * across every input brush so three-bvh-csg can preserve reference
8
+ * equality on the result and `mapRoofGroupMaterialIndex` can map result
9
+ * groups back to slots 0..3. Exposed so kinds that compose additional
10
+ * CSG ops on top of `getRoofSegmentBrushes` (e.g. dormer) use the same
11
+ * identity refs.
8
12
  */
9
- export declare function getRoofSegmentBrushes(node: RoofSegmentNode): {
13
+ export declare const roofCsgDummyMats: [
14
+ THREE.MeshBasicMaterial,
15
+ THREE.MeshBasicMaterial,
16
+ THREE.MeshBasicMaterial,
17
+ THREE.MeshBasicMaterial
18
+ ];
19
+ export declare const ROOF_MATERIAL_SLOT_COUNT = 4;
20
+ type RoofSegmentBrushSet = {
10
21
  deckSlab: Brush;
11
22
  shinSlab: Brush;
12
23
  wallBrush: Brush;
13
24
  innerBrush: Brush;
14
- } | null;
15
- export declare function generateRoofSegmentGeometry(node: RoofSegmentNode): THREE.BufferGeometry;
25
+ rakeBoards: THREE.BufferGeometry | null;
26
+ };
27
+ export declare function mapRoofGroupMaterialIndex(groupMaterialIndex: number | undefined, csgMaterials: THREE.Material[], matToIndex: Map<THREE.Material, number>): number;
28
+ /**
29
+ * Subtract a segment's trim cuts from an arbitrary segment-local geometry,
30
+ * returning the clipped result. The input geometry is consumed (disposed) on
31
+ * each successful CSG pass — callers that need to keep the original must pass a
32
+ * clone. Returns the input untouched when the segment has no trim. Used
33
+ * internally for rake-board / end-slope attachments and exported so roof
34
+ * accessories (chimney, vents, skylight, …) can clip their own meshes by the
35
+ * same trim, in the same segment-local frame.
36
+ */
37
+ export declare function clipGeometryBySegmentTrim(geometry: THREE.BufferGeometry | null, segment: RoofSegmentNode): THREE.BufferGeometry | null;
38
+ /**
39
+ * Generate complete hollow-shell geometry for a roof segment.
40
+ * Ports the prototype's CSG approach using three-bvh-csg.
41
+ */
42
+ export declare function getRoofSegmentBrushes(node: RoofSegmentNode): RoofSegmentBrushSet | null;
43
+ export declare function generateRoofSegmentGeometry(node: RoofSegmentNode, nodes?: Record<string, AnyNode>): THREE.BufferGeometry;
44
+ export declare function remapRoofShellFaces(geometry: THREE.BufferGeometry, node: RoofSegmentNode): void;
45
+ export type SurfaceFrame = {
46
+ point: THREE.Vector3;
47
+ normal: THREE.Vector3;
48
+ };
49
+ /**
50
+ * Returns the outer roof surface frame (point + normal) at a given segment-local XZ.
51
+ * This is used for skylight placement + cut direction so cutouts remain perpendicular
52
+ * to the true roof surface even on multi-slope roofs (gambrel/mansard/dutch).
53
+ */
54
+ export declare function getRoofOuterSurfaceFrameAtPoint(segment: RoofSegmentNode, lx: number, lz: number): SurfaceFrame;
55
+ export {};
16
56
  //# sourceMappingURL=roof-system.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EAIrB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,KAAK,EAA0B,MAAM,eAAe,CAAA;AA4CvE,eAAO,MAAM,UAAU,YAsFtB,CAAA;AAqLD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,GACpB;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,KAAK,CAAA;CAAE,GAAG,IAAI,CAqRlF;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,eAAe,GAAG,KAAK,CAAC,cAAc,CAmDvF"}
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"}