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

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 +74 -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 +15 -1
  138. package/dist/fence/lift.d.ts +38 -0
  139. package/dist/fence/lift.d.ts.map +1 -0
  140. package/dist/fence/lift.js +51 -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 +46 -0
  146. package/dist/fence/tool.d.ts.map +1 -1
  147. package/dist/fence/tool.js +103 -32
  148. package/dist/hvac-equipment/tool.d.ts.map +1 -1
  149. package/dist/hvac-equipment/tool.js +8 -3
  150. package/dist/index.d.ts +2 -0
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.js +6 -0
  153. package/dist/item/definition.d.ts.map +1 -1
  154. package/dist/item/definition.js +7 -1
  155. package/dist/item/floorplan-move.d.ts.map +1 -1
  156. package/dist/item/floorplan-move.js +50 -43
  157. package/dist/item/floorplan.d.ts +1 -0
  158. package/dist/item/floorplan.d.ts.map +1 -1
  159. package/dist/item/floorplan.js +49 -0
  160. package/dist/item/renderer.d.ts +3 -0
  161. package/dist/item/renderer.d.ts.map +1 -1
  162. package/dist/item/renderer.js +96 -8
  163. package/dist/level/definition.d.ts.map +1 -1
  164. package/dist/level/definition.js +7 -3
  165. package/dist/lineset/tool.d.ts.map +1 -1
  166. package/dist/lineset/tool.js +5 -1
  167. package/dist/liquid-line/tool.d.ts.map +1 -1
  168. package/dist/liquid-line/tool.js +7 -1
  169. package/dist/measurement/definition.d.ts.map +1 -1
  170. package/dist/measurement/definition.js +5 -0
  171. package/dist/measurement/floorplan.d.ts.map +1 -1
  172. package/dist/measurement/floorplan.js +11 -10
  173. package/dist/measurement/index.d.ts +1 -1
  174. package/dist/measurement/index.d.ts.map +1 -1
  175. package/dist/measurement/index.js +1 -1
  176. package/dist/measurement/resolve.d.ts +5 -0
  177. package/dist/measurement/resolve.d.ts.map +1 -1
  178. package/dist/measurement/resolve.js +2 -2
  179. package/dist/measurement/surface-query.js +5 -5
  180. package/dist/measurement/tool.d.ts +6 -1
  181. package/dist/measurement/tool.d.ts.map +1 -1
  182. package/dist/measurement/tool.js +7 -11
  183. package/dist/pipe-segment/tool.d.ts.map +1 -1
  184. package/dist/pipe-segment/tool.js +22 -19
  185. package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
  186. package/dist/roof-segment/floorplan-affordances.js +14 -8
  187. package/dist/shared/construction-dimension-standards.d.ts +34 -0
  188. package/dist/shared/construction-dimension-standards.d.ts.map +1 -0
  189. package/dist/shared/construction-dimension-standards.js +18 -0
  190. package/dist/shared/construction-length.d.ts +10 -0
  191. package/dist/shared/construction-length.d.ts.map +1 -0
  192. package/dist/shared/construction-length.js +57 -0
  193. package/dist/shared/dimension-string.d.ts +20 -0
  194. package/dist/shared/dimension-string.d.ts.map +1 -0
  195. package/dist/shared/dimension-string.js +19 -0
  196. package/dist/shared/draft-axis-guides.d.ts +36 -0
  197. package/dist/shared/draft-axis-guides.d.ts.map +1 -0
  198. package/dist/shared/draft-axis-guides.js +107 -0
  199. package/dist/shared/move-roof-tool.d.ts.map +1 -1
  200. package/dist/shared/move-roof-tool.js +17 -3
  201. package/dist/shared/opening-documentation-fields.d.ts +16 -0
  202. package/dist/shared/opening-documentation-fields.d.ts.map +1 -0
  203. package/dist/shared/opening-documentation-fields.js +54 -0
  204. package/dist/shared/opening-documentation.d.ts +47 -0
  205. package/dist/shared/opening-documentation.d.ts.map +1 -0
  206. package/dist/shared/opening-documentation.js +300 -0
  207. package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
  208. package/dist/shared/opening-guides-runtime.js +3 -2
  209. package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
  210. package/dist/shared/opening-placement-dimensions.js +14 -5
  211. package/dist/shared/wall-opening-ceiling.d.ts +30 -0
  212. package/dist/shared/wall-opening-ceiling.d.ts.map +1 -0
  213. package/dist/shared/wall-opening-ceiling.js +29 -0
  214. package/dist/shelf/floorplan-affordances.d.ts.map +1 -1
  215. package/dist/shelf/floorplan-affordances.js +10 -5
  216. package/dist/shelf/floorplan-move.d.ts +2 -16
  217. package/dist/shelf/floorplan-move.d.ts.map +1 -1
  218. package/dist/shelf/floorplan-move.js +19 -40
  219. package/dist/shelf/tool.d.ts.map +1 -1
  220. package/dist/shelf/tool.js +8 -3
  221. package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
  222. package/dist/site/recessed-slab-ground-holes.js +1 -4
  223. package/dist/site/renderer.d.ts.map +1 -1
  224. package/dist/site/renderer.js +118 -28
  225. package/dist/site/terrain-drape.d.ts +91 -0
  226. package/dist/site/terrain-drape.d.ts.map +1 -0
  227. package/dist/site/terrain-drape.js +205 -0
  228. package/dist/site/terrain-geometry.d.ts +131 -0
  229. package/dist/site/terrain-geometry.d.ts.map +1 -0
  230. package/dist/site/terrain-geometry.js +259 -0
  231. package/dist/site/terrain-mesh.d.ts +49 -0
  232. package/dist/site/terrain-mesh.d.ts.map +1 -0
  233. package/dist/site/terrain-mesh.js +122 -0
  234. package/dist/site/terrain-renderer.d.ts +28 -0
  235. package/dist/site/terrain-renderer.d.ts.map +1 -0
  236. package/dist/site/terrain-renderer.js +69 -0
  237. package/dist/skylight/definition.d.ts.map +1 -1
  238. package/dist/skylight/definition.js +1 -0
  239. package/dist/skylight/tool.d.ts.map +1 -1
  240. package/dist/skylight/tool.js +16 -1
  241. package/dist/slab/definition.d.ts.map +1 -1
  242. package/dist/slab/definition.js +87 -10
  243. package/dist/slab/elevation-limit.d.ts +43 -0
  244. package/dist/slab/elevation-limit.d.ts.map +1 -0
  245. package/dist/slab/elevation-limit.js +124 -0
  246. package/dist/slab/floorplan-affordances.d.ts +16 -0
  247. package/dist/slab/floorplan-affordances.d.ts.map +1 -1
  248. package/dist/slab/geometry.d.ts.map +1 -1
  249. package/dist/slab/geometry.js +98 -5
  250. package/dist/slab/panel.d.ts.map +1 -1
  251. package/dist/slab/panel.js +82 -4
  252. package/dist/slab/parametrics.d.ts +1 -1
  253. package/dist/slab/parametrics.d.ts.map +1 -1
  254. package/dist/slab/parametrics.js +13 -1
  255. package/dist/slab/placement-ownership.d.ts +3 -0
  256. package/dist/slab/placement-ownership.d.ts.map +1 -0
  257. package/dist/slab/placement-ownership.js +3 -0
  258. package/dist/slab/quick-measurement.d.ts.map +1 -1
  259. package/dist/slab/quick-measurement.js +3 -2
  260. package/dist/slab/system.d.ts.map +1 -1
  261. package/dist/slab/system.js +14 -4
  262. package/dist/slab/tool.d.ts.map +1 -1
  263. package/dist/slab/tool.js +81 -23
  264. package/dist/solar-panel/definition.d.ts.map +1 -1
  265. package/dist/solar-panel/definition.js +1 -0
  266. package/dist/solar-panel/tool.d.ts.map +1 -1
  267. package/dist/solar-panel/tool.js +17 -1
  268. package/dist/spawn/definition.d.ts.map +1 -1
  269. package/dist/spawn/definition.js +1 -0
  270. package/dist/spawn/floorplan-affordances.d.ts.map +1 -1
  271. package/dist/spawn/floorplan-affordances.js +7 -4
  272. package/dist/spawn/floorplan-move.d.ts.map +1 -1
  273. package/dist/spawn/floorplan-move.js +8 -6
  274. package/dist/spawn/renderer.d.ts +4 -0
  275. package/dist/spawn/renderer.d.ts.map +1 -1
  276. package/dist/spawn/renderer.js +32 -18
  277. package/dist/spawn/tool.d.ts +2 -2
  278. package/dist/spawn/tool.d.ts.map +1 -1
  279. package/dist/spawn/tool.js +78 -11
  280. package/dist/stair/definition.d.ts.map +1 -1
  281. package/dist/stair/definition.js +15 -7
  282. package/dist/stair/destination.d.ts +16 -0
  283. package/dist/stair/destination.d.ts.map +1 -0
  284. package/dist/stair/destination.js +24 -0
  285. package/dist/stair/documentation.d.ts +8 -0
  286. package/dist/stair/documentation.d.ts.map +1 -0
  287. package/dist/stair/documentation.js +245 -0
  288. package/dist/stair/floor-stack.d.ts.map +1 -1
  289. package/dist/stair/floor-stack.js +38 -0
  290. package/dist/stair/floorplan-affordances.d.ts.map +1 -1
  291. package/dist/stair/floorplan-affordances.js +28 -9
  292. package/dist/stair/floorplan-move.d.ts +3 -5
  293. package/dist/stair/floorplan-move.d.ts.map +1 -1
  294. package/dist/stair/floorplan-move.js +14 -16
  295. package/dist/stair/floorplan.d.ts.map +1 -1
  296. package/dist/stair/floorplan.js +27 -14
  297. package/dist/stair/panel.d.ts.map +1 -1
  298. package/dist/stair/panel.js +35 -2
  299. package/dist/stair/renderer.d.ts.map +1 -1
  300. package/dist/stair/renderer.js +4 -3
  301. package/dist/structural-grid/coordination.d.ts +16 -0
  302. package/dist/structural-grid/coordination.d.ts.map +1 -0
  303. package/dist/structural-grid/coordination.js +105 -0
  304. package/dist/structural-grid/definition.d.ts +4 -0
  305. package/dist/structural-grid/definition.d.ts.map +1 -0
  306. package/dist/structural-grid/definition.js +51 -0
  307. package/dist/structural-grid/floorplan-tool.d.ts +16 -0
  308. package/dist/structural-grid/floorplan-tool.d.ts.map +1 -0
  309. package/dist/structural-grid/floorplan-tool.js +183 -0
  310. package/dist/structural-grid/floorplan.d.ts +3 -0
  311. package/dist/structural-grid/floorplan.d.ts.map +1 -0
  312. package/dist/structural-grid/floorplan.js +61 -0
  313. package/dist/structural-grid/index.d.ts +2 -0
  314. package/dist/structural-grid/index.d.ts.map +1 -0
  315. package/dist/structural-grid/index.js +1 -0
  316. package/dist/structural-grid/schema.d.ts +2 -0
  317. package/dist/structural-grid/schema.d.ts.map +1 -0
  318. package/dist/structural-grid/schema.js +1 -0
  319. package/dist/wall/construction-dimensions.d.ts +32 -0
  320. package/dist/wall/construction-dimensions.d.ts.map +1 -0
  321. package/dist/wall/construction-dimensions.js +1031 -0
  322. package/dist/wall/contextual-dimensions.d.ts +13 -0
  323. package/dist/wall/contextual-dimensions.d.ts.map +1 -0
  324. package/dist/wall/contextual-dimensions.js +221 -0
  325. package/dist/wall/definition.d.ts.map +1 -1
  326. package/dist/wall/definition.js +20 -1
  327. package/dist/wall/floorplan-affordances.d.ts.map +1 -1
  328. package/dist/wall/floorplan-affordances.js +23 -8
  329. package/dist/wall/floorplan-overrides.d.ts +9 -6
  330. package/dist/wall/floorplan-overrides.d.ts.map +1 -1
  331. package/dist/wall/floorplan-overrides.js +20 -11
  332. package/dist/wall/floorplan.d.ts +12 -3
  333. package/dist/wall/floorplan.d.ts.map +1 -1
  334. package/dist/wall/floorplan.js +121 -79
  335. package/dist/wall/measurement.d.ts.map +1 -1
  336. package/dist/wall/measurement.js +17 -4
  337. package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
  338. package/dist/wall/move-endpoint-tool.js +74 -27
  339. package/dist/wall/move-shared.d.ts.map +1 -1
  340. package/dist/wall/move-shared.js +3 -2
  341. package/dist/wall/move-tool.d.ts.map +1 -1
  342. package/dist/wall/move-tool.js +15 -3
  343. package/dist/wall/paint.d.ts.map +1 -1
  344. package/dist/wall/paint.js +10 -6
  345. package/dist/wall/panel.d.ts.map +1 -1
  346. package/dist/wall/panel.js +32 -5
  347. package/dist/wall/parametrics.d.ts.map +1 -1
  348. package/dist/wall/parametrics.js +2 -0
  349. package/dist/wall/preview.d.ts +8 -0
  350. package/dist/wall/preview.d.ts.map +1 -0
  351. package/dist/wall/preview.js +39 -0
  352. package/dist/wall/quick-measurement.d.ts.map +1 -1
  353. package/dist/wall/quick-measurement.js +3 -2
  354. package/dist/wall/renderer.d.ts.map +1 -1
  355. package/dist/wall/renderer.js +7 -5
  356. package/dist/wall/system.d.ts +1 -1
  357. package/dist/wall/system.d.ts.map +1 -1
  358. package/dist/wall/system.js +37 -2
  359. package/dist/wall/tool.d.ts.map +1 -1
  360. package/dist/wall/tool.js +148 -96
  361. package/dist/wall/treatment-level-data.d.ts +14 -0
  362. package/dist/wall/treatment-level-data.d.ts.map +1 -0
  363. package/dist/wall/treatment-level-data.js +31 -0
  364. package/dist/wall/treatments.d.ts +8 -2
  365. package/dist/wall/treatments.d.ts.map +1 -1
  366. package/dist/wall/treatments.js +58 -15
  367. package/dist/window/contextual-dimensions.d.ts +3 -0
  368. package/dist/window/contextual-dimensions.d.ts.map +1 -0
  369. package/dist/window/contextual-dimensions.js +7 -0
  370. package/dist/window/definition.d.ts.map +1 -1
  371. package/dist/window/definition.js +15 -10
  372. package/dist/window/floorplan-affordances.d.ts +2 -5
  373. package/dist/window/floorplan-affordances.d.ts.map +1 -1
  374. package/dist/window/floorplan-affordances.js +9 -15
  375. package/dist/window/floorplan-move.d.ts.map +1 -1
  376. package/dist/window/floorplan-move.js +1 -1
  377. package/dist/window/floorplan.d.ts.map +1 -1
  378. package/dist/window/floorplan.js +7 -1
  379. package/dist/window/move-tool.d.ts.map +1 -1
  380. package/dist/window/move-tool.js +3 -3
  381. package/dist/window/panel.d.ts.map +1 -1
  382. package/dist/window/panel.js +4 -1
  383. package/dist/window/schema.d.ts +1 -1
  384. package/dist/window/schema.d.ts.map +1 -1
  385. package/dist/window/schema.js +1 -1
  386. package/dist/window/tool.d.ts.map +1 -1
  387. package/dist/window/tool.js +64 -7
  388. package/dist/window/window-math.d.ts +7 -3
  389. package/dist/window/window-math.d.ts.map +1 -1
  390. package/dist/window/window-math.js +8 -3
  391. package/dist/zone/contextual-dimensions.d.ts +3 -0
  392. package/dist/zone/contextual-dimensions.d.ts.map +1 -0
  393. package/dist/zone/contextual-dimensions.js +43 -0
  394. package/dist/zone/definition.d.ts.map +1 -1
  395. package/dist/zone/definition.js +9 -1
  396. package/dist/zone/floorplan-affordances.d.ts +36 -0
  397. package/dist/zone/floorplan-affordances.d.ts.map +1 -1
  398. package/dist/zone/floorplan.d.ts.map +1 -1
  399. package/dist/zone/floorplan.js +59 -3
  400. package/dist/zone/quantities-panel.d.ts.map +1 -1
  401. package/dist/zone/quantities-panel.js +48 -4
  402. package/dist/zone/room-clear-dimensions.d.ts +3 -0
  403. package/dist/zone/room-clear-dimensions.d.ts.map +1 -0
  404. package/dist/zone/room-clear-dimensions.js +406 -0
  405. package/dist/zone/room-documentation.d.ts +11 -0
  406. package/dist/zone/room-documentation.d.ts.map +1 -0
  407. package/dist/zone/room-documentation.js +97 -0
  408. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/skylight/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EAIpB,MAAM,kBAAkB,CAAA;AASzB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAoMvC;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,OAAO,YAAY,CAgFlE,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/skylight/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EAIpB,MAAM,kBAAkB,CAAA;AASzB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAoMvC;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,OAAO,YAAY,CAiFlE,CAAA"}
@@ -230,6 +230,7 @@ export const skylightDefinition = {
230
230
  kind: 'parametric',
231
231
  module: () => import('./renderer'),
232
232
  },
233
+ preview: () => import('./preview'),
233
234
  system: {
234
235
  module: () => import('./system'),
235
236
  priority: 3,
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/skylight/tool.tsx"],"names":[],"mappings":"AA4BA,QAAA,MAAM,YAAY,mCAuHjB,CAAA;AAED,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/skylight/tool.tsx"],"names":[],"mappings":"AA4BA,QAAA,MAAM,YAAY,mCAsIjB,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { emitter, SkylightNode, sceneRegistry, useScene, } from '@pascal-app/core';
4
- import { triggerSFX } from '@pascal-app/editor';
4
+ import { triggerSFX, usePlacementPreview } from '@pascal-app/editor';
5
5
  import { useViewer } from '@pascal-app/viewer';
6
6
  import { useEffect, useMemo, useRef, useState } from 'react';
7
7
  import * as THREE from 'three';
@@ -54,6 +54,12 @@ const SkylightTool = () => {
54
54
  setPreviewSurfaceQuat(surfaceQuatFromNormal(normal, new THREE.Quaternion()));
55
55
  setPreviewYaw((event.node.rotation ?? 0) + (hit.segment.rotation ?? 0));
56
56
  setPreviewPos(worldToBuildingLocal(wx, wy, wz));
57
+ usePlacementPreview.getState().set(SkylightNode.parse({
58
+ ...previewNode,
59
+ parentId: hit.segment.id,
60
+ position: [hit.localX, hit.localY, hit.localZ],
61
+ roofSegmentId: hit.segment.id,
62
+ }), hit.segment);
57
63
  publishRoofSurfacePlacementGuides({
58
64
  roof: event.node,
59
65
  segment: hit.segment,
@@ -78,6 +84,9 @@ const SkylightTool = () => {
78
84
  state.dirtyNodes.add(hit.segment.id);
79
85
  setSelection({ selectedIds: [skylight.id] });
80
86
  triggerSFX('sfx:item-place');
87
+ const placementPreview = usePlacementPreview.getState();
88
+ if (placementPreview.node?.id === previewNode.id)
89
+ placementPreview.clear();
81
90
  clearRoofSurfacePlacementGuides();
82
91
  event.stopPropagation();
83
92
  };
@@ -88,12 +97,18 @@ const SkylightTool = () => {
88
97
  emitter.off('roof:move', updatePreview);
89
98
  emitter.off('roof:enter', updatePreview);
90
99
  emitter.off('roof:click', onClick);
100
+ const placementPreview = usePlacementPreview.getState();
101
+ if (placementPreview.node?.id === previewNode.id)
102
+ placementPreview.clear();
91
103
  clearRoofSurfacePlacementGuides();
92
104
  };
93
105
  }, [activeBuildingId, setSelection, previewNode]);
94
106
  return (_jsxs(_Fragment, { children: [_jsx(RoofAttachmentFallbackPreview, { activeBuildingId: activeBuildingId, ghost: _jsx(SkylightPreview, { node: previewNode, invalid: true }), onInvalidTarget: () => {
95
107
  setPreviewPos(null);
96
108
  setPreviewSurfaceQuat(null);
109
+ const placementPreview = usePlacementPreview.getState();
110
+ if (placementPreview.node?.id === previewNode.id)
111
+ placementPreview.clear();
97
112
  clearRoofSurfacePlacementGuides();
98
113
  } }), activeBuildingId && previewPos && previewSurfaceQuat && (_jsx("group", { position: previewPos, children: _jsx("group", { "rotation-y": previewYaw, children: _jsx("group", { quaternion: previewSurfaceQuat, children: _jsx(SkylightPreview, { node: previewNode }) }) }) }))] }));
99
114
  };
@@ -1 +1 @@
1
- {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/slab/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EAGpB,MAAM,kBAAkB,CAAA;AAczB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAqGnC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,OAAO,QAAQ,CA+G1D,CAAA"}
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/slab/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EAKpB,MAAM,kBAAkB,CAAA;AA0BzB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAsNnC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,OAAO,QAAQ,CAiH1D,CAAA"}
@@ -1,5 +1,7 @@
1
- import { pointInPolygon2D, } from '@pascal-app/core';
1
+ import { MIN_SLAB_THICKNESS, markSlabChangeDependents, pointInPolygon2D, syncStairRises, } from '@pascal-app/core';
2
+ import { clearStructuralElevationGuide, publishStructuralElevationGuide, resolveStructuralElevationSnap, } from '@pascal-app/editor';
2
3
  import { polygonMeasurementFeatures } from '../shared/polygon-measurement';
4
+ import { applySlabBaseElevationChange, applySlabThicknessChange, applySlabTopChange, getSlabBaseElevation, slabElevationUpperBound, } from './elevation-limit';
3
5
  import { buildSlabFloorplan } from './floorplan';
4
6
  import { slabAddVertexAffordance, slabDeleteVertexAffordance, slabMoveEdgeAffordance, slabMoveVertexAffordance, } from './floorplan-affordances';
5
7
  import { slabFloorplanMoveTarget } from './floorplan-move';
@@ -74,19 +76,42 @@ function slabHandleAnchor(slab) {
74
76
  }
75
77
  return best ?? fallback;
76
78
  }
77
- // Slab height arrow — vertical chevron on solid slab surface near the
78
- // polygon center. Drags elevation through zero: positive values extrude
79
- // upward from ground while negative values create a recessed floor whose
80
- // depth follows the pointer. Same registry-handle pipeline as the column
81
- // height arrow, so live override + commit-on-release come for free.
82
- function slabHeightHandle() {
79
+ function slabElevationGuideSource(slab) {
80
+ return {
81
+ nodeId: slab.id,
82
+ levelId: slab.parentId,
83
+ anchor: slabHandleAnchor(slab),
84
+ };
85
+ }
86
+ function slabChangePreviewOverrides(slab, patch, sceneApi) {
87
+ const next = { ...slab, ...patch };
88
+ const nodes = { ...sceneApi.nodes(), [slab.id]: next };
89
+ const previews = new Map();
90
+ markSlabChangeDependents(slab, next, nodes, (id) => previews.set(id, {}));
91
+ for (const update of syncStairRises(nodes)) {
92
+ const segment = nodes[update.id];
93
+ if (segment?.type !== 'stair-segment' ||
94
+ !segment.parentId ||
95
+ !previews.has(segment.parentId)) {
96
+ continue;
97
+ }
98
+ previews.set(update.id, update.data);
99
+ }
100
+ return [...previews];
101
+ }
102
+ function slabRecessedDepthHandle() {
83
103
  return {
84
104
  kind: 'linear-resize',
85
105
  axis: 'y',
86
106
  anchor: 'min',
87
107
  min: MIN_SLAB_ELEVATION,
108
+ max: (n, sceneApi) => slabElevationUpperBound(sceneApi.nodes(), n),
88
109
  currentValue: (n) => n.elevation ?? 0.05,
89
- apply: (_n, newValue) => ({ elevation: newValue }),
110
+ magneticSnap: (n, newValue, sceneApi) => resolveStructuralElevationSnap(slabElevationGuideSource(n), newValue, sceneApi.nodes()),
111
+ onDrag: (n, sceneApi) => publishStructuralElevationGuide(slabElevationGuideSource(n), n.elevation ?? 0.05, sceneApi.nodes()),
112
+ onDragEnd: (n) => clearStructuralElevationGuide(n.id),
113
+ apply: (n, newValue) => applySlabTopChange(n, newValue),
114
+ previewOverrides: (n, newValue, sceneApi) => slabChangePreviewOverrides(n, applySlabTopChange(n, newValue), sceneApi),
90
115
  placement: {
91
116
  position: (n) => {
92
117
  const [cx, cz] = slabHandleAnchor(n);
@@ -96,8 +121,58 @@ function slabHeightHandle() {
96
121
  },
97
122
  };
98
123
  }
99
- function slabHandles(_node) {
100
- return [slabHeightHandle()];
124
+ function slabThicknessHandle() {
125
+ return {
126
+ kind: 'linear-resize',
127
+ axis: 'y',
128
+ anchor: 'min',
129
+ min: MIN_SLAB_THICKNESS,
130
+ max: (n, sceneApi) => Math.max(MIN_SLAB_THICKNESS, slabElevationUpperBound(sceneApi.nodes(), n) - getSlabBaseElevation(n)),
131
+ currentValue: (n) => n.thickness ?? 0.05,
132
+ magneticSnap: (n, newThickness, sceneApi) => {
133
+ const base = getSlabBaseElevation(n);
134
+ const snappedTop = resolveStructuralElevationSnap(slabElevationGuideSource(n), base + newThickness, sceneApi.nodes());
135
+ return Math.max(MIN_SLAB_THICKNESS, snappedTop - base);
136
+ },
137
+ onDrag: (n, sceneApi) => publishStructuralElevationGuide(slabElevationGuideSource(n), n.elevation ?? 0.05, sceneApi.nodes()),
138
+ onDragEnd: (n) => clearStructuralElevationGuide(n.id),
139
+ apply: (n, newThickness) => applySlabThicknessChange(n, newThickness),
140
+ previewOverrides: (n, newThickness, sceneApi) => slabChangePreviewOverrides(n, applySlabThicknessChange(n, newThickness), sceneApi),
141
+ placement: {
142
+ position: (n) => {
143
+ const [cx, cz] = slabHandleAnchor(n);
144
+ return [cx, (n.elevation ?? 0.05) + HEIGHT_HANDLE_OFFSET, cz];
145
+ },
146
+ },
147
+ };
148
+ }
149
+ function slabBaseElevationHandle() {
150
+ return {
151
+ kind: 'linear-resize',
152
+ axis: 'y',
153
+ anchor: 'min',
154
+ shape: 'tracker',
155
+ gridSnap: true,
156
+ min: (n) => MIN_SLAB_ELEVATION - (n.thickness ?? 0.05),
157
+ max: (n, sceneApi) => slabElevationUpperBound(sceneApi.nodes(), n) - (n.thickness ?? 0.05),
158
+ currentValue: (n) => getSlabBaseElevation(n),
159
+ magneticSnap: (n, newValue, sceneApi) => resolveStructuralElevationSnap(slabElevationGuideSource(n), newValue, sceneApi.nodes()),
160
+ onDrag: (n, sceneApi) => publishStructuralElevationGuide(slabElevationGuideSource(n), getSlabBaseElevation(n), sceneApi.nodes()),
161
+ onDragEnd: (n) => clearStructuralElevationGuide(n.id),
162
+ apply: (n, newBase) => applySlabBaseElevationChange(n, newBase),
163
+ previewOverrides: (n, newBase, sceneApi) => slabChangePreviewOverrides(n, applySlabBaseElevationChange(n, newBase), sceneApi),
164
+ placement: {
165
+ position: (n) => {
166
+ const [cx, cz] = slabHandleAnchor(n);
167
+ return [cx, getSlabBaseElevation(n), cz];
168
+ },
169
+ },
170
+ };
171
+ }
172
+ function slabHandles(node) {
173
+ return node.recessed
174
+ ? [slabRecessedDepthHandle()]
175
+ : [slabThicknessHandle(), slabBaseElevationHandle()];
101
176
  }
102
177
  /**
103
178
  * Slab — Phase 5 batch kind, polygon-based. Stage B: `def.geometry`
@@ -131,6 +206,8 @@ export const slabDefinition = {
131
206
  holes: [],
132
207
  holeMetadata: [],
133
208
  elevation: 0.05,
209
+ thickness: 0.05,
210
+ recessed: false,
134
211
  autoFromWalls: false,
135
212
  }),
136
213
  capabilities: {
@@ -0,0 +1,43 @@
1
+ import { type AnyNode, type AnyNodeId, type SlabElevationClamp, type SlabNode } from '@pascal-app/core';
2
+ /** Level-local Y of a solid slab's underside (its placement anchor). */
3
+ export declare function getSlabBaseElevation(slab: Pick<SlabNode, 'elevation' | 'thickness'>): number;
4
+ /** Stable vertical reference used by relative slab presets. */
5
+ export declare function getSlabAnchorElevation(slab: Pick<SlabNode, 'elevation' | 'thickness' | 'recessed' | 'recessedRimElevation'>): number;
6
+ /**
7
+ * Translate a solid slab to a new underside elevation without changing its
8
+ * authored thickness. Recessed slabs use a different rim/depth contract and
9
+ * keep the existing top/depth control instead.
10
+ */
11
+ export declare function applySlabBaseElevationChange(slab: Pick<SlabNode, 'thickness'>, newBase: number): Pick<SlabNode, 'elevation'>;
12
+ /** Translate a solid underside or recessed rim without resizing the body. */
13
+ export declare function applySlabAnchorElevationChange(slab: Pick<SlabNode, 'elevation' | 'thickness' | 'recessed' | 'recessedRimElevation'>, newAnchor: number): Partial<SlabNode>;
14
+ export declare function getSlabRecessDepth(slab: Pick<SlabNode, 'elevation' | 'recessedRimElevation'>): number;
15
+ /** Resize a recess downward while keeping its rim anchor fixed. */
16
+ export declare function applySlabRecessDepthChange(slab: Pick<SlabNode, 'recessedRimElevation'>, newDepth: number): Pick<SlabNode, 'elevation'>;
17
+ /**
18
+ * Resize a solid slab upward from its underside. The occupied interval changes
19
+ * from [base, old top] to [base, base + new thickness], so anything hosted on
20
+ * the walking surface observes the new elevation.
21
+ */
22
+ export declare function applySlabThicknessChange(slab: Pick<SlabNode, 'elevation' | 'thickness'>, newThickness: number): Pick<SlabNode, 'elevation' | 'thickness' | 'recessed'>;
23
+ /**
24
+ * Move a slab's authored top while preserving thickness. Recessed slabs keep
25
+ * their pool-depth gesture; a grounded solid crossing below datum becomes
26
+ * recessed. Solid slab thickness is edited separately.
27
+ */
28
+ export declare function applySlabTopChange(slab: SlabNode, newTop: number): Partial<SlabNode>;
29
+ /**
30
+ * Apply a signed surface preset around the current anchor. Negative values make
31
+ * a recess below the anchor; positive values make a solid upward from it.
32
+ */
33
+ export declare function applySlabElevationPreset(slab: SlabNode, signedDepth: number): Partial<SlabNode>;
34
+ /**
35
+ * Level-context wrapper over the pure core clamp: a slab under
36
+ * plane-bound walls may not rise past the storey plane minus the
37
+ * minimum wall height. Slabs outside a level (no parent) are
38
+ * unconstrained.
39
+ */
40
+ export declare function clampSlabElevation(nodes: Readonly<Record<AnyNodeId, AnyNode>>, slab: SlabNode, proposedElevation: number): SlabElevationClamp;
41
+ /** Drag-time upper bound for the slab height arrow; +Infinity when unconstrained. */
42
+ export declare function slabElevationUpperBound(nodes: Readonly<Record<AnyNodeId, AnyNode>>, slab: SlabNode): number;
43
+ //# sourceMappingURL=elevation-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elevation-limit.d.ts","sourceRoot":"","sources":["../../src/slab/elevation-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EAMd,KAAK,kBAAkB,EACvB,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAA;AAUzB,wEAAwE;AACxE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,CAAC,GAAG,MAAM,CAE5F;AAED,+DAA+D;AAC/D,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,sBAAsB,CAAC,GACpF,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EACjC,OAAO,EAAE,MAAM,GACd,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAE7B;AAED,6EAA6E;AAC7E,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,sBAAsB,CAAC,EACrF,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,QAAQ,CAAC,CAOnB;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,sBAAsB,CAAC,GACzD,MAAM,CAER;AAED,mEAAmE;AACnE,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,sBAAsB,CAAC,EAC5C,QAAQ,EAAE,MAAM,GACf,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAG7B;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,CAAC,EAC/C,YAAY,EAAE,MAAM,GACnB,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC,CAOxD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgBpF;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiB/F;AAiBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,EAC3C,IAAI,EAAE,QAAQ,EACd,iBAAiB,EAAE,MAAM,GACxB,kBAAkB,CAUpB;AAED,qFAAqF;AACrF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,EAC3C,IAAI,EAAE,QAAQ,GACb,MAAM,CAIR"}
@@ -0,0 +1,124 @@
1
+ import { clampSlabElevationForWalls, getSlabElevationUpperBound, getStoredLevelHeight, MIN_SLAB_THICKNESS, } from '@pascal-app/core';
2
+ const GROUNDED_SLAB_EPSILON = 1e-3;
3
+ /** Level-local Y of a solid slab's underside (its placement anchor). */
4
+ export function getSlabBaseElevation(slab) {
5
+ return (slab.elevation ?? 0.05) - (slab.thickness ?? 0.05);
6
+ }
7
+ /** Stable vertical reference used by relative slab presets. */
8
+ export function getSlabAnchorElevation(slab) {
9
+ return slab.recessed ? (slab.recessedRimElevation ?? 0) : getSlabBaseElevation(slab);
10
+ }
11
+ /**
12
+ * Translate a solid slab to a new underside elevation without changing its
13
+ * authored thickness. Recessed slabs use a different rim/depth contract and
14
+ * keep the existing top/depth control instead.
15
+ */
16
+ export function applySlabBaseElevationChange(slab, newBase) {
17
+ return { elevation: newBase + (slab.thickness ?? 0.05) };
18
+ }
19
+ /** Translate a solid underside or recessed rim without resizing the body. */
20
+ export function applySlabAnchorElevationChange(slab, newAnchor) {
21
+ if (!slab.recessed)
22
+ return applySlabBaseElevationChange(slab, newAnchor);
23
+ const rim = getSlabAnchorElevation(slab);
24
+ return {
25
+ elevation: slab.elevation + (newAnchor - rim),
26
+ recessedRimElevation: newAnchor,
27
+ };
28
+ }
29
+ export function getSlabRecessDepth(slab) {
30
+ return Math.max(MIN_SLAB_THICKNESS, (slab.recessedRimElevation ?? 0) - slab.elevation);
31
+ }
32
+ /** Resize a recess downward while keeping its rim anchor fixed. */
33
+ export function applySlabRecessDepthChange(slab, newDepth) {
34
+ const depth = Math.max(MIN_SLAB_THICKNESS, newDepth);
35
+ return { elevation: (slab.recessedRimElevation ?? 0) - depth };
36
+ }
37
+ /**
38
+ * Resize a solid slab upward from its underside. The occupied interval changes
39
+ * from [base, old top] to [base, base + new thickness], so anything hosted on
40
+ * the walking surface observes the new elevation.
41
+ */
42
+ export function applySlabThicknessChange(slab, newThickness) {
43
+ const thickness = Math.max(MIN_SLAB_THICKNESS, newThickness);
44
+ return {
45
+ elevation: getSlabBaseElevation(slab) + thickness,
46
+ thickness,
47
+ recessed: false,
48
+ };
49
+ }
50
+ /**
51
+ * Move a slab's authored top while preserving thickness. Recessed slabs keep
52
+ * their pool-depth gesture; a grounded solid crossing below datum becomes
53
+ * recessed. Solid slab thickness is edited separately.
54
+ */
55
+ export function applySlabTopChange(slab, newTop) {
56
+ if (slab.recessed) {
57
+ const rim = getSlabAnchorElevation(slab);
58
+ if (newTop < rim)
59
+ return { elevation: newTop, recessed: true };
60
+ return {
61
+ elevation: Math.max(newTop, rim + MIN_SLAB_THICKNESS),
62
+ thickness: Math.max(MIN_SLAB_THICKNESS, newTop - rim),
63
+ recessed: false,
64
+ recessedRimElevation: undefined,
65
+ };
66
+ }
67
+ const grounded = Math.abs(slab.elevation - slab.thickness) < GROUNDED_SLAB_EPSILON;
68
+ if (grounded && newTop <= 0)
69
+ return { elevation: newTop, recessed: true };
70
+ return { elevation: newTop, recessed: false };
71
+ }
72
+ /**
73
+ * Apply a signed surface preset around the current anchor. Negative values make
74
+ * a recess below the anchor; positive values make a solid upward from it.
75
+ */
76
+ export function applySlabElevationPreset(slab, signedDepth) {
77
+ const anchor = getSlabAnchorElevation(slab);
78
+ if (signedDepth < 0) {
79
+ return {
80
+ elevation: anchor + signedDepth,
81
+ recessed: true,
82
+ recessedRimElevation: anchor,
83
+ fillToTerrain: undefined,
84
+ };
85
+ }
86
+ const thickness = Math.max(MIN_SLAB_THICKNESS, signedDepth);
87
+ return {
88
+ elevation: anchor + thickness,
89
+ thickness,
90
+ recessed: false,
91
+ recessedRimElevation: undefined,
92
+ };
93
+ }
94
+ function resolveSlabLevelContext(nodes, slab) {
95
+ const parent = slab.parentId ? nodes[slab.parentId] : undefined;
96
+ if (parent?.type !== 'level')
97
+ return null;
98
+ const level = parent;
99
+ const children = level.children.map((childId) => nodes[childId]);
100
+ return {
101
+ storeyHeight: getStoredLevelHeight(level),
102
+ walls: children.filter((child) => child?.type === 'wall'),
103
+ slabs: children.filter((child) => child?.type === 'slab'),
104
+ };
105
+ }
106
+ /**
107
+ * Level-context wrapper over the pure core clamp: a slab under
108
+ * plane-bound walls may not rise past the storey plane minus the
109
+ * minimum wall height. Slabs outside a level (no parent) are
110
+ * unconstrained.
111
+ */
112
+ export function clampSlabElevation(nodes, slab, proposedElevation) {
113
+ const context = resolveSlabLevelContext(nodes, slab);
114
+ if (!context)
115
+ return { elevation: proposedElevation, clamped: false };
116
+ return clampSlabElevationForWalls(proposedElevation, slab, context.walls, context.slabs, context.storeyHeight);
117
+ }
118
+ /** Drag-time upper bound for the slab height arrow; +Infinity when unconstrained. */
119
+ export function slabElevationUpperBound(nodes, slab) {
120
+ const context = resolveSlabLevelContext(nodes, slab);
121
+ if (!context)
122
+ return Number.POSITIVE_INFINITY;
123
+ return getSlabElevationUpperBound(slab, context.walls, context.slabs, context.storeyHeight);
124
+ }
@@ -13,6 +13,8 @@ export declare const slabMoveVertexAffordance: import("@pascal-app/core").Floorp
13
13
  elevatorId?: string | undefined;
14
14
  }[];
15
15
  elevation: number;
16
+ thickness: number;
17
+ recessed: boolean;
16
18
  autoFromWalls: boolean;
17
19
  name?: string | undefined;
18
20
  camera?: {
@@ -41,6 +43,8 @@ export declare const slabMoveVertexAffordance: import("@pascal-app/core").Floorp
41
43
  } | undefined;
42
44
  materialPreset?: string | undefined;
43
45
  slots?: Record<string, string> | undefined;
46
+ recessedRimElevation?: number | undefined;
47
+ fillToTerrain?: boolean | undefined;
44
48
  }>;
45
49
  export declare const slabAddVertexAffordance: import("@pascal-app/core").FloorplanAffordance<{
46
50
  object: "node";
@@ -57,6 +61,8 @@ export declare const slabAddVertexAffordance: import("@pascal-app/core").Floorpl
57
61
  elevatorId?: string | undefined;
58
62
  }[];
59
63
  elevation: number;
64
+ thickness: number;
65
+ recessed: boolean;
60
66
  autoFromWalls: boolean;
61
67
  name?: string | undefined;
62
68
  camera?: {
@@ -85,6 +91,8 @@ export declare const slabAddVertexAffordance: import("@pascal-app/core").Floorpl
85
91
  } | undefined;
86
92
  materialPreset?: string | undefined;
87
93
  slots?: Record<string, string> | undefined;
94
+ recessedRimElevation?: number | undefined;
95
+ fillToTerrain?: boolean | undefined;
88
96
  }>;
89
97
  export declare const slabMoveEdgeAffordance: import("@pascal-app/core").FloorplanAffordance<{
90
98
  object: "node";
@@ -101,6 +109,8 @@ export declare const slabMoveEdgeAffordance: import("@pascal-app/core").Floorpla
101
109
  elevatorId?: string | undefined;
102
110
  }[];
103
111
  elevation: number;
112
+ thickness: number;
113
+ recessed: boolean;
104
114
  autoFromWalls: boolean;
105
115
  name?: string | undefined;
106
116
  camera?: {
@@ -129,6 +139,8 @@ export declare const slabMoveEdgeAffordance: import("@pascal-app/core").Floorpla
129
139
  } | undefined;
130
140
  materialPreset?: string | undefined;
131
141
  slots?: Record<string, string> | undefined;
142
+ recessedRimElevation?: number | undefined;
143
+ fillToTerrain?: boolean | undefined;
132
144
  }>;
133
145
  export declare const slabDeleteVertexAffordance: import("@pascal-app/core").FloorplanAffordance<{
134
146
  object: "node";
@@ -145,6 +157,8 @@ export declare const slabDeleteVertexAffordance: import("@pascal-app/core").Floo
145
157
  elevatorId?: string | undefined;
146
158
  }[];
147
159
  elevation: number;
160
+ thickness: number;
161
+ recessed: boolean;
148
162
  autoFromWalls: boolean;
149
163
  name?: string | undefined;
150
164
  camera?: {
@@ -173,5 +187,7 @@ export declare const slabDeleteVertexAffordance: import("@pascal-app/core").Floo
173
187
  } | undefined;
174
188
  materialPreset?: string | undefined;
175
189
  slots?: Record<string, string> | undefined;
190
+ recessedRimElevation?: number | undefined;
191
+ fillToTerrain?: boolean | undefined;
176
192
  }>;
177
193
  //# sourceMappingURL=floorplan-affordances.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/slab/floorplan-affordances.ts"],"names":[],"mappings":"AAgEA,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGpC,CAAA;AACD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGnC,CAAA;AACD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGlC,CAAA;AACD,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGtC,CAAA"}
1
+ {"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/slab/floorplan-affordances.ts"],"names":[],"mappings":"AAgEA,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGpC,CAAA;AACD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGnC,CAAA;AACD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGlC,CAAA;AACD,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGtC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/slab/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAEL,KAAK,WAAW,EAKhB,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAIL,KAAK,EAKN,MAAM,OAAO,CAAA;AAqJd,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,QAAQ,EACd,GAAG,CAAC,EAAE,eAAe,EACrB,OAAO,GAAE,aAA0B,EACnC,QAAQ,UAAO,EACf,WAAW,GAAE,WAAoB,EACjC,UAAU,CAAC,EAAE,MAAM,GAClB,KAAK,CA8BP"}
1
+ {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/slab/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EAMpB,KAAK,QAAQ,EAId,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAGL,KAAK,WAAW,EAKhB,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAIL,KAAK,EAKN,MAAM,OAAO,CAAA;AAuOd,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,QAAQ,EACd,GAAG,CAAC,EAAE,eAAe,EACrB,OAAO,GAAE,aAA0B,EACnC,QAAQ,UAAO,EACf,WAAW,GAAE,WAAoB,EACjC,UAAU,CAAC,EAAE,MAAM,GAClB,KAAK,CA4DP"}
@@ -1,6 +1,7 @@
1
- import { getMaterialPresetByRef, slabPolygonContextFromGeometry, } from '@pascal-app/core';
2
- import { applyMaterialPresetToMaterials, createDefaultMaterial, createMaterial, createSurfaceRoleMaterial, generateSlabGeometry, resolveMaterialRef, resolveSlotDefaultMaterial, } from '@pascal-app/viewer';
1
+ import { getLevelElevations, getMaterialPresetByRef, getRenderableSlabPolygon, slabPolygonContextFromGeometry, surfaceHeightAt, terrainFieldOf, } from '@pascal-app/core';
2
+ import { applyMaterialPresetToMaterials, buildTerrainPerimeterFillGeometry, createDefaultMaterial, createMaterial, createSurfaceRoleMaterial, generateSlabGeometry, resolveMaterialRef, resolveSlotDefaultMaterial, } from '@pascal-app/viewer';
3
3
  import { BufferGeometry, Float32BufferAttribute, FrontSide, Group, Mesh, Vector3, } from 'three';
4
+ import { creaseCrossings } from '../site/terrain-drape';
4
5
  import { SLAB_SIDE_SLOT_DEFAULT, SLAB_TOP_SLOT_DEFAULT } from './slots';
5
6
  const slabMaterialCache = new Map();
6
7
  function getSlabSlotMaterial(node, slotId, shading, textures, colorPreset, sceneTheme, sceneMaterials) {
@@ -67,8 +68,10 @@ function splitSlabFacesByFacing(geometry) {
67
68
  const build = (data) => {
68
69
  const geo = new BufferGeometry();
69
70
  geo.setAttribute('position', new Float32BufferAttribute(data.pos, 3));
70
- if (data.uv.length > 0)
71
+ if (data.uv.length > 0) {
71
72
  geo.setAttribute('uv', new Float32BufferAttribute(data.uv, 2));
73
+ geo.setAttribute('uv2', new Float32BufferAttribute(data.uv.slice(), 2));
74
+ }
72
75
  geo.computeVertexNormals();
73
76
  return geo;
74
77
  };
@@ -108,9 +111,86 @@ function getLegacySlabMaterial(node, shading) {
108
111
  slabMaterialCache.set(cacheKey, material);
109
112
  return material;
110
113
  }
114
+ function terrainFillContext(ctx) {
115
+ if (!ctx)
116
+ return null;
117
+ const level = ctx.parent;
118
+ if (level?.type !== 'level' || !level.parentId)
119
+ return null;
120
+ const building = ctx.resolve(level.parentId);
121
+ if (building?.type !== 'building' || !building.parentId)
122
+ return null;
123
+ const site = ctx.resolve(building.parentId);
124
+ if (site?.type !== 'site')
125
+ return null;
126
+ const field = terrainFieldOf(site);
127
+ const nodes = {
128
+ [site.id]: site,
129
+ [building.id]: building,
130
+ [level.id]: level,
131
+ };
132
+ for (const childId of building.children) {
133
+ const child = ctx.resolve(childId);
134
+ if (child)
135
+ nodes[child.id] = child;
136
+ }
137
+ const elevation = getLevelElevations(nodes).get(level.id);
138
+ if (!elevation)
139
+ return null;
140
+ const baseWorldY = (building.position?.[1] ?? 0) + elevation.baseY;
141
+ if (Math.abs(baseWorldY) >= 1e-4)
142
+ return null;
143
+ return {
144
+ baseWorldY,
145
+ building,
146
+ field,
147
+ };
148
+ }
149
+ function buildSlabTerrainFillGeometry(node, polygon, ctx) {
150
+ const terrain = terrainFillContext(ctx);
151
+ if (!terrain || polygon.length < 3)
152
+ return null;
153
+ let area2 = 0;
154
+ for (let index = 0; index < polygon.length; index += 1) {
155
+ const [ax, az] = polygon[index];
156
+ const [bx, bz] = polygon[(index + 1) % polygon.length];
157
+ area2 += ax * bz - bx * az;
158
+ }
159
+ const contour = area2 < 0 ? [...polygon].reverse() : polygon;
160
+ const angle = terrain.building.rotation?.[1] ?? 0;
161
+ const cos = Math.cos(angle);
162
+ const sin = Math.sin(angle);
163
+ const [offsetX, , offsetZ] = terrain.building.position ?? [0, 0, 0];
164
+ const toSite = (x, z) => [
165
+ cos * x + sin * z + offsetX,
166
+ -sin * x + cos * z + offsetZ,
167
+ ];
168
+ const points = [];
169
+ for (let index = 0; index < contour.length; index += 1) {
170
+ const [ax, az] = contour[index];
171
+ const [bx, bz] = contour[(index + 1) % contour.length];
172
+ const [siteAx, siteAz] = toSite(ax, az);
173
+ const [siteBx, siteBz] = toSite(bx, bz);
174
+ points.push([ax, az]);
175
+ if (terrain.field) {
176
+ for (const t of creaseCrossings(terrain.field, siteAx, siteAz, siteBx, siteBz)) {
177
+ points.push([ax + (bx - ax) * t, az + (bz - az) * t]);
178
+ }
179
+ }
180
+ }
181
+ const top = node.elevation - node.thickness;
182
+ const localPoints = points.map(([x, z]) => ({ x, z }));
183
+ const bottomY = points.map(([x, z]) => {
184
+ const [siteX, siteZ] = toSite(x, z);
185
+ const ground = terrain.field ? surfaceHeightAt(terrain.field, siteX, siteZ) : 0;
186
+ return Math.min(top, ground - terrain.baseWorldY);
187
+ });
188
+ return buildTerrainPerimeterFillGeometry(localPoints, bottomY, top, 1e-4);
189
+ }
111
190
  export function buildSlabGeometry(node, ctx, shading = 'rendered', textures = true, colorPreset = 'clay', sceneTheme) {
112
191
  const group = new Group();
113
- const merged = generateSlabGeometry(node, slabPolygonContextFromGeometry(ctx));
192
+ const polygonContext = slabPolygonContextFromGeometry(ctx);
193
+ const merged = generateSlabGeometry(node, polygonContext);
114
194
  const { top, side } = splitSlabFacesByFacing(merged);
115
195
  merged.dispose();
116
196
  const elevation = node.elevation ?? 0.05;
@@ -125,9 +205,22 @@ export function buildSlabGeometry(node, ctx, shading = 'rendered', textures = tr
125
205
  mesh.castShadow = true;
126
206
  mesh.receiveShadow = true;
127
207
  mesh.userData.slotId = slotId;
128
- if (elevation < 0)
208
+ // Solid slabs bake [elevation − thickness, elevation] into the geometry;
209
+ // recessed shells are authored from floor to rim and translated so the
210
+ // floor sits at `elevation`.
211
+ if (node.recessed)
129
212
  mesh.position.y = elevation;
130
213
  group.add(mesh);
131
214
  }
215
+ if (node.fillToTerrain && !node.recessed) {
216
+ const terrainFill = buildSlabTerrainFillGeometry(node, getRenderableSlabPolygon(node, polygonContext), ctx);
217
+ if (terrainFill) {
218
+ const mesh = new Mesh(terrainFill, getSlabSlotMaterial(node, 'side', shading, textures, colorPreset, sceneTheme, ctx?.materials));
219
+ mesh.castShadow = true;
220
+ mesh.receiveShadow = true;
221
+ mesh.userData.slotId = 'side';
222
+ group.add(mesh);
223
+ }
224
+ }
132
225
  return group;
133
226
  }
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/slab/panel.tsx"],"names":[],"mappings":"AAmBA;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,uCAiQxB;AAED,eAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/slab/panel.tsx"],"names":[],"mappings":"AA+BA;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,uCA8ZxB;AAED,eAAe,SAAS,CAAA"}