@pascal-app/core 0.9.1 → 1.0.0-beta.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 (378) hide show
  1. package/README.md +17 -10
  2. package/dist/events/bus.d.ts +49 -2
  3. package/dist/events/bus.d.ts.map +1 -1
  4. package/dist/hooks/scene-registry/item-clip-registry.d.ts +18 -0
  5. package/dist/hooks/scene-registry/item-clip-registry.d.ts.map +1 -0
  6. package/dist/hooks/scene-registry/item-clip-registry.js +10 -0
  7. package/dist/hooks/scene-registry/scene-registry.d.ts +8 -1
  8. package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
  9. package/dist/hooks/scene-registry/scene-registry.js +27 -1
  10. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +17 -1
  11. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
  12. package/dist/hooks/spatial-grid/floor-placed-elevation.js +61 -8
  13. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +135 -28
  14. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  15. package/dist/hooks/spatial-grid/spatial-grid-manager.js +427 -271
  16. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +46 -1
  17. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  18. package/dist/hooks/spatial-grid/spatial-grid-sync.js +208 -9
  19. package/dist/hooks/spatial-grid/support-host-id.d.ts +3 -0
  20. package/dist/hooks/spatial-grid/support-host-id.d.ts.map +1 -0
  21. package/dist/hooks/spatial-grid/support-host-id.js +2 -0
  22. package/dist/hooks/spatial-grid/support-host-patch.d.ts +51 -0
  23. package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -0
  24. package/dist/hooks/spatial-grid/support-host-patch.js +164 -0
  25. package/dist/index.d.ts +33 -11
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +32 -10
  28. package/dist/lib/level-name.d.ts +4 -0
  29. package/dist/lib/level-name.d.ts.map +1 -0
  30. package/dist/lib/level-name.js +10 -0
  31. package/dist/lib/measurement-geometry.d.ts +23 -0
  32. package/dist/lib/measurement-geometry.d.ts.map +1 -0
  33. package/dist/lib/measurement-geometry.js +249 -0
  34. package/dist/lib/polygon-geometry.d.ts +0 -1
  35. package/dist/lib/polygon-geometry.d.ts.map +1 -1
  36. package/dist/lib/polygon-geometry.js +0 -18
  37. package/dist/lib/selection-proxy.d.ts +4 -0
  38. package/dist/lib/selection-proxy.d.ts.map +1 -0
  39. package/dist/lib/selection-proxy.js +12 -0
  40. package/dist/lib/slab-polygon.d.ts +31 -2
  41. package/dist/lib/slab-polygon.d.ts.map +1 -1
  42. package/dist/lib/slab-polygon.js +557 -31
  43. package/dist/lib/slots.d.ts +14 -0
  44. package/dist/lib/slots.d.ts.map +1 -0
  45. package/dist/lib/slots.js +26 -0
  46. package/dist/lib/space-detection.d.ts +40 -6
  47. package/dist/lib/space-detection.d.ts.map +1 -1
  48. package/dist/lib/space-detection.js +574 -192
  49. package/dist/lib/terrain-brush.d.ts +163 -0
  50. package/dist/lib/terrain-brush.d.ts.map +1 -0
  51. package/dist/lib/terrain-brush.js +359 -0
  52. package/dist/lib/terrain-codec.d.ts +51 -0
  53. package/dist/lib/terrain-codec.d.ts.map +1 -0
  54. package/dist/lib/terrain-codec.js +167 -0
  55. package/dist/lib/terrain-field.d.ts +150 -0
  56. package/dist/lib/terrain-field.d.ts.map +1 -0
  57. package/dist/lib/terrain-field.js +248 -0
  58. package/dist/lib/terrain-raycast.d.ts +44 -0
  59. package/dist/lib/terrain-raycast.d.ts.map +1 -0
  60. package/dist/lib/terrain-raycast.js +188 -0
  61. package/dist/lib/terrain-source.d.ts +60 -0
  62. package/dist/lib/terrain-source.d.ts.map +1 -0
  63. package/dist/lib/terrain-source.js +90 -0
  64. package/dist/lib/terrain-support.d.ts +60 -0
  65. package/dist/lib/terrain-support.d.ts.map +1 -0
  66. package/dist/lib/terrain-support.js +150 -0
  67. package/dist/lib/wall-distance.d.ts +60 -0
  68. package/dist/lib/wall-distance.d.ts.map +1 -0
  69. package/dist/lib/wall-distance.js +85 -0
  70. package/dist/lib/zone-quantities.d.ts +21 -0
  71. package/dist/lib/zone-quantities.d.ts.map +1 -0
  72. package/dist/lib/zone-quantities.js +428 -0
  73. package/dist/material-library.d.ts +28 -1
  74. package/dist/material-library.d.ts.map +1 -1
  75. package/dist/material-library.js +2233 -441
  76. package/dist/registry/handles.d.ts +91 -3
  77. package/dist/registry/handles.d.ts.map +1 -1
  78. package/dist/registry/index.d.ts +3 -3
  79. package/dist/registry/index.d.ts.map +1 -1
  80. package/dist/registry/index.js +1 -1
  81. package/dist/registry/registry.d.ts +46 -3
  82. package/dist/registry/registry.d.ts.map +1 -1
  83. package/dist/registry/registry.js +82 -1
  84. package/dist/registry/subtree.d.ts.map +1 -1
  85. package/dist/registry/subtree.js +8 -1
  86. package/dist/registry/types.d.ts +781 -39
  87. package/dist/registry/types.d.ts.map +1 -1
  88. package/dist/schema/index.d.ts +27 -8
  89. package/dist/schema/index.d.ts.map +1 -1
  90. package/dist/schema/index.js +23 -6
  91. package/dist/schema/material.d.ts +3 -2
  92. package/dist/schema/material.d.ts.map +1 -1
  93. package/dist/schema/material.js +7 -5
  94. package/dist/schema/nodes/box-vent.d.ts +2 -2
  95. package/dist/schema/nodes/cabinet.d.ts +536 -0
  96. package/dist/schema/nodes/cabinet.d.ts.map +1 -0
  97. package/dist/schema/nodes/cabinet.js +139 -0
  98. package/dist/schema/nodes/ceiling.d.ts +4 -3
  99. package/dist/schema/nodes/ceiling.d.ts.map +1 -1
  100. package/dist/schema/nodes/ceiling.js +11 -1
  101. package/dist/schema/nodes/chimney.d.ts +4 -4
  102. package/dist/schema/nodes/column.d.ts +4 -2
  103. package/dist/schema/nodes/column.d.ts.map +1 -1
  104. package/dist/schema/nodes/column.js +5 -0
  105. package/dist/schema/nodes/construction-dimension.d.ts +195 -0
  106. package/dist/schema/nodes/construction-dimension.d.ts.map +1 -0
  107. package/dist/schema/nodes/construction-dimension.js +151 -0
  108. package/dist/schema/nodes/cupola.d.ts +2 -2
  109. package/dist/schema/nodes/door.d.ts +42 -5
  110. package/dist/schema/nodes/door.d.ts.map +1 -1
  111. package/dist/schema/nodes/door.js +32 -0
  112. package/dist/schema/nodes/dormer.d.ts +8 -8
  113. package/dist/schema/nodes/dormer.js +1 -1
  114. package/dist/schema/nodes/downspout.d.ts +2 -2
  115. package/dist/schema/nodes/duct-fitting.d.ts +91 -0
  116. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -0
  117. package/dist/schema/nodes/duct-fitting.js +92 -0
  118. package/dist/schema/nodes/duct-segment.d.ts +61 -0
  119. package/dist/schema/nodes/duct-segment.d.ts.map +1 -0
  120. package/dist/schema/nodes/duct-segment.js +73 -0
  121. package/dist/schema/nodes/duct-terminal.d.ts +58 -0
  122. package/dist/schema/nodes/duct-terminal.d.ts.map +1 -0
  123. package/dist/schema/nodes/duct-terminal.js +53 -0
  124. package/dist/schema/nodes/elevator.d.ts +3 -2
  125. package/dist/schema/nodes/elevator.d.ts.map +1 -1
  126. package/dist/schema/nodes/elevator.js +3 -0
  127. package/dist/schema/nodes/eyebrow-vent.d.ts +2 -2
  128. package/dist/schema/nodes/fence.d.ts +20 -2
  129. package/dist/schema/nodes/fence.d.ts.map +1 -1
  130. package/dist/schema/nodes/fence.js +33 -2
  131. package/dist/schema/nodes/gutter.d.ts +2 -2
  132. package/dist/schema/nodes/hvac-equipment.d.ts +64 -0
  133. package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -0
  134. package/dist/schema/nodes/hvac-equipment.js +57 -0
  135. package/dist/schema/nodes/item.d.ts +9 -0
  136. package/dist/schema/nodes/item.d.ts.map +1 -1
  137. package/dist/schema/nodes/item.js +24 -0
  138. package/dist/schema/nodes/level.d.ts +2 -1
  139. package/dist/schema/nodes/level.d.ts.map +1 -1
  140. package/dist/schema/nodes/level.js +12 -31
  141. package/dist/schema/nodes/lineset.d.ts +42 -0
  142. package/dist/schema/nodes/lineset.d.ts.map +1 -0
  143. package/dist/schema/nodes/lineset.js +38 -0
  144. package/dist/schema/nodes/liquid-line.d.ts +34 -0
  145. package/dist/schema/nodes/liquid-line.d.ts.map +1 -0
  146. package/dist/schema/nodes/liquid-line.js +24 -0
  147. package/dist/schema/nodes/measurement.d.ts +306 -0
  148. package/dist/schema/nodes/measurement.d.ts.map +1 -0
  149. package/dist/schema/nodes/measurement.js +87 -0
  150. package/dist/schema/nodes/pipe-fitting.d.ts +56 -0
  151. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -0
  152. package/dist/schema/nodes/pipe-fitting.js +45 -0
  153. package/dist/schema/nodes/pipe-segment.d.ts +48 -0
  154. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -0
  155. package/dist/schema/nodes/pipe-segment.js +36 -0
  156. package/dist/schema/nodes/pipe-trap.d.ts +43 -0
  157. package/dist/schema/nodes/pipe-trap.d.ts.map +1 -0
  158. package/dist/schema/nodes/pipe-trap.js +36 -0
  159. package/dist/schema/nodes/ridge-vent.d.ts +18 -3
  160. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
  161. package/dist/schema/nodes/ridge-vent.js +221 -3
  162. package/dist/schema/nodes/roof-segment-shape.d.ts +90 -0
  163. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -0
  164. package/dist/schema/nodes/roof-segment-shape.js +318 -0
  165. package/dist/schema/nodes/roof-segment-walls.d.ts +101 -0
  166. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -0
  167. package/dist/schema/nodes/roof-segment-walls.js +330 -0
  168. package/dist/schema/nodes/roof-segment.d.ts +84 -8
  169. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  170. package/dist/schema/nodes/roof-segment.js +290 -5
  171. package/dist/schema/nodes/roof.d.ts +8 -8
  172. package/dist/schema/nodes/shelf.d.ts +4 -2
  173. package/dist/schema/nodes/shelf.d.ts.map +1 -1
  174. package/dist/schema/nodes/shelf.js +8 -0
  175. package/dist/schema/nodes/site.d.ts +9 -0
  176. package/dist/schema/nodes/site.d.ts.map +1 -1
  177. package/dist/schema/nodes/site.js +8 -6
  178. package/dist/schema/nodes/skylight.d.ts +10 -10
  179. package/dist/schema/nodes/slab.d.ts +8 -2
  180. package/dist/schema/nodes/slab.d.ts.map +1 -1
  181. package/dist/schema/nodes/slab.js +18 -2
  182. package/dist/schema/nodes/solar-panel.d.ts +4 -4
  183. package/dist/schema/nodes/spawn.d.ts +1 -0
  184. package/dist/schema/nodes/spawn.d.ts.map +1 -1
  185. package/dist/schema/nodes/spawn.js +2 -0
  186. package/dist/schema/nodes/stair-segment.d.ts +4 -4
  187. package/dist/schema/nodes/stair.d.ts +16 -13
  188. package/dist/schema/nodes/stair.d.ts.map +1 -1
  189. package/dist/schema/nodes/stair.js +11 -1
  190. package/dist/schema/nodes/structural-grid.d.ts +27 -0
  191. package/dist/schema/nodes/structural-grid.d.ts.map +1 -0
  192. package/dist/schema/nodes/structural-grid.js +17 -0
  193. package/dist/schema/nodes/turbine-vent.d.ts +2 -2
  194. package/dist/schema/nodes/wall.d.ts +248 -6
  195. package/dist/schema/nodes/wall.d.ts.map +1 -1
  196. package/dist/schema/nodes/wall.js +266 -0
  197. package/dist/schema/nodes/window.d.ts +40 -3
  198. package/dist/schema/nodes/window.d.ts.map +1 -1
  199. package/dist/schema/nodes/window.js +30 -0
  200. package/dist/schema/nodes/zone.d.ts +22 -0
  201. package/dist/schema/nodes/zone.d.ts.map +1 -1
  202. package/dist/schema/nodes/zone.js +21 -0
  203. package/dist/schema/scene-material.d.ts +41 -0
  204. package/dist/schema/scene-material.d.ts.map +1 -0
  205. package/dist/schema/scene-material.js +9 -0
  206. package/dist/schema/terrain.d.ts +28 -0
  207. package/dist/schema/terrain.d.ts.map +1 -0
  208. package/dist/schema/terrain.js +30 -0
  209. package/dist/schema/types.d.ts +1300 -97
  210. package/dist/schema/types.d.ts.map +1 -1
  211. package/dist/schema/types.js +27 -0
  212. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts +80 -0
  213. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts.map +1 -0
  214. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.js +89 -0
  215. package/dist/services/alignment-anchors.d.ts.map +1 -1
  216. package/dist/services/alignment-anchors.js +30 -1
  217. package/dist/services/alignment.d.ts +5 -0
  218. package/dist/services/alignment.d.ts.map +1 -1
  219. package/dist/services/alignment.js +2 -0
  220. package/dist/services/hosting.d.ts +8 -0
  221. package/dist/services/hosting.d.ts.map +1 -1
  222. package/dist/services/hosting.js +13 -4
  223. package/dist/services/index.d.ts +9 -2
  224. package/dist/services/index.d.ts.map +1 -1
  225. package/dist/services/index.js +9 -2
  226. package/dist/services/level-height.d.ts +27 -0
  227. package/dist/services/level-height.d.ts.map +1 -0
  228. package/dist/services/level-height.js +94 -0
  229. package/dist/services/opening-guides.d.ts +141 -0
  230. package/dist/services/opening-guides.d.ts.map +1 -0
  231. package/dist/services/opening-guides.js +267 -0
  232. package/dist/services/port-connectivity.d.ts +115 -0
  233. package/dist/services/port-connectivity.d.ts.map +1 -0
  234. package/dist/services/port-connectivity.js +300 -0
  235. package/dist/services/riser-diagram.d.ts +40 -0
  236. package/dist/services/riser-diagram.d.ts.map +1 -0
  237. package/dist/services/riser-diagram.js +110 -0
  238. package/dist/services/snap.d.ts +9 -1
  239. package/dist/services/snap.d.ts.map +1 -1
  240. package/dist/services/snap.js +21 -1
  241. package/dist/services/storey.d.ts +103 -0
  242. package/dist/services/storey.d.ts.map +1 -0
  243. package/dist/services/storey.js +296 -0
  244. package/dist/services/system-graph.d.ts +30 -0
  245. package/dist/services/system-graph.d.ts.map +1 -0
  246. package/dist/services/system-graph.js +164 -0
  247. package/dist/services/validate-dwv.d.ts +32 -0
  248. package/dist/services/validate-dwv.d.ts.map +1 -0
  249. package/dist/services/validate-dwv.js +118 -0
  250. package/dist/store/actions/node-actions.d.ts.map +1 -1
  251. package/dist/store/actions/node-actions.js +141 -4
  252. package/dist/store/history-control.d.ts +31 -0
  253. package/dist/store/history-control.d.ts.map +1 -1
  254. package/dist/store/history-control.js +130 -0
  255. package/dist/store/use-live-terrain.d.ts +65 -0
  256. package/dist/store/use-live-terrain.d.ts.map +1 -0
  257. package/dist/store/use-live-terrain.js +31 -0
  258. package/dist/store/use-live-transforms.d.ts +8 -0
  259. package/dist/store/use-live-transforms.d.ts.map +1 -1
  260. package/dist/store/use-scene.d.ts +47 -3
  261. package/dist/store/use-scene.d.ts.map +1 -1
  262. package/dist/store/use-scene.js +992 -55
  263. package/dist/systems/elevator/elevator-opening-system.d.ts +1 -0
  264. package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -1
  265. package/dist/systems/elevator/elevator-opening-system.js +27 -21
  266. package/dist/systems/elevator/elevator-service.d.ts +0 -2
  267. package/dist/systems/elevator/elevator-service.d.ts.map +1 -1
  268. package/dist/systems/elevator/elevator-service.js +2 -24
  269. package/dist/systems/fence/fence-centerline.d.ts +12 -0
  270. package/dist/systems/fence/fence-centerline.d.ts.map +1 -0
  271. package/dist/systems/fence/fence-centerline.js +37 -0
  272. package/dist/systems/fence/fence-spline.d.ts +39 -0
  273. package/dist/systems/fence/fence-spline.d.ts.map +1 -0
  274. package/dist/systems/fence/fence-spline.js +196 -0
  275. package/dist/systems/slab/slab-placement.d.ts +11 -0
  276. package/dist/systems/slab/slab-placement.d.ts.map +1 -0
  277. package/dist/systems/slab/slab-placement.js +14 -0
  278. package/dist/systems/slab/slab-support.d.ts +137 -0
  279. package/dist/systems/slab/slab-support.d.ts.map +1 -0
  280. package/dist/systems/slab/slab-support.js +557 -0
  281. package/dist/systems/stair/stair-footprint.d.ts.map +1 -1
  282. package/dist/systems/stair/stair-footprint.js +21 -11
  283. package/dist/systems/stair/stair-opening-preview.d.ts +1300 -505
  284. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  285. package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
  286. package/dist/systems/stair/stair-opening-sync.js +19 -33
  287. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
  288. package/dist/systems/stair/stair-opening-system.js +32 -4
  289. package/dist/systems/stair/stair-rise.d.ts +22 -0
  290. package/dist/systems/stair/stair-rise.d.ts.map +1 -0
  291. package/dist/systems/stair/stair-rise.js +79 -0
  292. package/dist/systems/wall/wall-curve.d.ts +10 -0
  293. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  294. package/dist/systems/wall/wall-curve.js +1 -1
  295. package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
  296. package/dist/systems/wall/wall-mitering.js +44 -8
  297. package/dist/systems/wall/wall-top.d.ts +40 -0
  298. package/dist/systems/wall/wall-top.d.ts.map +1 -0
  299. package/dist/systems/wall/wall-top.js +46 -0
  300. package/dist/utils/clone-scene-graph.d.ts +1 -0
  301. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  302. package/dist/utils/clone-scene-graph.js +56 -5
  303. package/dist/utils/heal-scene-graph.d.ts +18 -0
  304. package/dist/utils/heal-scene-graph.d.ts.map +1 -0
  305. package/dist/utils/heal-scene-graph.js +106 -0
  306. package/dist/validation/validate-build-json.d.ts +3 -0
  307. package/dist/validation/validate-build-json.d.ts.map +1 -1
  308. package/dist/validation/validate-build-json.js +90 -5
  309. package/package.json +4 -4
  310. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +0 -2
  311. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +0 -1
  312. package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +0 -273
  313. package/dist/lib/space-detection-pause.test.d.ts +0 -2
  314. package/dist/lib/space-detection-pause.test.d.ts.map +0 -1
  315. package/dist/lib/space-detection-pause.test.js +0 -42
  316. package/dist/lib/space-detection.test.d.ts +0 -2
  317. package/dist/lib/space-detection.test.d.ts.map +0 -1
  318. package/dist/lib/space-detection.test.js +0 -77
  319. package/dist/registry/registry.test.d.ts +0 -2
  320. package/dist/registry/registry.test.d.ts.map +0 -1
  321. package/dist/registry/registry.test.js +0 -183
  322. package/dist/registry/relations-resolver.test.d.ts +0 -2
  323. package/dist/registry/relations-resolver.test.d.ts.map +0 -1
  324. package/dist/registry/relations-resolver.test.js +0 -183
  325. package/dist/registry/scene-api.test.d.ts +0 -2
  326. package/dist/registry/scene-api.test.d.ts.map +0 -1
  327. package/dist/registry/scene-api.test.js +0 -183
  328. package/dist/registry/subtree.test.d.ts +0 -2
  329. package/dist/registry/subtree.test.d.ts.map +0 -1
  330. package/dist/registry/subtree.test.js +0 -133
  331. package/dist/schema/asset-url.test.d.ts +0 -2
  332. package/dist/schema/asset-url.test.d.ts.map +0 -1
  333. package/dist/schema/asset-url.test.js +0 -134
  334. package/dist/services/alignment-anchors.test.d.ts +0 -2
  335. package/dist/services/alignment-anchors.test.d.ts.map +0 -1
  336. package/dist/services/alignment-anchors.test.js +0 -383
  337. package/dist/services/alignment.test.d.ts +0 -2
  338. package/dist/services/alignment.test.d.ts.map +0 -1
  339. package/dist/services/alignment.test.js +0 -92
  340. package/dist/services/drag-session.test.d.ts +0 -2
  341. package/dist/services/drag-session.test.d.ts.map +0 -1
  342. package/dist/services/drag-session.test.js +0 -219
  343. package/dist/services/hosting.test.d.ts +0 -2
  344. package/dist/services/hosting.test.d.ts.map +0 -1
  345. package/dist/services/hosting.test.js +0 -199
  346. package/dist/services/movement.test.d.ts +0 -2
  347. package/dist/services/movement.test.d.ts.map +0 -1
  348. package/dist/services/movement.test.js +0 -133
  349. package/dist/services/single-undo-dance.test.d.ts +0 -2
  350. package/dist/services/single-undo-dance.test.d.ts.map +0 -1
  351. package/dist/services/single-undo-dance.test.js +0 -210
  352. package/dist/services/snap.test.d.ts +0 -2
  353. package/dist/services/snap.test.d.ts.map +0 -1
  354. package/dist/services/snap.test.js +0 -95
  355. package/dist/store/actions/node-mutation-sanitize.test.d.ts +0 -2
  356. package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +0 -1
  357. package/dist/store/actions/node-mutation-sanitize.test.js +0 -147
  358. package/dist/store/actions/reparent.test.d.ts +0 -2
  359. package/dist/store/actions/reparent.test.d.ts.map +0 -1
  360. package/dist/store/actions/reparent.test.js +0 -212
  361. package/dist/store/use-scene-elevator-migration.test.d.ts +0 -2
  362. package/dist/store/use-scene-elevator-migration.test.d.ts.map +0 -1
  363. package/dist/store/use-scene-elevator-migration.test.js +0 -109
  364. package/dist/systems/elevator/elevator-opening-sync.test.d.ts +0 -2
  365. package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +0 -1
  366. package/dist/systems/elevator/elevator-opening-sync.test.js +0 -146
  367. package/dist/systems/elevator/elevator-runtime.test.d.ts +0 -2
  368. package/dist/systems/elevator/elevator-runtime.test.d.ts.map +0 -1
  369. package/dist/systems/elevator/elevator-runtime.test.js +0 -64
  370. package/dist/systems/stair/stair-opening-preview.test.d.ts +0 -2
  371. package/dist/systems/stair/stair-opening-preview.test.d.ts.map +0 -1
  372. package/dist/systems/stair/stair-opening-preview.test.js +0 -80
  373. package/dist/systems/stair/stair-opening-sync.test.d.ts +0 -2
  374. package/dist/systems/stair/stair-opening-sync.test.d.ts.map +0 -1
  375. package/dist/systems/stair/stair-opening-sync.test.js +0 -446
  376. package/dist/utils/clone-scene-graph.test.d.ts +0 -2
  377. package/dist/utils/clone-scene-graph.test.d.ts.map +0 -1
  378. package/dist/utils/clone-scene-graph.test.js +0 -59
@@ -3,6 +3,46 @@ import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
4
  import { MaterialSchema } from '../material';
5
5
  export const RoofType = z.enum(['hip', 'gable', 'shed', 'gambrel', 'dutch', 'mansard', 'flat']);
6
+ export const MIN_ROOF_SEGMENT_TRIM_SPAN = 0.1;
7
+ const DEFAULT_ROOF_SEGMENT_WIDTH = 8;
8
+ const DEFAULT_ROOF_SEGMENT_DEPTH = 6;
9
+ export const RoofSegmentTrim = z
10
+ .object({
11
+ left: z.number().min(0).default(0),
12
+ right: z.number().min(0).default(0),
13
+ front: z.number().min(0).default(0),
14
+ back: z.number().min(0).default(0),
15
+ frontLeft: z.number().min(0).default(0),
16
+ frontRight: z.number().min(0).default(0),
17
+ backLeft: z.number().min(0).default(0),
18
+ backRight: z.number().min(0).default(0),
19
+ frontLeftX: z.number().min(0).default(0),
20
+ frontLeftZ: z.number().min(0).default(0),
21
+ frontRightX: z.number().min(0).default(0),
22
+ frontRightZ: z.number().min(0).default(0),
23
+ backLeftX: z.number().min(0).default(0),
24
+ backLeftZ: z.number().min(0).default(0),
25
+ backRightX: z.number().min(0).default(0),
26
+ backRightZ: z.number().min(0).default(0),
27
+ })
28
+ .default({
29
+ left: 0,
30
+ right: 0,
31
+ front: 0,
32
+ back: 0,
33
+ frontLeft: 0,
34
+ frontRight: 0,
35
+ backLeft: 0,
36
+ backRight: 0,
37
+ frontLeftX: 0,
38
+ frontLeftZ: 0,
39
+ frontRightX: 0,
40
+ frontRightZ: 0,
41
+ backLeftX: 0,
42
+ backLeftZ: 0,
43
+ backRightX: 0,
44
+ backRightZ: 0,
45
+ });
6
46
  // Default shape ratios. Tuning these used to require editing the geometry
7
47
  // code in two places; they are now schema fields with these defaults.
8
48
  export const ROOF_SHAPE_DEFAULTS = {
@@ -18,6 +58,17 @@ export const ROOF_SHAPE_DEFAULTS = {
18
58
  dutchHipWidthRatio: 0.25,
19
59
  /** Dutch: hip face rises this fraction of the way to the peak. */
20
60
  dutchHipHeightRatio: 0.5,
61
+ /** Dutch: gable waist span along the ridge axis, as a fraction of the max span. */
62
+ dutchWaistLengthRatio: 0.98,
63
+ /**
64
+ * Dutch: how far the gablet's barge board extends outward past the gablet
65
+ * end-wall, along the ridge axis, in metres. 0 disables the rake. The board
66
+ * lies in the gablet's slope planes (coplanar with the main Dutch slopes)
67
+ * and overhangs the lower hip skirt; the gablet end-wall itself stays put.
68
+ */
69
+ dutchGabletRake: 0.48,
70
+ /** Dutch: thickness of the top gable rake slab. */
71
+ dutchTopRakeThickness: 0.21,
21
72
  };
22
73
  export const RoofSegmentNode = BaseNode.extend({
23
74
  id: objectId('rseg'),
@@ -45,6 +96,10 @@ export const RoofSegmentNode = BaseNode.extend({
45
96
  // Footprint dimensions
46
97
  width: z.number().default(8),
47
98
  depth: z.number().default(6),
99
+ // Segment-local distances trimmed from each footprint side. The trim
100
+ // boundary is projected vertically through the roof volume, so the
101
+ // resulting edge follows the actual sloped roof surfaces.
102
+ trim: RoofSegmentTrim,
48
103
  // Wall height beneath the roof
49
104
  wallHeight: z.number().default(0.5),
50
105
  // Roof pitch in degrees — angle of the primary slope face.
@@ -90,6 +145,17 @@ export const RoofSegmentNode = BaseNode.extend({
90
145
  .min(0.1)
91
146
  .max(0.9)
92
147
  .default(ROOF_SHAPE_DEFAULTS.dutchHipHeightRatio),
148
+ dutchWaistLengthRatio: z
149
+ .number()
150
+ .min(0.1)
151
+ .max(1)
152
+ .default(ROOF_SHAPE_DEFAULTS.dutchWaistLengthRatio),
153
+ dutchGabletRake: z.number().min(0).max(3).default(ROOF_SHAPE_DEFAULTS.dutchGabletRake),
154
+ dutchTopRakeThickness: z
155
+ .number()
156
+ .min(0.01)
157
+ .max(0.5)
158
+ .default(ROOF_SHAPE_DEFAULTS.dutchTopRakeThickness),
93
159
  // Hosted accessories — chimney, dormer, skylight, box-vent,
94
160
  // ridge-vent, solar-panel, gutter. Each accessory's `parentId` points back
95
161
  // here; the segment renderer mounts them recursively via
@@ -105,6 +171,7 @@ export const RoofSegmentNode = BaseNode.extend({
105
171
  Multiple segments can be combined to form complex roof shapes.
106
172
  - roofType: hip, gable, shed, gambrel, dutch, mansard, flat
107
173
  - width/depth: footprint dimensions
174
+ - trim: segment-local side cut distances
108
175
  - wallHeight: height of walls below the roof
109
176
  - pitch: roof slope in degrees (angle of the primary slope face)
110
177
  - wallThickness/deckThickness: structural thicknesses
@@ -113,16 +180,144 @@ export const RoofSegmentNode = BaseNode.extend({
113
180
  - gambrelLowerWidthRatio / gambrelLowerHeightRatio: kink position on gambrel roofs
114
181
  - mansardSteepWidthRatio / mansardSteepHeightRatio: waist position on mansard roofs
115
182
  - dutchHipWidthRatio / dutchHipHeightRatio: hip-to-gable split on dutch roofs
183
+ - dutchWaistLengthRatio: gable waist span along the ridge axis
184
+ - dutchGabletRake: gablet barge-board overhang past the gablet end-wall (m, 0 = none)
185
+ - dutchTopRakeThickness: thickness of the top gable rake slab
116
186
  `);
187
+ function finiteNonNegative(value) {
188
+ return typeof value === 'number' && Number.isFinite(value) ? Math.max(0, value) : 0;
189
+ }
190
+ function finitePositive(value, fallback) {
191
+ return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : fallback;
192
+ }
193
+ function normalizeTrimAxis(start, end, span) {
194
+ const maxTotal = Math.max(0, finiteNonNegative(span) - MIN_ROOF_SEGMENT_TRIM_SPAN);
195
+ let a = Math.min(finiteNonNegative(start), maxTotal);
196
+ let b = Math.min(finiteNonNegative(end), maxTotal);
197
+ const total = a + b;
198
+ if (total > maxTotal && total > 0) {
199
+ const scale = maxTotal / total;
200
+ a *= scale;
201
+ b *= scale;
202
+ }
203
+ return [a, b];
204
+ }
205
+ export function normalizeRoofSegmentTrim(node) {
206
+ const trim = node.trim ?? {};
207
+ const [left, right] = normalizeTrimAxis(trim.left, trim.right, node.width);
208
+ const [back, front] = normalizeTrimAxis(trim.back, trim.front, node.depth);
209
+ const maxWidthDiagonal = Math.max(0, finiteNonNegative(node.width) - left - right);
210
+ const maxDepthDiagonal = Math.max(0, finiteNonNegative(node.depth) - front - back);
211
+ const maxWidthPair = Math.max(0, maxWidthDiagonal - MIN_ROOF_SEGMENT_TRIM_SPAN);
212
+ const maxDepthPair = Math.max(0, maxDepthDiagonal - MIN_ROOF_SEGMENT_TRIM_SPAN);
213
+ let [frontLeftX, frontLeftZ] = normalizeCornerAxisTrim(trim.frontLeft, trim.frontLeftX, trim.frontLeftZ, maxWidthPair, maxDepthPair);
214
+ let [frontRightX, frontRightZ] = normalizeCornerAxisTrim(trim.frontRight, trim.frontRightX, trim.frontRightZ, maxWidthPair, maxDepthPair);
215
+ let [backLeftX, backLeftZ] = normalizeCornerAxisTrim(trim.backLeft, trim.backLeftX, trim.backLeftZ, maxWidthPair, maxDepthPair);
216
+ let [backRightX, backRightZ] = normalizeCornerAxisTrim(trim.backRight, trim.backRightX, trim.backRightZ, maxWidthPair, maxDepthPair);
217
+ for (let i = 0; i < 3; i += 1) {
218
+ ;
219
+ [frontLeftX, frontRightX] = normalizeTrimPair(frontLeftX, frontRightX, maxWidthPair);
220
+ [backLeftX, backRightX] = normalizeTrimPair(backLeftX, backRightX, maxWidthPair);
221
+ [frontLeftZ, backLeftZ] = normalizeTrimPair(frontLeftZ, backLeftZ, maxDepthPair);
222
+ [frontRightZ, backRightZ] = normalizeTrimPair(frontRightZ, backRightZ, maxDepthPair);
223
+ }
224
+ const frontLeft = Math.min(frontLeftX, frontLeftZ);
225
+ const frontRight = Math.min(frontRightX, frontRightZ);
226
+ const backLeft = Math.min(backLeftX, backLeftZ);
227
+ const backRight = Math.min(backRightX, backRightZ);
228
+ return {
229
+ left,
230
+ right,
231
+ front,
232
+ back,
233
+ frontLeft,
234
+ frontRight,
235
+ backLeft,
236
+ backRight,
237
+ frontLeftX,
238
+ frontLeftZ,
239
+ frontRightX,
240
+ frontRightZ,
241
+ backLeftX,
242
+ backLeftZ,
243
+ backRightX,
244
+ backRightZ,
245
+ };
246
+ }
247
+ function normalizeTrimPair(a, b, maxTotal) {
248
+ const total = a + b;
249
+ if (total <= maxTotal || total <= 0)
250
+ return [a, b];
251
+ const scale = maxTotal / total;
252
+ return [a * scale, b * scale];
253
+ }
254
+ function normalizeCornerAxisTrim(scalar, axisX, axisZ, maxX, maxZ) {
255
+ const x = finiteNonNegative(axisX);
256
+ const z = finiteNonNegative(axisZ);
257
+ const fallback = finiteNonNegative(scalar);
258
+ if (x > 0 || z > 0) {
259
+ return [Math.min(x, maxX), Math.min(z, maxZ)];
260
+ }
261
+ return [Math.min(fallback, maxX), Math.min(fallback, maxZ)];
262
+ }
263
+ function getDutchUpperShellBounds(node) {
264
+ const metrics = getDutchRoofMetrics(node);
265
+ const width = finitePositive(node.width, DEFAULT_ROOF_SEGMENT_WIDTH);
266
+ const depth = finitePositive(node.depth, DEFAULT_ROOF_SEGMENT_DEPTH);
267
+ const rake = node.dutchGabletRake ?? ROOF_SHAPE_DEFAULTS.dutchGabletRake;
268
+ const rakeReach = metrics.axis === 'x'
269
+ ? Math.min(Math.max(0, rake), Math.max(0, width / 2 - metrics.waistHalfX) * 0.98)
270
+ : Math.min(Math.max(0, rake), Math.max(0, depth / 2 - metrics.waistHalfZ) * 0.98);
271
+ return {
272
+ ...metrics,
273
+ upperHalfX: metrics.axis === 'x' ? metrics.waistHalfX + rakeReach : metrics.waistHalfX,
274
+ upperHalfZ: metrics.axis === 'x' ? metrics.waistHalfZ : metrics.waistHalfZ + rakeReach,
275
+ };
276
+ }
117
277
  function withRatioDefaults(input) {
118
278
  return {
119
279
  ...input,
280
+ width: finitePositive(input.width, DEFAULT_ROOF_SEGMENT_WIDTH),
281
+ depth: finitePositive(input.depth, DEFAULT_ROOF_SEGMENT_DEPTH),
120
282
  gambrelLowerWidthRatio: input.gambrelLowerWidthRatio ?? ROOF_SHAPE_DEFAULTS.gambrelLowerWidthRatio,
121
283
  gambrelLowerHeightRatio: input.gambrelLowerHeightRatio ?? ROOF_SHAPE_DEFAULTS.gambrelLowerHeightRatio,
122
284
  mansardSteepWidthRatio: input.mansardSteepWidthRatio ?? ROOF_SHAPE_DEFAULTS.mansardSteepWidthRatio,
123
285
  mansardSteepHeightRatio: input.mansardSteepHeightRatio ?? ROOF_SHAPE_DEFAULTS.mansardSteepHeightRatio,
124
286
  dutchHipWidthRatio: input.dutchHipWidthRatio ?? ROOF_SHAPE_DEFAULTS.dutchHipWidthRatio,
125
287
  dutchHipHeightRatio: input.dutchHipHeightRatio ?? ROOF_SHAPE_DEFAULTS.dutchHipHeightRatio,
288
+ dutchWaistLengthRatio: input.dutchWaistLengthRatio ?? ROOF_SHAPE_DEFAULTS.dutchWaistLengthRatio,
289
+ };
290
+ }
291
+ export function getDutchRoofMetrics(input) {
292
+ const width = finitePositive(input.width, DEFAULT_ROOF_SEGMENT_WIDTH);
293
+ const depth = finitePositive(input.depth, DEFAULT_ROOF_SEGMENT_DEPTH);
294
+ const inset = Math.min(width, depth) * (input.dutchHipWidthRatio ?? ROOF_SHAPE_DEFAULTS.dutchHipWidthRatio);
295
+ const waistLengthRatio = input.dutchWaistLengthRatio ?? ROOF_SHAPE_DEFAULTS.dutchWaistLengthRatio;
296
+ if (width >= depth) {
297
+ const waistHalfX = Math.max(0, (width / 2 - inset) * waistLengthRatio);
298
+ const waistHalfZ = Math.max(0, depth / 2 - inset);
299
+ return {
300
+ axis: 'x',
301
+ inset,
302
+ waistHalfX,
303
+ waistHalfZ,
304
+ ridgeStart: [-waistHalfX, 0],
305
+ ridgeEnd: [waistHalfX, 0],
306
+ shoulderInsetAlongDepth: Math.max(0, depth / 2 - waistHalfZ),
307
+ shoulderInsetAlongWidth: Math.max(0, width / 2 - waistHalfX),
308
+ };
309
+ }
310
+ const waistHalfX = Math.max(0, width / 2 - inset);
311
+ const waistHalfZ = Math.max(0, (depth / 2 - inset) * waistLengthRatio);
312
+ return {
313
+ axis: 'z',
314
+ inset,
315
+ waistHalfX,
316
+ waistHalfZ,
317
+ ridgeStart: [0, waistHalfZ],
318
+ ridgeEnd: [0, -waistHalfZ],
319
+ shoulderInsetAlongDepth: Math.max(0, depth / 2 - waistHalfZ),
320
+ shoulderInsetAlongWidth: Math.max(0, width / 2 - waistHalfX),
126
321
  };
127
322
  }
128
323
  function getPrimarySlopeRun(input) {
@@ -188,19 +383,109 @@ export function getSegmentSlopeFrame(node) {
188
383
  export function getActiveRoofHeight(node) {
189
384
  return getSegmentSlopeFrame(node).activeRh;
190
385
  }
386
+ export function getRoofSegmentVisibleTopBounds(segment) {
387
+ const { activeRh, cosTheta, sinTheta } = getSegmentSlopeFrame(segment);
388
+ const width = finitePositive(segment.width, DEFAULT_ROOF_SEGMENT_WIDTH);
389
+ const depth = finitePositive(segment.depth, DEFAULT_ROOF_SEGMENT_DEPTH);
390
+ const trim = normalizeRoofSegmentTrim({ ...segment, width, depth });
391
+ const horizontalOverhang = finiteNonNegative(segment.overhang) * cosTheta;
392
+ const deckExt = finiteNonNegative(segment.wallThickness) / 2 + horizontalOverhang;
393
+ const shingleOverhang = finiteNonNegative(segment.shingleThickness) * sinTheta;
394
+ let xExt = deckExt;
395
+ let frontExt = deckExt;
396
+ let backExt = deckExt;
397
+ if (segment.roofType === 'hip' ||
398
+ segment.roofType === 'mansard' ||
399
+ segment.roofType === 'dutch') {
400
+ xExt += shingleOverhang;
401
+ frontExt += shingleOverhang;
402
+ backExt += shingleOverhang;
403
+ }
404
+ else if (segment.roofType === 'gable' || segment.roofType === 'gambrel') {
405
+ frontExt += shingleOverhang;
406
+ backExt += shingleOverhang;
407
+ }
408
+ else if (segment.roofType === 'shed' && activeRh > 0) {
409
+ frontExt += shingleOverhang;
410
+ }
411
+ let minX = trim.left > 0 ? -width / 2 + trim.left : -width / 2 - xExt;
412
+ let maxX = trim.right > 0 ? width / 2 - trim.right : width / 2 + xExt;
413
+ let minZ = trim.back > 0 ? -depth / 2 + trim.back : -depth / 2 - backExt;
414
+ let maxZ = trim.front > 0 ? depth / 2 - trim.front : depth / 2 + frontExt;
415
+ if (trim.frontLeftX > 0 && trim.frontLeftZ > 0 && maxZ - trim.frontLeftZ < 0) {
416
+ minX = Math.max(minX, minX + (trim.frontLeftX * (trim.frontLeftZ - maxZ)) / trim.frontLeftZ);
417
+ }
418
+ if (trim.backLeftX > 0 && trim.backLeftZ > 0 && minZ + trim.backLeftZ > 0) {
419
+ minX = Math.max(minX, minX + (trim.backLeftX * (trim.backLeftZ + minZ)) / trim.backLeftZ);
420
+ }
421
+ if (trim.frontRightX > 0 && trim.frontRightZ > 0 && maxZ - trim.frontRightZ < 0) {
422
+ maxX = Math.min(maxX, maxX - (trim.frontRightX * (trim.frontRightZ - maxZ)) / trim.frontRightZ);
423
+ }
424
+ if (trim.backRightX > 0 && trim.backRightZ > 0 && minZ + trim.backRightZ > 0) {
425
+ maxX = Math.min(maxX, maxX - (trim.backRightX * (trim.backRightZ + minZ)) / trim.backRightZ);
426
+ }
427
+ if (trim.frontLeftX > 0 && trim.frontLeftZ > 0 && minX + trim.frontLeftX > 0) {
428
+ maxZ = Math.min(maxZ, maxZ - (trim.frontLeftZ * (trim.frontLeftX + minX)) / trim.frontLeftX);
429
+ }
430
+ if (trim.frontRightX > 0 && trim.frontRightZ > 0 && maxX - trim.frontRightX < 0) {
431
+ maxZ = Math.min(maxZ, maxZ - (trim.frontRightZ * (trim.frontRightX - maxX)) / trim.frontRightX);
432
+ }
433
+ if (trim.backLeftX > 0 && trim.backLeftZ > 0 && minX + trim.backLeftX > 0) {
434
+ minZ = Math.max(minZ, minZ + (trim.backLeftZ * (trim.backLeftX + minX)) / trim.backLeftX);
435
+ }
436
+ if (trim.backRightX > 0 && trim.backRightZ > 0 && maxX - trim.backRightX < 0) {
437
+ minZ = Math.max(minZ, minZ + (trim.backRightZ * (trim.backRightX - maxX)) / trim.backRightX);
438
+ }
439
+ return {
440
+ minX,
441
+ maxX,
442
+ minZ,
443
+ maxZ,
444
+ width: Math.max(0.01, maxX - minX),
445
+ depth: Math.max(0.01, maxZ - minZ),
446
+ };
447
+ }
191
448
  /** Segment-local surface height used by roof accessory placement and hit disambiguation. */
192
449
  export function getRoofSegmentSurfaceY(node, localX, localZ) {
193
- const activeRh = getActiveRoofHeight(node);
450
+ const slopeFrame = getSegmentSlopeFrame(node);
451
+ const activeRh = slopeFrame.activeRh;
194
452
  const peakY = node.wallHeight + activeRh;
195
453
  if (activeRh === 0)
196
454
  return node.wallHeight;
197
- if (node.roofType === 'gable' ||
198
- node.roofType === 'gambrel' ||
199
- node.roofType === 'mansard' ||
200
- node.roofType === 'dutch') {
455
+ if (node.roofType === 'gable' || node.roofType === 'gambrel' || node.roofType === 'mansard') {
201
456
  const t = node.depth > 0 ? Math.abs(localZ) / (node.depth / 2) : 0;
202
457
  return peakY - t * activeRh;
203
458
  }
459
+ if (node.roofType === 'dutch') {
460
+ const hipHeightRatio = node.dutchHipHeightRatio ?? ROOF_SHAPE_DEFAULTS.dutchHipHeightRatio;
461
+ const metrics = getDutchUpperShellBounds(node);
462
+ const lowerRise = activeRh * hipHeightRatio;
463
+ if (metrics.axis === 'x') {
464
+ const waistHalfZ = Math.max(0.0001, metrics.waistHalfZ);
465
+ if (Math.abs(localX) <= metrics.upperHalfX && Math.abs(localZ) <= waistHalfZ) {
466
+ const upperRise = activeRh * (1 - hipHeightRatio);
467
+ const upperTan = upperRise / waistHalfZ;
468
+ return peakY - Math.abs(localZ) * upperTan;
469
+ }
470
+ const xProgressDenom = Math.max(0.0001, node.width / 2 - metrics.waistHalfX);
471
+ const zProgressDenom = Math.max(0.0001, node.depth / 2 - waistHalfZ);
472
+ const xProgress = Math.max(0, Math.abs(localX) - metrics.waistHalfX) / xProgressDenom;
473
+ const zProgress = Math.max(0, Math.abs(localZ) - waistHalfZ) / zProgressDenom;
474
+ return node.wallHeight + lowerRise * (1 - Math.min(1, Math.max(xProgress, zProgress)));
475
+ }
476
+ const waistHalfX = Math.max(0.0001, metrics.waistHalfX);
477
+ if (Math.abs(localX) <= waistHalfX && Math.abs(localZ) <= metrics.upperHalfZ) {
478
+ const upperRise = activeRh * (1 - hipHeightRatio);
479
+ const upperRun = waistHalfX;
480
+ const upperTan = upperRise / upperRun;
481
+ return peakY - Math.abs(localX) * upperTan;
482
+ }
483
+ const xProgressDenom = Math.max(0.0001, node.width / 2 - waistHalfX);
484
+ const zProgressDenom = Math.max(0.0001, node.depth / 2 - metrics.waistHalfZ);
485
+ const xProgress = Math.max(0, Math.abs(localX) - waistHalfX) / xProgressDenom;
486
+ const zProgress = Math.max(0, Math.abs(localZ) - metrics.waistHalfZ) / zProgressDenom;
487
+ return node.wallHeight + lowerRise * (1 - Math.min(1, Math.max(xProgress, zProgress)));
488
+ }
204
489
  if (node.roofType === 'shed') {
205
490
  const t = (localZ + node.depth / 2) / (node.depth || 1);
206
491
  return peakY - t * activeRh;
@@ -25,7 +25,7 @@ export declare const RoofNode: z.ZodObject<{
25
25
  type: z.ZodDefault<z.ZodLiteral<"roof">>;
26
26
  material: z.ZodOptional<z.ZodObject<{
27
27
  id: z.ZodOptional<z.ZodString>;
28
- preset: z.ZodOptional<z.ZodEnum<{
28
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
29
29
  custom: "custom";
30
30
  white: "white";
31
31
  brick: "brick";
@@ -36,7 +36,7 @@ export declare const RoofNode: z.ZodObject<{
36
36
  plaster: "plaster";
37
37
  tile: "tile";
38
38
  marble: "marble";
39
- }>>;
39
+ }>>>;
40
40
  properties: z.ZodOptional<z.ZodObject<{
41
41
  color: z.ZodDefault<z.ZodString>;
42
42
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -58,7 +58,7 @@ export declare const RoofNode: z.ZodObject<{
58
58
  materialPreset: z.ZodOptional<z.ZodString>;
59
59
  topMaterial: z.ZodOptional<z.ZodObject<{
60
60
  id: z.ZodOptional<z.ZodString>;
61
- preset: z.ZodOptional<z.ZodEnum<{
61
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
62
62
  custom: "custom";
63
63
  white: "white";
64
64
  brick: "brick";
@@ -69,7 +69,7 @@ export declare const RoofNode: z.ZodObject<{
69
69
  plaster: "plaster";
70
70
  tile: "tile";
71
71
  marble: "marble";
72
- }>>;
72
+ }>>>;
73
73
  properties: z.ZodOptional<z.ZodObject<{
74
74
  color: z.ZodDefault<z.ZodString>;
75
75
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -91,7 +91,7 @@ export declare const RoofNode: z.ZodObject<{
91
91
  topMaterialPreset: z.ZodOptional<z.ZodString>;
92
92
  edgeMaterial: z.ZodOptional<z.ZodObject<{
93
93
  id: z.ZodOptional<z.ZodString>;
94
- preset: z.ZodOptional<z.ZodEnum<{
94
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
95
95
  custom: "custom";
96
96
  white: "white";
97
97
  brick: "brick";
@@ -102,7 +102,7 @@ export declare const RoofNode: z.ZodObject<{
102
102
  plaster: "plaster";
103
103
  tile: "tile";
104
104
  marble: "marble";
105
- }>>;
105
+ }>>>;
106
106
  properties: z.ZodOptional<z.ZodObject<{
107
107
  color: z.ZodDefault<z.ZodString>;
108
108
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -124,7 +124,7 @@ export declare const RoofNode: z.ZodObject<{
124
124
  edgeMaterialPreset: z.ZodOptional<z.ZodString>;
125
125
  wallMaterial: z.ZodOptional<z.ZodObject<{
126
126
  id: z.ZodOptional<z.ZodString>;
127
- preset: z.ZodOptional<z.ZodEnum<{
127
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
128
128
  custom: "custom";
129
129
  white: "white";
130
130
  brick: "brick";
@@ -135,7 +135,7 @@ export declare const RoofNode: z.ZodObject<{
135
135
  plaster: "plaster";
136
136
  tile: "tile";
137
137
  marble: "marble";
138
- }>>;
138
+ }>>>;
139
139
  properties: z.ZodOptional<z.ZodObject<{
140
140
  color: z.ZodDefault<z.ZodString>;
141
141
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -47,6 +47,7 @@ export declare const ShelfNode: z.ZodObject<{
47
47
  children: z.ZodDefault<z.ZodArray<z.ZodDefault<z.ZodTemplateLiteral<`item_${string}`>>>>;
48
48
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
49
49
  rotation: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
50
+ supportSlabId: z.ZodOptional<z.ZodString>;
50
51
  width: z.ZodDefault<z.ZodNumber>;
51
52
  depth: z.ZodDefault<z.ZodNumber>;
52
53
  thickness: z.ZodDefault<z.ZodNumber>;
@@ -69,7 +70,7 @@ export declare const ShelfNode: z.ZodObject<{
69
70
  }>>;
70
71
  material: z.ZodOptional<z.ZodObject<{
71
72
  id: z.ZodOptional<z.ZodString>;
72
- preset: z.ZodOptional<z.ZodEnum<{
73
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
73
74
  custom: "custom";
74
75
  white: "white";
75
76
  brick: "brick";
@@ -80,7 +81,7 @@ export declare const ShelfNode: z.ZodObject<{
80
81
  plaster: "plaster";
81
82
  tile: "tile";
82
83
  marble: "marble";
83
- }>>;
84
+ }>>>;
84
85
  properties: z.ZodOptional<z.ZodObject<{
85
86
  color: z.ZodDefault<z.ZodString>;
86
87
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -100,6 +101,7 @@ export declare const ShelfNode: z.ZodObject<{
100
101
  }, z.core.$strip>>;
101
102
  }, z.core.$strip>>;
102
103
  materialPreset: z.ZodOptional<z.ZodString>;
104
+ slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
103
105
  }, z.core.$strip>;
104
106
  export type ShelfNode = z.infer<typeof ShelfNode>;
105
107
  //# sourceMappingURL=shelf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shelf.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/shelf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwDpB,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
1
+ {"version":3,"file":"shelf.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/shelf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiEpB,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA"}
@@ -42,6 +42,8 @@ export const ShelfNode = BaseNode.extend({
42
42
  children: z.array(ItemNode.shape.id).default([]),
43
43
  position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
44
44
  rotation: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
45
+ // Persisted slab-support host — see ItemNode.supportSlabId for the rules.
46
+ supportSlabId: z.string().optional(),
45
47
  // Dimensions (meters). Schema-level defaults intentionally reproduce
46
48
  // the v1 wall-shelf so existing v1 scenes that omit the v2-introduced
47
49
  // fields (style / rows / columns / with*) load with their original
@@ -81,4 +83,10 @@ export const ShelfNode = BaseNode.extend({
81
83
  // unchanged once `'shelf'` is added to `MaterialTarget`.
82
84
  material: MaterialSchema.optional(),
83
85
  materialPreset: z.string().optional(),
86
+ // Per-slot material overrides, mirroring `ItemNode.slots`. Key = slot id
87
+ // (`shelves` / `frame` / `back`, see `shelfSlots`), value = a `MaterialRef`
88
+ // string (`library:<id>` or `scene:<id>`). Absent slot = fall back to the
89
+ // legacy whole-shelf `material` / `materialPreset`, then the registry slot
90
+ // default. A dangling ref renders the default (never blocks).
91
+ slots: z.record(z.string(), z.string()).optional(),
84
92
  });
@@ -21,6 +21,15 @@ export declare const SiteNode: z.ZodObject<{
21
21
  type: z.ZodLiteral<"polygon">;
22
22
  points: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
23
23
  }, z.core.$strip>>>;
24
+ terrain: z.ZodOptional<z.ZodObject<{
25
+ type: z.ZodLiteral<"heightfield">;
26
+ origin: z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>;
27
+ spacing: z.ZodNumber;
28
+ cols: z.ZodNumber;
29
+ rows: z.ZodNumber;
30
+ step: z.ZodNumber;
31
+ heights: z.ZodString;
32
+ }, z.core.$strip>>;
24
33
  children: z.ZodDefault<z.ZodArray<z.ZodString>>;
25
34
  }, z.core.$strip>;
26
35
  export type SiteNode = z.infer<typeof SiteNode>;
@@ -1 +1 @@
1
- {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/site.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAevB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;iBAsBpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
1
+ {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/site.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAUvB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4BpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
@@ -2,16 +2,12 @@
2
2
  import dedent from 'dedent';
3
3
  import { z } from 'zod';
4
4
  import { BaseNode, nodeType, objectId } from '../base';
5
+ import { TerrainData } from '../terrain';
5
6
  // 2D Polygon
6
7
  const PropertyLineData = z.object({
7
8
  type: z.literal('polygon'),
8
9
  points: z.array(z.tuple([z.number(), z.number()])),
9
10
  });
10
- // 3D Polygon/Mesh
11
- // const TerrainData = z.object({
12
- // type: z.literal('terrain'),
13
- // points: z.array(z.tuple([z.number(), z.number(), z.number()])),
14
- // })
15
11
  export const SiteNode = BaseNode.extend({
16
12
  id: objectId('site'),
17
13
  type: nodeType('site'),
@@ -26,10 +22,16 @@ export const SiteNode = BaseNode.extend({
26
22
  [-15, 15],
27
23
  ],
28
24
  }),
29
- // terrain: TerrainData,
25
+ /**
26
+ * Sculpted ground. Absent means flat ground at the datum — the state every
27
+ * scene that predates terrain is in, and the state an untouched site stays in
28
+ * so ~11 KB of base64 zeroes does not land in every saved scene.
29
+ */
30
+ terrain: TerrainData.optional(),
30
31
  children: z.array(z.string()).default([]),
31
32
  }).describe(dedent `
32
33
  Site node - used to represent a site
33
34
  - polygon: polygon data
35
+ - terrain: optional sculpted heightfield; absent means flat ground
34
36
  - children: array of child node ids (buildings, items)
35
37
  `);
@@ -14,15 +14,15 @@ export declare const SkylightType: z.ZodEnum<{
14
14
  }>;
15
15
  export type SkylightType = (typeof SKYLIGHT_TYPE_ORDER)[number];
16
16
  export declare const SkylightOpeningSide: z.ZodEnum<{
17
+ right: "right";
18
+ left: "left";
17
19
  top: "top";
18
20
  bottom: "bottom";
19
- left: "left";
20
- right: "right";
21
21
  }>;
22
22
  export type SkylightOpeningSide = z.infer<typeof SkylightOpeningSide>;
23
23
  export declare const SkylightSlideDirection: z.ZodEnum<{
24
- x: "x";
25
24
  z: "z";
25
+ x: "x";
26
26
  }>;
27
27
  export type SkylightSlideDirection = z.infer<typeof SkylightSlideDirection>;
28
28
  export type SkylightTypePreset = {
@@ -173,7 +173,7 @@ export declare const SkylightNode: z.ZodObject<{
173
173
  type: z.ZodDefault<z.ZodLiteral<"skylight">>;
174
174
  material: z.ZodOptional<z.ZodObject<{
175
175
  id: z.ZodOptional<z.ZodString>;
176
- preset: z.ZodOptional<z.ZodEnum<{
176
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
177
177
  custom: "custom";
178
178
  white: "white";
179
179
  brick: "brick";
@@ -184,7 +184,7 @@ export declare const SkylightNode: z.ZodObject<{
184
184
  plaster: "plaster";
185
185
  tile: "tile";
186
186
  marble: "marble";
187
- }>>;
187
+ }>>>;
188
188
  properties: z.ZodOptional<z.ZodObject<{
189
189
  color: z.ZodDefault<z.ZodString>;
190
190
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -206,7 +206,7 @@ export declare const SkylightNode: z.ZodObject<{
206
206
  materialPreset: z.ZodOptional<z.ZodString>;
207
207
  glassMaterial: z.ZodOptional<z.ZodObject<{
208
208
  id: z.ZodOptional<z.ZodString>;
209
- preset: z.ZodOptional<z.ZodEnum<{
209
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
210
210
  custom: "custom";
211
211
  white: "white";
212
212
  brick: "brick";
@@ -217,7 +217,7 @@ export declare const SkylightNode: z.ZodObject<{
217
217
  plaster: "plaster";
218
218
  tile: "tile";
219
219
  marble: "marble";
220
- }>>;
220
+ }>>>;
221
221
  properties: z.ZodOptional<z.ZodObject<{
222
222
  color: z.ZodDefault<z.ZodString>;
223
223
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -256,17 +256,17 @@ export declare const SkylightNode: z.ZodObject<{
256
256
  lanternTopScale: z.ZodDefault<z.ZodNumber>;
257
257
  openingAngle: z.ZodDefault<z.ZodNumber>;
258
258
  openingSide: z.ZodDefault<z.ZodEnum<{
259
+ right: "right";
260
+ left: "left";
259
261
  top: "top";
260
262
  bottom: "bottom";
261
- left: "left";
262
- right: "right";
263
263
  }>>;
264
264
  operationState: z.ZodDefault<z.ZodNumber>;
265
265
  motorHousing: z.ZodDefault<z.ZodBoolean>;
266
266
  slideFraction: z.ZodDefault<z.ZodNumber>;
267
267
  slideDirection: z.ZodDefault<z.ZodEnum<{
268
- x: "x";
269
268
  z: "z";
269
+ x: "x";
270
270
  }>>;
271
271
  trackWidth: z.ZodDefault<z.ZodNumber>;
272
272
  motorHousingSize: z.ZodDefault<z.ZodNumber>;
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ export declare const MIN_SLAB_THICKNESS = 0.02;
2
3
  export declare const SlabNode: z.ZodObject<{
3
4
  object: z.ZodDefault<z.ZodLiteral<"node">>;
4
5
  name: z.ZodOptional<z.ZodString>;
@@ -19,7 +20,7 @@ export declare const SlabNode: z.ZodObject<{
19
20
  type: z.ZodDefault<z.ZodLiteral<"slab">>;
20
21
  material: z.ZodOptional<z.ZodObject<{
21
22
  id: z.ZodOptional<z.ZodString>;
22
- preset: z.ZodOptional<z.ZodEnum<{
23
+ preset: z.ZodOptional<z.ZodCatch<z.ZodEnum<{
23
24
  custom: "custom";
24
25
  white: "white";
25
26
  brick: "brick";
@@ -30,7 +31,7 @@ export declare const SlabNode: z.ZodObject<{
30
31
  plaster: "plaster";
31
32
  tile: "tile";
32
33
  marble: "marble";
33
- }>>;
34
+ }>>>;
34
35
  properties: z.ZodOptional<z.ZodObject<{
35
36
  color: z.ZodDefault<z.ZodString>;
36
37
  roughness: z.ZodDefault<z.ZodNumber>;
@@ -50,6 +51,7 @@ export declare const SlabNode: z.ZodObject<{
50
51
  }, z.core.$strip>>;
51
52
  }, z.core.$strip>>;
52
53
  materialPreset: z.ZodOptional<z.ZodString>;
54
+ slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
53
55
  polygon: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
54
56
  holes: z.ZodDefault<z.ZodArray<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>>;
55
57
  holeMetadata: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -62,6 +64,10 @@ export declare const SlabNode: z.ZodObject<{
62
64
  elevatorId: z.ZodOptional<z.ZodString>;
63
65
  }, z.core.$strip>>>;
64
66
  elevation: z.ZodDefault<z.ZodNumber>;
67
+ thickness: z.ZodDefault<z.ZodNumber>;
68
+ recessed: z.ZodDefault<z.ZodBoolean>;
69
+ recessedRimElevation: z.ZodOptional<z.ZodNumber>;
70
+ fillToTerrain: z.ZodOptional<z.ZodBoolean>;
65
71
  autoFromWalls: z.ZodDefault<z.ZodBoolean>;
66
72
  }, z.core.$strip>;
67
73
  export type SlabNode = z.infer<typeof SlabNode>;
@@ -1 +1 @@
1
- {"version":3,"file":"slab.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/slab.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}
1
+ {"version":3,"file":"slab.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/slab.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQvB,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+BpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA"}