@pascal-app/nodes 1.0.5 → 1.0.7

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 (566) hide show
  1. package/README.md +1 -0
  2. package/dist/beam/actions/move-endpoint.d.ts +24 -0
  3. package/dist/beam/actions/move-endpoint.d.ts.map +1 -0
  4. package/dist/beam/actions/move-endpoint.js +54 -0
  5. package/dist/beam/definition.d.ts +14 -0
  6. package/dist/beam/definition.d.ts.map +1 -0
  7. package/dist/beam/definition.js +173 -0
  8. package/dist/beam/draft-settings.d.ts +17 -0
  9. package/dist/beam/draft-settings.d.ts.map +1 -0
  10. package/dist/beam/draft-settings.js +81 -0
  11. package/dist/beam/drafting.d.ts +35 -0
  12. package/dist/beam/drafting.d.ts.map +1 -0
  13. package/dist/beam/drafting.js +103 -0
  14. package/dist/beam/floorplan-affordances.d.ts +8 -0
  15. package/dist/beam/floorplan-affordances.d.ts.map +1 -0
  16. package/dist/beam/floorplan-affordances.js +40 -0
  17. package/dist/beam/floorplan-move.d.ts +11 -0
  18. package/dist/beam/floorplan-move.d.ts.map +1 -0
  19. package/dist/beam/floorplan-move.js +54 -0
  20. package/dist/beam/floorplan.d.ts +11 -0
  21. package/dist/beam/floorplan.d.ts.map +1 -0
  22. package/dist/beam/floorplan.js +91 -0
  23. package/dist/beam/geometry.d.ts +19 -0
  24. package/dist/beam/geometry.d.ts.map +1 -0
  25. package/dist/beam/geometry.js +63 -0
  26. package/dist/beam/index.d.ts +3 -0
  27. package/dist/beam/index.d.ts.map +1 -0
  28. package/dist/beam/index.js +2 -0
  29. package/dist/beam/move-endpoint-tool.d.ts +21 -0
  30. package/dist/beam/move-endpoint-tool.d.ts.map +1 -0
  31. package/dist/beam/move-endpoint-tool.js +49 -0
  32. package/dist/beam/move-tool.d.ts +12 -0
  33. package/dist/beam/move-tool.d.ts.map +1 -0
  34. package/dist/beam/move-tool.js +114 -0
  35. package/dist/beam/panel-model.d.ts +28 -0
  36. package/dist/beam/panel-model.d.ts.map +1 -0
  37. package/dist/beam/panel-model.js +123 -0
  38. package/dist/beam/panel.d.ts +13 -0
  39. package/dist/beam/panel.d.ts.map +1 -0
  40. package/dist/beam/panel.js +107 -0
  41. package/dist/beam/parametrics.d.ts +3 -0
  42. package/dist/beam/parametrics.d.ts.map +1 -0
  43. package/dist/beam/parametrics.js +4 -0
  44. package/dist/beam/renderer.d.ts +13 -0
  45. package/dist/beam/renderer.d.ts.map +1 -0
  46. package/dist/beam/renderer.js +36 -0
  47. package/dist/beam/schema.d.ts +2 -0
  48. package/dist/beam/schema.d.ts.map +1 -0
  49. package/dist/beam/schema.js +1 -0
  50. package/dist/beam/tool.d.ts +13 -0
  51. package/dist/beam/tool.d.ts.map +1 -0
  52. package/dist/beam/tool.js +152 -0
  53. package/dist/box-vent/panel.d.ts.map +1 -1
  54. package/dist/box-vent/panel.js +8 -7
  55. package/dist/cabinet/batchable.d.ts +10 -0
  56. package/dist/cabinet/batchable.d.ts.map +1 -0
  57. package/dist/cabinet/batchable.js +12 -0
  58. package/dist/cabinet/compartment-card.d.ts.map +1 -1
  59. package/dist/cabinet/compartment-card.js +142 -46
  60. package/dist/cabinet/countertop-layout.d.ts +5 -0
  61. package/dist/cabinet/countertop-layout.d.ts.map +1 -1
  62. package/dist/cabinet/definition.d.ts.map +1 -1
  63. package/dist/cabinet/definition.js +3 -0
  64. package/dist/cabinet/dimension-input.d.ts +6 -0
  65. package/dist/cabinet/dimension-input.d.ts.map +1 -0
  66. package/dist/cabinet/dimension-input.js +8 -0
  67. package/dist/cabinet/essential-controls.d.ts.map +1 -1
  68. package/dist/cabinet/essential-controls.js +82 -17
  69. package/dist/cabinet/index.d.ts +1 -1
  70. package/dist/cabinet/index.d.ts.map +1 -1
  71. package/dist/cabinet/index.js +1 -1
  72. package/dist/cabinet/kitchen-catalog.d.ts +17 -4
  73. package/dist/cabinet/kitchen-catalog.d.ts.map +1 -1
  74. package/dist/cabinet/kitchen-catalog.js +45 -7
  75. package/dist/cabinet/kitchen-collection.d.ts.map +1 -1
  76. package/dist/cabinet/kitchen-collection.js +21 -5
  77. package/dist/cabinet/kitchen-module-actions.d.ts.map +1 -1
  78. package/dist/cabinet/kitchen-module-actions.js +107 -14
  79. package/dist/cabinet/neighbor-placement.d.ts +10 -0
  80. package/dist/cabinet/neighbor-placement.d.ts.map +1 -1
  81. package/dist/cabinet/panel.d.ts.map +1 -1
  82. package/dist/cabinet/panel.js +127 -50
  83. package/dist/cabinet/run-finishing.d.ts +5 -0
  84. package/dist/cabinet/run-finishing.d.ts.map +1 -1
  85. package/dist/cabinet/run-ops.d.ts +5 -0
  86. package/dist/cabinet/run-ops.d.ts.map +1 -1
  87. package/dist/cabinet/run-panel.d.ts.map +1 -1
  88. package/dist/cabinet/run-panel.js +203 -52
  89. package/dist/cabinet/tool.d.ts.map +1 -1
  90. package/dist/cabinet/tool.js +8 -5
  91. package/dist/ceiling/build-up-section.d.ts +7 -0
  92. package/dist/ceiling/build-up-section.d.ts.map +1 -0
  93. package/dist/ceiling/build-up-section.js +57 -0
  94. package/dist/ceiling/definition.d.ts.map +1 -1
  95. package/dist/ceiling/definition.js +3 -1
  96. package/dist/ceiling/floorplan-affordances.d.ts +112 -0
  97. package/dist/ceiling/floorplan-affordances.d.ts.map +1 -1
  98. package/dist/ceiling/materials.d.ts +5 -0
  99. package/dist/ceiling/materials.d.ts.map +1 -1
  100. package/dist/ceiling/materials.js +17 -0
  101. package/dist/ceiling/panel-model.d.ts +13 -0
  102. package/dist/ceiling/panel-model.d.ts.map +1 -0
  103. package/dist/ceiling/panel-model.js +49 -0
  104. package/dist/ceiling/panel.d.ts.map +1 -1
  105. package/dist/ceiling/panel.js +82 -18
  106. package/dist/ceiling/renderer.d.ts.map +1 -1
  107. package/dist/ceiling/renderer.js +10 -4
  108. package/dist/ceiling/tool.d.ts.map +1 -1
  109. package/dist/ceiling/tool.js +24 -4
  110. package/dist/chimney/panel.d.ts.map +1 -1
  111. package/dist/chimney/panel.js +113 -41
  112. package/dist/column/definition.d.ts.map +1 -1
  113. package/dist/column/definition.js +3 -0
  114. package/dist/column/floorplan.d.ts.map +1 -1
  115. package/dist/column/floorplan.js +17 -0
  116. package/dist/column/hosted-resize.d.ts +28 -1
  117. package/dist/column/hosted-resize.d.ts.map +1 -1
  118. package/dist/column/panel.d.ts.map +1 -1
  119. package/dist/column/panel.js +125 -37
  120. package/dist/column/post-options.d.ts +10 -0
  121. package/dist/column/post-options.d.ts.map +1 -0
  122. package/dist/column/post-options.js +71 -0
  123. package/dist/column/post-placement.d.ts +78 -0
  124. package/dist/column/post-placement.d.ts.map +1 -0
  125. package/dist/column/post-placement.js +157 -0
  126. package/dist/column/post-section.d.ts +17 -0
  127. package/dist/column/post-section.d.ts.map +1 -0
  128. package/dist/column/post-section.js +95 -0
  129. package/dist/column/post-tool.d.ts +11 -0
  130. package/dist/column/post-tool.d.ts.map +1 -0
  131. package/dist/column/post-tool.js +94 -0
  132. package/dist/column/tool.d.ts +3 -10
  133. package/dist/column/tool.d.ts.map +1 -1
  134. package/dist/column/tool.js +13 -1
  135. package/dist/cupola/panel.d.ts.map +1 -1
  136. package/dist/cupola/panel.js +14 -7
  137. package/dist/door/actions.d.ts +7 -0
  138. package/dist/door/actions.d.ts.map +1 -0
  139. package/dist/door/actions.js +32 -0
  140. package/dist/door/contextual-dimensions.d.ts.map +1 -1
  141. package/dist/door/contextual-dimensions.js +11 -1
  142. package/dist/door/definition.d.ts.map +1 -1
  143. package/dist/door/definition.js +34 -7
  144. package/dist/door/floorplan-affordances.d.ts.map +1 -1
  145. package/dist/door/floorplan-affordances.js +5 -2
  146. package/dist/door/floorplan-move.d.ts.map +1 -1
  147. package/dist/door/floorplan-move.js +28 -6
  148. package/dist/door/floorplan.d.ts +2 -0
  149. package/dist/door/floorplan.d.ts.map +1 -1
  150. package/dist/door/floorplan.js +89 -16
  151. package/dist/door/move-tool.d.ts.map +1 -1
  152. package/dist/door/move-tool.js +60 -16
  153. package/dist/door/paint.d.ts +2 -7
  154. package/dist/door/paint.d.ts.map +1 -1
  155. package/dist/door/paint.js +26 -2
  156. package/dist/door/panel.d.ts.map +1 -1
  157. package/dist/door/panel.js +242 -90
  158. package/dist/door/parametrics.js +1 -1
  159. package/dist/door/placement.d.ts.map +1 -1
  160. package/dist/door/placement.js +9 -2
  161. package/dist/door/swing.d.ts +22 -0
  162. package/dist/door/swing.d.ts.map +1 -0
  163. package/dist/door/swing.js +36 -0
  164. package/dist/door/tool.d.ts.map +1 -1
  165. package/dist/door/tool.js +76 -29
  166. package/dist/dormer/panel-actions-section.d.ts.map +1 -1
  167. package/dist/dormer/panel-actions-section.js +3 -1
  168. package/dist/dormer/panel-position-section.d.ts.map +1 -1
  169. package/dist/dormer/panel-position-section.js +4 -3
  170. package/dist/dormer/panel-windows-section.d.ts.map +1 -1
  171. package/dist/dormer/panel-windows-section.js +38 -1
  172. package/dist/dormer/panel.d.ts.map +1 -1
  173. package/dist/dormer/panel.js +24 -18
  174. package/dist/downspout/inspector-editors.d.ts.map +1 -1
  175. package/dist/downspout/inspector-editors.js +3 -2
  176. package/dist/duct-fitting/inspector-editors.d.ts.map +1 -1
  177. package/dist/duct-fitting/inspector-editors.js +6 -1
  178. package/dist/duct-fitting/tool.d.ts.map +1 -1
  179. package/dist/duct-fitting/tool.js +11 -2
  180. package/dist/duct-terminal/tool.d.ts.map +1 -1
  181. package/dist/duct-terminal/tool.js +11 -2
  182. package/dist/elevator/panel.d.ts.map +1 -1
  183. package/dist/elevator/panel.js +41 -18
  184. package/dist/eyebrow-vent/panel.d.ts.map +1 -1
  185. package/dist/eyebrow-vent/panel.js +16 -6
  186. package/dist/fence/drafting.d.ts +2 -3
  187. package/dist/fence/drafting.d.ts.map +1 -1
  188. package/dist/fence/drafting.js +2 -3
  189. package/dist/fence/inspector-editors.d.ts.map +1 -1
  190. package/dist/fence/inspector-editors.js +64 -21
  191. package/dist/fence/move-endpoint-tool.d.ts.map +1 -1
  192. package/dist/fence/move-endpoint-tool.js +11 -2
  193. package/dist/fence/system.d.ts.map +1 -1
  194. package/dist/fence/system.js +13 -0
  195. package/dist/fence-feature/actions.d.ts.map +1 -1
  196. package/dist/fence-feature/actions.js +5 -2
  197. package/dist/fence-feature/inspector.d.ts.map +1 -1
  198. package/dist/fence-feature/inspector.js +150 -34
  199. package/dist/fence-feature/move-session.d.ts +1 -1
  200. package/dist/floor-opening/floorplan.d.ts +29 -6
  201. package/dist/floor-opening/floorplan.d.ts.map +1 -1
  202. package/dist/floor-opening/floorplan.js +172 -14
  203. package/dist/gutter/downspouts-panel.d.ts.map +1 -1
  204. package/dist/gutter/downspouts-panel.js +14 -2
  205. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  206. package/dist/hvac-equipment/tool.js +3 -2
  207. package/dist/i18n/definition-messages.d.ts +5 -0
  208. package/dist/i18n/definition-messages.d.ts.map +1 -0
  209. package/dist/i18n/definition-messages.js +771 -0
  210. package/dist/index.d.ts +4 -1
  211. package/dist/index.d.ts.map +1 -1
  212. package/dist/index.js +6 -1
  213. package/dist/item/authored-params.d.ts.map +1 -1
  214. package/dist/item/authored-params.js +19 -4
  215. package/dist/item/floorplan.d.ts +1 -1
  216. package/dist/item/floorplan.d.ts.map +1 -1
  217. package/dist/item/panel.d.ts.map +1 -1
  218. package/dist/item/panel.js +9 -7
  219. package/dist/liquid-line/tool.d.ts.map +1 -1
  220. package/dist/liquid-line/tool.js +10 -3
  221. package/dist/measurement/tool.d.ts +1 -1
  222. package/dist/measurement/tool.d.ts.map +1 -1
  223. package/dist/measurement/tool.js +8 -8
  224. package/dist/pipe-fitting/tool.d.ts.map +1 -1
  225. package/dist/pipe-fitting/tool.js +3 -2
  226. package/dist/pipe-trap/tool.d.ts.map +1 -1
  227. package/dist/pipe-trap/tool.js +7 -2
  228. package/dist/procedural-item/renderer.d.ts.map +1 -1
  229. package/dist/procedural-item/renderer.js +8 -1
  230. package/dist/ridge-vent/panel.d.ts.map +1 -1
  231. package/dist/ridge-vent/panel.js +22 -9
  232. package/dist/roof/barrel-panel.d.ts.map +1 -1
  233. package/dist/roof/barrel-panel.js +7 -3
  234. package/dist/roof/definition.d.ts.map +1 -1
  235. package/dist/roof/definition.js +33 -3
  236. package/dist/roof/floorplan-overrides.d.ts +22 -0
  237. package/dist/roof/floorplan-overrides.d.ts.map +1 -0
  238. package/dist/roof/floorplan-overrides.js +46 -0
  239. package/dist/roof/floorplan-tool.d.ts +9 -0
  240. package/dist/roof/floorplan-tool.d.ts.map +1 -0
  241. package/dist/roof/floorplan-tool.js +168 -0
  242. package/dist/roof/floorplan.d.ts.map +1 -1
  243. package/dist/roof/floorplan.js +131 -41
  244. package/dist/roof/glazing-controls.d.ts +2 -1
  245. package/dist/roof/glazing-controls.d.ts.map +1 -1
  246. package/dist/roof/glazing-controls.js +51 -13
  247. package/dist/roof/glazing-panel-editor.d.ts.map +1 -1
  248. package/dist/roof/glazing-panel-editor.js +40 -13
  249. package/dist/roof/glazing-panel.d.ts.map +1 -1
  250. package/dist/roof/glazing-panel.js +73 -9
  251. package/dist/roof/paint.d.ts +19 -0
  252. package/dist/roof/paint.d.ts.map +1 -0
  253. package/dist/roof/paint.js +158 -0
  254. package/dist/roof/panel.d.ts.map +1 -1
  255. package/dist/roof/panel.js +90 -22
  256. package/dist/roof/renderer.d.ts.map +1 -1
  257. package/dist/roof/renderer.js +13 -2
  258. package/dist/roof/roof-footprint-source.d.ts +17 -0
  259. package/dist/roof/roof-footprint-source.d.ts.map +1 -1
  260. package/dist/roof/roof-footprint-source.js +14 -0
  261. package/dist/roof/roof-footprint.d.ts +36 -2
  262. package/dist/roof/roof-footprint.d.ts.map +1 -1
  263. package/dist/roof/roof-footprint.js +124 -2
  264. package/dist/roof/roof-materials.d.ts.map +1 -1
  265. package/dist/roof/roof-materials.js +10 -1
  266. package/dist/roof/roof-placement-mode.d.ts +0 -2
  267. package/dist/roof/roof-placement-mode.d.ts.map +1 -1
  268. package/dist/roof/roof-placement-mode.js +8 -6
  269. package/dist/roof/roof-plan-creases.d.ts +50 -0
  270. package/dist/roof/roof-plan-creases.d.ts.map +1 -0
  271. package/dist/roof/roof-plan-creases.js +194 -0
  272. package/dist/roof/roof-ridge-mode.d.ts +20 -0
  273. package/dist/roof/roof-ridge-mode.d.ts.map +1 -0
  274. package/dist/roof/roof-ridge-mode.js +16 -0
  275. package/dist/roof/tool.d.ts +17 -4
  276. package/dist/roof/tool.d.ts.map +1 -1
  277. package/dist/roof/tool.js +211 -113
  278. package/dist/roof/wall-catch.d.ts +106 -0
  279. package/dist/roof/wall-catch.d.ts.map +1 -0
  280. package/dist/roof/wall-catch.js +267 -0
  281. package/dist/roof-segment/build-up-section.d.ts +9 -0
  282. package/dist/roof-segment/build-up-section.d.ts.map +1 -0
  283. package/dist/roof-segment/build-up-section.js +191 -0
  284. package/dist/roof-segment/definition.d.ts.map +1 -1
  285. package/dist/roof-segment/definition.js +50 -5
  286. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  287. package/dist/roof-segment/floorplan-affordances.js +68 -19
  288. package/dist/roof-segment/floorplan.d.ts.map +1 -1
  289. package/dist/roof-segment/floorplan.js +16 -12
  290. package/dist/roof-segment/paint.d.ts +3 -1
  291. package/dist/roof-segment/paint.d.ts.map +1 -1
  292. package/dist/roof-segment/paint.js +43 -2
  293. package/dist/roof-segment/panel-model.d.ts +23 -0
  294. package/dist/roof-segment/panel-model.d.ts.map +1 -0
  295. package/dist/roof-segment/panel-model.js +64 -0
  296. package/dist/roof-segment/panel.d.ts.map +1 -1
  297. package/dist/roof-segment/panel.js +96 -14
  298. package/dist/roof-segment/parametrics.d.ts.map +1 -1
  299. package/dist/roof-segment/parametrics.js +4 -0
  300. package/dist/roof-segment/renderer.d.ts.map +1 -1
  301. package/dist/roof-segment/renderer.js +26 -5
  302. package/dist/separator/definition.d.ts.map +1 -1
  303. package/dist/separator/definition.js +10 -12
  304. package/dist/separator/floorplan-affordances.d.ts +9 -0
  305. package/dist/separator/floorplan-affordances.d.ts.map +1 -0
  306. package/dist/separator/floorplan-affordances.js +23 -0
  307. package/dist/separator/floorplan.d.ts +9 -0
  308. package/dist/separator/floorplan.d.ts.map +1 -0
  309. package/dist/separator/floorplan.js +54 -0
  310. package/dist/separator/renderer.d.ts +4 -0
  311. package/dist/separator/renderer.d.ts.map +1 -1
  312. package/dist/separator/renderer.js +21 -6
  313. package/dist/separator/selection.d.ts +10 -0
  314. package/dist/separator/selection.d.ts.map +1 -0
  315. package/dist/separator/selection.js +35 -0
  316. package/dist/shared/build-up-controls.d.ts +88 -0
  317. package/dist/shared/build-up-controls.d.ts.map +1 -0
  318. package/dist/shared/build-up-controls.js +139 -0
  319. package/dist/shared/curtain-opening-limits.d.ts.map +1 -1
  320. package/dist/shared/curtain-opening-limits.js +44 -14
  321. package/dist/shared/item-interaction-actions.d.ts.map +1 -1
  322. package/dist/shared/item-interaction-actions.js +11 -2
  323. package/dist/shared/layer-thickness.d.ts +2 -0
  324. package/dist/shared/layer-thickness.d.ts.map +1 -0
  325. package/dist/shared/layer-thickness.js +3 -0
  326. package/dist/shared/move-roof-tool.d.ts.map +1 -1
  327. package/dist/shared/move-roof-tool.js +100 -5
  328. package/dist/shared/node-batch/batchable.d.ts +2 -0
  329. package/dist/shared/node-batch/batchable.d.ts.map +1 -1
  330. package/dist/shared/node-batch/batchable.js +4 -0
  331. package/dist/shared/node-batch/candidates.d.ts +21 -5
  332. package/dist/shared/node-batch/candidates.d.ts.map +1 -1
  333. package/dist/shared/node-batch/candidates.js +85 -50
  334. package/dist/shared/node-batch/system.d.ts.map +1 -1
  335. package/dist/shared/node-batch/system.js +24 -15
  336. package/dist/shared/opening-casing-move.d.ts +16 -0
  337. package/dist/shared/opening-casing-move.d.ts.map +1 -0
  338. package/dist/shared/opening-casing-move.js +33 -0
  339. package/dist/shared/opening-casing-section.d.ts +15 -0
  340. package/dist/shared/opening-casing-section.d.ts.map +1 -0
  341. package/dist/shared/opening-casing-section.js +38 -0
  342. package/dist/shared/opening-casing.d.ts +26 -0
  343. package/dist/shared/opening-casing.d.ts.map +1 -0
  344. package/dist/shared/opening-casing.js +80 -0
  345. package/dist/shared/opening-depth-position.d.ts +13 -0
  346. package/dist/shared/opening-depth-position.d.ts.map +1 -0
  347. package/dist/shared/opening-depth-position.js +34 -0
  348. package/dist/shared/opening-documentation.d.ts.map +1 -1
  349. package/dist/shared/opening-documentation.js +17 -8
  350. package/dist/shared/opening-guides-runtime.d.ts +2 -1
  351. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  352. package/dist/shared/opening-guides-runtime.js +11 -7
  353. package/dist/shared/opening-labels.d.ts +11 -0
  354. package/dist/shared/opening-labels.d.ts.map +1 -0
  355. package/dist/shared/opening-labels.js +46 -0
  356. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  357. package/dist/shared/opening-placement-dimensions.js +11 -9
  358. package/dist/shared/opening-plane-offset.d.ts +4 -3
  359. package/dist/shared/opening-plane-offset.d.ts.map +1 -1
  360. package/dist/shared/opening-plane-offset.js +7 -4
  361. package/dist/shared/opening-swap.d.ts +8 -0
  362. package/dist/shared/opening-swap.d.ts.map +1 -0
  363. package/dist/shared/opening-swap.js +18 -0
  364. package/dist/shared/polygon-vertex-affordance.d.ts +19 -0
  365. package/dist/shared/polygon-vertex-affordance.d.ts.map +1 -1
  366. package/dist/shared/polygon-vertex-affordance.js +65 -6
  367. package/dist/shared/roof-opening-host.d.ts +2 -1
  368. package/dist/shared/roof-opening-host.d.ts.map +1 -1
  369. package/dist/shared/roof-opening-host.js +14 -5
  370. package/dist/shared/roof-wall-opening-cut.d.ts.map +1 -1
  371. package/dist/shared/roof-wall-opening-cut.js +14 -6
  372. package/dist/shared/roof-wall-opening-placement.d.ts +2 -1
  373. package/dist/shared/roof-wall-opening-placement.d.ts.map +1 -1
  374. package/dist/shared/roof-wall-opening-placement.js +6 -4
  375. package/dist/shared/run-hanger-inspector.d.ts.map +1 -1
  376. package/dist/shared/run-hanger-inspector.js +39 -5
  377. package/dist/shared/system-check-panel.d.ts.map +1 -1
  378. package/dist/shared/system-check-panel.js +94 -15
  379. package/dist/shared/wall-attach-target.d.ts.map +1 -1
  380. package/dist/shared/wall-attach-target.js +6 -3
  381. package/dist/shelf/definition.d.ts.map +1 -1
  382. package/dist/shelf/definition.js +2 -0
  383. package/dist/site/ground-hole.d.ts +3 -3
  384. package/dist/site/ground-hole.js +3 -3
  385. package/dist/site/ground-veil.d.ts +5 -12
  386. package/dist/site/ground-veil.d.ts.map +1 -1
  387. package/dist/site/ground-veil.js +9 -33
  388. package/dist/site/panel.d.ts.map +1 -1
  389. package/dist/site/panel.js +52 -12
  390. package/dist/site/renderer.d.ts.map +1 -1
  391. package/dist/site/renderer.js +52 -23
  392. package/dist/skylight/panel.d.ts.map +1 -1
  393. package/dist/skylight/panel.js +49 -19
  394. package/dist/slab/deck-geometry.d.ts +28 -0
  395. package/dist/slab/deck-geometry.d.ts.map +1 -0
  396. package/dist/slab/deck-geometry.js +320 -0
  397. package/dist/slab/definition.d.ts +2 -1
  398. package/dist/slab/definition.d.ts.map +1 -1
  399. package/dist/slab/definition.js +6 -1
  400. package/dist/slab/dependency-tracker.d.ts.map +1 -1
  401. package/dist/slab/dependency-tracker.js +3 -0
  402. package/dist/slab/floorplan-affordances.d.ts +500 -0
  403. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  404. package/dist/slab/geometry.d.ts.map +1 -1
  405. package/dist/slab/geometry.js +46 -9
  406. package/dist/slab/panel.d.ts.map +1 -1
  407. package/dist/slab/panel.js +97 -21
  408. package/dist/slab/renderer.d.ts +11 -0
  409. package/dist/slab/renderer.d.ts.map +1 -0
  410. package/dist/slab/renderer.js +19 -0
  411. package/dist/slab/system.d.ts.map +1 -1
  412. package/dist/slab/system.js +12 -1
  413. package/dist/solar-panel/panel.d.ts.map +1 -1
  414. package/dist/solar-panel/panel.js +49 -14
  415. package/dist/stair/construction-controls.d.ts +3 -1
  416. package/dist/stair/construction-controls.d.ts.map +1 -1
  417. package/dist/stair/construction-controls.js +75 -12
  418. package/dist/stair/paint.d.ts +6 -0
  419. package/dist/stair/paint.d.ts.map +1 -1
  420. package/dist/stair/panel.d.ts.map +1 -1
  421. package/dist/stair/panel.js +243 -51
  422. package/dist/stair/parametrics.d.ts.map +1 -1
  423. package/dist/stair/parametrics.js +7 -0
  424. package/dist/stair/placement-defaults.d.ts +18 -0
  425. package/dist/stair/placement-defaults.d.ts.map +1 -0
  426. package/dist/stair/placement-defaults.js +27 -0
  427. package/dist/stair/railing-controls.d.ts.map +1 -1
  428. package/dist/stair/railing-controls.js +78 -18
  429. package/dist/stair/renderer.d.ts.map +1 -1
  430. package/dist/stair/renderer.js +16 -10
  431. package/dist/stair/structure-controls.d.ts +18 -0
  432. package/dist/stair/structure-controls.d.ts.map +1 -0
  433. package/dist/stair/structure-controls.js +275 -0
  434. package/dist/stair/tool.d.ts.map +1 -1
  435. package/dist/stair/tool.js +13 -9
  436. package/dist/stair/use-stair-render-data.d.ts +41 -0
  437. package/dist/stair/use-stair-render-data.d.ts.map +1 -1
  438. package/dist/stair-segment/panel.d.ts.map +1 -1
  439. package/dist/stair-segment/panel.js +65 -18
  440. package/dist/turbine-vent/panel.d.ts.map +1 -1
  441. package/dist/turbine-vent/panel.js +14 -5
  442. package/dist/unit/unit-panel.d.ts.map +1 -1
  443. package/dist/unit/unit-panel.js +28 -12
  444. package/dist/wall/actions.d.ts +1 -1
  445. package/dist/wall/actions.d.ts.map +1 -1
  446. package/dist/wall/actions.js +17 -13
  447. package/dist/wall/construction-dimensions.d.ts +6 -0
  448. package/dist/wall/construction-dimensions.d.ts.map +1 -1
  449. package/dist/wall/construction-dimensions.js +8 -0
  450. package/dist/wall/contextual-dimensions.d.ts +6 -0
  451. package/dist/wall/contextual-dimensions.d.ts.map +1 -1
  452. package/dist/wall/contextual-dimensions.js +104 -17
  453. package/dist/wall/curtain-opening-frame.d.ts.map +1 -1
  454. package/dist/wall/curtain-opening-frame.js +6 -4
  455. package/dist/wall/curtain-wall-layout.d.ts +1 -1
  456. package/dist/wall/curtain-wall-layout.d.ts.map +1 -1
  457. package/dist/wall/curtain-wall-layout.js +6 -4
  458. package/dist/wall/curtain-wall-materials.d.ts.map +1 -1
  459. package/dist/wall/curtain-wall-materials.js +8 -3
  460. package/dist/wall/curtain-wall-panel.d.ts.map +1 -1
  461. package/dist/wall/curtain-wall-panel.js +241 -37
  462. package/dist/wall/curve-tool.d.ts.map +1 -1
  463. package/dist/wall/curve-tool.js +2 -3
  464. package/dist/wall/definition.d.ts.map +1 -1
  465. package/dist/wall/definition.js +20 -5
  466. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  467. package/dist/wall/floorplan-affordances.js +9 -6
  468. package/dist/wall/floorplan-move.d.ts.map +1 -1
  469. package/dist/wall/floorplan-move.js +66 -16
  470. package/dist/wall/floorplan.d.ts +4 -5
  471. package/dist/wall/floorplan.d.ts.map +1 -1
  472. package/dist/wall/floorplan.js +62 -46
  473. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  474. package/dist/wall/move-endpoint-tool.js +1 -0
  475. package/dist/wall/move-tool.d.ts.map +1 -1
  476. package/dist/wall/move-tool.js +77 -12
  477. package/dist/wall/paint.d.ts +2 -2
  478. package/dist/wall/paint.d.ts.map +1 -1
  479. package/dist/wall/paint.js +11 -4
  480. package/dist/wall/panel-model.d.ts +17 -2
  481. package/dist/wall/panel-model.d.ts.map +1 -1
  482. package/dist/wall/panel-model.js +158 -18
  483. package/dist/wall/panel.d.ts +8 -0
  484. package/dist/wall/panel.d.ts.map +1 -1
  485. package/dist/wall/panel.js +228 -156
  486. package/dist/wall/parametrics.d.ts +1 -1
  487. package/dist/wall/parametrics.d.ts.map +1 -1
  488. package/dist/wall/parametrics.js +14 -1
  489. package/dist/wall/railing-wall-adapter.d.ts +7 -0
  490. package/dist/wall/railing-wall-adapter.d.ts.map +1 -0
  491. package/dist/wall/railing-wall-adapter.js +38 -0
  492. package/dist/wall/railing-wall-floorplan.d.ts +8 -0
  493. package/dist/wall/railing-wall-floorplan.d.ts.map +1 -0
  494. package/dist/wall/railing-wall-floorplan.js +27 -0
  495. package/dist/wall/railing-wall-geometry.d.ts +12 -0
  496. package/dist/wall/railing-wall-geometry.d.ts.map +1 -0
  497. package/dist/wall/railing-wall-geometry.js +51 -0
  498. package/dist/wall/railing-wall-guard.d.ts +81 -0
  499. package/dist/wall/railing-wall-guard.d.ts.map +1 -0
  500. package/dist/wall/railing-wall-guard.js +435 -0
  501. package/dist/wall/railing-wall-materials.d.ts +11 -0
  502. package/dist/wall/railing-wall-materials.d.ts.map +1 -0
  503. package/dist/wall/railing-wall-materials.js +31 -0
  504. package/dist/wall/railing-wall-panel-model.d.ts +30 -0
  505. package/dist/wall/railing-wall-panel-model.d.ts.map +1 -0
  506. package/dist/wall/railing-wall-panel-model.js +117 -0
  507. package/dist/wall/railing-wall-panel.d.ts +17 -0
  508. package/dist/wall/railing-wall-panel.d.ts.map +1 -0
  509. package/dist/wall/railing-wall-panel.js +42 -0
  510. package/dist/wall/rectangle-command.d.ts +79 -1
  511. package/dist/wall/rectangle-command.d.ts.map +1 -1
  512. package/dist/wall/rectangle-tool.d.ts.map +1 -1
  513. package/dist/wall/rectangle-tool.js +2 -0
  514. package/dist/wall/renderer.d.ts.map +1 -1
  515. package/dist/wall/renderer.js +3 -1
  516. package/dist/wall/skirting-floor-gaps.d.ts +8 -0
  517. package/dist/wall/skirting-floor-gaps.d.ts.map +1 -0
  518. package/dist/wall/skirting-floor-gaps.js +36 -0
  519. package/dist/wall/system.d.ts +0 -14
  520. package/dist/wall/system.d.ts.map +1 -1
  521. package/dist/wall/system.js +6 -1
  522. package/dist/wall/tool.d.ts +16 -0
  523. package/dist/wall/tool.d.ts.map +1 -1
  524. package/dist/wall/tool.js +160 -47
  525. package/dist/wall/treatments.d.ts +3 -0
  526. package/dist/wall/treatments.d.ts.map +1 -1
  527. package/dist/wall/treatments.js +30 -7
  528. package/dist/window/actions.d.ts +7 -0
  529. package/dist/window/actions.d.ts.map +1 -0
  530. package/dist/window/actions.js +29 -0
  531. package/dist/window/definition.d.ts.map +1 -1
  532. package/dist/window/definition.js +11 -2
  533. package/dist/window/floorplan-move.d.ts.map +1 -1
  534. package/dist/window/floorplan-move.js +5 -0
  535. package/dist/window/floorplan.d.ts +2 -0
  536. package/dist/window/floorplan.d.ts.map +1 -1
  537. package/dist/window/floorplan.js +58 -1
  538. package/dist/window/mechanism.d.ts.map +1 -1
  539. package/dist/window/mechanism.js +21 -1
  540. package/dist/window/move-tool.d.ts.map +1 -1
  541. package/dist/window/move-tool.js +10 -3
  542. package/dist/window/paint.d.ts +2 -7
  543. package/dist/window/paint.d.ts.map +1 -1
  544. package/dist/window/paint.js +31 -3
  545. package/dist/window/panel.d.ts.map +1 -1
  546. package/dist/window/panel.js +311 -69
  547. package/dist/window/placement.d.ts.map +1 -1
  548. package/dist/window/placement.js +5 -1
  549. package/dist/window/swing.d.ts +13 -0
  550. package/dist/window/swing.d.ts.map +1 -0
  551. package/dist/window/swing.js +16 -0
  552. package/dist/window/tool.d.ts.map +1 -1
  553. package/dist/window/tool.js +19 -14
  554. package/dist/zone/floorplan-affordances.d.ts +136 -0
  555. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  556. package/dist/zone/quantities-panel.d.ts.map +1 -1
  557. package/dist/zone/quantities-panel.js +34 -9
  558. package/dist/zone/renderer.d.ts.map +1 -1
  559. package/dist/zone/renderer.js +9 -5
  560. package/package.json +14 -14
  561. package/dist/site/generic-foundation-geometry.d.ts +0 -16
  562. package/dist/site/generic-foundation-geometry.d.ts.map +0 -1
  563. package/dist/site/generic-foundation-geometry.js +0 -75
  564. package/dist/site/generic-foundation.d.ts +0 -4
  565. package/dist/site/generic-foundation.d.ts.map +0 -1
  566. package/dist/site/generic-foundation.js +0 -91
package/dist/wall/tool.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { calculateLevelMiters, collectAlignmentAnchors, DEFAULT_LEVEL_HEIGHT, emitter, GROUND_SUPPORT_ID, getWallMiterBoundaryPoints, resolveAlignment, resolveBuildingForLevel, sceneRegistry, useScene, wallClosesRoom, } from '@pascal-app/core';
3
- import { addWallPolygonDraftCorner, CursorSphere, chainEndJoinsExistingWall, clearPlacementSurface, commitWallPolygonDraft, createWallOnCurrentLevel, DraftMeasurementLabel, discardWallPolygonDraft, EDITOR_LAYER, formatAngleRadians, formatLinearMeasurement, getAngleArcToSegmentReference, getAngleToSegmentReference, getSegmentAngleReferenceAtPoint, getWallDrawVariant, isAlignmentGuideActive, isAngleSnapActive, isMagneticSnapActive, markToolCancelConsumed, publishHorizontalConstructionPlane, publishPlacementSurface, resampleTerrainConstructionPlane, resolveEventConstructionPlane, resolvePointerSupportSurface, snapWallDraftPointDetailed, startWallPolygonDraft, triggerSFX, useAlignmentGuides, useEditor, useFloorplanDraftPreview, useSegmentDraftChain, useWallDrawVariant, useWallSnapIndicator, visibleScene, WALL_CONNECT_SNAP_RADIUS, WALL_JOIN_SNAP_RADIUS, wallPolygonDraftWalls, } from '@pascal-app/editor';
3
+ import { addWallPolygonDraftCorner, CursorSphere, chainEndJoinsExistingWall, clearPlacementSurface, commitWallPolygonDraft, createInvisibleWallOnCurrentLevel, createWallOnCurrentLevel, DraftMeasurementLabel, discardWallPolygonDraft, EDITOR_LAYER, endWallPullRun, formatAngleRadians, formatLinearMeasurement, getAngleArcToSegmentReference, getAngleToSegmentReference, getSegmentAngleReferenceAtPoint, getWallDrawVariant, getWallLineKind, invisibleWallDraftSnapLines, isAlignmentGuideActive, isAngleSnapActive, isMagneticSnapActive, isWallRunFree, markToolCancelConsumed, publishHorizontalConstructionPlane, publishPlacementSurface, publishWallRunFeedback, resampleTerrainConstructionPlane, resolveEventConstructionPlane, resolveLevelConstructionPlane, resolvePointerSupportSurface, snapWallDraftPointDetailed, snapWallRunDraftPoint, startWallPolygonDraft, triggerSFX, useAlignmentGuides, useEditor, useFloorplanDraftPreview, useSegmentDraftChain, useWallDraftThickness, useWallDrawVariant, useWallPullRun, useWallSnapIndicator, visibleScene, WALL_CONNECT_SNAP_RADIUS, WALL_JOIN_SNAP_RADIUS, wallDraftIsRun, wallPolygonDraftWalls, wallRunDirection, } from '@pascal-app/editor';
4
4
  import { getSceneTheme, useViewer } from '@pascal-app/viewer';
5
5
  import { useThree } from '@react-three/fiber';
6
6
  import { useEffect, useRef, useState } from 'react';
@@ -10,14 +10,23 @@ import RectangleWallTool from './rectangle-tool.js';
10
10
  /**
11
11
  * Phase 5 Stage D — wall placement tool (kind-owned).
12
12
  *
13
- * 1:1 port of the legacy `WallTool`. Two-click flow: click 1 sets the
14
- * start, click 2 creates the wall. Between clicks a vertical preview
15
- * rectangle + length/angle measurement HUD follow the pointer. Snapping is
16
- * governed by the global snapping mode (`'off'` is the bypass); Esc cancels.
13
+ * Walls: click 1 sets the start, click 2 creates the wall, and the tool waits
14
+ * for the next start. Polygon: each click adds a corner and the next side
15
+ * chains from it until Esc, a double-click, closing the loop or teeing into
16
+ * another wall. Between clicks a vertical preview rectangle + length/angle
17
+ * measurement HUD follow the pointer. Snapping is governed by the global
18
+ * snapping mode (`'off'` is the bypass): a Walls segment locks to 15° rays from
19
+ * its start; a Polygon side holds square to the one before and the house's
20
+ * axes, with projection guides and a labelled snap marker
21
+ * (`snapWallRunDraftPoint`).
17
22
  *
18
23
  * Not a `DragAction` — same reasoning as fence/slab/ceiling placement:
19
24
  * stateful sequence of grid:click events, not a single drag-up.
20
25
  *
26
+ * A wall end's pull grip (`startWallPull`) arms a run already started at that
27
+ * end: the tool seeds its chain from `useWallPullRun`, its first wall square to
28
+ * the pulled one, and ends the pull when the chain stops.
29
+ *
21
30
  * Mounted via `def.tool` from `wall/definition.ts`.
22
31
  */
23
32
  const DRAFT_WALL_THICKNESS = 0.1;
@@ -290,6 +299,25 @@ function getBelowLevelWalls() {
290
299
  .sort((a, b) => b.level - a.level)[0];
291
300
  return getLevelWalls(belowLevel?.id ?? null, nodes);
292
301
  }
302
+ /**
303
+ * The walls the line tool snaps a drafted point against. `walls` is the active
304
+ * level, which the measurement HUD reports against. `snapWalls` adds an open
305
+ * Polygon room's sides and, as a reference for the corner and edge snaps, the
306
+ * floor below. `bodyWalls` leaves the floor below out: a body capture T-joins
307
+ * the wall it lands in, and a wall on another floor can't be joined, so an end
308
+ * near a lower wall's face stays where the plan (which only knows the active
309
+ * level) puts it. An invisible-wall draft also catches the invisible walls
310
+ * already drawn (`invisibleWallDraftSnapLines`).
311
+ */
312
+ export function getWallDraftSnapWalls() {
313
+ const walls = getCurrentLevelWalls();
314
+ const draftWalls = [...wallPolygonDraftWalls(), ...invisibleWallDraftSnapLines()];
315
+ return {
316
+ walls,
317
+ snapWalls: [...walls, ...getBelowLevelWalls(), ...draftWalls],
318
+ bodyWalls: [...walls, ...draftWalls],
319
+ };
320
+ }
293
321
  const LineWallTool = () => {
294
322
  const unit = useViewer((state) => state.unit);
295
323
  const metricNotation = useViewer((state) => state.metricNotation);
@@ -311,7 +339,7 @@ const LineWallTool = () => {
311
339
  const cameraRef = useRef(camera);
312
340
  cameraRef.current = camera;
313
341
  const previewHeight = typeof wallDefaults?.height === 'number' ? wallDefaults.height : activeLevelHeight;
314
- const previewThickness = typeof wallDefaults?.thickness === 'number' ? wallDefaults.thickness : DRAFT_WALL_THICKNESS;
342
+ const previewThickness = useWallDraftThickness(DRAFT_WALL_THICKNESS);
315
343
  const previewHeightRef = useRef(previewHeight);
316
344
  previewHeightRef.current = previewHeight;
317
345
  const previewThicknessRef = useRef(previewThickness);
@@ -452,11 +480,60 @@ const LineWallTool = () => {
452
480
  useWallSnapIndicator.getState().clear();
453
481
  useSegmentDraftChain.getState().clear('wall');
454
482
  clearPlacementSurface();
483
+ seededPullSeq = null;
484
+ runReference = null;
485
+ // A pulled run ends with its chain: back to Select.
486
+ endWallPullRun();
455
487
  };
456
488
  // In 2D-only view the plan owns wall drafting; this tool stays mounted
457
489
  // behind the hidden canvas and still hears the plan's grid events, so it
458
490
  // must not also draft (it would add every corner twice).
459
491
  const planOwnsInput = () => visibleScene(useEditor.getState()) === '2d';
492
+ // The pull run this chain was seeded from.
493
+ let seededPullSeq = null;
494
+ // Direction of the run's last wall (the pulled one first); null before one.
495
+ let runReference = null;
496
+ // The floor plan forwards its own snapped moves; it shows their feedback.
497
+ const fromCanvas = (event) => event.nativeEvent?.target instanceof HTMLCanvasElement;
498
+ // A started run holds square to its last wall and the house's axes.
499
+ const snapRun = (point, event) => {
500
+ const runStart = chainFirstVertex.current ?? startingPoint.current;
501
+ return snapWallRunDraftPoint({
502
+ point,
503
+ start: [startingPoint.current.x, startingPoint.current.z],
504
+ runStart: [runStart.x, runStart.z],
505
+ reference: runReference,
506
+ walls: getWallDraftSnapWalls().bodyWalls,
507
+ free: isWallRunFree(event.nativeEvent),
508
+ });
509
+ };
510
+ // A wall end's pull grip opens the run at that end: start the chain there,
511
+ // on the pulled wall's own base, as if its end had been clicked.
512
+ const seedPull = (run) => {
513
+ if (!run || run.seq === seededPullSeq || planOwnsInput())
514
+ return;
515
+ const { walls } = getWallDraftSnapWalls();
516
+ const plane = snappedWallConstructionPlane([run.sourceWallId], walls) ?? resolveLevelConstructionPlane();
517
+ if (!plane)
518
+ return;
519
+ seededPullSeq = run.seq;
520
+ runReference = run.reference;
521
+ constructionPlane.current = plane;
522
+ flatConstructionBase.current = false;
523
+ chainWallIds.current = [];
524
+ startingPoint.current.set(run.start[0], plane.localY, run.start[1]);
525
+ chainFirstVertex.current = startingPoint.current.clone();
526
+ endingPoint.current.copy(startingPoint.current);
527
+ buildingState.current = 1;
528
+ const draftPreview = useFloorplanDraftPreview.getState();
529
+ draftPreview.setWallDraftStart(run.start);
530
+ draftPreview.setWallDraftEnd(run.start);
531
+ cursorRef.current?.position.copy(startingPoint.current);
532
+ if (wallPreviewRef.current)
533
+ wallPreviewRef.current.visible = false;
534
+ setDraftMeasurement(null);
535
+ setAxisGuide({ origin: run.start, endOrigin: null, y: plane.localY, angleLabel: null });
536
+ };
460
537
  const onGridMove = (event) => {
461
538
  if (!(cursorRef.current && wallPreviewRef.current) || planOwnsInput())
462
539
  return;
@@ -472,32 +549,48 @@ const LineWallTool = () => {
472
549
  else if (pointed) {
473
550
  publishPlacementSurface(surfacePointScratch.set(event.position[0], pointed.worldY, event.position[2]), SURFACE_UP);
474
551
  }
475
- const walls = getCurrentLevelWalls();
476
- // Add walls on the floor below as extra snap references so the new wall
477
- // can align with the level beneath it. Kept separate from `walls` so the
478
- // measurement HUD only reports against the active level.
479
- const snapWalls = [...walls, ...getBelowLevelWalls(), ...wallPolygonDraftWalls()];
552
+ // Walls on the floor below are extra snap references so the new wall can
553
+ // align with the level beneath it; the measurement HUD reports against
554
+ // the active level's `walls` only.
555
+ const { walls, snapWalls, bodyWalls } = getWallDraftSnapWalls();
480
556
  const localPoint = pointed?.localPoint
481
557
  ? [pointed.localPoint[0], pointed.localPoint[2]]
482
558
  : [event.localPosition[0], event.localPosition[2]];
483
559
  // Snapping is governed entirely by the snapping mode (grid / lines /
484
560
  // angles / off). `'off'` is the bypass — there is no Shift hold-to-bypass.
485
- const angleLocked = buildingState.current === 1 && isAngleSnapActive();
486
- const snapResult = snapWallDraftPointDetailed({
487
- point: localPoint,
488
- walls: snapWalls,
489
- start: angleLocked ? [startingPoint.current.x, startingPoint.current.z] : undefined,
490
- angleSnap: angleLocked,
491
- magnetic: isMagneticSnapActive(),
492
- });
493
- gridPosition = alignPoint(snapResult.point, { applySnap: !angleLocked });
494
- // Stand the magnetic beacon at the endpoint when it locked onto an
495
- // existing wall corner / wall point; clear it for plain grid/angle moves.
496
- useWallSnapIndicator
497
- .getState()
498
- .set(snapResult.snap
499
- ? { x: gridPosition[0], z: gridPosition[1], kind: snapResult.snap }
500
- : null);
561
+ // Everything here is building-local: the lattice, the 15° rays and the
562
+ // alignment axes all turn with a building the site planner turned.
563
+ if (buildingState.current === 1 && wallDraftIsRun()) {
564
+ // A started run holds square and shows its guides and snap marker.
565
+ const runSnap = snapRun(localPoint, event);
566
+ gridPosition = runSnap.point;
567
+ if (fromCanvas(event))
568
+ publishWallRunFeedback(runSnap);
569
+ }
570
+ else {
571
+ // A Walls segment locks to 15° rays from its start.
572
+ const angleLocked = buildingState.current === 1 && isAngleSnapActive();
573
+ const snapResult = snapWallDraftPointDetailed({
574
+ point: localPoint,
575
+ walls: snapWalls,
576
+ start: angleLocked ? [startingPoint.current.x, startingPoint.current.z] : undefined,
577
+ angleSnap: angleLocked,
578
+ magnetic: isMagneticSnapActive(),
579
+ captureWallBodies: true,
580
+ bodyWalls,
581
+ });
582
+ // A point locked onto a wall stays on it: alignment only shows its guides.
583
+ gridPosition = alignPoint(snapResult.point, {
584
+ applySnap: !angleLocked && snapResult.snap === null,
585
+ });
586
+ // Stand the magnetic beacon at the endpoint when it locked onto an
587
+ // existing wall corner / wall point; clear it for plain grid/angle moves.
588
+ useWallSnapIndicator
589
+ .getState()
590
+ .set(snapResult.snap
591
+ ? { x: gridPosition[0], z: gridPosition[1], kind: snapResult.snap }
592
+ : null);
593
+ }
501
594
  if (buildingState.current === 1) {
502
595
  const snappedLocal = gridPosition;
503
596
  const draftY = constructionPlane.current?.localY ?? event.localPosition[1];
@@ -537,8 +630,7 @@ const LineWallTool = () => {
537
630
  stopDrafting();
538
631
  return;
539
632
  }
540
- const walls = getCurrentLevelWalls();
541
- const snapWalls = [...walls, ...getBelowLevelWalls(), ...wallPolygonDraftWalls()];
633
+ const { walls, snapWalls, bodyWalls } = getWallDraftSnapWalls();
542
634
  const pointed = buildingState.current === 0 ? pointedSurfaceFor(event) : null;
543
635
  const localClick = pointed?.localPoint
544
636
  ? [pointed.localPoint[0], pointed.localPoint[2]]
@@ -548,8 +640,12 @@ const LineWallTool = () => {
548
640
  point: localClick,
549
641
  walls: snapWalls,
550
642
  magnetic: isMagneticSnapActive(),
643
+ captureWallBodies: true,
644
+ bodyWalls,
645
+ });
646
+ const snappedStart = alignPoint(snapResult.point, {
647
+ applySnap: snapResult.snap === null,
551
648
  });
552
- const snappedStart = alignPoint(snapResult.point);
553
649
  const resolvedPlane = (pointed?.sourceNodeId
554
650
  ? resolveEventConstructionPlane(event, pointed)
555
651
  : pointMatches(snappedStart, snapResult.point)
@@ -562,6 +658,7 @@ const LineWallTool = () => {
562
658
  gridPosition = snappedStart;
563
659
  startingPoint.current.set(snappedStart[0], plane.localY, snappedStart[1]);
564
660
  chainFirstVertex.current = startingPoint.current.clone();
661
+ runReference = null;
565
662
  endingPoint.current.copy(startingPoint.current);
566
663
  buildingState.current = 1;
567
664
  const draftPreview = useFloorplanDraftPreview.getState();
@@ -593,13 +690,17 @@ const LineWallTool = () => {
593
690
  }
594
691
  else if (buildingState.current === 1) {
595
692
  const angleLocked = isAngleSnapActive();
596
- const snappedEnd = alignPoint(snapWallDraftPointDetailed({
597
- point: localClick,
598
- walls: snapWalls,
599
- start: angleLocked ? [startingPoint.current.x, startingPoint.current.z] : undefined,
600
- angleSnap: angleLocked,
601
- magnetic: isMagneticSnapActive(),
602
- }).point, { applySnap: !angleLocked });
693
+ const snappedEnd = wallDraftIsRun()
694
+ ? snapRun(localClick, event).point
695
+ : alignPoint(snapWallDraftPointDetailed({
696
+ point: localClick,
697
+ walls: snapWalls,
698
+ start: angleLocked ? [startingPoint.current.x, startingPoint.current.z] : undefined,
699
+ angleSnap: angleLocked,
700
+ magnetic: isMagneticSnapActive(),
701
+ captureWallBodies: true,
702
+ bodyWalls,
703
+ }).point, { applySnap: !angleLocked });
603
704
  const dx = snappedEnd[0] - startingPoint.current.x;
604
705
  const dz = snappedEnd[1] - startingPoint.current.z;
605
706
  if (dx * dx + dz * dz < 0.01 * 0.01)
@@ -620,29 +721,38 @@ const LineWallTool = () => {
620
721
  stopDrafting();
621
722
  return;
622
723
  }
724
+ runReference = wallRunDirection([startingPoint.current.x, startingPoint.current.z], snappedEnd);
623
725
  nextStart = snappedEnd;
624
726
  }
625
727
  else {
626
728
  const draftPlane = constructionPlane.current;
627
729
  const commitPointed = draftPlane?.supportSlabId === GROUND_SUPPORT_ID ? null : pointedSurfaceFor(event);
628
730
  // Both start and end are building-local ✓
629
- const createdWall = createWallOnCurrentLevel([startingPoint.current.x, startingPoint.current.z], snappedEnd, {
630
- supportCap: commitPointed ? commitPointed.elevation : (draftPlane?.elevation ?? null),
631
- preferredSupportSlabId: draftPlane?.supportSlabId ?? null,
632
- constructionElevation: draftPlane?.elevation ?? null,
633
- constructionHeight: previewHeightRef.current,
634
- constructionSourceNodeId: constructionPlane.current?.sourceNodeId ?? null,
635
- flatConstructionBase: flatConstructionBase.current,
636
- });
731
+ // The Walls variant's Invisible draws room separators, not walls.
732
+ const createdWall = getWallLineKind() === 'invisible'
733
+ ? createInvisibleWallOnCurrentLevel([startingPoint.current.x, startingPoint.current.z], snappedEnd)
734
+ : createWallOnCurrentLevel([startingPoint.current.x, startingPoint.current.z], snappedEnd, {
735
+ supportCap: commitPointed
736
+ ? commitPointed.elevation
737
+ : (draftPlane?.elevation ?? null),
738
+ preferredSupportSlabId: draftPlane?.supportSlabId ?? null,
739
+ constructionElevation: draftPlane?.elevation ?? null,
740
+ constructionHeight: previewHeightRef.current,
741
+ constructionSourceNodeId: constructionPlane.current?.sourceNodeId ?? null,
742
+ flatConstructionBase: flatConstructionBase.current,
743
+ });
637
744
  if (!createdWall)
638
745
  return;
639
746
  chainWallIds.current.push(createdWall.id);
747
+ // The run's next wall holds square to this one.
748
+ runReference = wallRunDirection(createdWall.start, createdWall.end);
640
749
  // The new segment is now a real node — make it an alignment target
641
750
  // for the next segment, and drop the just-shown guide.
642
751
  refreshAlignmentCandidates();
643
752
  useAlignmentGuides.getState().clear();
644
753
  useWallSnapIndicator.getState().clear();
645
- if (useEditor.getState().getContinuation('wall') === 'single') {
754
+ // Walls draws one wall per two clicks.
755
+ if (!wallDraftIsRun()) {
646
756
  stopDrafting();
647
757
  return;
648
758
  }
@@ -659,7 +769,7 @@ const LineWallTool = () => {
659
769
  const levelWalls = getCurrentLevelWalls();
660
770
  if (closedToChainStart ||
661
771
  chainEndJoinsExistingWall(createdWall.end, levelWalls, chainWallIds.current) ||
662
- wallClosesRoom(levelWalls, createdWall)) {
772
+ (createdWall.type === 'wall' && wallClosesRoom(levelWalls, createdWall))) {
663
773
  stopDrafting();
664
774
  return;
665
775
  }
@@ -702,9 +812,12 @@ const LineWallTool = () => {
702
812
  emitter.on('grid:move', onGridMove);
703
813
  emitter.on('grid:click', onGridClick);
704
814
  emitter.on('tool:cancel', onCancel);
815
+ const stopPullSeeding = useWallPullRun.subscribe((state) => seedPull(state.run));
816
+ seedPull(useWallPullRun.getState().run);
705
817
  return () => {
706
818
  // Leaving the tool mid-polygon abandons it (nothing was written).
707
819
  discardWallPolygonDraft();
820
+ stopPullSeeding();
708
821
  emitter.off('grid:move', onGridMove);
709
822
  emitter.off('grid:click', onGridClick);
710
823
  emitter.off('tool:cancel', onCancel);
@@ -7,6 +7,9 @@ type OpeningLike = {
7
7
  width?: number;
8
8
  height?: number;
9
9
  position?: [number, number, number];
10
+ casingFaceA?: boolean;
11
+ casingFaceB?: boolean;
12
+ casingWidth?: number;
10
13
  };
11
14
  type TrimKind = WallTrimKind;
12
15
  type WallSide = WallFace;
@@ -1 +1 @@
1
- {"version":3,"file":"treatments.d.ts","sourceRoot":"","sources":["../../src/wall/treatments.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,eAAe,EAOpB,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,YAAY,EAEjB,KAAK,cAAc,EAIpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAA8B,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAMhG,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CACpC,CAAA;AAED,KAAK,QAAQ,GAAG,YAAY,CAAA;AAC5B,KAAK,QAAQ,GAAG,QAAQ,CAAA;AACxB,KAAK,cAAc,GAAG,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;AAE5D,KAAK,mBAAmB,GAAG,cAAc,CAAA;AAoMzC,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAMzD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAoBlE;AAwND,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,QAAQ,EACd,aAAa,EAAE,WAAW,EAAE,EAC5B,SAAS,EAAE,sBAAsB,2FA2GlC;AAkBD,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,EACtB,cAAc,EAAE,cAAc;;;;;;;EAU/B;AAED,eAAO,MAAM,cAAc,uFAKxB;IACD,IAAI,EAAE,QAAQ,CAAA;IACd,aAAa,EAAE,WAAW,EAAE,CAAA;IAC5B,SAAS,EAAE,sBAAsB,CAAA;IACjC,SAAS,EAAE,MAAM,CAAC,mBAAmB,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;CACvD,iCA+DC,CAAA"}
1
+ {"version":3,"file":"treatments.d.ts","sourceRoot":"","sources":["../../src/wall/treatments.tsx"],"names":[],"mappings":"AAEA,OAAO,EAUL,KAAK,aAAa,EAClB,KAAK,eAAe,EAOpB,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,YAAY,EAEjB,KAAK,cAAc,EAKpB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,EAA8B,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAMhG,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,KAAK,QAAQ,GAAG,YAAY,CAAA;AAC5B,KAAK,QAAQ,GAAG,QAAQ,CAAA;AACxB,KAAK,cAAc,GAAG,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;AAE5D,KAAK,mBAAmB,GAAG,cAAc,CAAA;AAoMzC,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAMzD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAoBlE;AA2OD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,QAAQ,EACd,aAAa,EAAE,WAAW,EAAE,EAC5B,SAAS,EAAE,sBAAsB,2FAgHlC;AAkBD,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,EACtB,cAAc,EAAE,cAAc;;;;;;;EAU/B;AAED,eAAO,MAAM,cAAc,uFAKxB;IACD,IAAI,EAAE,QAAQ,CAAA;IACd,aAAa,EAAE,WAAW,EAAE,CAAA;IAC5B,SAAS,EAAE,sBAAsB,CAAA;IACjC,SAAS,EAAE,MAAM,CAAC,mBAAmB,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;CACvD,iCA+DC,CAAA"}
@@ -1,11 +1,12 @@
1
1
  'use client';
2
2
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
- import { getWallCurveFrameAt, getWallLocalFaceZ, getWallMiterBoundaryPoints, getWallTrimFaces, getWallTrimSlotId, isCurvedWall, spatialGridManager, useScene, WALL_CHAIR_RAIL_DEFAULT, WALL_CROWN_DEFAULT, WALL_SKIRTING_DEFAULT, WALL_SURFACE_SLOT_DEFAULTS, wallDoorStepRuns, wallFaceBaseOffset, wallFaceScriptSkirtingGap, } from '@pascal-app/core';
3
+ import { getWallCurveFrameAt, getWallLocalFaceZ, getWallMiterBoundaryPoints, getWallTrimFaces, getWallTrimSlotId, isCurvedWall, openingCasingBoards, resolveOpeningCasingHost, spatialGridManager, useScene, WALL_CHAIR_RAIL_DEFAULT, WALL_CROWN_DEFAULT, WALL_SKIRTING_DEFAULT, WALL_SURFACE_SLOT_DEFAULTS, wallDoorStepRuns, wallFaceBaseOffset, wallFaceScriptSkirtingGap, } from '@pascal-app/core';
4
4
  import { baseMaterial, createMaterialFromPresetRef, resolveMaterialRef, } from '@pascal-app/viewer';
5
5
  import { memo, useEffect, useMemo } from 'react';
6
6
  import * as THREE from 'three';
7
7
  import { mergeGeometries as mergeBufferGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
8
8
  import { resolveWallOpeningCeiling } from '../shared/wall-opening-ceiling.js';
9
+ import { skirtingFloorOpeningRanges } from './skirting-floor-gaps.js';
9
10
  import { treatmentMiterDataForProud } from './treatment-level-data.js';
10
11
  const CURVE_SEGMENTS = 24;
11
12
  const MIN_SLICE_PROUD = 0.0005;
@@ -340,8 +341,17 @@ function subtractOpeningRanges(ranges, openings) {
340
341
  }
341
342
  return next;
342
343
  }
343
- function trimOpeningRanges(node, childrenNodes, yBottom, height) {
344
+ /**
345
+ * Where a trim on `face`, from `yBottom` to `height` above it, breaks for the wall's doors and
346
+ * windows: across each opening it reaches, and across each casing board on that face it reaches
347
+ * (the legs beside the cutout, the head over it, a window's bottom board under it), so a skirting
348
+ * or chair rail stops against the casing instead of running through it. A face the opening is not
349
+ * cased on breaks at the cutout only.
350
+ */
351
+ function trimOpeningRanges(node, face, childrenNodes, yBottom, height) {
344
352
  const yTop = yBottom + height;
353
+ const reaches = (bottom, top) => top > yBottom + EPS && bottom < yTop - EPS;
354
+ const nodes = useScene.getState().nodes;
345
355
  return childrenNodes
346
356
  .filter((child) => child.type === 'door' || child.type === 'window')
347
357
  .flatMap((child) => {
@@ -349,10 +359,19 @@ function trimOpeningRanges(node, childrenNodes, yBottom, height) {
349
359
  const childHeight = child.height ?? 0;
350
360
  const position = child.position ?? [0, 0, 0];
351
361
  const childBottom = position[1] - childHeight / 2;
352
- const childTop = childBottom + childHeight;
353
- if (childTop <= yBottom + EPS || childBottom >= yTop - EPS)
354
- return [];
355
- return [[position[0] - width / 2, position[0] + width / 2]];
362
+ const ranges = [];
363
+ if (reaches(childBottom, childBottom + childHeight))
364
+ ranges.push([position[0] - width / 2, position[0] + width / 2]);
365
+ const opening = { ...child, position };
366
+ const host = resolveOpeningCasingHost(opening, nodes, node);
367
+ if (!host)
368
+ return ranges;
369
+ for (const board of openingCasingBoards(opening, host)) {
370
+ const [x, y] = [position[0] + board.center[0], position[1] + board.center[1]];
371
+ if (board.face === face && reaches(y - board.size[1] / 2, y + board.size[1] / 2))
372
+ ranges.push([x - board.size[0] / 2, x + board.size[0] / 2]);
373
+ }
374
+ return ranges;
356
375
  });
357
376
  }
358
377
  function buildPlanPolygon(outer, inner) {
@@ -456,9 +475,13 @@ export function buildTrimGeometry(node, side, trim, kind, childrenNodes, levelDa
456
475
  };
457
476
  const face = resolveTreatmentSideSign(node, side) > 0 ? 'a' : 'b';
458
477
  const faceScript = kind === 'skirting' ? node.finishScripts?.[face] : undefined;
478
+ const floorGaps = kind === 'skirting' ? skirtingFloorOpeningRanges(node, face, useScene.getState().nodes) : [];
459
479
  const runs = bases.flatMap((base) => {
460
480
  const bottom = support ? base.elevation - support.elevation : yBottom;
461
- const openingRanges = trimOpeningRanges(node, childrenNodes, bottom, height);
481
+ const openingRanges = [
482
+ ...trimOpeningRanges(node, face, childrenNodes, bottom, height),
483
+ ...floorGaps,
484
+ ];
462
485
  if (support)
463
486
  for (const child of childrenNodes) {
464
487
  for (const run of wallDoorStepRuns(node, child, support.faceDatum, support.elevation))
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The window's action-menu contribution, in 2D and 3D, mirroring the door's: swap a casement's
3
+ * hinge side without opening the panel. One undo step; a closed window opens so the new side
4
+ * shows.
5
+ */
6
+ export default function WindowActions(): import("react").JSX.Element | null;
7
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/window/actions.tsx"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,uCAoBpC"}
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { usePascalI18n, useScene } from '@pascal-app/core';
4
+ import { ActionMenuButton } from '@pascal-app/editor';
5
+ import { useViewer } from '@pascal-app/viewer';
6
+ import { ArrowLeftRight } from 'lucide-react';
7
+ import { applyOpeningSwap } from '../shared/opening-swap.js';
8
+ import { windowMechanism } from './mechanism.js';
9
+ import { canSwapWindowHinge, swapWindowHingePatch } from './swing.js';
10
+ /**
11
+ * The window's action-menu contribution, in 2D and 3D, mirroring the door's: swap a casement's
12
+ * hinge side without opening the panel. One undo step; a closed window opens so the new side
13
+ * shows.
14
+ */
15
+ export default function WindowActions() {
16
+ const i18n = usePascalI18n();
17
+ const selected = useViewer((s) => s.selection.selectedIds);
18
+ const windowNode = useScene((s) => {
19
+ const node = selected.length === 1 ? s.nodes[selected[0]] : undefined;
20
+ return node?.type === 'window' ? node : undefined;
21
+ });
22
+ const readOnly = useScene((s) => s.readOnly);
23
+ if (!windowNode || readOnly || !canSwapWindowHinge(windowNode))
24
+ return null;
25
+ return (_jsx(ActionMenuButton, { label: i18n._({ id: 'node.window.actions.swapHingeSide', message: 'Swap hinge side' }), onClick: (event) => {
26
+ event.stopPropagation();
27
+ applyOpeningSwap(windowNode, swapWindowHingePatch(windowNode), windowMechanism);
28
+ }, children: _jsx(ArrowLeftRight, { className: "h-4 w-4" }) }));
29
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/window/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EAGT,cAAc,EAEd,QAAQ,EAER,UAAU,IAAI,cAAc,EAC7B,MAAM,kBAAkB,CAAA;AAkCzB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAOrC,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GAC3B,SAAS,GAAG,IAAI,CAWlB;AAwMD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,OAAO,UAAU,CAgH9D,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/window/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EAGT,cAAc,EAEd,QAAQ,EAER,UAAU,IAAI,cAAc,EAC7B,MAAM,kBAAkB,CAAA;AAmCzB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAOrC,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GAC3B,SAAS,GAAG,IAAI,CAWlB;AAwMD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,OAAO,UAAU,CAwH9D,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { getDormerWallHorizontalBoundsAtHeight, getDormerWallOpeningVerticalBounds, windowSlots, } from '@pascal-app/core';
2
+ import { NEW_WINDOW_FRAME_THICKNESS } from '@pascal-app/core/building';
2
3
  import { curtainOpeningResizeMax } from '../shared/curtain-opening-limits.js';
3
4
  import { windowBatchable } from '../shared/node-batch/batchable.js';
4
5
  import { buildWindowFloorplanSchedule, computeWindowFloorplanLevelData, } from '../shared/opening-documentation.js';
@@ -228,19 +229,27 @@ export const windowDefinition = {
228
229
  kind: 'window',
229
230
  snapProfile: 'item',
230
231
  facingIndicator: true,
231
- schemaVersion: 3,
232
+ schemaVersion: 4,
232
233
  schema: WindowNode,
233
234
  category: 'structure',
234
235
  extensions: {
235
236
  'pascal:editor/floorplan': {
236
237
  contextualDimensions: buildWindowContextualDimensions,
237
238
  schedule: buildWindowFloorplanSchedule,
239
+ // Swap a casement's hinge side from the action bar, in 2D and 3D.
240
+ actionMenu: { actions: () => import('./actions.js') },
238
241
  },
239
242
  },
240
243
  // Same schema-driven defaults trick as door: parse a stub, strip
241
244
  // id/type. Window also has many fields with zod `.default()` set.
242
245
  defaults: () => {
243
- const stub = WindowNode.parse({ id: 'window_default', type: 'window' });
246
+ const stub = WindowNode.parse({
247
+ id: 'window_default',
248
+ type: 'window',
249
+ frameThickness: NEW_WINDOW_FRAME_THICKNESS,
250
+ casingFaceA: true,
251
+ casingFaceB: true,
252
+ });
244
253
  const { id: _id, type: _type, ...rest } = stub;
245
254
  return rest;
246
255
  },
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan-move.d.ts","sourceRoot":"","sources":["../../src/window/floorplan-move.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,mBAAmB,EAQxB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAA;AAsBzB;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,yBAAyB,EAAE,mBAAmB,CAAC,UAAU,CAkRrE,CAAA"}
1
+ {"version":3,"file":"floorplan-move.d.ts","sourceRoot":"","sources":["../../src/window/floorplan-move.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,mBAAmB,EAQxB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAA;AAuBzB;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,yBAAyB,EAAE,mBAAmB,CAAC,UAAU,CAwRrE,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { evaluateCorner, runAsSingleSceneHistoryStep, useLiveNodeOverrides, useLiveTransforms, useScene, WallNode as WallNodeSchema, } from '@pascal-app/core';
2
2
  import { isGridSnapActive, isMagneticSnapActive, snapToHalf, triggerSFX, useEditor, usePlacementPreview, } from '@pascal-app/editor';
3
3
  import { createFloorplanCursorResolver } from '../shared/floorplan-cursor.js';
4
+ import { movedOpeningCasingFaces } from '../shared/opening-casing-move.js';
4
5
  import { openingPlaneOffsetOnWall } from '../shared/opening-plane-offset.js';
5
6
  import { getOpeningHostLevelId, getRoofHostedOpeningPlanPoint } from '../shared/roof-opening-host.js';
6
7
  import { findClosestWallInPlan, projectWallLocalPointToPlan, resolveOpeningPlacement, snapLocalXToNeighbors, } from '../shared/wall-attach-target.js';
@@ -196,6 +197,8 @@ export const windowFloorplanMoveTarget = ({ node }) => {
196
197
  : 'front'
197
198
  : hit.side;
198
199
  const itemRotation = hit.itemRotation + (flipped ? Math.PI : 0);
200
+ // Another wall may be drawn the other way round: the casing keeps to its side.
201
+ const casing = movedOpeningCasingFaces(node, hit.wall.id, [0, itemRotation, 0], nodes);
199
202
  lastValid = {
200
203
  // Same-wall moves keep the wall-local plane offset; another host resets it.
201
204
  position: [clampedX, clampedY, openingPlaneOffsetOnWall(node, hit.wall.id)],
@@ -208,6 +211,7 @@ export const windowFloorplanMoveTarget = ({ node }) => {
208
211
  roofSegmentId: undefined,
209
212
  roofFace: undefined,
210
213
  visible: true,
214
+ ...casing,
211
215
  };
212
216
  setLiveOverride(`wall:${hit.wall.id}:${side}`, {
213
217
  parentId: hit.wall.id,
@@ -216,6 +220,7 @@ export const windowFloorplanMoveTarget = ({ node }) => {
216
220
  roofSegmentId: undefined,
217
221
  roofFace: undefined,
218
222
  visible: true,
223
+ ...casing,
219
224
  });
220
225
  useLiveTransforms.getState().set(nodeId, {
221
226
  position: lastValid.position,
@@ -8,6 +8,8 @@ import type { FloorplanGeometry, GeometryContext, WindowNode } from '@pascal-app
8
8
  * 2. Inset inner outline — the "glass pane" frame inside the cutout.
9
9
  * 3. Center mullion line down the middle of the opening, along the
10
10
  * wall direction — the legacy's standard glass divider.
11
+ * 4. Casing legs standing proud of each cased wall face beside the
12
+ * cutout (`buildOpeningCasingPlan`).
11
13
  *
12
14
  * Skipped vs the full legacy for now: arched / rounded opening shape
13
15
  * variants, multi-pane mullion grids.
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/window/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EAEjB,eAAe,EAEf,UAAU,EACX,MAAM,kBAAkB,CAAA;AAyEzB;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CA+N1B"}
1
+ {"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/window/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EAEjB,eAAe,EAEf,UAAU,EACX,MAAM,kBAAkB,CAAA;AAgFzB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CA6R1B"}