@pascal-app/nodes 0.1.1 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (408) hide show
  1. package/README.md +34 -0
  2. package/dist/building/definition.js +1 -1
  3. package/dist/cabinet/definition.d.ts.map +1 -1
  4. package/dist/cabinet/definition.js +809 -72
  5. package/dist/cabinet/geometry.d.ts.map +1 -1
  6. package/dist/cabinet/geometry.js +4 -0
  7. package/dist/cabinet/move-frame.js +3 -3
  8. package/dist/cabinet/panel.d.ts.map +1 -1
  9. package/dist/cabinet/panel.js +1 -0
  10. package/dist/cabinet/placement-snap.d.ts +8 -0
  11. package/dist/cabinet/placement-snap.d.ts.map +1 -0
  12. package/dist/cabinet/placement-snap.js +19 -0
  13. package/dist/cabinet/presets.js +8 -8
  14. package/dist/cabinet/quick-actions.d.ts.map +1 -1
  15. package/dist/cabinet/quick-actions.js +9 -3
  16. package/dist/cabinet/resize-limits.d.ts +11 -0
  17. package/dist/cabinet/resize-limits.d.ts.map +1 -0
  18. package/dist/cabinet/resize-limits.js +22 -0
  19. package/dist/cabinet/run-layout.d.ts +8 -2
  20. package/dist/cabinet/run-layout.d.ts.map +1 -1
  21. package/dist/cabinet/run-layout.js +59 -7
  22. package/dist/cabinet/run-ops.d.ts +44 -3
  23. package/dist/cabinet/run-ops.d.ts.map +1 -1
  24. package/dist/cabinet/run-ops.js +646 -110
  25. package/dist/cabinet/run-panel.d.ts +2 -1
  26. package/dist/cabinet/run-panel.d.ts.map +1 -1
  27. package/dist/cabinet/run-panel.js +38 -4
  28. package/dist/cabinet/stack-transitions.js +4 -4
  29. package/dist/cabinet/tool.d.ts.map +1 -1
  30. package/dist/cabinet/tool.js +95 -17
  31. package/dist/cabinet/wall-snap.d.ts.map +1 -1
  32. package/dist/cabinet/wall-snap.js +2 -6
  33. package/dist/ceiling/boundary-editor.d.ts.map +1 -1
  34. package/dist/ceiling/boundary-editor.js +2 -2
  35. package/dist/ceiling/definition.d.ts +1 -1
  36. package/dist/ceiling/definition.d.ts.map +1 -1
  37. package/dist/ceiling/definition.js +36 -5
  38. package/dist/ceiling/floorplan-affordances.d.ts +4 -4
  39. package/dist/ceiling/floorplan-move.d.ts +4 -4
  40. package/dist/ceiling/floorplan-move.d.ts.map +1 -1
  41. package/dist/ceiling/floorplan-move.js +5 -4
  42. package/dist/ceiling/hole-editor.d.ts.map +1 -1
  43. package/dist/ceiling/hole-editor.js +2 -2
  44. package/dist/ceiling/move-tool.d.ts.map +1 -1
  45. package/dist/ceiling/move-tool.js +4 -3
  46. package/dist/ceiling/panel.d.ts.map +1 -1
  47. package/dist/ceiling/panel.js +65 -3
  48. package/dist/ceiling/renderer.d.ts.map +1 -1
  49. package/dist/ceiling/renderer.js +6 -2
  50. package/dist/ceiling/tool.d.ts.map +1 -1
  51. package/dist/ceiling/tool.js +12 -1
  52. package/dist/chimney/definition.d.ts.map +1 -1
  53. package/dist/chimney/definition.js +1 -0
  54. package/dist/chimney/tool.d.ts.map +1 -1
  55. package/dist/chimney/tool.js +16 -1
  56. package/dist/column/definition.d.ts.map +1 -1
  57. package/dist/column/definition.js +14 -2
  58. package/dist/column/floorplan-affordances.d.ts.map +1 -1
  59. package/dist/column/floorplan-affordances.js +19 -14
  60. package/dist/column/floorplan-move.d.ts.map +1 -1
  61. package/dist/column/floorplan-move.js +7 -2
  62. package/dist/column/floorplan.d.ts +9 -1
  63. package/dist/column/floorplan.d.ts.map +1 -1
  64. package/dist/column/floorplan.js +59 -4
  65. package/dist/column/tool.d.ts.map +1 -1
  66. package/dist/column/tool.js +33 -7
  67. package/dist/construction-dimension/definition.d.ts +4 -0
  68. package/dist/construction-dimension/definition.d.ts.map +1 -0
  69. package/dist/construction-dimension/definition.js +83 -0
  70. package/dist/construction-dimension/drawing-coordination.d.ts +7 -0
  71. package/dist/construction-dimension/drawing-coordination.d.ts.map +1 -0
  72. package/dist/construction-dimension/drawing-coordination.js +54 -0
  73. package/dist/construction-dimension/floorplan-affordances.d.ts +4 -0
  74. package/dist/construction-dimension/floorplan-affordances.d.ts.map +1 -0
  75. package/dist/construction-dimension/floorplan-affordances.js +114 -0
  76. package/dist/construction-dimension/floorplan-tool.d.ts +21 -0
  77. package/dist/construction-dimension/floorplan-tool.d.ts.map +1 -0
  78. package/dist/construction-dimension/floorplan-tool.js +557 -0
  79. package/dist/construction-dimension/floorplan.d.ts +3 -0
  80. package/dist/construction-dimension/floorplan.d.ts.map +1 -0
  81. package/dist/construction-dimension/floorplan.js +457 -0
  82. package/dist/construction-dimension/geometry.d.ts +31 -0
  83. package/dist/construction-dimension/geometry.d.ts.map +1 -0
  84. package/dist/construction-dimension/geometry.js +144 -0
  85. package/dist/construction-dimension/index.d.ts +4 -0
  86. package/dist/construction-dimension/index.d.ts.map +1 -0
  87. package/dist/construction-dimension/index.js +3 -0
  88. package/dist/construction-dimension/panel.d.ts +2 -0
  89. package/dist/construction-dimension/panel.d.ts.map +1 -0
  90. package/dist/construction-dimension/panel.js +128 -0
  91. package/dist/construction-dimension/parametrics.d.ts +3 -0
  92. package/dist/construction-dimension/parametrics.d.ts.map +1 -0
  93. package/dist/construction-dimension/parametrics.js +4 -0
  94. package/dist/construction-dimension/schema.d.ts +2 -0
  95. package/dist/construction-dimension/schema.d.ts.map +1 -0
  96. package/dist/construction-dimension/schema.js +1 -0
  97. package/dist/door/contextual-dimensions.d.ts +3 -0
  98. package/dist/door/contextual-dimensions.d.ts.map +1 -0
  99. package/dist/door/contextual-dimensions.js +7 -0
  100. package/dist/door/definition.d.ts.map +1 -1
  101. package/dist/door/definition.js +13 -8
  102. package/dist/door/floorplan-affordances.d.ts +2 -5
  103. package/dist/door/floorplan-affordances.d.ts.map +1 -1
  104. package/dist/door/floorplan-affordances.js +9 -18
  105. package/dist/door/floorplan.d.ts +3 -4
  106. package/dist/door/floorplan.d.ts.map +1 -1
  107. package/dist/door/floorplan.js +88 -6
  108. package/dist/door/move-tool.d.ts.map +1 -1
  109. package/dist/door/move-tool.js +2 -2
  110. package/dist/door/panel.d.ts.map +1 -1
  111. package/dist/door/panel.js +3 -1
  112. package/dist/door/schema.d.ts +1 -1
  113. package/dist/door/schema.d.ts.map +1 -1
  114. package/dist/door/schema.js +1 -1
  115. package/dist/door/tool.d.ts.map +1 -1
  116. package/dist/door/tool.js +63 -6
  117. package/dist/dormer/definition.d.ts.map +1 -1
  118. package/dist/dormer/definition.js +1 -0
  119. package/dist/dormer/tool.d.ts.map +1 -1
  120. package/dist/dormer/tool.js +23 -1
  121. package/dist/duct-segment/tool.d.ts.map +1 -1
  122. package/dist/duct-segment/tool.js +20 -9
  123. package/dist/duct-terminal/tool.d.ts.map +1 -1
  124. package/dist/duct-terminal/tool.js +9 -6
  125. package/dist/elevator/floorplan-affordances.d.ts +2 -6
  126. package/dist/elevator/floorplan-affordances.d.ts.map +1 -1
  127. package/dist/elevator/floorplan-affordances.js +13 -12
  128. package/dist/fence/actions/move-endpoint.d.ts.map +1 -1
  129. package/dist/fence/actions/move-endpoint.js +29 -1
  130. package/dist/fence/definition.d.ts.map +1 -1
  131. package/dist/fence/definition.js +67 -14
  132. package/dist/fence/floorplan-affordances.d.ts.map +1 -1
  133. package/dist/fence/floorplan-affordances.js +48 -11
  134. package/dist/fence/floorplan-move.d.ts.map +1 -1
  135. package/dist/fence/floorplan-move.js +38 -3
  136. package/dist/fence/geometry.d.ts.map +1 -1
  137. package/dist/fence/geometry.js +9 -1
  138. package/dist/fence/lift.d.ts +15 -0
  139. package/dist/fence/lift.d.ts.map +1 -0
  140. package/dist/fence/lift.js +23 -0
  141. package/dist/fence/move-tool.d.ts.map +1 -1
  142. package/dist/fence/move-tool.js +25 -5
  143. package/dist/fence/system.d.ts +3 -0
  144. package/dist/fence/system.d.ts.map +1 -0
  145. package/dist/fence/system.js +41 -0
  146. package/dist/fence/tool.d.ts.map +1 -1
  147. package/dist/fence/tool.js +103 -32
  148. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  149. package/dist/hvac-equipment/tool.js +8 -3
  150. package/dist/index.d.ts +2 -0
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.js +6 -0
  153. package/dist/item/definition.d.ts.map +1 -1
  154. package/dist/item/definition.js +7 -1
  155. package/dist/item/floorplan-move.d.ts.map +1 -1
  156. package/dist/item/floorplan-move.js +50 -43
  157. package/dist/item/floorplan.d.ts +1 -0
  158. package/dist/item/floorplan.d.ts.map +1 -1
  159. package/dist/item/floorplan.js +49 -0
  160. package/dist/item/renderer.d.ts +3 -0
  161. package/dist/item/renderer.d.ts.map +1 -1
  162. package/dist/item/renderer.js +96 -8
  163. package/dist/level/definition.d.ts.map +1 -1
  164. package/dist/level/definition.js +7 -3
  165. package/dist/lineset/tool.d.ts.map +1 -1
  166. package/dist/lineset/tool.js +5 -1
  167. package/dist/liquid-line/tool.d.ts.map +1 -1
  168. package/dist/liquid-line/tool.js +7 -1
  169. package/dist/measurement/definition.d.ts.map +1 -1
  170. package/dist/measurement/definition.js +5 -0
  171. package/dist/measurement/floorplan.d.ts.map +1 -1
  172. package/dist/measurement/floorplan.js +11 -10
  173. package/dist/measurement/index.d.ts +1 -1
  174. package/dist/measurement/index.d.ts.map +1 -1
  175. package/dist/measurement/index.js +1 -1
  176. package/dist/measurement/resolve.d.ts +5 -0
  177. package/dist/measurement/resolve.d.ts.map +1 -1
  178. package/dist/measurement/resolve.js +2 -2
  179. package/dist/measurement/surface-query.js +5 -5
  180. package/dist/measurement/tool.d.ts +6 -1
  181. package/dist/measurement/tool.d.ts.map +1 -1
  182. package/dist/measurement/tool.js +7 -11
  183. package/dist/pipe-segment/tool.d.ts.map +1 -1
  184. package/dist/pipe-segment/tool.js +22 -19
  185. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  186. package/dist/roof-segment/floorplan-affordances.js +14 -8
  187. package/dist/shared/construction-dimension-standards.d.ts +34 -0
  188. package/dist/shared/construction-dimension-standards.d.ts.map +1 -0
  189. package/dist/shared/construction-dimension-standards.js +18 -0
  190. package/dist/shared/construction-length.d.ts +10 -0
  191. package/dist/shared/construction-length.d.ts.map +1 -0
  192. package/dist/shared/construction-length.js +57 -0
  193. package/dist/shared/dimension-string.d.ts +20 -0
  194. package/dist/shared/dimension-string.d.ts.map +1 -0
  195. package/dist/shared/dimension-string.js +19 -0
  196. package/dist/shared/draft-axis-guides.d.ts +36 -0
  197. package/dist/shared/draft-axis-guides.d.ts.map +1 -0
  198. package/dist/shared/draft-axis-guides.js +107 -0
  199. package/dist/shared/move-roof-tool.d.ts.map +1 -1
  200. package/dist/shared/move-roof-tool.js +17 -3
  201. package/dist/shared/opening-documentation-fields.d.ts +16 -0
  202. package/dist/shared/opening-documentation-fields.d.ts.map +1 -0
  203. package/dist/shared/opening-documentation-fields.js +54 -0
  204. package/dist/shared/opening-documentation.d.ts +47 -0
  205. package/dist/shared/opening-documentation.d.ts.map +1 -0
  206. package/dist/shared/opening-documentation.js +300 -0
  207. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  208. package/dist/shared/opening-guides-runtime.js +3 -2
  209. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  210. package/dist/shared/opening-placement-dimensions.js +14 -5
  211. package/dist/shared/wall-opening-ceiling.d.ts +30 -0
  212. package/dist/shared/wall-opening-ceiling.d.ts.map +1 -0
  213. package/dist/shared/wall-opening-ceiling.js +29 -0
  214. package/dist/shelf/floorplan-affordances.d.ts.map +1 -1
  215. package/dist/shelf/floorplan-affordances.js +10 -5
  216. package/dist/shelf/floorplan-move.d.ts +2 -16
  217. package/dist/shelf/floorplan-move.d.ts.map +1 -1
  218. package/dist/shelf/floorplan-move.js +19 -40
  219. package/dist/shelf/tool.d.ts.map +1 -1
  220. package/dist/shelf/tool.js +8 -3
  221. package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
  222. package/dist/site/recessed-slab-ground-holes.js +1 -4
  223. package/dist/site/renderer.d.ts.map +1 -1
  224. package/dist/site/renderer.js +118 -28
  225. package/dist/site/terrain-drape.d.ts +91 -0
  226. package/dist/site/terrain-drape.d.ts.map +1 -0
  227. package/dist/site/terrain-drape.js +205 -0
  228. package/dist/site/terrain-geometry.d.ts +131 -0
  229. package/dist/site/terrain-geometry.d.ts.map +1 -0
  230. package/dist/site/terrain-geometry.js +259 -0
  231. package/dist/site/terrain-mesh.d.ts +49 -0
  232. package/dist/site/terrain-mesh.d.ts.map +1 -0
  233. package/dist/site/terrain-mesh.js +122 -0
  234. package/dist/site/terrain-renderer.d.ts +28 -0
  235. package/dist/site/terrain-renderer.d.ts.map +1 -0
  236. package/dist/site/terrain-renderer.js +69 -0
  237. package/dist/skylight/definition.d.ts.map +1 -1
  238. package/dist/skylight/definition.js +1 -0
  239. package/dist/skylight/tool.d.ts.map +1 -1
  240. package/dist/skylight/tool.js +16 -1
  241. package/dist/slab/definition.d.ts.map +1 -1
  242. package/dist/slab/definition.js +87 -10
  243. package/dist/slab/elevation-limit.d.ts +43 -0
  244. package/dist/slab/elevation-limit.d.ts.map +1 -0
  245. package/dist/slab/elevation-limit.js +124 -0
  246. package/dist/slab/floorplan-affordances.d.ts +16 -0
  247. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  248. package/dist/slab/geometry.d.ts.map +1 -1
  249. package/dist/slab/geometry.js +98 -5
  250. package/dist/slab/panel.d.ts.map +1 -1
  251. package/dist/slab/panel.js +82 -4
  252. package/dist/slab/parametrics.d.ts +1 -1
  253. package/dist/slab/parametrics.d.ts.map +1 -1
  254. package/dist/slab/parametrics.js +13 -1
  255. package/dist/slab/placement-ownership.d.ts +3 -0
  256. package/dist/slab/placement-ownership.d.ts.map +1 -0
  257. package/dist/slab/placement-ownership.js +3 -0
  258. package/dist/slab/quick-measurement.d.ts.map +1 -1
  259. package/dist/slab/quick-measurement.js +3 -2
  260. package/dist/slab/system.d.ts.map +1 -1
  261. package/dist/slab/system.js +14 -4
  262. package/dist/slab/tool.d.ts.map +1 -1
  263. package/dist/slab/tool.js +81 -23
  264. package/dist/solar-panel/definition.d.ts.map +1 -1
  265. package/dist/solar-panel/definition.js +1 -0
  266. package/dist/solar-panel/tool.d.ts.map +1 -1
  267. package/dist/solar-panel/tool.js +17 -1
  268. package/dist/spawn/definition.d.ts.map +1 -1
  269. package/dist/spawn/definition.js +1 -0
  270. package/dist/spawn/floorplan-affordances.d.ts.map +1 -1
  271. package/dist/spawn/floorplan-affordances.js +7 -4
  272. package/dist/spawn/floorplan-move.d.ts.map +1 -1
  273. package/dist/spawn/floorplan-move.js +8 -6
  274. package/dist/spawn/renderer.d.ts +4 -0
  275. package/dist/spawn/renderer.d.ts.map +1 -1
  276. package/dist/spawn/renderer.js +32 -18
  277. package/dist/spawn/tool.d.ts +2 -2
  278. package/dist/spawn/tool.d.ts.map +1 -1
  279. package/dist/spawn/tool.js +78 -11
  280. package/dist/stair/definition.d.ts.map +1 -1
  281. package/dist/stair/definition.js +15 -7
  282. package/dist/stair/destination.d.ts +16 -0
  283. package/dist/stair/destination.d.ts.map +1 -0
  284. package/dist/stair/destination.js +24 -0
  285. package/dist/stair/documentation.d.ts +8 -0
  286. package/dist/stair/documentation.d.ts.map +1 -0
  287. package/dist/stair/documentation.js +245 -0
  288. package/dist/stair/floor-stack.d.ts.map +1 -1
  289. package/dist/stair/floor-stack.js +38 -0
  290. package/dist/stair/floorplan-affordances.d.ts.map +1 -1
  291. package/dist/stair/floorplan-affordances.js +28 -9
  292. package/dist/stair/floorplan-move.d.ts +3 -5
  293. package/dist/stair/floorplan-move.d.ts.map +1 -1
  294. package/dist/stair/floorplan-move.js +14 -16
  295. package/dist/stair/floorplan.d.ts.map +1 -1
  296. package/dist/stair/floorplan.js +27 -14
  297. package/dist/stair/panel.d.ts.map +1 -1
  298. package/dist/stair/panel.js +35 -2
  299. package/dist/stair/renderer.d.ts.map +1 -1
  300. package/dist/stair/renderer.js +4 -3
  301. package/dist/structural-grid/coordination.d.ts +16 -0
  302. package/dist/structural-grid/coordination.d.ts.map +1 -0
  303. package/dist/structural-grid/coordination.js +105 -0
  304. package/dist/structural-grid/definition.d.ts +4 -0
  305. package/dist/structural-grid/definition.d.ts.map +1 -0
  306. package/dist/structural-grid/definition.js +51 -0
  307. package/dist/structural-grid/floorplan-tool.d.ts +16 -0
  308. package/dist/structural-grid/floorplan-tool.d.ts.map +1 -0
  309. package/dist/structural-grid/floorplan-tool.js +183 -0
  310. package/dist/structural-grid/floorplan.d.ts +3 -0
  311. package/dist/structural-grid/floorplan.d.ts.map +1 -0
  312. package/dist/structural-grid/floorplan.js +61 -0
  313. package/dist/structural-grid/index.d.ts +2 -0
  314. package/dist/structural-grid/index.d.ts.map +1 -0
  315. package/dist/structural-grid/index.js +1 -0
  316. package/dist/structural-grid/schema.d.ts +2 -0
  317. package/dist/structural-grid/schema.d.ts.map +1 -0
  318. package/dist/structural-grid/schema.js +1 -0
  319. package/dist/wall/construction-dimensions.d.ts +32 -0
  320. package/dist/wall/construction-dimensions.d.ts.map +1 -0
  321. package/dist/wall/construction-dimensions.js +1031 -0
  322. package/dist/wall/contextual-dimensions.d.ts +13 -0
  323. package/dist/wall/contextual-dimensions.d.ts.map +1 -0
  324. package/dist/wall/contextual-dimensions.js +221 -0
  325. package/dist/wall/definition.d.ts.map +1 -1
  326. package/dist/wall/definition.js +20 -1
  327. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  328. package/dist/wall/floorplan-affordances.js +23 -8
  329. package/dist/wall/floorplan-overrides.d.ts +9 -6
  330. package/dist/wall/floorplan-overrides.d.ts.map +1 -1
  331. package/dist/wall/floorplan-overrides.js +20 -11
  332. package/dist/wall/floorplan.d.ts +12 -3
  333. package/dist/wall/floorplan.d.ts.map +1 -1
  334. package/dist/wall/floorplan.js +121 -79
  335. package/dist/wall/measurement.d.ts.map +1 -1
  336. package/dist/wall/measurement.js +17 -4
  337. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  338. package/dist/wall/move-endpoint-tool.js +74 -27
  339. package/dist/wall/move-shared.d.ts.map +1 -1
  340. package/dist/wall/move-shared.js +3 -2
  341. package/dist/wall/move-tool.d.ts.map +1 -1
  342. package/dist/wall/move-tool.js +15 -3
  343. package/dist/wall/paint.d.ts.map +1 -1
  344. package/dist/wall/paint.js +10 -6
  345. package/dist/wall/panel.d.ts.map +1 -1
  346. package/dist/wall/panel.js +32 -5
  347. package/dist/wall/parametrics.d.ts.map +1 -1
  348. package/dist/wall/parametrics.js +2 -0
  349. package/dist/wall/preview.d.ts +8 -0
  350. package/dist/wall/preview.d.ts.map +1 -0
  351. package/dist/wall/preview.js +39 -0
  352. package/dist/wall/quick-measurement.d.ts.map +1 -1
  353. package/dist/wall/quick-measurement.js +3 -2
  354. package/dist/wall/renderer.d.ts.map +1 -1
  355. package/dist/wall/renderer.js +7 -5
  356. package/dist/wall/system.d.ts +1 -1
  357. package/dist/wall/system.d.ts.map +1 -1
  358. package/dist/wall/system.js +37 -2
  359. package/dist/wall/tool.d.ts.map +1 -1
  360. package/dist/wall/tool.js +148 -96
  361. package/dist/wall/treatment-level-data.d.ts +14 -0
  362. package/dist/wall/treatment-level-data.d.ts.map +1 -0
  363. package/dist/wall/treatment-level-data.js +31 -0
  364. package/dist/wall/treatments.d.ts +8 -2
  365. package/dist/wall/treatments.d.ts.map +1 -1
  366. package/dist/wall/treatments.js +58 -15
  367. package/dist/window/contextual-dimensions.d.ts +3 -0
  368. package/dist/window/contextual-dimensions.d.ts.map +1 -0
  369. package/dist/window/contextual-dimensions.js +7 -0
  370. package/dist/window/definition.d.ts.map +1 -1
  371. package/dist/window/definition.js +15 -10
  372. package/dist/window/floorplan-affordances.d.ts +2 -5
  373. package/dist/window/floorplan-affordances.d.ts.map +1 -1
  374. package/dist/window/floorplan-affordances.js +9 -15
  375. package/dist/window/floorplan-move.d.ts.map +1 -1
  376. package/dist/window/floorplan-move.js +1 -1
  377. package/dist/window/floorplan.d.ts.map +1 -1
  378. package/dist/window/floorplan.js +7 -1
  379. package/dist/window/move-tool.d.ts.map +1 -1
  380. package/dist/window/move-tool.js +3 -3
  381. package/dist/window/panel.d.ts.map +1 -1
  382. package/dist/window/panel.js +4 -1
  383. package/dist/window/schema.d.ts +1 -1
  384. package/dist/window/schema.d.ts.map +1 -1
  385. package/dist/window/schema.js +1 -1
  386. package/dist/window/tool.d.ts.map +1 -1
  387. package/dist/window/tool.js +64 -7
  388. package/dist/window/window-math.d.ts +7 -3
  389. package/dist/window/window-math.d.ts.map +1 -1
  390. package/dist/window/window-math.js +8 -3
  391. package/dist/zone/contextual-dimensions.d.ts +3 -0
  392. package/dist/zone/contextual-dimensions.d.ts.map +1 -0
  393. package/dist/zone/contextual-dimensions.js +43 -0
  394. package/dist/zone/definition.d.ts.map +1 -1
  395. package/dist/zone/definition.js +9 -1
  396. package/dist/zone/floorplan-affordances.d.ts +36 -0
  397. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  398. package/dist/zone/floorplan.d.ts.map +1 -1
  399. package/dist/zone/floorplan.js +59 -3
  400. package/dist/zone/quantities-panel.d.ts.map +1 -1
  401. package/dist/zone/quantities-panel.js +48 -4
  402. package/dist/zone/room-clear-dimensions.d.ts +3 -0
  403. package/dist/zone/room-clear-dimensions.d.ts.map +1 -0
  404. package/dist/zone/room-clear-dimensions.js +406 -0
  405. package/dist/zone/room-documentation.d.ts +11 -0
  406. package/dist/zone/room-documentation.d.ts.map +1 -0
  407. package/dist/zone/room-documentation.js +97 -0
  408. package/package.json +7 -7
package/dist/wall/tool.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { calculateLevelMiters, collectAlignmentAnchors, emitter, getWallMiterBoundaryPoints, resolveAlignment, resolveBuildingForLevel, useScene, wallClosesRoom, } from '@pascal-app/core';
3
- import { CursorSphere, chainEndJoinsExistingWall, createWallOnCurrentLevel, EDITOR_LAYER, formatAngleRadians, formatLinearMeasurement, getAngleArcToSegmentReference, getAngleToSegmentReference, getSegmentAngleReferenceAtPoint, isAlignmentGuideActive, isAngleSnapActive, isMagneticSnapActive, markToolCancelConsumed, snapWallDraftPointDetailed, triggerSFX, useAlignmentGuides, useEditor, useSegmentDraftChain, useWallSnapIndicator, WALL_CONNECT_SNAP_RADIUS, WALL_JOIN_SNAP_RADIUS, } from '@pascal-app/editor';
2
+ import { calculateLevelMiters, collectAlignmentAnchors, DEFAULT_LEVEL_HEIGHT, emitter, getWallMiterBoundaryPoints, resolveAlignment, resolveBuildingForLevel, sceneRegistry, useScene, wallClosesRoom, } from '@pascal-app/core';
3
+ import { CursorSphere, chainEndJoinsExistingWall, clearPlacementSurface, createWallOnCurrentLevel, EDITOR_LAYER, formatAngleRadians, formatLinearMeasurement, getAngleArcToSegmentReference, getAngleToSegmentReference, getSegmentAngleReferenceAtPoint, isAlignmentGuideActive, isAngleSnapActive, isMagneticSnapActive, markToolCancelConsumed, publishHorizontalConstructionPlane, publishPlacementSurface, resampleTerrainConstructionPlane, resolveEventConstructionPlane, resolvePointerSupportSurface, snapWallDraftPointDetailed, triggerSFX, useAlignmentGuides, useEditor, useFloorplanDraftPreview, useSegmentDraftChain, useWallSnapIndicator, WALL_CONNECT_SNAP_RADIUS, WALL_JOIN_SNAP_RADIUS, } from '@pascal-app/editor';
4
4
  import { getSceneTheme, useViewer } from '@pascal-app/viewer';
5
- import { Html } from '@react-three/drei';
6
- import { useEffect, useMemo, useRef, useState } from 'react';
7
- import { BoxGeometry, BufferGeometry, DoubleSide, Vector3 } from 'three';
5
+ import { useThree } from '@react-three/fiber';
6
+ import { useEffect, useRef, useState } from 'react';
7
+ import { BoxGeometry, DoubleSide, Vector3 } from 'three';
8
+ import { DraftAngleArc, DraftAxisGuides, DraftMeasurementLabel, getNearestAxisAngleLabel, } from '../shared/draft-axis-guides';
8
9
  /**
9
10
  * Phase 5 Stage D — wall placement tool (kind-owned).
10
11
  *
@@ -18,7 +19,6 @@ import { BoxGeometry, BufferGeometry, DoubleSide, Vector3 } from 'three';
18
19
  *
19
20
  * Mounted via `def.tool` from `wall/definition.ts`.
20
21
  */
21
- const WALL_HEIGHT = 2.5;
22
22
  const DRAFT_WALL_THICKNESS = 0.1;
23
23
  /** Figma-style alignment-snap threshold (meters), matching the move tools. */
24
24
  const ALIGNMENT_THRESHOLD_M = 0.08;
@@ -29,19 +29,12 @@ const DRAFT_ANGLE_LABEL_Y_OFFSET = 0.08;
29
29
  const DRAFT_ANGLE_ARC_Y_OFFSET = 0.012;
30
30
  const DRAFT_ANGLE_ARC_MIN_RADIUS = 0.32;
31
31
  const DRAFT_ANGLE_ARC_MAX_RADIUS = 0.72;
32
- const DRAFT_ANGLE_ARC_SEGMENTS = 24;
33
- const DRAFT_AXIS_GUIDE_LENGTH = 2000;
34
- const DRAFT_AXIS_GUIDE_WIDTH = 0.035;
35
- const DRAFT_AXIS_GUIDE_HEIGHT = 0.004;
36
- const DRAFT_AXIS_GUIDE_Y_OFFSET = 0.026;
37
- const DRAFT_AXIS_ANGLE_ARC_Y_OFFSET = 0.05;
38
- const DRAFT_AXIS_ANGLE_LABEL_Y_OFFSET = 0.16;
39
- const DRAFT_AXIS_ANGLE_ARC_MIN_RADIUS = 0.36;
40
- const DRAFT_AXIS_ANGLE_ARC_MAX_RADIUS = 0.82;
41
- const AXIS_ANGLE_REFERENCES = [
42
- { vector: [1, 0], orientation: 'axis' },
43
- { vector: [0, 1], orientation: 'axis' },
44
- ];
32
+ // Grid-plane surface publish (pointer-decided): scratch + constant normal so
33
+ // per-move publishes don't allocate.
34
+ const SURFACE_UP = new Vector3(0, 1, 0);
35
+ const surfacePointScratch = new Vector3();
36
+ const wallSurfaceWorldScratch = new Vector3();
37
+ const wallSurfaceLocalScratch = new Vector3();
45
38
  function clamp(value, min, max) {
46
39
  return Math.min(max, Math.max(min, value));
47
40
  }
@@ -58,43 +51,6 @@ function isWithinWallJoinSnapRadius(point, vertex) {
58
51
  const dz = point[1] - vertex.z;
59
52
  return dx * dx + dz * dz <= WALL_JOIN_SNAP_RADIUS * WALL_JOIN_SNAP_RADIUS;
60
53
  }
61
- function getNearestAxisAngleLabel(start, end, y) {
62
- const dx = end[0] - start[0];
63
- const dz = end[1] - start[1];
64
- const length = Math.hypot(dx, dz);
65
- if (length < 0.01)
66
- return null;
67
- const draftVector = [dx, dz];
68
- const axisCandidates = [];
69
- for (const reference of AXIS_ANGLE_REFERENCES) {
70
- const angle = getAngleToSegmentReference(draftVector, reference);
71
- const arc = getAngleArcToSegmentReference(draftVector, reference);
72
- if (!(angle === null || arc === null)) {
73
- axisCandidates.push({ angle, arc });
74
- }
75
- }
76
- const nearestAxisAngle = axisCandidates.sort((a, b) => a.angle - b.angle)[0];
77
- if (!nearestAxisAngle)
78
- return null;
79
- const radius = clamp(length * 0.22, DRAFT_AXIS_ANGLE_ARC_MIN_RADIUS, DRAFT_AXIS_ANGLE_ARC_MAX_RADIUS);
80
- const { angle, arc } = nearestAxisAngle;
81
- return {
82
- id: 'axis',
83
- label: formatAngleRadians(angle),
84
- position: [
85
- start[0] + Math.cos(arc.midAngle) * (radius + 0.16),
86
- y + DRAFT_AXIS_ANGLE_LABEL_Y_OFFSET,
87
- start[1] + Math.sin(arc.midAngle) * (radius + 0.16),
88
- ],
89
- arc: {
90
- center: start,
91
- radius,
92
- startAngle: arc.startAngle,
93
- endAngle: arc.endAngle,
94
- y: y + DRAFT_AXIS_ANGLE_ARC_Y_OFFSET,
95
- },
96
- };
97
- }
98
54
  function toWallPlanPoint(point) {
99
55
  return [point.x, point.y];
100
56
  }
@@ -340,13 +296,23 @@ function getBelowLevelWalls() {
340
296
  export const WallTool = () => {
341
297
  const unit = useViewer((state) => state.unit);
342
298
  const isDark = useViewer((state) => getSceneTheme(state.sceneTheme).appearance === 'dark');
299
+ const activeLevelId = useViewer((state) => state.selection.levelId);
300
+ const activeLevelHeight = useScene((state) => {
301
+ const level = activeLevelId ? state.nodes[activeLevelId] : undefined;
302
+ return level?.type === 'level' ? (level.height ?? DEFAULT_LEVEL_HEIGHT) : DEFAULT_LEVEL_HEIGHT;
303
+ });
343
304
  // A placed wall preset seeds `toolDefaults.wall` (height / thickness …)
344
305
  // before the tool mounts, so the draft preview is drawn at the preset's
345
306
  // dimensions rather than the generic fallbacks — matching the wall that
346
307
  // will be created. Read through refs so the live event handlers below see
347
308
  // the latest values without re-subscribing.
348
309
  const wallDefaults = useEditor((s) => s.toolDefaults.wall);
349
- const previewHeight = typeof wallDefaults?.height === 'number' ? wallDefaults.height : WALL_HEIGHT;
310
+ // Camera for the pointer-support resolution (deck top vs floor) — read
311
+ // through a ref so the event handlers below see the live camera.
312
+ const camera = useThree((state) => state.camera);
313
+ const cameraRef = useRef(camera);
314
+ cameraRef.current = camera;
315
+ const previewHeight = typeof wallDefaults?.height === 'number' ? wallDefaults.height : activeLevelHeight;
350
316
  const previewThickness = typeof wallDefaults?.thickness === 'number' ? wallDefaults.thickness : DRAFT_WALL_THICKNESS;
351
317
  const previewHeightRef = useRef(previewHeight);
352
318
  previewHeightRef.current = previewHeight;
@@ -361,6 +327,7 @@ export const WallTool = () => {
361
327
  // the "segment tees into an existing wall" chain-termination test, so
362
328
  // snapping onto the chain's own segments never reads as a join.
363
329
  const chainWallIds = useRef([]);
330
+ const constructionPlane = useRef(null);
364
331
  const buildingState = useRef(0);
365
332
  const [draftMeasurement, setDraftMeasurement] = useState(null);
366
333
  const [axisGuide, setAxisGuide] = useState(null);
@@ -409,10 +376,70 @@ export const WallTool = () => {
409
376
  ? [point[0] + ar.snap.dx, point[1] + ar.snap.dz]
410
377
  : point;
411
378
  };
379
+ // The walking surface the pointer actually aims at (deck top when over
380
+ // the deck, floor/ground underneath it) — only for genuine 3D pointer
381
+ // events. The 2D floor plan emits synthetic grid events with no camera
382
+ // ray behind them; those keep the uncapped max election and leave the
383
+ // grid plane alone.
384
+ const pointedSurfaceFor = (event) => event.nativeEvent?.target instanceof HTMLCanvasElement
385
+ ? resolvePointerSupportSurface(cameraRef.current, event.position, {
386
+ includeNodeTopSurfaces: true,
387
+ })
388
+ : null;
389
+ const snappedWallConstructionPlane = (targetWallIds, walls) => {
390
+ const activeWallIds = new Set(walls.map((wall) => wall.id));
391
+ const targetIds = targetWallIds.filter((id) => activeWallIds.has(id));
392
+ if (targetIds.length === 0)
393
+ return null;
394
+ const buildingId = useViewer.getState().selection.buildingId;
395
+ const buildingMesh = buildingId ? sceneRegistry.nodes.get(buildingId) : undefined;
396
+ const currentLevelId = useViewer.getState().selection.levelId;
397
+ const levelMesh = currentLevelId
398
+ ? sceneRegistry.nodes.get(currentLevelId)
399
+ : undefined;
400
+ let resolved = null;
401
+ for (const id of targetIds) {
402
+ const targetWall = walls.find((wall) => wall.id === id);
403
+ if (!targetWall)
404
+ continue;
405
+ const wallMesh = sceneRegistry.nodes.get(id);
406
+ if (!wallMesh)
407
+ continue;
408
+ wallMesh.getWorldPosition(wallSurfaceWorldScratch);
409
+ const worldY = wallSurfaceWorldScratch.y;
410
+ wallSurfaceLocalScratch.copy(wallSurfaceWorldScratch);
411
+ if (buildingMesh)
412
+ buildingMesh.worldToLocal(wallSurfaceLocalScratch);
413
+ const localY = wallSurfaceLocalScratch.y;
414
+ wallSurfaceLocalScratch.copy(wallSurfaceWorldScratch);
415
+ if (levelMesh)
416
+ levelMesh.worldToLocal(wallSurfaceLocalScratch);
417
+ const elevation = wallSurfaceLocalScratch.y;
418
+ if (resolved &&
419
+ (Math.abs(resolved.worldY - worldY) > 1e-4 ||
420
+ Math.abs((resolved.elevation ?? elevation) - elevation) > 1e-4 ||
421
+ resolved.supportSlabId !== (targetWall.supportSlabId ?? null))) {
422
+ // An ambiguous junction at different elevations transfers no plane.
423
+ return null;
424
+ }
425
+ resolved = {
426
+ localY,
427
+ worldY,
428
+ elevation,
429
+ supportSlabId: targetWall.supportSlabId ?? null,
430
+ sourceNodeId: targetWall.id,
431
+ };
432
+ }
433
+ return resolved;
434
+ };
412
435
  const stopDrafting = () => {
413
436
  buildingState.current = 0;
437
+ constructionPlane.current = null;
414
438
  chainFirstVertex.current = null;
415
439
  chainWallIds.current = [];
440
+ const draftPreview = useFloorplanDraftPreview.getState();
441
+ draftPreview.setWallDraftStart(null);
442
+ draftPreview.setWallDraftEnd(null);
416
443
  if (wallPreviewRef.current) {
417
444
  wallPreviewRef.current.visible = false;
418
445
  }
@@ -421,16 +448,31 @@ export const WallTool = () => {
421
448
  useAlignmentGuides.getState().clear();
422
449
  useWallSnapIndicator.getState().clear();
423
450
  useSegmentDraftChain.getState().clear('wall');
451
+ clearPlacementSurface();
424
452
  };
425
453
  const onGridMove = (event) => {
426
454
  if (!(cursorRef.current && wallPreviewRef.current))
427
455
  return;
456
+ // Ride the grid event plane on the pointed surface: aiming at an
457
+ // elevated deck lifts the plane to the deck top, so the draft's XZ
458
+ // lands where the cursor points and the preview/cursor Y
459
+ // (`event.localPosition[1]`) sits at the base the committed wall
460
+ // will elect. Aiming past the deck edge drops it back to the floor.
461
+ const pointed = buildingState.current === 0 ? pointedSurfaceFor(event) : null;
462
+ if (constructionPlane.current) {
463
+ publishHorizontalConstructionPlane(event, constructionPlane.current);
464
+ }
465
+ else if (pointed) {
466
+ publishPlacementSurface(surfacePointScratch.set(event.position[0], pointed.worldY, event.position[2]), SURFACE_UP);
467
+ }
428
468
  const walls = getCurrentLevelWalls();
429
469
  // Add walls on the floor below as extra snap references so the new wall
430
470
  // can align with the level beneath it. Kept separate from `walls` so the
431
471
  // measurement HUD only reports against the active level.
432
472
  const snapWalls = [...walls, ...getBelowLevelWalls()];
433
- const localPoint = [event.localPosition[0], event.localPosition[2]];
473
+ const localPoint = pointed?.localPoint
474
+ ? [pointed.localPoint[0], pointed.localPoint[2]]
475
+ : [event.localPosition[0], event.localPosition[2]];
434
476
  // Snapping is governed entirely by the snapping mode (grid / lines /
435
477
  // angles / off). `'off'` is the bypass — there is no Shift hold-to-bypass.
436
478
  const angleLocked = buildingState.current === 1 && isAngleSnapActive();
@@ -451,10 +493,15 @@ export const WallTool = () => {
451
493
  : null);
452
494
  if (buildingState.current === 1) {
453
495
  const snappedLocal = gridPosition;
454
- endingPoint.current.set(snappedLocal[0], event.localPosition[1], snappedLocal[1]);
496
+ const draftY = constructionPlane.current?.localY ?? event.localPosition[1];
497
+ endingPoint.current.set(snappedLocal[0], draftY, snappedLocal[1]);
498
+ const draftPreview = useFloorplanDraftPreview.getState();
499
+ draftPreview.setWallDraftStart([startingPoint.current.x, startingPoint.current.z]);
500
+ draftPreview.setWallDraftEnd(snappedLocal);
455
501
  cursorRef.current.position.copy(endingPoint.current);
456
502
  setAxisGuide({
457
503
  origin: [startingPoint.current.x, startingPoint.current.z],
504
+ endOrigin: snappedLocal,
458
505
  y: startingPoint.current.y,
459
506
  angleLabel: getNearestAxisAngleLabel([startingPoint.current.x, startingPoint.current.z], snappedLocal, startingPoint.current.y),
460
507
  });
@@ -468,7 +515,8 @@ export const WallTool = () => {
468
515
  setDraftMeasurement(getDraftMeasurementState([startingPoint.current.x, startingPoint.current.z], snappedLocal, walls, unit, startingPoint.current.y, previewHeightRef.current));
469
516
  }
470
517
  else {
471
- cursorRef.current.position.set(gridPosition[0], event.localPosition[1], gridPosition[1]);
518
+ const hoverPlane = resampleTerrainConstructionPlane(resolveEventConstructionPlane(event, pointed), gridPosition);
519
+ cursorRef.current.position.set(gridPosition[0], hoverPlane.localY, gridPosition[1]);
472
520
  setDraftMeasurement(null);
473
521
  setAxisGuide(null);
474
522
  }
@@ -482,21 +530,37 @@ export const WallTool = () => {
482
530
  }
483
531
  const walls = getCurrentLevelWalls();
484
532
  const snapWalls = [...walls, ...getBelowLevelWalls()];
485
- const localClick = [event.localPosition[0], event.localPosition[2]];
533
+ const pointed = buildingState.current === 0 ? pointedSurfaceFor(event) : null;
534
+ const localClick = pointed?.localPoint
535
+ ? [pointed.localPoint[0], pointed.localPoint[2]]
536
+ : [event.localPosition[0], event.localPosition[2]];
486
537
  if (buildingState.current === 0) {
487
- const snappedStart = alignPoint(snapWallDraftPointDetailed({
538
+ const snapResult = snapWallDraftPointDetailed({
488
539
  point: localClick,
489
540
  walls: snapWalls,
490
541
  magnetic: isMagneticSnapActive(),
491
- }).point);
542
+ });
543
+ const snappedStart = alignPoint(snapResult.point);
544
+ const resolvedPlane = (pointed?.sourceNodeId
545
+ ? resolveEventConstructionPlane(event, pointed)
546
+ : pointMatches(snappedStart, snapResult.point)
547
+ ? snappedWallConstructionPlane(snapResult.targetWallIds, walls)
548
+ : null) ?? resolveEventConstructionPlane(event, pointed);
549
+ const plane = resampleTerrainConstructionPlane(resolvedPlane, snappedStart);
550
+ constructionPlane.current = plane;
551
+ publishHorizontalConstructionPlane(event, plane);
492
552
  gridPosition = snappedStart;
493
- startingPoint.current.set(snappedStart[0], event.localPosition[1], snappedStart[1]);
553
+ startingPoint.current.set(snappedStart[0], plane.localY, snappedStart[1]);
494
554
  chainFirstVertex.current = startingPoint.current.clone();
495
555
  endingPoint.current.copy(startingPoint.current);
496
556
  buildingState.current = 1;
557
+ const draftPreview = useFloorplanDraftPreview.getState();
558
+ draftPreview.setWallDraftStart(snappedStart);
559
+ draftPreview.setWallDraftEnd(snappedStart);
497
560
  setAxisGuide({
498
561
  origin: snappedStart,
499
- y: event.localPosition[1],
562
+ endOrigin: null,
563
+ y: plane.localY,
500
564
  angleLabel: null,
501
565
  });
502
566
  triggerSFX('sfx:structure-build-start');
@@ -523,7 +587,12 @@ export const WallTool = () => {
523
587
  if (dx * dx + dz * dz < 0.01 * 0.01)
524
588
  return;
525
589
  // Both start and end are building-local ✓
526
- const createdWall = createWallOnCurrentLevel([startingPoint.current.x, startingPoint.current.z], snappedEnd);
590
+ const createdWall = createWallOnCurrentLevel([startingPoint.current.x, startingPoint.current.z], snappedEnd, {
591
+ supportCap: constructionPlane.current?.elevation ?? null,
592
+ preferredSupportSlabId: constructionPlane.current?.supportSlabId ?? null,
593
+ constructionElevation: constructionPlane.current?.elevation ?? null,
594
+ constructionHeight: previewHeightRef.current,
595
+ });
527
596
  if (!createdWall)
528
597
  return;
529
598
  chainWallIds.current.push(createdWall.id);
@@ -558,13 +627,19 @@ export const WallTool = () => {
558
627
  // chains its next segment from the same point (its own snap
559
628
  // pipeline can resolve a slightly different endpoint).
560
629
  useSegmentDraftChain.getState().setChainStart('wall', [nextStart[0], nextStart[1]]);
561
- startingPoint.current.set(nextStart[0], event.localPosition[1], nextStart[1]);
630
+ const draftY = constructionPlane.current?.localY ?? event.localPosition[1];
631
+ startingPoint.current.set(nextStart[0], draftY, nextStart[1]);
562
632
  endingPoint.current.copy(startingPoint.current);
633
+ const draftPreview = useFloorplanDraftPreview.getState();
634
+ draftPreview.setWallDraftEnd(null);
635
+ draftPreview.setWallDraftStart(nextStart);
636
+ draftPreview.setWallDraftEnd(nextStart);
563
637
  cursorRef.current?.position.copy(startingPoint.current);
564
638
  buildingState.current = 1;
565
639
  setAxisGuide({
566
640
  origin: nextStart,
567
- y: event.localPosition[1],
641
+ endOrigin: null,
642
+ y: draftY,
568
643
  angleLabel: null,
569
644
  });
570
645
  // Hide the preview until the next `onGridMove` writes the
@@ -591,38 +666,15 @@ export const WallTool = () => {
591
666
  emitter.off('grid:move', onGridMove);
592
667
  emitter.off('grid:click', onGridClick);
593
668
  emitter.off('tool:cancel', onCancel);
669
+ clearPlacementSurface();
594
670
  useAlignmentGuides.getState().clear();
595
671
  useWallSnapIndicator.getState().clear();
596
672
  useSegmentDraftChain.getState().clear('wall');
673
+ const draftPreview = useFloorplanDraftPreview.getState();
674
+ draftPreview.setWallDraftStart(null);
675
+ draftPreview.setWallDraftEnd(null);
597
676
  };
598
677
  }, [unit]);
599
- return (_jsxs("group", { children: [_jsx(WallAxisGuides, { guide: axisGuide, labelColor: measurementColor, labelShadowColor: measurementShadowColor }), _jsx(CursorSphere, { height: previewHeight, ref: cursorRef }), _jsxs("mesh", { layers: EDITOR_LAYER, ref: wallPreviewRef, renderOrder: 1, visible: false, children: [_jsx("shapeGeometry", {}), _jsx("meshBasicMaterial", { color: "#818cf8", depthTest: false, depthWrite: false, opacity: 0.5, side: DoubleSide, transparent: true })] }), draftMeasurement && (_jsxs(_Fragment, { children: [_jsx(DraftMeasurementLabel, { color: measurementColor, label: draftMeasurement.lengthLabel, position: draftMeasurement.lengthPosition, shadowColor: measurementShadowColor }), draftMeasurement.angleLabels.map((angleLabel) => (_jsxs("group", { children: [_jsx(DraftAngleArc, { arc: angleLabel.arc, color: measurementColor }), _jsx(DraftMeasurementLabel, { color: measurementColor, label: angleLabel.label, position: angleLabel.position, shadowColor: measurementShadowColor })] }, angleLabel.id)))] }))] }));
678
+ return (_jsxs("group", { children: [_jsx(DraftAxisGuides, { guide: axisGuide, labelColor: measurementColor, labelShadowColor: measurementShadowColor }), _jsx(CursorSphere, { height: previewHeight, ref: cursorRef }), _jsxs("mesh", { layers: EDITOR_LAYER, ref: wallPreviewRef, renderOrder: 1, visible: false, children: [_jsx("shapeGeometry", {}), _jsx("meshBasicMaterial", { color: "#818cf8", depthTest: false, depthWrite: false, opacity: 0.5, side: DoubleSide, transparent: true })] }), draftMeasurement && (_jsxs(_Fragment, { children: [_jsx(DraftMeasurementLabel, { color: measurementColor, label: draftMeasurement.lengthLabel, position: draftMeasurement.lengthPosition, shadowColor: measurementShadowColor }), draftMeasurement.angleLabels.map((angleLabel) => (_jsxs("group", { children: [_jsx(DraftAngleArc, { arc: angleLabel.arc, color: measurementColor }), _jsx(DraftMeasurementLabel, { color: measurementColor, label: angleLabel.label, position: angleLabel.position, shadowColor: measurementShadowColor })] }, angleLabel.id)))] }))] }));
600
679
  };
601
- function WallAxisGuides({ guide, labelColor, labelShadowColor, }) {
602
- if (!guide)
603
- return null;
604
- const [x, z] = guide.origin;
605
- return (_jsxs(_Fragment, { children: [_jsxs("group", { position: [x, guide.y + DRAFT_AXIS_GUIDE_Y_OFFSET, z], children: [_jsx(WallAxisGuideLine, { axis: "x" }), _jsx(WallAxisGuideLine, { axis: "z" })] }), guide.angleLabel && (_jsxs(_Fragment, { children: [_jsx(DraftAngleArc, { arc: guide.angleLabel.arc, color: "#818cf8" }), _jsx(DraftMeasurementLabel, { color: labelColor, label: guide.angleLabel.label, position: guide.angleLabel.position, shadowColor: labelShadowColor })] }))] }));
606
- }
607
- function WallAxisGuideLine({ axis }) {
608
- return (_jsxs("mesh", { frustumCulled: false, layers: EDITOR_LAYER, renderOrder: 0, rotation: [0, axis === 'z' ? Math.PI / 2 : 0, 0], children: [_jsx("boxGeometry", { args: [DRAFT_AXIS_GUIDE_LENGTH, DRAFT_AXIS_GUIDE_HEIGHT, DRAFT_AXIS_GUIDE_WIDTH] }), _jsx("meshBasicMaterial", { color: "#818cf8", depthTest: false, depthWrite: false, opacity: 0.36, transparent: true })] }));
609
- }
610
- function DraftAngleArc({ arc, color }) {
611
- const geometry = useMemo(() => {
612
- const segmentCount = Math.max(8, Math.ceil((Math.abs(arc.endAngle - arc.startAngle) / Math.PI) * DRAFT_ANGLE_ARC_SEGMENTS));
613
- const points = Array.from({ length: segmentCount + 1 }, (_, index) => {
614
- const t = index / segmentCount;
615
- const angle = arc.startAngle + (arc.endAngle - arc.startAngle) * t;
616
- return new Vector3(arc.center[0] + Math.cos(angle) * arc.radius, arc.y, arc.center[1] + Math.sin(angle) * arc.radius);
617
- });
618
- return new BufferGeometry().setFromPoints(points);
619
- }, [arc]);
620
- return (_jsx("line", { frustumCulled: false, geometry: geometry, layers: EDITOR_LAYER, renderOrder: 2, children: _jsx("lineBasicNodeMaterial", { color: color, depthTest: false, depthWrite: false, linewidth: 2, opacity: 0.95, transparent: true }) }));
621
- }
622
- function DraftMeasurementLabel({ color, label, position, shadowColor, }) {
623
- return (_jsx(Html, { center: true, position: position, style: { pointerEvents: 'none', userSelect: 'none' }, zIndexRange: [100, 0], children: _jsx("div", { className: "whitespace-nowrap font-bold font-mono text-[15px]", style: {
624
- color,
625
- textShadow: `-1.5px -1.5px 0 ${shadowColor}, 1.5px -1.5px 0 ${shadowColor}, -1.5px 1.5px 0 ${shadowColor}, 1.5px 1.5px 0 ${shadowColor}, 0 0 4px ${shadowColor}, 0 0 4px ${shadowColor}`,
626
- }, children: label }) }));
627
- }
628
680
  export default WallTool;
@@ -0,0 +1,14 @@
1
+ import { type WallMiterData, type WallNode } from '@pascal-app/core';
2
+ export type WallTreatmentLevelData = {
3
+ walls: readonly WallNode[];
4
+ miterDataByProud: ReadonlyMap<number, WallMiterData>;
5
+ };
6
+ export declare function buildWallTreatmentLevelData(walls: readonly WallNode[], proudOffsets: readonly number[]): WallTreatmentLevelData;
7
+ export declare function treatmentMiterDataForProud(levelData: WallTreatmentLevelData, proud: number): WallMiterData | undefined;
8
+ type WallTreatmentLevelDataState = {
9
+ byLevelId: ReadonlyMap<string, WallTreatmentLevelData>;
10
+ setLevelData: (levelId: string, data: WallTreatmentLevelData) => void;
11
+ };
12
+ export declare const useWallTreatmentLevelData: import("zustand").UseBoundStore<import("zustand").StoreApi<WallTreatmentLevelDataState>>;
13
+ export {};
14
+ //# sourceMappingURL=treatment-level-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treatment-level-data.d.ts","sourceRoot":"","sources":["../../src/wall/treatment-level-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAA;AASzB,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IAC1B,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;CACrD,CAAA;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,SAAS,QAAQ,EAAE,EAC1B,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,sBAAsB,CAgBxB;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,sBAAsB,EACjC,KAAK,EAAE,MAAM,GACZ,aAAa,GAAG,SAAS,CAE3B;AAED,KAAK,2BAA2B,GAAG;IACjC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;IACtD,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAA;CACtE,CAAA;AAED,eAAO,MAAM,yBAAyB,0FAQnC,CAAA"}
@@ -0,0 +1,31 @@
1
+ import { calculateLevelMiters, getWallThickness, } from '@pascal-app/core';
2
+ import { create } from 'zustand';
3
+ const PROUD_KEY_PRECISION = 1e6;
4
+ function proudKey(proud) {
5
+ return Math.round(proud * PROUD_KEY_PRECISION) / PROUD_KEY_PRECISION;
6
+ }
7
+ export function buildWallTreatmentLevelData(walls, proudOffsets) {
8
+ const uniqueProudOffsets = new Set([0, ...proudOffsets.map(proudKey)]);
9
+ const miterDataByProud = new Map();
10
+ for (const proud of uniqueProudOffsets) {
11
+ const adjustedWalls = proud === 0
12
+ ? [...walls]
13
+ : walls.map((wall) => ({
14
+ ...wall,
15
+ thickness: getWallThickness(wall) + proud * 2,
16
+ }));
17
+ miterDataByProud.set(proud, calculateLevelMiters(adjustedWalls));
18
+ }
19
+ return { walls, miterDataByProud };
20
+ }
21
+ export function treatmentMiterDataForProud(levelData, proud) {
22
+ return levelData.miterDataByProud.get(proudKey(proud));
23
+ }
24
+ export const useWallTreatmentLevelData = create((set) => ({
25
+ byLevelId: new Map(),
26
+ setLevelData: (levelId, data) => set((state) => {
27
+ const byLevelId = new Map(state.byLevelId);
28
+ byLevelId.set(levelId, data);
29
+ return { byLevelId };
30
+ }),
31
+ }));
@@ -1,14 +1,19 @@
1
- import { type SceneMaterial, type SceneMaterialId, type WallNode } from '@pascal-app/core';
1
+ import { type SceneMaterial, type SceneMaterialId, type WallNode, type WallTrimConfig } from '@pascal-app/core';
2
2
  import { type RenderShading } from '@pascal-app/viewer';
3
3
  import * as THREE from 'three';
4
+ import { type WallTreatmentLevelData } from './treatment-level-data';
4
5
  type OpeningLike = {
5
6
  type: string;
6
7
  width?: number;
7
8
  height?: number;
8
9
  position?: [number, number, number];
9
10
  };
11
+ type TrimKind = 'skirting' | 'crown' | 'chairRail';
12
+ type WallSide = 'interior' | 'exterior';
10
13
  type SceneMaterials = Record<SceneMaterialId, SceneMaterial>;
11
14
  type WallTreatmentSlotId = 'skirtingInterior' | 'skirtingExterior' | 'crownInterior' | 'crownExterior' | 'chairRailInterior' | 'chairRailExterior';
15
+ export declare function wallTreatmentProudOffsets(node: WallNode): number[];
16
+ export declare function buildTrimGeometry(node: WallNode, side: WallSide, trim: WallTrimConfig, kind: TrimKind, childrenNodes: OpeningLike[], levelData: WallTreatmentLevelData): THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap> | null;
12
17
  export declare function createWallExtraSlotMaterials(node: WallNode, shading: RenderShading, sceneMaterials: SceneMaterials): {
13
18
  skirtingInterior: THREE.Material<THREE.MaterialEventMap>;
14
19
  skirtingExterior: THREE.Material<THREE.MaterialEventMap>;
@@ -17,9 +22,10 @@ export declare function createWallExtraSlotMaterials(node: WallNode, shading: Re
17
22
  chairRailInterior: THREE.Material<THREE.MaterialEventMap>;
18
23
  chairRailExterior: THREE.Material<THREE.MaterialEventMap>;
19
24
  };
20
- export declare const WallTreatments: import("react").MemoExoticComponent<({ node, childrenNodes, materials, }: {
25
+ export declare const WallTreatments: import("react").MemoExoticComponent<({ node, childrenNodes, levelData, materials, }: {
21
26
  node: WallNode;
22
27
  childrenNodes: OpeningLike[];
28
+ levelData: WallTreatmentLevelData;
23
29
  materials: Record<WallTreatmentSlotId, THREE.Material>;
24
30
  }) => import("react").JSX.Element>;
25
31
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"treatments.d.ts","sourceRoot":"","sources":["../../src/wall/treatments.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,eAAe,EAKpB,KAAK,QAAQ,EAId,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,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;AAID,KAAK,cAAc,GAAG,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;AAE5D,KAAK,mBAAmB,GACpB,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,mBAAmB,CAAA;AA0dvB,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,EACtB,cAAc,EAAE,cAAc;;;;;;;EAU/B;AAED,eAAO,MAAM,cAAc,4EAIxB;IACD,IAAI,EAAE,QAAQ,CAAA;IACd,aAAa,EAAE,WAAW,EAAE,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAC,mBAAmB,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;CACvD,iCAmEC,CAAA"}
1
+ {"version":3,"file":"treatments.d.ts","sourceRoot":"","sources":["../../src/wall/treatments.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,eAAe,EAMpB,KAAK,QAAQ,EAEb,KAAK,cAAc,EAEpB,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,UAAU,GAAG,OAAO,GAAG,WAAW,CAAA;AAClD,KAAK,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAA;AACvC,KAAK,cAAc,GAAG,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;AAE5D,KAAK,mBAAmB,GACpB,kBAAkB,GAClB,kBAAkB,GAClB,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,mBAAmB,CAAA;AAmNvB,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAoBlE;AAuND,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,2FAsDlC;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,iCAmEC,CAAA"}
@@ -1,10 +1,12 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { getWallCurveFrameAt, getWallThickness, isCurvedWall, WALL_CHAIR_RAIL_DEFAULT, WALL_CROWN_DEFAULT, WALL_SKIRTING_DEFAULT, WALL_SURFACE_SLOT_DEFAULTS, } from '@pascal-app/core';
3
+ import { getWallCurveFrameAt, getWallMiterBoundaryPoints, getWallThickness, isCurvedWall, useScene, WALL_CHAIR_RAIL_DEFAULT, WALL_CROWN_DEFAULT, WALL_SKIRTING_DEFAULT, WALL_SURFACE_SLOT_DEFAULTS, } 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
+ import { resolveWallOpeningCeiling } from '../shared/wall-opening-ceiling';
9
+ import { treatmentMiterDataForProud } from './treatment-level-data';
8
10
  const CURVE_SEGMENTS = 24;
9
11
  const MIN_SLICE_PROUD = 0.0005;
10
12
  const EPS = 1e-6;
@@ -219,6 +221,27 @@ function resolveTrimProfile(kind, trim) {
219
221
  TRIM_PROFILES[kind][defaultProfile] ??
220
222
  TRIM_PROFILES[kind].flat);
221
223
  }
224
+ export function wallTreatmentProudOffsets(node) {
225
+ const offsets = new Set();
226
+ const configs = [
227
+ ['skirting', node.skirting],
228
+ ['crown', node.crown],
229
+ ['chairRail', node.chairRail],
230
+ ];
231
+ for (const [kind, rawConfig] of configs) {
232
+ const trim = { ...TRIM_KIND_CONFIG[kind].defaultConfig, ...(rawConfig ?? {}) };
233
+ if (!trim.enabled)
234
+ continue;
235
+ const profile = resolveTrimProfile(kind, trim);
236
+ if (!profile)
237
+ continue;
238
+ for (let index = 0; index < profile.samples; index += 1) {
239
+ const t = (index + 0.5) / profile.samples;
240
+ offsets.add(Math.max(MIN_SLICE_PROUD, trim.proud * profile.proudAt(t)));
241
+ }
242
+ }
243
+ return [...offsets];
244
+ }
222
245
  function resolveTreatmentSideSign(node, side) {
223
246
  if (side === 'interior') {
224
247
  if (node.frontSide === 'interior')
@@ -261,8 +284,24 @@ function buildSidePolyline(node, side, offset) {
261
284
  }
262
285
  return points;
263
286
  }
287
+ function buildMiteredSidePolyline(node, levelData, side, offset) {
288
+ if (isCurvedWall(node))
289
+ return buildSidePolyline(node, side, offset);
290
+ const sideSign = resolveTreatmentSideSign(node, side);
291
+ const toLocal = wallToLocalTransform(node);
292
+ const proud = offset - getWallThickness(node) / 2;
293
+ const boundarySource = treatmentMiterDataForProud(levelData, proud);
294
+ if (!boundarySource)
295
+ return buildSidePolyline(node, side, offset);
296
+ const boundary = getWallMiterBoundaryPoints({ ...node, thickness: offset * 2 }, boundarySource);
297
+ if (!boundary)
298
+ return buildSidePolyline(node, side, offset);
299
+ const start = sideSign > 0 ? boundary.startLeft : boundary.startRight;
300
+ const end = sideSign > 0 ? boundary.endLeft : boundary.endRight;
301
+ return [toLocal(start.x, start.y), toLocal(end.x, end.y)];
302
+ }
264
303
  function clipPolyline(points, x0, x1) {
265
- if (points.length < 2 || x1 - x0 <= EPS)
304
+ if (points.length < 2 || (x0 !== undefined && x1 !== undefined && x1 - x0 <= EPS))
266
305
  return [];
267
306
  const out = [];
268
307
  for (let index = 0; index < points.length - 1; index += 1) {
@@ -272,8 +311,9 @@ function clipPolyline(points, x0, x1) {
272
311
  continue;
273
312
  const minX = Math.min(a.x, b.x);
274
313
  const maxX = Math.max(a.x, b.x);
275
- if (maxX < x0 - EPS || minX > x1 + EPS)
314
+ if ((x0 !== undefined && maxX < x0 - EPS) || (x1 !== undefined && minX > x1 + EPS)) {
276
315
  continue;
316
+ }
277
317
  const pushPointAt = (x) => {
278
318
  if (Math.abs(b.x - a.x) <= EPS) {
279
319
  return { x, z: a.z };
@@ -284,8 +324,8 @@ function clipPolyline(points, x0, x1) {
284
324
  z: a.z + (b.z - a.z) * t,
285
325
  };
286
326
  };
287
- const start = minX < x0 ? pushPointAt(x0) : a;
288
- const end = maxX > x1 ? pushPointAt(x1) : b;
327
+ const start = x0 !== undefined && minX < x0 ? pushPointAt(x0) : a;
328
+ const end = x1 !== undefined && maxX > x1 ? pushPointAt(x1) : b;
289
329
  if (out.length === 0 ||
290
330
  Math.hypot(out[out.length - 1].x - start.x, out[out.length - 1].z - start.z) > EPS) {
291
331
  out.push(start);
@@ -396,8 +436,8 @@ function mergeGeometries(geometries) {
396
436
  return merged;
397
437
  return null;
398
438
  }
399
- function buildTrimGeometry(node, side, trim, kind, childrenNodes) {
400
- const wallHeight = node.height ?? 2.5;
439
+ export function buildTrimGeometry(node, side, trim, kind, childrenNodes, levelData) {
440
+ const wallHeight = resolveWallOpeningCeiling(node, useScene.getState().nodes);
401
441
  const height = trim.height;
402
442
  const yBottom = kind === 'crown'
403
443
  ? Math.max(0, wallHeight - height)
@@ -405,11 +445,12 @@ function buildTrimGeometry(node, side, trim, kind, childrenNodes) {
405
445
  ? Math.max(0, Math.min(wallHeight - height, trim.offsetY ?? WALL_CHAIR_RAIL_DEFAULT.offsetY ?? 0.9))
406
446
  : 0;
407
447
  const thickness = getWallThickness(node);
408
- const inner = buildSidePolyline(node, side, thickness / 2);
448
+ const inner = buildMiteredSidePolyline(node, levelData, side, thickness / 2);
409
449
  if (inner.length < 2)
410
450
  return null;
451
+ const wallLength = Math.hypot(node.end[0] - node.start[0], node.end[1] - node.start[1]);
411
452
  const openingRanges = trimOpeningRanges(node, childrenNodes, yBottom, height);
412
- const fullRanges = [[inner[0].x, inner[inner.length - 1].x]];
453
+ const fullRanges = [[0, wallLength]];
413
454
  const runs = subtractOpeningRanges(fullRanges, openingRanges);
414
455
  if (runs.length === 0)
415
456
  return null;
@@ -419,14 +460,16 @@ function buildTrimGeometry(node, side, trim, kind, childrenNodes) {
419
460
  return null;
420
461
  const sliceHeight = height / profile.samples;
421
462
  for (const [runStart, runEnd] of runs) {
422
- const innerRun = clipPolyline(inner, runStart, runEnd);
463
+ const clipStart = runStart > EPS ? runStart : undefined;
464
+ const clipEnd = runEnd < wallLength - EPS ? runEnd : undefined;
465
+ const innerRun = clipPolyline(inner, clipStart, clipEnd);
423
466
  if (innerRun.length < 2)
424
467
  continue;
425
468
  for (let index = 0; index < profile.samples; index += 1) {
426
469
  const t = (index + 0.5) / profile.samples;
427
470
  const proud = Math.max(MIN_SLICE_PROUD, trim.proud * profile.proudAt(t));
428
- const outerRun = buildSidePolyline(node, side, thickness / 2 + proud);
429
- const outerClipped = clipPolyline(outerRun, runStart, runEnd);
471
+ const outerRun = buildMiteredSidePolyline(node, levelData, side, thickness / 2 + proud);
472
+ const outerClipped = clipPolyline(outerRun, clipStart, clipEnd);
430
473
  if (outerClipped.length < 2)
431
474
  continue;
432
475
  const slice = buildTrimSliceGeometry(outerClipped, innerRun, sliceHeight, yBottom + index * sliceHeight);
@@ -459,7 +502,7 @@ export function createWallExtraSlotMaterials(node, shading, sceneMaterials) {
459
502
  chairRailExterior: resolveWallSlotMaterial(node, 'chairRailExterior', shading, sceneMaterials),
460
503
  };
461
504
  }
462
- export const WallTreatments = memo(function WallTreatments({ node, childrenNodes, materials, }) {
505
+ export const WallTreatments = memo(function WallTreatments({ node, childrenNodes, levelData, materials, }) {
463
506
  const fallbackMaterial = materials.skirtingInterior ??
464
507
  materials.skirtingExterior ??
465
508
  materials.crownInterior ??
@@ -481,7 +524,7 @@ export const WallTreatments = memo(function WallTreatments({ node, childrenNodes
481
524
  ? ['interior', 'exterior']
482
525
  : [trim.sides];
483
526
  for (const side of sides) {
484
- const geometry = buildTrimGeometry(node, side, trim, kind, childrenNodes);
527
+ const geometry = buildTrimGeometry(node, side, trim, kind, childrenNodes, levelData);
485
528
  if (!geometry)
486
529
  continue;
487
530
  const slotId = TRIM_KIND_CONFIG[kind].slots[side];
@@ -494,7 +537,7 @@ export const WallTreatments = memo(function WallTreatments({ node, childrenNodes
494
537
  }
495
538
  }
496
539
  return out;
497
- }, [childrenNodes, fallbackMaterial, materials, node]);
540
+ }, [childrenNodes, fallbackMaterial, levelData, materials, node]);
498
541
  useEffect(() => () => {
499
542
  for (const entry of trimEntries)
500
543
  entry.geometry.dispose();
@@ -0,0 +1,3 @@
1
+ import type { FloorplanGeometry, GeometryContext, WindowNode } from '@pascal-app/core';
2
+ export declare function buildWindowContextualDimensions(node: WindowNode, ctx: GeometryContext): FloorplanGeometry | null;
3
+ //# sourceMappingURL=contextual-dimensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextual-dimensions.d.ts","sourceRoot":"","sources":["../../src/window/contextual-dimensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAGtF,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CAK1B"}