@pascal-app/core 1.0.0-beta.5 → 1.0.1

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 (417) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/capture/index.d.ts +3 -0
  4. package/dist/capture/index.d.ts.map +1 -0
  5. package/dist/capture/index.js +2 -0
  6. package/dist/capture/schema.d.ts +417 -0
  7. package/dist/capture/schema.d.ts.map +1 -0
  8. package/dist/capture/schema.js +350 -0
  9. package/dist/capture/source.d.ts +60 -0
  10. package/dist/capture/source.d.ts.map +1 -0
  11. package/dist/capture/source.js +254 -0
  12. package/dist/events/bus.d.ts +58 -7
  13. package/dist/events/bus.d.ts.map +1 -1
  14. package/dist/events/hidden-wall-pointer-hold.d.ts +28 -0
  15. package/dist/events/hidden-wall-pointer-hold.d.ts.map +1 -0
  16. package/dist/events/hidden-wall-pointer-hold.js +37 -0
  17. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +4 -4
  18. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
  19. package/dist/hooks/spatial-grid/floor-placed-elevation.js +7 -12
  20. package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts +4 -0
  21. package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts.map +1 -0
  22. package/dist/hooks/spatial-grid/floor-placed-footprints.js +7 -0
  23. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +5 -8
  24. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  25. package/dist/hooks/spatial-grid/spatial-grid-manager.js +23 -106
  26. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +2931 -2
  27. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  28. package/dist/hooks/spatial-grid/spatial-grid-sync.js +207 -30
  29. package/dist/hooks/spatial-grid/support-host-patch.d.ts +45 -1
  30. package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -1
  31. package/dist/hooks/spatial-grid/support-host-patch.js +174 -9
  32. package/dist/hooks/spatial-grid/use-spatial-query.d.ts +1 -1
  33. package/dist/hooks/spatial-grid/use-spatial-query.js +1 -1
  34. package/dist/index.d.ts +74 -64
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +74 -61
  37. package/dist/lib/asset-storage.d.ts.map +1 -1
  38. package/dist/lib/asset-storage.js +4 -1
  39. package/dist/lib/door-operation.d.ts +1 -1
  40. package/dist/lib/item-polygon-overlap.d.ts +6 -0
  41. package/dist/lib/item-polygon-overlap.d.ts.map +1 -0
  42. package/dist/lib/item-polygon-overlap.js +67 -0
  43. package/dist/lib/level-name.d.ts +1 -1
  44. package/dist/lib/measurement-geometry.d.ts +4 -4
  45. package/dist/lib/plan-footprint.d.ts +41 -0
  46. package/dist/lib/plan-footprint.d.ts.map +1 -0
  47. package/dist/lib/plan-footprint.js +58 -0
  48. package/dist/lib/polygon-union.d.ts +4 -0
  49. package/dist/lib/polygon-union.d.ts.map +1 -0
  50. package/dist/lib/polygon-union.js +306 -0
  51. package/dist/lib/roof-overlap.d.ts +32 -0
  52. package/dist/lib/roof-overlap.d.ts.map +1 -0
  53. package/dist/lib/roof-overlap.js +72 -0
  54. package/dist/lib/room-topology-index.d.ts +1 -1
  55. package/dist/lib/room-topology-index.js +1 -1
  56. package/dist/lib/selection-proxy.d.ts +1 -1
  57. package/dist/lib/slab-polygon.d.ts +36 -3
  58. package/dist/lib/slab-polygon.d.ts.map +1 -1
  59. package/dist/lib/slab-polygon.js +135 -29
  60. package/dist/lib/space-detection.d.ts +12 -1
  61. package/dist/lib/space-detection.d.ts.map +1 -1
  62. package/dist/lib/space-detection.js +58 -25
  63. package/dist/lib/terrain-brush.d.ts +1 -1
  64. package/dist/lib/terrain-brush.js +1 -1
  65. package/dist/lib/terrain-codec.d.ts +2 -2
  66. package/dist/lib/terrain-codec.js +1 -1
  67. package/dist/lib/terrain-raycast.d.ts +1 -1
  68. package/dist/lib/terrain-raycast.js +1 -1
  69. package/dist/lib/terrain-source.d.ts +3 -3
  70. package/dist/lib/terrain-source.js +3 -3
  71. package/dist/lib/terrain-support.d.ts +1 -1
  72. package/dist/lib/terrain-support.js +3 -3
  73. package/dist/lib/unit-containment.d.ts +19 -0
  74. package/dist/lib/unit-containment.d.ts.map +1 -0
  75. package/dist/lib/unit-containment.js +158 -0
  76. package/dist/lib/unit-report.d.ts +19 -0
  77. package/dist/lib/unit-report.d.ts.map +1 -0
  78. package/dist/lib/unit-report.js +36 -0
  79. package/dist/lib/wall-distance.d.ts +2 -2
  80. package/dist/lib/wall-distance.js +1 -1
  81. package/dist/lib/zone-quantities.d.ts +1 -1
  82. package/dist/lib/zone-quantities.js +7 -7
  83. package/dist/material-library.d.ts +1 -1
  84. package/dist/material-library.js +1 -1
  85. package/dist/procedural-items/fixtures.d.ts +261 -0
  86. package/dist/procedural-items/fixtures.d.ts.map +1 -0
  87. package/dist/procedural-items/fixtures.js +349 -0
  88. package/dist/procedural-items/index.d.ts +10 -0
  89. package/dist/procedural-items/index.d.ts.map +1 -0
  90. package/dist/procedural-items/index.js +9 -0
  91. package/dist/procedural-items/integration.d.ts +92 -0
  92. package/dist/procedural-items/integration.d.ts.map +1 -0
  93. package/dist/procedural-items/integration.js +19 -0
  94. package/dist/procedural-items/library-colors.d.ts +56 -0
  95. package/dist/procedural-items/library-colors.d.ts.map +1 -0
  96. package/dist/procedural-items/library-colors.js +84 -0
  97. package/dist/procedural-items/materials.d.ts +5 -0
  98. package/dist/procedural-items/materials.d.ts.map +1 -0
  99. package/dist/procedural-items/materials.js +47 -0
  100. package/dist/procedural-items/node.d.ts +280 -0
  101. package/dist/procedural-items/node.d.ts.map +1 -0
  102. package/dist/procedural-items/node.js +71 -0
  103. package/dist/procedural-items/placement.d.ts +7 -0
  104. package/dist/procedural-items/placement.d.ts.map +1 -0
  105. package/dist/procedural-items/placement.js +48 -0
  106. package/dist/procedural-items/query.d.ts +50 -0
  107. package/dist/procedural-items/query.d.ts.map +1 -0
  108. package/dist/procedural-items/query.js +298 -0
  109. package/dist/procedural-items/recipe.d.ts +144 -0
  110. package/dist/procedural-items/recipe.d.ts.map +1 -0
  111. package/dist/procedural-items/recipe.js +372 -0
  112. package/dist/procedural-items/spatial.d.ts +19 -0
  113. package/dist/procedural-items/spatial.d.ts.map +1 -0
  114. package/dist/procedural-items/spatial.js +39 -0
  115. package/dist/registry/__bench__/relations-resolver.bench.js +2 -2
  116. package/dist/registry/handles.d.ts +36 -7
  117. package/dist/registry/handles.d.ts.map +1 -1
  118. package/dist/registry/index.d.ts +6 -7
  119. package/dist/registry/index.d.ts.map +1 -1
  120. package/dist/registry/index.js +4 -5
  121. package/dist/registry/registry.d.ts +13 -6
  122. package/dist/registry/registry.d.ts.map +1 -1
  123. package/dist/registry/registry.js +37 -4
  124. package/dist/registry/relations-resolver.d.ts +2 -2
  125. package/dist/registry/relations-resolver.js +1 -1
  126. package/dist/registry/scene-api.d.ts +18 -2
  127. package/dist/registry/scene-api.d.ts.map +1 -1
  128. package/dist/registry/scene-api.js +50 -2
  129. package/dist/registry/subtree.d.ts +1 -1
  130. package/dist/registry/subtree.js +2 -2
  131. package/dist/registry/types.d.ts +246 -21
  132. package/dist/registry/types.d.ts.map +1 -1
  133. package/dist/registry/use-registry-version.js +1 -1
  134. package/dist/registry/validate-relations.d.ts +4 -0
  135. package/dist/registry/validate-relations.d.ts.map +1 -0
  136. package/dist/registry/validate-relations.js +22 -0
  137. package/dist/schema/__bench__/node-parsers.bench.d.ts +24 -0
  138. package/dist/schema/__bench__/node-parsers.bench.d.ts.map +1 -0
  139. package/dist/schema/__bench__/node-parsers.bench.js +314 -0
  140. package/dist/schema/__fixtures__/node-fixtures.d.ts +28 -0
  141. package/dist/schema/__fixtures__/node-fixtures.d.ts.map +1 -0
  142. package/dist/schema/__fixtures__/node-fixtures.js +127 -0
  143. package/dist/schema/base.d.ts +1 -1
  144. package/dist/schema/base.d.ts.map +1 -1
  145. package/dist/schema/base.js +9 -2
  146. package/dist/schema/collections.d.ts +1 -1
  147. package/dist/schema/collections.js +1 -1
  148. package/dist/schema/compiled-node-parsers.d.ts +40 -0
  149. package/dist/schema/compiled-node-parsers.d.ts.map +1 -0
  150. package/dist/schema/compiled-node-parsers.js +95 -0
  151. package/dist/schema/index.d.ts +73 -66
  152. package/dist/schema/index.d.ts.map +1 -1
  153. package/dist/schema/index.js +65 -57
  154. package/dist/schema/material.d.ts +1 -0
  155. package/dist/schema/material.d.ts.map +1 -1
  156. package/dist/schema/material.js +2 -1
  157. package/dist/schema/nodes/automatic-downspout.d.ts +17 -0
  158. package/dist/schema/nodes/automatic-downspout.d.ts.map +1 -0
  159. package/dist/schema/nodes/automatic-downspout.js +237 -0
  160. package/dist/schema/nodes/block.d.ts +107 -0
  161. package/dist/schema/nodes/block.d.ts.map +1 -0
  162. package/dist/schema/nodes/block.js +206 -0
  163. package/dist/schema/nodes/box-vent.d.ts +8 -2
  164. package/dist/schema/nodes/box-vent.d.ts.map +1 -1
  165. package/dist/schema/nodes/box-vent.js +4 -2
  166. package/dist/schema/nodes/building.d.ts +2 -2
  167. package/dist/schema/nodes/building.d.ts.map +1 -1
  168. package/dist/schema/nodes/building.js +8 -5
  169. package/dist/schema/nodes/cabinet.d.ts +26 -4
  170. package/dist/schema/nodes/cabinet.d.ts.map +1 -1
  171. package/dist/schema/nodes/cabinet.js +29 -8
  172. package/dist/schema/nodes/ceiling.d.ts +2 -2
  173. package/dist/schema/nodes/ceiling.js +5 -5
  174. package/dist/schema/nodes/chimney.d.ts +2 -2
  175. package/dist/schema/nodes/chimney.js +2 -2
  176. package/dist/schema/nodes/column.d.ts +7 -6
  177. package/dist/schema/nodes/column.d.ts.map +1 -1
  178. package/dist/schema/nodes/column.js +3 -2
  179. package/dist/schema/nodes/construction-dimension.d.ts +1 -1
  180. package/dist/schema/nodes/construction-dimension.js +2 -2
  181. package/dist/schema/nodes/cupola.d.ts +9 -1
  182. package/dist/schema/nodes/cupola.d.ts.map +1 -1
  183. package/dist/schema/nodes/cupola.js +4 -2
  184. package/dist/schema/nodes/door.d.ts +1 -1
  185. package/dist/schema/nodes/door.js +2 -2
  186. package/dist/schema/nodes/dormer.d.ts +45 -2
  187. package/dist/schema/nodes/dormer.d.ts.map +1 -1
  188. package/dist/schema/nodes/dormer.js +133 -9
  189. package/dist/schema/nodes/downspout.d.ts +11 -1
  190. package/dist/schema/nodes/downspout.d.ts.map +1 -1
  191. package/dist/schema/nodes/downspout.js +26 -2
  192. package/dist/schema/nodes/duct-fitting.d.ts +18 -1
  193. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -1
  194. package/dist/schema/nodes/duct-fitting.js +26 -5
  195. package/dist/schema/nodes/duct-segment.d.ts +23 -1
  196. package/dist/schema/nodes/duct-segment.d.ts.map +1 -1
  197. package/dist/schema/nodes/duct-segment.js +21 -1
  198. package/dist/schema/nodes/duct-terminal.d.ts +1 -1
  199. package/dist/schema/nodes/duct-terminal.js +1 -1
  200. package/dist/schema/nodes/elevator.d.ts +1 -1
  201. package/dist/schema/nodes/elevator.js +2 -2
  202. package/dist/schema/nodes/eyebrow-vent.d.ts +8 -2
  203. package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -1
  204. package/dist/schema/nodes/eyebrow-vent.js +4 -2
  205. package/dist/schema/nodes/fence.d.ts +1 -1
  206. package/dist/schema/nodes/fence.js +2 -2
  207. package/dist/schema/nodes/guide.d.ts +1 -1
  208. package/dist/schema/nodes/guide.js +2 -2
  209. package/dist/schema/nodes/gutter.d.ts +36 -2
  210. package/dist/schema/nodes/gutter.d.ts.map +1 -1
  211. package/dist/schema/nodes/gutter.js +310 -3
  212. package/dist/schema/nodes/hanger-overrides.d.ts +7 -0
  213. package/dist/schema/nodes/hanger-overrides.d.ts.map +1 -0
  214. package/dist/schema/nodes/hanger-overrides.js +6 -0
  215. package/dist/schema/nodes/hvac-equipment.d.ts +1 -1
  216. package/dist/schema/nodes/hvac-equipment.js +1 -1
  217. package/dist/schema/nodes/imported-mesh.d.ts +40 -0
  218. package/dist/schema/nodes/imported-mesh.d.ts.map +1 -0
  219. package/dist/schema/nodes/imported-mesh.js +27 -0
  220. package/dist/schema/nodes/item.d.ts +3 -2
  221. package/dist/schema/nodes/item.d.ts.map +1 -1
  222. package/dist/schema/nodes/item.js +8 -3
  223. package/dist/schema/nodes/lean-to-extension.d.ts +212 -0
  224. package/dist/schema/nodes/lean-to-extension.d.ts.map +1 -0
  225. package/dist/schema/nodes/lean-to-extension.js +114 -0
  226. package/dist/schema/nodes/level.d.ts +2 -2
  227. package/dist/schema/nodes/level.d.ts.map +1 -1
  228. package/dist/schema/nodes/level.js +1 -1
  229. package/dist/schema/nodes/lineset.d.ts +1 -1
  230. package/dist/schema/nodes/lineset.js +1 -1
  231. package/dist/schema/nodes/liquid-line.d.ts +1 -1
  232. package/dist/schema/nodes/liquid-line.js +1 -1
  233. package/dist/schema/nodes/measurement.d.ts +1 -1
  234. package/dist/schema/nodes/measurement.js +2 -2
  235. package/dist/schema/nodes/pipe-fitting.d.ts +10 -2
  236. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -1
  237. package/dist/schema/nodes/pipe-fitting.js +7 -3
  238. package/dist/schema/nodes/pipe-segment.d.ts +24 -2
  239. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -1
  240. package/dist/schema/nodes/pipe-segment.js +21 -1
  241. package/dist/schema/nodes/pipe-trap.d.ts +2 -2
  242. package/dist/schema/nodes/pipe-trap.js +1 -1
  243. package/dist/schema/nodes/ridge-vent.d.ts +2 -2
  244. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
  245. package/dist/schema/nodes/ridge-vent.js +7 -4
  246. package/dist/schema/nodes/roof-segment-shape.d.ts +5 -1
  247. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -1
  248. package/dist/schema/nodes/roof-segment-shape.js +65 -2
  249. package/dist/schema/nodes/roof-segment-walls.d.ts +4 -2
  250. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -1
  251. package/dist/schema/nodes/roof-segment-walls.js +2 -2
  252. package/dist/schema/nodes/roof-segment.d.ts +42 -2
  253. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  254. package/dist/schema/nodes/roof-segment.js +81 -4
  255. package/dist/schema/nodes/roof.d.ts +23 -2
  256. package/dist/schema/nodes/roof.d.ts.map +1 -1
  257. package/dist/schema/nodes/roof.js +17 -3
  258. package/dist/schema/nodes/scan.d.ts +19 -2
  259. package/dist/schema/nodes/scan.d.ts.map +1 -1
  260. package/dist/schema/nodes/scan.js +13 -3
  261. package/dist/schema/nodes/shelf.d.ts +3 -3
  262. package/dist/schema/nodes/shelf.d.ts.map +1 -1
  263. package/dist/schema/nodes/shelf.js +3 -4
  264. package/dist/schema/nodes/site.d.ts +1 -1
  265. package/dist/schema/nodes/site.js +2 -2
  266. package/dist/schema/nodes/skylight.d.ts +5 -5
  267. package/dist/schema/nodes/skylight.js +2 -2
  268. package/dist/schema/nodes/slab.d.ts +1 -1
  269. package/dist/schema/nodes/slab.js +3 -3
  270. package/dist/schema/nodes/solar-panel.d.ts +1 -1
  271. package/dist/schema/nodes/solar-panel.js +3 -3
  272. package/dist/schema/nodes/spawn.d.ts +1 -1
  273. package/dist/schema/nodes/spawn.js +1 -1
  274. package/dist/schema/nodes/stair-segment.d.ts +1 -1
  275. package/dist/schema/nodes/stair-segment.js +2 -2
  276. package/dist/schema/nodes/stair.d.ts +2 -2
  277. package/dist/schema/nodes/stair.js +3 -3
  278. package/dist/schema/nodes/structural-grid.d.ts +1 -1
  279. package/dist/schema/nodes/structural-grid.js +1 -1
  280. package/dist/schema/nodes/turbine-vent.d.ts +8 -2
  281. package/dist/schema/nodes/turbine-vent.d.ts.map +1 -1
  282. package/dist/schema/nodes/turbine-vent.js +4 -2
  283. package/dist/schema/nodes/unit.d.ts +33 -0
  284. package/dist/schema/nodes/unit.d.ts.map +1 -0
  285. package/dist/schema/nodes/unit.js +13 -0
  286. package/dist/schema/nodes/wall.d.ts +5 -5
  287. package/dist/schema/nodes/wall.d.ts.map +1 -1
  288. package/dist/schema/nodes/wall.js +13 -6
  289. package/dist/schema/nodes/window.d.ts +10 -3
  290. package/dist/schema/nodes/window.d.ts.map +1 -1
  291. package/dist/schema/nodes/window.js +6 -2
  292. package/dist/schema/nodes/zone.d.ts +2 -2
  293. package/dist/schema/nodes/zone.js +2 -2
  294. package/dist/schema/scene-material.js +2 -2
  295. package/dist/schema/types.d.ts +815 -118
  296. package/dist/schema/types.d.ts.map +1 -1
  297. package/dist/schema/types.js +79 -46
  298. package/dist/services/alignment-anchors.d.ts +6 -11
  299. package/dist/services/alignment-anchors.d.ts.map +1 -1
  300. package/dist/services/alignment-anchors.js +7 -34
  301. package/dist/services/drag-session.d.ts +4 -4
  302. package/dist/services/drag-session.js +1 -1
  303. package/dist/services/hosting.d.ts +4 -10
  304. package/dist/services/hosting.d.ts.map +1 -1
  305. package/dist/services/hosting.js +6 -16
  306. package/dist/services/index.d.ts +16 -13
  307. package/dist/services/index.d.ts.map +1 -1
  308. package/dist/services/index.js +16 -13
  309. package/dist/services/level-height.d.ts +2 -2
  310. package/dist/services/level-height.js +3 -3
  311. package/dist/services/movement.d.ts +3 -3
  312. package/dist/services/movement.js +2 -2
  313. package/dist/services/port-connectivity.d.ts +1 -1
  314. package/dist/services/port-connectivity.js +1 -1
  315. package/dist/services/riser-diagram.d.ts +1 -1
  316. package/dist/services/shelf-board.d.ts +5 -0
  317. package/dist/services/shelf-board.d.ts.map +1 -0
  318. package/dist/services/shelf-board.js +15 -0
  319. package/dist/services/storey.d.ts +2 -2
  320. package/dist/services/storey.js +2 -2
  321. package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts +13 -0
  322. package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts.map +1 -0
  323. package/dist/services/surface-hosting-procedural-parity.fixtures.js +4691 -0
  324. package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts +1060 -0
  325. package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts.map +1 -0
  326. package/dist/services/surface-hosting-shelf-parity.fixtures.js +3127 -0
  327. package/dist/services/surface-hosting.d.ts +88 -0
  328. package/dist/services/surface-hosting.d.ts.map +1 -0
  329. package/dist/services/surface-hosting.js +268 -0
  330. package/dist/services/surface-region.d.ts +8 -0
  331. package/dist/services/surface-region.d.ts.map +1 -0
  332. package/dist/services/surface-region.js +44 -0
  333. package/dist/services/system-graph.d.ts +12 -1
  334. package/dist/services/system-graph.d.ts.map +1 -1
  335. package/dist/services/system-graph.js +36 -6
  336. package/dist/services/validate-dwv.d.ts +1 -1
  337. package/dist/services/validate-dwv.js +1 -1
  338. package/dist/store/actions/node-actions.d.ts +9 -2
  339. package/dist/store/actions/node-actions.d.ts.map +1 -1
  340. package/dist/store/actions/node-actions.js +475 -24
  341. package/dist/store/history-control.d.ts +3 -3
  342. package/dist/store/history-invalidation.d.ts +3 -0
  343. package/dist/store/history-invalidation.d.ts.map +1 -0
  344. package/dist/store/history-invalidation.js +72 -0
  345. package/dist/store/scene-hydration.d.ts +5 -0
  346. package/dist/store/scene-hydration.d.ts.map +1 -0
  347. package/dist/store/scene-hydration.js +57 -0
  348. package/dist/store/use-interactive.d.ts +2 -2
  349. package/dist/store/use-live-terrain.d.ts +1 -1
  350. package/dist/store/use-scene.d.ts +7 -4
  351. package/dist/store/use-scene.d.ts.map +1 -1
  352. package/dist/store/use-scene.js +361 -87
  353. package/dist/systems/elevator/elevator-dispatch.d.ts +2 -2
  354. package/dist/systems/elevator/elevator-dispatch.js +1 -1
  355. package/dist/systems/elevator/elevator-geometry.d.ts +1 -1
  356. package/dist/systems/elevator/elevator-opening-sync.d.ts +1 -1
  357. package/dist/systems/elevator/elevator-opening-sync.js +2 -2
  358. package/dist/systems/elevator/elevator-opening-system.js +3 -3
  359. package/dist/systems/elevator/elevator-runtime.d.ts +3 -3
  360. package/dist/systems/elevator/elevator-runtime.js +3 -3
  361. package/dist/systems/elevator/elevator-service.d.ts +1 -1
  362. package/dist/systems/elevator/elevator-service.js +1 -1
  363. package/dist/systems/fence/fence-centerline.d.ts +2 -2
  364. package/dist/systems/fence/fence-centerline.js +2 -2
  365. package/dist/systems/fence/fence-spline.d.ts +2 -2
  366. package/dist/systems/roof/roof-elevation-system.d.ts +3 -0
  367. package/dist/systems/roof/roof-elevation-system.d.ts.map +1 -0
  368. package/dist/systems/roof/roof-elevation-system.js +94 -0
  369. package/dist/systems/roof/roof-elevation.d.ts +4 -0
  370. package/dist/systems/roof/roof-elevation.d.ts.map +1 -0
  371. package/dist/systems/roof/roof-elevation.js +95 -0
  372. package/dist/systems/roof/roof-footprint.d.ts +17 -0
  373. package/dist/systems/roof/roof-footprint.d.ts.map +1 -0
  374. package/dist/systems/roof/roof-footprint.js +83 -0
  375. package/dist/systems/slab/slab-placement.d.ts +1 -1
  376. package/dist/systems/slab/slab-support.d.ts +1 -1
  377. package/dist/systems/slab/slab-support.js +4 -4
  378. package/dist/systems/stair/stair-flight.d.ts +17 -0
  379. package/dist/systems/stair/stair-flight.d.ts.map +1 -0
  380. package/dist/systems/stair/stair-flight.js +27 -0
  381. package/dist/systems/stair/stair-footprint.d.ts +1 -1
  382. package/dist/systems/stair/stair-opening-preview.d.ts +1621 -1267
  383. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  384. package/dist/systems/stair/stair-opening-preview.js +2 -2
  385. package/dist/systems/stair/stair-opening-sync.d.ts +1 -1
  386. package/dist/systems/stair/stair-opening-sync.js +6 -6
  387. package/dist/systems/stair/stair-opening-system.d.ts +1 -0
  388. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
  389. package/dist/systems/stair/stair-opening-system.js +100 -103
  390. package/dist/systems/stair/stair-rise.d.ts +1 -1
  391. package/dist/systems/stair/stair-rise.d.ts.map +1 -1
  392. package/dist/systems/stair/stair-rise.js +23 -24
  393. package/dist/systems/wall/wall-curve.d.ts +3 -2
  394. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  395. package/dist/systems/wall/wall-curve.js +73 -0
  396. package/dist/systems/wall/wall-footprint.d.ts +3 -2
  397. package/dist/systems/wall/wall-footprint.d.ts.map +1 -1
  398. package/dist/systems/wall/wall-footprint.js +3 -2
  399. package/dist/systems/wall/wall-mitering.d.ts +1 -1
  400. package/dist/systems/wall/wall-mitering.js +1 -1
  401. package/dist/systems/wall/wall-move.d.ts +1 -1
  402. package/dist/systems/wall/wall-top.d.ts +1 -1
  403. package/dist/systems/wall/wall-topology.d.ts +2 -2
  404. package/dist/systems/wall/wall-topology.js +4 -4
  405. package/dist/utils/clone-scene-graph.d.ts +3 -3
  406. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  407. package/dist/utils/clone-scene-graph.js +35 -3
  408. package/dist/utils/scene-migrations.d.ts +3 -3
  409. package/dist/utils/scene-migrations.js +3 -3
  410. package/dist/utils/vertical-scene-migration.js +5 -5
  411. package/dist/validation/validate-build-json.d.ts +7 -1
  412. package/dist/validation/validate-build-json.d.ts.map +1 -1
  413. package/dist/validation/validate-build-json.js +92 -4
  414. package/package.json +23 -5
  415. package/dist/systems/elevator/elevator-runtime-system.d.ts +0 -2
  416. package/dist/systems/elevator/elevator-runtime-system.d.ts.map +0 -1
  417. package/dist/systems/elevator/elevator-runtime-system.js +0 -8
@@ -1 +1 @@
1
- {"version":3,"file":"stair-opening-preview.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-opening-preview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC7E,OAA6B,EAAE,KAAK,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAClG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AAGpE,KAAK,oBAAoB,GAAG;IAC1B,EAAE,EAAE,SAAS,CAAA;IACb,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,WAAW,CAAC,CAAA;CACtC,CAAA;AAoBD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,cAAc,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,EAClD,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACrD,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,WAYvC;AAED,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,cAAc,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,EAClD,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACrD,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwBvC;AAED,wBAAgB,qCAAqC;;mBAUlC,oBAAoB,EAAE;;EAiCxC"}
1
+ {"version":3,"file":"stair-opening-preview.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-opening-preview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC7E,OAA6B,EAAE,KAAK,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAClG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AAGpE,KAAK,oBAAoB,GAAG;IAC1B,EAAE,EAAE,SAAS,CAAA;IACb,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,WAAW,CAAC,CAAA;CACtC,CAAA;AAoBD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,cAAc,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,EAClD,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACrD,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,WAYvC;AAED,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,cAAc,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,EAClD,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACrD,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwBvC;AAED,wBAAgB,qCAAqC;;mBAUlC,oBAAoB,EAAE;;EAiCxC"}
@@ -1,5 +1,5 @@
1
- import useLiveNodeOverrides, {} from '../../store/use-live-node-overrides';
2
- import useScene from '../../store/use-scene';
1
+ import useLiveNodeOverrides, {} from '../../store/use-live-node-overrides.js';
2
+ import useScene from '../../store/use-scene.js';
3
3
  const SURFACE_OPENING_FIELDS = ['holes', 'holeMetadata'];
4
4
  function isSurface(node) {
5
5
  return node?.type === 'slab' || node?.type === 'ceiling';
@@ -1,4 +1,4 @@
1
- import type { AnyNode, AnyNodeId, CeilingNode, SlabNode } from '../../schema';
1
+ import type { AnyNode, AnyNodeId, CeilingNode, SlabNode } from '../../schema/index.js';
2
2
  export declare function syncAutoStairOpenings(nodes: Record<string, AnyNode>): {
3
3
  id: AnyNodeId;
4
4
  data: Partial<SlabNode | CeilingNode>;
@@ -1,9 +1,9 @@
1
- import { resolveBuildingForLevel, resolveLevelId } from '../../hooks/spatial-grid/spatial-grid-sync';
2
- import { polygonContainsPolygon, polygonsOverlap } from '../../lib/polygon-relations';
3
- import { resolveCeilingHeight } from '../../services/level-height';
4
- import { getLevelElevations } from '../../services/storey';
5
- import { computeSegmentTransforms, rotateXZ } from './stair-footprint';
6
- import { resolveStairTotalRise } from './stair-rise';
1
+ import { resolveBuildingForLevel, resolveLevelId } from '../../hooks/spatial-grid/spatial-grid-sync.js';
2
+ import { polygonContainsPolygon, polygonsOverlap } from '../../lib/polygon-relations.js';
3
+ import { resolveCeilingHeight } from '../../services/level-height.js';
4
+ import { getLevelElevations } from '../../services/storey.js';
5
+ import { computeSegmentTransforms, rotateXZ } from './stair-footprint.js';
6
+ import { resolveStairTotalRise } from './stair-rise.js';
7
7
  const CURVED_STAIR_SLAB_OPENING_RATIO = 0.8;
8
8
  const STRAIGHT_STAIR_TARGET_THRESHOLD_MIN = 0.35;
9
9
  const STAIR_SLAB_OPENING_TIGHTENING = 0;
@@ -1,2 +1,3 @@
1
+ export declare function initializeStairOpeningSync(): () => void;
1
2
  export declare const StairOpeningSystem: () => null;
2
3
  //# sourceMappingURL=stair-opening-system.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stair-opening-system.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-opening-system.tsx"],"names":[],"mappings":"AA4CA,eAAO,MAAM,kBAAkB,YAoH9B,CAAA"}
1
+ {"version":3,"file":"stair-opening-system.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-opening-system.tsx"],"names":[],"mappings":"AA6CA,wBAAgB,0BAA0B,eAsGzC;AAED,eAAO,MAAM,kBAAkB,YAG9B,CAAA"}
@@ -1,12 +1,13 @@
1
1
  'use client';
2
- import { useEffect, useRef } from 'react';
3
- import { pauseSceneHistory, resumeSceneHistory } from '../../store/history-control';
4
- import useLiveNodeOverrides from '../../store/use-live-node-overrides';
5
- import useLiveTransforms from '../../store/use-live-transforms';
6
- import useScene from '../../store/use-scene';
7
- import { createSurfaceOpeningPreviewController, getNodesWithLiveStairOpeningInputs, hasLiveStairOpeningInputs, } from './stair-opening-preview';
8
- import { syncAutoStairOpenings } from './stair-opening-sync';
9
- import { syncStairRises } from './stair-rise';
2
+ import { useEffect } from 'react';
3
+ import { pauseSceneHistory, resumeSceneHistory } from '../../store/history-control.js';
4
+ import { queueSceneNormalization } from '../../store/scene-hydration.js';
5
+ import useLiveNodeOverrides from '../../store/use-live-node-overrides.js';
6
+ import useLiveTransforms from '../../store/use-live-transforms.js';
7
+ import useScene from '../../store/use-scene.js';
8
+ import { createSurfaceOpeningPreviewController, getNodesWithLiveStairOpeningInputs, hasLiveStairOpeningInputs, } from './stair-opening-preview.js';
9
+ import { syncAutoStairOpenings } from './stair-opening-sync.js';
10
+ import { syncStairRises } from './stair-rise.js';
10
11
  function isOpeningRelevantNode(node) {
11
12
  return (node?.type === 'building' ||
12
13
  node?.type === 'ceiling' ||
@@ -29,104 +30,100 @@ function hasOpeningRelevantNodeChange(nextNodes, prevNodes) {
29
30
  }
30
31
  return false;
31
32
  }
32
- export const StairOpeningSystem = () => {
33
- const syncingAutoOpeningsRef = useRef(false);
34
- const syncingPreviewOpeningsRef = useRef(false);
35
- const previewControllerRef = useRef(createSurfaceOpeningPreviewController());
36
- useEffect(() => {
37
- const applyUpdates = (updates) => {
38
- if (updates.length === 0)
39
- return;
40
- syncingAutoOpeningsRef.current = true;
41
- pauseSceneHistory(useScene);
42
- try {
43
- useScene.getState().updateNodes(updates);
44
- }
45
- finally {
46
- resumeSceneHistory(useScene);
47
- }
48
- queueMicrotask(() => {
49
- syncingAutoOpeningsRef.current = false;
50
- });
51
- };
52
- const applyPreviewUpdates = (updates) => {
53
- syncingPreviewOpeningsRef.current = true;
54
- previewControllerRef.current.apply(updates);
55
- queueMicrotask(() => {
56
- syncingPreviewOpeningsRef.current = false;
57
- });
58
- };
59
- const clearPreviewUpdates = () => {
60
- if (previewControllerRef.current.previewSurfaceIds.size === 0)
61
- return;
62
- syncingPreviewOpeningsRef.current = true;
63
- previewControllerRef.current.clear();
64
- queueMicrotask(() => {
65
- syncingPreviewOpeningsRef.current = false;
66
- });
67
- };
68
- const refreshLivePreview = () => {
69
- if (syncingPreviewOpeningsRef.current)
70
- return;
71
- const nodes = useScene.getState().nodes;
72
- const liveTransforms = useLiveTransforms.getState().transforms;
73
- const liveOverrides = useLiveNodeOverrides.getState().overrides;
74
- const previewSurfaceIds = previewControllerRef.current.previewSurfaceIds;
75
- if (!hasLiveStairOpeningInputs(nodes, liveTransforms, liveOverrides, previewSurfaceIds)) {
76
- clearPreviewUpdates();
77
- return;
78
- }
79
- applyPreviewUpdates(syncAutoStairOpenings(getNodesWithLiveStairOpeningInputs(nodes, liveTransforms, liveOverrides, previewSurfaceIds)));
80
- };
81
- const runAutoSync = () => {
82
- // Rise first: straight stairs converge their flight heights to the
83
- // resolved rise (level height or deck elevation), and the opening pass
84
- // reads those segment heights — so it must run against the post-rise
85
- // nodes.
86
- applyUpdates(syncStairRises(useScene.getState().nodes));
87
- applyUpdates(syncAutoStairOpenings(useScene.getState().nodes));
88
- };
89
- let disposed = false;
90
- let autoSyncQueued = false;
91
- const scheduleAutoSync = () => {
92
- if (autoSyncQueued)
93
- return;
94
- autoSyncQueued = true;
95
- // One microtask later so every other scene-store listener for the
96
- // triggering transition (and, at mount, the editor's spatial-grid
97
- // init) runs first — the spatial-grid sync in particular. The
98
- // deck-attached rise elects the stair's floor-stack base elevation
99
- // through the spatial grid; syncing before the grid listener would
100
- // rescale flights against the pre-transition slab state.
101
- queueMicrotask(() => {
102
- autoSyncQueued = false;
103
- if (disposed)
104
- return;
105
- runAutoSync();
106
- refreshLivePreview();
107
- });
108
- };
109
- scheduleAutoSync();
110
- const unsubscribeScene = useScene.subscribe((state, prevState) => {
111
- if (syncingAutoOpeningsRef.current)
112
- return;
113
- if (!hasOpeningRelevantNodeChange(state.nodes, prevState.nodes))
114
- return;
115
- scheduleAutoSync();
33
+ export function initializeStairOpeningSync() {
34
+ let syncingAutoOpenings = false;
35
+ let syncingPreviewOpenings = false;
36
+ const previewController = createSurfaceOpeningPreviewController();
37
+ const applyUpdates = (updates) => {
38
+ if (updates.length === 0)
39
+ return;
40
+ syncingAutoOpenings = true;
41
+ pauseSceneHistory(useScene);
42
+ try {
43
+ useScene.getState().updateNodes(updates);
44
+ }
45
+ finally {
46
+ resumeSceneHistory(useScene);
47
+ syncingAutoOpenings = false;
48
+ }
49
+ };
50
+ const applyPreviewUpdates = (updates) => {
51
+ syncingPreviewOpenings = true;
52
+ previewController.apply(updates);
53
+ queueMicrotask(() => {
54
+ syncingPreviewOpenings = false;
116
55
  });
117
- const unsubscribeLiveTransforms = useLiveTransforms.subscribe(() => {
118
- refreshLivePreview();
56
+ };
57
+ const clearPreviewUpdates = () => {
58
+ if (previewController.previewSurfaceIds.size === 0)
59
+ return;
60
+ syncingPreviewOpenings = true;
61
+ previewController.clear();
62
+ queueMicrotask(() => {
63
+ syncingPreviewOpenings = false;
119
64
  });
120
- const unsubscribeLiveOverrides = useLiveNodeOverrides.subscribe(() => {
65
+ };
66
+ const refreshLivePreview = () => {
67
+ if (syncingPreviewOpenings)
68
+ return;
69
+ const nodes = useScene.getState().nodes;
70
+ const liveTransforms = useLiveTransforms.getState().transforms;
71
+ const liveOverrides = useLiveNodeOverrides.getState().overrides;
72
+ const previewSurfaceIds = previewController.previewSurfaceIds;
73
+ if (!hasLiveStairOpeningInputs(nodes, liveTransforms, liveOverrides, previewSurfaceIds)) {
74
+ clearPreviewUpdates();
75
+ return;
76
+ }
77
+ applyPreviewUpdates(syncAutoStairOpenings(getNodesWithLiveStairOpeningInputs(nodes, liveTransforms, liveOverrides, previewSurfaceIds)));
78
+ };
79
+ const runAutoSync = () => {
80
+ // Rise first: straight stairs converge their flight heights to the
81
+ // resolved rise (level height or deck elevation), and the opening pass
82
+ // reads those segment heights — so it must run against the post-rise
83
+ // nodes.
84
+ applyUpdates(syncStairRises(useScene.getState().nodes));
85
+ applyUpdates(syncAutoStairOpenings(useScene.getState().nodes));
86
+ };
87
+ let disposed = false;
88
+ let syncGeneration = 0;
89
+ const scheduleAutoSync = () => {
90
+ const generation = ++syncGeneration;
91
+ // One microtask later so every other scene-store listener for the
92
+ // triggering transition (and, at mount, the editor's spatial-grid
93
+ // init) runs first — the spatial-grid sync in particular. The
94
+ // deck-attached rise elects the stair's floor-stack base elevation
95
+ // through the spatial grid; syncing before the grid listener would
96
+ // rescale flights against the pre-transition slab state.
97
+ queueSceneNormalization(() => {
98
+ if (disposed || generation !== syncGeneration)
99
+ return;
100
+ runAutoSync();
121
101
  refreshLivePreview();
122
102
  });
123
- return () => {
124
- disposed = true;
125
- unsubscribeScene();
126
- unsubscribeLiveTransforms();
127
- unsubscribeLiveOverrides();
128
- previewControllerRef.current.clear();
129
- };
130
- }, []);
103
+ };
104
+ scheduleAutoSync();
105
+ const unsubscribeScene = useScene.subscribe((state, prevState) => {
106
+ if (syncingAutoOpenings)
107
+ return;
108
+ if (!hasOpeningRelevantNodeChange(state.nodes, prevState.nodes))
109
+ return;
110
+ scheduleAutoSync();
111
+ });
112
+ const unsubscribeLiveTransforms = useLiveTransforms.subscribe(() => {
113
+ refreshLivePreview();
114
+ });
115
+ const unsubscribeLiveOverrides = useLiveNodeOverrides.subscribe(() => {
116
+ refreshLivePreview();
117
+ });
118
+ return () => {
119
+ disposed = true;
120
+ unsubscribeScene();
121
+ unsubscribeLiveTransforms();
122
+ unsubscribeLiveOverrides();
123
+ previewController.clear();
124
+ };
125
+ }
126
+ export const StairOpeningSystem = () => {
127
+ useEffect(() => initializeStairOpeningSync(), []);
131
128
  return null;
132
129
  };
@@ -1,4 +1,4 @@
1
- import type { AnyNode, AnyNodeId, StairNode } from '../../schema';
1
+ import type { AnyNode, AnyNodeId, StairNode } from '../../schema/index.js';
2
2
  export declare function resolveStairTotalRise(stair: StairNode, nodes: Record<string, AnyNode>): number;
3
3
  /**
4
4
  * Keeps straight stairs' flight segments in step with the resolved rise.
@@ -1 +1 @@
1
- {"version":3,"file":"stair-rise.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-rise.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAoB,MAAM,cAAc,CAAA;AAInF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAiC9F;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,KAAK,CAAC;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAgClD"}
1
+ {"version":3,"file":"stair-rise.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-rise.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAoB,MAAM,cAAc,CAAA;AAInF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA+B9F;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,KAAK,CAAC;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC,CAgClD"}
@@ -1,35 +1,34 @@
1
- import { getFloorStackedPosition } from '../../hooks/spatial-grid/floor-placed-elevation';
2
- import { DEFAULT_LEVEL_HEIGHT } from '../../services/level-height';
3
- import { getLevelFloorToFloorHeight } from '../../services/storey';
1
+ import { getFloorStackedPosition } from '../../hooks/spatial-grid/floor-placed-elevation.js';
2
+ import { DEFAULT_LEVEL_HEIGHT } from '../../services/level-height.js';
3
+ import { getLevelFloorToFloorHeight } from '../../services/storey.js';
4
4
  export function resolveStairTotalRise(stair, nodes) {
5
5
  if (stair.totalRise !== undefined)
6
6
  return stair.totalRise;
7
7
  const level = Object.values(nodes).find((node) => node.type === 'level' && node.children.includes(stair.id));
8
+ // Both destinations are absolute level-local heights, while the stair's own
9
+ // base may be lifted onto a floor slab by the floor-stack
10
+ // (`FloorElevationSystem` / `syncStairGroupElevation` put the group at
11
+ // `position[1] + elected slab elevation`). The rise is measured from that
12
+ // base, so subtract it — electing the base exactly the way the visual
13
+ // systems do (persisted `supportSlabId` honored, uncapped election
14
+ // otherwise) keeps base + rise landing precisely on the destination surface.
15
+ const baseElevation = getFloorStackedPosition({
16
+ node: stair,
17
+ nodes,
18
+ position: stair.position,
19
+ rotation: stair.rotation,
20
+ levelId: level?.id ?? null,
21
+ })[1];
8
22
  if (stair.deckSlabId) {
23
+ // The deck's `elevation` IS its walking surface (level-local). A stale
24
+ // reference (deck gone) falls through to the level-derived rise.
9
25
  const deck = nodes[stair.deckSlabId];
10
- // The deck's `elevation` IS its walking surface (level-local), but the
11
- // stair's own base may be lifted onto a floor slab by the floor-stack
12
- // (`FloorElevationSystem` / `syncStairGroupElevation` put the group at
13
- // `position[1] + elected slab elevation`). The rise is measured from
14
- // that base, so subtract it — electing the base exactly the way the
15
- // visual systems do (persisted `supportSlabId` honored, uncapped
16
- // election otherwise) keeps base + rise landing precisely on the deck's
17
- // walking surface. A stale reference (deck gone) falls through to the
18
- // level-derived rise.
19
- if (deck?.type === 'slab') {
20
- const baseElevation = getFloorStackedPosition({
21
- node: stair,
22
- nodes,
23
- position: stair.position,
24
- rotation: stair.rotation,
25
- levelId: level?.id ?? null,
26
- })[1];
26
+ if (deck?.type === 'slab')
27
27
  return (deck.elevation ?? 0.05) - baseElevation;
28
- }
29
28
  }
30
- return level?.type === 'level'
31
- ? getLevelFloorToFloorHeight(level.id, nodes)
32
- : DEFAULT_LEVEL_HEIGHT;
29
+ if (level?.type !== 'level')
30
+ return DEFAULT_LEVEL_HEIGHT;
31
+ return getLevelFloorToFloorHeight(level.id, nodes) - baseElevation;
33
32
  }
34
33
  const RISE_SYNC_EPSILON = 1e-4;
35
34
  /**
@@ -1,5 +1,5 @@
1
- import type { FenceNode, WallNode } from '../../schema';
2
- import type { Point2D } from './wall-mitering';
1
+ import type { FenceNode, WallNode } from '../../schema/index.js';
2
+ import type { Point2D } from './wall-mitering.js';
3
3
  type WallCurveLike = Pick<WallNode | FenceNode, 'start' | 'end' | 'curveOffset'>;
4
4
  type CurveFrame = {
5
5
  point: Point2D;
@@ -47,6 +47,7 @@ export declare function getWallArcData(wall: WallCurveLike): {
47
47
  export declare function getWallCurveFrameAt(wall: WallCurveLike, t: number): CurveFrame;
48
48
  export declare function getWallMidpointHandlePoint(wall: WallCurveLike): Point2D;
49
49
  export declare function sampleWallCenterline(wall: WallCurveLike, segments?: number): Point2D[];
50
+ export declare function constrainWallCurveOffsetToAvoidIntersections(wall: WallNode, proposedOffset: number, walls: readonly WallNode[]): number;
50
51
  export declare function getWallCurveLength(wall: WallCurveLike, segments?: number): number;
51
52
  export declare function getWallSurfacePolygon(wall: Pick<WallNode | FenceNode, 'start' | 'end' | 'curveOffset' | 'thickness'>, segments?: number, miterOverrides?: WallSurfaceMiterOverrides): Point2D[];
52
53
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"wall-curve.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-curve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAK9C,KAAK,aAAa,GAAG,IAAI,CAAC,QAAQ,GAAG,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,aAAa,CAAC,CAAA;AAEhF,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,KAAK,yBAAyB,GAAG;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAcD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE9D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE5D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,UAErD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,aAAa,UAExD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,aAAa,UAE5D;AAWD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,UAG3E;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,aAAa,UAI5D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,WAE/C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa;;;;;;;;;;;;;EA6BpD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa;;;;;;;;;SA2BjD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAwC9E;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,aAAa,WAE7D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,SAA0B,aAM3F;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,SAA0B,UASzF;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,aAAa,GAAG,WAAW,CAAC,EAC/E,QAAQ,SAA0B,EAClC,cAAc,CAAC,EAAE,yBAAyB,aA2B3C"}
1
+ {"version":3,"file":"wall-curve.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-curve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAO9C,KAAK,aAAa,GAAG,IAAI,CAAC,QAAQ,GAAG,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,aAAa,CAAC,CAAA;AAEhF,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,KAAK,yBAAyB,GAAG;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAcD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE9D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE5D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,UAErD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,aAAa,UAExD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,aAAa,UAE5D;AAWD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,UAG3E;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,aAAa,UAI5D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,WAE/C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa;;;;;;;;;;;;;EA6BpD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa;;;;;;;;;SA2BjD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAwC9E;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,aAAa,WAE7D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,SAA0B,aAM3F;AAgED,wBAAgB,4CAA4C,CAC1D,IAAI,EAAE,QAAQ,EACd,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,SAAS,QAAQ,EAAE,UAoB3B;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,SAA0B,UASzF;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,EAAE,OAAO,GAAG,KAAK,GAAG,aAAa,GAAG,WAAW,CAAC,EAC/E,QAAQ,SAA0B,EAClC,cAAc,CAAC,EAAE,yBAAyB,aA2B3C"}
@@ -1,5 +1,7 @@
1
1
  const CURVE_EPSILON = 1e-6;
2
2
  const DEFAULT_SAMPLE_SEGMENTS = 24;
3
+ const CURVE_INTERSECTION_SEARCH_STEPS = 20;
4
+ const CURVE_INTERSECTION_TOLERANCE = 1e-6;
3
5
  function clamp01(value) {
4
6
  return Math.max(0, Math.min(1, value));
5
7
  }
@@ -142,6 +144,77 @@ export function sampleWallCenterline(wall, segments = DEFAULT_SAMPLE_SEGMENTS) {
142
144
  const count = Math.max(1, segments);
143
145
  return Array.from({ length: count + 1 }, (_, index) => getWallCurveFrameAt(wall, index / count).point);
144
146
  }
147
+ function segmentIntersectionPoint(a, b, c, d) {
148
+ const abX = b.x - a.x;
149
+ const abY = b.y - a.y;
150
+ const cdX = d.x - c.x;
151
+ const cdY = d.y - c.y;
152
+ const denominator = abX * cdY - abY * cdX;
153
+ if (Math.abs(denominator) <= CURVE_INTERSECTION_TOLERANCE)
154
+ return null;
155
+ const acX = c.x - a.x;
156
+ const acY = c.y - a.y;
157
+ const t = (acX * cdY - acY * cdX) / denominator;
158
+ const u = (acX * abY - acY * abX) / denominator;
159
+ if (t < -CURVE_INTERSECTION_TOLERANCE ||
160
+ t > 1 + CURVE_INTERSECTION_TOLERANCE ||
161
+ u < -CURVE_INTERSECTION_TOLERANCE ||
162
+ u > 1 + CURVE_INTERSECTION_TOLERANCE) {
163
+ return null;
164
+ }
165
+ return { x: a.x + t * abX, y: a.y + t * abY };
166
+ }
167
+ function pointMatchesEndpoint(point, wall) {
168
+ return [getWallStartPoint(wall), getWallEndPoint(wall)].some((endpoint) => distance(point, endpoint) <= CURVE_INTERSECTION_TOLERANCE);
169
+ }
170
+ function wallCurveIntersectsSibling(wall, sibling) {
171
+ const wallPoints = sampleWallCenterline(wall);
172
+ const siblingPoints = sampleWallCenterline(sibling);
173
+ for (let wallIndex = 0; wallIndex < wallPoints.length - 1; wallIndex += 1) {
174
+ const wallStart = wallPoints[wallIndex];
175
+ const wallEnd = wallPoints[wallIndex + 1];
176
+ for (let siblingIndex = 0; siblingIndex < siblingPoints.length - 1; siblingIndex += 1) {
177
+ const siblingStart = siblingPoints[siblingIndex];
178
+ const siblingEnd = siblingPoints[siblingIndex + 1];
179
+ const intersection = segmentIntersectionPoint(wallStart, wallEnd, siblingStart, siblingEnd);
180
+ if (!intersection)
181
+ continue;
182
+ if (pointMatchesEndpoint(intersection, wall) && pointMatchesEndpoint(intersection, sibling)) {
183
+ continue;
184
+ }
185
+ return true;
186
+ }
187
+ }
188
+ return false;
189
+ }
190
+ function wallCurveIntersectsSiblings(wall, walls) {
191
+ if (!isCurvedWall(wall))
192
+ return false;
193
+ return walls.some((sibling) => sibling.id !== wall.id &&
194
+ sibling.parentId === wall.parentId &&
195
+ wallCurveIntersectsSibling(wall, sibling));
196
+ }
197
+ export function constrainWallCurveOffsetToAvoidIntersections(wall, proposedOffset, walls) {
198
+ const currentOffset = normalizeWallCurveOffset(wall, wall.curveOffset ?? 0);
199
+ const normalizedProposal = normalizeWallCurveOffset(wall, proposedOffset);
200
+ const proposedWall = { ...wall, curveOffset: normalizedProposal };
201
+ if (!wallCurveIntersectsSiblings(proposedWall, walls))
202
+ return normalizedProposal;
203
+ const currentWall = { ...wall, curveOffset: currentOffset };
204
+ if (wallCurveIntersectsSiblings(currentWall, walls))
205
+ return currentOffset;
206
+ let safeOffset = currentOffset;
207
+ let blockedOffset = normalizedProposal;
208
+ for (let index = 0; index < CURVE_INTERSECTION_SEARCH_STEPS; index += 1) {
209
+ const candidateOffset = (safeOffset + blockedOffset) / 2;
210
+ const candidateWall = { ...wall, curveOffset: candidateOffset };
211
+ if (wallCurveIntersectsSiblings(candidateWall, walls))
212
+ blockedOffset = candidateOffset;
213
+ else
214
+ safeOffset = candidateOffset;
215
+ }
216
+ return normalizeWallCurveOffset(wall, safeOffset);
217
+ }
145
218
  export function getWallCurveLength(wall, segments = DEFAULT_SAMPLE_SEGMENTS) {
146
219
  const points = sampleWallCenterline(wall, segments);
147
220
  let totalLength = 0;
@@ -1,5 +1,6 @@
1
- import type { WallNode } from '../../schema';
2
- import { type Point2D, type WallMiterData } from './wall-mitering';
1
+ import type { WallNode } from '../../schema/index.js';
2
+ import { type Point2D, type WallMiterData } from './wall-mitering.js';
3
+ export { calculateLevelMiters, type Point2D, type WallMiterData } from './wall-mitering.js';
3
4
  export declare const DEFAULT_WALL_THICKNESS = 0.1;
4
5
  export declare const DEFAULT_WALL_HEIGHT = 2.5;
5
6
  export declare function getWallThickness(wallNode: WallNode): number;
@@ -1 +1 @@
1
- {"version":3,"file":"wall-footprint.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-footprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,EAEL,KAAK,OAAO,EAEZ,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAA;AAExB,eAAO,MAAM,sBAAsB,MAAM,CAAA;AACzC,eAAO,MAAM,mBAAmB,MAAM,CAAA;AAGtC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE3D;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,GAAG,OAAO,EAAE,CA6D5F"}
1
+ {"version":3,"file":"wall-footprint.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-footprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,EAEL,KAAK,OAAO,EAEZ,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,oBAAoB,EAAE,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAExF,eAAO,MAAM,sBAAsB,MAAM,CAAA;AACzC,eAAO,MAAM,mBAAmB,MAAM,CAAA;AAGtC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE3D;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,GAAG,OAAO,EAAE,CA6D5F"}
@@ -1,5 +1,6 @@
1
- import { getWallSurfacePolygon, isCurvedWall } from './wall-curve';
2
- import { getWallMiterBoundaryPoints, pointToKey, } from './wall-mitering';
1
+ import { getWallSurfacePolygon, isCurvedWall } from './wall-curve.js';
2
+ import { getWallMiterBoundaryPoints, pointToKey, } from './wall-mitering.js';
3
+ export { calculateLevelMiters } from './wall-mitering.js';
3
4
  export const DEFAULT_WALL_THICKNESS = 0.1;
4
5
  export const DEFAULT_WALL_HEIGHT = 2.5;
5
6
  const CURVED_WALL_SURFACE_SEGMENTS = 24;
@@ -1,4 +1,4 @@
1
- import type { WallNode } from '../../schema';
1
+ import type { WallNode } from '../../schema/index.js';
2
2
  export interface Point2D {
3
3
  x: number;
4
4
  y: number;
@@ -1,4 +1,4 @@
1
- import { getWallCurveFrameAt, isCurvedWall } from './wall-curve';
1
+ import { getWallCurveFrameAt, isCurvedWall } from './wall-curve.js';
2
2
  // ============================================================================
3
3
  // UTILITY FUNCTIONS
4
4
  // ============================================================================
@@ -1,4 +1,4 @@
1
- import type { WallNode } from '../../schema';
1
+ import type { WallNode } from '../../schema/index.js';
2
2
  export type WallPlanPoint = [number, number];
3
3
  export type WallMoveAxis = [number, number];
4
4
  export type WallMoveEndpoint = 'start' | 'end';
@@ -1,4 +1,4 @@
1
- import type { WallNode } from '../../schema/nodes/wall';
1
+ import type { WallNode } from '../../schema/nodes/wall.js';
2
2
  /**
3
3
  * Minimum wall body height in meters. Governs both the wall height
4
4
  * arrow's lower drag bound and the slab-elevation clamp: a slab may not
@@ -1,5 +1,5 @@
1
- import { type AnyNode, type AnyNodeId, type WallNode } from '../../schema';
2
- import type { WallPlanPoint } from './wall-move';
1
+ import { type AnyNode, type AnyNodeId, type WallNode } from '../../schema/index.js';
2
+ import type { WallPlanPoint } from './wall-move.js';
3
3
  export type WallTopologyChanges = {
4
4
  create: Array<{
5
5
  node: AnyNode;
@@ -1,7 +1,7 @@
1
- import { GROUND_SUPPORT_ID } from '../../hooks/spatial-grid/support-host-id';
2
- import { terrainSupportLift } from '../../lib/terrain-support';
3
- import { getScaledDimensions, WallNode as WallSchema, } from '../../schema';
4
- import { getWallArcData, getWallCurveFrameAt, getWallCurveLength, isCurvedWall } from './wall-curve';
1
+ import { GROUND_SUPPORT_ID } from '../../hooks/spatial-grid/support-host-id.js';
2
+ import { terrainSupportLift } from '../../lib/terrain-support.js';
3
+ import { getScaledDimensions, WallNode as WallSchema, } from '../../schema/index.js';
4
+ import { getWallArcData, getWallCurveFrameAt, getWallCurveLength, isCurvedWall } from './wall-curve.js';
5
5
  const WALL_MIN_LENGTH = 0.01;
6
6
  const WALL_SPLIT_ENDPOINT_EPSILON = 0.02;
7
7
  const WALL_INTERSECTION_EPSILON = 1e-6;
@@ -1,6 +1,6 @@
1
- import type { AnyNode, AnyNodeId } from '../schema';
2
- import type { Collection, CollectionId } from '../schema/collections';
3
- import type { SceneMaterial, SceneMaterialId } from '../schema/scene-material';
1
+ import type { AnyNode, AnyNodeId } from '../schema/index.js';
2
+ import type { Collection, CollectionId } from '../schema/collections.js';
3
+ import type { SceneMaterial, SceneMaterialId } from '../schema/scene-material.js';
4
4
  export type SceneGraph = {
5
5
  nodes: Record<AnyNodeId, AnyNode>;
6
6
  rootNodeIds: AnyNodeId[];
@@ -1 +1 @@
1
- {"version":3,"file":"clone-scene-graph.d.ts","sourceRoot":"","sources":["../../src/utils/clone-scene-graph.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE9E,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACjC,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;IAClD,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAUD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CA6IlE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,OAAO,EAAE,SAAS,GACjB;IAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAAC,UAAU,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAsG/E;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE,qBAA0B,GAClC,UAAU,CA0EZ"}
1
+ {"version":3,"file":"clone-scene-graph.d.ts","sourceRoot":"","sources":["../../src/utils/clone-scene-graph.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAE9E,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACjC,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;IAClD,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAUD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAqKlE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EACjC,OAAO,EAAE,SAAS,GACjB;IAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAAC,UAAU,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAqH/E;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,UAAU,EACtB,OAAO,GAAE,qBAA0B,GAClC,UAAU,CA0EZ"}
@@ -1,6 +1,6 @@
1
- import { GROUND_SUPPORT_ID } from '../hooks/spatial-grid/floor-placed-elevation';
2
- import { remapConstructionDimensionReferences, remapMeasurementReferences, } from '../lib/measurement-geometry';
3
- import { generateId } from '../schema/base';
1
+ import { GROUND_SUPPORT_ID } from '../hooks/spatial-grid/floor-placed-elevation.js';
2
+ import { remapConstructionDimensionReferences, remapMeasurementReferences, } from '../lib/measurement-geometry.js';
3
+ import { generateId } from '../schema/base.js';
4
4
  /**
5
5
  * Extracts the type prefix from a node ID (e.g., "wall_abc123" -> "wall")
6
6
  */
@@ -64,6 +64,18 @@ export function cloneSceneGraph(sceneGraph) {
64
64
  ;
65
65
  clonedNode.roofSegmentId = idMap.get(clonedNode.roofSegmentId);
66
66
  }
67
+ if ('hostRoofId' in clonedNode && typeof clonedNode.hostRoofId === 'string') {
68
+ ;
69
+ clonedNode.hostRoofId = idMap.get(clonedNode.hostRoofId);
70
+ }
71
+ if ('hostRoofSegmentId' in clonedNode && typeof clonedNode.hostRoofSegmentId === 'string') {
72
+ ;
73
+ clonedNode.hostRoofSegmentId = idMap.get(clonedNode.hostRoofSegmentId);
74
+ }
75
+ if (clonedNode.type === 'roof' && clonedNode.support?.kind === 'roof') {
76
+ clonedNode.support.roofSegmentId = (idMap.get(clonedNode.support.roofSegmentId) ??
77
+ clonedNode.support.roofSegmentId);
78
+ }
67
79
  // Remap supportSlabId (persisted slab-support hosts). The 'ground'
68
80
  // sentinel is not a node id — keep it as-is.
69
81
  if ('supportSlabId' in clonedNode &&
@@ -72,6 +84,12 @@ export function cloneSceneGraph(sceneGraph) {
72
84
  ;
73
85
  clonedNode.supportSlabId = idMap.get(clonedNode.supportSlabId);
74
86
  }
87
+ if (clonedNode.type === 'unit') {
88
+ clonedNode.members = clonedNode.members.flatMap((id) => {
89
+ const remapped = idMap.get(id);
90
+ return remapped ? [remapped] : [];
91
+ });
92
+ }
75
93
  if ('deckSlabId' in clonedNode && typeof clonedNode.deckSlabId === 'string') {
76
94
  ;
77
95
  clonedNode.deckSlabId = idMap.get(clonedNode.deckSlabId);
@@ -223,6 +241,20 @@ export function cloneLevelSubtree(nodes, levelId) {
223
241
  cloned.roofSegmentId =
224
242
  idMap.get(cloned.roofSegmentId) ?? cloned.roofSegmentId;
225
243
  }
244
+ if ('hostRoofId' in cloned && typeof cloned.hostRoofId === 'string') {
245
+ ;
246
+ cloned.hostRoofId =
247
+ idMap.get(cloned.hostRoofId) ?? cloned.hostRoofId;
248
+ }
249
+ if ('hostRoofSegmentId' in cloned && typeof cloned.hostRoofSegmentId === 'string') {
250
+ ;
251
+ cloned.hostRoofSegmentId =
252
+ idMap.get(cloned.hostRoofSegmentId) ?? cloned.hostRoofSegmentId;
253
+ }
254
+ if (cloned.type === 'roof' && cloned.support?.kind === 'roof') {
255
+ cloned.support.roofSegmentId = (idMap.get(cloned.support.roofSegmentId) ??
256
+ cloned.support.roofSegmentId);
257
+ }
226
258
  // Remap supportSlabId when the host slab is inside the cloned subtree;
227
259
  // preserve it otherwise (like wallId, the reference may point outside).
228
260
  if ('supportSlabId' in cloned && typeof cloned.supportSlabId === 'string') {