@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,4 +1,4 @@
1
- import type { AnyNode, AnyNodeId, LevelNode, SlabNode } from '../../schema';
1
+ import type { AnyNode, AnyNodeId, LevelNode, SlabNode } from '../../schema/index.js';
2
2
  export declare function resolveLevelId(node: AnyNode, nodes: Record<string, AnyNode>): string;
3
3
  /**
4
4
  * Walks the parent chain of `nodeId` and returns the id of the first ancestor
@@ -28,6 +28,24 @@ export declare function findLevelAncestorId(nodeId: AnyNodeId, nodes: Record<str
28
28
  */
29
29
  export declare function resolveBuildingForLevel(levelId: AnyNodeId, nodes: Record<AnyNodeId, AnyNode>): AnyNodeId | null;
30
30
  export declare function initSpatialGridSync(): () => void;
31
+ /**
32
+ * Bulk slab-change guard. A scene load, reload, paste or import changes tens to
33
+ * thousands of slabs in one store write, and scanning every node twice per slab
34
+ * is O(slabs × nodes): a 4,600-slab scene blocked the main thread for ~5 s on
35
+ * every load. When at least this many slabs are added, removed or reshaped in
36
+ * one write, `markAllSlabDependents` dirties every node any slab could affect,
37
+ * once, and the per-slab scans are skipped. The marks are a superset of the
38
+ * per-slab result — and `setScene` marks every node dirty right after `set()`
39
+ * regardless — so load-time behaviour is unchanged; the saving is the scans.
40
+ */
41
+ export declare const BULK_SLAB_CHANGE_THRESHOLD = 32;
42
+ export declare function countBulkSlabChanges(nodes: Record<string, AnyNode>, prevNodes: Record<string, AnyNode>): number;
43
+ /**
44
+ * Every node a slab change can dirty, without looking at any slab: walls and
45
+ * ceilings (overlap and covering-below rules), stairs (deck attachment) and
46
+ * level-hosted floor-placed kinds (the generic re-elevation sweep).
47
+ */
48
+ export declare function markAllSlabDependents(nodes: Record<string, AnyNode>, markDirty: (id: AnyNodeId) => void): void;
31
49
  /**
32
50
  * A level's stored height moved: plane-bound walls follow the new plane,
33
51
  * stair rise re-derives, and ceilings/fences re-resolve their clamp — mark
@@ -45,7 +63,2918 @@ export declare function markDeckAttachedStairs(slabId: string, nodes: Record<str
45
63
  * Dirty every consumer of a slab's top or underside. Kept pure so committed
46
64
  * scene writes and live handle previews use the same dependency boundary.
47
65
  */
48
- export declare function markSlabChangeDependents(previous: SlabNode, next: SlabNode, nodes: Record<string, AnyNode>, markDirty: (id: AnyNodeId) => void): void;
66
+ export declare function markSlabChangeDependents(previous: SlabNode, next: SlabNode, nodes: Record<string, AnyNode>, markDirty: (id: AnyNodeId) => void, previousNodes?: Record<string, {
67
+ object: "node";
68
+ id: `site_${string}`;
69
+ parentId: string | null;
70
+ visible: boolean;
71
+ metadata: Record<string, unknown>;
72
+ children: string[];
73
+ polygon: {
74
+ type: "polygon";
75
+ points: [number, number][];
76
+ };
77
+ type: "site";
78
+ name?: string | undefined;
79
+ camera?: {
80
+ position: [number, number, number];
81
+ target: [number, number, number];
82
+ mode: "perspective" | "orthographic";
83
+ fov?: number | undefined;
84
+ zoom?: number | undefined;
85
+ } | undefined;
86
+ terrain?: {
87
+ type: "heightfield";
88
+ origin: [number, number];
89
+ spacing: number;
90
+ cols: number;
91
+ rows: number;
92
+ step: number;
93
+ heights: string;
94
+ } | undefined;
95
+ } | {
96
+ object: "node";
97
+ position: [number, number, number];
98
+ id: `building_${string}`;
99
+ parentId: string | null;
100
+ visible: boolean;
101
+ metadata: Record<string, unknown>;
102
+ rotation: [number, number, number];
103
+ children: (`elevator_${string}` | `level_${string}` | `unit_${string}`)[];
104
+ type: "building";
105
+ name?: string | undefined;
106
+ camera?: {
107
+ position: [number, number, number];
108
+ target: [number, number, number];
109
+ mode: "perspective" | "orthographic";
110
+ fov?: number | undefined;
111
+ zoom?: number | undefined;
112
+ } | undefined;
113
+ } | {
114
+ object: "node";
115
+ position: [number, number, number];
116
+ id: `elevator_${string}`;
117
+ parentId: string | null;
118
+ visible: boolean;
119
+ metadata: Record<string, unknown>;
120
+ rotation: number;
121
+ width: number;
122
+ depth: number;
123
+ shaftWallThickness: number;
124
+ shaftStyle: "glass" | "solid";
125
+ cabHeight: number;
126
+ doorWidth: number;
127
+ doorHeight: number;
128
+ doorStyle: "center-opening" | "single-left" | "single-right";
129
+ doorPanelStyle: "glass-frame" | "solid-panel" | "segmented-panel";
130
+ fromLevelId: string | null;
131
+ toLevelId: string | null;
132
+ disabledLevelIds: string[];
133
+ serviceOnlyLevelIds: string[];
134
+ defaultLevelId: string | null;
135
+ speed: number;
136
+ doorDurationMs: number;
137
+ dwellMs: number;
138
+ type: "elevator";
139
+ name?: string | undefined;
140
+ camera?: {
141
+ position: [number, number, number];
142
+ target: [number, number, number];
143
+ mode: "perspective" | "orthographic";
144
+ fov?: number | undefined;
145
+ zoom?: number | undefined;
146
+ } | undefined;
147
+ slots?: Record<string, string> | undefined;
148
+ material?: {
149
+ id?: string | undefined;
150
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
151
+ properties?: {
152
+ color: string;
153
+ roughness: number;
154
+ metalness: number;
155
+ opacity: number;
156
+ transparent: boolean;
157
+ side: "front" | "back" | "double";
158
+ } | undefined;
159
+ texture?: {
160
+ url: string;
161
+ repeat?: [number, number] | undefined;
162
+ scale?: number | undefined;
163
+ } | undefined;
164
+ } | undefined;
165
+ materialPreset?: string | undefined;
166
+ shaftWidth?: number | undefined;
167
+ shaftDepth?: number | undefined;
168
+ servedLevelIds?: string[] | undefined;
169
+ } | {
170
+ object: "node";
171
+ id: `unit_${string}`;
172
+ name: string;
173
+ parentId: string | null;
174
+ visible: boolean;
175
+ metadata: Record<string, unknown>;
176
+ color: string;
177
+ kind: "apartment" | "hotel-room" | "commercial" | "common";
178
+ members: `zone_${string}`[];
179
+ type: "unit";
180
+ camera?: {
181
+ position: [number, number, number];
182
+ target: [number, number, number];
183
+ mode: "perspective" | "orthographic";
184
+ fov?: number | undefined;
185
+ zoom?: number | undefined;
186
+ } | undefined;
187
+ } | {
188
+ object: "node";
189
+ id: `level_${string}`;
190
+ parentId: string | null;
191
+ visible: boolean;
192
+ metadata: Record<string, unknown>;
193
+ children: (`block_${string}` | `ceiling_${string}` | `item_${string}` | `procedural-item_${string}` | `column_${string}` | `construction-dimension_${string}` | `wall_${string}` | `roof_${string}` | `slab_${string}` | `fence_${string}` | `structural-grid_${string}` | `imesh_${string}` | `zone_${string}` | `stair_${string}` | `scan_${string}` | `guide_${string}` | `measurement_${string}` | `spawn_${string}` | `shelf_${string}` | `duct-segment_${string}` | `duct-fitting_${string}` | `duct-terminal_${string}` | `hvac-equipment_${string}` | `lineset_${string}` | `liquid-line_${string}` | `pipe-segment_${string}` | `pipe-fitting_${string}` | `pipe-trap_${string}`)[];
194
+ level: number;
195
+ baseElevation: number;
196
+ type: "level";
197
+ name?: string | undefined;
198
+ camera?: {
199
+ position: [number, number, number];
200
+ target: [number, number, number];
201
+ mode: "perspective" | "orthographic";
202
+ fov?: number | undefined;
203
+ zoom?: number | undefined;
204
+ } | undefined;
205
+ height?: number | undefined;
206
+ } | {
207
+ object: "node";
208
+ position: [number, number, number];
209
+ id: `leanto_${string}`;
210
+ parentId: string | null;
211
+ visible: boolean;
212
+ metadata: Record<string, unknown>;
213
+ rotation: [number, number, number];
214
+ children: (`column_${string}` | `roof_${string}`)[];
215
+ pitch: number;
216
+ shingleThickness: number;
217
+ canopyForm: "gable" | "mono" | "butterfly";
218
+ hostKind: "wall" | "slab-edge" | "freestanding" | "conical-roof";
219
+ hostHeightOffset: number;
220
+ span: number;
221
+ autoSpan: boolean;
222
+ projection: number;
223
+ highEdgeHeight: number;
224
+ lowEdgeHeight: number;
225
+ resizeLock: "preserve-high-edge" | "preserve-low-edge" | "preserve-pitch";
226
+ leftEndCondition: "open" | "wall-abutment" | "joined";
227
+ rightEndCondition: "open" | "wall-abutment" | "joined";
228
+ autoMiterCorners: boolean;
229
+ sideFlashing: boolean;
230
+ flashingProjection: number;
231
+ flashingHeight: number;
232
+ highSideMode: "wall-ledger" | "independent-high-beam";
233
+ ledgerVerticalOffset: number;
234
+ lowBeamInset: number;
235
+ gutterEnabled: boolean;
236
+ gutterProfile: "box" | "k-style" | "half-round";
237
+ gutterSize: number;
238
+ downspoutEnabled: boolean;
239
+ downspoutPosition: number;
240
+ connectionMode: "manual" | "auto";
241
+ connectionOffset: number;
242
+ connectionInset: number;
243
+ matchHostRoofMaterial: boolean;
244
+ matchHostRoofStructure: boolean;
245
+ roofThickness: number;
246
+ highOverhang: number;
247
+ lowOverhang: number;
248
+ leftOverhang: number;
249
+ rightOverhang: number;
250
+ coveringType: "generic" | "shingle" | "metal-panel";
251
+ beamWidth: number;
252
+ beamHeight: number;
253
+ ledgerDepth: number;
254
+ ledgerHeight: number;
255
+ rafterWidth: number;
256
+ rafterHeight: number;
257
+ rafterSpacing: number;
258
+ rafterEndInset: number;
259
+ framingStrategy: "hidden" | "rafters" | "purlins" | "covering-specific";
260
+ purlinWidth: number;
261
+ purlinHeight: number;
262
+ purlinSpacing: number;
263
+ postWidth: number;
264
+ postDepth: number;
265
+ postCount: number;
266
+ postLayoutMode: "count" | "target-spacing";
267
+ postSpacing: number;
268
+ postInset: number;
269
+ omittedPostSlots: {
270
+ side: "low" | "high";
271
+ index: number;
272
+ layoutCount: number;
273
+ }[];
274
+ postBracing: "none" | "knee";
275
+ footingStyle: "none" | "base-plate" | "concrete-pad";
276
+ type: "lean-to-extension";
277
+ name?: string | undefined;
278
+ camera?: {
279
+ position: [number, number, number];
280
+ target: [number, number, number];
281
+ mode: "perspective" | "orthographic";
282
+ fov?: number | undefined;
283
+ zoom?: number | undefined;
284
+ } | undefined;
285
+ slots?: Record<string, string> | undefined;
286
+ hostSlabId?: `slab_${string}` | undefined;
287
+ hostSlabEdgeIndex?: number | undefined;
288
+ hostSlabEdgeT?: number | undefined;
289
+ spanArcCenterZ?: number | undefined;
290
+ spanArcRadius?: number | undefined;
291
+ hostRoofId?: `roof_${string}` | undefined;
292
+ hostRoofSegmentId?: string | undefined;
293
+ hostRoofEdge?: "+X" | "-X" | "+Z" | "-Z" | undefined;
294
+ hostRoofEdgeRange?: [number, number] | undefined;
295
+ } | {
296
+ object: "node";
297
+ position: [number, number, number];
298
+ id: `column_${string}`;
299
+ parentId: string | null;
300
+ visible: boolean;
301
+ metadata: Record<string, unknown>;
302
+ rotation: number;
303
+ children: string[];
304
+ width: number;
305
+ depth: number;
306
+ height: number;
307
+ baseHeight: number;
308
+ style: "plain" | "faceted" | "fluted" | "lathe-turned" | "dravidian-carved" | "cluster";
309
+ crossSection: "round" | "square" | "rectangular" | "octagonal" | "sixteen-sided";
310
+ radius: number;
311
+ edgeSoftness: number;
312
+ capitalHeight: number;
313
+ shaftProfile: "straight" | "tapered" | "bulged" | "baluster" | "hourglass";
314
+ shaftTaper: number;
315
+ shaftBulge: number;
316
+ shaftStartScale: number;
317
+ shaftEndScale: number;
318
+ shaftSegmentCount: number;
319
+ shaftTwistStep: number;
320
+ shaftCornerRadius: number;
321
+ shaftDetail: "fluted" | "lathe-turned" | "none" | "spiral" | "panelled";
322
+ baseStyle: "none" | "simple-square" | "round-rings" | "square-plinth" | "stepped-square" | "lotus" | "ribbed-lotus" | "panelled-pedestal";
323
+ baseWidthScale: number;
324
+ baseDepthScale: number;
325
+ baseTierCount: number;
326
+ baseStepSpread: number;
327
+ basePlinthHeightRatio: number;
328
+ baseRoundBandScale: number;
329
+ baseNeckScale: number;
330
+ baseRoundBandCount: number;
331
+ baseRibCount: number;
332
+ baseCarvingLevel: number;
333
+ basePanelInset: number;
334
+ capitalStyle: "none" | "simple" | "simple-slab" | "rounded" | "stepped" | "doric" | "volute" | "ionic-volute" | "leaf-carved" | "corinthian-leaf" | "south-indian-bracket" | "wood-bracket";
335
+ capitalWidthScale: number;
336
+ capitalDepthScale: number;
337
+ capitalTierCount: number;
338
+ capitalStepSpread: number;
339
+ capitalBandCount: number;
340
+ voluteSize: number;
341
+ voluteCount: number;
342
+ leafCount: number;
343
+ leafRows: number;
344
+ bracketDepth: number;
345
+ bracketTierCount: number;
346
+ pendantCount: number;
347
+ capitalCarvingLevel: number;
348
+ ringCount: number;
349
+ ringPlacement: "top" | "ends" | "even" | "bottom";
350
+ ringThickness: number;
351
+ ringSpread: number;
352
+ fluteCount: number;
353
+ fluteDepth: number;
354
+ fluteWidth: number;
355
+ spiralTwist: number;
356
+ spiralRibCount: number;
357
+ panelCount: number;
358
+ panelInsetDepth: number;
359
+ panelShape: "rectangle" | "arched" | "diamond";
360
+ latheRingCount: number;
361
+ latheRingSpacing: "top" | "ends" | "even" | "bottom";
362
+ carvingLevel: number;
363
+ carvingPlacement: "base" | "shaft" | "capital" | "all";
364
+ lowerBandEnabled: boolean;
365
+ lowerBandHeight: number;
366
+ lowerBandCarvingLevel: number;
367
+ dentilCount: number;
368
+ beadCount: number;
369
+ supportStyle: "vertical" | "a-frame" | "y-frame" | "v-frame" | "x-brace" | "k-brace" | "single-strut" | "tripod" | "trestle" | "portal-frame" | "box-frame";
370
+ braceWidth: number;
371
+ braceDepth: number;
372
+ braceBottomSpread: number;
373
+ braceTopSpread: number;
374
+ bracePlateEnabled: boolean;
375
+ type: "column";
376
+ name?: string | undefined;
377
+ camera?: {
378
+ position: [number, number, number];
379
+ target: [number, number, number];
380
+ mode: "perspective" | "orthographic";
381
+ fov?: number | undefined;
382
+ zoom?: number | undefined;
383
+ } | undefined;
384
+ supportSlabId?: string | undefined;
385
+ slots?: Record<string, string> | undefined;
386
+ material?: {
387
+ id?: string | undefined;
388
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
389
+ properties?: {
390
+ color: string;
391
+ roughness: number;
392
+ metalness: number;
393
+ opacity: number;
394
+ transparent: boolean;
395
+ side: "front" | "back" | "double";
396
+ } | undefined;
397
+ texture?: {
398
+ url: string;
399
+ repeat?: [number, number] | undefined;
400
+ scale?: number | undefined;
401
+ } | undefined;
402
+ } | undefined;
403
+ materialPreset?: string | undefined;
404
+ } | {
405
+ object: "node";
406
+ mode: "radius" | "linear" | "diameter" | "center-mark" | "chord" | "arc-length" | "angular" | "coordinate";
407
+ id: `construction-dimension_${string}`;
408
+ parentId: string | null;
409
+ visible: boolean;
410
+ metadata: Record<string, unknown>;
411
+ anchors: ([number, number, number] | {
412
+ kind: "feature";
413
+ reference: {
414
+ nodeId: string;
415
+ featureId: string;
416
+ parameters?: Record<string, string | number | boolean> | undefined;
417
+ };
418
+ fallback: [number, number, number];
419
+ })[];
420
+ baseline: {
421
+ origin: [number, number];
422
+ direction: [number, number];
423
+ };
424
+ chainMode: "point-to-point" | "continuous";
425
+ featureCount: number;
426
+ showCenterMark: boolean;
427
+ prefix: string;
428
+ suffix: string;
429
+ textOverride: string | null;
430
+ datumPolicy: "centerline" | "wall-face" | "structural-face" | "finish-face";
431
+ terminator: "architectural-tick" | "filled-arrow" | "open-arrow" | "dot";
432
+ textPosition: "above" | "centered";
433
+ imperialPrecision: "1" | "1/2" | "1/4" | "1/8" | "1/16";
434
+ metricNotation: "meters" | "millimeters";
435
+ extensionStartGap: number;
436
+ extensionOvershoot: number;
437
+ drawingType: "floor-plan" | "foundation-plan" | "reflected-ceiling-plan" | "roof-plan" | "site-plan";
438
+ drawingOverrides: {
439
+ drawingType: "floor-plan" | "foundation-plan" | "reflected-ceiling-plan" | "roof-plan" | "site-plan";
440
+ presentation: "shown" | "omit" | "controlled";
441
+ suppressedSegmentIndexes: number[];
442
+ }[];
443
+ controllingDimensionId: `construction-dimension_${string}` | null;
444
+ type: "construction-dimension";
445
+ name?: string | undefined;
446
+ camera?: {
447
+ position: [number, number, number];
448
+ target: [number, number, number];
449
+ mode: "perspective" | "orthographic";
450
+ fov?: number | undefined;
451
+ zoom?: number | undefined;
452
+ } | undefined;
453
+ } | {
454
+ object: "node";
455
+ position: [number, number, number];
456
+ id: `block_${string}`;
457
+ parentId: string | null;
458
+ visible: boolean;
459
+ metadata: Record<string, unknown>;
460
+ rotation: number;
461
+ children: string[];
462
+ topology: {
463
+ vertices: {
464
+ id: string;
465
+ position: [number, number, number];
466
+ }[];
467
+ edges: {
468
+ id: string;
469
+ vertexIds: [string, string];
470
+ }[];
471
+ faces: {
472
+ id: string;
473
+ vertexIds: string[];
474
+ materialSlot: string;
475
+ }[];
476
+ };
477
+ slots: Record<string, string>;
478
+ slotNames: Record<string, string>;
479
+ type: "block";
480
+ name?: string | undefined;
481
+ camera?: {
482
+ position: [number, number, number];
483
+ target: [number, number, number];
484
+ mode: "perspective" | "orthographic";
485
+ fov?: number | undefined;
486
+ zoom?: number | undefined;
487
+ } | undefined;
488
+ supportSlabId?: string | undefined;
489
+ } | {
490
+ object: "node";
491
+ id: `structural-grid_${string}`;
492
+ parentId: string | null;
493
+ visible: boolean;
494
+ metadata: Record<string, unknown>;
495
+ label: string;
496
+ start: [number, number];
497
+ end: [number, number];
498
+ showStartBubble: boolean;
499
+ showEndBubble: boolean;
500
+ type: "structural-grid";
501
+ name?: string | undefined;
502
+ camera?: {
503
+ position: [number, number, number];
504
+ target: [number, number, number];
505
+ mode: "perspective" | "orthographic";
506
+ fov?: number | undefined;
507
+ zoom?: number | undefined;
508
+ } | undefined;
509
+ } | {
510
+ object: "node";
511
+ id: `wall_${string}`;
512
+ parentId: string | null;
513
+ visible: boolean;
514
+ metadata: Record<string, unknown>;
515
+ children: (`item_${string}` | `procedural-item_${string}` | `door_${string}` | `window_${string}` | `leanto_${string}`)[];
516
+ start: [number, number];
517
+ end: [number, number];
518
+ frontSide: "unknown" | "interior" | "exterior";
519
+ backSide: "unknown" | "interior" | "exterior";
520
+ type: "wall";
521
+ name?: string | undefined;
522
+ camera?: {
523
+ position: [number, number, number];
524
+ target: [number, number, number];
525
+ mode: "perspective" | "orthographic";
526
+ fov?: number | undefined;
527
+ zoom?: number | undefined;
528
+ } | undefined;
529
+ supportSlabId?: string | undefined;
530
+ slots?: Record<string, string> | undefined;
531
+ material?: {
532
+ id?: string | undefined;
533
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
534
+ properties?: {
535
+ color: string;
536
+ roughness: number;
537
+ metalness: number;
538
+ opacity: number;
539
+ transparent: boolean;
540
+ side: "front" | "back" | "double";
541
+ } | undefined;
542
+ texture?: {
543
+ url: string;
544
+ repeat?: [number, number] | undefined;
545
+ scale?: number | undefined;
546
+ } | undefined;
547
+ } | undefined;
548
+ materialPreset?: string | undefined;
549
+ height?: number | undefined;
550
+ thickness?: number | undefined;
551
+ fillToTerrain?: boolean | undefined;
552
+ interiorMaterial?: {
553
+ id?: string | undefined;
554
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
555
+ properties?: {
556
+ color: string;
557
+ roughness: number;
558
+ metalness: number;
559
+ opacity: number;
560
+ transparent: boolean;
561
+ side: "front" | "back" | "double";
562
+ } | undefined;
563
+ texture?: {
564
+ url: string;
565
+ repeat?: [number, number] | undefined;
566
+ scale?: number | undefined;
567
+ } | undefined;
568
+ } | undefined;
569
+ interiorMaterialPreset?: string | undefined;
570
+ exteriorMaterial?: {
571
+ id?: string | undefined;
572
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
573
+ properties?: {
574
+ color: string;
575
+ roughness: number;
576
+ metalness: number;
577
+ opacity: number;
578
+ transparent: boolean;
579
+ side: "front" | "back" | "double";
580
+ } | undefined;
581
+ texture?: {
582
+ url: string;
583
+ repeat?: [number, number] | undefined;
584
+ scale?: number | undefined;
585
+ } | undefined;
586
+ } | undefined;
587
+ exteriorMaterialPreset?: string | undefined;
588
+ curveOffset?: number | undefined;
589
+ supportOffset?: number | undefined;
590
+ faceBands?: {
591
+ enabled: boolean;
592
+ count: number;
593
+ lowerHeight: number;
594
+ middleHeight: number;
595
+ upperHeight: number;
596
+ } | undefined;
597
+ skirting?: {
598
+ enabled: boolean;
599
+ sides: "interior" | "exterior" | "both";
600
+ height: number;
601
+ proud: number;
602
+ profile: "flat" | "bevel" | "triangle" | "cove" | "bullnose" | "base-modern" | "base-colonial" | "base-shoe" | "base-ogee" | "crown-cove" | "crown-ogee" | "crown-craftsman" | "crown-layered" | "rail-rounded" | "rail-ogee" | "rail-picture" | "rail-stepped";
603
+ offsetY?: number | undefined;
604
+ } | undefined;
605
+ crown?: {
606
+ enabled: boolean;
607
+ sides: "interior" | "exterior" | "both";
608
+ height: number;
609
+ proud: number;
610
+ profile: "flat" | "bevel" | "triangle" | "cove" | "bullnose" | "base-modern" | "base-colonial" | "base-shoe" | "base-ogee" | "crown-cove" | "crown-ogee" | "crown-craftsman" | "crown-layered" | "rail-rounded" | "rail-ogee" | "rail-picture" | "rail-stepped";
611
+ offsetY?: number | undefined;
612
+ } | undefined;
613
+ chairRail?: {
614
+ enabled: boolean;
615
+ sides: "interior" | "exterior" | "both";
616
+ height: number;
617
+ proud: number;
618
+ profile: "flat" | "bevel" | "triangle" | "cove" | "bullnose" | "base-modern" | "base-colonial" | "base-shoe" | "base-ogee" | "crown-cove" | "crown-ogee" | "crown-craftsman" | "crown-layered" | "rail-rounded" | "rail-ogee" | "rail-picture" | "rail-stepped";
619
+ offsetY?: number | undefined;
620
+ } | undefined;
621
+ } | {
622
+ object: "node";
623
+ id: `fence_${string}`;
624
+ parentId: string | null;
625
+ visible: boolean;
626
+ metadata: Record<string, unknown>;
627
+ color: string;
628
+ height: number;
629
+ baseHeight: number;
630
+ style: "slat" | "rail" | "privacy" | "horizontal";
631
+ baseStyle: "floating" | "grounded";
632
+ thickness: number;
633
+ postSpacing: number;
634
+ start: [number, number];
635
+ end: [number, number];
636
+ postSize: number;
637
+ topRailHeight: number;
638
+ groundClearance: number;
639
+ edgeInset: number;
640
+ slatGap: number;
641
+ postCap: "flat" | "none" | "pyramid";
642
+ showInfill: boolean;
643
+ type: "fence";
644
+ name?: string | undefined;
645
+ camera?: {
646
+ position: [number, number, number];
647
+ target: [number, number, number];
648
+ mode: "perspective" | "orthographic";
649
+ fov?: number | undefined;
650
+ zoom?: number | undefined;
651
+ } | undefined;
652
+ path?: [number, number][] | undefined;
653
+ supportSlabId?: string | undefined;
654
+ slots?: Record<string, string> | undefined;
655
+ material?: {
656
+ id?: string | undefined;
657
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
658
+ properties?: {
659
+ color: string;
660
+ roughness: number;
661
+ metalness: number;
662
+ opacity: number;
663
+ transparent: boolean;
664
+ side: "front" | "back" | "double";
665
+ } | undefined;
666
+ texture?: {
667
+ url: string;
668
+ repeat?: [number, number] | undefined;
669
+ scale?: number | undefined;
670
+ } | undefined;
671
+ } | undefined;
672
+ materialPreset?: string | undefined;
673
+ curveOffset?: number | undefined;
674
+ supportOffset?: number | undefined;
675
+ tangents?: ([number, number] | null)[] | undefined;
676
+ } | {
677
+ object: "node";
678
+ position: [number, number, number];
679
+ id: `cabinet_${string}`;
680
+ parentId: string | null;
681
+ visible: boolean;
682
+ metadata: Record<string, unknown>;
683
+ rotation: number;
684
+ children: string[];
685
+ width: number;
686
+ depth: number;
687
+ operationState: number;
688
+ runTier: "wall" | "base" | "tall";
689
+ withWaterfall: boolean;
690
+ withFinishedEnds: boolean;
691
+ carcassHeight: number;
692
+ plinthHeight: number;
693
+ toeKickDepth: number;
694
+ boardThickness: number;
695
+ countertopThickness: number;
696
+ countertopOverhang: number;
697
+ countertopBackOverhang: number;
698
+ withFinishedBack: boolean;
699
+ frontThickness: number;
700
+ frontGap: number;
701
+ frontStyle: "slab" | "shaker" | "raised-arch";
702
+ panelReady: boolean;
703
+ handleStyle: "none" | "bar" | "cutout" | "hole" | "knob";
704
+ handlePosition: "top" | "auto" | "center";
705
+ frontOverlay: "full" | "inset";
706
+ withBottomPanel: boolean;
707
+ showPlinth: boolean;
708
+ withCountertop: boolean;
709
+ type: "cabinet";
710
+ name?: string | undefined;
711
+ camera?: {
712
+ position: [number, number, number];
713
+ target: [number, number, number];
714
+ mode: "perspective" | "orthographic";
715
+ fov?: number | undefined;
716
+ zoom?: number | undefined;
717
+ } | undefined;
718
+ supportSlabId?: string | undefined;
719
+ slots?: Record<string, string> | undefined;
720
+ material?: {
721
+ id?: string | undefined;
722
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
723
+ properties?: {
724
+ color: string;
725
+ roughness: number;
726
+ metalness: number;
727
+ opacity: number;
728
+ transparent: boolean;
729
+ side: "front" | "back" | "double";
730
+ } | undefined;
731
+ texture?: {
732
+ url: string;
733
+ repeat?: [number, number] | undefined;
734
+ scale?: number | undefined;
735
+ } | undefined;
736
+ } | undefined;
737
+ materialPreset?: string | undefined;
738
+ barLedge?: {
739
+ edge: "back" | "right" | "left";
740
+ height: number;
741
+ depth: number;
742
+ } | undefined;
743
+ stack?: ({
744
+ type: "shelf";
745
+ id: string;
746
+ shelfCount?: number | undefined;
747
+ height?: number | undefined;
748
+ } | {
749
+ type: "drawer";
750
+ id: string;
751
+ drawerCount?: number | undefined;
752
+ height?: number | undefined;
753
+ } | {
754
+ type: "door";
755
+ id: string;
756
+ doorType?: "glass" | "double" | "single-left" | "single-right" | undefined;
757
+ shelfCount?: number | undefined;
758
+ height?: number | undefined;
759
+ } | {
760
+ type: "sink";
761
+ id: string;
762
+ sinkLayout?: "double" | "single" | "double-offset" | undefined;
763
+ height?: number | undefined;
764
+ } | {
765
+ type: "oven";
766
+ id: string;
767
+ height?: number | undefined;
768
+ } | {
769
+ type: "microwave";
770
+ id: string;
771
+ height?: number | undefined;
772
+ } | {
773
+ type: "dishwasher";
774
+ id: string;
775
+ height?: number | undefined;
776
+ } | {
777
+ type: "cooktop-gas";
778
+ id: string;
779
+ cooktopLayout?: "gas-2burner" | "gas-4burner" | "gas-5burner-wok" | "gas-6burner" | undefined;
780
+ cooktopBurnersOn?: boolean | undefined;
781
+ cooktopActiveBurners?: number[] | undefined;
782
+ cooktopKnobProgress?: number[] | undefined;
783
+ cooktopShowGrate?: boolean | undefined;
784
+ height?: number | undefined;
785
+ } | {
786
+ type: "cooktop-induction";
787
+ id: string;
788
+ cooktopLayout?: "induction-2zone" | "induction-4zone" | undefined;
789
+ cooktopBurnersOn?: boolean | undefined;
790
+ cooktopActiveBurners?: number[] | undefined;
791
+ cooktopKnobProgress?: number[] | undefined;
792
+ cooktopShowGrate?: boolean | undefined;
793
+ height?: number | undefined;
794
+ } | {
795
+ type: "pull-out-pantry";
796
+ id: string;
797
+ shelfCount?: number | undefined;
798
+ pantryRackStyle?: "glass" | "wire" | "tray" | undefined;
799
+ height?: number | undefined;
800
+ } | {
801
+ type: "fridge-single";
802
+ id: string;
803
+ height?: number | undefined;
804
+ } | {
805
+ type: "fridge-double";
806
+ id: string;
807
+ height?: number | undefined;
808
+ } | {
809
+ type: "fridge-top-freezer";
810
+ id: string;
811
+ height?: number | undefined;
812
+ } | {
813
+ type: "fridge-bottom-freezer";
814
+ id: string;
815
+ height?: number | undefined;
816
+ } | {
817
+ type: "hood-pyramid";
818
+ id: string;
819
+ height?: number | undefined;
820
+ } | {
821
+ type: "hood-curved-glass";
822
+ id: string;
823
+ height?: number | undefined;
824
+ })[] | undefined;
825
+ } | {
826
+ object: "node";
827
+ position: [number, number, number];
828
+ id: `cabinet-module_${string}`;
829
+ parentId: string | null;
830
+ visible: boolean;
831
+ metadata: Record<string, unknown>;
832
+ rotation: number;
833
+ children: string[];
834
+ width: number;
835
+ depth: number;
836
+ operationState: number;
837
+ carcassHeight: number;
838
+ plinthHeight: number;
839
+ toeKickDepth: number;
840
+ boardThickness: number;
841
+ countertopThickness: number;
842
+ countertopOverhang: number;
843
+ countertopBackOverhang: number;
844
+ withFinishedBack: boolean;
845
+ frontThickness: number;
846
+ frontGap: number;
847
+ frontStyle: "slab" | "shaker" | "raised-arch";
848
+ panelReady: boolean;
849
+ handleStyle: "none" | "bar" | "cutout" | "hole" | "knob";
850
+ handlePosition: "top" | "auto" | "center";
851
+ frontOverlay: "full" | "inset";
852
+ withBottomPanel: boolean;
853
+ showPlinth: boolean;
854
+ withCountertop: boolean;
855
+ cabinetType: "base" | "tall";
856
+ moduleKind: "standard" | "corner-filler";
857
+ topFinish: "trim" | "none" | "top-cabinet";
858
+ topFinishHeight: number;
859
+ topFinishDepth: number;
860
+ type: "cabinet-module";
861
+ name?: string | undefined;
862
+ camera?: {
863
+ position: [number, number, number];
864
+ target: [number, number, number];
865
+ mode: "perspective" | "orthographic";
866
+ fov?: number | undefined;
867
+ zoom?: number | undefined;
868
+ } | undefined;
869
+ supportSlabId?: string | undefined;
870
+ slots?: Record<string, string> | undefined;
871
+ material?: {
872
+ id?: string | undefined;
873
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
874
+ properties?: {
875
+ color: string;
876
+ roughness: number;
877
+ metalness: number;
878
+ opacity: number;
879
+ transparent: boolean;
880
+ side: "front" | "back" | "double";
881
+ } | undefined;
882
+ texture?: {
883
+ url: string;
884
+ repeat?: [number, number] | undefined;
885
+ scale?: number | undefined;
886
+ } | undefined;
887
+ } | undefined;
888
+ materialPreset?: string | undefined;
889
+ stack?: ({
890
+ type: "shelf";
891
+ id: string;
892
+ shelfCount?: number | undefined;
893
+ height?: number | undefined;
894
+ } | {
895
+ type: "drawer";
896
+ id: string;
897
+ drawerCount?: number | undefined;
898
+ height?: number | undefined;
899
+ } | {
900
+ type: "door";
901
+ id: string;
902
+ doorType?: "glass" | "double" | "single-left" | "single-right" | undefined;
903
+ shelfCount?: number | undefined;
904
+ height?: number | undefined;
905
+ } | {
906
+ type: "sink";
907
+ id: string;
908
+ sinkLayout?: "double" | "single" | "double-offset" | undefined;
909
+ height?: number | undefined;
910
+ } | {
911
+ type: "oven";
912
+ id: string;
913
+ height?: number | undefined;
914
+ } | {
915
+ type: "microwave";
916
+ id: string;
917
+ height?: number | undefined;
918
+ } | {
919
+ type: "dishwasher";
920
+ id: string;
921
+ height?: number | undefined;
922
+ } | {
923
+ type: "cooktop-gas";
924
+ id: string;
925
+ cooktopLayout?: "gas-2burner" | "gas-4burner" | "gas-5burner-wok" | "gas-6burner" | undefined;
926
+ cooktopBurnersOn?: boolean | undefined;
927
+ cooktopActiveBurners?: number[] | undefined;
928
+ cooktopKnobProgress?: number[] | undefined;
929
+ cooktopShowGrate?: boolean | undefined;
930
+ height?: number | undefined;
931
+ } | {
932
+ type: "cooktop-induction";
933
+ id: string;
934
+ cooktopLayout?: "induction-2zone" | "induction-4zone" | undefined;
935
+ cooktopBurnersOn?: boolean | undefined;
936
+ cooktopActiveBurners?: number[] | undefined;
937
+ cooktopKnobProgress?: number[] | undefined;
938
+ cooktopShowGrate?: boolean | undefined;
939
+ height?: number | undefined;
940
+ } | {
941
+ type: "pull-out-pantry";
942
+ id: string;
943
+ shelfCount?: number | undefined;
944
+ pantryRackStyle?: "glass" | "wire" | "tray" | undefined;
945
+ height?: number | undefined;
946
+ } | {
947
+ type: "fridge-single";
948
+ id: string;
949
+ height?: number | undefined;
950
+ } | {
951
+ type: "fridge-double";
952
+ id: string;
953
+ height?: number | undefined;
954
+ } | {
955
+ type: "fridge-top-freezer";
956
+ id: string;
957
+ height?: number | undefined;
958
+ } | {
959
+ type: "fridge-bottom-freezer";
960
+ id: string;
961
+ height?: number | undefined;
962
+ } | {
963
+ type: "hood-pyramid";
964
+ id: string;
965
+ height?: number | undefined;
966
+ } | {
967
+ type: "hood-curved-glass";
968
+ id: string;
969
+ height?: number | undefined;
970
+ })[] | undefined;
971
+ openSide?: "right" | "left" | undefined;
972
+ cornerShelf?: boolean | undefined;
973
+ } | {
974
+ object: "node";
975
+ position: [number, number, number];
976
+ id: `item_${string}`;
977
+ parentId: string | null;
978
+ visible: boolean;
979
+ metadata: Record<string, unknown>;
980
+ scale: [number, number, number];
981
+ rotation: [number, number, number];
982
+ children: string[];
983
+ asset: {
984
+ id: string;
985
+ category: string;
986
+ name: string;
987
+ thumbnail: string;
988
+ source: "library" | "community" | "mine";
989
+ src: string;
990
+ dimensions: [number, number, number];
991
+ offset: [number, number, number];
992
+ rotation: [number, number, number];
993
+ scale: [number, number, number];
994
+ floorPlanUrl?: string | undefined;
995
+ isDraft?: boolean | undefined;
996
+ attachTo?: "wall" | "ceiling" | "wall-side" | undefined;
997
+ recessed?: boolean | undefined;
998
+ tags?: string[] | undefined;
999
+ functionTags?: string[] | undefined;
1000
+ surface?: {
1001
+ height: number;
1002
+ } | undefined;
1003
+ interactive?: {
1004
+ controls: ({
1005
+ kind: "toggle";
1006
+ label?: string | undefined;
1007
+ default?: boolean | undefined;
1008
+ } | {
1009
+ kind: "slider";
1010
+ label: string;
1011
+ min: number;
1012
+ max: number;
1013
+ step: number;
1014
+ displayMode: "slider" | "stepper" | "dial";
1015
+ unit?: string | undefined;
1016
+ default?: number | undefined;
1017
+ } | {
1018
+ kind: "temperature";
1019
+ label: string;
1020
+ min: number;
1021
+ max: number;
1022
+ unit: "C" | "F";
1023
+ default?: number | undefined;
1024
+ })[];
1025
+ effects: ({
1026
+ kind: "animation";
1027
+ clips: {
1028
+ on?: string | undefined;
1029
+ off?: string | undefined;
1030
+ loop?: string | undefined;
1031
+ };
1032
+ } | {
1033
+ kind: "light";
1034
+ color: string;
1035
+ intensityRange: [number, number];
1036
+ offset: [number, number, number];
1037
+ distance?: number | undefined;
1038
+ })[];
1039
+ } | undefined;
1040
+ };
1041
+ type: "item";
1042
+ name?: string | undefined;
1043
+ camera?: {
1044
+ position: [number, number, number];
1045
+ target: [number, number, number];
1046
+ mode: "perspective" | "orthographic";
1047
+ fov?: number | undefined;
1048
+ zoom?: number | undefined;
1049
+ } | undefined;
1050
+ side?: "front" | "back" | undefined;
1051
+ supportSlabId?: string | undefined;
1052
+ slots?: Record<string, string> | undefined;
1053
+ roofSegmentId?: string | undefined;
1054
+ wallId?: string | undefined;
1055
+ wallT?: number | undefined;
1056
+ roofFace?: "front" | "back" | "right" | "left" | undefined;
1057
+ blockFaceId?: string | undefined;
1058
+ collectionIds?: `collection_${string}`[] | undefined;
1059
+ } | {
1060
+ object: "node";
1061
+ position: [number, number, number];
1062
+ id: `procedural-item_${string}`;
1063
+ parentId: string | null;
1064
+ visible: boolean;
1065
+ metadata: Record<string, unknown>;
1066
+ rotation: [number, number, number];
1067
+ children: string[];
1068
+ slots: Record<string, string>;
1069
+ parameters: Record<string, number>;
1070
+ recipe: {
1071
+ version: 1;
1072
+ name: string;
1073
+ description: string;
1074
+ parameters: {
1075
+ id: string;
1076
+ label: string;
1077
+ default: number;
1078
+ min: number;
1079
+ max: number;
1080
+ step: number;
1081
+ unit: "count" | "m" | "rad";
1082
+ part?: string | undefined;
1083
+ axis?: "x" | "y" | "z" | undefined;
1084
+ }[];
1085
+ slots: {
1086
+ id: string;
1087
+ label: string;
1088
+ color: string;
1089
+ finish?: "wood" | "glass" | "metal" | undefined;
1090
+ }[];
1091
+ parts: {
1092
+ id: string;
1093
+ label: string;
1094
+ count: import("../../procedural-items/index.js").Expr;
1095
+ shapes: {
1096
+ id: string;
1097
+ primitive: "box" | "roundedBox" | "cylinder";
1098
+ slot: string;
1099
+ size: [import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr];
1100
+ position: [import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr];
1101
+ rotation?: [import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr] | undefined;
1102
+ radius?: import("../../procedural-items/index.js").Expr | undefined;
1103
+ support?: boolean | undefined;
1104
+ }[];
1105
+ }[];
1106
+ constraints: {
1107
+ left: import("../../procedural-items/index.js").Expr;
1108
+ relation: "lte" | "gte";
1109
+ right: import("../../procedural-items/index.js").Expr;
1110
+ message: string;
1111
+ }[];
1112
+ classification?: {
1113
+ category: string;
1114
+ functionTags: string[];
1115
+ tags: string[];
1116
+ } | undefined;
1117
+ mounting?: {
1118
+ attachTo: "ceiling" | "wall-side";
1119
+ reference: string;
1120
+ } | undefined;
1121
+ surfaces?: {
1122
+ id: string;
1123
+ label: string;
1124
+ position: [import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr];
1125
+ size: [import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr];
1126
+ part?: string | undefined;
1127
+ rotation?: [import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr, import("../../procedural-items/index.js").Expr] | undefined;
1128
+ }[] | undefined;
1129
+ };
1130
+ attachments: Record<string, string>;
1131
+ type: "procedural-item";
1132
+ name?: string | undefined;
1133
+ camera?: {
1134
+ position: [number, number, number];
1135
+ target: [number, number, number];
1136
+ mode: "perspective" | "orthographic";
1137
+ fov?: number | undefined;
1138
+ zoom?: number | undefined;
1139
+ } | undefined;
1140
+ side?: "front" | "back" | undefined;
1141
+ supportSlabId?: string | undefined;
1142
+ wallId?: string | undefined;
1143
+ } | {
1144
+ object: "node";
1145
+ position: [number, number, number];
1146
+ id: `imesh_${string}`;
1147
+ parentId: string | null;
1148
+ visible: boolean;
1149
+ metadata: Record<string, unknown>;
1150
+ rotation: [number, number, number];
1151
+ primitives: {
1152
+ positions: number[];
1153
+ indices: number[];
1154
+ color: string;
1155
+ opacity: number;
1156
+ normals?: number[] | undefined;
1157
+ }[];
1158
+ type: "imported-mesh";
1159
+ name?: string | undefined;
1160
+ camera?: {
1161
+ position: [number, number, number];
1162
+ target: [number, number, number];
1163
+ mode: "perspective" | "orthographic";
1164
+ fov?: number | undefined;
1165
+ zoom?: number | undefined;
1166
+ } | undefined;
1167
+ } | {
1168
+ object: "node";
1169
+ id: `zone_${string}`;
1170
+ name: string;
1171
+ parentId: string | null;
1172
+ visible: boolean;
1173
+ metadata: Record<string, unknown>;
1174
+ color: string;
1175
+ polygon: [number, number][];
1176
+ autoFromWalls: boolean;
1177
+ boundaryWallIds: `wall_${string}`[];
1178
+ spaceRole: "generic" | "room";
1179
+ roomNumber: string;
1180
+ enclosureStatus: "auto" | "open" | "enclosed";
1181
+ floorFinish: string;
1182
+ wallFinish: string;
1183
+ ceilingFinish: string;
1184
+ ceilingHeight: number;
1185
+ occupancy: string;
1186
+ clearDimensionPolicy: "none" | "inside-faces" | "finish-faces";
1187
+ type: "zone";
1188
+ camera?: {
1189
+ position: [number, number, number];
1190
+ target: [number, number, number];
1191
+ mode: "perspective" | "orthographic";
1192
+ fov?: number | undefined;
1193
+ zoom?: number | undefined;
1194
+ } | undefined;
1195
+ } | {
1196
+ object: "node";
1197
+ id: `slab_${string}`;
1198
+ parentId: string | null;
1199
+ visible: boolean;
1200
+ metadata: Record<string, unknown>;
1201
+ recessed: boolean;
1202
+ polygon: [number, number][];
1203
+ holes: [number, number][][];
1204
+ holeMetadata: {
1205
+ source: "stair" | "elevator" | "manual";
1206
+ stairId?: string | undefined;
1207
+ elevatorId?: string | undefined;
1208
+ }[];
1209
+ autoFromWalls: boolean;
1210
+ elevation: number;
1211
+ thickness: number;
1212
+ type: "slab";
1213
+ name?: string | undefined;
1214
+ camera?: {
1215
+ position: [number, number, number];
1216
+ target: [number, number, number];
1217
+ mode: "perspective" | "orthographic";
1218
+ fov?: number | undefined;
1219
+ zoom?: number | undefined;
1220
+ } | undefined;
1221
+ slots?: Record<string, string> | undefined;
1222
+ material?: {
1223
+ id?: string | undefined;
1224
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1225
+ properties?: {
1226
+ color: string;
1227
+ roughness: number;
1228
+ metalness: number;
1229
+ opacity: number;
1230
+ transparent: boolean;
1231
+ side: "front" | "back" | "double";
1232
+ } | undefined;
1233
+ texture?: {
1234
+ url: string;
1235
+ repeat?: [number, number] | undefined;
1236
+ scale?: number | undefined;
1237
+ } | undefined;
1238
+ } | undefined;
1239
+ materialPreset?: string | undefined;
1240
+ recessedRimElevation?: number | undefined;
1241
+ fillToTerrain?: boolean | undefined;
1242
+ } | {
1243
+ object: "node";
1244
+ id: `ceiling_${string}`;
1245
+ parentId: string | null;
1246
+ visible: boolean;
1247
+ metadata: Record<string, unknown>;
1248
+ children: (`item_${string}` | `procedural-item_${string}`)[];
1249
+ polygon: [number, number][];
1250
+ holes: [number, number][][];
1251
+ holeMetadata: {
1252
+ source: "stair" | "elevator" | "manual";
1253
+ stairId?: string | undefined;
1254
+ elevatorId?: string | undefined;
1255
+ }[];
1256
+ autoFromWalls: boolean;
1257
+ type: "ceiling";
1258
+ name?: string | undefined;
1259
+ camera?: {
1260
+ position: [number, number, number];
1261
+ target: [number, number, number];
1262
+ mode: "perspective" | "orthographic";
1263
+ fov?: number | undefined;
1264
+ zoom?: number | undefined;
1265
+ } | undefined;
1266
+ slots?: Record<string, string> | undefined;
1267
+ material?: {
1268
+ id?: string | undefined;
1269
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1270
+ properties?: {
1271
+ color: string;
1272
+ roughness: number;
1273
+ metalness: number;
1274
+ opacity: number;
1275
+ transparent: boolean;
1276
+ side: "front" | "back" | "double";
1277
+ } | undefined;
1278
+ texture?: {
1279
+ url: string;
1280
+ repeat?: [number, number] | undefined;
1281
+ scale?: number | undefined;
1282
+ } | undefined;
1283
+ } | undefined;
1284
+ materialPreset?: string | undefined;
1285
+ height?: number | undefined;
1286
+ } | {
1287
+ object: "node";
1288
+ position: [number, number, number];
1289
+ id: `roof_${string}`;
1290
+ parentId: string | null;
1291
+ visible: boolean;
1292
+ metadata: Record<string, unknown>;
1293
+ rotation: number;
1294
+ children: `rseg_${string}`[];
1295
+ support: {
1296
+ kind: "level";
1297
+ } | {
1298
+ kind: "walls";
1299
+ } | {
1300
+ kind: "roof";
1301
+ roofSegmentId: `rseg_${string}`;
1302
+ localPosition: [number, number];
1303
+ curbHeight: number;
1304
+ };
1305
+ type: "roof";
1306
+ name?: string | undefined;
1307
+ camera?: {
1308
+ position: [number, number, number];
1309
+ target: [number, number, number];
1310
+ mode: "perspective" | "orthographic";
1311
+ fov?: number | undefined;
1312
+ zoom?: number | undefined;
1313
+ } | undefined;
1314
+ material?: {
1315
+ id?: string | undefined;
1316
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1317
+ properties?: {
1318
+ color: string;
1319
+ roughness: number;
1320
+ metalness: number;
1321
+ opacity: number;
1322
+ transparent: boolean;
1323
+ side: "front" | "back" | "double";
1324
+ } | undefined;
1325
+ texture?: {
1326
+ url: string;
1327
+ repeat?: [number, number] | undefined;
1328
+ scale?: number | undefined;
1329
+ } | undefined;
1330
+ } | undefined;
1331
+ materialPreset?: string | undefined;
1332
+ topMaterial?: {
1333
+ id?: string | undefined;
1334
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1335
+ properties?: {
1336
+ color: string;
1337
+ roughness: number;
1338
+ metalness: number;
1339
+ opacity: number;
1340
+ transparent: boolean;
1341
+ side: "front" | "back" | "double";
1342
+ } | undefined;
1343
+ texture?: {
1344
+ url: string;
1345
+ repeat?: [number, number] | undefined;
1346
+ scale?: number | undefined;
1347
+ } | undefined;
1348
+ } | undefined;
1349
+ topMaterialPreset?: string | undefined;
1350
+ edgeMaterial?: {
1351
+ id?: string | undefined;
1352
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1353
+ properties?: {
1354
+ color: string;
1355
+ roughness: number;
1356
+ metalness: number;
1357
+ opacity: number;
1358
+ transparent: boolean;
1359
+ side: "front" | "back" | "double";
1360
+ } | undefined;
1361
+ texture?: {
1362
+ url: string;
1363
+ repeat?: [number, number] | undefined;
1364
+ scale?: number | undefined;
1365
+ } | undefined;
1366
+ } | undefined;
1367
+ edgeMaterialPreset?: string | undefined;
1368
+ wallMaterial?: {
1369
+ id?: string | undefined;
1370
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1371
+ properties?: {
1372
+ color: string;
1373
+ roughness: number;
1374
+ metalness: number;
1375
+ opacity: number;
1376
+ transparent: boolean;
1377
+ side: "front" | "back" | "double";
1378
+ } | undefined;
1379
+ texture?: {
1380
+ url: string;
1381
+ repeat?: [number, number] | undefined;
1382
+ scale?: number | undefined;
1383
+ } | undefined;
1384
+ } | undefined;
1385
+ wallMaterialPreset?: string | undefined;
1386
+ } | {
1387
+ object: "node";
1388
+ position: [number, number, number];
1389
+ id: `rseg_${string}`;
1390
+ parentId: string | null;
1391
+ visible: boolean;
1392
+ metadata: Record<string, unknown>;
1393
+ rotation: number;
1394
+ children: string[];
1395
+ trim: {
1396
+ left: number;
1397
+ right: number;
1398
+ front: number;
1399
+ back: number;
1400
+ frontLeft: number;
1401
+ frontRight: number;
1402
+ backLeft: number;
1403
+ backRight: number;
1404
+ frontLeftX: number;
1405
+ frontLeftZ: number;
1406
+ frontRightX: number;
1407
+ frontRightZ: number;
1408
+ backLeftX: number;
1409
+ backLeftZ: number;
1410
+ backRightX: number;
1411
+ backRightZ: number;
1412
+ };
1413
+ width: number;
1414
+ depth: number;
1415
+ roofType: "flat" | "hip" | "gable" | "shed" | "gambrel" | "dutch" | "mansard" | "conical";
1416
+ wallHeight: number;
1417
+ pitch: number;
1418
+ wallThickness: number;
1419
+ deckThickness: number;
1420
+ overhang: number;
1421
+ shingleThickness: number;
1422
+ managedByParent: boolean;
1423
+ wallShell: "omit" | "auto" | "include";
1424
+ shedInsetEndPanels: boolean;
1425
+ gambrelLowerWidthRatio: number;
1426
+ gambrelLowerHeightRatio: number;
1427
+ mansardSteepWidthRatio: number;
1428
+ mansardSteepHeightRatio: number;
1429
+ dutchHipWidthRatio: number;
1430
+ dutchHipHeightRatio: number;
1431
+ dutchWaistLengthRatio: number;
1432
+ dutchGabletRake: number;
1433
+ dutchTopRakeThickness: number;
1434
+ type: "roof-segment";
1435
+ name?: string | undefined;
1436
+ camera?: {
1437
+ position: [number, number, number];
1438
+ target: [number, number, number];
1439
+ mode: "perspective" | "orthographic";
1440
+ fov?: number | undefined;
1441
+ zoom?: number | undefined;
1442
+ } | undefined;
1443
+ material?: {
1444
+ id?: string | undefined;
1445
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1446
+ properties?: {
1447
+ color: string;
1448
+ roughness: number;
1449
+ metalness: number;
1450
+ opacity: number;
1451
+ transparent: boolean;
1452
+ side: "front" | "back" | "double";
1453
+ } | undefined;
1454
+ texture?: {
1455
+ url: string;
1456
+ repeat?: [number, number] | undefined;
1457
+ scale?: number | undefined;
1458
+ } | undefined;
1459
+ } | undefined;
1460
+ materialPreset?: string | undefined;
1461
+ topMaterial?: {
1462
+ id?: string | undefined;
1463
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1464
+ properties?: {
1465
+ color: string;
1466
+ roughness: number;
1467
+ metalness: number;
1468
+ opacity: number;
1469
+ transparent: boolean;
1470
+ side: "front" | "back" | "double";
1471
+ } | undefined;
1472
+ texture?: {
1473
+ url: string;
1474
+ repeat?: [number, number] | undefined;
1475
+ scale?: number | undefined;
1476
+ } | undefined;
1477
+ } | undefined;
1478
+ topMaterialPreset?: string | undefined;
1479
+ edgeMaterial?: {
1480
+ id?: string | undefined;
1481
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1482
+ properties?: {
1483
+ color: string;
1484
+ roughness: number;
1485
+ metalness: number;
1486
+ opacity: number;
1487
+ transparent: boolean;
1488
+ side: "front" | "back" | "double";
1489
+ } | undefined;
1490
+ texture?: {
1491
+ url: string;
1492
+ repeat?: [number, number] | undefined;
1493
+ scale?: number | undefined;
1494
+ } | undefined;
1495
+ } | undefined;
1496
+ edgeMaterialPreset?: string | undefined;
1497
+ wallMaterial?: {
1498
+ id?: string | undefined;
1499
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1500
+ properties?: {
1501
+ color: string;
1502
+ roughness: number;
1503
+ metalness: number;
1504
+ opacity: number;
1505
+ transparent: boolean;
1506
+ side: "front" | "back" | "double";
1507
+ } | undefined;
1508
+ texture?: {
1509
+ url: string;
1510
+ repeat?: [number, number] | undefined;
1511
+ scale?: number | undefined;
1512
+ } | undefined;
1513
+ } | undefined;
1514
+ wallMaterialPreset?: string | undefined;
1515
+ conicalStartAngle?: number | undefined;
1516
+ conicalSweepAngle?: number | undefined;
1517
+ conicalFullCircle?: boolean | undefined;
1518
+ arc?: {
1519
+ centerX: number;
1520
+ centerZ: number;
1521
+ radius: number;
1522
+ } | undefined;
1523
+ shedSideInfillSpan?: number | undefined;
1524
+ shedSideInfillMinX?: number | undefined;
1525
+ shedSideInfillMaxX?: number | undefined;
1526
+ shedFootprintPieces?: [number, number][][] | undefined;
1527
+ shedOpenEndSides?: ("right" | "left")[] | undefined;
1528
+ shedJointFrame?: {
1529
+ position: [number, number, number];
1530
+ rotation: number;
1531
+ } | undefined;
1532
+ shedJointOwnerId?: string | undefined;
1533
+ shedJointNeighborIds?: string[] | undefined;
1534
+ shedJointScopeId?: string | undefined;
1535
+ } | {
1536
+ object: "node";
1537
+ position: [number, number, number];
1538
+ id: `shelf_${string}`;
1539
+ parentId: string | null;
1540
+ visible: boolean;
1541
+ metadata: Record<string, unknown>;
1542
+ rotation: [number, number, number];
1543
+ children: string[];
1544
+ width: number;
1545
+ depth: number;
1546
+ height: number;
1547
+ style: "wall-shelf" | "bookshelf" | "open-rack" | "cubby";
1548
+ rows: number;
1549
+ thickness: number;
1550
+ columns: number;
1551
+ withBack: boolean;
1552
+ withSides: boolean;
1553
+ withBottom: boolean;
1554
+ bracketStyle: "hidden" | "minimal" | "industrial";
1555
+ type: "shelf";
1556
+ name?: string | undefined;
1557
+ camera?: {
1558
+ position: [number, number, number];
1559
+ target: [number, number, number];
1560
+ mode: "perspective" | "orthographic";
1561
+ fov?: number | undefined;
1562
+ zoom?: number | undefined;
1563
+ } | undefined;
1564
+ supportSlabId?: string | undefined;
1565
+ slots?: Record<string, string> | undefined;
1566
+ material?: {
1567
+ id?: string | undefined;
1568
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1569
+ properties?: {
1570
+ color: string;
1571
+ roughness: number;
1572
+ metalness: number;
1573
+ opacity: number;
1574
+ transparent: boolean;
1575
+ side: "front" | "back" | "double";
1576
+ } | undefined;
1577
+ texture?: {
1578
+ url: string;
1579
+ repeat?: [number, number] | undefined;
1580
+ scale?: number | undefined;
1581
+ } | undefined;
1582
+ } | undefined;
1583
+ materialPreset?: string | undefined;
1584
+ } | {
1585
+ object: "node";
1586
+ position: [number, number, number];
1587
+ id: `stair_${string}`;
1588
+ parentId: string | null;
1589
+ visible: boolean;
1590
+ metadata: Record<string, unknown>;
1591
+ rotation: number;
1592
+ children: `sseg_${string}`[];
1593
+ width: number;
1594
+ fromLevelId: string | null;
1595
+ toLevelId: string | null;
1596
+ thickness: number;
1597
+ stairType: "straight" | "spiral" | "curved";
1598
+ slabOpeningMode: "none" | "destination";
1599
+ openingOffset: number;
1600
+ stepCount: number;
1601
+ fillToFloor: boolean;
1602
+ innerRadius: number;
1603
+ sweepAngle: number;
1604
+ topLandingMode: "none" | "integrated";
1605
+ topLandingDepth: number;
1606
+ showCenterColumn: boolean;
1607
+ showStepSupports: boolean;
1608
+ railingMode: "right" | "left" | "none" | "both";
1609
+ railingHeight: number;
1610
+ type: "stair";
1611
+ name?: string | undefined;
1612
+ camera?: {
1613
+ position: [number, number, number];
1614
+ target: [number, number, number];
1615
+ mode: "perspective" | "orthographic";
1616
+ fov?: number | undefined;
1617
+ zoom?: number | undefined;
1618
+ } | undefined;
1619
+ supportSlabId?: string | undefined;
1620
+ slots?: Record<string, string> | undefined;
1621
+ material?: {
1622
+ id?: string | undefined;
1623
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1624
+ properties?: {
1625
+ color: string;
1626
+ roughness: number;
1627
+ metalness: number;
1628
+ opacity: number;
1629
+ transparent: boolean;
1630
+ side: "front" | "back" | "double";
1631
+ } | undefined;
1632
+ texture?: {
1633
+ url: string;
1634
+ repeat?: [number, number] | undefined;
1635
+ scale?: number | undefined;
1636
+ } | undefined;
1637
+ } | undefined;
1638
+ materialPreset?: string | undefined;
1639
+ railingMaterial?: {
1640
+ id?: string | undefined;
1641
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1642
+ properties?: {
1643
+ color: string;
1644
+ roughness: number;
1645
+ metalness: number;
1646
+ opacity: number;
1647
+ transparent: boolean;
1648
+ side: "front" | "back" | "double";
1649
+ } | undefined;
1650
+ texture?: {
1651
+ url: string;
1652
+ repeat?: [number, number] | undefined;
1653
+ scale?: number | undefined;
1654
+ } | undefined;
1655
+ } | undefined;
1656
+ railingMaterialPreset?: string | undefined;
1657
+ treadMaterial?: {
1658
+ id?: string | undefined;
1659
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1660
+ properties?: {
1661
+ color: string;
1662
+ roughness: number;
1663
+ metalness: number;
1664
+ opacity: number;
1665
+ transparent: boolean;
1666
+ side: "front" | "back" | "double";
1667
+ } | undefined;
1668
+ texture?: {
1669
+ url: string;
1670
+ repeat?: [number, number] | undefined;
1671
+ scale?: number | undefined;
1672
+ } | undefined;
1673
+ } | undefined;
1674
+ treadMaterialPreset?: string | undefined;
1675
+ sideMaterial?: {
1676
+ id?: string | undefined;
1677
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1678
+ properties?: {
1679
+ color: string;
1680
+ roughness: number;
1681
+ metalness: number;
1682
+ opacity: number;
1683
+ transparent: boolean;
1684
+ side: "front" | "back" | "double";
1685
+ } | undefined;
1686
+ texture?: {
1687
+ url: string;
1688
+ repeat?: [number, number] | undefined;
1689
+ scale?: number | undefined;
1690
+ } | undefined;
1691
+ } | undefined;
1692
+ sideMaterialPreset?: string | undefined;
1693
+ deckSlabId?: string | undefined;
1694
+ totalRise?: number | undefined;
1695
+ } | {
1696
+ object: "node";
1697
+ position: [number, number, number];
1698
+ id: `sseg_${string}`;
1699
+ parentId: string | null;
1700
+ visible: boolean;
1701
+ metadata: Record<string, unknown>;
1702
+ length: number;
1703
+ rotation: number;
1704
+ width: number;
1705
+ height: number;
1706
+ thickness: number;
1707
+ stepCount: number;
1708
+ fillToFloor: boolean;
1709
+ segmentType: "stair" | "landing";
1710
+ attachmentSide: "front" | "right" | "left";
1711
+ type: "stair-segment";
1712
+ name?: string | undefined;
1713
+ camera?: {
1714
+ position: [number, number, number];
1715
+ target: [number, number, number];
1716
+ mode: "perspective" | "orthographic";
1717
+ fov?: number | undefined;
1718
+ zoom?: number | undefined;
1719
+ } | undefined;
1720
+ material?: {
1721
+ id?: string | undefined;
1722
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1723
+ properties?: {
1724
+ color: string;
1725
+ roughness: number;
1726
+ metalness: number;
1727
+ opacity: number;
1728
+ transparent: boolean;
1729
+ side: "front" | "back" | "double";
1730
+ } | undefined;
1731
+ texture?: {
1732
+ url: string;
1733
+ repeat?: [number, number] | undefined;
1734
+ scale?: number | undefined;
1735
+ } | undefined;
1736
+ } | undefined;
1737
+ materialPreset?: string | undefined;
1738
+ } | {
1739
+ object: "node";
1740
+ position: [number, number, number];
1741
+ id: `scan_${string}`;
1742
+ parentId: string | null;
1743
+ visible: boolean;
1744
+ metadata: Record<string, unknown>;
1745
+ opacity: number;
1746
+ url: string | null;
1747
+ scale: number;
1748
+ rotation: [number, number, number];
1749
+ captureSession: {
1750
+ sessionId: string;
1751
+ schemaVersion?: number | undefined;
1752
+ revisionId?: string | undefined;
1753
+ manifestUrl?: string | undefined;
1754
+ } | null;
1755
+ layers: Record<string, boolean>;
1756
+ type: "scan";
1757
+ name?: string | undefined;
1758
+ camera?: {
1759
+ position: [number, number, number];
1760
+ target: [number, number, number];
1761
+ mode: "perspective" | "orthographic";
1762
+ fov?: number | undefined;
1763
+ zoom?: number | undefined;
1764
+ } | undefined;
1765
+ } | {
1766
+ object: "node";
1767
+ position: [number, number, number];
1768
+ id: `guide_${string}`;
1769
+ parentId: string | null;
1770
+ visible: boolean;
1771
+ metadata: Record<string, unknown>;
1772
+ opacity: number;
1773
+ url: string;
1774
+ scale: number;
1775
+ rotation: [number, number, number];
1776
+ scaleReference: {
1777
+ start: [number, number];
1778
+ end: [number, number];
1779
+ realLengthMeters: number;
1780
+ measuredLengthUnits: number;
1781
+ metersPerUnit: number;
1782
+ label: string;
1783
+ } | null;
1784
+ type: "guide";
1785
+ name?: string | undefined;
1786
+ camera?: {
1787
+ position: [number, number, number];
1788
+ target: [number, number, number];
1789
+ mode: "perspective" | "orthographic";
1790
+ fov?: number | undefined;
1791
+ zoom?: number | undefined;
1792
+ } | undefined;
1793
+ } | {
1794
+ object: "node";
1795
+ id: `measurement_${string}`;
1796
+ parentId: string | null;
1797
+ visible: boolean;
1798
+ metadata: Record<string, unknown>;
1799
+ measurement: {
1800
+ kind: "distance";
1801
+ points: [[number, number, number] | {
1802
+ kind: "feature";
1803
+ reference: {
1804
+ nodeId: string;
1805
+ featureId: string;
1806
+ parameters?: Record<string, string | number | boolean> | undefined;
1807
+ };
1808
+ fallback: [number, number, number];
1809
+ }, [number, number, number] | {
1810
+ kind: "feature";
1811
+ reference: {
1812
+ nodeId: string;
1813
+ featureId: string;
1814
+ parameters?: Record<string, string | number | boolean> | undefined;
1815
+ };
1816
+ fallback: [number, number, number];
1817
+ }];
1818
+ } | {
1819
+ kind: "angle";
1820
+ points: [[number, number, number] | {
1821
+ kind: "feature";
1822
+ reference: {
1823
+ nodeId: string;
1824
+ featureId: string;
1825
+ parameters?: Record<string, string | number | boolean> | undefined;
1826
+ };
1827
+ fallback: [number, number, number];
1828
+ }, [number, number, number] | {
1829
+ kind: "feature";
1830
+ reference: {
1831
+ nodeId: string;
1832
+ featureId: string;
1833
+ parameters?: Record<string, string | number | boolean> | undefined;
1834
+ };
1835
+ fallback: [number, number, number];
1836
+ }, [number, number, number] | {
1837
+ kind: "feature";
1838
+ reference: {
1839
+ nodeId: string;
1840
+ featureId: string;
1841
+ parameters?: Record<string, string | number | boolean> | undefined;
1842
+ };
1843
+ fallback: [number, number, number];
1844
+ }];
1845
+ } | {
1846
+ kind: "area";
1847
+ base: ([number, number, number] | {
1848
+ kind: "feature";
1849
+ reference: {
1850
+ nodeId: string;
1851
+ featureId: string;
1852
+ parameters?: Record<string, string | number | boolean> | undefined;
1853
+ };
1854
+ fallback: [number, number, number];
1855
+ })[];
1856
+ } | {
1857
+ kind: "perimeter";
1858
+ base: ([number, number, number] | {
1859
+ kind: "feature";
1860
+ reference: {
1861
+ nodeId: string;
1862
+ featureId: string;
1863
+ parameters?: Record<string, string | number | boolean> | undefined;
1864
+ };
1865
+ fallback: [number, number, number];
1866
+ })[];
1867
+ } | {
1868
+ kind: "volume";
1869
+ base: ([number, number, number] | {
1870
+ kind: "feature";
1871
+ reference: {
1872
+ nodeId: string;
1873
+ featureId: string;
1874
+ parameters?: Record<string, string | number | boolean> | undefined;
1875
+ };
1876
+ fallback: [number, number, number];
1877
+ })[];
1878
+ extrusion: [number, number, number];
1879
+ };
1880
+ type: "measurement";
1881
+ name?: string | undefined;
1882
+ camera?: {
1883
+ position: [number, number, number];
1884
+ target: [number, number, number];
1885
+ mode: "perspective" | "orthographic";
1886
+ fov?: number | undefined;
1887
+ zoom?: number | undefined;
1888
+ } | undefined;
1889
+ } | {
1890
+ object: "node";
1891
+ position: [number, number, number];
1892
+ id: `spawn_${string}`;
1893
+ parentId: string | null;
1894
+ visible: boolean;
1895
+ metadata: Record<string, unknown>;
1896
+ rotation: number;
1897
+ type: "spawn";
1898
+ name?: string | undefined;
1899
+ camera?: {
1900
+ position: [number, number, number];
1901
+ target: [number, number, number];
1902
+ mode: "perspective" | "orthographic";
1903
+ fov?: number | undefined;
1904
+ zoom?: number | undefined;
1905
+ } | undefined;
1906
+ supportSlabId?: string | undefined;
1907
+ } | {
1908
+ object: "node";
1909
+ position: [number, number, number];
1910
+ id: `window_${string}`;
1911
+ parentId: string | null;
1912
+ visible: boolean;
1913
+ metadata: Record<string, unknown>;
1914
+ rotation: [number, number, number];
1915
+ width: number;
1916
+ height: number;
1917
+ constructionType: "framed" | "masonry";
1918
+ dimensionReference: "nominal" | "rough-opening" | "masonry-opening" | "finish-opening";
1919
+ operationState: number;
1920
+ openingKind: "window" | "opening";
1921
+ openingShape: "rectangle" | "rounded" | "arch";
1922
+ openingRadiusMode: "all" | "individual";
1923
+ cornerRadius: number;
1924
+ archHeight: number;
1925
+ openingRevealRadius: number;
1926
+ frameThickness: number;
1927
+ frameDepth: number;
1928
+ hingesSide: "right" | "left";
1929
+ columnRatios: number[];
1930
+ windowType: "fixed" | "sliding" | "casement" | "awning" | "hopper" | "single-hung" | "double-hung" | "bay" | "bow" | "louvered";
1931
+ awningDirection: "up" | "down";
1932
+ casementStyle: "french" | "single";
1933
+ openingCornerRadii: [number, number, number, number];
1934
+ rowRatios: number[];
1935
+ columnDividerThickness: number;
1936
+ rowDividerThickness: number;
1937
+ sill: boolean;
1938
+ sillDepth: number;
1939
+ sillThickness: number;
1940
+ type: "window";
1941
+ name?: string | undefined;
1942
+ camera?: {
1943
+ position: [number, number, number];
1944
+ target: [number, number, number];
1945
+ mode: "perspective" | "orthographic";
1946
+ fov?: number | undefined;
1947
+ zoom?: number | undefined;
1948
+ } | undefined;
1949
+ side?: "front" | "back" | undefined;
1950
+ slots?: Record<string, string> | undefined;
1951
+ material?: {
1952
+ id?: string | undefined;
1953
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
1954
+ properties?: {
1955
+ color: string;
1956
+ roughness: number;
1957
+ metalness: number;
1958
+ opacity: number;
1959
+ transparent: boolean;
1960
+ side: "front" | "back" | "double";
1961
+ } | undefined;
1962
+ texture?: {
1963
+ url: string;
1964
+ repeat?: [number, number] | undefined;
1965
+ scale?: number | undefined;
1966
+ } | undefined;
1967
+ } | undefined;
1968
+ roofSegmentId?: string | undefined;
1969
+ wallId?: string | undefined;
1970
+ roofFace?: "front" | "back" | "right" | "left" | undefined;
1971
+ mark?: string | undefined;
1972
+ roughOpeningWidth?: number | undefined;
1973
+ roughOpeningHeight?: number | undefined;
1974
+ masonryOpeningWidth?: number | undefined;
1975
+ masonryOpeningHeight?: number | undefined;
1976
+ finishOpeningWidth?: number | undefined;
1977
+ finishOpeningHeight?: number | undefined;
1978
+ dormerId?: string | undefined;
1979
+ dormerFace?: "front" | "back" | "right" | "left" | undefined;
1980
+ } | {
1981
+ object: "node";
1982
+ position: [number, number, number];
1983
+ id: `door_${string}`;
1984
+ parentId: string | null;
1985
+ visible: boolean;
1986
+ metadata: Record<string, unknown>;
1987
+ rotation: [number, number, number];
1988
+ width: number;
1989
+ height: number;
1990
+ leafCount: 3 | 2 | 1 | 4;
1991
+ constructionType: "framed" | "masonry";
1992
+ dimensionReference: "nominal" | "rough-opening" | "masonry-opening" | "finish-opening";
1993
+ doorCategory: "interior" | "garage";
1994
+ doorType: "double" | "hinged" | "french" | "folding" | "pocket" | "barn" | "sliding" | "garage-sectional" | "garage-rollup" | "garage-tiltup";
1995
+ operationState: number;
1996
+ slideDirection: "right" | "left";
1997
+ trackStyle: "visible" | "none" | "pocket" | "overhead";
1998
+ garagePanelCount: number;
1999
+ openingKind: "door" | "opening";
2000
+ openingShape: "rectangle" | "rounded" | "arch";
2001
+ openingRadiusMode: "all" | "individual";
2002
+ openingTopRadii: [number, number];
2003
+ cornerRadius: number;
2004
+ archHeight: number;
2005
+ openingRevealRadius: number;
2006
+ frameThickness: number;
2007
+ frameDepth: number;
2008
+ threshold: boolean;
2009
+ thresholdHeight: number;
2010
+ hingesSide: "right" | "left";
2011
+ swingDirection: "inward" | "outward";
2012
+ swingAngle: number;
2013
+ segments: {
2014
+ type: "glass" | "panel" | "empty";
2015
+ heightRatio: number;
2016
+ columnRatios: number[];
2017
+ dividerThickness: number;
2018
+ panelDepth: number;
2019
+ panelInset: number;
2020
+ }[];
2021
+ handle: boolean;
2022
+ handleHeight: number;
2023
+ handleSide: "right" | "left";
2024
+ contentPadding: [number, number];
2025
+ doorCloser: boolean;
2026
+ panicBar: boolean;
2027
+ panicBarHeight: number;
2028
+ type: "door";
2029
+ name?: string | undefined;
2030
+ camera?: {
2031
+ position: [number, number, number];
2032
+ target: [number, number, number];
2033
+ mode: "perspective" | "orthographic";
2034
+ fov?: number | undefined;
2035
+ zoom?: number | undefined;
2036
+ } | undefined;
2037
+ side?: "front" | "back" | undefined;
2038
+ slots?: Record<string, string> | undefined;
2039
+ material?: {
2040
+ id?: string | undefined;
2041
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2042
+ properties?: {
2043
+ color: string;
2044
+ roughness: number;
2045
+ metalness: number;
2046
+ opacity: number;
2047
+ transparent: boolean;
2048
+ side: "front" | "back" | "double";
2049
+ } | undefined;
2050
+ texture?: {
2051
+ url: string;
2052
+ repeat?: [number, number] | undefined;
2053
+ scale?: number | undefined;
2054
+ } | undefined;
2055
+ } | undefined;
2056
+ roofSegmentId?: string | undefined;
2057
+ wallId?: string | undefined;
2058
+ roofFace?: "front" | "back" | "right" | "left" | undefined;
2059
+ mark?: string | undefined;
2060
+ roughOpeningWidth?: number | undefined;
2061
+ roughOpeningHeight?: number | undefined;
2062
+ masonryOpeningWidth?: number | undefined;
2063
+ masonryOpeningHeight?: number | undefined;
2064
+ finishOpeningWidth?: number | undefined;
2065
+ finishOpeningHeight?: number | undefined;
2066
+ } | {
2067
+ object: "node";
2068
+ position: [number, number, number];
2069
+ id: `bvent_${string}`;
2070
+ parentId: string | null;
2071
+ visible: boolean;
2072
+ metadata: Record<string, unknown>;
2073
+ rotation: number;
2074
+ materialPreset: string;
2075
+ width: number;
2076
+ depth: number;
2077
+ height: number;
2078
+ hoodOverhang: number;
2079
+ topTaper: number;
2080
+ capHeight: number;
2081
+ capGap: number;
2082
+ domeCurvature: number;
2083
+ baseInset: number;
2084
+ baseHeight: number;
2085
+ cornerBevel: number;
2086
+ style: "box" | "cap" | "dome";
2087
+ type: "box-vent";
2088
+ name?: string | undefined;
2089
+ camera?: {
2090
+ position: [number, number, number];
2091
+ target: [number, number, number];
2092
+ mode: "perspective" | "orthographic";
2093
+ fov?: number | undefined;
2094
+ zoom?: number | undefined;
2095
+ } | undefined;
2096
+ slots?: Record<string, string> | undefined;
2097
+ material?: {
2098
+ id?: string | undefined;
2099
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2100
+ properties?: {
2101
+ color: string;
2102
+ roughness: number;
2103
+ metalness: number;
2104
+ opacity: number;
2105
+ transparent: boolean;
2106
+ side: "front" | "back" | "double";
2107
+ } | undefined;
2108
+ texture?: {
2109
+ url: string;
2110
+ repeat?: [number, number] | undefined;
2111
+ scale?: number | undefined;
2112
+ } | undefined;
2113
+ } | undefined;
2114
+ roofSegmentId?: string | undefined;
2115
+ } | {
2116
+ object: "node";
2117
+ position: [number, number, number];
2118
+ id: `rvent_${string}`;
2119
+ parentId: string | null;
2120
+ visible: boolean;
2121
+ metadata: Record<string, unknown>;
2122
+ length: number;
2123
+ rotation: number;
2124
+ width: number;
2125
+ height: number;
2126
+ style: "metal" | "standard" | "shingled";
2127
+ endCaps: boolean;
2128
+ type: "ridge-vent";
2129
+ name?: string | undefined;
2130
+ camera?: {
2131
+ position: [number, number, number];
2132
+ target: [number, number, number];
2133
+ mode: "perspective" | "orthographic";
2134
+ fov?: number | undefined;
2135
+ zoom?: number | undefined;
2136
+ } | undefined;
2137
+ material?: {
2138
+ id?: string | undefined;
2139
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2140
+ properties?: {
2141
+ color: string;
2142
+ roughness: number;
2143
+ metalness: number;
2144
+ opacity: number;
2145
+ transparent: boolean;
2146
+ side: "front" | "back" | "double";
2147
+ } | undefined;
2148
+ texture?: {
2149
+ url: string;
2150
+ repeat?: [number, number] | undefined;
2151
+ scale?: number | undefined;
2152
+ } | undefined;
2153
+ } | undefined;
2154
+ materialPreset?: string | undefined;
2155
+ roofSegmentId?: string | undefined;
2156
+ } | {
2157
+ object: "node";
2158
+ position: [number, number, number];
2159
+ id: `tvent_${string}`;
2160
+ parentId: string | null;
2161
+ visible: boolean;
2162
+ metadata: Record<string, unknown>;
2163
+ rotation: number;
2164
+ materialPreset: string;
2165
+ height: number;
2166
+ style: "cylinder" | "globe";
2167
+ diameter: number;
2168
+ neckHeight: number;
2169
+ baseOverhang: number;
2170
+ vaneCount: number;
2171
+ spinSpeed: number;
2172
+ type: "turbine-vent";
2173
+ name?: string | undefined;
2174
+ camera?: {
2175
+ position: [number, number, number];
2176
+ target: [number, number, number];
2177
+ mode: "perspective" | "orthographic";
2178
+ fov?: number | undefined;
2179
+ zoom?: number | undefined;
2180
+ } | undefined;
2181
+ slots?: Record<string, string> | undefined;
2182
+ material?: {
2183
+ id?: string | undefined;
2184
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2185
+ properties?: {
2186
+ color: string;
2187
+ roughness: number;
2188
+ metalness: number;
2189
+ opacity: number;
2190
+ transparent: boolean;
2191
+ side: "front" | "back" | "double";
2192
+ } | undefined;
2193
+ texture?: {
2194
+ url: string;
2195
+ repeat?: [number, number] | undefined;
2196
+ scale?: number | undefined;
2197
+ } | undefined;
2198
+ } | undefined;
2199
+ roofSegmentId?: string | undefined;
2200
+ } | {
2201
+ object: "node";
2202
+ position: [number, number, number];
2203
+ id: `cupola_${string}`;
2204
+ parentId: string | null;
2205
+ visible: boolean;
2206
+ metadata: Record<string, unknown>;
2207
+ rotation: number;
2208
+ materialPreset: string;
2209
+ width: number;
2210
+ depth: number;
2211
+ height: number;
2212
+ roofStyle: "dome" | "pyramid";
2213
+ finial: boolean;
2214
+ type: "cupola";
2215
+ name?: string | undefined;
2216
+ camera?: {
2217
+ position: [number, number, number];
2218
+ target: [number, number, number];
2219
+ mode: "perspective" | "orthographic";
2220
+ fov?: number | undefined;
2221
+ zoom?: number | undefined;
2222
+ } | undefined;
2223
+ slots?: Record<string, string> | undefined;
2224
+ material?: {
2225
+ id?: string | undefined;
2226
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2227
+ properties?: {
2228
+ color: string;
2229
+ roughness: number;
2230
+ metalness: number;
2231
+ opacity: number;
2232
+ transparent: boolean;
2233
+ side: "front" | "back" | "double";
2234
+ } | undefined;
2235
+ texture?: {
2236
+ url: string;
2237
+ repeat?: [number, number] | undefined;
2238
+ scale?: number | undefined;
2239
+ } | undefined;
2240
+ } | undefined;
2241
+ roofSegmentId?: string | undefined;
2242
+ } | {
2243
+ object: "node";
2244
+ position: [number, number, number];
2245
+ id: `eyebrow-vent_${string}`;
2246
+ parentId: string | null;
2247
+ visible: boolean;
2248
+ metadata: Record<string, unknown>;
2249
+ rotation: number;
2250
+ materialPreset: string;
2251
+ width: number;
2252
+ depth: number;
2253
+ height: number;
2254
+ style: "half-round" | "scoop" | "slant-box";
2255
+ louverCount: number;
2256
+ backRatio: number;
2257
+ type: "eyebrow-vent";
2258
+ name?: string | undefined;
2259
+ camera?: {
2260
+ position: [number, number, number];
2261
+ target: [number, number, number];
2262
+ mode: "perspective" | "orthographic";
2263
+ fov?: number | undefined;
2264
+ zoom?: number | undefined;
2265
+ } | undefined;
2266
+ slots?: Record<string, string> | undefined;
2267
+ material?: {
2268
+ id?: string | undefined;
2269
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2270
+ properties?: {
2271
+ color: string;
2272
+ roughness: number;
2273
+ metalness: number;
2274
+ opacity: number;
2275
+ transparent: boolean;
2276
+ side: "front" | "back" | "double";
2277
+ } | undefined;
2278
+ texture?: {
2279
+ url: string;
2280
+ repeat?: [number, number] | undefined;
2281
+ scale?: number | undefined;
2282
+ } | undefined;
2283
+ } | undefined;
2284
+ roofSegmentId?: string | undefined;
2285
+ } | {
2286
+ object: "node";
2287
+ position: [number, number, number];
2288
+ id: `gutter_${string}`;
2289
+ parentId: string | null;
2290
+ visible: boolean;
2291
+ metadata: Record<string, unknown>;
2292
+ length: number;
2293
+ rotation: number;
2294
+ materialPreset: string;
2295
+ thickness: number;
2296
+ profile: "box" | "k-style" | "half-round";
2297
+ size: number;
2298
+ hangerStyle: "none" | "strap";
2299
+ hangerSpacing: number;
2300
+ endCapLeft: boolean;
2301
+ endCapRight: boolean;
2302
+ outlets: {
2303
+ id: string;
2304
+ offset: number;
2305
+ diameter: number;
2306
+ generatedBy?: "default-downspout" | undefined;
2307
+ }[];
2308
+ type: "gutter";
2309
+ name?: string | undefined;
2310
+ camera?: {
2311
+ position: [number, number, number];
2312
+ target: [number, number, number];
2313
+ mode: "perspective" | "orthographic";
2314
+ fov?: number | undefined;
2315
+ zoom?: number | undefined;
2316
+ } | undefined;
2317
+ slots?: Record<string, string> | undefined;
2318
+ material?: {
2319
+ id?: string | undefined;
2320
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2321
+ properties?: {
2322
+ color: string;
2323
+ roughness: number;
2324
+ metalness: number;
2325
+ opacity: number;
2326
+ transparent: boolean;
2327
+ side: "front" | "back" | "double";
2328
+ } | undefined;
2329
+ texture?: {
2330
+ url: string;
2331
+ repeat?: [number, number] | undefined;
2332
+ scale?: number | undefined;
2333
+ } | undefined;
2334
+ } | undefined;
2335
+ roofSegmentId?: string | undefined;
2336
+ arc?: {
2337
+ centerX: number;
2338
+ centerZ: number;
2339
+ radius: number;
2340
+ } | undefined;
2341
+ } | {
2342
+ object: "node";
2343
+ position: [number, number, number];
2344
+ id: `chimney_${string}`;
2345
+ parentId: string | null;
2346
+ visible: boolean;
2347
+ metadata: Record<string, unknown>;
2348
+ rotation: number;
2349
+ width: number;
2350
+ depth: number;
2351
+ cornerBevel: number;
2352
+ cap: boolean;
2353
+ panelDepth: number;
2354
+ panelHeight: number;
2355
+ bodyShape: "round" | "square";
2356
+ bodyHollowDepth: number;
2357
+ bodyHollowMargin: number;
2358
+ heightAboveRidge: number;
2359
+ cutoutOffset: number;
2360
+ capShape: "flat" | "none" | "stepped" | "sloped";
2361
+ capOverhang: number;
2362
+ capThickness: number;
2363
+ flueCount: number;
2364
+ flueShape: "round" | "square";
2365
+ flueHeight: number;
2366
+ flueDiameter: number;
2367
+ flueSpacing: number;
2368
+ flueWallThickness: number;
2369
+ shoulderStyle: "tapered" | "none" | "corbeled";
2370
+ shoulderHeight: number;
2371
+ shoulderExtent: number;
2372
+ bandStyle: "double" | "none" | "single";
2373
+ bandHeight: number;
2374
+ bandExtent: number;
2375
+ bandOffset: number;
2376
+ cricketStyle: "none" | "simple";
2377
+ cricketLength: number;
2378
+ cricketHeight: number;
2379
+ cricketSide: "front" | "back";
2380
+ panelStyle: "rectangular" | "none";
2381
+ panelOffsetTop: number;
2382
+ panelMargin: number;
2383
+ type: "chimney";
2384
+ name?: string | undefined;
2385
+ camera?: {
2386
+ position: [number, number, number];
2387
+ target: [number, number, number];
2388
+ mode: "perspective" | "orthographic";
2389
+ fov?: number | undefined;
2390
+ zoom?: number | undefined;
2391
+ } | undefined;
2392
+ material?: {
2393
+ id?: string | undefined;
2394
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2395
+ properties?: {
2396
+ color: string;
2397
+ roughness: number;
2398
+ metalness: number;
2399
+ opacity: number;
2400
+ transparent: boolean;
2401
+ side: "front" | "back" | "double";
2402
+ } | undefined;
2403
+ texture?: {
2404
+ url: string;
2405
+ repeat?: [number, number] | undefined;
2406
+ scale?: number | undefined;
2407
+ } | undefined;
2408
+ } | undefined;
2409
+ materialPreset?: string | undefined;
2410
+ roofSegmentId?: string | undefined;
2411
+ topMaterial?: {
2412
+ id?: string | undefined;
2413
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2414
+ properties?: {
2415
+ color: string;
2416
+ roughness: number;
2417
+ metalness: number;
2418
+ opacity: number;
2419
+ transparent: boolean;
2420
+ side: "front" | "back" | "double";
2421
+ } | undefined;
2422
+ texture?: {
2423
+ url: string;
2424
+ repeat?: [number, number] | undefined;
2425
+ scale?: number | undefined;
2426
+ } | undefined;
2427
+ } | undefined;
2428
+ topMaterialPreset?: string | undefined;
2429
+ } | {
2430
+ object: "node";
2431
+ position: [number, number, number];
2432
+ id: `solarpanel_${string}`;
2433
+ parentId: string | null;
2434
+ visible: boolean;
2435
+ metadata: Record<string, unknown>;
2436
+ rotation: number;
2437
+ rows: number;
2438
+ frameThickness: number;
2439
+ frameDepth: number;
2440
+ columns: number;
2441
+ panelWidth: number;
2442
+ panelHeight: number;
2443
+ gapX: number;
2444
+ gapY: number;
2445
+ mountingType: "flush" | "tilted";
2446
+ tiltAngle: number;
2447
+ standoffHeight: number;
2448
+ type: "solar-panel";
2449
+ name?: string | undefined;
2450
+ camera?: {
2451
+ position: [number, number, number];
2452
+ target: [number, number, number];
2453
+ mode: "perspective" | "orthographic";
2454
+ fov?: number | undefined;
2455
+ zoom?: number | undefined;
2456
+ } | undefined;
2457
+ material?: {
2458
+ id?: string | undefined;
2459
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2460
+ properties?: {
2461
+ color: string;
2462
+ roughness: number;
2463
+ metalness: number;
2464
+ opacity: number;
2465
+ transparent: boolean;
2466
+ side: "front" | "back" | "double";
2467
+ } | undefined;
2468
+ texture?: {
2469
+ url: string;
2470
+ repeat?: [number, number] | undefined;
2471
+ scale?: number | undefined;
2472
+ } | undefined;
2473
+ } | undefined;
2474
+ materialPreset?: string | undefined;
2475
+ roofSegmentId?: string | undefined;
2476
+ panelMaterial?: {
2477
+ id?: string | undefined;
2478
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2479
+ properties?: {
2480
+ color: string;
2481
+ roughness: number;
2482
+ metalness: number;
2483
+ opacity: number;
2484
+ transparent: boolean;
2485
+ side: "front" | "back" | "double";
2486
+ } | undefined;
2487
+ texture?: {
2488
+ url: string;
2489
+ repeat?: [number, number] | undefined;
2490
+ scale?: number | undefined;
2491
+ } | undefined;
2492
+ } | undefined;
2493
+ panelMaterialPreset?: string | undefined;
2494
+ panelTypePreset?: "residential" | "residential-large" | "compact" | "frameless" | undefined;
2495
+ surfaceNormal?: [number, number, number] | undefined;
2496
+ } | {
2497
+ object: "node";
2498
+ position: [number, number, number];
2499
+ id: `skylight_${string}`;
2500
+ parentId: string | null;
2501
+ visible: boolean;
2502
+ metadata: Record<string, unknown>;
2503
+ rotation: number;
2504
+ width: number;
2505
+ height: number;
2506
+ operationState: number;
2507
+ slideDirection: "x" | "z";
2508
+ frameThickness: number;
2509
+ frameDepth: number;
2510
+ curbHeight: number;
2511
+ cutoutOffset: number;
2512
+ skylightType: "flat" | "sliding" | "opening" | "walk-on" | "lantern";
2513
+ glassThickness: number;
2514
+ lanternHeight: number;
2515
+ lanternTopScale: number;
2516
+ openingAngle: number;
2517
+ openingSide: "top" | "right" | "left" | "bottom";
2518
+ motorHousing: boolean;
2519
+ slideFraction: number;
2520
+ trackWidth: number;
2521
+ motorHousingSize: number;
2522
+ curb: boolean;
2523
+ type: "skylight";
2524
+ name?: string | undefined;
2525
+ camera?: {
2526
+ position: [number, number, number];
2527
+ target: [number, number, number];
2528
+ mode: "perspective" | "orthographic";
2529
+ fov?: number | undefined;
2530
+ zoom?: number | undefined;
2531
+ } | undefined;
2532
+ material?: {
2533
+ id?: string | undefined;
2534
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2535
+ properties?: {
2536
+ color: string;
2537
+ roughness: number;
2538
+ metalness: number;
2539
+ opacity: number;
2540
+ transparent: boolean;
2541
+ side: "front" | "back" | "double";
2542
+ } | undefined;
2543
+ texture?: {
2544
+ url: string;
2545
+ repeat?: [number, number] | undefined;
2546
+ scale?: number | undefined;
2547
+ } | undefined;
2548
+ } | undefined;
2549
+ materialPreset?: string | undefined;
2550
+ roofSegmentId?: string | undefined;
2551
+ surfaceNormal?: [number, number, number] | undefined;
2552
+ glassMaterial?: {
2553
+ id?: string | undefined;
2554
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2555
+ properties?: {
2556
+ color: string;
2557
+ roughness: number;
2558
+ metalness: number;
2559
+ opacity: number;
2560
+ transparent: boolean;
2561
+ side: "front" | "back" | "double";
2562
+ } | undefined;
2563
+ texture?: {
2564
+ url: string;
2565
+ repeat?: [number, number] | undefined;
2566
+ scale?: number | undefined;
2567
+ } | undefined;
2568
+ } | undefined;
2569
+ glassMaterialPreset?: string | undefined;
2570
+ } | {
2571
+ object: "node";
2572
+ position: [number, number, number];
2573
+ id: `dormer_${string}`;
2574
+ parentId: string | null;
2575
+ visible: boolean;
2576
+ metadata: Record<string, unknown>;
2577
+ rotation: number;
2578
+ children: `window_${string}`[];
2579
+ width: number;
2580
+ depth: number;
2581
+ height: number;
2582
+ roofType: "flat" | "hip" | "gable" | "shed" | "gambrel" | "dutch" | "mansard" | "conical";
2583
+ roofHeight: number;
2584
+ shedHighSide: "front" | "back";
2585
+ wallSkirtHeight: number;
2586
+ windowWidth: number;
2587
+ windowHeight: number;
2588
+ windowOffsetX: number;
2589
+ windowOffsetY: number;
2590
+ windowFrameThickness: number;
2591
+ windowFrameDepth: number;
2592
+ windowColumns: number;
2593
+ windowRows: number;
2594
+ windowDividerThickness: number;
2595
+ windowShape: "rectangle" | "rounded" | "arch";
2596
+ windowArchHeight: number;
2597
+ windowCornerRadii: [number, number, number, number];
2598
+ windowSill: boolean;
2599
+ windowSillDepth: number;
2600
+ windowSillThickness: number;
2601
+ type: "dormer";
2602
+ name?: string | undefined;
2603
+ camera?: {
2604
+ position: [number, number, number];
2605
+ target: [number, number, number];
2606
+ mode: "perspective" | "orthographic";
2607
+ fov?: number | undefined;
2608
+ zoom?: number | undefined;
2609
+ } | undefined;
2610
+ material?: {
2611
+ id?: string | undefined;
2612
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2613
+ properties?: {
2614
+ color: string;
2615
+ roughness: number;
2616
+ metalness: number;
2617
+ opacity: number;
2618
+ transparent: boolean;
2619
+ side: "front" | "back" | "double";
2620
+ } | undefined;
2621
+ texture?: {
2622
+ url: string;
2623
+ repeat?: [number, number] | undefined;
2624
+ scale?: number | undefined;
2625
+ } | undefined;
2626
+ } | undefined;
2627
+ materialPreset?: string | undefined;
2628
+ roofSegmentId?: string | undefined;
2629
+ topMaterial?: {
2630
+ id?: string | undefined;
2631
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2632
+ properties?: {
2633
+ color: string;
2634
+ roughness: number;
2635
+ metalness: number;
2636
+ opacity: number;
2637
+ transparent: boolean;
2638
+ side: "front" | "back" | "double";
2639
+ } | undefined;
2640
+ texture?: {
2641
+ url: string;
2642
+ repeat?: [number, number] | undefined;
2643
+ scale?: number | undefined;
2644
+ } | undefined;
2645
+ } | undefined;
2646
+ topMaterialPreset?: string | undefined;
2647
+ wallMaterial?: {
2648
+ id?: string | undefined;
2649
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2650
+ properties?: {
2651
+ color: string;
2652
+ roughness: number;
2653
+ metalness: number;
2654
+ opacity: number;
2655
+ transparent: boolean;
2656
+ side: "front" | "back" | "double";
2657
+ } | undefined;
2658
+ texture?: {
2659
+ url: string;
2660
+ repeat?: [number, number] | undefined;
2661
+ scale?: number | undefined;
2662
+ } | undefined;
2663
+ } | undefined;
2664
+ wallMaterialPreset?: string | undefined;
2665
+ sideMaterial?: {
2666
+ id?: string | undefined;
2667
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2668
+ properties?: {
2669
+ color: string;
2670
+ roughness: number;
2671
+ metalness: number;
2672
+ opacity: number;
2673
+ transparent: boolean;
2674
+ side: "front" | "back" | "double";
2675
+ } | undefined;
2676
+ texture?: {
2677
+ url: string;
2678
+ repeat?: [number, number] | undefined;
2679
+ scale?: number | undefined;
2680
+ } | undefined;
2681
+ } | undefined;
2682
+ sideMaterialPreset?: string | undefined;
2683
+ } | {
2684
+ object: "node";
2685
+ id: `downspout_${string}`;
2686
+ parentId: string | null;
2687
+ visible: boolean;
2688
+ metadata: Record<string, unknown>;
2689
+ length: number;
2690
+ materialPreset: string;
2691
+ diameter: number;
2692
+ shape: "round" | "auto" | "rect";
2693
+ standoff: number;
2694
+ strapStyle: "none" | "band";
2695
+ strapSpacing: number;
2696
+ terminal: "straight" | "splash" | "kickout";
2697
+ type: "downspout";
2698
+ name?: string | undefined;
2699
+ camera?: {
2700
+ position: [number, number, number];
2701
+ target: [number, number, number];
2702
+ mode: "perspective" | "orthographic";
2703
+ fov?: number | undefined;
2704
+ zoom?: number | undefined;
2705
+ } | undefined;
2706
+ slots?: Record<string, string> | undefined;
2707
+ material?: {
2708
+ id?: string | undefined;
2709
+ preset?: "custom" | "white" | "brick" | "concrete" | "wood" | "glass" | "metal" | "plaster" | "tile" | "marble" | undefined;
2710
+ properties?: {
2711
+ color: string;
2712
+ roughness: number;
2713
+ metalness: number;
2714
+ opacity: number;
2715
+ transparent: boolean;
2716
+ side: "front" | "back" | "double";
2717
+ } | undefined;
2718
+ texture?: {
2719
+ url: string;
2720
+ repeat?: [number, number] | undefined;
2721
+ scale?: number | undefined;
2722
+ } | undefined;
2723
+ } | undefined;
2724
+ gutterId?: string | undefined;
2725
+ outletId?: string | undefined;
2726
+ lengthMode?: "manual" | "to-ground" | undefined;
2727
+ } | {
2728
+ object: "node";
2729
+ id: `duct-segment_${string}`;
2730
+ parentId: string | null;
2731
+ visible: boolean;
2732
+ metadata: Record<string, unknown>;
2733
+ path: [number, number, number][];
2734
+ width: number;
2735
+ height: number;
2736
+ diameter: number;
2737
+ shape: "round" | "rect" | "oval";
2738
+ roll: number;
2739
+ ductMaterial: "spiral" | "sheet-metal" | "flex" | "duct-board";
2740
+ seamDetail: boolean;
2741
+ insulated: boolean;
2742
+ insulationR: number;
2743
+ system: "supply" | "return";
2744
+ type: "duct-segment";
2745
+ name?: string | undefined;
2746
+ camera?: {
2747
+ position: [number, number, number];
2748
+ target: [number, number, number];
2749
+ mode: "perspective" | "orthographic";
2750
+ fov?: number | undefined;
2751
+ zoom?: number | undefined;
2752
+ } | undefined;
2753
+ slots?: Record<string, string> | undefined;
2754
+ autoHangers?: boolean | undefined;
2755
+ hangerOverrides?: Record<string, {
2756
+ fraction?: number | undefined;
2757
+ skipped?: boolean | undefined;
2758
+ hostId?: string | undefined;
2759
+ }> | undefined;
2760
+ hangerStyle?: "double" | "single" | undefined;
2761
+ hangerSpacing?: number | undefined;
2762
+ hangerMaxReach?: number | undefined;
2763
+ wallAttachment?: {
2764
+ wallId: `wall_${string}`;
2765
+ side: "front" | "back";
2766
+ startUV: [number, number];
2767
+ endUV: [number, number];
2768
+ offset: number;
2769
+ } | undefined;
2770
+ } | {
2771
+ object: "node";
2772
+ position: [number, number, number];
2773
+ id: `duct-fitting_${string}`;
2774
+ parentId: string | null;
2775
+ visible: boolean;
2776
+ metadata: Record<string, unknown>;
2777
+ rotation: [number, number, number];
2778
+ width: number;
2779
+ height: number;
2780
+ angle: number;
2781
+ diameter: number;
2782
+ shape: "round" | "rect" | "oval";
2783
+ ductMaterial: "sheet-metal" | "flex" | "duct-board";
2784
+ system: "supply" | "return";
2785
+ fittingType: "elbow" | "tee" | "cross" | "reducer" | "transition" | "end-cap" | "damper" | "access-panel" | "coupling";
2786
+ shape2: "round" | "rect" | "oval";
2787
+ width2: number;
2788
+ height2: number;
2789
+ branchAngle: number;
2790
+ diameter2: number;
2791
+ damperAngle: number;
2792
+ panelWidth: number;
2793
+ panelHeight: number;
2794
+ type: "duct-fitting";
2795
+ name?: string | undefined;
2796
+ camera?: {
2797
+ position: [number, number, number];
2798
+ target: [number, number, number];
2799
+ mode: "perspective" | "orthographic";
2800
+ fov?: number | undefined;
2801
+ zoom?: number | undefined;
2802
+ } | undefined;
2803
+ slots?: Record<string, string> | undefined;
2804
+ inletShape?: "round" | "rect" | "oval" | undefined;
2805
+ outletShape?: "round" | "rect" | "oval" | undefined;
2806
+ } | {
2807
+ object: "node";
2808
+ position: [number, number, number];
2809
+ id: `duct-terminal_${string}`;
2810
+ parentId: string | null;
2811
+ visible: boolean;
2812
+ metadata: Record<string, unknown>;
2813
+ rotation: number;
2814
+ width: number;
2815
+ depth: number;
2816
+ terminalType: "supply-register" | "diffuser" | "return-grille";
2817
+ mount: "wall" | "ceiling" | "floor";
2818
+ collarShape: "round" | "rect" | "oval";
2819
+ collarDiameter: number;
2820
+ collarWidth: number;
2821
+ collarHeight: number;
2822
+ type: "duct-terminal";
2823
+ name?: string | undefined;
2824
+ camera?: {
2825
+ position: [number, number, number];
2826
+ target: [number, number, number];
2827
+ mode: "perspective" | "orthographic";
2828
+ fov?: number | undefined;
2829
+ zoom?: number | undefined;
2830
+ } | undefined;
2831
+ supportSlabId?: string | undefined;
2832
+ } | {
2833
+ object: "node";
2834
+ position: [number, number, number];
2835
+ id: `hvac-equipment_${string}`;
2836
+ parentId: string | null;
2837
+ visible: boolean;
2838
+ metadata: Record<string, unknown>;
2839
+ rotation: number;
2840
+ width: number;
2841
+ depth: number;
2842
+ height: number;
2843
+ equipmentType: "furnace" | "air-handler" | "condenser";
2844
+ supplyShape: "round" | "rect" | "oval";
2845
+ returnShape: "round" | "rect" | "oval";
2846
+ supplyDiameter: number;
2847
+ returnDiameter: number;
2848
+ supplyWidth: number;
2849
+ supplyHeight: number;
2850
+ returnWidth: number;
2851
+ returnHeight: number;
2852
+ type: "hvac-equipment";
2853
+ name?: string | undefined;
2854
+ camera?: {
2855
+ position: [number, number, number];
2856
+ target: [number, number, number];
2857
+ mode: "perspective" | "orthographic";
2858
+ fov?: number | undefined;
2859
+ zoom?: number | undefined;
2860
+ } | undefined;
2861
+ supportSlabId?: string | undefined;
2862
+ } | {
2863
+ object: "node";
2864
+ id: `lineset_${string}`;
2865
+ parentId: string | null;
2866
+ visible: boolean;
2867
+ metadata: Record<string, unknown>;
2868
+ path: [number, number, number][];
2869
+ insulated: boolean;
2870
+ suctionDiameter: number;
2871
+ liquidDiameter: number;
2872
+ type: "lineset";
2873
+ name?: string | undefined;
2874
+ camera?: {
2875
+ position: [number, number, number];
2876
+ target: [number, number, number];
2877
+ mode: "perspective" | "orthographic";
2878
+ fov?: number | undefined;
2879
+ zoom?: number | undefined;
2880
+ } | undefined;
2881
+ } | {
2882
+ object: "node";
2883
+ id: `liquid-line_${string}`;
2884
+ parentId: string | null;
2885
+ visible: boolean;
2886
+ metadata: Record<string, unknown>;
2887
+ path: [number, number, number][];
2888
+ diameter: number;
2889
+ type: "liquid-line";
2890
+ name?: string | undefined;
2891
+ camera?: {
2892
+ position: [number, number, number];
2893
+ target: [number, number, number];
2894
+ mode: "perspective" | "orthographic";
2895
+ fov?: number | undefined;
2896
+ zoom?: number | undefined;
2897
+ } | undefined;
2898
+ } | {
2899
+ object: "node";
2900
+ id: `pipe-segment_${string}`;
2901
+ parentId: string | null;
2902
+ visible: boolean;
2903
+ metadata: Record<string, unknown>;
2904
+ path: [number, number, number][];
2905
+ diameter: number;
2906
+ system: "waste" | "vent";
2907
+ pipeMaterial: "abs" | "pvc" | "cast-iron";
2908
+ type: "pipe-segment";
2909
+ name?: string | undefined;
2910
+ camera?: {
2911
+ position: [number, number, number];
2912
+ target: [number, number, number];
2913
+ mode: "perspective" | "orthographic";
2914
+ fov?: number | undefined;
2915
+ zoom?: number | undefined;
2916
+ } | undefined;
2917
+ autoHangers?: boolean | undefined;
2918
+ hangerOverrides?: Record<string, {
2919
+ fraction?: number | undefined;
2920
+ skipped?: boolean | undefined;
2921
+ hostId?: string | undefined;
2922
+ }> | undefined;
2923
+ hangerStyle?: "double" | "single" | undefined;
2924
+ hangerSpacing?: number | undefined;
2925
+ hangerMaxReach?: number | undefined;
2926
+ wallAttachment?: {
2927
+ wallId: `wall_${string}`;
2928
+ side: "front" | "back";
2929
+ startUV: [number, number];
2930
+ endUV: [number, number];
2931
+ offset: number;
2932
+ } | undefined;
2933
+ } | {
2934
+ object: "node";
2935
+ position: [number, number, number];
2936
+ id: `pipe-fitting_${string}`;
2937
+ parentId: string | null;
2938
+ visible: boolean;
2939
+ metadata: Record<string, unknown>;
2940
+ rotation: [number, number, number];
2941
+ angle: number;
2942
+ diameter: number;
2943
+ system: "waste" | "vent";
2944
+ fittingType: "elbow" | "cross" | "reducer" | "end-cap" | "coupling" | "wye" | "sanitary-tee" | "cleanout";
2945
+ diameter2: number;
2946
+ pipeMaterial: "abs" | "pvc" | "cast-iron";
2947
+ cleanoutStyle: "end" | "inline";
2948
+ type: "pipe-fitting";
2949
+ name?: string | undefined;
2950
+ camera?: {
2951
+ position: [number, number, number];
2952
+ target: [number, number, number];
2953
+ mode: "perspective" | "orthographic";
2954
+ fov?: number | undefined;
2955
+ zoom?: number | undefined;
2956
+ } | undefined;
2957
+ } | {
2958
+ object: "node";
2959
+ position: [number, number, number];
2960
+ id: `pipe-trap_${string}`;
2961
+ parentId: string | null;
2962
+ visible: boolean;
2963
+ metadata: Record<string, unknown>;
2964
+ rotation: number;
2965
+ diameter: number;
2966
+ pipeMaterial: "abs" | "pvc" | "cast-iron";
2967
+ armLengthM: number;
2968
+ type: "pipe-trap";
2969
+ name?: string | undefined;
2970
+ camera?: {
2971
+ position: [number, number, number];
2972
+ target: [number, number, number];
2973
+ mode: "perspective" | "orthographic";
2974
+ fov?: number | undefined;
2975
+ zoom?: number | undefined;
2976
+ } | undefined;
2977
+ }>): void;
49
2978
  /**
50
2979
  * The sculpted ground moved: every node the terrain *supports* must re-elevate.
51
2980
  *