@pascal-app/nodes 1.0.6 → 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/roof/tool.js CHANGED
@@ -1,17 +1,22 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { collectAlignmentAnchors, emitter, getActiveRoofHeight, getWallArcData, getWallBaseElevationForNodes, getWallEffectiveHeightForNodes, isCurvedWall, RoofNode, RoofSegmentNode, RoofType as RoofTypeSchema, resolveBuildingForLevel, resolveLevelId, resolveRoomRoofFootprint, sceneRegistry, wallSegmentAnchors, } from '@pascal-app/core';
3
- import { CursorSphere, clearSurfacePlanSnapFeedback, EDITOR_LAYER, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, resolveSurfacePlanPointSnap, snapWorldXZForActiveBuilding, triggerSFX, useEditor, useFloorplanDraftPreview, useInteractionScope, useRegistryToolContext, } from '@pascal-app/editor';
2
+ import { collectAlignmentAnchors, emitter, getActiveRoofHeight, getWallArcData, getWallBaseElevationForNodes, getWallEffectiveHeightForNodes, getWallThickness, isCurvedWall, RoofNode, RoofSegmentNode, RoofType as RoofTypeSchema, resolveBuildingForLevel, resolveLevelId, wallSegmentAnchors, } from '@pascal-app/core';
3
+ import { CursorSphere, clearSurfacePlanSnapFeedback, EDITOR_LAYER, isGridSnapActive, isMagneticSnapActive, markToolCancelConsumed, resolveSurfacePlanPointSnap, snapWorldXZForActiveBuilding, triggerSFX, useEditor, useFloorplanDraftPreview, useInteractionScope, useRegistryToolContext, visibleScene, } from '@pascal-app/editor';
4
4
  import { generateRoofSegmentGeometry, useViewer } from '@pascal-app/viewer';
5
5
  import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
6
6
  import * as THREE from 'three';
7
7
  import { BufferGeometry, DoubleSide, Float32BufferAttribute, Vector3, } from 'three';
8
8
  import { createConicalRoofSectorAboveWall } from './conical-roof.js';
9
9
  import { resolveConicalRoofPlacement } from './conical-roof-placement.js';
10
- import { isStandardRoofWallEligible, parseRoofFootprintSource, resolveRoofFootprintElevation, resolveRoofFootprintWorldElevation, resolveRoofWallTopWorldElevation, subscribeToConicalRoofWallClicks, } from './roof-footprint.js';
10
+ import { isStandardRoofWallEligible, parseRoofFootprintSource, pickRoofRoom, resolveRoofFootprintElevation, resolveRoofFootprintWorldElevation, resolveRoofWallTopWorldElevation, roofEdgeAnchors, roofFootprintPreviewIds, roofSnapEdges, subscribeToConicalRoofWallClicks, } from './roof-footprint.js';
11
11
  import useRoofFootprintSource from './roof-footprint-source.js';
12
12
  import { drawnRoofLevelTarget, drawnRoofSupport, roofLevelTarget, roofLevelTargetOffset, seatedRoofElevation, writeRoofNodes, writeSeatedRoofEdit, } from './roof-level-target.js';
13
13
  import useRoofPlacementMode, {} from './roof-placement-mode.js';
14
- const DEFAULT_WALL_HEIGHT = 0.5;
14
+ import useRoofRidgeMode, { ridgeQuarterTurn } from './roof-ridge-mode.js';
15
+ import { bearingWallThickness, roofCatchWalls, segmentWallLine, settleSegmentOnEdges, } from './wall-catch.js';
16
+ // Rafters bear on the top plate, as standard trusses do; a raised heel is the segment's Wall Height.
17
+ const DEFAULT_HEEL_HEIGHT = 0;
18
+ // A cone's curb: it stands on the ground or on another roof, not on a plate.
19
+ const DEFAULT_CONICAL_CURB_HEIGHT = 0.5;
15
20
  const DEFAULT_PITCH_DEG = 40;
16
21
  const GRID_OFFSET = 0.02;
17
22
  function placementOptions(mode) {
@@ -20,11 +25,21 @@ function placementOptions(mode) {
20
25
  requireRoofSupport: mode === 'roof',
21
26
  };
22
27
  }
23
- function resolveRoofDraftPlacement(footprintWidth, footprintDepth, quarterTurn, parentRotation = 0, roofType = 'gable') {
28
+ /**
29
+ * A placed segment's quarter turn: given outright, or from a ridge mode, which
30
+ * runs the ridge along the footprint's long side ('long') or across it.
31
+ */
32
+ function resolveQuarterTurn(ridge, footprintWidth, footprintDepth) {
33
+ return typeof ridge === 'boolean'
34
+ ? ridge
35
+ : ridgeQuarterTurn(footprintWidth, footprintDepth, ridge);
36
+ }
37
+ function resolveRoofDraftPlacement(footprintWidth, footprintDepth, ridge, parentRotation = 0, roofType = 'gable') {
24
38
  if (roofType === 'conical') {
25
39
  const diameter = Math.max(footprintWidth, footprintDepth);
26
40
  return { width: diameter, depth: diameter, rotation: -parentRotation };
27
41
  }
42
+ const quarterTurn = resolveQuarterTurn(ridge, footprintWidth, footprintDepth);
28
43
  return {
29
44
  width: quarterTurn ? footprintDepth : footprintWidth,
30
45
  depth: quarterTurn ? footprintWidth : footprintDepth,
@@ -42,47 +57,62 @@ function getLevelWalls(levelId, nodes) {
42
57
  .map((childId) => nodes[childId])
43
58
  .filter((node) => node?.type === 'wall');
44
59
  }
45
- // Walls on the level directly beneath the active one. Levels share the same
46
- // local XZ origin (they only differ in world Y), so these walls live in the
47
- // identical coordinate frame and feed straight into both the alignment pool
48
- // and the magnetic wall-snap pipeline — letting a roof drawn on the upper
49
- // floor snap onto the wall corners of the floor below.
50
- function getBelowLevelWalls(currentLevelId, nodes) {
60
+ // The level directly beneath the active one. Levels share the same local XZ
61
+ // origin (they only differ in world Y), so its walls live in the identical
62
+ // coordinate frame and feed straight into both the alignment pool and the
63
+ // magnetic wall-snap pipeline — letting a roof drawn on the upper floor snap
64
+ // onto the wall corners of the floor below.
65
+ function getBelowLevel(currentLevelId, nodes) {
51
66
  if (!currentLevelId)
52
- return [];
67
+ return undefined;
53
68
  const currentLevel = nodes[currentLevelId];
54
69
  if (currentLevel?.type !== 'level')
55
- return [];
70
+ return undefined;
56
71
  const buildingId = resolveBuildingForLevel(currentLevel.id, nodes);
57
72
  if (!buildingId)
58
- return [];
73
+ return undefined;
59
74
  const building = nodes[buildingId];
60
75
  if (building?.type !== 'building')
61
- return [];
76
+ return undefined;
62
77
  const currentIndex = currentLevel.level;
63
- const belowLevel = (building.children ?? [])
78
+ return (building.children ?? [])
64
79
  .map((childId) => nodes[childId])
65
80
  .filter((node) => node?.type === 'level' && node.level < currentIndex)
66
81
  .sort((a, b) => b.level - a.level)[0];
67
- return getLevelWalls(belowLevel?.id ?? null, nodes);
82
+ }
83
+ // Walls on the level directly beneath the active one.
84
+ function getBelowLevelWalls(currentLevelId, nodes) {
85
+ return getLevelWalls(getBelowLevel(currentLevelId, nodes)?.id ?? null, nodes);
86
+ }
87
+ // The active level and the one beneath it, whose rooms' edges a roof draws to.
88
+ function roofEdgeLevelIds(currentLevelId, nodes) {
89
+ const below = getBelowLevel(currentLevelId, nodes);
90
+ return [currentLevelId, below?.id].filter((id) => !!id);
68
91
  }
69
92
  // Current-level + floor-below walls — the magnetic snap targets the roof draft
70
93
  // locks onto (corners, midpoints, crossings, wall bodies), matching the wall
71
- // tool. Same coordinate frame, so no transform is needed.
94
+ // tool. Same coordinate frame, so no transform is needed. A porch, deck or
95
+ // patio is drawn to as the house is: its invisible walls, and its railings at
96
+ // their outside faces in place of their centre lines (`roofSnapEdges`).
72
97
  function getRoofSnapWalls(currentLevelId, nodes, roofType) {
73
98
  const walls = [
74
99
  ...getLevelWalls(currentLevelId, nodes),
75
100
  ...getBelowLevelWalls(currentLevelId, nodes),
76
101
  ];
77
- return roofType === 'conical'
78
- ? walls.filter((wall) => isCurvedWall(wall))
79
- : walls.filter(isStandardRoofWallEligible);
102
+ if (roofType === 'conical')
103
+ return walls.filter((wall) => isCurvedWall(wall));
104
+ const edges = roofSnapEdges(nodes, roofEdgeLevelIds(currentLevelId, nodes));
105
+ return [...walls.filter((wall) => !edges.faced.has(wall.id)), ...edges.references].filter(isStandardRoofWallEligible);
80
106
  }
81
- // Current-level alignment anchors plus the floor-below wall corners.
82
- function collectRoofAlignmentAnchors(nodes, currentLevelId, roofType) {
107
+ // Current-level alignment anchors plus the floor-below wall corners, and both
108
+ // levels' invisible walls and porch, deck and patio corners.
109
+ export function collectRoofAlignmentAnchors(nodes, currentLevelId, roofType) {
83
110
  const anchors = [
84
111
  ...collectAlignmentAnchors(nodes, '', currentLevelId),
85
- ...getBelowLevelWalls(currentLevelId, nodes).flatMap((wall) => wallSegmentAnchors(wall.id, wall.start, wall.end, wall.thickness)),
112
+ ...getBelowLevelWalls(currentLevelId, nodes).flatMap((wall) => wallSegmentAnchors(wall.id, wall.start, wall.end, wall.thickness, wall.justification)),
113
+ ...(roofType === 'conical'
114
+ ? []
115
+ : roofEdgeAnchors(nodes, roofEdgeLevelIds(currentLevelId, nodes))),
86
116
  ];
87
117
  if (roofType === 'conical') {
88
118
  return anchors.filter((anchor) => {
@@ -96,9 +126,51 @@ function collectRoofAlignmentAnchors(nodes, currentLevelId, roofType) {
96
126
  });
97
127
  }
98
128
  /**
99
- * Creates a roof group with one default gable segment
129
+ * A grid event's point as the roof tools draft and commit it, the 3D tool and the plan's alike:
130
+ * through the shared surface snap pipeline, magnetic lock onto wall corners / midpoints / crossings
131
+ * / bodies on the active level and the floor below (raising the green beacon), falling back to
132
+ * alignment guides, then to the building-grid snap. The pipeline reads the active snapping mode
133
+ * (grid / lines / angles / off). `levelId` is intentionally omitted so the explicit floor-below
134
+ * `walls` aren't filtered back out.
135
+ */
136
+ export function resolveRoofDraftPoint(event, levelId, nodes, roofType, candidates) {
137
+ const rawPoint = [event.localPosition[0], event.localPosition[2]];
138
+ const gridFallback = isGridSnapActive()
139
+ ? snapWorldXZForActiveBuilding(event.position[0], event.position[2], useEditor.getState().gridSnapStep).local
140
+ : rawPoint;
141
+ return resolveSurfacePlanPointSnap({
142
+ rawPoint,
143
+ fallbackPoint: gridFallback,
144
+ walls: getRoofSnapWalls(levelId, nodes, roofType),
145
+ candidates,
146
+ movingId: '__roof-draft__',
147
+ highlightWalls: true,
148
+ }).point;
149
+ }
150
+ /**
151
+ * A drawn segment whose gable and heel walls stand flush on the walls it is drawn over, and whose
152
+ * walls' outer faces stand on the rooms' edges it is drawn out to: a porch's invisible walls, a
153
+ * deck's railings at their outside faces (`settleSegmentOnEdges`).
100
154
  */
101
- export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selectedIds, quarterTurn, placementMode) => {
155
+ function onBearingWalls(segment, roof, walls) {
156
+ const thickness = bearingWallThickness(segmentWallLine(roof, segment), walls);
157
+ const bearing = thickness === null ? segment : { ...segment, wallThickness: thickness };
158
+ return { ...bearing, ...settleSegmentOnEdges(roof, bearing, walls) };
159
+ }
160
+ /**
161
+ * A new roof's place, and its one segment centred in it: the segment settled onto a room's edge
162
+ * (`onBearingWalls`) moves off the roof's centre, so the roof moves with it.
163
+ */
164
+ function centredRoof(roof, segment) {
165
+ const [x, z] = segmentWallLine(roof, segment).center;
166
+ return { center: [x, z], segment: { ...segment, position: [0, segment.position[1], 0] } };
167
+ }
168
+ /**
169
+ * Creates a roof group with one default gable segment. `ridge` is a quarter
170
+ * turn outright, or a ridge mode: 'long' runs the ridge along the drawn
171
+ * rectangle's long side, 'short' across it.
172
+ */
173
+ export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selectedIds, ridge, placementMode) => {
102
174
  const nodes = sceneApi.nodes();
103
175
  // A placed roof preset seeds `toolDefaults.roof` with the flattened
104
176
  // subtree params (roofType, pitch, wallHeight, overhang, materials, …)
@@ -114,7 +186,7 @@ export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selecte
114
186
  const footprintDepth = Math.max(Math.abs(corner2[2] - corner1[2]), 1);
115
187
  if (roofType === 'conical') {
116
188
  const diameter = Math.max(footprintWidth, footprintDepth);
117
- const curbHeight = typeof defaults.wallHeight === 'number' ? defaults.wallHeight : DEFAULT_WALL_HEIGHT;
189
+ const curbHeight = typeof defaults.wallHeight === 'number' ? defaults.wallHeight : DEFAULT_CONICAL_CURB_HEIGHT;
118
190
  const cone = RoofSegmentNode.parse({
119
191
  pitch: DEFAULT_PITCH_DEG,
120
192
  ...defaults,
@@ -177,34 +249,24 @@ export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selecte
177
249
  }
178
250
  if (targetRoofId) {
179
251
  const targetRoof = nodes[targetRoofId];
180
- let localX = centerX;
181
- let localZ = centerZ;
182
- // Convert world coordinates to the local space of the parent roof
183
- const targetObj = sceneRegistry.nodes.get(targetRoofId);
184
- if (targetObj) {
185
- const worldVec = new THREE.Vector3(centerX, 0, centerZ);
186
- targetObj.worldToLocal(worldVec);
187
- localX = worldVec.x;
188
- localZ = worldVec.z;
189
- }
190
- else {
191
- // Math fallback if mesh isn't ready
192
- const dx = centerX - targetRoof.position[0];
193
- const dz = centerZ - targetRoof.position[2];
194
- const angle = -targetRoof.rotation;
195
- localX = dx * Math.cos(angle) - dz * Math.sin(angle);
196
- localZ = dx * Math.sin(angle) + dz * Math.cos(angle);
197
- }
198
- const placement = resolveRoofDraftPlacement(footprintWidth, footprintDepth, quarterTurn, targetRoof.rotation, roofType);
252
+ // The corners are in the level's plan, the roof's frame: its own place and turn in it. (Its
253
+ // mesh's world matrix also carries the building's, which would throw the plane off.)
254
+ const dx = centerX - targetRoof.position[0];
255
+ const dz = centerZ - targetRoof.position[2];
256
+ const angle = -targetRoof.rotation;
257
+ const localX = dx * Math.cos(angle) - dz * Math.sin(angle);
258
+ const localZ = dx * Math.sin(angle) + dz * Math.cos(angle);
259
+ const placement = resolveRoofDraftPlacement(footprintWidth, footprintDepth, ridge, targetRoof.rotation, roofType);
199
260
  const sibling = targetRoof.children
200
261
  .map((id) => nodes[id])
201
262
  .find((node) => node?.type === 'roof-segment');
202
- const segment = RoofSegmentNode.parse({
263
+ const drawn = RoofSegmentNode.parse({
203
264
  roofSystem: sibling?.type === 'roof-segment' ? sibling.roofSystem : undefined,
204
265
  glazing: sibling?.type === 'roof-segment' ? sibling.glazing : undefined,
205
266
  barrelRise: sibling?.type === 'roof-segment' ? sibling.barrelRise : undefined,
206
267
  barrelSegments: sibling?.type === 'roof-segment' ? sibling.barrelSegments : undefined,
207
- wallHeight: DEFAULT_WALL_HEIGHT,
268
+ // A wing bears where the roof it joins does: on the plate, or on the same raised heel.
269
+ wallHeight: sibling?.type === 'roof-segment' ? sibling.wallHeight : DEFAULT_HEEL_HEIGHT,
208
270
  pitch: DEFAULT_PITCH_DEG,
209
271
  roofType: 'gable',
210
272
  ...defaults,
@@ -213,6 +275,7 @@ export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selecte
213
275
  position: [localX, 0, localZ],
214
276
  rotation: placement.rotation,
215
277
  });
278
+ const segment = onBearingWalls(drawn, targetRoof, roofCatchWalls(nodes, targetRoof.parentId));
216
279
  writeSeatedRoofEdit(sceneApi, {
217
280
  create: [{ node: segment, parentId: targetRoofId }],
218
281
  });
@@ -223,10 +286,14 @@ export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selecte
223
286
  const roofCount = Object.values(nodes).filter((n) => n.type === 'roof').length;
224
287
  const name = `Roof ${roofCount + 1}`;
225
288
  const roofRotation = typeof defaults.rotation === 'number' ? defaults.rotation : 0;
226
- const placement = resolveRoofDraftPlacement(footprintWidth, footprintDepth, quarterTurn, roofRotation, roofType);
289
+ const placement = resolveRoofDraftPlacement(footprintWidth, footprintDepth, ridge, roofRotation, roofType);
227
290
  // Create the segment first (centered in its new parent)
228
- const segment = RoofSegmentNode.parse({
229
- wallHeight: DEFAULT_WALL_HEIGHT,
291
+ const drawnRoof = {
292
+ position: [centerX, 0, centerZ],
293
+ rotation: roofRotation,
294
+ };
295
+ const { center: [roofX, roofZ], segment, } = centredRoof(drawnRoof, onBearingWalls(RoofSegmentNode.parse({
296
+ wallHeight: DEFAULT_HEEL_HEIGHT,
230
297
  pitch: DEFAULT_PITCH_DEG,
231
298
  roofType: 'gable',
232
299
  ...defaults,
@@ -234,7 +301,7 @@ export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selecte
234
301
  depth: placement.depth,
235
302
  position: [0, 0, 0],
236
303
  rotation: placement.rotation,
237
- });
304
+ }), drawnRoof, roofCatchWalls(nodes, levelId)));
238
305
  // Drawn over a storey's walls, the roof goes on the level above them.
239
306
  const target = drawnRoofLevelTarget(nodes, levelId, segment.wallHeight + getActiveRoofHeight(segment), { center: [centerX, centerZ], width: footprintWidth, depth: footprintDepth, roofType });
240
307
  const support = drawnRoofSupport(target, levelId);
@@ -243,14 +310,14 @@ export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selecte
243
310
  const placed = RoofNode.parse({
244
311
  ...defaults,
245
312
  name,
246
- position: [centerX, 0, centerZ],
313
+ position: [roofX, 0, roofZ],
247
314
  support,
248
315
  children: [segment.id],
249
316
  });
250
317
  const roof = support.kind === 'walls'
251
318
  ? RoofNode.parse({
252
319
  ...placed,
253
- position: [centerX, seatedRoofElevation(target, placed, [segment]), centerZ],
320
+ position: [roofX, seatedRoofElevation(target, placed, [segment]), roofZ],
254
321
  })
255
322
  : placed;
256
323
  // Create roof first (so segment can be parented to it), then segment
@@ -261,9 +328,10 @@ export const commitRoofPlacement = (sceneApi, levelId, corner1, corner2, selecte
261
328
  triggerSFX('sfx:structure-build');
262
329
  return roof.id;
263
330
  };
264
- export const commitRoofFootprint = (sceneApi, levelId, target, quarterTurn) => {
331
+ export const commitRoofFootprint = (sceneApi, levelId, target, ridge) => {
265
332
  if (!target.rectangular)
266
333
  return null;
334
+ const quarterTurn = resolveQuarterTurn(ridge, target.width, target.depth);
267
335
  const nodes = sceneApi.nodes();
268
336
  const defaults = useEditor.getState().toolDefaults.roof ?? {};
269
337
  const parsedRoofType = RoofTypeSchema.safeParse(defaults.roofType);
@@ -271,10 +339,15 @@ export const commitRoofFootprint = (sceneApi, levelId, target, quarterTurn) => {
271
339
  if (roofType === 'conical')
272
340
  return null;
273
341
  const roofCount = Object.values(nodes).filter((node) => node.type === 'roof').length;
274
- const segment = RoofSegmentNode.parse({
342
+ const walls = target.wallIds
343
+ .map((id) => nodes[id])
344
+ .filter((node) => node?.type === 'wall');
345
+ const picked = RoofSegmentNode.parse({
275
346
  pitch: DEFAULT_PITCH_DEG,
276
347
  roofType: 'gable',
277
348
  ...defaults,
349
+ // Its gable and heel walls stand flush on the room's walls.
350
+ ...(walls.length > 0 && { wallThickness: Math.max(...walls.map(getWallThickness)) }),
278
351
  wallHeight: 0,
279
352
  width: quarterTurn ? target.depth : target.width,
280
353
  depth: quarterTurn ? target.width : target.depth,
@@ -283,16 +356,27 @@ export const commitRoofFootprint = (sceneApi, levelId, target, quarterTurn) => {
283
356
  });
284
357
  // A roof belongs to the level above the walls it covers, whichever level the tool was armed
285
358
  // on: over the top floor, the building's roof level.
286
- const firstWall = target.wallIds.map((id) => nodes[id]).find((node) => node?.type === 'wall');
287
- const wallsLevelId = (firstWall ? resolveLevelId(firstWall, nodes) : levelId);
359
+ const firstWall = walls[0];
360
+ const wallsLevelId = (target.levelId ??
361
+ (firstWall ? resolveLevelId(firstWall, nodes) : levelId));
362
+ // Over a porch, deck or patio, the roof's walls stand their outer faces on the room's outside
363
+ // edge, as a house roof's stand on the walls' outside faces.
364
+ const pickedRoof = {
365
+ position: [target.center[0], 0, target.center[1]],
366
+ rotation: target.rotation,
367
+ };
368
+ const { center, segment } = centredRoof(pickedRoof, {
369
+ ...picked,
370
+ ...settleSegmentOnEdges(pickedRoof, picked, roofCatchWalls(nodes, wallsLevelId)),
371
+ });
288
372
  const level = roofLevelTarget(nodes, wallsLevelId, getActiveRoofHeight(segment));
289
373
  const roof = RoofNode.parse({
290
374
  ...defaults,
291
375
  name: `Roof ${roofCount + 1}`,
292
376
  position: [
293
- target.center[0],
377
+ center[0],
294
378
  resolveRoofFootprintElevation(level.levelId, target, level.nodes),
295
- target.center[1],
379
+ center[1],
296
380
  ],
297
381
  rotation: target.rotation,
298
382
  support: { kind: 'walls' },
@@ -472,16 +556,16 @@ export const RoofTool = () => {
472
556
  const roofType = parsedRoofType.success ? parsedRoofType.data : 'gable';
473
557
  const footprintSourceChoice = useRoofFootprintSource((state) => state.source);
474
558
  const footprintSource = parseRoofFootprintSource(footprintSourceChoice, roofType);
475
- const previewWallHeight = typeof roofDefaults?.wallHeight === 'number' ? roofDefaults.wallHeight : DEFAULT_WALL_HEIGHT;
559
+ const previewWallHeight = typeof roofDefaults?.wallHeight === 'number'
560
+ ? roofDefaults.wallHeight
561
+ : roofType === 'conical'
562
+ ? DEFAULT_CONICAL_CURB_HEIGHT
563
+ : DEFAULT_HEEL_HEIGHT;
476
564
  const previewPitch = typeof roofDefaults?.pitch === 'number' ? roofDefaults.pitch : DEFAULT_PITCH_DEG;
477
565
  const selectedIdsRef = useRef(selectedIds);
478
566
  useEffect(() => {
479
567
  selectedIdsRef.current = selectedIds;
480
568
  }, [selectedIds]);
481
- useEffect(() => {
482
- useRoofPlacementMode.getState().setConical(roofType === 'conical');
483
- return () => useRoofPlacementMode.getState().setConical(false);
484
- }, [roofType]);
485
569
  useEffect(() => {
486
570
  if (!currentLevelId)
487
571
  return;
@@ -508,10 +592,11 @@ export const RoofTool = () => {
508
592
  // Clear preset-seeded defaults on deactivation so a later manual roof draw
509
593
  // isn't built with a stale preset's parameters. Unmount-only.
510
594
  useEffect(() => () => useEditor.getState().setToolDefaults('roof', null), []);
595
+ // Each arming starts with the ridge along the long side. Unmount-only.
596
+ useEffect(() => () => useRoofRidgeMode.getState().reset(), []);
511
597
  const corner1Ref = useRef(null);
512
598
  const previousGridPosRef = useRef(null);
513
- const quarterTurnRef = useRef(false);
514
- const [quarterTurn, setQuarterTurn] = useState(false);
599
+ const ridgeMode = useRoofRidgeMode((state) => state.mode);
515
600
  const [footprintTarget, setFootprintTarget] = useState(null);
516
601
  const previewTargetIdRef = useRef(null);
517
602
  const [previewedConicalWallId, setPreviewedConicalWallId] = useState(null);
@@ -531,41 +616,23 @@ export const RoofTool = () => {
531
616
  if (!currentLevelId)
532
617
  return;
533
618
  outlineRef.current.geometry = new BufferGeometry();
534
- useFloorplanDraftPreview.getState().setRoofDraftQuarterTurn(quarterTurnRef.current);
619
+ // The 2D draft's ridge line follows the drawn rectangle and the ridge mode.
620
+ const syncDraftRidge = (corner1, corner2) => useFloorplanDraftPreview
621
+ .getState()
622
+ .setRoofDraftQuarterTurn(ridgeQuarterTurn(Math.abs(corner2[0] - corner1[0]), Math.abs(corner2[2] - corner1[2]), useRoofRidgeMode.getState().mode));
623
+ let lastCursor = null;
535
624
  // Alignment candidates — anchors of every alignable object on the active
536
625
  // level plus the wall corners of the floor directly below, so a roof drawn
537
626
  // on the upper floor aligns to the walls beneath it. Refreshed after each
538
627
  // roof commits. Both corners of the rectangle align.
539
628
  let alignmentCandidates = collectRoofAlignmentAnchors(sceneApi.nodes(), currentLevelId, roofType);
540
- // Resolve a grid:move/click into the drafted corner via the shared surface
541
- // snap pipeline: magnetic lock onto wall corners / midpoints / crossings /
542
- // bodies on the active level + floor below (raising the green beacon),
543
- // falling back to alignment guides, then to the world-grid snap. The same
544
- // path the slab/ceiling tools use, so the beacon and coloring match. The
545
- // pipeline reads the active snapping mode (grid / lines / angles / off),
546
- // so this tool never inspects the flags. `levelId` is intentionally omitted
547
- // so the explicit floor-below `walls` aren't filtered back out.
548
- const resolveDraftPoint = (event) => {
549
- const rawPoint = [event.localPosition[0], event.localPosition[2]];
550
- const gridFallback = isGridSnapActive()
551
- ? snapWorldXZForActiveBuilding(event.position[0], event.position[2], useEditor.getState().gridSnapStep).local
552
- : rawPoint;
553
- const nodes = sceneApi.nodes();
554
- return resolveSurfacePlanPointSnap({
555
- rawPoint,
556
- fallbackPoint: gridFallback,
557
- walls: getRoofSnapWalls(currentLevelId, nodes, roofType),
558
- candidates: alignmentCandidates,
559
- movingId: '__roof-draft__',
560
- highlightWalls: true,
561
- }).point;
562
- };
629
+ const resolveDraftPoint = (event) => resolveRoofDraftPoint(event, currentLevelId, sceneApi.nodes(), roofType, alignmentCandidates);
563
630
  const updateFootprintPreview = (target) => {
564
631
  setFootprintTarget((previous) => (previous?.id === target?.id ? previous : target));
565
632
  if (previewTargetIdRef.current === (target?.id ?? null))
566
633
  return;
567
634
  previewTargetIdRef.current = target?.id ?? null;
568
- setPreviewSelectedIds(target?.wallIds ?? []);
635
+ setPreviewSelectedIds(roofFootprintPreviewIds(target));
569
636
  };
570
637
  const updateOutline = (corner1, corner2) => {
571
638
  let gridY = corner1[1] + GRID_OFFSET;
@@ -574,7 +641,9 @@ export const RoofTool = () => {
574
641
  const centerZ = (corner1[2] + corner2[2]) / 2;
575
642
  const diameter = Math.max(Math.abs(corner2[0] - corner1[0]), Math.abs(corner2[2] - corner1[2]));
576
643
  const defaults = useEditor.getState().toolDefaults.roof;
577
- const curbHeight = typeof defaults?.wallHeight === 'number' ? defaults.wallHeight : DEFAULT_WALL_HEIGHT;
644
+ const curbHeight = typeof defaults?.wallHeight === 'number'
645
+ ? defaults.wallHeight
646
+ : DEFAULT_CONICAL_CURB_HEIGHT;
578
647
  const target = drawnRoofLevelTarget(sceneApi.nodes(), currentLevelId, 0, {
579
648
  center: [centerX, centerZ],
580
649
  width: diameter,
@@ -619,16 +688,20 @@ export const RoofTool = () => {
619
688
  outlineRef.current.geometry = new BufferGeometry().setFromPoints(groundPoints);
620
689
  outlineRef.current.visible = true;
621
690
  };
691
+ // In 2D-only view the plan's own roof tool owns the input (`floorplan-tool.tsx`); this tool,
692
+ // mounted behind the hidden canvas from an earlier visit, still hears the plan's grid events,
693
+ // so it must not also draft or commit (every roof would be made twice).
694
+ const planOwnsInput = () => visibleScene(useEditor.getState()) === '2d';
622
695
  const onGridMove = (event) => {
623
- if (!cursorRef.current)
696
+ if (!cursorRef.current || planOwnsInput())
624
697
  return;
625
698
  if (footprintSource !== 'draw') {
626
699
  const [snappedX, snappedZ] = resolveDraftPoint(event);
627
700
  let target = null;
628
701
  if (footprintSource === 'room') {
629
- target = resolveRoomRoofFootprint(currentLevelId, sceneApi.nodes(), [snappedX, snappedZ], {
630
- rectangularOnly: true,
631
- });
702
+ const room = pickRoofRoom(currentLevelId, sceneApi.nodes(), [snappedX, snappedZ]);
703
+ target = room.target;
704
+ useRoofFootprintSource.getState().setRoomPick(room.pick);
632
705
  updateFootprintPreview(target);
633
706
  }
634
707
  cursorRef.current.position.set(snappedX, target
@@ -658,20 +731,26 @@ export const RoofTool = () => {
658
731
  const draftPreview = useFloorplanDraftPreview.getState();
659
732
  draftPreview.setRoofDraftStart([corner1Ref.current[0], corner1Ref.current[2]]);
660
733
  draftPreview.setRoofDraftEnd([gridX, gridZ]);
734
+ syncDraftRidge(corner1Ref.current, cursorPosition);
661
735
  updateOutline(corner1Ref.current, cursorPosition);
662
736
  }
737
+ lastCursor = cursorPosition;
663
738
  };
664
739
  const onGridClick = (event) => {
665
- if (!currentLevelId)
740
+ if (!currentLevelId || planOwnsInput())
666
741
  return;
667
742
  if (footprintSource !== 'draw') {
668
743
  if (footprintSource !== 'room')
669
744
  return;
670
745
  const [snappedX, snappedZ] = resolveDraftPoint(event);
671
- const target = resolveRoomRoofFootprint(currentLevelId, sceneApi.nodes(), [snappedX, snappedZ], { rectangularOnly: true });
746
+ const { target, pick } = pickRoofRoom(currentLevelId, sceneApi.nodes(), [
747
+ snappedX,
748
+ snappedZ,
749
+ ]);
750
+ useRoofFootprintSource.getState().setRoomPick(pick);
672
751
  if (!target)
673
752
  return;
674
- const roofId = commitRoofFootprint(sceneApi, currentLevelId, target, quarterTurnRef.current);
753
+ const roofId = commitRoofFootprint(sceneApi, currentLevelId, target, useRoofRidgeMode.getState().mode);
675
754
  if (roofId)
676
755
  selectNode(roofId);
677
756
  return;
@@ -679,7 +758,7 @@ export const RoofTool = () => {
679
758
  const [gridX, gridZ] = resolveDraftPoint(event);
680
759
  const y = event.localPosition[1];
681
760
  if (corner1Ref.current) {
682
- const roofId = commitRoofPlacement(sceneApi, currentLevelId, corner1Ref.current, [gridX, y, gridZ], selectedIdsRef.current, quarterTurnRef.current, useRoofPlacementMode.getState().mode);
761
+ const roofId = commitRoofPlacement(sceneApi, currentLevelId, corner1Ref.current, [gridX, y, gridZ], selectedIdsRef.current, useRoofRidgeMode.getState().mode, useRoofPlacementMode.getState().mode);
683
762
  if (!roofId)
684
763
  return;
685
764
  selectNode(roofId);
@@ -703,21 +782,32 @@ export const RoofTool = () => {
703
782
  }));
704
783
  }
705
784
  };
785
+ const dropCorner = () => {
786
+ corner1Ref.current = null;
787
+ outlineRef.current.visible = false;
788
+ setPreview((prev) => ({ ...prev, corner1: null }));
789
+ };
790
+ // A corner opened before the view went 2D-only would end the next rectangle drawn back in
791
+ // split view. The plan's tool clears the shared draft as it takes over.
792
+ const unsubscribeView = useEditor.subscribe((state) => {
793
+ if (corner1Ref.current && visibleScene(state) === '2d')
794
+ dropCorner();
795
+ });
706
796
  const onCancel = () => {
707
797
  if (corner1Ref.current) {
708
798
  markToolCancelConsumed();
709
- corner1Ref.current = null;
799
+ dropCorner();
710
800
  const draftPreview = useFloorplanDraftPreview.getState();
711
801
  draftPreview.setRoofDraftStart(null);
712
802
  draftPreview.setRoofDraftEnd(null);
713
- outlineRef.current.visible = false;
714
- setPreview((prev) => ({ ...prev, corner1: null }));
715
803
  }
716
804
  clearSurfacePlanSnapFeedback();
717
805
  previewTargetIdRef.current = null;
718
806
  setPreviewSelectedIds([]);
719
807
  };
720
808
  const onKeyDown = (event) => {
809
+ if (planOwnsInput())
810
+ return;
721
811
  if (event.target instanceof HTMLInputElement ||
722
812
  event.target instanceof HTMLTextAreaElement ||
723
813
  (event.target instanceof HTMLElement && event.target.isContentEditable)) {
@@ -743,12 +833,14 @@ export const RoofTool = () => {
743
833
  return;
744
834
  }
745
835
  event.preventDefault();
746
- const nextQuarterTurn = !quarterTurnRef.current;
747
- quarterTurnRef.current = nextQuarterTurn;
748
- setQuarterTurn(nextQuarterTurn);
749
- useFloorplanDraftPreview.getState().setRoofDraftQuarterTurn(nextQuarterTurn);
836
+ useRoofRidgeMode.getState().toggle();
750
837
  triggerSFX('sfx:item-rotate');
751
838
  };
839
+ // The HUD chip flips the mode too; either way the 2D draft follows.
840
+ const unsubscribeRidgeMode = useRoofRidgeMode.subscribe(() => {
841
+ if (corner1Ref.current && lastCursor)
842
+ syncDraftRidge(corner1Ref.current, lastCursor);
843
+ });
752
844
  emitter.on('grid:move', onGridMove);
753
845
  emitter.on('grid:click', onGridClick);
754
846
  emitter.on('tool:cancel', onCancel);
@@ -788,11 +880,14 @@ export const RoofTool = () => {
788
880
  emitter.off('wall:leave', onWallLeave);
789
881
  unsubscribeConicalRoofWallClicks();
790
882
  window.removeEventListener('keydown', onKeyDown);
883
+ unsubscribeRidgeMode();
884
+ unsubscribeView();
791
885
  clearSurfacePlanSnapFeedback();
792
886
  previewTargetIdRef.current = null;
793
887
  setPreviewedConicalWallId(null);
794
888
  setInvalidStandardWallHover(false);
795
889
  setPreviewSelectedIds([]);
890
+ useRoofFootprintSource.getState().setRoomPick(null);
796
891
  corner1Ref.current = null;
797
892
  const draftPreview = useFloorplanDraftPreview.getState();
798
893
  draftPreview.setRoofDraftStart(null);
@@ -899,14 +994,14 @@ export const RoofTool = () => {
899
994
  !resolvedPreviewDimensions ||
900
995
  (roofType === 'conical' && footprintSource !== 'draw'))
901
996
  return null;
902
- const placement = resolveRoofDraftPlacement(resolvedPreviewDimensions.length, resolvedPreviewDimensions.width, quarterTurn, 0, roofType);
997
+ const placement = resolveRoofDraftPlacement(resolvedPreviewDimensions.length, resolvedPreviewDimensions.width, ridgeMode, 0, roofType);
903
998
  return buildRoofGhostGeometry(placement.width, placement.depth, ghostWallHeight, previewPitch, roofType);
904
999
  }, [
905
1000
  footprintSource,
906
1001
  ghostWallHeight,
907
1002
  invalidStandardWallHover,
908
1003
  previewPitch,
909
- quarterTurn,
1004
+ ridgeMode,
910
1005
  resolvedPreviewDimensions,
911
1006
  roofType,
912
1007
  ]);
@@ -915,14 +1010,14 @@ export const RoofTool = () => {
915
1010
  !resolvedPreviewDimensions ||
916
1011
  (roofType === 'conical' && footprintSource !== 'draw'))
917
1012
  return null;
918
- const placement = resolveRoofDraftPlacement(resolvedPreviewDimensions.length, resolvedPreviewDimensions.width, quarterTurn, 0, roofType);
1013
+ const placement = resolveRoofDraftPlacement(resolvedPreviewDimensions.length, resolvedPreviewDimensions.width, ridgeMode, 0, roofType);
919
1014
  return buildRoofGhostEdges(placement.width, placement.depth, ghostWallHeight, previewPitch, roofType);
920
1015
  }, [
921
1016
  footprintSource,
922
1017
  ghostWallHeight,
923
1018
  invalidStandardWallHover,
924
1019
  previewPitch,
925
- quarterTurn,
1020
+ ridgeMode,
926
1021
  resolvedPreviewDimensions,
927
1022
  roofType,
928
1023
  ]);
@@ -954,7 +1049,10 @@ export const RoofTool = () => {
954
1049
  ], rotation: [
955
1050
  0,
956
1051
  (footprintSource !== 'draw' ? (footprintTarget?.rotation ?? 0) : 0) +
957
- (roofType === 'conical' ? 0 : quarterTurn ? Math.PI / 2 : 0),
1052
+ (roofType !== 'conical' &&
1053
+ ridgeQuarterTurn(resolvedPreviewDimensions.length, resolvedPreviewDimensions.width, ridgeMode)
1054
+ ? Math.PI / 2
1055
+ : 0),
958
1056
  0,
959
1057
  ], children: [roofGhostGeometry && (_jsx("mesh", { geometry: roofGhostGeometry, layers: EDITOR_LAYER, renderOrder: 1, children: _jsx("meshBasicMaterial", { color: ghostColor, depthTest: false, depthWrite: false, opacity: 0.16, side: DoubleSide, transparent: true }) })), roofGhostEdges && (_jsx("lineSegments", { geometry: roofGhostEdges, layers: EDITOR_LAYER, renderOrder: 2, children: _jsx("lineBasicMaterial", { color: ghostColor, depthTest: false, depthWrite: false, opacity: 0.5, transparent: true }) }))] }))] }));
960
1058
  };