@pascal-app/nodes 0.1.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 (408) hide show
  1. package/README.md +34 -0
  2. package/dist/building/definition.js +1 -1
  3. package/dist/cabinet/definition.d.ts.map +1 -1
  4. package/dist/cabinet/definition.js +809 -72
  5. package/dist/cabinet/geometry.d.ts.map +1 -1
  6. package/dist/cabinet/geometry.js +4 -0
  7. package/dist/cabinet/move-frame.js +3 -3
  8. package/dist/cabinet/panel.d.ts.map +1 -1
  9. package/dist/cabinet/panel.js +1 -0
  10. package/dist/cabinet/placement-snap.d.ts +8 -0
  11. package/dist/cabinet/placement-snap.d.ts.map +1 -0
  12. package/dist/cabinet/placement-snap.js +19 -0
  13. package/dist/cabinet/presets.js +8 -8
  14. package/dist/cabinet/quick-actions.d.ts.map +1 -1
  15. package/dist/cabinet/quick-actions.js +9 -3
  16. package/dist/cabinet/resize-limits.d.ts +11 -0
  17. package/dist/cabinet/resize-limits.d.ts.map +1 -0
  18. package/dist/cabinet/resize-limits.js +22 -0
  19. package/dist/cabinet/run-layout.d.ts +8 -2
  20. package/dist/cabinet/run-layout.d.ts.map +1 -1
  21. package/dist/cabinet/run-layout.js +59 -7
  22. package/dist/cabinet/run-ops.d.ts +44 -3
  23. package/dist/cabinet/run-ops.d.ts.map +1 -1
  24. package/dist/cabinet/run-ops.js +646 -110
  25. package/dist/cabinet/run-panel.d.ts +2 -1
  26. package/dist/cabinet/run-panel.d.ts.map +1 -1
  27. package/dist/cabinet/run-panel.js +38 -4
  28. package/dist/cabinet/stack-transitions.js +4 -4
  29. package/dist/cabinet/tool.d.ts.map +1 -1
  30. package/dist/cabinet/tool.js +95 -17
  31. package/dist/cabinet/wall-snap.d.ts.map +1 -1
  32. package/dist/cabinet/wall-snap.js +2 -6
  33. package/dist/ceiling/boundary-editor.d.ts.map +1 -1
  34. package/dist/ceiling/boundary-editor.js +2 -2
  35. package/dist/ceiling/definition.d.ts +1 -1
  36. package/dist/ceiling/definition.d.ts.map +1 -1
  37. package/dist/ceiling/definition.js +36 -5
  38. package/dist/ceiling/floorplan-affordances.d.ts +4 -4
  39. package/dist/ceiling/floorplan-move.d.ts +4 -4
  40. package/dist/ceiling/floorplan-move.d.ts.map +1 -1
  41. package/dist/ceiling/floorplan-move.js +5 -4
  42. package/dist/ceiling/hole-editor.d.ts.map +1 -1
  43. package/dist/ceiling/hole-editor.js +2 -2
  44. package/dist/ceiling/move-tool.d.ts.map +1 -1
  45. package/dist/ceiling/move-tool.js +4 -3
  46. package/dist/ceiling/panel.d.ts.map +1 -1
  47. package/dist/ceiling/panel.js +65 -3
  48. package/dist/ceiling/renderer.d.ts.map +1 -1
  49. package/dist/ceiling/renderer.js +6 -2
  50. package/dist/ceiling/tool.d.ts.map +1 -1
  51. package/dist/ceiling/tool.js +12 -1
  52. package/dist/chimney/definition.d.ts.map +1 -1
  53. package/dist/chimney/definition.js +1 -0
  54. package/dist/chimney/tool.d.ts.map +1 -1
  55. package/dist/chimney/tool.js +16 -1
  56. package/dist/column/definition.d.ts.map +1 -1
  57. package/dist/column/definition.js +14 -2
  58. package/dist/column/floorplan-affordances.d.ts.map +1 -1
  59. package/dist/column/floorplan-affordances.js +19 -14
  60. package/dist/column/floorplan-move.d.ts.map +1 -1
  61. package/dist/column/floorplan-move.js +7 -2
  62. package/dist/column/floorplan.d.ts +9 -1
  63. package/dist/column/floorplan.d.ts.map +1 -1
  64. package/dist/column/floorplan.js +59 -4
  65. package/dist/column/tool.d.ts.map +1 -1
  66. package/dist/column/tool.js +33 -7
  67. package/dist/construction-dimension/definition.d.ts +4 -0
  68. package/dist/construction-dimension/definition.d.ts.map +1 -0
  69. package/dist/construction-dimension/definition.js +83 -0
  70. package/dist/construction-dimension/drawing-coordination.d.ts +7 -0
  71. package/dist/construction-dimension/drawing-coordination.d.ts.map +1 -0
  72. package/dist/construction-dimension/drawing-coordination.js +54 -0
  73. package/dist/construction-dimension/floorplan-affordances.d.ts +4 -0
  74. package/dist/construction-dimension/floorplan-affordances.d.ts.map +1 -0
  75. package/dist/construction-dimension/floorplan-affordances.js +114 -0
  76. package/dist/construction-dimension/floorplan-tool.d.ts +21 -0
  77. package/dist/construction-dimension/floorplan-tool.d.ts.map +1 -0
  78. package/dist/construction-dimension/floorplan-tool.js +557 -0
  79. package/dist/construction-dimension/floorplan.d.ts +3 -0
  80. package/dist/construction-dimension/floorplan.d.ts.map +1 -0
  81. package/dist/construction-dimension/floorplan.js +457 -0
  82. package/dist/construction-dimension/geometry.d.ts +31 -0
  83. package/dist/construction-dimension/geometry.d.ts.map +1 -0
  84. package/dist/construction-dimension/geometry.js +144 -0
  85. package/dist/construction-dimension/index.d.ts +4 -0
  86. package/dist/construction-dimension/index.d.ts.map +1 -0
  87. package/dist/construction-dimension/index.js +3 -0
  88. package/dist/construction-dimension/panel.d.ts +2 -0
  89. package/dist/construction-dimension/panel.d.ts.map +1 -0
  90. package/dist/construction-dimension/panel.js +128 -0
  91. package/dist/construction-dimension/parametrics.d.ts +3 -0
  92. package/dist/construction-dimension/parametrics.d.ts.map +1 -0
  93. package/dist/construction-dimension/parametrics.js +4 -0
  94. package/dist/construction-dimension/schema.d.ts +2 -0
  95. package/dist/construction-dimension/schema.d.ts.map +1 -0
  96. package/dist/construction-dimension/schema.js +1 -0
  97. package/dist/door/contextual-dimensions.d.ts +3 -0
  98. package/dist/door/contextual-dimensions.d.ts.map +1 -0
  99. package/dist/door/contextual-dimensions.js +7 -0
  100. package/dist/door/definition.d.ts.map +1 -1
  101. package/dist/door/definition.js +13 -8
  102. package/dist/door/floorplan-affordances.d.ts +2 -5
  103. package/dist/door/floorplan-affordances.d.ts.map +1 -1
  104. package/dist/door/floorplan-affordances.js +9 -18
  105. package/dist/door/floorplan.d.ts +3 -4
  106. package/dist/door/floorplan.d.ts.map +1 -1
  107. package/dist/door/floorplan.js +88 -6
  108. package/dist/door/move-tool.d.ts.map +1 -1
  109. package/dist/door/move-tool.js +2 -2
  110. package/dist/door/panel.d.ts.map +1 -1
  111. package/dist/door/panel.js +3 -1
  112. package/dist/door/schema.d.ts +1 -1
  113. package/dist/door/schema.d.ts.map +1 -1
  114. package/dist/door/schema.js +1 -1
  115. package/dist/door/tool.d.ts.map +1 -1
  116. package/dist/door/tool.js +63 -6
  117. package/dist/dormer/definition.d.ts.map +1 -1
  118. package/dist/dormer/definition.js +1 -0
  119. package/dist/dormer/tool.d.ts.map +1 -1
  120. package/dist/dormer/tool.js +23 -1
  121. package/dist/duct-segment/tool.d.ts.map +1 -1
  122. package/dist/duct-segment/tool.js +20 -9
  123. package/dist/duct-terminal/tool.d.ts.map +1 -1
  124. package/dist/duct-terminal/tool.js +9 -6
  125. package/dist/elevator/floorplan-affordances.d.ts +2 -6
  126. package/dist/elevator/floorplan-affordances.d.ts.map +1 -1
  127. package/dist/elevator/floorplan-affordances.js +13 -12
  128. package/dist/fence/actions/move-endpoint.d.ts.map +1 -1
  129. package/dist/fence/actions/move-endpoint.js +29 -1
  130. package/dist/fence/definition.d.ts.map +1 -1
  131. package/dist/fence/definition.js +67 -14
  132. package/dist/fence/floorplan-affordances.d.ts.map +1 -1
  133. package/dist/fence/floorplan-affordances.js +48 -11
  134. package/dist/fence/floorplan-move.d.ts.map +1 -1
  135. package/dist/fence/floorplan-move.js +38 -3
  136. package/dist/fence/geometry.d.ts.map +1 -1
  137. package/dist/fence/geometry.js +9 -1
  138. package/dist/fence/lift.d.ts +15 -0
  139. package/dist/fence/lift.d.ts.map +1 -0
  140. package/dist/fence/lift.js +23 -0
  141. package/dist/fence/move-tool.d.ts.map +1 -1
  142. package/dist/fence/move-tool.js +25 -5
  143. package/dist/fence/system.d.ts +3 -0
  144. package/dist/fence/system.d.ts.map +1 -0
  145. package/dist/fence/system.js +41 -0
  146. package/dist/fence/tool.d.ts.map +1 -1
  147. package/dist/fence/tool.js +103 -32
  148. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  149. package/dist/hvac-equipment/tool.js +8 -3
  150. package/dist/index.d.ts +2 -0
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.js +6 -0
  153. package/dist/item/definition.d.ts.map +1 -1
  154. package/dist/item/definition.js +7 -1
  155. package/dist/item/floorplan-move.d.ts.map +1 -1
  156. package/dist/item/floorplan-move.js +50 -43
  157. package/dist/item/floorplan.d.ts +1 -0
  158. package/dist/item/floorplan.d.ts.map +1 -1
  159. package/dist/item/floorplan.js +49 -0
  160. package/dist/item/renderer.d.ts +3 -0
  161. package/dist/item/renderer.d.ts.map +1 -1
  162. package/dist/item/renderer.js +96 -8
  163. package/dist/level/definition.d.ts.map +1 -1
  164. package/dist/level/definition.js +7 -3
  165. package/dist/lineset/tool.d.ts.map +1 -1
  166. package/dist/lineset/tool.js +5 -1
  167. package/dist/liquid-line/tool.d.ts.map +1 -1
  168. package/dist/liquid-line/tool.js +7 -1
  169. package/dist/measurement/definition.d.ts.map +1 -1
  170. package/dist/measurement/definition.js +5 -0
  171. package/dist/measurement/floorplan.d.ts.map +1 -1
  172. package/dist/measurement/floorplan.js +11 -10
  173. package/dist/measurement/index.d.ts +1 -1
  174. package/dist/measurement/index.d.ts.map +1 -1
  175. package/dist/measurement/index.js +1 -1
  176. package/dist/measurement/resolve.d.ts +5 -0
  177. package/dist/measurement/resolve.d.ts.map +1 -1
  178. package/dist/measurement/resolve.js +2 -2
  179. package/dist/measurement/surface-query.js +5 -5
  180. package/dist/measurement/tool.d.ts +6 -1
  181. package/dist/measurement/tool.d.ts.map +1 -1
  182. package/dist/measurement/tool.js +7 -11
  183. package/dist/pipe-segment/tool.d.ts.map +1 -1
  184. package/dist/pipe-segment/tool.js +22 -19
  185. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  186. package/dist/roof-segment/floorplan-affordances.js +14 -8
  187. package/dist/shared/construction-dimension-standards.d.ts +34 -0
  188. package/dist/shared/construction-dimension-standards.d.ts.map +1 -0
  189. package/dist/shared/construction-dimension-standards.js +18 -0
  190. package/dist/shared/construction-length.d.ts +10 -0
  191. package/dist/shared/construction-length.d.ts.map +1 -0
  192. package/dist/shared/construction-length.js +57 -0
  193. package/dist/shared/dimension-string.d.ts +20 -0
  194. package/dist/shared/dimension-string.d.ts.map +1 -0
  195. package/dist/shared/dimension-string.js +19 -0
  196. package/dist/shared/draft-axis-guides.d.ts +36 -0
  197. package/dist/shared/draft-axis-guides.d.ts.map +1 -0
  198. package/dist/shared/draft-axis-guides.js +107 -0
  199. package/dist/shared/move-roof-tool.d.ts.map +1 -1
  200. package/dist/shared/move-roof-tool.js +17 -3
  201. package/dist/shared/opening-documentation-fields.d.ts +16 -0
  202. package/dist/shared/opening-documentation-fields.d.ts.map +1 -0
  203. package/dist/shared/opening-documentation-fields.js +54 -0
  204. package/dist/shared/opening-documentation.d.ts +47 -0
  205. package/dist/shared/opening-documentation.d.ts.map +1 -0
  206. package/dist/shared/opening-documentation.js +300 -0
  207. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  208. package/dist/shared/opening-guides-runtime.js +3 -2
  209. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  210. package/dist/shared/opening-placement-dimensions.js +14 -5
  211. package/dist/shared/wall-opening-ceiling.d.ts +30 -0
  212. package/dist/shared/wall-opening-ceiling.d.ts.map +1 -0
  213. package/dist/shared/wall-opening-ceiling.js +29 -0
  214. package/dist/shelf/floorplan-affordances.d.ts.map +1 -1
  215. package/dist/shelf/floorplan-affordances.js +10 -5
  216. package/dist/shelf/floorplan-move.d.ts +2 -16
  217. package/dist/shelf/floorplan-move.d.ts.map +1 -1
  218. package/dist/shelf/floorplan-move.js +19 -40
  219. package/dist/shelf/tool.d.ts.map +1 -1
  220. package/dist/shelf/tool.js +8 -3
  221. package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
  222. package/dist/site/recessed-slab-ground-holes.js +1 -4
  223. package/dist/site/renderer.d.ts.map +1 -1
  224. package/dist/site/renderer.js +118 -28
  225. package/dist/site/terrain-drape.d.ts +91 -0
  226. package/dist/site/terrain-drape.d.ts.map +1 -0
  227. package/dist/site/terrain-drape.js +205 -0
  228. package/dist/site/terrain-geometry.d.ts +131 -0
  229. package/dist/site/terrain-geometry.d.ts.map +1 -0
  230. package/dist/site/terrain-geometry.js +259 -0
  231. package/dist/site/terrain-mesh.d.ts +49 -0
  232. package/dist/site/terrain-mesh.d.ts.map +1 -0
  233. package/dist/site/terrain-mesh.js +122 -0
  234. package/dist/site/terrain-renderer.d.ts +28 -0
  235. package/dist/site/terrain-renderer.d.ts.map +1 -0
  236. package/dist/site/terrain-renderer.js +69 -0
  237. package/dist/skylight/definition.d.ts.map +1 -1
  238. package/dist/skylight/definition.js +1 -0
  239. package/dist/skylight/tool.d.ts.map +1 -1
  240. package/dist/skylight/tool.js +16 -1
  241. package/dist/slab/definition.d.ts.map +1 -1
  242. package/dist/slab/definition.js +87 -10
  243. package/dist/slab/elevation-limit.d.ts +43 -0
  244. package/dist/slab/elevation-limit.d.ts.map +1 -0
  245. package/dist/slab/elevation-limit.js +124 -0
  246. package/dist/slab/floorplan-affordances.d.ts +16 -0
  247. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  248. package/dist/slab/geometry.d.ts.map +1 -1
  249. package/dist/slab/geometry.js +98 -5
  250. package/dist/slab/panel.d.ts.map +1 -1
  251. package/dist/slab/panel.js +82 -4
  252. package/dist/slab/parametrics.d.ts +1 -1
  253. package/dist/slab/parametrics.d.ts.map +1 -1
  254. package/dist/slab/parametrics.js +13 -1
  255. package/dist/slab/placement-ownership.d.ts +3 -0
  256. package/dist/slab/placement-ownership.d.ts.map +1 -0
  257. package/dist/slab/placement-ownership.js +3 -0
  258. package/dist/slab/quick-measurement.d.ts.map +1 -1
  259. package/dist/slab/quick-measurement.js +3 -2
  260. package/dist/slab/system.d.ts.map +1 -1
  261. package/dist/slab/system.js +14 -4
  262. package/dist/slab/tool.d.ts.map +1 -1
  263. package/dist/slab/tool.js +81 -23
  264. package/dist/solar-panel/definition.d.ts.map +1 -1
  265. package/dist/solar-panel/definition.js +1 -0
  266. package/dist/solar-panel/tool.d.ts.map +1 -1
  267. package/dist/solar-panel/tool.js +17 -1
  268. package/dist/spawn/definition.d.ts.map +1 -1
  269. package/dist/spawn/definition.js +1 -0
  270. package/dist/spawn/floorplan-affordances.d.ts.map +1 -1
  271. package/dist/spawn/floorplan-affordances.js +7 -4
  272. package/dist/spawn/floorplan-move.d.ts.map +1 -1
  273. package/dist/spawn/floorplan-move.js +8 -6
  274. package/dist/spawn/renderer.d.ts +4 -0
  275. package/dist/spawn/renderer.d.ts.map +1 -1
  276. package/dist/spawn/renderer.js +32 -18
  277. package/dist/spawn/tool.d.ts +2 -2
  278. package/dist/spawn/tool.d.ts.map +1 -1
  279. package/dist/spawn/tool.js +78 -11
  280. package/dist/stair/definition.d.ts.map +1 -1
  281. package/dist/stair/definition.js +15 -7
  282. package/dist/stair/destination.d.ts +16 -0
  283. package/dist/stair/destination.d.ts.map +1 -0
  284. package/dist/stair/destination.js +24 -0
  285. package/dist/stair/documentation.d.ts +8 -0
  286. package/dist/stair/documentation.d.ts.map +1 -0
  287. package/dist/stair/documentation.js +245 -0
  288. package/dist/stair/floor-stack.d.ts.map +1 -1
  289. package/dist/stair/floor-stack.js +38 -0
  290. package/dist/stair/floorplan-affordances.d.ts.map +1 -1
  291. package/dist/stair/floorplan-affordances.js +28 -9
  292. package/dist/stair/floorplan-move.d.ts +3 -5
  293. package/dist/stair/floorplan-move.d.ts.map +1 -1
  294. package/dist/stair/floorplan-move.js +14 -16
  295. package/dist/stair/floorplan.d.ts.map +1 -1
  296. package/dist/stair/floorplan.js +27 -14
  297. package/dist/stair/panel.d.ts.map +1 -1
  298. package/dist/stair/panel.js +35 -2
  299. package/dist/stair/renderer.d.ts.map +1 -1
  300. package/dist/stair/renderer.js +4 -3
  301. package/dist/structural-grid/coordination.d.ts +16 -0
  302. package/dist/structural-grid/coordination.d.ts.map +1 -0
  303. package/dist/structural-grid/coordination.js +105 -0
  304. package/dist/structural-grid/definition.d.ts +4 -0
  305. package/dist/structural-grid/definition.d.ts.map +1 -0
  306. package/dist/structural-grid/definition.js +51 -0
  307. package/dist/structural-grid/floorplan-tool.d.ts +16 -0
  308. package/dist/structural-grid/floorplan-tool.d.ts.map +1 -0
  309. package/dist/structural-grid/floorplan-tool.js +183 -0
  310. package/dist/structural-grid/floorplan.d.ts +3 -0
  311. package/dist/structural-grid/floorplan.d.ts.map +1 -0
  312. package/dist/structural-grid/floorplan.js +61 -0
  313. package/dist/structural-grid/index.d.ts +2 -0
  314. package/dist/structural-grid/index.d.ts.map +1 -0
  315. package/dist/structural-grid/index.js +1 -0
  316. package/dist/structural-grid/schema.d.ts +2 -0
  317. package/dist/structural-grid/schema.d.ts.map +1 -0
  318. package/dist/structural-grid/schema.js +1 -0
  319. package/dist/wall/construction-dimensions.d.ts +32 -0
  320. package/dist/wall/construction-dimensions.d.ts.map +1 -0
  321. package/dist/wall/construction-dimensions.js +1031 -0
  322. package/dist/wall/contextual-dimensions.d.ts +13 -0
  323. package/dist/wall/contextual-dimensions.d.ts.map +1 -0
  324. package/dist/wall/contextual-dimensions.js +221 -0
  325. package/dist/wall/definition.d.ts.map +1 -1
  326. package/dist/wall/definition.js +20 -1
  327. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  328. package/dist/wall/floorplan-affordances.js +23 -8
  329. package/dist/wall/floorplan-overrides.d.ts +9 -6
  330. package/dist/wall/floorplan-overrides.d.ts.map +1 -1
  331. package/dist/wall/floorplan-overrides.js +20 -11
  332. package/dist/wall/floorplan.d.ts +12 -3
  333. package/dist/wall/floorplan.d.ts.map +1 -1
  334. package/dist/wall/floorplan.js +121 -79
  335. package/dist/wall/measurement.d.ts.map +1 -1
  336. package/dist/wall/measurement.js +17 -4
  337. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  338. package/dist/wall/move-endpoint-tool.js +74 -27
  339. package/dist/wall/move-shared.d.ts.map +1 -1
  340. package/dist/wall/move-shared.js +3 -2
  341. package/dist/wall/move-tool.d.ts.map +1 -1
  342. package/dist/wall/move-tool.js +15 -3
  343. package/dist/wall/paint.d.ts.map +1 -1
  344. package/dist/wall/paint.js +10 -6
  345. package/dist/wall/panel.d.ts.map +1 -1
  346. package/dist/wall/panel.js +32 -5
  347. package/dist/wall/parametrics.d.ts.map +1 -1
  348. package/dist/wall/parametrics.js +2 -0
  349. package/dist/wall/preview.d.ts +8 -0
  350. package/dist/wall/preview.d.ts.map +1 -0
  351. package/dist/wall/preview.js +39 -0
  352. package/dist/wall/quick-measurement.d.ts.map +1 -1
  353. package/dist/wall/quick-measurement.js +3 -2
  354. package/dist/wall/renderer.d.ts.map +1 -1
  355. package/dist/wall/renderer.js +7 -5
  356. package/dist/wall/system.d.ts +1 -1
  357. package/dist/wall/system.d.ts.map +1 -1
  358. package/dist/wall/system.js +37 -2
  359. package/dist/wall/tool.d.ts.map +1 -1
  360. package/dist/wall/tool.js +148 -96
  361. package/dist/wall/treatment-level-data.d.ts +14 -0
  362. package/dist/wall/treatment-level-data.d.ts.map +1 -0
  363. package/dist/wall/treatment-level-data.js +31 -0
  364. package/dist/wall/treatments.d.ts +8 -2
  365. package/dist/wall/treatments.d.ts.map +1 -1
  366. package/dist/wall/treatments.js +58 -15
  367. package/dist/window/contextual-dimensions.d.ts +3 -0
  368. package/dist/window/contextual-dimensions.d.ts.map +1 -0
  369. package/dist/window/contextual-dimensions.js +7 -0
  370. package/dist/window/definition.d.ts.map +1 -1
  371. package/dist/window/definition.js +15 -10
  372. package/dist/window/floorplan-affordances.d.ts +2 -5
  373. package/dist/window/floorplan-affordances.d.ts.map +1 -1
  374. package/dist/window/floorplan-affordances.js +9 -15
  375. package/dist/window/floorplan-move.d.ts.map +1 -1
  376. package/dist/window/floorplan-move.js +1 -1
  377. package/dist/window/floorplan.d.ts.map +1 -1
  378. package/dist/window/floorplan.js +7 -1
  379. package/dist/window/move-tool.d.ts.map +1 -1
  380. package/dist/window/move-tool.js +3 -3
  381. package/dist/window/panel.d.ts.map +1 -1
  382. package/dist/window/panel.js +4 -1
  383. package/dist/window/schema.d.ts +1 -1
  384. package/dist/window/schema.d.ts.map +1 -1
  385. package/dist/window/schema.js +1 -1
  386. package/dist/window/tool.d.ts.map +1 -1
  387. package/dist/window/tool.js +64 -7
  388. package/dist/window/window-math.d.ts +7 -3
  389. package/dist/window/window-math.d.ts.map +1 -1
  390. package/dist/window/window-math.js +8 -3
  391. package/dist/zone/contextual-dimensions.d.ts +3 -0
  392. package/dist/zone/contextual-dimensions.d.ts.map +1 -0
  393. package/dist/zone/contextual-dimensions.js +43 -0
  394. package/dist/zone/definition.d.ts.map +1 -1
  395. package/dist/zone/definition.js +9 -1
  396. package/dist/zone/floorplan-affordances.d.ts +36 -0
  397. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  398. package/dist/zone/floorplan.d.ts.map +1 -1
  399. package/dist/zone/floorplan.js +59 -3
  400. package/dist/zone/quantities-panel.d.ts.map +1 -1
  401. package/dist/zone/quantities-panel.js +48 -4
  402. package/dist/zone/room-clear-dimensions.d.ts +3 -0
  403. package/dist/zone/room-clear-dimensions.d.ts.map +1 -0
  404. package/dist/zone/room-clear-dimensions.js +406 -0
  405. package/dist/zone/room-documentation.d.ts +11 -0
  406. package/dist/zone/room-documentation.d.ts.map +1 -0
  407. package/dist/zone/room-documentation.js +97 -0
  408. package/package.json +7 -7
@@ -1,23 +1,55 @@
1
- import { calculateLevelMiters, getWallCurveLength, getWallMidpointHandlePoint, getWallPlanFootprint, isCurvedWall, } from '@pascal-app/core';
1
+ import { calculateLevelMiters, getWallCurveFrameAt, getWallCurveLength, getWallMidpointHandlePoint, getWallPlanFootprint, getWallThickness, isCurvedWall, } from '@pascal-app/core';
2
+ import { floorplanGeometryMetadata, readFloorplanContext } from '@pascal-app/editor';
3
+ import { constructionDimensionStandard } from '../shared/construction-dimension-standards';
4
+ import { buildCurvedWallConstructionDimensions, buildLevelWallConstructionDimensionPlan, buildWallConstructionDimensions, renderPlannedConstructionDimensions, } from './construction-dimensions';
2
5
  // Same constants the legacy `getFloorplanWall` uses (editor/lib/floorplan/walls.ts).
3
6
  // Slightly exaggerates thin walls so the 2D plan stays legible without
4
7
  // drifting from BIM data. Inlined to keep nodes/wall self-contained.
5
8
  const FLOORPLAN_WALL_THICKNESS_SCALE = 1.18;
6
9
  const FLOORPLAN_MIN_VISIBLE_WALL_THICKNESS = 0.13;
7
10
  const FLOORPLAN_MAX_EXTRA_THICKNESS = 0.035;
11
+ const FLOORPLAN_SELECTION_HATCH_SPACING = 0.12;
12
+ const FLOORPLAN_SELECTED_WALL_STROKE_WIDTH = 0.03;
13
+ const FLOORPLAN_SELECTION_HATCH_STROKE_WIDTH = 0.02;
14
+ const WALL_DIMENSION_REFERENCES = ['finished-faces', 'centerline', 'stud-faces'];
8
15
  function floorplanWallThickness(wall) {
9
- const baseThickness = wall.thickness ?? 0.1;
16
+ const baseThickness = getWallThickness(wall);
10
17
  const scaledThickness = baseThickness * FLOORPLAN_WALL_THICKNESS_SCALE;
11
18
  return Math.min(baseThickness + FLOORPLAN_MAX_EXTRA_THICKNESS, Math.max(baseThickness, scaledThickness, FLOORPLAN_MIN_VISIBLE_WALL_THICKNESS));
12
19
  }
13
20
  function exaggerateWallThickness(wall) {
14
21
  return { ...wall, thickness: floorplanWallThickness(wall) };
15
22
  }
16
- function formatLengthMetric(meters) {
17
- return `${Number.parseFloat(meters.toFixed(2))}m`;
18
- }
19
- export function computeWallFloorplanLevelData({ siblings, }) {
20
- return calculateLevelMiters(siblings.map(exaggerateWallThickness));
23
+ export function computeWallFloorplanLevelData({ siblings, nodes, }) {
24
+ const walls = siblings.map(exaggerateWallThickness);
25
+ const constructionDimensionsByReference = {};
26
+ for (const reference of WALL_DIMENSION_REFERENCES) {
27
+ let cached;
28
+ Object.defineProperty(constructionDimensionsByReference, reference, {
29
+ enumerable: true,
30
+ get: () => {
31
+ if (cached)
32
+ return cached;
33
+ const datumPolicy = reference === 'finished-faces'
34
+ ? 'wall-face'
35
+ : reference === 'stud-faces'
36
+ ? 'structural-face'
37
+ : 'centerline';
38
+ cached = buildLevelWallConstructionDimensionPlan(siblings, nodes, constructionDimensionStandard({
39
+ datumPolicy,
40
+ ...(reference === 'finished-faces'
41
+ ? { intersectionReferencePolicy: 'both-faces' }
42
+ : {}),
43
+ }));
44
+ return cached;
45
+ },
46
+ });
47
+ }
48
+ return {
49
+ miters: calculateLevelMiters(walls),
50
+ documentMiters: calculateLevelMiters([...siblings]),
51
+ constructionDimensionsByReference,
52
+ };
21
53
  }
22
54
  /**
23
55
  * Stage C floor-plan builder for wall — emits the full chrome stack the
@@ -29,25 +61,27 @@ export function computeWallFloorplanLevelData({ siblings, }) {
29
61
  * wall body easily.
30
62
  * 4. Two endpoint handles (start + end) when selected — the registry
31
63
  * layer hosts the 5-circle stack + hover transitions + 2D drag.
32
- * 5. A small dimension label at the midpoint when selected.
64
+ * 5. Exterior facade strings plus interior wall spans and hosted-opening widths.
33
65
  *
34
66
  * `ctx.levelData` provides the shared level miter graph when the floor-plan
35
67
  * dispatcher precomputes it; `ctx.siblings` remains the fallback path for
36
68
  * direct builder callers.
37
69
  */
38
70
  export function buildWallFloorplan(node, ctx) {
39
- const self = exaggerateWallThickness(node);
71
+ const { automaticDimensions, metricNotation, purpose, wallDimensionReference } = readFloorplanContext(ctx);
72
+ const documentMode = purpose === 'document';
73
+ const wallForPurpose = (wall) => (documentMode ? wall : exaggerateWallThickness(wall));
74
+ const self = wallForPurpose(node);
40
75
  // Prefer the level-batch miter graph the floor-plan dispatcher precomputes
41
76
  // once per pass (`computeWallFloorplanLevelData`). Only the fallback path —
42
77
  // a direct builder caller with no shared data — pays the O(N) exaggerate +
43
78
  // level-wide miter calc per wall; the dispatcher path is O(1) here, which is
44
79
  // what keeps a wall drag from being O(N²) across the level.
45
- const miters = ctx.levelData ??
80
+ const levelData = ctx.levelData;
81
+ const miters = (documentMode ? levelData?.documentMiters : levelData?.miters) ??
46
82
  calculateLevelMiters([
47
83
  self,
48
- ...ctx.siblings
49
- .filter((s) => s.type === 'wall')
50
- .map(exaggerateWallThickness),
84
+ ...ctx.siblings.filter((s) => s.type === 'wall').map(wallForPurpose),
51
85
  ]);
52
86
  const polygon = getWallPlanFootprint(self, miters);
53
87
  if (!polygon || polygon.length < 3)
@@ -75,8 +109,9 @@ export function buildWallFloorplan(node, ctx) {
75
109
  points,
76
110
  fill,
77
111
  stroke,
78
- strokeWidth: showSelectedChrome ? 0.03 : 0.02,
112
+ strokeWidth: showSelectedChrome ? FLOORPLAN_SELECTED_WALL_STROKE_WIDTH : 0.02,
79
113
  opacity: 0.92,
114
+ metadata: floorplanGeometryMetadata({ annotationObstacle: 'outline' }),
80
115
  // Once the wall is selected, the body keeps catching the pointer
81
116
  // so the cursor stays neutral (no drag/pointer affordance from
82
117
  // the slab below leaking through), but only the side-arrows and
@@ -85,15 +120,44 @@ export function buildWallFloorplan(node, ctx) {
85
120
  cursor: isSelected ? 'default' : undefined,
86
121
  },
87
122
  ];
123
+ if (automaticDimensions) {
124
+ const dimensionStroke = isSelected && palette ? palette.selectedStroke : (palette?.measurementStroke ?? '#334155');
125
+ const dimensionStandard = constructionDimensionStandard({
126
+ datumPolicy: wallDimensionDatumPolicy(wallDimensionReference),
127
+ metricNotation,
128
+ });
129
+ const exteriorCornerDimensionStandard = constructionDimensionStandard({
130
+ datumPolicy: 'structural-face',
131
+ metricNotation,
132
+ });
133
+ if (isCurvedWall(node)) {
134
+ children.push(...buildCurvedWallConstructionDimensions(self, {
135
+ unit: view?.unit ?? 'metric',
136
+ stroke: dimensionStroke,
137
+ profile: documentMode ? 'document' : 'editor',
138
+ standard: exteriorCornerDimensionStandard,
139
+ siblings: ctx.siblings.filter((sibling) => sibling.type === 'wall'),
140
+ }));
141
+ }
142
+ else {
143
+ const planned = levelData?.constructionDimensionsByReference[wallDimensionReference].get(node.id);
144
+ if (planned) {
145
+ children.push(...renderPlannedConstructionDimensions(planned, view?.unit ?? 'metric', dimensionStroke, documentMode ? 'document' : 'editor', dimensionStandard));
146
+ }
147
+ else if (!levelData) {
148
+ children.push(...buildWallConstructionDimensions(self, ctx, {
149
+ unit: view?.unit ?? 'metric',
150
+ stroke: dimensionStroke,
151
+ profile: documentMode ? 'document' : 'editor',
152
+ standard: exteriorCornerDimensionStandard,
153
+ }));
154
+ }
155
+ }
156
+ }
88
157
  // Selection hatch overlay — only when the wall is *the* selected item
89
158
  // (not when it's just marquee-highlighted), matching the legacy.
90
159
  if (isSelected && palette) {
91
- children.push({
92
- kind: 'hatch',
93
- points,
94
- color: palette.selectedHatch,
95
- opacity: 1,
96
- });
160
+ children.push(...buildSelectedWallHatchLines(self, palette.selectedHatch));
97
161
  }
98
162
  // Hit-line on the centerline. Stroke width is in screen pixels so it
99
163
  // stays clickable at any zoom. Skipped while selected — the user has
@@ -136,19 +200,18 @@ export function buildWallFloorplan(node, ctx) {
136
200
  const dz = node.end[1] - node.start[1];
137
201
  const wallLength = Math.hypot(dx, dz);
138
202
  if (wallLength > 1e-6) {
139
- const midX = (node.start[0] + node.end[0]) / 2;
140
- const midZ = (node.start[1] + node.end[1]) / 2;
203
+ const midpoint = getWallMidpointHandlePoint(node);
141
204
  const nx = -dz / wallLength;
142
205
  const nz = dx / wallLength;
143
206
  const offset = floorplanWallThickness(node) / 2 + 0.05;
144
207
  children.push({
145
208
  kind: 'move-arrow',
146
- point: [midX + nx * offset, midZ + nz * offset],
209
+ point: [midpoint.x + nx * offset, midpoint.y + nz * offset],
147
210
  angle: Math.atan2(nz, nx),
148
211
  });
149
212
  children.push({
150
213
  kind: 'move-arrow',
151
- point: [midX - nx * offset, midZ - nz * offset],
214
+ point: [midpoint.x - nx * offset, midpoint.y - nz * offset],
152
215
  angle: Math.atan2(-nz, -nx),
153
216
  });
154
217
  }
@@ -169,65 +232,44 @@ export function buildWallFloorplan(node, ctx) {
169
232
  payload: { wallId: node.id },
170
233
  });
171
234
  }
172
- // Length measurement. Curved walls use the simple rounded label
173
- // (the chord-vs-arc thing is hard to express with a dimension line);
174
- // straight walls get the full architect's overlay with extension
175
- // marks + ticks, offset to the side facing away from the level
176
- // centroid (matches the legacy `getWallMeasurementOverlay`).
177
- const length = getWallCurveLength(node);
178
- if (length >= 0.1) {
179
- const dx = node.end[0] - node.start[0];
180
- const dz = node.end[1] - node.start[1];
181
- const midX = (node.start[0] + node.end[0]) / 2;
182
- const midZ = (node.start[1] + node.end[1]) / 2;
183
- if (isCurvedWall(node)) {
184
- children.push({
185
- kind: 'dimension-label',
186
- cx: midX,
187
- cy: midZ,
188
- text: formatLengthMetric(length),
189
- angle: Math.atan2(dz, dx),
190
- });
191
- }
192
- else {
193
- // Outward unit normal = perpendicular to (dx, dz), choose the
194
- // side facing away from other walls' centroid so the dimension
195
- // line sits outside the building.
196
- const nx = -dz / length;
197
- const nz = dx / length;
198
- const wallSiblings = ctx.siblings.filter((s) => s.type === 'wall');
199
- const centroid = wallCentroid([node, ...wallSiblings]);
200
- const cx = midX - centroid[0];
201
- const cz = midZ - centroid[1];
202
- const facingAway = cx * nx + cz * nz >= 0 ? 1 : -1;
203
- children.push({
204
- kind: 'dimension',
205
- start: [node.start[0], node.start[1]],
206
- end: [node.end[0], node.end[1]],
207
- offsetNormal: [nx * facingAway, nz * facingAway],
208
- offsetDistance: 0.75,
209
- extensionOvershoot: 0.12,
210
- text: formatLengthMetric(length),
211
- });
212
- }
213
- }
214
235
  }
215
236
  return { kind: 'group', children };
216
237
  }
217
- function wallCentroid(walls) {
218
- // Mean of every wall endpoint — cheap approximation of "where the
219
- // building lives" so we can offset the dimension line away from it.
220
- let sumX = 0;
221
- let sumZ = 0;
222
- let count = 0;
223
- for (const wall of walls) {
224
- sumX += wall.start[0] + wall.end[0];
225
- sumZ += wall.start[1] + wall.end[1];
226
- count += 2;
238
+ function buildSelectedWallHatchLines(wall, stroke) {
239
+ const length = getWallCurveLength(wall);
240
+ if (length <= 1e-6)
241
+ return [];
242
+ const halfAcross = getWallThickness(wall) / 2;
243
+ const halfAlong = halfAcross;
244
+ const count = Math.max(1, Math.floor(length / FLOORPLAN_SELECTION_HATCH_SPACING));
245
+ const spacing = length / count;
246
+ const lines = [];
247
+ for (let index = 0; index < count; index += 1) {
248
+ const along = (index + 0.5) * spacing;
249
+ const frame = getWallCurveFrameAt(wall, along / length);
250
+ lines.push({
251
+ kind: 'line',
252
+ x1: frame.point.x - frame.tangent.x * halfAlong - frame.normal.x * halfAcross,
253
+ y1: frame.point.y - frame.tangent.y * halfAlong - frame.normal.y * halfAcross,
254
+ x2: frame.point.x + frame.tangent.x * halfAlong + frame.normal.x * halfAcross,
255
+ y2: frame.point.y + frame.tangent.y * halfAlong + frame.normal.y * halfAcross,
256
+ stroke,
257
+ strokeWidth: FLOORPLAN_SELECTION_HATCH_STROKE_WIDTH,
258
+ pointerEvents: 'none',
259
+ metadata: floorplanGeometryMetadata({ renderPass: 'overlay' }),
260
+ });
261
+ }
262
+ return lines;
263
+ }
264
+ function wallDimensionDatumPolicy(reference) {
265
+ switch (reference) {
266
+ case 'centerline':
267
+ return 'centerline';
268
+ case 'stud-faces':
269
+ return 'structural-face';
270
+ case 'finished-faces':
271
+ return 'wall-face';
227
272
  }
228
- if (count === 0)
229
- return [0, 0];
230
- return [sumX / count, sumZ / count];
231
273
  }
232
274
  /**
233
275
  * Doors, windows, and wall-attached items would tear if the wall bent
@@ -1 +1 @@
1
- {"version":3,"file":"measurement.d.ts","sourceRoot":"","sources":["../../src/wall/measurement.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAEhC,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAIzB,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,kBAAkB,EAAE,CAuF5E;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC7B,WAAW,EAAE,MAAM,GAClB,yBAAyB,GAAG,IAAI,CA2ElC;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,2BAA2B,GACrC,kBAAkB,GAAG,IAAI,CA6B3B"}
1
+ {"version":3,"file":"measurement.d.ts","sourceRoot":"","sources":["../../src/wall/measurement.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,EAGhC,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAKzB,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,kBAAkB,EAAE,CAmG5E;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAC7B,WAAW,EAAE,MAAM,GAClB,yBAAyB,GAAG,IAAI,CA8ElC;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,2BAA2B,GACrC,kBAAkB,GAAG,IAAI,CAgC3B"}
@@ -1,7 +1,9 @@
1
- import { DEFAULT_WALL_HEIGHT, getWallCurveFrameAt, getWallThickness, sampleWallCenterline, } from '@pascal-app/core';
1
+ import { getWallArcData, getWallCurveFrameAt, getWallThickness, sampleWallCenterline, useScene, } from '@pascal-app/core';
2
+ import { resolveWallOpeningCeiling } from '../shared/wall-opening-ceiling';
2
3
  const point = (x, y, z) => [x, y, z];
3
4
  export function wallMeasurementFeatures(wall) {
4
- const height = wall.height ?? DEFAULT_WALL_HEIGHT;
5
+ const height = resolveWallOpeningCeiling(wall, useScene.getState().nodes);
6
+ const arc = getWallArcData(wall);
5
7
  const centerline = sampleWallCenterline(wall).map(({ x, y }) => point(x, 0, y));
6
8
  const midpoint = getWallCurveFrameAt(wall, 0.5).point;
7
9
  const halfThickness = getWallThickness(wall) / 2;
@@ -42,6 +44,17 @@ export function wallMeasurementFeatures(wall) {
42
44
  priority: 90,
43
45
  geometry: { kind: 'point', point: point(midpoint.x, 0, midpoint.y) },
44
46
  },
47
+ ...(arc
48
+ ? [
49
+ {
50
+ id: 'wall:curve:center',
51
+ label: 'Wall arc center',
52
+ snapKind: 'center',
53
+ priority: 90,
54
+ geometry: { kind: 'point', point: point(arc.center.x, 0, arc.center.y) },
55
+ },
56
+ ]
57
+ : []),
45
58
  {
46
59
  id: 'wall:face:left',
47
60
  label: 'Wall face',
@@ -132,7 +145,7 @@ export function matchWallMeasurementFeature(wall, hit, maxDistance) {
132
145
  const faceDistance = Math.hypot(hit[0] - faceX, hit[2] - faceZ);
133
146
  const threshold = Math.max(maxDistance, halfThickness + 0.03);
134
147
  if (faceDistance <= threshold && (!best || faceDistance < best.distance)) {
135
- const height = Math.max(0, Math.min(wall.height ?? DEFAULT_WALL_HEIGHT, hit[1]));
148
+ const height = Math.max(0, Math.min(resolveWallOpeningCeiling(wall, useScene.getState().nodes), hit[1]));
136
149
  best = {
137
150
  featureId: side > 0 ? 'wall:face:left' : 'wall:face:right',
138
151
  point: point(faceX, height, faceZ),
@@ -162,7 +175,7 @@ export function resolveWallMeasurementFeature(wall, reference) {
162
175
  if (typeof heightValue !== 'number' || feature.geometry.kind !== 'path') {
163
176
  return normal ? { ...feature, normal } : feature;
164
177
  }
165
- const height = Math.max(0, Math.min(wall.height ?? DEFAULT_WALL_HEIGHT, heightValue));
178
+ const height = Math.max(0, Math.min(resolveWallOpeningCeiling(wall, useScene.getState().nodes), heightValue));
166
179
  return {
167
180
  ...feature,
168
181
  ...(normal ? { normal } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"move-endpoint-tool.d.ts","sourceRoot":"","sources":["../../src/wall/move-endpoint-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAcL,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAyBzB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,QAAQ,CAAA;IACd,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAA;CAC1B,CAAA;AA6HD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,MAAM,EAAE,kBAAkB,CAAA;CAAE,CA4dzE,CAAA;AAkBD,eAAe,oBAAoB,CAAA"}
1
+ {"version":3,"file":"move-endpoint-tool.d.ts","sourceRoot":"","sources":["../../src/wall/move-endpoint-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAeL,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AA2BzB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,QAAQ,CAAA;IACd,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAA;CAC1B,CAAA;AA6HD,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,MAAM,EAAE,kBAAkB,CAAA;CAAE,CAqhBzE,CAAA;AAkBD,eAAe,oBAAoB,CAAA"}
@@ -1,10 +1,12 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { collectAlignmentAnchors, DEFAULT_WALL_HEIGHT, emitter, getWallCurveLength, getWallThickness, pauseSceneHistory, resolveAlignment, resumeSceneHistory, runAsSingleSceneHistoryStep, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
3
+ import { collectAlignmentAnchors, emitter, getWallBaseElevationForNodes, getWallCurveLength, getWallThickness, pauseSceneHistory, resolveAlignment, resolveMovedWallSupportSlabPatch, resumeSceneHistory, runAsSingleSceneHistoryStep, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
4
4
  import { CursorSphere, formatAngleRadians, getAngleToSegmentReference, getSegmentAngleReferenceAtPoint, isAlignmentGuideActive, isAngleSnapActive, isMagneticSnapActive, isSegmentLongEnough, MeasurementPill, markToolCancelConsumed, resolveEndpointWallSplit, snapWallDraftPointDetailed, triggerSFX, useAlignmentGuides, useInteractionScope, useWallSnapIndicator, WALL_CONNECT_SNAP_RADIUS, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { Html } from '@react-three/drei';
7
7
  import { useCallback, useEffect, useRef, useState } from 'react';
8
+ import { LevelOffsetGroup } from '../shared/level-offset-group';
9
+ import { resolveWallOpeningCeiling } from '../shared/wall-opening-ceiling';
8
10
  /** Figma-style alignment-snap threshold (meters), matching the item move /
9
11
  * placement tools. 8 cm gives a magnetic pull without fighting grid snap. */
10
12
  const ALIGNMENT_THRESHOLD_M = 0.08;
@@ -102,6 +104,12 @@ export const MoveWallEndpointTool = ({ target }) => {
102
104
  });
103
105
  const [altPressed, setAltPressed] = useState(false);
104
106
  const unit = useViewer((s) => s.unit);
107
+ const nodes = useScene((state) => state.nodes);
108
+ const liveOverride = useLiveNodeOverrides((state) => state.overrides.get(target.wall.id));
109
+ const effectiveWall = liveOverride
110
+ ? { ...target.wall, ...liveOverride }
111
+ : target.wall;
112
+ const wallBaseElevation = getWallBaseElevationForNodes(effectiveWall, nodes);
105
113
  // Alt-detach only affects walls sharing the moving endpoint; walls linked
106
114
  // solely to the fixed endpoint never move, so the hint would be noise.
107
115
  const movingOriginal = target.endpoint === 'start' ? originalStartRef.current : originalEndRef.current;
@@ -116,18 +124,38 @@ export const MoveWallEndpointTool = ({ target }) => {
116
124
  const originalStart = originalStartRef.current;
117
125
  const originalEnd = originalEndRef.current;
118
126
  const fixedPoint = fixedPointRef.current;
127
+ const movingOriginalPoint = target.endpoint === 'start' ? originalStart : originalEnd;
128
+ // Walls attached to the MOVING corner cascade with the drag, but the snap
129
+ // pipeline reads the scene store, which keeps their pre-drag coordinates
130
+ // until commit. Their stale corners would recreate the old junction as a
131
+ // snap/alignment target: inside the connect radius the endpoint could
132
+ // never land closer than ~5cm to where it started, making sub-5cm
133
+ // corrections (e.g. squaring a scan-imported 91° corner) impossible.
134
+ // Excluded while attached; under Alt-detach they stay put and remain
135
+ // legitimate targets.
136
+ const movingLinkedWallIds = linkedOriginalsRef.current
137
+ .filter((wall) => samePoint(wall.start, movingOriginalPoint) || samePoint(wall.end, movingOriginalPoint))
138
+ .map((wall) => wall.id);
119
139
  const levelWalls = Object.values(useScene.getState().nodes).filter((node) => node?.type === 'wall' && (node.parentId ?? null) === (target.wall.parentId ?? null));
120
140
  // Alignment candidates — anchors of every OTHER alignable object (walls,
121
141
  // fences, items, slabs, ceilings, columns), gathered once (the set is
122
142
  // stable during the drag). Coords are building-local, the same frame as
123
143
  // the cursor and the 3D guide layer, so the published guide lines up.
144
+ // The attached variant additionally drops anchors owned by walls that
145
+ // follow the moving corner (see `movingLinkedWallIds` above) — their
146
+ // scene coordinates are stale during the drag.
124
147
  const wallAlignmentCandidates = collectAlignmentAnchors(useScene.getState().nodes, nodeId);
148
+ const movingLinkedIdSet = new Set(movingLinkedWallIds);
149
+ const attachedAlignmentCandidates = wallAlignmentCandidates.filter((anchor) => !movingLinkedIdSet.has(anchor.nodeId));
125
150
  pauseSceneHistory(useScene);
126
151
  let wasCommitted = false;
127
- // Last point handed to `applyPreview` — lets the Alt keydown/keyup
128
- // handlers re-run the preview immediately on a modifier change instead of
129
- // waiting for the next mousemove.
130
- let lastMovedPoint = null;
152
+ // Last RAW cursor point from `grid:move` — lets the Alt keydown/keyup
153
+ // handlers re-run the FULL snap pipeline immediately on a modifier change
154
+ // instead of waiting for the next mousemove. The raw point (not the
155
+ // snapped one) matters: the snap/alignment candidate set depends on Alt
156
+ // (stale-junction exclusion above), so a point snapped under the previous
157
+ // modifier state must not be reused as-is.
158
+ let lastRawPoint = null;
131
159
  // The first pointer-up is the *grab* of a click-to-move; later ones are
132
160
  // drops. See the `!hasChanged` branch in `onPointerUp`.
133
161
  let hasReleasedOnce = false;
@@ -160,7 +188,6 @@ export const MoveWallEndpointTool = ({ target }) => {
160
188
  touchedWallIds.clear();
161
189
  };
162
190
  const applyPreview = (movingPoint, detachLinkedWalls = false) => {
163
- lastMovedPoint = movingPoint;
164
191
  const nextStart = target.endpoint === 'start' ? movingPoint : fixedPoint;
165
192
  const nextEnd = target.endpoint === 'end' ? movingPoint : fixedPoint;
166
193
  const linkedUpdates = detachLinkedWalls
@@ -213,16 +240,18 @@ export const MoveWallEndpointTool = ({ target }) => {
213
240
  window.addEventListener('click', swallow, { capture: true, once: true });
214
241
  setTimeout(() => window.removeEventListener('click', swallow, { capture: true }), 300);
215
242
  };
216
- const onGridMove = (event) => {
217
- const planPoint = [event.localPosition[0], event.localPosition[2]];
218
- // Endpoint move honours the active snapping mode (the HUD chip): grid →
219
- // lattice; lines → magnetic corner/alignment snap; angles → lock the
220
- // segment to 15° rays from the FIXED corner; off → raw. No Shift bypass —
221
- // Shift cycles the mode now, and Off is the bypass.
243
+ // Full snap pipeline from a RAW cursor point to the applied endpoint —
244
+ // shared by `grid:move` and the Alt keydown/keyup handlers, since the
245
+ // candidate set (stale-junction exclusion) flips with the modifier.
246
+ // Endpoint move honours the active snapping mode (the HUD chip): grid →
247
+ // lattice; lines → magnetic corner/alignment snap; angles → lock the
248
+ // segment to 15° rays from the FIXED corner; off → raw. No Shift bypass —
249
+ // Shift cycles the mode now, and Off is the bypass.
250
+ const resolveDragPoint = (planPoint) => {
222
251
  const snapResult = snapWallDraftPointDetailed({
223
252
  point: planPoint,
224
253
  walls: levelWalls,
225
- ignoreWallIds: [nodeId],
254
+ ignoreWallIds: altPressedRef.current ? [nodeId] : [nodeId, ...movingLinkedWallIds],
226
255
  start: fixedPoint,
227
256
  angleSnap: isAngleSnapActive(),
228
257
  magnetic: isMagneticSnapActive(),
@@ -238,10 +267,13 @@ export const MoveWallEndpointTool = ({ target }) => {
238
267
  // (isAlignmentGuideActive); the magnetic pull onto them is applied only in
239
268
  // 'lines' mode (isMagneticSnapActive).
240
269
  let alignedPoint = snappedPoint;
241
- if (isAlignmentGuideActive() && wallAlignmentCandidates.length > 0) {
270
+ const alignmentCandidates = altPressedRef.current
271
+ ? wallAlignmentCandidates
272
+ : attachedAlignmentCandidates;
273
+ if (isAlignmentGuideActive() && alignmentCandidates.length > 0) {
242
274
  const ar = resolveAlignment({
243
275
  moving: [{ nodeId, kind: 'corner', x: snappedPoint[0], z: snappedPoint[1] }],
244
- candidates: wallAlignmentCandidates,
276
+ candidates: alignmentCandidates,
245
277
  threshold: ALIGNMENT_THRESHOLD_M,
246
278
  });
247
279
  const magnetic = isMagneticSnapActive();
@@ -273,14 +305,20 @@ export const MoveWallEndpointTool = ({ target }) => {
273
305
  .set(snapResult.snap
274
306
  ? { x: alignedPoint[0], z: alignedPoint[1], kind: snapResult.snap }
275
307
  : null);
308
+ return alignedPoint;
309
+ };
310
+ const onGridMove = (event) => {
311
+ const planPoint = [event.localPosition[0], event.localPosition[2]];
312
+ lastRawPoint = planPoint;
276
313
  // The keydown listener can't observe an Alt press that predates the
277
314
  // tool mounting; the pointer event can. Sync the shared ref (single Alt
278
- // source for preview, HUD badge, and commit) before applying.
315
+ // source for snap targets, preview, HUD badge, and commit) before the
316
+ // snap pipeline reads it.
279
317
  if (event.nativeEvent.altKey !== altPressedRef.current) {
280
318
  altPressedRef.current = event.nativeEvent.altKey;
281
319
  setAltPressed(event.nativeEvent.altKey);
282
320
  }
283
- applyPreview(alignedPoint, altPressedRef.current);
321
+ applyPreview(resolveDragPoint(planPoint), altPressedRef.current);
284
322
  };
285
323
  const onPointerUp = () => {
286
324
  useAlignmentGuides.getState().clear();
@@ -353,6 +391,14 @@ export const MoveWallEndpointTool = ({ target }) => {
353
391
  },
354
392
  })),
355
393
  ]);
394
+ const affectedIds = [nodeId, ...linkedUpdates.map((u) => u.id)];
395
+ const committedNodes = useScene.getState().nodes;
396
+ useScene.getState().updateNodes(affectedIds.flatMap((id) => {
397
+ const wall = committedNodes[id];
398
+ return wall?.type === 'wall'
399
+ ? [{ id, data: resolveMovedWallSupportSlabPatch(wall, committedNodes) }]
400
+ : [];
401
+ }));
356
402
  useScene.getState().markDirty(nodeId);
357
403
  for (const u of linkedUpdates) {
358
404
  useScene.getState().markDirty(u.id);
@@ -375,17 +421,18 @@ export const MoveWallEndpointTool = ({ target }) => {
375
421
  markToolCancelConsumed();
376
422
  exitMoveMode();
377
423
  };
378
- // Single Alt writer for keyboard transitions. Re-running the preview on
379
- // the flip keeps geometry and the HUD badge in lockstep — detach reverts
380
- // the linked walls instantly, re-attach snaps them onto the dragged point
381
- // — without waiting for the next mousemove.
424
+ // Single Alt writer for keyboard transitions. Re-running the FULL snap
425
+ // pipeline from the raw cursor on the flip keeps geometry and the HUD
426
+ // badge in lockstep — detach reverts the linked walls instantly and
427
+ // re-snaps against their (now live) corners, re-attach drops them from
428
+ // the candidate set again — without waiting for the next mousemove.
382
429
  const setAltState = (pressed) => {
383
430
  if (altPressedRef.current === pressed)
384
431
  return;
385
432
  altPressedRef.current = pressed;
386
433
  setAltPressed(pressed);
387
- if (lastMovedPoint) {
388
- applyPreview(lastMovedPoint, pressed);
434
+ if (lastRawPoint) {
435
+ applyPreview(resolveDragPoint(lastRawPoint), pressed);
389
436
  }
390
437
  };
391
438
  const onKeyDown = (event) => {
@@ -437,12 +484,12 @@ export const MoveWallEndpointTool = ({ target }) => {
437
484
  end: previewEnd,
438
485
  curveOffset: target.wall.curveOffset,
439
486
  });
440
- const wallHeight = target.wall.height ?? DEFAULT_WALL_HEIGHT;
487
+ const wallHeight = resolveWallOpeningCeiling(effectiveWall, nodes);
441
488
  const dimMidX = (previewStart[0] + previewEnd[0]) / 2;
442
489
  const dimMidZ = (previewStart[1] + previewEnd[1]) / 2;
443
- return (_jsxs("group", { children: [_jsx(CursorSphere, { position: cursorLocalPos, showTooltip: false }), _jsx(Html, { center: true, position: [dimMidX, wallHeight + 0.3, dimMidZ], style: { pointerEvents: 'none', touchAction: 'none' }, zIndexRange: [100, 0], children: _jsx(MeasurementPill, { height: wallHeight, length: liveLength, primary: "length", thickness: getWallThickness(target.wall), unit: unit }) }), canDetachCorner && (_jsx(Html, { position: [cursorLocalPos[0], 0, cursorLocalPos[2]], style: { pointerEvents: 'none', touchAction: 'none' }, zIndexRange: [100, 0], children: _jsx("div", { className: "translate-y-10", children: _jsx("div", { className: `whitespace-nowrap rounded-full border px-2 py-1 font-medium text-[11px] shadow-lg backdrop-blur-md transition-colors ${altPressed
444
- ? 'border-amber-500/80 bg-amber-500/15 text-amber-100'
445
- : 'border-border bg-background/95 text-muted-foreground'}`, children: altPressed ? 'Detaching corner' : 'Alt to detach' }) }) })), angleLabel && _jsx(EndpointAngleLabel, { label: angleLabel.label, position: angleLabel.position })] }));
490
+ return (_jsx(LevelOffsetGroup, { children: _jsxs("group", { position: [0, wallBaseElevation, 0], children: [_jsx(CursorSphere, { position: cursorLocalPos, showTooltip: false }), _jsx(Html, { center: true, position: [dimMidX, wallHeight + 0.3, dimMidZ], style: { pointerEvents: 'none', touchAction: 'none' }, zIndexRange: [100, 0], children: _jsx(MeasurementPill, { height: wallHeight, length: liveLength, primary: "length", thickness: getWallThickness(effectiveWall), unit: unit }) }), canDetachCorner && (_jsx(Html, { position: [cursorLocalPos[0], 0, cursorLocalPos[2]], style: { pointerEvents: 'none', touchAction: 'none' }, zIndexRange: [100, 0], children: _jsx("div", { className: "translate-y-10", children: _jsx("div", { className: `whitespace-nowrap rounded-full border px-2 py-1 font-medium text-[11px] shadow-lg backdrop-blur-md transition-colors ${altPressed
491
+ ? 'border-amber-500/80 bg-amber-500/15 text-amber-100'
492
+ : 'border-border bg-background/95 text-muted-foreground'}`, children: altPressed ? 'Detaching corner' : 'Alt to detach' }) }) })), angleLabel && (_jsx(EndpointAngleLabel, { label: angleLabel.label, position: angleLabel.position }))] }) }));
446
493
  };
447
494
  function EndpointAngleLabel({ label, position, }) {
448
495
  return (_jsx(Html, { center: true, position: position, style: { pointerEvents: 'none' }, zIndexRange: [100, 0], children: _jsx("div", { className: "whitespace-nowrap rounded-full border border-border bg-background/95 px-2 py-1 font-mono font-semibold text-[11px] text-foreground shadow-lg backdrop-blur-md", children: label }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"move-shared.d.ts","sourceRoot":"","sources":["../../src/wall/move-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAMd,QAAQ,EACR,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EACb,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAA;AAazB,wBAAgB,SAAS,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,WAE3D;AAMD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,CAQvF;AAED,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAA;AAEzC;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;IACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,aAAa,EAAE,aAAa,CAAA;IAC5B,WAAW,EAAE,aAAa,CAAA;CAC3B,GAAG,kBAAkB,EAAE,CA2CvB;AA0BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,UAiB/C;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACpD,OAAO,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC,GACzD,QAAQ,EAAE,CASZ;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,WAAW,EAAE,KAAK,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAAA;IAC1D,SAAS,EAAE,aAAa,CAAA;IACxB,OAAO,EAAE,aAAa,CAAA;IACtB,aAAa,EAAE,QAAQ,EAAE,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC,CAkClD;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,aAAa,CAAA;IACpB,GAAG,EAAE,aAAa,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,WAAW,EAAE,KAAK,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAAA;IAC1D,SAAS,EAAE,aAAa,CAAA;IACxB,OAAO,EAAE,aAAa,CAAA;IACtB,aAAa,EAAE,QAAQ,EAAE,CAAA;CAC1B,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAqCrD"}
1
+ {"version":3,"file":"move-shared.d.ts","sourceRoot":"","sources":["../../src/wall/move-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EAKd,QAAQ,EACR,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EACb,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAA;AAczB,wBAAgB,SAAS,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,WAE3D;AAMD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,CAQvF;AAED,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAA;AAEzC;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;IACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,aAAa,EAAE,aAAa,CAAA;IAC5B,WAAW,EAAE,aAAa,CAAA;CAC3B,GAAG,kBAAkB,EAAE,CA2CvB;AA0BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,UAiB/C;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACpD,OAAO,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC,GACzD,QAAQ,EAAE,CASZ;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,WAAW,EAAE,KAAK,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAAA;IAC1D,SAAS,EAAE,aAAa,CAAA;IACxB,OAAO,EAAE,aAAa,CAAA;IACtB,aAAa,EAAE,QAAQ,EAAE,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC,CAkClD;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,aAAa,CAAA;IACpB,GAAG,EAAE,aAAa,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAC5C,WAAW,EAAE,KAAK,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAAA;IAC1D,SAAS,EAAE,aAAa,CAAA;IACxB,OAAO,EAAE,aAAa,CAAA;IACtB,aAAa,EAAE,QAAQ,EAAE,CAAA;CAC1B,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAqCrD"}
@@ -1,5 +1,6 @@
1
- import { DEFAULT_WALL_HEIGHT, getMaterialPresetByRef, parseMaterialRef, resolveMaterial, useScene, WallNode as WallSchema, } from '@pascal-app/core';
1
+ import { getMaterialPresetByRef, parseMaterialRef, resolveMaterial, useScene, WallNode as WallSchema, } from '@pascal-app/core';
2
2
  import { isSegmentLongEnough } from '@pascal-app/editor';
3
+ import { resolveWallOpeningCeiling } from '../shared/wall-opening-ceiling';
3
4
  /**
4
5
  * Pure helpers shared by the 3D `MoveWallTool` and the 2D
5
6
  * `wallFloorplanMoveTarget`. Lives in `packages/nodes` because the
@@ -153,7 +154,7 @@ export function buildBridgeWallPreviews(args) {
153
154
  start: [...plan.originalPoint],
154
155
  end: [...nextPoint],
155
156
  color: getWallGhostColor(plan.wall),
156
- height: plan.wall.height ?? DEFAULT_WALL_HEIGHT,
157
+ height: resolveWallOpeningCeiling(plan.wall, useScene.getState().nodes),
157
158
  };
158
159
  previews.push({ ghost, wall });
159
160
  wallsForDuplicateCheck.push(wall);
@@ -1 +1 @@
1
- {"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/wall/move-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAqBL,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAqIzB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CA6hBrD,CAAA;AAED,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/wall/move-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAwBL,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAqIzB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CA4iBrD,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { detectSpacesForLevel, emitter, getPerpendicularWallMoveAxis, getPlannedLinkedWallUpdates, pauseSceneHistory, planAutoCeilingsForLevel, planAutoSlabsForLevel, planWallMoveJunctions, projectAutoSlabsForPlan, resumeSceneHistory, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
3
+ import { detectSpacesForLevel, emitter, getCeilingClampBound, getPerpendicularWallMoveAxis, getPlannedLinkedWallUpdates, getStoredLevelHeight, pauseSceneHistory, planAutoCeilingsForLevel, planAutoSlabsForLevel, planWallMoveJunctions, resolveMovedWallSupportSlabPatch, resumeSceneHistory, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
4
4
  import { CursorSphere, EDITOR_LAYER, getSegmentGridStep, isSegmentLongEnough, markToolCancelConsumed, snapBuildingLocalToWorldGrid, snapScalarToGrid, triggerSFX, useEditor, } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
@@ -182,9 +182,10 @@ export const MoveWallTool = ({ node }) => {
182
182
  // re-flowed through the planner.
183
183
  const existingSlabs = getLevelSlabs(levelId, sceneState.nodes);
184
184
  const slabPlan = planAutoSlabsForLevel(roomPolygons, existingSlabs);
185
+ const levelNode = sceneState.nodes[levelId];
185
186
  const ceilingPlan = planAutoCeilingsForLevel(roomPolygons, getLevelCeilings(levelId, sceneState.nodes), {
186
- walls: levelWalls,
187
- slabs: projectAutoSlabsForPlan(existingSlabs, slabPlan),
187
+ storeyHeight: levelNode?.type === 'level' ? getStoredLevelHeight(levelNode) : undefined,
188
+ ceilingClampBound: (polygon) => getCeilingClampBound(levelId, sceneState.nodes, polygon),
188
189
  });
189
190
  latestSurfacePlans = { slabs: slabPlan, ceilings: ceilingPlan };
190
191
  const overrideEntries = [];
@@ -435,6 +436,17 @@ export const MoveWallTool = ({ node }) => {
435
436
  // undoable step. Then drop the live overrides — the renderer
436
437
  // now reads the committed walls + polygons directly.
437
438
  commitSurfacesToStore();
439
+ const affectedWallIds = [
440
+ ...commitUpdates.map((entry) => entry.id),
441
+ ...bridgeCreates.map((entry) => entry.node.id),
442
+ ];
443
+ const committedNodes = useScene.getState().nodes;
444
+ useScene.getState().updateNodes(affectedWallIds.flatMap((id) => {
445
+ const wall = committedNodes[id];
446
+ return wall?.type === 'wall'
447
+ ? [{ id, data: resolveMovedWallSupportSlabPatch(wall, committedNodes) }]
448
+ : [];
449
+ }));
438
450
  clearSurfaceOverrides();
439
451
  clearWallOverrides();
440
452
  pauseSceneHistory(useScene);
@@ -1 +1 @@
1
- {"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/wall/paint.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,eAAe,EAOpB,KAAK,QAAQ,EAGd,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAA2C,KAAK,GAAG,EAAa,MAAM,OAAO,CAAA;AAmDpF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,IAAI,EAAE,QAAQ,CAAA;IACd,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IAC/C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IACrD,aAAa,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IAC5D,GAAG,CAAC,EAAE,GAAG,CAAA;CACV,GAAG,MAAM,GAAG,IAAI,CAmDhB;AAqCD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,eAoCtB,CAAA"}
1
+ {"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/wall/paint.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,eAAe,EAOpB,KAAK,QAAQ,EAGd,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAA2C,KAAK,GAAG,EAAa,MAAM,OAAO,CAAA;AAoDpF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,IAAI,EAAE,QAAQ,CAAA;IACd,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;IAC/C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IACrD,aAAa,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;IAC5D,GAAG,CAAC,EAAE,GAAG,CAAA;CACV,GAAG,MAAM,GAAG,IAAI,CA+DhB;AAqCD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,eAoCtB,CAAA"}