@pascal-app/core 0.9.1 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +17 -10
  2. package/dist/events/bus.d.ts +49 -2
  3. package/dist/events/bus.d.ts.map +1 -1
  4. package/dist/hooks/scene-registry/item-clip-registry.d.ts +18 -0
  5. package/dist/hooks/scene-registry/item-clip-registry.d.ts.map +1 -0
  6. package/dist/hooks/scene-registry/item-clip-registry.js +10 -0
  7. package/dist/hooks/scene-registry/scene-registry.d.ts +8 -1
  8. package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
  9. package/dist/hooks/scene-registry/scene-registry.js +27 -1
  10. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +17 -1
  11. package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
  12. package/dist/hooks/spatial-grid/floor-placed-elevation.js +61 -8
  13. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +135 -28
  14. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  15. package/dist/hooks/spatial-grid/spatial-grid-manager.js +427 -271
  16. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +46 -1
  17. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  18. package/dist/hooks/spatial-grid/spatial-grid-sync.js +208 -9
  19. package/dist/hooks/spatial-grid/support-host-id.d.ts +3 -0
  20. package/dist/hooks/spatial-grid/support-host-id.d.ts.map +1 -0
  21. package/dist/hooks/spatial-grid/support-host-id.js +2 -0
  22. package/dist/hooks/spatial-grid/support-host-patch.d.ts +51 -0
  23. package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -0
  24. package/dist/hooks/spatial-grid/support-host-patch.js +164 -0
  25. package/dist/index.d.ts +33 -11
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +32 -10
  28. package/dist/lib/level-name.d.ts +4 -0
  29. package/dist/lib/level-name.d.ts.map +1 -0
  30. package/dist/lib/level-name.js +10 -0
  31. package/dist/lib/measurement-geometry.d.ts +23 -0
  32. package/dist/lib/measurement-geometry.d.ts.map +1 -0
  33. package/dist/lib/measurement-geometry.js +249 -0
  34. package/dist/lib/polygon-geometry.d.ts +0 -1
  35. package/dist/lib/polygon-geometry.d.ts.map +1 -1
  36. package/dist/lib/polygon-geometry.js +0 -18
  37. package/dist/lib/selection-proxy.d.ts +4 -0
  38. package/dist/lib/selection-proxy.d.ts.map +1 -0
  39. package/dist/lib/selection-proxy.js +12 -0
  40. package/dist/lib/slab-polygon.d.ts +31 -2
  41. package/dist/lib/slab-polygon.d.ts.map +1 -1
  42. package/dist/lib/slab-polygon.js +557 -31
  43. package/dist/lib/slots.d.ts +14 -0
  44. package/dist/lib/slots.d.ts.map +1 -0
  45. package/dist/lib/slots.js +26 -0
  46. package/dist/lib/space-detection.d.ts +40 -6
  47. package/dist/lib/space-detection.d.ts.map +1 -1
  48. package/dist/lib/space-detection.js +574 -192
  49. package/dist/lib/terrain-brush.d.ts +163 -0
  50. package/dist/lib/terrain-brush.d.ts.map +1 -0
  51. package/dist/lib/terrain-brush.js +359 -0
  52. package/dist/lib/terrain-codec.d.ts +51 -0
  53. package/dist/lib/terrain-codec.d.ts.map +1 -0
  54. package/dist/lib/terrain-codec.js +167 -0
  55. package/dist/lib/terrain-field.d.ts +150 -0
  56. package/dist/lib/terrain-field.d.ts.map +1 -0
  57. package/dist/lib/terrain-field.js +248 -0
  58. package/dist/lib/terrain-raycast.d.ts +44 -0
  59. package/dist/lib/terrain-raycast.d.ts.map +1 -0
  60. package/dist/lib/terrain-raycast.js +188 -0
  61. package/dist/lib/terrain-source.d.ts +60 -0
  62. package/dist/lib/terrain-source.d.ts.map +1 -0
  63. package/dist/lib/terrain-source.js +90 -0
  64. package/dist/lib/terrain-support.d.ts +60 -0
  65. package/dist/lib/terrain-support.d.ts.map +1 -0
  66. package/dist/lib/terrain-support.js +150 -0
  67. package/dist/lib/wall-distance.d.ts +60 -0
  68. package/dist/lib/wall-distance.d.ts.map +1 -0
  69. package/dist/lib/wall-distance.js +85 -0
  70. package/dist/lib/zone-quantities.d.ts +21 -0
  71. package/dist/lib/zone-quantities.d.ts.map +1 -0
  72. package/dist/lib/zone-quantities.js +428 -0
  73. package/dist/material-library.d.ts +28 -1
  74. package/dist/material-library.d.ts.map +1 -1
  75. package/dist/material-library.js +2233 -441
  76. package/dist/registry/handles.d.ts +91 -3
  77. package/dist/registry/handles.d.ts.map +1 -1
  78. package/dist/registry/index.d.ts +3 -3
  79. package/dist/registry/index.d.ts.map +1 -1
  80. package/dist/registry/index.js +1 -1
  81. package/dist/registry/registry.d.ts +46 -3
  82. package/dist/registry/registry.d.ts.map +1 -1
  83. package/dist/registry/registry.js +82 -1
  84. package/dist/registry/subtree.d.ts.map +1 -1
  85. package/dist/registry/subtree.js +8 -1
  86. package/dist/registry/types.d.ts +781 -39
  87. package/dist/registry/types.d.ts.map +1 -1
  88. package/dist/schema/index.d.ts +27 -8
  89. package/dist/schema/index.d.ts.map +1 -1
  90. package/dist/schema/index.js +23 -6
  91. package/dist/schema/material.d.ts +3 -2
  92. package/dist/schema/material.d.ts.map +1 -1
  93. package/dist/schema/material.js +7 -5
  94. package/dist/schema/nodes/box-vent.d.ts +2 -2
  95. package/dist/schema/nodes/cabinet.d.ts +536 -0
  96. package/dist/schema/nodes/cabinet.d.ts.map +1 -0
  97. package/dist/schema/nodes/cabinet.js +139 -0
  98. package/dist/schema/nodes/ceiling.d.ts +4 -3
  99. package/dist/schema/nodes/ceiling.d.ts.map +1 -1
  100. package/dist/schema/nodes/ceiling.js +11 -1
  101. package/dist/schema/nodes/chimney.d.ts +4 -4
  102. package/dist/schema/nodes/column.d.ts +4 -2
  103. package/dist/schema/nodes/column.d.ts.map +1 -1
  104. package/dist/schema/nodes/column.js +5 -0
  105. package/dist/schema/nodes/construction-dimension.d.ts +195 -0
  106. package/dist/schema/nodes/construction-dimension.d.ts.map +1 -0
  107. package/dist/schema/nodes/construction-dimension.js +151 -0
  108. package/dist/schema/nodes/cupola.d.ts +2 -2
  109. package/dist/schema/nodes/door.d.ts +42 -5
  110. package/dist/schema/nodes/door.d.ts.map +1 -1
  111. package/dist/schema/nodes/door.js +32 -0
  112. package/dist/schema/nodes/dormer.d.ts +8 -8
  113. package/dist/schema/nodes/dormer.js +1 -1
  114. package/dist/schema/nodes/downspout.d.ts +2 -2
  115. package/dist/schema/nodes/duct-fitting.d.ts +91 -0
  116. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -0
  117. package/dist/schema/nodes/duct-fitting.js +92 -0
  118. package/dist/schema/nodes/duct-segment.d.ts +61 -0
  119. package/dist/schema/nodes/duct-segment.d.ts.map +1 -0
  120. package/dist/schema/nodes/duct-segment.js +73 -0
  121. package/dist/schema/nodes/duct-terminal.d.ts +58 -0
  122. package/dist/schema/nodes/duct-terminal.d.ts.map +1 -0
  123. package/dist/schema/nodes/duct-terminal.js +53 -0
  124. package/dist/schema/nodes/elevator.d.ts +3 -2
  125. package/dist/schema/nodes/elevator.d.ts.map +1 -1
  126. package/dist/schema/nodes/elevator.js +3 -0
  127. package/dist/schema/nodes/eyebrow-vent.d.ts +2 -2
  128. package/dist/schema/nodes/fence.d.ts +20 -2
  129. package/dist/schema/nodes/fence.d.ts.map +1 -1
  130. package/dist/schema/nodes/fence.js +33 -2
  131. package/dist/schema/nodes/gutter.d.ts +2 -2
  132. package/dist/schema/nodes/hvac-equipment.d.ts +64 -0
  133. package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -0
  134. package/dist/schema/nodes/hvac-equipment.js +57 -0
  135. package/dist/schema/nodes/item.d.ts +9 -0
  136. package/dist/schema/nodes/item.d.ts.map +1 -1
  137. package/dist/schema/nodes/item.js +24 -0
  138. package/dist/schema/nodes/level.d.ts +2 -1
  139. package/dist/schema/nodes/level.d.ts.map +1 -1
  140. package/dist/schema/nodes/level.js +12 -31
  141. package/dist/schema/nodes/lineset.d.ts +42 -0
  142. package/dist/schema/nodes/lineset.d.ts.map +1 -0
  143. package/dist/schema/nodes/lineset.js +38 -0
  144. package/dist/schema/nodes/liquid-line.d.ts +34 -0
  145. package/dist/schema/nodes/liquid-line.d.ts.map +1 -0
  146. package/dist/schema/nodes/liquid-line.js +24 -0
  147. package/dist/schema/nodes/measurement.d.ts +306 -0
  148. package/dist/schema/nodes/measurement.d.ts.map +1 -0
  149. package/dist/schema/nodes/measurement.js +87 -0
  150. package/dist/schema/nodes/pipe-fitting.d.ts +56 -0
  151. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -0
  152. package/dist/schema/nodes/pipe-fitting.js +45 -0
  153. package/dist/schema/nodes/pipe-segment.d.ts +48 -0
  154. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -0
  155. package/dist/schema/nodes/pipe-segment.js +36 -0
  156. package/dist/schema/nodes/pipe-trap.d.ts +43 -0
  157. package/dist/schema/nodes/pipe-trap.d.ts.map +1 -0
  158. package/dist/schema/nodes/pipe-trap.js +36 -0
  159. package/dist/schema/nodes/ridge-vent.d.ts +18 -3
  160. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
  161. package/dist/schema/nodes/ridge-vent.js +221 -3
  162. package/dist/schema/nodes/roof-segment-shape.d.ts +90 -0
  163. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -0
  164. package/dist/schema/nodes/roof-segment-shape.js +318 -0
  165. package/dist/schema/nodes/roof-segment-walls.d.ts +101 -0
  166. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -0
  167. package/dist/schema/nodes/roof-segment-walls.js +330 -0
  168. package/dist/schema/nodes/roof-segment.d.ts +84 -8
  169. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  170. package/dist/schema/nodes/roof-segment.js +290 -5
  171. package/dist/schema/nodes/roof.d.ts +8 -8
  172. package/dist/schema/nodes/shelf.d.ts +4 -2
  173. package/dist/schema/nodes/shelf.d.ts.map +1 -1
  174. package/dist/schema/nodes/shelf.js +8 -0
  175. package/dist/schema/nodes/site.d.ts +9 -0
  176. package/dist/schema/nodes/site.d.ts.map +1 -1
  177. package/dist/schema/nodes/site.js +8 -6
  178. package/dist/schema/nodes/skylight.d.ts +10 -10
  179. package/dist/schema/nodes/slab.d.ts +8 -2
  180. package/dist/schema/nodes/slab.d.ts.map +1 -1
  181. package/dist/schema/nodes/slab.js +18 -2
  182. package/dist/schema/nodes/solar-panel.d.ts +4 -4
  183. package/dist/schema/nodes/spawn.d.ts +1 -0
  184. package/dist/schema/nodes/spawn.d.ts.map +1 -1
  185. package/dist/schema/nodes/spawn.js +2 -0
  186. package/dist/schema/nodes/stair-segment.d.ts +4 -4
  187. package/dist/schema/nodes/stair.d.ts +16 -13
  188. package/dist/schema/nodes/stair.d.ts.map +1 -1
  189. package/dist/schema/nodes/stair.js +11 -1
  190. package/dist/schema/nodes/structural-grid.d.ts +27 -0
  191. package/dist/schema/nodes/structural-grid.d.ts.map +1 -0
  192. package/dist/schema/nodes/structural-grid.js +17 -0
  193. package/dist/schema/nodes/turbine-vent.d.ts +2 -2
  194. package/dist/schema/nodes/wall.d.ts +248 -6
  195. package/dist/schema/nodes/wall.d.ts.map +1 -1
  196. package/dist/schema/nodes/wall.js +266 -0
  197. package/dist/schema/nodes/window.d.ts +40 -3
  198. package/dist/schema/nodes/window.d.ts.map +1 -1
  199. package/dist/schema/nodes/window.js +30 -0
  200. package/dist/schema/nodes/zone.d.ts +22 -0
  201. package/dist/schema/nodes/zone.d.ts.map +1 -1
  202. package/dist/schema/nodes/zone.js +21 -0
  203. package/dist/schema/scene-material.d.ts +41 -0
  204. package/dist/schema/scene-material.d.ts.map +1 -0
  205. package/dist/schema/scene-material.js +9 -0
  206. package/dist/schema/terrain.d.ts +28 -0
  207. package/dist/schema/terrain.d.ts.map +1 -0
  208. package/dist/schema/terrain.js +30 -0
  209. package/dist/schema/types.d.ts +1300 -97
  210. package/dist/schema/types.d.ts.map +1 -1
  211. package/dist/schema/types.js +27 -0
  212. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts +80 -0
  213. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts.map +1 -0
  214. package/dist/services/__fixtures__/wall-plane-top-boundary-repro.js +89 -0
  215. package/dist/services/alignment-anchors.d.ts.map +1 -1
  216. package/dist/services/alignment-anchors.js +30 -1
  217. package/dist/services/alignment.d.ts +5 -0
  218. package/dist/services/alignment.d.ts.map +1 -1
  219. package/dist/services/alignment.js +2 -0
  220. package/dist/services/hosting.d.ts +8 -0
  221. package/dist/services/hosting.d.ts.map +1 -1
  222. package/dist/services/hosting.js +13 -4
  223. package/dist/services/index.d.ts +9 -2
  224. package/dist/services/index.d.ts.map +1 -1
  225. package/dist/services/index.js +9 -2
  226. package/dist/services/level-height.d.ts +27 -0
  227. package/dist/services/level-height.d.ts.map +1 -0
  228. package/dist/services/level-height.js +94 -0
  229. package/dist/services/opening-guides.d.ts +141 -0
  230. package/dist/services/opening-guides.d.ts.map +1 -0
  231. package/dist/services/opening-guides.js +267 -0
  232. package/dist/services/port-connectivity.d.ts +115 -0
  233. package/dist/services/port-connectivity.d.ts.map +1 -0
  234. package/dist/services/port-connectivity.js +300 -0
  235. package/dist/services/riser-diagram.d.ts +40 -0
  236. package/dist/services/riser-diagram.d.ts.map +1 -0
  237. package/dist/services/riser-diagram.js +110 -0
  238. package/dist/services/snap.d.ts +9 -1
  239. package/dist/services/snap.d.ts.map +1 -1
  240. package/dist/services/snap.js +21 -1
  241. package/dist/services/storey.d.ts +103 -0
  242. package/dist/services/storey.d.ts.map +1 -0
  243. package/dist/services/storey.js +296 -0
  244. package/dist/services/system-graph.d.ts +30 -0
  245. package/dist/services/system-graph.d.ts.map +1 -0
  246. package/dist/services/system-graph.js +164 -0
  247. package/dist/services/validate-dwv.d.ts +32 -0
  248. package/dist/services/validate-dwv.d.ts.map +1 -0
  249. package/dist/services/validate-dwv.js +118 -0
  250. package/dist/store/actions/node-actions.d.ts.map +1 -1
  251. package/dist/store/actions/node-actions.js +141 -4
  252. package/dist/store/history-control.d.ts +31 -0
  253. package/dist/store/history-control.d.ts.map +1 -1
  254. package/dist/store/history-control.js +130 -0
  255. package/dist/store/use-live-terrain.d.ts +65 -0
  256. package/dist/store/use-live-terrain.d.ts.map +1 -0
  257. package/dist/store/use-live-terrain.js +31 -0
  258. package/dist/store/use-live-transforms.d.ts +8 -0
  259. package/dist/store/use-live-transforms.d.ts.map +1 -1
  260. package/dist/store/use-scene.d.ts +47 -3
  261. package/dist/store/use-scene.d.ts.map +1 -1
  262. package/dist/store/use-scene.js +992 -55
  263. package/dist/systems/elevator/elevator-opening-system.d.ts +1 -0
  264. package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -1
  265. package/dist/systems/elevator/elevator-opening-system.js +27 -21
  266. package/dist/systems/elevator/elevator-service.d.ts +0 -2
  267. package/dist/systems/elevator/elevator-service.d.ts.map +1 -1
  268. package/dist/systems/elevator/elevator-service.js +2 -24
  269. package/dist/systems/fence/fence-centerline.d.ts +12 -0
  270. package/dist/systems/fence/fence-centerline.d.ts.map +1 -0
  271. package/dist/systems/fence/fence-centerline.js +37 -0
  272. package/dist/systems/fence/fence-spline.d.ts +39 -0
  273. package/dist/systems/fence/fence-spline.d.ts.map +1 -0
  274. package/dist/systems/fence/fence-spline.js +196 -0
  275. package/dist/systems/slab/slab-placement.d.ts +11 -0
  276. package/dist/systems/slab/slab-placement.d.ts.map +1 -0
  277. package/dist/systems/slab/slab-placement.js +14 -0
  278. package/dist/systems/slab/slab-support.d.ts +137 -0
  279. package/dist/systems/slab/slab-support.d.ts.map +1 -0
  280. package/dist/systems/slab/slab-support.js +557 -0
  281. package/dist/systems/stair/stair-footprint.d.ts.map +1 -1
  282. package/dist/systems/stair/stair-footprint.js +21 -11
  283. package/dist/systems/stair/stair-opening-preview.d.ts +1300 -505
  284. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  285. package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
  286. package/dist/systems/stair/stair-opening-sync.js +19 -33
  287. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
  288. package/dist/systems/stair/stair-opening-system.js +32 -4
  289. package/dist/systems/stair/stair-rise.d.ts +22 -0
  290. package/dist/systems/stair/stair-rise.d.ts.map +1 -0
  291. package/dist/systems/stair/stair-rise.js +79 -0
  292. package/dist/systems/wall/wall-curve.d.ts +10 -0
  293. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  294. package/dist/systems/wall/wall-curve.js +1 -1
  295. package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
  296. package/dist/systems/wall/wall-mitering.js +44 -8
  297. package/dist/systems/wall/wall-top.d.ts +40 -0
  298. package/dist/systems/wall/wall-top.d.ts.map +1 -0
  299. package/dist/systems/wall/wall-top.js +46 -0
  300. package/dist/utils/clone-scene-graph.d.ts +1 -0
  301. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  302. package/dist/utils/clone-scene-graph.js +56 -5
  303. package/dist/utils/heal-scene-graph.d.ts +18 -0
  304. package/dist/utils/heal-scene-graph.d.ts.map +1 -0
  305. package/dist/utils/heal-scene-graph.js +106 -0
  306. package/dist/validation/validate-build-json.d.ts +3 -0
  307. package/dist/validation/validate-build-json.d.ts.map +1 -1
  308. package/dist/validation/validate-build-json.js +90 -5
  309. package/package.json +4 -4
  310. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +0 -2
  311. package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +0 -1
  312. package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +0 -273
  313. package/dist/lib/space-detection-pause.test.d.ts +0 -2
  314. package/dist/lib/space-detection-pause.test.d.ts.map +0 -1
  315. package/dist/lib/space-detection-pause.test.js +0 -42
  316. package/dist/lib/space-detection.test.d.ts +0 -2
  317. package/dist/lib/space-detection.test.d.ts.map +0 -1
  318. package/dist/lib/space-detection.test.js +0 -77
  319. package/dist/registry/registry.test.d.ts +0 -2
  320. package/dist/registry/registry.test.d.ts.map +0 -1
  321. package/dist/registry/registry.test.js +0 -183
  322. package/dist/registry/relations-resolver.test.d.ts +0 -2
  323. package/dist/registry/relations-resolver.test.d.ts.map +0 -1
  324. package/dist/registry/relations-resolver.test.js +0 -183
  325. package/dist/registry/scene-api.test.d.ts +0 -2
  326. package/dist/registry/scene-api.test.d.ts.map +0 -1
  327. package/dist/registry/scene-api.test.js +0 -183
  328. package/dist/registry/subtree.test.d.ts +0 -2
  329. package/dist/registry/subtree.test.d.ts.map +0 -1
  330. package/dist/registry/subtree.test.js +0 -133
  331. package/dist/schema/asset-url.test.d.ts +0 -2
  332. package/dist/schema/asset-url.test.d.ts.map +0 -1
  333. package/dist/schema/asset-url.test.js +0 -134
  334. package/dist/services/alignment-anchors.test.d.ts +0 -2
  335. package/dist/services/alignment-anchors.test.d.ts.map +0 -1
  336. package/dist/services/alignment-anchors.test.js +0 -383
  337. package/dist/services/alignment.test.d.ts +0 -2
  338. package/dist/services/alignment.test.d.ts.map +0 -1
  339. package/dist/services/alignment.test.js +0 -92
  340. package/dist/services/drag-session.test.d.ts +0 -2
  341. package/dist/services/drag-session.test.d.ts.map +0 -1
  342. package/dist/services/drag-session.test.js +0 -219
  343. package/dist/services/hosting.test.d.ts +0 -2
  344. package/dist/services/hosting.test.d.ts.map +0 -1
  345. package/dist/services/hosting.test.js +0 -199
  346. package/dist/services/movement.test.d.ts +0 -2
  347. package/dist/services/movement.test.d.ts.map +0 -1
  348. package/dist/services/movement.test.js +0 -133
  349. package/dist/services/single-undo-dance.test.d.ts +0 -2
  350. package/dist/services/single-undo-dance.test.d.ts.map +0 -1
  351. package/dist/services/single-undo-dance.test.js +0 -210
  352. package/dist/services/snap.test.d.ts +0 -2
  353. package/dist/services/snap.test.d.ts.map +0 -1
  354. package/dist/services/snap.test.js +0 -95
  355. package/dist/store/actions/node-mutation-sanitize.test.d.ts +0 -2
  356. package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +0 -1
  357. package/dist/store/actions/node-mutation-sanitize.test.js +0 -147
  358. package/dist/store/actions/reparent.test.d.ts +0 -2
  359. package/dist/store/actions/reparent.test.d.ts.map +0 -1
  360. package/dist/store/actions/reparent.test.js +0 -212
  361. package/dist/store/use-scene-elevator-migration.test.d.ts +0 -2
  362. package/dist/store/use-scene-elevator-migration.test.d.ts.map +0 -1
  363. package/dist/store/use-scene-elevator-migration.test.js +0 -109
  364. package/dist/systems/elevator/elevator-opening-sync.test.d.ts +0 -2
  365. package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +0 -1
  366. package/dist/systems/elevator/elevator-opening-sync.test.js +0 -146
  367. package/dist/systems/elevator/elevator-runtime.test.d.ts +0 -2
  368. package/dist/systems/elevator/elevator-runtime.test.d.ts.map +0 -1
  369. package/dist/systems/elevator/elevator-runtime.test.js +0 -64
  370. package/dist/systems/stair/stair-opening-preview.test.d.ts +0 -2
  371. package/dist/systems/stair/stair-opening-preview.test.d.ts.map +0 -1
  372. package/dist/systems/stair/stair-opening-preview.test.js +0 -80
  373. package/dist/systems/stair/stair-opening-sync.test.d.ts +0 -2
  374. package/dist/systems/stair/stair-opening-sync.test.d.ts.map +0 -1
  375. package/dist/systems/stair/stair-opening-sync.test.js +0 -446
  376. package/dist/utils/clone-scene-graph.test.d.ts +0 -2
  377. package/dist/utils/clone-scene-graph.test.d.ts.map +0 -1
  378. package/dist/utils/clone-scene-graph.test.js +0 -59
@@ -1,4 +1,19 @@
1
- import { AnyNode as AnyNodeSchema, getEffectiveWallSurfaceMaterial, getWallSurfaceMaterialSignature, } from '../../schema';
1
+ import { nodeRegistry } from '../../registry/registry';
2
+ import { AnyNode as AnyNodeSchema, createDefaultRidgeVentsForSegment, getEffectiveWallSurfaceMaterial, getWallSurfaceMaterialSignature, isAutoRidgeVentEnabled, isDefaultRidgeVentNode, } from '../../schema';
3
+ const DEFAULT_RIDGE_VENT_REFRESH_FIELDS = new Set([
4
+ 'roofType',
5
+ 'width',
6
+ 'depth',
7
+ 'pitch',
8
+ 'overhang',
9
+ 'wallThickness',
10
+ 'shingleThickness',
11
+ 'gambrelLowerWidthRatio',
12
+ 'mansardSteepWidthRatio',
13
+ 'dutchHipWidthRatio',
14
+ 'dutchWaistLengthRatio',
15
+ 'dutchGabletRake',
16
+ ]);
2
17
  const NUMBER_FORMAT_BOUNDS = {
3
18
  safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],
4
19
  int32: [-2147483648, 2147483647],
@@ -328,8 +343,21 @@ function parseCreatedNode(node, parentId) {
328
343
  warnSanitizedNodeMutation('create', node.id, sanitized.issues);
329
344
  return sanitized.value;
330
345
  }
346
+ // An explicit `key: undefined` in update data REMOVES the key: optional
347
+ // fields like wall.height encode a mode by their absence (absent =
348
+ // plane-bound top), and zod's safeParse echoes explicit-undefined keys, so
349
+ // a plain spread would leave a lingering own key that breaks `'height' in
350
+ // node` checks.
351
+ function mergeNodeUpdate(currentNode, patch) {
352
+ const merged = { ...currentNode, ...patch };
353
+ for (const key of Object.keys(patch)) {
354
+ if (patch[key] === undefined)
355
+ delete merged[key];
356
+ }
357
+ return merged;
358
+ }
331
359
  function parseUpdatedNode(currentNode, data) {
332
- const candidate = { ...currentNode, ...data };
360
+ const candidate = mergeNodeUpdate(currentNode, data);
333
361
  const parsed = AnyNodeSchema.safeParse(candidate);
334
362
  if (parsed.success)
335
363
  return parsed.data;
@@ -339,7 +367,35 @@ function parseUpdatedNode(currentNode, data) {
339
367
  return candidate;
340
368
  }
341
369
  warnSanitizedNodeMutation('update', currentNode.id, sanitized.issues);
342
- return { ...currentNode, ...sanitized.value };
370
+ return mergeNodeUpdate(currentNode, sanitized.value);
371
+ }
372
+ function shouldRefreshDefaultRidgeVents(data) {
373
+ return Object.keys(data).some((key) => DEFAULT_RIDGE_VENT_REFRESH_FIELDS.has(key));
374
+ }
375
+ function refreshDefaultRidgeVentsForSegment(nextNodes, segment) {
376
+ const childIds = Array.isArray(segment.children) ? segment.children : [];
377
+ if (!isAutoRidgeVentEnabled(segment, nextNodes))
378
+ return [];
379
+ const defaultIds = childIds.filter((childId) => isDefaultRidgeVentNode(nextNodes[childId], segment.id));
380
+ const defaultIdSet = new Set(defaultIds);
381
+ for (const id of defaultIds) {
382
+ delete nextNodes[id];
383
+ }
384
+ const nextVents = createDefaultRidgeVentsForSegment(segment);
385
+ for (const vent of nextVents) {
386
+ nextNodes[vent.id] = {
387
+ ...vent,
388
+ parentId: segment.id,
389
+ };
390
+ }
391
+ nextNodes[segment.id] = {
392
+ ...segment,
393
+ children: [
394
+ ...childIds.filter((childId) => !defaultIdSet.has(childId)),
395
+ ...nextVents.map((vent) => vent.id),
396
+ ],
397
+ };
398
+ return nextVents.map((vent) => vent.id);
343
399
  }
344
400
  // Track pending RAF for updateNodesAction to prevent multiple queued callbacks
345
401
  let pendingRafId = null;
@@ -370,7 +426,10 @@ function areWallStylesCompatible(a, b) {
370
426
  return ((a.parentId ?? null) === (b.parentId ?? null) &&
371
427
  Math.abs((a.curveOffset ?? 0) - (b.curveOffset ?? 0)) <= 1e-6 &&
372
428
  Math.abs((a.thickness ?? 0.2) - (b.thickness ?? 0.2)) <= 1e-6 &&
373
- Math.abs((a.height ?? 2.5) - (b.height ?? 2.5)) <= 1e-6 &&
429
+ // Absent height means plane-bound (follows the storey), which must never
430
+ // merge with an explicit height — even one that currently matches the plane.
431
+ (a.height == null) === (b.height == null) &&
432
+ Math.abs((a.height ?? 0) - (b.height ?? 0)) <= 1e-6 &&
374
433
  aInterior === bInterior &&
375
434
  aExterior === bExterior &&
376
435
  a.frontSide === b.frontSide &&
@@ -575,6 +634,11 @@ export const applyNodeChangesAction = (set, get, changes) => {
575
634
  }
576
635
  }
577
636
  nextNodes[id] = updatedNode;
637
+ if (updatedNode.type === 'roof-segment' && shouldRefreshDefaultRidgeVents(data)) {
638
+ for (const ventId of refreshDefaultRidgeVentsForSegment(nextNodes, updatedNode)) {
639
+ nodesToMarkDirty.add(ventId);
640
+ }
641
+ }
578
642
  nodesToMarkDirty.add(id);
579
643
  }
580
644
  for (const { node, parentId } of createOps) {
@@ -659,6 +723,7 @@ export const updateNodesAction = (set, get, updates) => {
659
723
  if (get().readOnly)
660
724
  return;
661
725
  const parentsToUpdate = new Set();
726
+ const extraNodesToUpdate = new Set();
662
727
  set((state) => {
663
728
  const nextNodes = { ...state.nodes };
664
729
  for (const { id, data } of updates) {
@@ -702,6 +767,11 @@ export const updateNodesAction = (set, get, updates) => {
702
767
  }
703
768
  // Apply the update
704
769
  nextNodes[id] = updatedNode;
770
+ if (updatedNode.type === 'roof-segment' && shouldRefreshDefaultRidgeVents(data)) {
771
+ for (const ventId of refreshDefaultRidgeVentsForSegment(nextNodes, updatedNode)) {
772
+ extraNodesToUpdate.add(ventId);
773
+ }
774
+ }
705
775
  }
706
776
  return { nodes: nextNodes };
707
777
  });
@@ -712,6 +782,9 @@ export const updateNodesAction = (set, get, updates) => {
712
782
  for (const pId of parentsToUpdate) {
713
783
  pendingUpdates.add(pId);
714
784
  }
785
+ for (const id of extraNodesToUpdate) {
786
+ pendingUpdates.add(id);
787
+ }
715
788
  if (pendingRafId !== null) {
716
789
  cancelAnimationFrame(pendingRafId);
717
790
  }
@@ -728,6 +801,7 @@ export const deleteNodesAction = (set, get, ids) => {
728
801
  return;
729
802
  const parentsToMarkDirty = new Set();
730
803
  const nodesToMarkDirty = new Set();
804
+ const deletedIds = new Set();
731
805
  const mergePlans = buildWallMergePlans(get().nodes, ids);
732
806
  set((state) => {
733
807
  const nextNodes = { ...state.nodes };
@@ -741,6 +815,13 @@ export const deleteNodesAction = (set, get, ids) => {
741
815
  return;
742
816
  allIds.add(id);
743
817
  const node = nextNodes[id];
818
+ const cascadeDeletes = node
819
+ ? nodeRegistry.get(node.type)?.parametrics?.onDeleteCascade?.(node, nextNodes, allIds)
820
+ : null;
821
+ if (cascadeDeletes) {
822
+ for (const companionId of cascadeDeletes)
823
+ collect(companionId);
824
+ }
744
825
  if (node && 'children' in node) {
745
826
  for (const cid of node.children)
746
827
  collect(cid);
@@ -751,6 +832,29 @@ export const deleteNodesAction = (set, get, ids) => {
751
832
  for (const plan of mergePlans) {
752
833
  allIds.add(plan.secondaryWallId);
753
834
  }
835
+ for (const id of allIds)
836
+ deletedIds.add(id);
837
+ // Let each deleted kind undo what it imposed on its neighbours (e.g. an
838
+ // auto-inserted elbow re-extends the duct runs it trimmed back onto the
839
+ // corner it replaced). Read against pre-deletion `nextNodes`; skip
840
+ // patches that target a node also being deleted.
841
+ for (const id of allIds) {
842
+ const node = nextNodes[id];
843
+ if (!node)
844
+ continue;
845
+ const onDelete = nodeRegistry.get(node.type)?.parametrics?.onDelete;
846
+ if (!onDelete)
847
+ continue;
848
+ for (const { id: targetId, data } of onDelete(node, nextNodes)) {
849
+ if (allIds.has(targetId))
850
+ continue;
851
+ const target = nextNodes[targetId];
852
+ if (!target)
853
+ continue;
854
+ nextNodes[targetId] = { ...target, ...data };
855
+ nodesToMarkDirty.add(targetId);
856
+ }
857
+ }
754
858
  for (const plan of mergePlans) {
755
859
  const primaryWall = nextNodes[plan.primaryWallId];
756
860
  if (!(primaryWall && primaryWall.type === 'wall') || allIds.has(plan.primaryWallId)) {
@@ -773,6 +877,34 @@ export const deleteNodesAction = (set, get, ids) => {
773
877
  nodesToMarkDirty.add(update.id);
774
878
  }
775
879
  }
880
+ // Deleting a slab strips `supportSlabId` / `deckSlabId` references from
881
+ // surviving nodes in the same undo commit (mirrors the collectionIds
882
+ // cleanup below), so those nodes re-elect their support / re-derive
883
+ // their rise. Deletion is the ONLY writer — a host merely reshaped away
884
+ // keeps the field and the read path falls back, letting hosting resume
885
+ // if the slab returns.
886
+ const deletedSlabIds = new Set();
887
+ for (const id of allIds) {
888
+ if (nextNodes[id]?.type === 'slab')
889
+ deletedSlabIds.add(id);
890
+ }
891
+ if (deletedSlabIds.size > 0) {
892
+ for (const [nodeId, node] of Object.entries(nextNodes)) {
893
+ if (allIds.has(nodeId))
894
+ continue;
895
+ const patch = {};
896
+ const hostId = node.supportSlabId;
897
+ if (hostId && deletedSlabIds.has(hostId))
898
+ patch.supportSlabId = undefined;
899
+ const deckId = node.deckSlabId;
900
+ if (deckId && deletedSlabIds.has(deckId))
901
+ patch.deckSlabId = undefined;
902
+ if (Object.keys(patch).length > 0) {
903
+ nextNodes[nodeId] = { ...node, ...patch };
904
+ nodesToMarkDirty.add(nodeId);
905
+ }
906
+ }
907
+ }
776
908
  for (const id of allIds) {
777
909
  const node = nextNodes[id];
778
910
  if (!node)
@@ -805,6 +937,11 @@ export const deleteNodesAction = (set, get, ids) => {
805
937
  }
806
938
  return { nodes: nextNodes, rootNodeIds: nextRootIds, collections: nextCollections };
807
939
  });
940
+ // Deleted ids must leave the dirty set: every consumer skips missing
941
+ // nodes without clearing them, so a mark on a deleted node would sit in
942
+ // the set (and defeat the consumers' empty-set early exit) forever.
943
+ for (const id of deletedIds)
944
+ get().clearDirty(id);
808
945
  // Mark affected nodes dirty: parents of deleted nodes and their remaining children
809
946
  // (e.g. deleting a slab affects sibling walls via level elevation changes)
810
947
  parentsToMarkDirty.forEach((parentId) => {
@@ -1,3 +1,20 @@
1
+ import type { Collection, CollectionId } from '../schema/collections';
2
+ import type { SceneMaterial, SceneMaterialId } from '../schema/scene-material';
3
+ import type { AnyNode, AnyNodeId } from '../schema/types';
4
+ export type SceneSnapshot = {
5
+ nodes: Record<AnyNodeId, AnyNode>;
6
+ rootNodeIds: AnyNodeId[];
7
+ collections: Record<CollectionId, Collection>;
8
+ materials: Record<SceneMaterialId, SceneMaterial>;
9
+ installedPlugins: string[];
10
+ };
11
+ export type SceneCommitOrigin = 'local' | 'load' | 'host';
12
+ export type SceneCommit = {
13
+ origin: SceneCommitOrigin;
14
+ before: SceneSnapshot;
15
+ current: SceneSnapshot;
16
+ };
17
+ export type SceneCommitListener = (commit: SceneCommit) => void;
1
18
  type TemporalStoreLike = {
2
19
  temporal: {
3
20
  getState(): {
@@ -6,9 +23,23 @@ type TemporalStoreLike = {
6
23
  };
7
24
  };
8
25
  };
26
+ type TemporalHistoryStoreLike<TPastState> = {
27
+ temporal: {
28
+ getState(): {
29
+ pastStates: TPastState[];
30
+ };
31
+ setState(state: {
32
+ pastStates: TPastState[];
33
+ }): void;
34
+ };
35
+ };
36
+ export declare function areSceneSnapshotsEqual(left: SceneSnapshot, right: SceneSnapshot): boolean;
37
+ export declare function subscribeSceneCommits(listener: SceneCommitListener): () => void;
38
+ export declare function notifySceneCommit(commit: SceneCommit): void;
9
39
  export declare function pauseSceneHistory(sceneStore: TemporalStoreLike): void;
10
40
  export declare function resumeSceneHistory(sceneStore: TemporalStoreLike): void;
11
41
  export declare function getSceneHistoryPauseDepth(): number;
12
42
  export declare function resetSceneHistoryPauseDepth(): void;
43
+ export declare function runAsSingleSceneHistoryStep<TPastState, TResult>(sceneStore: TemporalHistoryStoreLike<TPastState>, run: () => TResult): TResult;
13
44
  export {};
14
45
  //# sourceMappingURL=history-control.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"history-control.d.ts","sourceRoot":"","sources":["../../src/store/history-control.ts"],"names":[],"mappings":"AAEA,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE;QACR,QAAQ,IAAI;YACV,KAAK,IAAI,IAAI,CAAA;YACb,MAAM,IAAI,IAAI,CAAA;SACf,CAAA;KACF,CAAA;CACF,CAAA;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAKrE;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAStE;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
1
+ {"version":3,"file":"history-control.d.ts","sourceRoot":"","sources":["../../src/store/history-control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAIzD,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACjC,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,WAAW,EAAE,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAA;IAC7C,SAAS,EAAE,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;IACjD,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;AAEzD,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,iBAAiB,CAAA;IACzB,MAAM,EAAE,aAAa,CAAA;IACrB,OAAO,EAAE,aAAa,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;AAE/D,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE;QACR,QAAQ,IAAI;YACV,KAAK,IAAI,IAAI,CAAA;YACb,MAAM,IAAI,IAAI,CAAA;SACf,CAAA;KACF,CAAA;CACF,CAAA;AAED,KAAK,wBAAwB,CAAC,UAAU,IAAI;IAC1C,QAAQ,EAAE;QACR,QAAQ,IAAI;YACV,UAAU,EAAE,UAAU,EAAE,CAAA;SACzB,CAAA;QACD,QAAQ,CAAC,KAAK,EAAE;YAAE,UAAU,EAAE,UAAU,EAAE,CAAA;SAAE,GAAG,IAAI,CAAA;KACpD,CAAA;CACF,CAAA;AA+BD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAQzF;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI,CAK/E;AAYD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAiB3D;AAyBD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAKrE;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAStE;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAkBD,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,OAAO,EAC7D,UAAU,EAAE,wBAAwB,CAAC,UAAU,CAAC,EAChD,GAAG,EAAE,MAAM,OAAO,GACjB,OAAO,CAuBT"}
@@ -1,4 +1,92 @@
1
1
  let sceneHistoryPauseDepth = 0;
2
+ const sceneCommitListeners = new Set();
3
+ let sceneCommitTransactionDepth = 0;
4
+ let pendingSceneCommit = null;
5
+ function areSemanticValuesEqual(left, right) {
6
+ if (Object.is(left, right))
7
+ return true;
8
+ if (typeof left !== typeof right || left === null || right === null)
9
+ return false;
10
+ if (Array.isArray(left) || Array.isArray(right)) {
11
+ if (!(Array.isArray(left) && Array.isArray(right)) || left.length !== right.length)
12
+ return false;
13
+ return left.every((value, index) => areSemanticValuesEqual(value, right[index]));
14
+ }
15
+ if (typeof left !== 'object' || typeof right !== 'object')
16
+ return false;
17
+ const leftRecord = left;
18
+ const rightRecord = right;
19
+ const leftKeys = Object.keys(leftRecord);
20
+ const rightKeys = Object.keys(rightRecord);
21
+ if (leftKeys.length !== rightKeys.length)
22
+ return false;
23
+ for (const key of leftKeys) {
24
+ if (!(key in rightRecord) || !areSemanticValuesEqual(leftRecord[key], rightRecord[key])) {
25
+ return false;
26
+ }
27
+ }
28
+ return true;
29
+ }
30
+ export function areSceneSnapshotsEqual(left, right) {
31
+ return (areSemanticValuesEqual(left.nodes, right.nodes) &&
32
+ areSemanticValuesEqual(left.rootNodeIds, right.rootNodeIds) &&
33
+ areSemanticValuesEqual(left.collections, right.collections) &&
34
+ areSemanticValuesEqual(left.materials, right.materials) &&
35
+ areSemanticValuesEqual(left.installedPlugins, right.installedPlugins));
36
+ }
37
+ export function subscribeSceneCommits(listener) {
38
+ sceneCommitListeners.add(listener);
39
+ return () => {
40
+ sceneCommitListeners.delete(listener);
41
+ };
42
+ }
43
+ function emitSceneCommit(commit) {
44
+ for (const listener of [...sceneCommitListeners]) {
45
+ try {
46
+ listener(commit);
47
+ }
48
+ catch (error) {
49
+ console.error('[Scene] Scene commit listener failed', error);
50
+ }
51
+ }
52
+ }
53
+ export function notifySceneCommit(commit) {
54
+ if (areSceneSnapshotsEqual(commit.before, commit.current))
55
+ return;
56
+ if (sceneCommitTransactionDepth > 0) {
57
+ if (pendingSceneCommit) {
58
+ pendingSceneCommit = {
59
+ origin: pendingSceneCommit.origin,
60
+ before: pendingSceneCommit.before,
61
+ current: commit.current,
62
+ };
63
+ }
64
+ else {
65
+ pendingSceneCommit = commit;
66
+ }
67
+ return;
68
+ }
69
+ emitSceneCommit(commit);
70
+ }
71
+ function beginSceneCommitTransaction() {
72
+ sceneCommitTransactionDepth += 1;
73
+ }
74
+ function pendingSceneCommitIsNoOp() {
75
+ return Boolean(pendingSceneCommit &&
76
+ areSceneSnapshotsEqual(pendingSceneCommit.before, pendingSceneCommit.current));
77
+ }
78
+ function endSceneCommitTransaction() {
79
+ if (sceneCommitTransactionDepth === 0)
80
+ return;
81
+ sceneCommitTransactionDepth -= 1;
82
+ if (sceneCommitTransactionDepth > 0)
83
+ return;
84
+ const commit = pendingSceneCommit;
85
+ pendingSceneCommit = null;
86
+ if (commit && !areSceneSnapshotsEqual(commit.before, commit.current)) {
87
+ emitSceneCommit(commit);
88
+ }
89
+ }
2
90
  export function pauseSceneHistory(sceneStore) {
3
91
  if (sceneHistoryPauseDepth === 0) {
4
92
  sceneStore.temporal.getState().pause();
@@ -20,3 +108,45 @@ export function getSceneHistoryPauseDepth() {
20
108
  export function resetSceneHistoryPauseDepth() {
21
109
  sceneHistoryPauseDepth = 0;
22
110
  }
111
+ function retainedPastStateCount(before, after) {
112
+ for (let start = 0; start < before.length; start += 1) {
113
+ const retained = before.length - start;
114
+ if (retained > after.length)
115
+ continue;
116
+ let matches = true;
117
+ for (let index = 0; index < retained; index += 1) {
118
+ if (before[start + index] !== after[index]) {
119
+ matches = false;
120
+ break;
121
+ }
122
+ }
123
+ if (matches)
124
+ return retained;
125
+ }
126
+ return 0;
127
+ }
128
+ export function runAsSingleSceneHistoryStep(sceneStore, run) {
129
+ const beforePastStates = sceneStore.temporal.getState().pastStates;
130
+ beginSceneCommitTransaction();
131
+ try {
132
+ const result = run();
133
+ const afterPastStates = sceneStore.temporal.getState().pastStates;
134
+ const retainedCount = retainedPastStateCount(beforePastStates, afterPastStates);
135
+ const addedCount = afterPastStates.length - retainedCount;
136
+ if (addedCount > 0 && pendingSceneCommitIsNoOp()) {
137
+ sceneStore.temporal.setState({ pastStates: afterPastStates.slice(0, retainedCount) });
138
+ }
139
+ else if (addedCount > 1) {
140
+ const firstAddedState = afterPastStates[retainedCount];
141
+ if (firstAddedState !== undefined) {
142
+ sceneStore.temporal.setState({
143
+ pastStates: [...afterPastStates.slice(0, retainedCount), firstAddedState],
144
+ });
145
+ }
146
+ }
147
+ return result;
148
+ }
149
+ finally {
150
+ endSceneCommitTransaction();
151
+ }
152
+ }
@@ -0,0 +1,65 @@
1
+ import type { HeightPatch, TerrainField } from '../lib/terrain-field';
2
+ /**
3
+ * In-progress terrain edits, held as a live `TerrainField` rather than as node
4
+ * data.
5
+ *
6
+ * This is the sculpting analogue of `useLiveNodeOverrides`, and it exists because
7
+ * that store cannot be reused here. An override stores *node* values, so a live
8
+ * terrain override would have to be a `TerrainData` — meaning every dab of a
9
+ * brush would base64-encode the whole field, ~11 KB at 65² and ~44 KB at 129²,
10
+ * dozens of times a second. Holding the decoded field instead makes a dab cost
11
+ * one `applyHeightPatch` (a typed-array copy) and nothing else.
12
+ *
13
+ * The store also carries the **stroke's starting field**, which is what makes the
14
+ * saturating stroke model possible: a brush computes `snapshot + delta · mask`
15
+ * rather than accumulating onto the current field, so re-crossing your own stroke
16
+ * cannot compound. Without a snapshot the same drag deposits material twice
17
+ * wherever it overlaps itself, which is the single most common way a sculpt tool
18
+ * feels wrong.
19
+ *
20
+ * `lastPatch` is how the renderer knows what to upload: it takes the patch,
21
+ * pushes exactly those rows, and never diffs the whole field.
22
+ */
23
+ export type LiveTerrainStroke = {
24
+ /** The field as it was at pointer-down. Never mutated during the stroke. */
25
+ readonly snapshot: TerrainField;
26
+ /** The field as of the most recent dab — what the renderer and readers see. */
27
+ readonly field: TerrainField;
28
+ /**
29
+ * The most recent dab's patch, or null right after `begin`. The renderer
30
+ * consumes this for the dirty-rect upload; a null means "nothing new to push".
31
+ */
32
+ readonly lastPatch: HeightPatch | null;
33
+ };
34
+ type LiveTerrainState = {
35
+ /** Keyed by site node id — a scene can hold more than one site. */
36
+ strokes: Map<string, LiveTerrainStroke>;
37
+ /**
38
+ * Start a stroke from `field`.
39
+ *
40
+ * A second `begin` for the same site *replaces* the stroke rather than being
41
+ * rejected — and that is a hazard, not idempotence, which is why it is spelled
42
+ * out here: the caller passes the field it is currently reading, and mid-stroke
43
+ * that field is the live one, dabs included. So a re-begin adopts uncommitted
44
+ * dabs as the new stroke's snapshot, where they become the saturating baseline
45
+ * and get persisted by the next commit — visible on screen the whole time, yet
46
+ * absent from history and unreachable by undo.
47
+ *
48
+ * `advance` takes the opposite stance for the same reason (a dab with no stroke
49
+ * is ignored rather than inventing a snapshot): the invariant is that a snapshot
50
+ * only ever comes from a deliberate stroke boundary. Callers own the boundary —
51
+ * `end` first, or don't begin.
52
+ */
53
+ begin(siteId: string, field: TerrainField): void;
54
+ /** Record a dab. `field` must be the result of applying `patch`. */
55
+ advance(siteId: string, field: TerrainField, patch: HeightPatch): void;
56
+ /** The live field for a site, or undefined when no stroke is in flight. */
57
+ fieldOf(siteId: string): TerrainField | undefined;
58
+ strokeOf(siteId: string): LiveTerrainStroke | undefined;
59
+ /** End the stroke. The caller persists the field first if it wants to keep it. */
60
+ end(siteId: string): void;
61
+ endAll(): void;
62
+ };
63
+ declare const useLiveTerrain: import("zustand").UseBoundStore<import("zustand").StoreApi<LiveTerrainState>>;
64
+ export default useLiveTerrain;
65
+ //# sourceMappingURL=use-live-terrain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-live-terrain.d.ts","sourceRoot":"","sources":["../../src/store/use-live-terrain.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAErE;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;IAC5B;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI,CAAA;CACvC,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,mEAAmE;IACnE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IACvC;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAAA;IAChD,oEAAoE;IACpE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACtE,2EAA2E;IAC3E,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAA;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAAA;IACvD,kFAAkF;IAClF,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,MAAM,IAAI,IAAI,CAAA;CACf,CAAA;AAED,QAAA,MAAM,cAAc,+EAkCjB,CAAA;AAEH,eAAe,cAAc,CAAA"}
@@ -0,0 +1,31 @@
1
+ import { create } from 'zustand';
2
+ const useLiveTerrain = create((set, get) => ({
3
+ strokes: new Map(),
4
+ begin: (siteId, field) => set((state) => {
5
+ const next = new Map(state.strokes);
6
+ next.set(siteId, { snapshot: field, field, lastPatch: null });
7
+ return { strokes: next };
8
+ }),
9
+ advance: (siteId, field, patch) => set((state) => {
10
+ const current = state.strokes.get(siteId);
11
+ // A dab with no stroke is a bug in the caller, not something to paper over
12
+ // by inventing a snapshot — that would silently disable the saturating
13
+ // model and reintroduce compounding.
14
+ if (!current)
15
+ return state;
16
+ const next = new Map(state.strokes);
17
+ next.set(siteId, { snapshot: current.snapshot, field, lastPatch: patch });
18
+ return { strokes: next };
19
+ }),
20
+ fieldOf: (siteId) => get().strokes.get(siteId)?.field,
21
+ strokeOf: (siteId) => get().strokes.get(siteId),
22
+ end: (siteId) => set((state) => {
23
+ if (!state.strokes.has(siteId))
24
+ return state;
25
+ const next = new Map(state.strokes);
26
+ next.delete(siteId);
27
+ return { strokes: next };
28
+ }),
29
+ endAll: () => set((state) => (state.strokes.size === 0 ? state : { strokes: new Map() })),
30
+ }));
31
+ export default useLiveTerrain;
@@ -1,6 +1,14 @@
1
1
  export type LiveTransform = {
2
2
  position: [number, number, number];
3
3
  rotation: number;
4
+ /**
5
+ * Pointer-decided support cap (level-local Y) published by 3D drags:
6
+ * the elevation of the surface the cursor ray actually points at. The
7
+ * floor-elevation system passes it to the slab-support election so a
8
+ * deck above the aimed-at floor never lifts the dragged node. Absent
9
+ * for 2D floorplan drags (no camera ray) — election stays uncapped.
10
+ */
11
+ supportElevationCap?: number;
4
12
  };
5
13
  type LiveTransformState = {
6
14
  transforms: Map<string, LiveTransform>;
@@ -1 +1 @@
1
- {"version":3,"file":"use-live-transforms.d.ts","sourceRoot":"","sources":["../../src/store/use-live-transforms.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACtC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,IAAI,CAAA;IACnD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAA;IAC9C,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,IAAI,IAAI,CAAA;CACjB,CAAA;AAED,QAAA,MAAM,iBAAiB,iFAgBpB,CAAA;AAEH,eAAe,iBAAiB,CAAA"}
1
+ {"version":3,"file":"use-live-transforms.d.ts","sourceRoot":"","sources":["../../src/store/use-live-transforms.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACtC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,IAAI,CAAA;IACnD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAA;IAC9C,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,QAAQ,IAAI,IAAI,CAAA;CACjB,CAAA;AAED,QAAA,MAAM,iBAAiB,iFAgBpB,CAAA;AAEH,eAAe,iBAAiB,CAAA"}
@@ -1,18 +1,31 @@
1
1
  import type { TemporalState } from 'zundo';
2
2
  import { type StoreApi, type UseBoundStore } from 'zustand';
3
3
  import type { Collection, CollectionId } from '../schema/collections';
4
- import type { AnyNode, AnyNodeId } from '../schema/types';
4
+ import { SceneMaterial, type SceneMaterialId } from '../schema/scene-material';
5
+ import { type AnyNode, type AnyNodeId } from '../schema/types';
6
+ import { type SceneCommitOrigin, type SceneSnapshot } from './history-control';
5
7
  export type SceneState = {
6
8
  nodes: Record<AnyNodeId, AnyNode>;
7
9
  rootNodeIds: AnyNodeId[];
8
10
  dirtyNodes: Set<AnyNodeId>;
9
11
  collections: Record<CollectionId, Collection>;
12
+ materials: Record<SceneMaterialId, SceneMaterial>;
13
+ installedPlugins: string[];
14
+ hasExplicitPluginInstallState: boolean;
10
15
  readOnly: boolean;
11
16
  setReadOnly: (readOnly: boolean) => void;
12
17
  loadScene: () => void;
13
18
  clearScene: () => void;
14
19
  unloadScene: () => void;
15
- setScene: (nodes: Record<AnyNodeId, AnyNode>, rootNodeIds: AnyNodeId[]) => void;
20
+ setScene: (nodes: Record<AnyNodeId, AnyNode>, rootNodeIds: AnyNodeId[], extra?: {
21
+ collections?: Record<CollectionId, Collection>;
22
+ materials?: Record<SceneMaterialId, SceneMaterial>;
23
+ installedPlugins?: string[];
24
+ hasExplicitPluginInstallState?: boolean;
25
+ }) => void;
26
+ setInstalledPlugins: (pluginIds: string[], options?: {
27
+ explicit?: boolean;
28
+ }) => void;
16
29
  markDirty: (id: AnyNodeId) => void;
17
30
  clearDirty: (id: AnyNodeId) => void;
18
31
  createNode: (node: AnyNode, parentId?: AnyNodeId) => void;
@@ -43,11 +56,42 @@ export type SceneState = {
43
56
  updateCollection: (id: CollectionId, data: Partial<Omit<Collection, 'id'>>) => void;
44
57
  addToCollection: (id: CollectionId, nodeId: AnyNodeId) => void;
45
58
  removeFromCollection: (id: CollectionId, nodeId: AnyNodeId) => void;
59
+ addSceneMaterial: (material: SceneMaterial) => void;
60
+ updateSceneMaterial: (id: SceneMaterialId, data: Partial<Omit<SceneMaterial, 'id'>>) => void;
61
+ removeSceneMaterial: (id: SceneMaterialId) => void;
46
62
  };
47
63
  type UseSceneStore = UseBoundStore<StoreApi<SceneState>> & {
48
- temporal: StoreApi<TemporalState<Pick<SceneState, 'nodes' | 'rootNodeIds' | 'collections'>>>;
64
+ temporal: StoreApi<TemporalState<Pick<SceneState, 'nodes' | 'rootNodeIds' | 'collections' | 'materials' | 'installedPlugins'>>>;
49
65
  };
50
66
  declare const useScene: UseSceneStore;
51
67
  export default useScene;
68
+ export declare function acquireSceneReadOnlyLease(): () => void;
69
+ export type SceneNodePatch = {
70
+ id: AnyNodeId;
71
+ data: Partial<AnyNode>;
72
+ removeFields: string[];
73
+ };
74
+ export type SceneMaterialPatch = {
75
+ id: SceneMaterialId;
76
+ material: SceneMaterial | null;
77
+ };
78
+ export type ScenePatch = {
79
+ materialChanges: SceneMaterialPatch[];
80
+ nodeUpdates: SceneNodePatch[];
81
+ };
82
+ export type SceneNodeStructuralPatch = {
83
+ node: AnyNode;
84
+ position: number;
85
+ };
86
+ export type SceneOperationPatch = ScenePatch & {
87
+ nodeCreates: SceneNodeStructuralPatch[];
88
+ nodeDeletes: SceneNodeStructuralPatch[];
89
+ };
90
+ export declare function applySceneOperationPatch(changes: SceneOperationPatch): boolean;
91
+ export declare function applyScenePatch(changes: ScenePatch): boolean;
92
+ export type ApplySceneSnapshotOptions = {
93
+ origin: Extract<SceneCommitOrigin, 'load' | 'host'>;
94
+ };
95
+ export declare function applySceneSnapshot(snapshot: SceneSnapshot, options: ApplySceneSnapshotOptions): boolean;
52
96
  export declare function clearSceneHistory(): void;
53
97
  //# sourceMappingURL=use-scene.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-scene.d.ts","sourceRoot":"","sources":["../../src/store/use-scene.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-scene.d.ts","sourceRoot":"","sources":["../../src/store/use-scene.ts"],"names":[],"mappings":"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"}