@pascal-app/nodes 1.0.3 → 1.0.4

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 (708) hide show
  1. package/dist/block/definition.d.ts.map +1 -1
  2. package/dist/block/definition.js +18 -3
  3. package/dist/block/floorplan.d.ts +11 -1
  4. package/dist/block/floorplan.d.ts.map +1 -1
  5. package/dist/block/floorplan.js +81 -13
  6. package/dist/block/geometry.d.ts +2 -2
  7. package/dist/block/geometry.d.ts.map +1 -1
  8. package/dist/block/geometry.js +39 -24
  9. package/dist/block/hosted-edit.d.ts.map +1 -1
  10. package/dist/block/hosted-edit.js +25 -0
  11. package/dist/block/material-slots.d.ts +1 -3
  12. package/dist/block/material-slots.d.ts.map +1 -1
  13. package/dist/block/material-slots.js +1 -11
  14. package/dist/block/paint.d.ts.map +1 -1
  15. package/dist/block/paint.js +4 -10
  16. package/dist/block/panel.d.ts.map +1 -1
  17. package/dist/block/panel.js +8 -3
  18. package/dist/block/selection.d.ts.map +1 -1
  19. package/dist/block/selection.js +2 -2
  20. package/dist/box-vent/definition.d.ts.map +1 -1
  21. package/dist/box-vent/definition.js +2 -5
  22. package/dist/box-vent/panel.d.ts.map +1 -1
  23. package/dist/box-vent/panel.js +5 -28
  24. package/dist/cabinet/countertop-layout.d.ts +13 -2
  25. package/dist/cabinet/countertop-layout.d.ts.map +1 -1
  26. package/dist/cabinet/definition.d.ts.map +1 -1
  27. package/dist/cabinet/definition.js +1 -2
  28. package/dist/cabinet/floorplan.d.ts.map +1 -1
  29. package/dist/cabinet/floorplan.js +125 -28
  30. package/dist/cabinet/geometry/shared.d.ts +1 -2
  31. package/dist/cabinet/geometry/shared.d.ts.map +1 -1
  32. package/dist/cabinet/geometry/shared.js +1 -2
  33. package/dist/cabinet/run-layout.d.ts.map +1 -1
  34. package/dist/cabinet/run-layout.js +8 -5
  35. package/dist/cabinet/run-ops.d.ts +13 -2
  36. package/dist/cabinet/run-ops.d.ts.map +1 -1
  37. package/dist/cabinet/tool.d.ts.map +1 -1
  38. package/dist/cabinet/tool.js +22 -24
  39. package/dist/cabinet/wall-snap.d.ts.map +1 -1
  40. package/dist/cabinet/wall-snap.js +8 -8
  41. package/dist/ceiling/boundary-editor.d.ts.map +1 -1
  42. package/dist/ceiling/boundary-editor.js +5 -3
  43. package/dist/ceiling/definition.d.ts +4 -4
  44. package/dist/ceiling/definition.d.ts.map +1 -1
  45. package/dist/ceiling/definition.js +15 -15
  46. package/dist/ceiling/floorplan-affordances.d.ts +84 -4
  47. package/dist/ceiling/floorplan-affordances.d.ts.map +1 -1
  48. package/dist/ceiling/floorplan-affordances.js +0 -1
  49. package/dist/ceiling/floorplan-move.d.ts.map +1 -1
  50. package/dist/ceiling/floorplan-move.js +0 -1
  51. package/dist/ceiling/floorplan.d.ts +1 -1
  52. package/dist/ceiling/floorplan.d.ts.map +1 -1
  53. package/dist/ceiling/floorplan.js +2 -1
  54. package/dist/ceiling/height-bounds.d.ts +19 -0
  55. package/dist/ceiling/height-bounds.d.ts.map +1 -0
  56. package/dist/ceiling/height-bounds.js +24 -0
  57. package/dist/ceiling/hole-editor.d.ts.map +1 -1
  58. package/dist/ceiling/hole-editor.js +3 -4
  59. package/dist/ceiling/materials.d.ts +1 -1
  60. package/dist/ceiling/materials.d.ts.map +1 -1
  61. package/dist/ceiling/materials.js +10 -3
  62. package/dist/ceiling/paint.d.ts +2 -8
  63. package/dist/ceiling/paint.d.ts.map +1 -1
  64. package/dist/ceiling/paint.js +121 -24
  65. package/dist/ceiling/panel.d.ts.map +1 -1
  66. package/dist/ceiling/panel.js +40 -23
  67. package/dist/ceiling/renderer.d.ts.map +1 -1
  68. package/dist/ceiling/renderer.js +41 -5
  69. package/dist/chimney/move-tool.d.ts.map +1 -1
  70. package/dist/chimney/move-tool.js +8 -2
  71. package/dist/chimney/paint.d.ts.map +1 -1
  72. package/dist/chimney/paint.js +3 -10
  73. package/dist/column/definition.d.ts.map +1 -1
  74. package/dist/column/definition.js +24 -2
  75. package/dist/column/floorplan-affordances.d.ts.map +1 -1
  76. package/dist/column/floorplan-affordances.js +5 -0
  77. package/dist/column/floorplan.d.ts +1 -1
  78. package/dist/column/floorplan.d.ts.map +1 -1
  79. package/dist/column/floorplan.js +47 -2
  80. package/dist/column/hosted-resize.d.ts +101 -2
  81. package/dist/column/hosted-resize.d.ts.map +1 -1
  82. package/dist/column/panel.d.ts.map +1 -1
  83. package/dist/column/panel.js +147 -146
  84. package/dist/column/renderer.d.ts.map +1 -1
  85. package/dist/column/renderer.js +6 -4
  86. package/dist/column/surface.d.ts.map +1 -1
  87. package/dist/column/surface.js +7 -0
  88. package/dist/construction-dimension/floorplan.js +7 -3
  89. package/dist/cupola/definition.d.ts.map +1 -1
  90. package/dist/cupola/definition.js +2 -8
  91. package/dist/cupola/panel.d.ts.map +1 -1
  92. package/dist/cupola/panel.js +5 -23
  93. package/dist/door/definition.d.ts.map +1 -1
  94. package/dist/door/definition.js +12 -3
  95. package/dist/door/door-math.d.ts +5 -10
  96. package/dist/door/door-math.d.ts.map +1 -1
  97. package/dist/door/door-math.js +14 -15
  98. package/dist/door/floorplan-move.d.ts.map +1 -1
  99. package/dist/door/floorplan-move.js +3 -1
  100. package/dist/door/floorplan.d.ts.map +1 -1
  101. package/dist/door/floorplan.js +55 -21
  102. package/dist/door/mechanism.d.ts +4 -0
  103. package/dist/door/mechanism.d.ts.map +1 -0
  104. package/dist/door/mechanism.js +24 -0
  105. package/dist/door/move-tool.d.ts.map +1 -1
  106. package/dist/door/move-tool.js +72 -48
  107. package/dist/door/paint.d.ts.map +1 -1
  108. package/dist/door/paint.js +3 -0
  109. package/dist/door/panel.d.ts.map +1 -1
  110. package/dist/door/panel.js +34 -259
  111. package/dist/door/placement.d.ts +45 -0
  112. package/dist/door/placement.d.ts.map +1 -0
  113. package/dist/door/placement.js +51 -0
  114. package/dist/door/preview.d.ts.map +1 -1
  115. package/dist/door/preview.js +2 -0
  116. package/dist/door/renderer.d.ts.map +1 -1
  117. package/dist/door/renderer.js +3 -2
  118. package/dist/door/tool.d.ts.map +1 -1
  119. package/dist/door/tool.js +92 -21
  120. package/dist/dormer/csg-geometry.d.ts.map +1 -1
  121. package/dist/dormer/csg-geometry.js +2 -0
  122. package/dist/dormer/paint.d.ts.map +1 -1
  123. package/dist/dormer/paint.js +2 -5
  124. package/dist/dormer/panel.d.ts.map +1 -1
  125. package/dist/dormer/panel.js +4 -14
  126. package/dist/downspout/definition.d.ts.map +1 -1
  127. package/dist/downspout/definition.js +2 -2
  128. package/dist/duct-fitting/definition.d.ts.map +1 -1
  129. package/dist/duct-fitting/definition.js +2 -1
  130. package/dist/duct-fitting/geometry.d.ts.map +1 -1
  131. package/dist/duct-fitting/geometry.js +1 -1
  132. package/dist/duct-fitting/move-tool.d.ts.map +1 -1
  133. package/dist/duct-fitting/move-tool.js +8 -2
  134. package/dist/duct-segment/definition.d.ts.map +1 -1
  135. package/dist/duct-segment/definition.js +2 -2
  136. package/dist/duct-segment/geometry.d.ts.map +1 -1
  137. package/dist/duct-segment/geometry.js +1 -1
  138. package/dist/duct-segment/move-tool.d.ts.map +1 -1
  139. package/dist/duct-segment/move-tool.js +8 -2
  140. package/dist/elevator/definition.d.ts.map +1 -1
  141. package/dist/elevator/definition.js +1 -2
  142. package/dist/elevator/panel.d.ts.map +1 -1
  143. package/dist/elevator/panel.js +5 -27
  144. package/dist/elevator/parametrics.js +1 -1
  145. package/dist/elevator/renderer.d.ts.map +1 -1
  146. package/dist/elevator/renderer.js +3 -4
  147. package/dist/eyebrow-vent/definition.d.ts.map +1 -1
  148. package/dist/eyebrow-vent/definition.js +2 -5
  149. package/dist/eyebrow-vent/paint.d.ts.map +1 -1
  150. package/dist/eyebrow-vent/paint.js +3 -6
  151. package/dist/eyebrow-vent/panel.d.ts.map +1 -1
  152. package/dist/eyebrow-vent/panel.js +5 -23
  153. package/dist/fence/actions/move-endpoint.d.ts +1 -1
  154. package/dist/fence/actions/move-endpoint.d.ts.map +1 -1
  155. package/dist/fence/actions/move-endpoint.js +2 -1
  156. package/dist/fence/definition.d.ts +2 -1
  157. package/dist/fence/definition.d.ts.map +1 -1
  158. package/dist/fence/definition.js +83 -28
  159. package/dist/fence/drafting.d.ts +36 -0
  160. package/dist/fence/drafting.d.ts.map +1 -0
  161. package/dist/fence/drafting.js +210 -0
  162. package/dist/fence/feature-tool.d.ts +4 -0
  163. package/dist/fence/feature-tool.d.ts.map +1 -0
  164. package/dist/fence/feature-tool.js +140 -0
  165. package/dist/fence/features.d.ts +2 -0
  166. package/dist/fence/features.d.ts.map +1 -0
  167. package/dist/fence/features.js +12 -0
  168. package/dist/fence/floorplan-affordances.d.ts.map +1 -1
  169. package/dist/fence/floorplan-affordances.js +2 -1
  170. package/dist/fence/floorplan.d.ts +2 -3
  171. package/dist/fence/floorplan.d.ts.map +1 -1
  172. package/dist/fence/floorplan.js +131 -71
  173. package/dist/fence/geometry-parts.d.ts +50 -0
  174. package/dist/fence/geometry-parts.d.ts.map +1 -0
  175. package/dist/fence/geometry-parts.js +1144 -0
  176. package/dist/fence/geometry.d.ts +2 -3
  177. package/dist/fence/geometry.d.ts.map +1 -1
  178. package/dist/fence/geometry.js +84 -7
  179. package/dist/fence/index.d.ts +1 -0
  180. package/dist/fence/index.d.ts.map +1 -1
  181. package/dist/fence/index.js +1 -0
  182. package/dist/fence/inspector-editors.d.ts +15 -0
  183. package/dist/fence/inspector-editors.d.ts.map +1 -1
  184. package/dist/fence/inspector-editors.js +128 -3
  185. package/dist/fence/lift.d.ts.map +1 -1
  186. package/dist/fence/lift.js +5 -2
  187. package/dist/fence/move-tool.js +2 -1
  188. package/dist/fence/panel-model.d.ts +4 -0
  189. package/dist/fence/panel-model.d.ts.map +1 -0
  190. package/dist/fence/panel-model.js +12 -0
  191. package/dist/fence/parametrics.d.ts +0 -12
  192. package/dist/fence/parametrics.d.ts.map +1 -1
  193. package/dist/fence/parametrics.js +185 -18
  194. package/dist/fence/system.d.ts.map +1 -1
  195. package/dist/fence/system.js +141 -31
  196. package/dist/fence/tool.d.ts.map +1 -1
  197. package/dist/fence/tool.js +256 -47
  198. package/dist/fence-feature/actions.d.ts +7 -0
  199. package/dist/fence-feature/actions.d.ts.map +1 -0
  200. package/dist/fence-feature/actions.js +26 -0
  201. package/dist/fence-feature/definition.d.ts +4 -0
  202. package/dist/fence-feature/definition.d.ts.map +1 -0
  203. package/dist/fence-feature/definition.js +112 -0
  204. package/dist/fence-feature/floorplan-affordances.d.ts +3 -0
  205. package/dist/fence-feature/floorplan-affordances.d.ts.map +1 -0
  206. package/dist/fence-feature/floorplan-affordances.js +37 -0
  207. package/dist/fence-feature/floorplan.d.ts +4 -0
  208. package/dist/fence-feature/floorplan.d.ts.map +1 -0
  209. package/dist/fence-feature/floorplan.js +120 -0
  210. package/dist/fence-feature/geometry.d.ts +5 -0
  211. package/dist/fence-feature/geometry.d.ts.map +1 -0
  212. package/dist/fence-feature/geometry.js +43 -0
  213. package/dist/fence-feature/handles.d.ts +5 -0
  214. package/dist/fence-feature/handles.d.ts.map +1 -0
  215. package/dist/fence-feature/handles.js +84 -0
  216. package/dist/fence-feature/inspector.d.ts +6 -0
  217. package/dist/fence-feature/inspector.d.ts.map +1 -0
  218. package/dist/fence-feature/inspector.js +214 -0
  219. package/dist/fence-feature/interaction.d.ts +3 -0
  220. package/dist/fence-feature/interaction.d.ts.map +1 -0
  221. package/dist/fence-feature/interaction.js +41 -0
  222. package/dist/fence-feature/move-session.d.ts +9 -0
  223. package/dist/fence-feature/move-session.d.ts.map +1 -0
  224. package/dist/fence-feature/move-session.js +48 -0
  225. package/dist/fence-feature/move-tool.d.ts +5 -0
  226. package/dist/fence-feature/move-tool.d.ts.map +1 -0
  227. package/dist/fence-feature/move-tool.js +58 -0
  228. package/dist/fence-feature/pick-target.d.ts +7 -0
  229. package/dist/fence-feature/pick-target.d.ts.map +1 -0
  230. package/dist/fence-feature/pick-target.js +52 -0
  231. package/dist/floor-opening/definition.d.ts +3 -0
  232. package/dist/floor-opening/definition.d.ts.map +1 -0
  233. package/dist/floor-opening/definition.js +41 -0
  234. package/dist/floor-opening/floorplan.d.ts +156 -0
  235. package/dist/floor-opening/floorplan.d.ts.map +1 -0
  236. package/dist/floor-opening/floorplan.js +63 -0
  237. package/dist/gutter/definition.d.ts.map +1 -1
  238. package/dist/gutter/definition.js +2 -2
  239. package/dist/imported-mesh/definition.d.ts.map +1 -1
  240. package/dist/imported-mesh/definition.js +2 -0
  241. package/dist/imported-mesh/geometry.d.ts +1 -1
  242. package/dist/imported-mesh/geometry.d.ts.map +1 -1
  243. package/dist/imported-mesh/geometry.js +40 -12
  244. package/dist/index.d.ts +13 -2
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js +20 -2
  247. package/dist/item/authored-face-host.d.ts +10 -0
  248. package/dist/item/authored-face-host.d.ts.map +1 -0
  249. package/dist/item/authored-face-host.js +87 -0
  250. package/dist/item/authored-params.d.ts +15 -0
  251. package/dist/item/authored-params.d.ts.map +1 -0
  252. package/dist/item/authored-params.js +72 -0
  253. package/dist/item/definition.d.ts +2 -2
  254. package/dist/item/definition.d.ts.map +1 -1
  255. package/dist/item/definition.js +33 -4
  256. package/dist/item/floorplan.d.ts +1 -1
  257. package/dist/item/floorplan.d.ts.map +1 -1
  258. package/dist/item/floorplan.js +35 -5
  259. package/dist/item/index.d.ts +1 -0
  260. package/dist/item/index.d.ts.map +1 -1
  261. package/dist/item/index.js +1 -0
  262. package/dist/item/model-loader.d.ts +2 -0
  263. package/dist/item/model-loader.d.ts.map +1 -1
  264. package/dist/item/model-loader.js +55 -23
  265. package/dist/item/move-tool.js +4 -4
  266. package/dist/item/paint.d.ts.map +1 -1
  267. package/dist/item/paint.js +5 -24
  268. package/dist/item/panel.d.ts +1 -3
  269. package/dist/item/panel.d.ts.map +1 -1
  270. package/dist/item/panel.js +20 -24
  271. package/dist/item/placement-notice.d.ts +14 -0
  272. package/dist/item/placement-notice.d.ts.map +1 -0
  273. package/dist/item/placement-notice.js +38 -0
  274. package/dist/item/plan-symbols.d.ts +67 -0
  275. package/dist/item/plan-symbols.d.ts.map +1 -0
  276. package/dist/item/plan-symbols.js +407 -0
  277. package/dist/item/renderer.d.ts +10 -0
  278. package/dist/item/renderer.d.ts.map +1 -1
  279. package/dist/item/renderer.js +64 -38
  280. package/dist/item/script-param-defaults.d.ts +12 -0
  281. package/dist/item/script-param-defaults.d.ts.map +1 -0
  282. package/dist/item/script-param-defaults.js +34 -0
  283. package/dist/lean-to-extension/definition.d.ts.map +1 -1
  284. package/dist/lean-to-extension/definition.js +1 -2
  285. package/dist/lean-to-extension/geometry.d.ts.map +1 -1
  286. package/dist/lean-to-extension/geometry.js +1 -1
  287. package/dist/lean-to-extension/layout.d.ts.map +1 -1
  288. package/dist/lean-to-extension/layout.js +2 -3
  289. package/dist/lean-to-extension/placement-validation.d.ts.map +1 -1
  290. package/dist/lean-to-extension/placement-validation.js +5 -5
  291. package/dist/lean-to-extension/tool.d.ts.map +1 -1
  292. package/dist/lean-to-extension/tool.js +5 -5
  293. package/dist/lineset/move-tool.d.ts.map +1 -1
  294. package/dist/lineset/move-tool.js +8 -2
  295. package/dist/liquid-line/move-tool.d.ts.map +1 -1
  296. package/dist/liquid-line/move-tool.js +8 -2
  297. package/dist/measurement/definition.js +1 -1
  298. package/dist/pipe-fitting/move-tool.d.ts.map +1 -1
  299. package/dist/pipe-fitting/move-tool.js +8 -2
  300. package/dist/pipe-segment/move-tool.d.ts.map +1 -1
  301. package/dist/pipe-segment/move-tool.js +8 -2
  302. package/dist/procedural-item/animation.d.ts +8 -0
  303. package/dist/procedural-item/animation.d.ts.map +1 -0
  304. package/dist/procedural-item/animation.js +116 -0
  305. package/dist/procedural-item/definition.d.ts.map +1 -1
  306. package/dist/procedural-item/definition.js +74 -8
  307. package/dist/procedural-item/geometry.d.ts +5 -1
  308. package/dist/procedural-item/geometry.d.ts.map +1 -1
  309. package/dist/procedural-item/geometry.js +239 -15
  310. package/dist/procedural-item/renderer.d.ts.map +1 -1
  311. package/dist/procedural-item/renderer.js +272 -23
  312. package/dist/ridge-vent/panel.d.ts.map +1 -1
  313. package/dist/ridge-vent/panel.js +5 -23
  314. package/dist/ridge-vent/renderer.d.ts.map +1 -1
  315. package/dist/ridge-vent/renderer.js +9 -8
  316. package/dist/roof/definition.d.ts.map +1 -1
  317. package/dist/roof/definition.js +4 -1
  318. package/dist/roof/floorplan.d.ts +8 -0
  319. package/dist/roof/floorplan.d.ts.map +1 -1
  320. package/dist/roof/floorplan.js +194 -18
  321. package/dist/roof/panel-model.d.ts.map +1 -1
  322. package/dist/roof/panel-model.js +10 -6
  323. package/dist/roof/panel.d.ts.map +1 -1
  324. package/dist/roof/panel.js +3 -10
  325. package/dist/roof/renderer.d.ts.map +1 -1
  326. package/dist/roof/renderer.js +5 -2
  327. package/dist/roof-segment/panel.d.ts.map +1 -1
  328. package/dist/roof-segment/panel.js +5 -24
  329. package/dist/roof-segment/renderer.d.ts.map +1 -1
  330. package/dist/roof-segment/renderer.js +17 -8
  331. package/dist/separator/definition.d.ts +3 -0
  332. package/dist/separator/definition.d.ts.map +1 -0
  333. package/dist/separator/definition.js +39 -0
  334. package/dist/separator/renderer.d.ts +5 -0
  335. package/dist/separator/renderer.d.ts.map +1 -0
  336. package/dist/separator/renderer.js +36 -0
  337. package/dist/shared/duct-body-paint.d.ts +0 -4
  338. package/dist/shared/duct-body-paint.d.ts.map +1 -1
  339. package/dist/shared/duct-body-paint.js +1 -5
  340. package/dist/shared/item-interaction-actions.d.ts +6 -0
  341. package/dist/shared/item-interaction-actions.d.ts.map +1 -0
  342. package/dist/shared/item-interaction-actions.js +27 -0
  343. package/dist/shared/item-interactions.d.ts +9 -0
  344. package/dist/shared/item-interactions.d.ts.map +1 -0
  345. package/dist/shared/item-interactions.js +74 -0
  346. package/dist/shared/item-light-placement.d.ts +2 -0
  347. package/dist/shared/item-light-placement.d.ts.map +1 -0
  348. package/dist/shared/item-light-placement.js +3 -0
  349. package/dist/shared/move-roof-tool.js +2 -1
  350. package/dist/shared/node-batch/batchable.d.ts +12 -0
  351. package/dist/shared/node-batch/batchable.d.ts.map +1 -0
  352. package/dist/shared/node-batch/batchable.js +41 -0
  353. package/dist/shared/node-batch/candidates.d.ts +7 -5
  354. package/dist/shared/node-batch/candidates.d.ts.map +1 -1
  355. package/dist/shared/node-batch/candidates.js +43 -59
  356. package/dist/shared/node-batch/release.d.ts +8 -0
  357. package/dist/shared/node-batch/release.d.ts.map +1 -0
  358. package/dist/shared/node-batch/release.js +16 -0
  359. package/dist/shared/node-batch/system.d.ts.map +1 -1
  360. package/dist/shared/node-batch/system.js +17 -12
  361. package/dist/shared/node-batch/types.d.ts +4 -1
  362. package/dist/shared/node-batch/types.d.ts.map +1 -1
  363. package/dist/shared/opening-documentation.d.ts +13 -1
  364. package/dist/shared/opening-documentation.d.ts.map +1 -1
  365. package/dist/shared/opening-documentation.js +245 -59
  366. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  367. package/dist/shared/opening-guides-runtime.js +17 -14
  368. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  369. package/dist/shared/opening-placement-dimensions.js +3 -3
  370. package/dist/shared/opening-plane-offset.d.ts +23 -0
  371. package/dist/shared/opening-plane-offset.d.ts.map +1 -0
  372. package/dist/shared/opening-plane-offset.js +24 -0
  373. package/dist/shared/polygon-centroid-move.d.ts.map +1 -1
  374. package/dist/shared/polygon-centroid-move.js +4 -1
  375. package/dist/shared/polygon-vertex-affordance.d.ts.map +1 -1
  376. package/dist/shared/polygon-vertex-affordance.js +19 -15
  377. package/dist/shared/run-hangers.d.ts.map +1 -1
  378. package/dist/shared/run-hangers.js +5 -4
  379. package/dist/shared/scripted-opening-handles.d.ts +18 -0
  380. package/dist/shared/scripted-opening-handles.d.ts.map +1 -0
  381. package/dist/shared/scripted-opening-handles.js +53 -0
  382. package/dist/shared/scripted-opening.d.ts +25 -0
  383. package/dist/shared/scripted-opening.d.ts.map +1 -0
  384. package/dist/shared/scripted-opening.js +72 -0
  385. package/dist/shared/slot-paint.d.ts +14 -2
  386. package/dist/shared/slot-paint.d.ts.map +1 -1
  387. package/dist/shared/slot-paint.js +29 -29
  388. package/dist/shared/surface-paint.d.ts.map +1 -1
  389. package/dist/shared/surface-paint.js +2 -5
  390. package/dist/shared/swap-preview-material.d.ts +11 -0
  391. package/dist/shared/swap-preview-material.d.ts.map +1 -0
  392. package/dist/shared/swap-preview-material.js +16 -0
  393. package/dist/shared/system-checks.d.ts.map +1 -1
  394. package/dist/shared/system-checks.js +5 -3
  395. package/dist/shared/wall-attach-target.d.ts +3 -10
  396. package/dist/shared/wall-attach-target.d.ts.map +1 -1
  397. package/dist/shared/wall-attach-target.js +3 -63
  398. package/dist/shared/wall-opening-ceiling.d.ts +5 -15
  399. package/dist/shared/wall-opening-ceiling.d.ts.map +1 -1
  400. package/dist/shared/wall-opening-ceiling.js +10 -18
  401. package/dist/shelf/definition.d.ts.map +1 -1
  402. package/dist/shelf/definition.js +1 -1
  403. package/dist/shelf/geometry.d.ts.map +1 -1
  404. package/dist/shelf/geometry.js +1 -2
  405. package/dist/shelf/paint.d.ts.map +1 -1
  406. package/dist/shelf/paint.js +4 -10
  407. package/dist/site/line-ribbon.d.ts +31 -0
  408. package/dist/site/line-ribbon.d.ts.map +1 -0
  409. package/dist/site/line-ribbon.js +117 -0
  410. package/dist/site/lot-mask.d.ts +18 -0
  411. package/dist/site/lot-mask.d.ts.map +1 -0
  412. package/dist/site/lot-mask.js +35 -0
  413. package/dist/site/panel.d.ts +10 -0
  414. package/dist/site/panel.d.ts.map +1 -0
  415. package/dist/site/panel.js +155 -0
  416. package/dist/site/parametrics.d.ts +7 -0
  417. package/dist/site/parametrics.d.ts.map +1 -1
  418. package/dist/site/parametrics.js +8 -0
  419. package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
  420. package/dist/site/recessed-slab-ground-holes.js +5 -2
  421. package/dist/site/renderer.d.ts.map +1 -1
  422. package/dist/site/renderer.js +150 -19
  423. package/dist/site/setbacks.d.ts +33 -0
  424. package/dist/site/setbacks.d.ts.map +1 -0
  425. package/dist/site/setbacks.js +204 -0
  426. package/dist/site/terrain-geometry.d.ts +28 -1
  427. package/dist/site/terrain-geometry.d.ts.map +1 -1
  428. package/dist/site/terrain-geometry.js +78 -4
  429. package/dist/site/terrain-holes.d.ts +15 -0
  430. package/dist/site/terrain-holes.d.ts.map +1 -0
  431. package/dist/site/terrain-holes.js +74 -0
  432. package/dist/site/terrain-mesh.d.ts +9 -2
  433. package/dist/site/terrain-mesh.d.ts.map +1 -1
  434. package/dist/site/terrain-mesh.js +36 -9
  435. package/dist/site/terrain-renderer.d.ts +9 -2
  436. package/dist/site/terrain-renderer.d.ts.map +1 -1
  437. package/dist/site/terrain-renderer.js +14 -4
  438. package/dist/slab/boundary-editor.d.ts +1 -1
  439. package/dist/slab/boundary-editor.d.ts.map +1 -1
  440. package/dist/slab/boundary-editor.js +13 -13
  441. package/dist/slab/definition.d.ts.map +1 -1
  442. package/dist/slab/definition.js +19 -3
  443. package/dist/slab/dependency-tracker.d.ts.map +1 -1
  444. package/dist/slab/dependency-tracker.js +67 -7
  445. package/dist/slab/elevation-limit.d.ts.map +1 -1
  446. package/dist/slab/elevation-limit.js +2 -2
  447. package/dist/slab/floorplan-affordances.d.ts +176 -4
  448. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  449. package/dist/slab/floorplan-affordances.js +0 -1
  450. package/dist/slab/floorplan-move.d.ts.map +1 -1
  451. package/dist/slab/floorplan-move.js +3 -4
  452. package/dist/slab/floorplan.d.ts +7 -0
  453. package/dist/slab/floorplan.d.ts.map +1 -1
  454. package/dist/slab/floorplan.js +22 -5
  455. package/dist/slab/geometry.d.ts.map +1 -1
  456. package/dist/slab/geometry.js +186 -76
  457. package/dist/slab/move-tool.js +7 -6
  458. package/dist/slab/paint.d.ts +18 -5
  459. package/dist/slab/paint.d.ts.map +1 -1
  460. package/dist/slab/paint.js +458 -9
  461. package/dist/slab/panel.d.ts.map +1 -1
  462. package/dist/slab/panel.js +28 -9
  463. package/dist/slab/placement-ownership.d.ts +2 -1
  464. package/dist/slab/placement-ownership.d.ts.map +1 -1
  465. package/dist/slab/placement-ownership.js +2 -2
  466. package/dist/slab/surface-split.d.ts +24 -0
  467. package/dist/slab/surface-split.d.ts.map +1 -0
  468. package/dist/slab/surface-split.js +389 -0
  469. package/dist/slab/tool.d.ts.map +1 -1
  470. package/dist/slab/tool.js +3 -3
  471. package/dist/stair/baluster-geometry.d.ts +21 -0
  472. package/dist/stair/baluster-geometry.d.ts.map +1 -0
  473. package/dist/stair/baluster-geometry.js +74 -0
  474. package/dist/stair/baluster-guard.d.ts +50 -0
  475. package/dist/stair/baluster-guard.d.ts.map +1 -0
  476. package/dist/stair/baluster-guard.js +71 -0
  477. package/dist/stair/boards-guard.d.ts +37 -0
  478. package/dist/stair/boards-guard.d.ts.map +1 -0
  479. package/dist/stair/boards-guard.js +61 -0
  480. package/dist/stair/cable-guard.d.ts +39 -0
  481. package/dist/stair/cable-guard.d.ts.map +1 -0
  482. package/dist/stair/cable-guard.js +105 -0
  483. package/dist/stair/construction-controls.d.ts +15 -0
  484. package/dist/stair/construction-controls.d.ts.map +1 -0
  485. package/dist/stair/construction-controls.js +29 -0
  486. package/dist/stair/continuous-railings.d.ts +10 -0
  487. package/dist/stair/continuous-railings.d.ts.map +1 -0
  488. package/dist/stair/continuous-railings.js +159 -0
  489. package/dist/stair/definition.d.ts.map +1 -1
  490. package/dist/stair/definition.js +16 -37
  491. package/dist/stair/documentation.d.ts +1 -1
  492. package/dist/stair/documentation.d.ts.map +1 -1
  493. package/dist/stair/documentation.js +10 -17
  494. package/dist/stair/floorplan-affordances.d.ts.map +1 -1
  495. package/dist/stair/floorplan-affordances.js +9 -25
  496. package/dist/stair/floorplan.d.ts +1 -23
  497. package/dist/stair/floorplan.d.ts.map +1 -1
  498. package/dist/stair/floorplan.js +102 -86
  499. package/dist/stair/glass-guard.d.ts +72 -0
  500. package/dist/stair/glass-guard.d.ts.map +1 -0
  501. package/dist/stair/glass-guard.js +167 -0
  502. package/dist/stair/guard-path.d.ts +119 -0
  503. package/dist/stair/guard-path.d.ts.map +1 -0
  504. package/dist/stair/guard-path.js +208 -0
  505. package/dist/stair/materials.d.ts +11 -0
  506. package/dist/stair/materials.d.ts.map +1 -0
  507. package/dist/stair/materials.js +51 -0
  508. package/dist/stair/metal-guard.d.ts +38 -0
  509. package/dist/stair/metal-guard.d.ts.map +1 -0
  510. package/dist/stair/metal-guard.js +79 -0
  511. package/dist/stair/paint.d.ts +32 -0
  512. package/dist/stair/paint.d.ts.map +1 -1
  513. package/dist/stair/paint.js +75 -36
  514. package/dist/stair/panel.d.ts.map +1 -1
  515. package/dist/stair/panel.js +154 -17
  516. package/dist/stair/parametrics.d.ts +1 -1
  517. package/dist/stair/parametrics.d.ts.map +1 -1
  518. package/dist/stair/parametrics.js +32 -15
  519. package/dist/stair/plan-entry.d.ts +31 -0
  520. package/dist/stair/plan-entry.d.ts.map +1 -0
  521. package/dist/stair/plan-entry.js +325 -0
  522. package/dist/stair/post-and-rail-guard.d.ts +31 -0
  523. package/dist/stair/post-and-rail-guard.d.ts.map +1 -0
  524. package/dist/stair/post-and-rail-guard.js +63 -0
  525. package/dist/stair/railing-controls.d.ts +9 -0
  526. package/dist/stair/railing-controls.d.ts.map +1 -0
  527. package/dist/stair/railing-controls.js +49 -0
  528. package/dist/stair/renderer.d.ts.map +1 -1
  529. package/dist/stair/renderer.js +259 -259
  530. package/dist/stair/use-stair-render-data.d.ts +317 -0
  531. package/dist/stair/use-stair-render-data.d.ts.map +1 -0
  532. package/dist/stair/use-stair-render-data.js +73 -0
  533. package/dist/stair-segment/definition.d.ts.map +1 -1
  534. package/dist/stair-segment/definition.js +51 -10
  535. package/dist/stair-segment/panel.d.ts.map +1 -1
  536. package/dist/stair-segment/panel.js +36 -42
  537. package/dist/stair-segment/parametrics.d.ts +1 -1
  538. package/dist/stair-segment/parametrics.d.ts.map +1 -1
  539. package/dist/stair-segment/parametrics.js +21 -8
  540. package/dist/stair-segment/renderer.d.ts.map +1 -1
  541. package/dist/stair-segment/renderer.js +16 -28
  542. package/dist/turbine-vent/definition.d.ts.map +1 -1
  543. package/dist/turbine-vent/definition.js +2 -5
  544. package/dist/turbine-vent/paint.d.ts.map +1 -1
  545. package/dist/turbine-vent/paint.js +2 -5
  546. package/dist/turbine-vent/panel.d.ts.map +1 -1
  547. package/dist/turbine-vent/panel.js +5 -23
  548. package/dist/unit/unit-panel.d.ts.map +1 -1
  549. package/dist/unit/unit-panel.js +6 -1
  550. package/dist/wall/actions.d.ts.map +1 -1
  551. package/dist/wall/actions.js +7 -2
  552. package/dist/wall/construction-dimensions.js +8 -5
  553. package/dist/wall/contextual-dimensions.js +4 -4
  554. package/dist/wall/curtain-wall-materials.d.ts +1 -1
  555. package/dist/wall/curtain-wall-materials.d.ts.map +1 -1
  556. package/dist/wall/curtain-wall-materials.js +2 -2
  557. package/dist/wall/curve-tool.d.ts.map +1 -1
  558. package/dist/wall/curve-tool.js +4 -0
  559. package/dist/wall/definition.d.ts.map +1 -1
  560. package/dist/wall/definition.js +41 -17
  561. package/dist/wall/floorplan-move.d.ts +1 -1
  562. package/dist/wall/floorplan-move.d.ts.map +1 -1
  563. package/dist/wall/floorplan-move.js +20 -83
  564. package/dist/wall/floorplan-tool.d.ts.map +1 -1
  565. package/dist/wall/floorplan-tool.js +10 -11
  566. package/dist/wall/floorplan.d.ts +3 -1
  567. package/dist/wall/floorplan.d.ts.map +1 -1
  568. package/dist/wall/floorplan.js +184 -21
  569. package/dist/wall/measurement.d.ts.map +1 -1
  570. package/dist/wall/measurement.js +5 -5
  571. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  572. package/dist/wall/move-endpoint-tool.js +20 -7
  573. package/dist/wall/move-shared.d.ts.map +1 -1
  574. package/dist/wall/move-shared.js +11 -7
  575. package/dist/wall/move-tool.d.ts.map +1 -1
  576. package/dist/wall/move-tool.js +118 -148
  577. package/dist/wall/paint.d.ts +26 -15
  578. package/dist/wall/paint.d.ts.map +1 -1
  579. package/dist/wall/paint.js +306 -117
  580. package/dist/wall/panel-model.d.ts +18 -0
  581. package/dist/wall/panel-model.d.ts.map +1 -1
  582. package/dist/wall/panel-model.js +77 -19
  583. package/dist/wall/panel.d.ts.map +1 -1
  584. package/dist/wall/panel.js +217 -41
  585. package/dist/wall/parametrics.d.ts.map +1 -1
  586. package/dist/wall/parametrics.js +3 -0
  587. package/dist/wall/rectangle-command.d.ts +111 -12
  588. package/dist/wall/rectangle-command.d.ts.map +1 -1
  589. package/dist/wall/rectangle-tool.d.ts.map +1 -1
  590. package/dist/wall/rectangle-tool.js +26 -8
  591. package/dist/wall/renderer.d.ts.map +1 -1
  592. package/dist/wall/renderer.js +4 -2
  593. package/dist/wall/split-floorplan-layer.d.ts.map +1 -1
  594. package/dist/wall/split-floorplan-layer.js +7 -7
  595. package/dist/wall/split-session.d.ts.map +1 -1
  596. package/dist/wall/split-session.js +7 -1
  597. package/dist/wall/system.d.ts.map +1 -1
  598. package/dist/wall/system.js +36 -4
  599. package/dist/wall/tool.d.ts.map +1 -1
  600. package/dist/wall/tool.js +105 -49
  601. package/dist/wall/treatment-level-data.d.ts +3 -2
  602. package/dist/wall/treatment-level-data.d.ts.map +1 -1
  603. package/dist/wall/treatment-level-data.js +17 -13
  604. package/dist/wall/treatments.d.ts +10 -10
  605. package/dist/wall/treatments.d.ts.map +1 -1
  606. package/dist/wall/treatments.js +67 -54
  607. package/dist/wall/wall-batch-system.d.ts +7 -0
  608. package/dist/wall/wall-batch-system.d.ts.map +1 -1
  609. package/dist/wall/wall-batch-system.js +35 -3
  610. package/dist/wall/wall-batch.d.ts +6 -0
  611. package/dist/wall/wall-batch.d.ts.map +1 -1
  612. package/dist/wall/wall-batch.js +7 -1
  613. package/dist/window/definition.d.ts.map +1 -1
  614. package/dist/window/definition.js +12 -4
  615. package/dist/window/floorplan-move.d.ts.map +1 -1
  616. package/dist/window/floorplan-move.js +3 -1
  617. package/dist/window/floorplan.d.ts.map +1 -1
  618. package/dist/window/floorplan.js +145 -60
  619. package/dist/window/mechanism.d.ts +4 -0
  620. package/dist/window/mechanism.d.ts.map +1 -0
  621. package/dist/window/mechanism.js +20 -0
  622. package/dist/window/move-tool.d.ts.map +1 -1
  623. package/dist/window/move-tool.js +79 -48
  624. package/dist/window/paint.d.ts.map +1 -1
  625. package/dist/window/paint.js +3 -0
  626. package/dist/window/panel.d.ts.map +1 -1
  627. package/dist/window/panel.js +32 -88
  628. package/dist/window/placement.d.ts +23 -0
  629. package/dist/window/placement.d.ts.map +1 -0
  630. package/dist/window/placement.js +66 -0
  631. package/dist/window/preview.d.ts.map +1 -1
  632. package/dist/window/preview.js +2 -0
  633. package/dist/window/renderer.d.ts.map +1 -1
  634. package/dist/window/renderer.js +3 -2
  635. package/dist/window/tool.d.ts.map +1 -1
  636. package/dist/window/tool.js +96 -24
  637. package/dist/window/window-math.d.ts +6 -14
  638. package/dist/window/window-math.d.ts.map +1 -1
  639. package/dist/window/window-math.js +14 -20
  640. package/dist/zone/contextual-dimensions.d.ts.map +1 -1
  641. package/dist/zone/contextual-dimensions.js +6 -28
  642. package/dist/zone/definition.d.ts.map +1 -1
  643. package/dist/zone/definition.js +3 -3
  644. package/dist/zone/floorplan-affordances.d.ts +200 -0
  645. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  646. package/dist/zone/floorplan.d.ts +1 -1
  647. package/dist/zone/floorplan.d.ts.map +1 -1
  648. package/dist/zone/floorplan.js +93 -53
  649. package/dist/zone/quantities-panel.d.ts.map +1 -1
  650. package/dist/zone/quantities-panel.js +3 -14
  651. package/dist/zone/quick-measurement.d.ts +2 -2
  652. package/dist/zone/quick-measurement.d.ts.map +1 -1
  653. package/dist/zone/quick-measurement.js +6 -5
  654. package/dist/zone/renderer.d.ts +1 -1
  655. package/dist/zone/renderer.d.ts.map +1 -1
  656. package/dist/zone/renderer.js +58 -146
  657. package/dist/zone/room-clear-dimensions.js +3 -3
  658. package/dist/zone/room-documentation.d.ts.map +1 -1
  659. package/dist/zone/room-documentation.js +2 -6
  660. package/package.json +11 -11
  661. package/dist/block/slots.d.ts +0 -4
  662. package/dist/block/slots.d.ts.map +0 -1
  663. package/dist/block/slots.js +0 -17
  664. package/dist/cabinet/slots.d.ts +0 -4
  665. package/dist/cabinet/slots.d.ts.map +0 -1
  666. package/dist/cabinet/slots.js +0 -24
  667. package/dist/ceiling/slots.d.ts +0 -6
  668. package/dist/ceiling/slots.d.ts.map +0 -1
  669. package/dist/ceiling/slots.js +0 -7
  670. package/dist/column/slots.d.ts +0 -9
  671. package/dist/column/slots.d.ts.map +0 -1
  672. package/dist/column/slots.js +0 -19
  673. package/dist/door/slots.d.ts +0 -9
  674. package/dist/door/slots.d.ts.map +0 -1
  675. package/dist/door/slots.js +0 -20
  676. package/dist/elevator/slots.d.ts +0 -8
  677. package/dist/elevator/slots.d.ts.map +0 -1
  678. package/dist/elevator/slots.js +0 -17
  679. package/dist/fence/slots.d.ts +0 -10
  680. package/dist/fence/slots.d.ts.map +0 -1
  681. package/dist/fence/slots.js +0 -23
  682. package/dist/item/__fixtures__/main-floorplan.d.ts +0 -26
  683. package/dist/item/__fixtures__/main-floorplan.d.ts.map +0 -1
  684. package/dist/item/__fixtures__/main-floorplan.js +0 -297
  685. package/dist/lean-to-extension/slots.d.ts +0 -5
  686. package/dist/lean-to-extension/slots.d.ts.map +0 -1
  687. package/dist/lean-to-extension/slots.js +0 -15
  688. package/dist/shelf/slots.d.ts +0 -9
  689. package/dist/shelf/slots.d.ts.map +0 -1
  690. package/dist/shelf/slots.js +0 -30
  691. package/dist/slab/slots.d.ts +0 -10
  692. package/dist/slab/slots.d.ts.map +0 -1
  693. package/dist/slab/slots.js +0 -20
  694. package/dist/stair/floor-stack.d.ts +0 -10
  695. package/dist/stair/floor-stack.d.ts.map +0 -1
  696. package/dist/stair/floor-stack.js +0 -115
  697. package/dist/stair/slots.d.ts +0 -7
  698. package/dist/stair/slots.d.ts.map +0 -1
  699. package/dist/stair/slots.js +0 -13
  700. package/dist/wall/drawing-mode.d.ts +0 -12
  701. package/dist/wall/drawing-mode.d.ts.map +0 -1
  702. package/dist/wall/drawing-mode.js +0 -38
  703. package/dist/wall/slots.d.ts +0 -10
  704. package/dist/wall/slots.d.ts.map +0 -1
  705. package/dist/wall/slots.js +0 -92
  706. package/dist/window/slots.d.ts +0 -5
  707. package/dist/window/slots.d.ts.map +0 -1
  708. package/dist/window/slots.js +0 -11
@@ -1,13 +1,7 @@
1
- import { detectSpacesForLevel, getCeilingClampBound, getPerpendicularWallMoveAxis, getPlannedLinkedWallUpdates, getStoredLevelHeight, planAutoCeilingsForLevel, planAutoSlabsForLevel, planWallMoveJunctions, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
2
- import { getFloorplanWallThickness, getSegmentGridStep, isSegmentLongEnough, snapScalarToGrid, useWallMoveGhosts, } from '@pascal-app/editor';
1
+ import { createLevelStructurePreview, getPerpendicularWallMoveAxis, getPlannedLinkedWallUpdates, planWallEndRejoins, planWallMoveJunctions, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
2
+ import { getFloorplanWallThickness, getSegmentGridStep, isSegmentLongEnough, snapScalarToGrid, useWallMoveGhosts, WALL_CONNECT_SNAP_RADIUS, } from '@pascal-app/editor';
3
3
  import { useViewer } from '@pascal-app/viewer';
4
4
  import { buildBridgeWallCreates, buildBridgeWallPreviews, getLinkedWallSnapshots, getWallsAfterUpdates, stripWallIsNewMetadata, } from './move-shared';
5
- function getLevelSlabs(levelId, nodes) {
6
- return Object.values(nodes).filter((entry) => entry?.type === 'slab' && (entry.parentId ?? null) === levelId);
7
- }
8
- function getLevelCeilings(levelId, nodes) {
9
- return Object.values(nodes).filter((entry) => entry?.type === 'ceiling' && (entry.parentId ?? null) === levelId);
10
- }
11
5
  /**
12
6
  * 2D floor-plan move handler for wall.
13
7
  *
@@ -32,7 +26,7 @@ function getLevelCeilings(levelId, nodes) {
32
26
  * overrides after the write lands so the system reads from the new
33
27
  * committed scene state.
34
28
  *
35
- * Existing automatic slabs and ceilings receive live polygon overrides during
29
+ * Existing slabs, ceilings and zones receive live polygon overrides during
36
30
  * the drag. New surfaces and removals stay deferred until commit because live
37
31
  * overrides cannot represent nodes that do not exist in the scene.
38
32
  */
@@ -78,40 +72,22 @@ export const wallFloorplanMoveTarget = ({ node }) => {
78
72
  let lastNextStart = originalStart;
79
73
  let lastNextEnd = originalEnd;
80
74
  const levelId = node.parentId ?? null;
75
+ const previewStructure = levelId
76
+ ? createLevelStructurePreview(levelId, useScene.getState().nodes)
77
+ : null;
78
+ const dragNodes = Object.fromEntries(Object.values(useScene.getState().nodes)
79
+ .filter((node) => node.parentId === levelId)
80
+ .map((node) => [node.id, node]));
81
81
  const affectedIds = [wallId, ...linkedOriginals.map((wall) => wall.id)];
82
82
  const affectedIdSet = new Set(affectedIds);
83
83
  const touchedSurfaceIds = new Set();
84
- let latestSurfacePlans = null;
85
- const planSurfaces = (walls) => {
86
- if (!levelId)
87
- return null;
88
- const sceneState = useScene.getState();
89
- const levelWalls = walls.filter((wall) => (wall.parentId ?? null) === levelId);
90
- const { roomPolygons } = detectSpacesForLevel(levelId, levelWalls);
91
- const slabs = planAutoSlabsForLevel(roomPolygons, getLevelSlabs(levelId, sceneState.nodes));
92
- const levelNode = sceneState.nodes[levelId];
93
- const ceilings = planAutoCeilingsForLevel(roomPolygons, getLevelCeilings(levelId, sceneState.nodes), {
94
- storeyHeight: levelNode?.type === 'level' ? getStoredLevelHeight(levelNode) : undefined,
95
- ceilingClampBound: (polygon) => getCeilingClampBound(levelId, sceneState.nodes, polygon),
96
- });
97
- return { slabs, ceilings };
98
- };
99
84
  const publishSurfacePreviews = (walls) => {
100
- const plans = planSurfaces(walls);
101
- latestSurfacePlans = plans;
102
- if (!plans)
85
+ if (!previewStructure)
103
86
  return;
104
- const entries = [];
105
- for (const update of plans.slabs.update) {
106
- if (update.data.polygon !== undefined) {
107
- entries.push([update.id, { polygon: update.data.polygon }]);
108
- }
109
- }
110
- for (const update of plans.ceilings.update) {
111
- if (update.data.polygon !== undefined || update.data.height !== undefined) {
112
- entries.push([update.id, update.data]);
113
- }
114
- }
87
+ const updates = previewStructure(walls);
88
+ const entries = updates.flatMap((update) => 'polygon' in update.data || 'holes' in update.data
89
+ ? [[update.id, update.data]]
90
+ : []);
115
91
  const nextIds = new Set(entries.map(([id]) => id));
116
92
  const overrides = useLiveNodeOverrides.getState();
117
93
  const sceneState = useScene.getState();
@@ -142,7 +118,6 @@ export const wallFloorplanMoveTarget = ({ node }) => {
142
118
  sceneState.markDirty(id);
143
119
  }
144
120
  touchedSurfaceIds.clear();
145
- latestSurfacePlans = null;
146
121
  };
147
122
  const session = {
148
123
  affectedIds,
@@ -222,7 +197,7 @@ export const wallFloorplanMoveTarget = ({ node }) => {
222
197
  // `existingWalls` snapshot needs the post-drag layout so duplicate
223
198
  // detection works; we synthesise it from scene state + the
224
199
  // overrides we just published (zustand is still on baseline).
225
- const previewSceneWalls = getWallsAfterUpdates(useScene.getState().nodes, [
200
+ const previewSceneWalls = getWallsAfterUpdates(dragNodes, [
226
201
  { id: wallId, data: { start: nextStart, end: nextEnd } },
227
202
  ...linkedUpdates.map((u) => ({ id: u.id, data: { start: u.start, end: u.end } })),
228
203
  ]).filter((wall) => !collapsedIds.has(wall.id));
@@ -306,49 +281,11 @@ export const wallFloorplanMoveTarget = ({ node }) => {
306
281
  existingWalls,
307
282
  wallCount: Object.values(sceneState.nodes).filter((entry) => entry?.type === 'wall').length,
308
283
  });
309
- const finalWalls = [
310
- ...existingWalls,
311
- ...bridgeCreates.map((entry) => ({ ...entry.node, parentId: entry.parentId ?? null })),
312
- ];
313
- const surfacePlans = planSurfaces(finalWalls) ?? latestSurfacePlans;
314
- const surfaceUpdates = surfacePlans
315
- ? [
316
- ...surfacePlans.slabs.update.map((entry) => ({
317
- id: entry.id,
318
- data: entry.data,
319
- })),
320
- ...surfacePlans.ceilings.update.map((entry) => ({
321
- id: entry.id,
322
- data: entry.data,
323
- })),
324
- ]
325
- : [];
326
- const surfaceCreates = surfacePlans
327
- ? [
328
- ...surfacePlans.slabs.create.map((slab) => ({
329
- node: slab,
330
- parentId: levelId,
331
- })),
332
- ...surfacePlans.ceilings.create.map((ceiling) => ({
333
- node: ceiling,
334
- parentId: levelId,
335
- })),
336
- ]
337
- : [];
338
- const surfaceDeletes = surfacePlans
339
- ? [
340
- ...surfacePlans.slabs.delete.map((id) => id),
341
- ...surfacePlans.ceilings.delete.map((id) => id),
342
- ]
343
- : [];
344
- sceneState.applyNodeChanges({
345
- update: [
346
- ...commitUpdates,
347
- ...surfaceUpdates,
348
- ],
349
- create: [...bridgeCreates, ...surfaceCreates],
350
- delete: Array.from(new Set([...collapsedLinkedWallIds, ...surfaceDeletes])),
351
- });
284
+ sceneState.applyNodeChanges(planWallEndRejoins(sceneState.nodes, commitUpdates.map(({ id }) => id), WALL_CONNECT_SNAP_RADIUS, {
285
+ update: commitUpdates,
286
+ create: bridgeCreates,
287
+ delete: Array.from(collapsedLinkedWallIds),
288
+ }));
352
289
  // Drop the live overrides now that the committed scene state
353
290
  // matches them — leaving them around would keep the system
354
291
  // double-merging the same values and would shadow any genuine
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan-tool.d.ts","sourceRoot":"","sources":["../../src/wall/floorplan-tool.tsx"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,oBAAoB,EAO1B,MAAM,oBAAoB,CAAA;AAK3B,oGAAoG;AACpG,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,oBAAoB,sCAIpE"}
1
+ {"version":3,"file":"floorplan-tool.d.ts","sourceRoot":"","sources":["../../src/wall/floorplan-tool.tsx"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,oBAAoB,EAQ1B,MAAM,oBAAoB,CAAA;AAI3B,oGAAoG;AACpG,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,oBAAoB,sCAEpE"}
@@ -1,15 +1,12 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { emitter, resolveTerrainWallConstructionOptions, useScene, } from '@pascal-app/core';
4
- import { markToolCancelConsumed, triggerSFX, useEditor, useFloorplanDraftPreview, useFloorplanRender, useInteractionScope, } from '@pascal-app/editor';
4
+ import { markToolCancelConsumed, triggerSFX, useEditor, useFloorplanDraftPreview, useFloorplanRender, useInteractionScope, useWallDrawVariant, } from '@pascal-app/editor';
5
5
  import { useEffect, useRef, useState } from 'react';
6
- import { useWallDrawingMode, useWallDrawingModeKeys } from './drawing-mode';
7
6
  import { createWallRectangle } from './rectangle-command';
8
7
  /** The wall's plan tool: line drafting stays with the panel; rectangle mode mounts its own tool. */
9
8
  export default function WallFloorplanTool(props) {
10
- useWallDrawingModeKeys();
11
- const mode = useWallDrawingMode((s) => s.mode);
12
- return mode === 'rectangle' ? _jsx(RectangleFloorplanTool, { ...props }) : null;
9
+ return useWallDrawVariant() === 'rectangle' ? _jsx(RectangleFloorplanTool, { ...props }) : null;
13
10
  }
14
11
  /**
15
12
  * Rectangle mode in the floor plan. Pointer moves stay with the panel, so the
@@ -80,12 +77,14 @@ function RectangleFloorplanTool({ activeLevelId }) {
80
77
  if (e.button === 0)
81
78
  claim(e);
82
79
  };
83
- // The panel publishes the snapped cursor only when it moves to a new
84
- // point, so each change while a corner is down is the line draft's tick.
85
- const stopTick = useFloorplanDraftPreview.subscribe((state, previous) => {
80
+ // The panel moves the snapped cursor; the wall draft's tick as the dragged
81
+ // corner steps to a new spot.
82
+ const stopTicks = useFloorplanDraftPreview.subscribe((state, previous) => {
83
+ const [now, before] = [state.cursorPoint, previous.cursorPoint];
86
84
  if (state.wallRectangleDraftStart &&
87
- state.cursorPoint &&
88
- state.cursorPoint !== previous.cursorPoint)
85
+ now &&
86
+ before &&
87
+ (now[0] !== before[0] || now[1] !== before[1]))
89
88
  triggerSFX('sfx:grid-snap');
90
89
  });
91
90
  svg.addEventListener('pointerdown', onDown, true);
@@ -93,7 +92,7 @@ function RectangleFloorplanTool({ activeLevelId }) {
93
92
  svg.addEventListener('dblclick', stopDouble, true);
94
93
  emitter.on('tool:cancel', cancel);
95
94
  return () => {
96
- stopTick();
95
+ stopTicks();
97
96
  svg.removeEventListener('pointerdown', onDown, true);
98
97
  svg.removeEventListener('click', onClick, true);
99
98
  svg.removeEventListener('dblclick', stopDouble, true);
@@ -1,10 +1,12 @@
1
- import { type AnyNode, type FloorplanGeometry, type GeometryContext, type WallMiterData, type WallNode } from '@pascal-app/core';
1
+ import { type AnyNode, type FloorplanGeometry, type GeometryContext, type WallLayerMiterData, type WallMiterData, type WallNode } from '@pascal-app/core';
2
2
  import { type WallConstructionDimensionPlan } from './construction-dimensions';
3
3
  declare const WALL_DIMENSION_REFERENCES: readonly ["finished-faces", "centerline", "stud-faces"];
4
4
  type WallDimensionReference = (typeof WALL_DIMENSION_REFERENCES)[number];
5
5
  export type WallFloorplanLevelData = {
6
6
  miters: WallMiterData;
7
7
  documentMiters: WallMiterData;
8
+ layerMiters: WallLayerMiterData;
9
+ documentLayerMiters: WallLayerMiterData;
8
10
  constructionDimensionsByReference: Record<WallDimensionReference, WallConstructionDimensionPlan>;
9
11
  };
10
12
  export declare function computeWallFloorplanLevelData({ siblings, nodes, }: {
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/wall/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EAQpB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAKL,KAAK,6BAA6B,EACnC,MAAM,2BAA2B,CAAA;AAalC,QAAA,MAAM,yBAAyB,yDAA0D,CAAA;AAEzF,KAAK,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAA;AAexE,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,aAAa,CAAA;IACrB,cAAc,EAAE,aAAa,CAAA;IAC7B,iCAAiC,EAAE,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,CAAC,CAAA;CACjG,CAAA;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B,GAAG,sBAAsB,CAqCzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CA8NjG"}
1
+ {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/wall/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EAGZ,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EAYpB,KAAK,kBAAkB,EAEvB,KAAK,aAAa,EAClB,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAA;AAQzB,OAAO,EAKL,KAAK,6BAA6B,EACnC,MAAM,2BAA2B,CAAA;AAalC,QAAA,MAAM,yBAAyB,yDAA0D,CAAA;AAEzF,KAAK,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAA;AAsBxE,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,aAAa,CAAA;IACrB,cAAc,EAAE,aAAa,CAAA;IAC7B,WAAW,EAAE,kBAAkB,CAAA;IAC/B,mBAAmB,EAAE,kBAAkB,CAAA;IACvC,iCAAiC,EAAE,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,CAAC,CAAA;CACjG,CAAA;AAqJD,wBAAgB,6BAA6B,CAAC,EAC5C,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B,GAAG,sBAAsB,CA0CzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,GAAG,iBAAiB,GAAG,IAAI,CAgPjG"}
@@ -1,5 +1,5 @@
1
- import { calculateLevelMiters, getWallCurveFrameAt, getWallCurveLength, getWallEffectiveHeightForNodes, getWallMidpointHandlePoint, getWallPlanFootprint, getWallThickness, isCurvedWall, } from '@pascal-app/core';
2
- import { floorplanGeometryMetadata, readFloorplanContext } from '@pascal-app/editor';
1
+ import { calculateLevelLayerMiters, calculateLevelMiters, getWallBodyCenterOffset, getWallCurveFrameAt, getWallCurveLength, getWallEffectiveHeightForNodes, getWallFaceOffsets, getWallLayerPolylines, getWallLocalFaceZ, getWallMidpointHandlePoint, getWallPlanFootprint, getWallThickness, isCurvedWall, wallLayerBoundaryOffsets, } from '@pascal-app/core';
2
+ import { floorplanGeometryMetadata, readFloorplanContext, WALL_PUSH_AFFORDANCE, } from '@pascal-app/editor';
3
3
  import { constructionDimensionStandard } from '../shared/construction-dimension-standards';
4
4
  import { buildCurvedWallConstructionDimensions, buildLevelWallConstructionDimensionPlan, buildWallConstructionDimensions, renderPlannedConstructionDimensions, } from './construction-dimensions';
5
5
  import { buildCurtainWallFloorplan } from './curtain-wall-floorplan';
@@ -22,6 +22,148 @@ function floorplanWallThickness(wall) {
22
22
  function exaggerateWallThickness(wall) {
23
23
  return { ...wall, thickness: floorplanWallThickness(wall) };
24
24
  }
25
+ // Assembly offsets are measured from the body centre; a justified wall's body
26
+ // sits off its reference line, so the layer lines move with it.
27
+ function wallLayerOffsets(wall) {
28
+ const centre = getWallBodyCenterOffset(wall);
29
+ return wallLayerBoundaryOffsets(wall, getWallThickness(wall)).map((offset) => offset + centre);
30
+ }
31
+ // --- Assembly layer lines ---------------------------------------------------
32
+ //
33
+ // The mitered outer footprint is unchanged; these are the boundaries BETWEEN
34
+ // the assembly's layers, offset in from the footprint and mitered at the same
35
+ // corners so they meet cleanly (see `calculateLevelLayerMiters` in
36
+ // `packages/core/src/systems/wall/wall-assembly.ts` for the corner, T-junction
37
+ // and different-assembly rules).
38
+ //
39
+ // In `document` purpose the framing cavity gets the standard poché (a light
40
+ // hatch) and the finish layers are thin solid lines. In `edit` purpose the
41
+ // footprint keeps today's look and the layer lines are drawn at reduced
42
+ // opacity with no poché, so the editor stays readable.
43
+ //
44
+ // Curved walls are skipped: the offset miter is a straight-line construction
45
+ // and a curved wall's layers would need arc offsets. Stated plainly rather
46
+ // than approximated — a curved wall draws exactly as it does today.
47
+ const LAYER_LINE_STROKE = '#1f2937';
48
+ const LAYER_LINE_WIDTH_DOCUMENT = 0.008;
49
+ const LAYER_LINE_WIDTH_EDIT = 0.006;
50
+ const LAYER_LINE_OPACITY_EDIT = 0.35;
51
+ const FRAMING_POCHE_COLOR = '#94a3b8';
52
+ const FRAMING_POCHE_OPACITY = 0.28;
53
+ /** Along-wall spans, measured from `wall.start`, occupied by doors / windows. */
54
+ function openingSpans(wall, children) {
55
+ const spans = [];
56
+ for (const child of children) {
57
+ if (child.type !== 'door' && child.type !== 'window')
58
+ continue;
59
+ const distance = child.position?.[0];
60
+ const width = child.width;
61
+ if (typeof distance !== 'number' || typeof width !== 'number' || width <= 0)
62
+ continue;
63
+ spans.push([distance - width / 2, distance + width / 2]);
64
+ }
65
+ return spans.sort((a, b) => a[0] - b[0]);
66
+ }
67
+ /**
68
+ * Cut one mitered layer boundary at the openings hosted by the wall, so an
69
+ * opening reads as a hole through EVERY layer and not just the footprint.
70
+ * Parameterised along the wall direction, which is exact for straight walls.
71
+ */
72
+ function cutAtOpenings(line, wall, spans) {
73
+ const segment = {
74
+ start: [line.start.x, line.start.y],
75
+ end: [line.end.x, line.end.y],
76
+ };
77
+ if (spans.length === 0)
78
+ return [segment];
79
+ const dx = wall.end[0] - wall.start[0];
80
+ const dy = wall.end[1] - wall.start[1];
81
+ const length = Math.hypot(dx, dy);
82
+ if (length < 1e-9)
83
+ return [segment];
84
+ const ux = dx / length;
85
+ const uy = dy / length;
86
+ const along = (p) => (p.x - wall.start[0]) * ux + (p.y - wall.start[1]) * uy;
87
+ const a0 = along(line.start);
88
+ const a1 = along(line.end);
89
+ if (Math.abs(a1 - a0) < 1e-9)
90
+ return [segment];
91
+ const at = (t) => [
92
+ line.start.x + (line.end.x - line.start.x) * t,
93
+ line.start.y + (line.end.y - line.start.y) * t,
94
+ ];
95
+ const toT = (distance) => (distance - a0) / (a1 - a0);
96
+ const pieces = [];
97
+ let cursor = 0;
98
+ for (const [lo, hi] of spans) {
99
+ const tLo = Math.max(0, Math.min(1, toT(lo)));
100
+ const tHi = Math.max(0, Math.min(1, toT(hi)));
101
+ const from = Math.min(tLo, tHi);
102
+ const to = Math.max(tLo, tHi);
103
+ if (from > cursor + 1e-6)
104
+ pieces.push({ start: at(cursor), end: at(from) });
105
+ cursor = Math.max(cursor, to);
106
+ }
107
+ if (cursor < 1 - 1e-6)
108
+ pieces.push({ start: at(cursor), end: at(1) });
109
+ return pieces;
110
+ }
111
+ /**
112
+ * The layer-boundary lines plus the framing poché for one wall.
113
+ * `wall` is the (possibly exaggerated) wall the footprint was built from, so
114
+ * the stack is scaled to whatever thickness is actually drawn.
115
+ */
116
+ function buildWallAssemblyLayers(wall, source, layerMiters, children, documentMode) {
117
+ if (!source.assembly || isCurvedWall(source))
118
+ return [];
119
+ const offsets = wallLayerOffsets(wall);
120
+ if (offsets.length < 3)
121
+ return [];
122
+ const lines = getWallLayerPolylines(wall, layerMiters, offsets);
123
+ if (lines.length < 3)
124
+ return [];
125
+ const spans = openingSpans(source, children);
126
+ const out = [];
127
+ // Framing poché first, so the boundary lines sit on top of it.
128
+ if (documentMode) {
129
+ for (let i = 0; i < lines.length - 1; i += 1) {
130
+ if (lines[i + 1].role !== 'framing')
131
+ continue;
132
+ const outer = lines[i];
133
+ const inner = lines[i + 1];
134
+ out.push({
135
+ kind: 'hatch',
136
+ points: [
137
+ [outer.start.x, outer.start.y],
138
+ [outer.end.x, outer.end.y],
139
+ [inner.end.x, inner.end.y],
140
+ [inner.start.x, inner.start.y],
141
+ ],
142
+ color: FRAMING_POCHE_COLOR,
143
+ opacity: FRAMING_POCHE_OPACITY,
144
+ });
145
+ }
146
+ }
147
+ // Interior boundaries only — index 0 and the last index are the two outer
148
+ // faces, already drawn by the mitered footprint polygon.
149
+ for (let i = 1; i < lines.length - 1; i += 1) {
150
+ for (const piece of cutAtOpenings(lines[i], source, spans)) {
151
+ out.push({
152
+ kind: 'line',
153
+ x1: piece.start[0],
154
+ y1: piece.start[1],
155
+ x2: piece.end[0],
156
+ y2: piece.end[1],
157
+ stroke: LAYER_LINE_STROKE,
158
+ strokeWidth: documentMode ? LAYER_LINE_WIDTH_DOCUMENT : LAYER_LINE_WIDTH_EDIT,
159
+ opacity: documentMode ? 1 : LAYER_LINE_OPACITY_EDIT,
160
+ pointerEvents: 'none',
161
+ metadata: floorplanGeometryMetadata({ renderPass: 'overlay' }),
162
+ });
163
+ }
164
+ }
165
+ return out;
166
+ }
25
167
  export function computeWallFloorplanLevelData({ siblings, nodes, }) {
26
168
  const walls = siblings.map(exaggerateWallThickness);
27
169
  const constructionDimensionsByReference = {};
@@ -47,9 +189,14 @@ export function computeWallFloorplanLevelData({ siblings, nodes, }) {
47
189
  },
48
190
  });
49
191
  }
192
+ const documentWalls = [...siblings];
193
+ const miters = calculateLevelMiters(walls);
194
+ const documentMiters = calculateLevelMiters(documentWalls);
50
195
  return {
51
- miters: calculateLevelMiters(walls),
52
- documentMiters: calculateLevelMiters([...siblings]),
196
+ miters,
197
+ documentMiters,
198
+ layerMiters: calculateLevelLayerMiters(walls, miters, wallLayerOffsets),
199
+ documentLayerMiters: calculateLevelLayerMiters(documentWalls, documentMiters, wallLayerOffsets),
53
200
  constructionDimensionsByReference,
54
201
  };
55
202
  }
@@ -80,11 +227,18 @@ export function buildWallFloorplan(node, ctx) {
80
227
  // level-wide miter calc per wall; the dispatcher path is O(1) here, which is
81
228
  // what keeps a wall drag from being O(N²) across the level.
82
229
  const levelData = ctx.levelData;
83
- const miters = (documentMode ? levelData?.documentMiters : levelData?.miters) ??
84
- calculateLevelMiters([
230
+ let purposeWalls;
231
+ const getPurposeWalls = () => {
232
+ purposeWalls ??= [
85
233
  self,
86
234
  ...ctx.siblings.filter((s) => s.type === 'wall').map(wallForPurpose),
87
- ]);
235
+ ];
236
+ return purposeWalls;
237
+ };
238
+ const miters = (documentMode ? levelData?.documentMiters : levelData?.miters) ??
239
+ calculateLevelMiters(getPurposeWalls());
240
+ const getLayerMiters = () => (documentMode ? levelData?.documentLayerMiters : levelData?.layerMiters) ??
241
+ calculateLevelLayerMiters(getPurposeWalls(), miters, wallLayerOffsets);
88
242
  const polygon = getWallPlanFootprint(self, miters);
89
243
  if (!polygon || polygon.length < 3)
90
244
  return null;
@@ -125,6 +279,10 @@ export function buildWallFloorplan(node, ctx) {
125
279
  if (node.wallType === 'curtain') {
126
280
  children.push(...buildCurtainWallFloorplan(node, getWallEffectiveHeightForNodes(node, ctx.sceneNodes ?? {}), stroke, ctx.children));
127
281
  }
282
+ else if (node.assembly) {
283
+ // Assembly layer lines + framing poché, drawn inside the footprint.
284
+ children.push(...buildWallAssemblyLayers(self, node, getLayerMiters(), ctx.children, documentMode));
285
+ }
128
286
  if (automaticDimensions) {
129
287
  const dimensionStroke = isSelected && palette ? palette.selectedStroke : (palette?.measurementStroke ?? '#334155');
130
288
  const dimensionStandard = constructionDimensionStandard({
@@ -196,8 +354,8 @@ export function buildWallFloorplan(node, ctx) {
196
354
  payload: { wallId: node.id, endpoint: 'end' },
197
355
  });
198
356
  const thicknessFrame = getWallCurveFrameAt(self, 0.5);
199
- const halfVisibleThickness = getWallThickness(self) / 2;
200
357
  for (const side of [1, -1]) {
358
+ const halfVisibleThickness = getWallLocalFaceZ(self, side > 0 ? 'a' : 'b') * side;
201
359
  children.push({
202
360
  kind: 'endpoint-handle',
203
361
  point: [
@@ -209,11 +367,10 @@ export function buildWallFloorplan(node, ctx) {
209
367
  payload: { wallId: node.id, side },
210
368
  });
211
369
  }
212
- // Side move arrows — two directional arrows at the wall midpoint,
213
- // pointing outward perpendicular to the wall. Mirrors the 3D
214
- // `WallMoveSideHandles` arrows so users can grab the wall body
215
- // from the floor plan. PointerDown on either arrow activates
216
- // `wallFloorplanMoveTarget` via the registry-layer dispatcher.
370
+ // Side push arrows — two directional arrows at the wall midpoint,
371
+ // pointing outward perpendicular to the wall. They are the 3D side
372
+ // arrows' push (same handle, drag and commit, run by the floor plan for
373
+ // `WALL_PUSH_AFFORDANCE`); only their placement is plan-specific.
217
374
  {
218
375
  const dx = node.end[0] - node.start[0];
219
376
  const dz = node.end[1] - node.start[1];
@@ -222,16 +379,22 @@ export function buildWallFloorplan(node, ctx) {
222
379
  const midpoint = getWallMidpointHandlePoint(node);
223
380
  const nx = -dz / wallLength;
224
381
  const nz = dx / wallLength;
225
- const offset = floorplanWallThickness(node) / 2 + 0.05;
382
+ const offsets = getWallFaceOffsets({ ...node, thickness: floorplanWallThickness(node) });
383
+ const offset = offsets.a + 0.05;
384
+ const backOffset = -offsets.b + 0.05;
226
385
  children.push({
227
386
  kind: 'move-arrow',
228
387
  point: [midpoint.x + nx * offset, midpoint.y + nz * offset],
229
388
  angle: Math.atan2(nz, nx),
389
+ affordance: WALL_PUSH_AFFORDANCE,
390
+ payload: { wallId: node.id, side: 'a' },
230
391
  });
231
392
  children.push({
232
393
  kind: 'move-arrow',
233
- point: [midpoint.x - nx * offset, midpoint.y - nz * offset],
394
+ point: [midpoint.x - nx * backOffset, midpoint.y - nz * backOffset],
234
395
  angle: Math.atan2(-nz, -nx),
396
+ affordance: WALL_PUSH_AFFORDANCE,
397
+ payload: { wallId: node.id, side: 'b' },
235
398
  });
236
399
  }
237
400
  }
@@ -257,8 +420,8 @@ function buildSelectedWallHatchLines(wall, stroke) {
257
420
  const length = getWallCurveLength(wall);
258
421
  if (length <= 1e-6)
259
422
  return [];
260
- const halfAcross = getWallThickness(wall) / 2;
261
- const halfAlong = halfAcross;
423
+ const offsets = getWallFaceOffsets(wall);
424
+ const halfAlong = offsets.a - getWallBodyCenterOffset(wall);
262
425
  const count = Math.max(1, Math.floor(length / FLOORPLAN_SELECTION_HATCH_SPACING));
263
426
  const spacing = length / count;
264
427
  const lines = [];
@@ -267,10 +430,10 @@ function buildSelectedWallHatchLines(wall, stroke) {
267
430
  const frame = getWallCurveFrameAt(wall, along / length);
268
431
  lines.push({
269
432
  kind: 'line',
270
- x1: frame.point.x - frame.tangent.x * halfAlong - frame.normal.x * halfAcross,
271
- y1: frame.point.y - frame.tangent.y * halfAlong - frame.normal.y * halfAcross,
272
- x2: frame.point.x + frame.tangent.x * halfAlong + frame.normal.x * halfAcross,
273
- y2: frame.point.y + frame.tangent.y * halfAlong + frame.normal.y * halfAcross,
433
+ x1: frame.point.x - frame.tangent.x * halfAlong - frame.normal.x * -offsets.b,
434
+ y1: frame.point.y - frame.tangent.y * halfAlong - frame.normal.y * -offsets.b,
435
+ x2: frame.point.x + frame.tangent.x * halfAlong + frame.normal.x * offsets.a,
436
+ y2: frame.point.y + frame.tangent.y * halfAlong + frame.normal.y * offsets.a,
274
437
  stroke,
275
438
  strokeWidth: FLOORPLAN_SELECTION_HATCH_STROKE_WIDTH,
276
439
  pointerEvents: 'none',
@@ -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,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
+ {"version":3,"file":"measurement.d.ts","sourceRoot":"","sources":["../../src/wall/measurement.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,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,CA2F5E;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,4 +1,4 @@
1
- import { getWallArcData, getWallCurveFrameAt, getWallThickness, sampleWallCenterline, useScene, } from '@pascal-app/core';
1
+ import { getWallArcData, getWallCurveFrameAt, getWallFaceOffsets, getWallLocalFaceZ, sampleWallCenterline, useScene, } from '@pascal-app/core';
2
2
  import { resolveWallOpeningCeiling } from '../shared/wall-opening-ceiling';
3
3
  const point = (x, y, z) => [x, y, z];
4
4
  export function wallMeasurementFeatures(wall) {
@@ -6,14 +6,14 @@ export function wallMeasurementFeatures(wall) {
6
6
  const arc = getWallArcData(wall);
7
7
  const centerline = sampleWallCenterline(wall).map(({ x, y }) => point(x, 0, y));
8
8
  const midpoint = getWallCurveFrameAt(wall, 0.5).point;
9
- const halfThickness = getWallThickness(wall) / 2;
9
+ const { a, b } = getWallFaceOffsets(wall);
10
10
  const leftFace = centerline.map((_center, index) => {
11
11
  const frame = getWallCurveFrameAt(wall, index / Math.max(1, centerline.length - 1));
12
- return point(frame.point.x + frame.normal.x * halfThickness, 0, frame.point.y + frame.normal.y * halfThickness);
12
+ return point(frame.point.x + frame.normal.x * a, 0, frame.point.y + frame.normal.y * a);
13
13
  });
14
14
  const rightFace = centerline.map((_center, index) => {
15
15
  const frame = getWallCurveFrameAt(wall, index / Math.max(1, centerline.length - 1));
16
- return point(frame.point.x - frame.normal.x * halfThickness, 0, frame.point.y - frame.normal.y * halfThickness);
16
+ return point(frame.point.x - frame.normal.x * -b, 0, frame.point.y - frame.normal.y * -b);
17
17
  });
18
18
  return [
19
19
  {
@@ -139,7 +139,7 @@ export function matchWallMeasurementFeature(wall, hit, maxDistance) {
139
139
  const side = (hit[0] - frame.point.x) * frame.normal.x + (hit[2] - frame.point.y) * frame.normal.y >= 0
140
140
  ? 1
141
141
  : -1;
142
- const halfThickness = getWallThickness(wall) / 2;
142
+ const halfThickness = getWallLocalFaceZ(wall, side > 0 ? 'a' : 'b') * side;
143
143
  const faceX = frame.point.x + frame.normal.x * halfThickness * side;
144
144
  const faceZ = frame.point.y + frame.normal.y * halfThickness * side;
145
145
  const faceDistance = Math.hypot(hit[0] - faceX, hit[2] - faceZ);
@@ -1 +1 @@
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
+ {"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;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,CA+hBzE,CAAA;AAkBD,eAAe,oBAAoB,CAAA"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { collectAlignmentAnchors, emitter, getWallBaseElevationForNodes, getWallCurveLength, getWallThickness, pauseSceneHistory, resolveAlignment, resolveMovedWallSupportSlabPatch, resumeSceneHistory, runAsSingleSceneHistoryStep, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
3
+ import { acquireSceneHistoryPause, collectAlignmentAnchors, emitter, getWallBaseElevationForNodes, getWallCurveLength, getWallThickness, resolveAlignment, resolveMovedWallSupportSlabPatch, 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';
@@ -147,8 +147,13 @@ export const MoveWallEndpointTool = ({ target }) => {
147
147
  const wallAlignmentCandidates = collectAlignmentAnchors(useScene.getState().nodes, nodeId);
148
148
  const movingLinkedIdSet = new Set(movingLinkedWallIds);
149
149
  const attachedAlignmentCandidates = wallAlignmentCandidates.filter((anchor) => !movingLinkedIdSet.has(anchor.nodeId));
150
- pauseSceneHistory(useScene);
150
+ // A lease, so a cancel and the unmount that follows it release it once.
151
+ const releaseHistory = acquireSceneHistoryPause(useScene);
151
152
  let wasCommitted = false;
153
+ // Ends with the drop, the dismiss or the cancel: the window listeners stay
154
+ // until the unmount, and a release after Escape must not commit the
155
+ // cancelled preview (nor a late pointer move republish it).
156
+ let live = true;
152
157
  // Last RAW cursor point from `grid:move` — lets the Alt keydown/keyup
153
158
  // handlers re-run the FULL snap pipeline immediately on a modifier change
154
159
  // instead of waiting for the next mousemove. The raw point (not the
@@ -308,6 +313,8 @@ export const MoveWallEndpointTool = ({ target }) => {
308
313
  return alignedPoint;
309
314
  };
310
315
  const onGridMove = (event) => {
316
+ if (!live)
317
+ return;
311
318
  const planPoint = [event.localPosition[0], event.localPosition[2]];
312
319
  lastRawPoint = planPoint;
313
320
  // The keydown listener can't observe an Alt press that predates the
@@ -321,6 +328,8 @@ export const MoveWallEndpointTool = ({ target }) => {
321
328
  applyPreview(resolveDragPoint(planPoint), altPressedRef.current);
322
329
  };
323
330
  const onPointerUp = () => {
331
+ if (!live)
332
+ return;
324
333
  useAlignmentGuides.getState().clear();
325
334
  useWallSnapIndicator.getState().clear();
326
335
  // The handle sits on the wall body, so the browser fires a click on the
@@ -343,11 +352,13 @@ export const MoveWallEndpointTool = ({ target }) => {
343
352
  hasReleasedOnce = true;
344
353
  return;
345
354
  }
355
+ live = false;
346
356
  restoreOriginal();
347
357
  useViewer.getState().setSelection({ selectedIds: [nodeId] });
348
358
  exitMoveMode();
349
359
  return;
350
360
  }
361
+ live = false;
351
362
  if (isSegmentLongEnough(preview.start, preview.end)) {
352
363
  wasCommitted = true;
353
364
  const linkedUpdates = altPressedRef.current
@@ -360,7 +371,7 @@ export const MoveWallEndpointTool = ({ target }) => {
360
371
  // ops (create halves, migrate attachments, delete host) would each
361
372
  // push their own entry, so the whole commit runs as one history step.
362
373
  clearPreviewOverrides();
363
- resumeSceneHistory(useScene);
374
+ releaseHistory();
364
375
  runAsSingleSceneHistoryStep(useScene, () => {
365
376
  // Dropping the endpoint on another wall's interior splits that host
366
377
  // like the draw path does. Linked walls updated in this commit share
@@ -404,7 +415,6 @@ export const MoveWallEndpointTool = ({ target }) => {
404
415
  useScene.getState().markDirty(u.id);
405
416
  }
406
417
  });
407
- pauseSceneHistory(useScene);
408
418
  triggerSFX('sfx:item-place');
409
419
  }
410
420
  useViewer.getState().setSelection({ selectedIds: [nodeId] });
@@ -412,11 +422,14 @@ export const MoveWallEndpointTool = ({ target }) => {
412
422
  exitMoveMode();
413
423
  };
414
424
  const onCancel = () => {
425
+ if (!live)
426
+ return;
427
+ live = false;
415
428
  useAlignmentGuides.getState().clear();
416
429
  useWallSnapIndicator.getState().clear();
417
430
  restoreOriginal();
418
431
  useViewer.getState().setSelection({ selectedIds: [nodeId] });
419
- resumeSceneHistory(useScene);
432
+ releaseHistory();
420
433
  setAngleLabel(null);
421
434
  markToolCancelConsumed();
422
435
  exitMoveMode();
@@ -427,7 +440,7 @@ export const MoveWallEndpointTool = ({ target }) => {
427
440
  // re-snaps against their (now live) corners, re-attach drops them from
428
441
  // the candidate set again — without waiting for the next mousemove.
429
442
  const setAltState = (pressed) => {
430
- if (altPressedRef.current === pressed)
443
+ if (!live || altPressedRef.current === pressed)
431
444
  return;
432
445
  altPressedRef.current = pressed;
433
446
  setAltPressed(pressed);
@@ -463,7 +476,7 @@ export const MoveWallEndpointTool = ({ target }) => {
463
476
  if (!wasCommitted) {
464
477
  restoreOriginal(false);
465
478
  }
466
- resumeSceneHistory(useScene);
479
+ releaseHistory();
467
480
  emitter.off('grid:move', onGridMove);
468
481
  emitter.off('tool:cancel', onCancel);
469
482
  window.removeEventListener('pointerup', onPointerUp);