@pascal-app/core 1.0.7 → 1.1.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 (266) hide show
  1. package/dist/agent-operations/__fixtures__/cases.d.ts +3 -2
  2. package/dist/agent-operations/__fixtures__/cases.d.ts.map +1 -1
  3. package/dist/agent-operations/__fixtures__/native-materials.d.ts +4 -0
  4. package/dist/agent-operations/__fixtures__/native-materials.d.ts.map +1 -1
  5. package/dist/agent-operations/__fixtures__/place-items-cases.d.ts.map +1 -1
  6. package/dist/agent-operations/__fixtures__/place-items-cases.js +28 -0
  7. package/dist/agent-operations/__fixtures__/roof-bearing-cases.d.ts +9567 -9563
  8. package/dist/agent-operations/__fixtures__/roof-bearing-cases.d.ts.map +1 -1
  9. package/dist/agent-operations/__fixtures__/verify-scene-cases.d.ts +77 -77
  10. package/dist/agent-operations/asset-catalog.d.ts +21 -11
  11. package/dist/agent-operations/asset-catalog.d.ts.map +1 -1
  12. package/dist/agent-operations/asset-catalog.js +28 -10
  13. package/dist/agent-operations/asset-views.d.ts +8 -3
  14. package/dist/agent-operations/asset-views.d.ts.map +1 -1
  15. package/dist/agent-operations/asset-views.js +19 -3
  16. package/dist/agent-operations/author-scene.d.ts.map +1 -1
  17. package/dist/agent-operations/author-scene.js +2 -3
  18. package/dist/agent-operations/batch.d.ts +7 -1
  19. package/dist/agent-operations/batch.d.ts.map +1 -1
  20. package/dist/agent-operations/batch.js +17 -2
  21. package/dist/agent-operations/catalog-asset.d.ts +15 -0
  22. package/dist/agent-operations/catalog-asset.d.ts.map +1 -0
  23. package/dist/agent-operations/catalog-asset.js +4 -0
  24. package/dist/agent-operations/circulation-spaces.d.ts +1724 -1723
  25. package/dist/agent-operations/circulation-spaces.d.ts.map +1 -1
  26. package/dist/agent-operations/design-brief.d.ts.map +1 -1
  27. package/dist/agent-operations/design-brief.js +2 -0
  28. package/dist/agent-operations/furnish-room.d.ts.map +1 -1
  29. package/dist/agent-operations/furnish-room.js +2 -1
  30. package/dist/agent-operations/index.d.ts +3 -0
  31. package/dist/agent-operations/index.d.ts.map +1 -1
  32. package/dist/agent-operations/index.js +4 -1
  33. package/dist/agent-operations/level-reads.d.ts.map +1 -1
  34. package/dist/agent-operations/level-reads.js +5 -2
  35. package/dist/agent-operations/move-plan.d.ts.map +1 -1
  36. package/dist/agent-operations/move-plan.js +11 -9
  37. package/dist/agent-operations/place-in-room.d.ts.map +1 -1
  38. package/dist/agent-operations/place-in-room.js +2 -1
  39. package/dist/agent-operations/place-items.d.ts.map +1 -1
  40. package/dist/agent-operations/place-items.js +2 -1
  41. package/dist/agent-operations/scene-queries.d.ts +2944 -2943
  42. package/dist/agent-operations/scene-queries.d.ts.map +1 -1
  43. package/dist/agent-operations/scene-view.d.ts.map +1 -1
  44. package/dist/agent-operations/scene-view.js +38 -13
  45. package/dist/agent-operations/search-assets.d.ts.map +1 -1
  46. package/dist/agent-operations/search-assets.js +6 -0
  47. package/dist/agent-operations/types.d.ts +3 -2
  48. package/dist/agent-operations/types.d.ts.map +1 -1
  49. package/dist/agent-operations/usage-checks.js +18 -3
  50. package/dist/agent-operations/verify-scene.d.ts.map +1 -1
  51. package/dist/agent-operations/verify-scene.js +4 -2
  52. package/dist/agent-operations/wall-object-observations.d.ts.map +1 -1
  53. package/dist/agent-operations/wall-object-observations.js +1 -1
  54. package/dist/agent-tools/assets.js +1 -1
  55. package/dist/agent-tools/wall-openings.js +2 -2
  56. package/dist/building/__fixtures__/wall-opening-cases.d.ts +13 -12
  57. package/dist/building/__fixtures__/wall-opening-cases.d.ts.map +1 -1
  58. package/dist/building/level-duplication.d.ts +1281 -1279
  59. package/dist/building/level-duplication.d.ts.map +1 -1
  60. package/dist/building/level-duplication.js +3 -1
  61. package/dist/building/merge-windows.d.ts.map +1 -1
  62. package/dist/building/merge-windows.js +4 -3
  63. package/dist/building/wall-openings.d.ts +95 -81
  64. package/dist/building/wall-openings.d.ts.map +1 -1
  65. package/dist/building/wall-openings.js +74 -25
  66. package/dist/commands/structure/shared.d.ts +3203 -3202
  67. package/dist/commands/structure/shared.d.ts.map +1 -1
  68. package/dist/commands/structure/zone-wall-merge.d.ts +2028 -2025
  69. package/dist/commands/structure/zone-wall-merge.d.ts.map +1 -1
  70. package/dist/contracts/reference-inventory.d.ts.map +1 -1
  71. package/dist/contracts/reference-inventory.js +0 -1
  72. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +6 -1
  73. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  74. package/dist/hooks/spatial-grid/spatial-grid-manager.js +30 -9
  75. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +2101 -2100
  76. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  77. package/dist/hooks/spatial-grid/spatial-grid-sync.js +8 -4
  78. package/dist/index.d.ts +13 -4
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +13 -4
  81. package/dist/lib/__fixtures__/mezzanine.d.ts +6428 -6424
  82. package/dist/lib/__fixtures__/mezzanine.d.ts.map +1 -1
  83. package/dist/lib/absorb-wall-separators.d.ts +2267 -2266
  84. package/dist/lib/absorb-wall-separators.d.ts.map +1 -1
  85. package/dist/lib/asset-storage.d.ts.map +1 -1
  86. package/dist/lib/asset-storage.js +3 -0
  87. package/dist/lib/build-mode.d.ts +11 -0
  88. package/dist/lib/build-mode.d.ts.map +1 -0
  89. package/dist/lib/build-mode.js +24 -0
  90. package/dist/lib/corner-pair.d.ts +2 -0
  91. package/dist/lib/corner-pair.d.ts.map +1 -1
  92. package/dist/lib/door-interaction.d.ts +14 -0
  93. package/dist/lib/door-interaction.d.ts.map +1 -0
  94. package/dist/lib/door-interaction.js +62 -0
  95. package/dist/lib/elevator-support.d.ts +15 -0
  96. package/dist/lib/elevator-support.d.ts.map +1 -0
  97. package/dist/lib/elevator-support.js +40 -0
  98. package/dist/lib/floor-foundation-datum.d.ts.map +1 -1
  99. package/dist/lib/floor-foundation-datum.js +5 -1
  100. package/dist/lib/floor-intent-changes.d.ts.map +1 -1
  101. package/dist/lib/floor-intent-changes.js +6 -4
  102. package/dist/lib/floorplan/context.d.ts +95 -0
  103. package/dist/lib/floorplan/context.d.ts.map +1 -0
  104. package/dist/lib/floorplan/context.js +155 -0
  105. package/dist/lib/floorplan/index.d.ts +6 -0
  106. package/dist/lib/floorplan/index.d.ts.map +1 -0
  107. package/dist/lib/floorplan/index.js +5 -0
  108. package/dist/lib/floorplan/marks.d.ts +71 -0
  109. package/dist/lib/floorplan/marks.d.ts.map +1 -0
  110. package/dist/lib/floorplan/marks.js +157 -0
  111. package/dist/lib/floorplan/plan-math.d.ts +18 -0
  112. package/dist/lib/floorplan/plan-math.d.ts.map +1 -0
  113. package/dist/lib/floorplan/plan-math.js +82 -0
  114. package/dist/lib/floorplan/svg-paths.d.ts +17 -0
  115. package/dist/lib/floorplan/svg-paths.d.ts.map +1 -0
  116. package/dist/lib/floorplan/svg-paths.js +92 -0
  117. package/dist/lib/floorplan/wall-affordances.d.ts +31 -0
  118. package/dist/lib/floorplan/wall-affordances.d.ts.map +1 -0
  119. package/dist/lib/floorplan/wall-affordances.js +24 -0
  120. package/dist/lib/hierarchy.d.ts +19 -0
  121. package/dist/lib/hierarchy.d.ts.map +1 -0
  122. package/dist/lib/hierarchy.js +53 -0
  123. package/dist/lib/opening-floor-datum.d.ts +1 -1
  124. package/dist/lib/opening-floor-datum.d.ts.map +1 -1
  125. package/dist/lib/opening-floor-datum.js +2 -2
  126. package/dist/lib/own-floor-intent.d.ts.map +1 -1
  127. package/dist/lib/own-floor-intent.js +2 -2
  128. package/dist/lib/polygon-boolean.d.ts.map +1 -1
  129. package/dist/lib/polygon-boolean.js +2 -1
  130. package/dist/lib/room-floor-elevation.d.ts +12 -0
  131. package/dist/lib/room-floor-elevation.d.ts.map +1 -0
  132. package/dist/lib/room-floor-elevation.js +41 -0
  133. package/dist/lib/room-floor-feasibility.d.ts.map +1 -1
  134. package/dist/lib/room-floor-feasibility.js +1 -1
  135. package/dist/lib/space-detection.d.ts.map +1 -1
  136. package/dist/lib/space-detection.js +1 -0
  137. package/dist/lib/wall-face-script.d.ts.map +1 -1
  138. package/dist/lib/wall-face-script.js +3 -3
  139. package/dist/lib/window-interaction.d.ts +16 -0
  140. package/dist/lib/window-interaction.d.ts.map +1 -0
  141. package/dist/lib/window-interaction.js +82 -0
  142. package/dist/lib/zone-quantities.js +1 -1
  143. package/dist/node-slots/column.d.ts +5 -0
  144. package/dist/node-slots/column.d.ts.map +1 -1
  145. package/dist/node-slots/column.js +10 -0
  146. package/dist/registry/__fixtures__/roof-planes.d.ts +69 -0
  147. package/dist/registry/__fixtures__/roof-planes.d.ts.map +1 -0
  148. package/dist/registry/__fixtures__/roof-planes.js +59 -0
  149. package/dist/registry/index.d.ts +3 -2
  150. package/dist/registry/index.d.ts.map +1 -1
  151. package/dist/registry/index.js +2 -1
  152. package/dist/registry/registry.d.ts +5 -0
  153. package/dist/registry/registry.d.ts.map +1 -1
  154. package/dist/registry/registry.js +10 -0
  155. package/dist/registry/roofs.d.ts +34 -0
  156. package/dist/registry/roofs.d.ts.map +1 -0
  157. package/dist/registry/roofs.js +61 -0
  158. package/dist/registry/types.d.ts +54 -0
  159. package/dist/registry/types.d.ts.map +1 -1
  160. package/dist/registry/validate-relations.d.ts +5 -1
  161. package/dist/registry/validate-relations.d.ts.map +1 -1
  162. package/dist/registry/validate-relations.js +6 -2
  163. package/dist/schema/asset-url.d.ts +8 -0
  164. package/dist/schema/asset-url.d.ts.map +1 -1
  165. package/dist/schema/asset-url.js +17 -0
  166. package/dist/schema/index.d.ts +1 -1
  167. package/dist/schema/index.d.ts.map +1 -1
  168. package/dist/schema/index.js +1 -1
  169. package/dist/schema/nodes/roof-segment-resize.d.ts.map +1 -1
  170. package/dist/schema/nodes/roof-segment-resize.js +2 -2
  171. package/dist/schema/nodes/roof-segment.d.ts +2 -0
  172. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  173. package/dist/schema/nodes/roof-segment.js +40 -2
  174. package/dist/schema/nodes/roof.d.ts +1 -1
  175. package/dist/schema/nodes/roof.d.ts.map +1 -1
  176. package/dist/schema/nodes/roof.js +13 -8
  177. package/dist/schema/nodes/wall.d.ts +1 -0
  178. package/dist/schema/nodes/wall.d.ts.map +1 -1
  179. package/dist/schema/nodes/wall.js +6 -0
  180. package/dist/schema/types.d.ts +2 -1
  181. package/dist/schema/types.d.ts.map +1 -1
  182. package/dist/services/index.d.ts +1 -1
  183. package/dist/services/index.d.ts.map +1 -1
  184. package/dist/services/index.js +1 -1
  185. package/dist/services/movement.d.ts +7 -0
  186. package/dist/services/movement.d.ts.map +1 -1
  187. package/dist/services/movement.js +13 -0
  188. package/dist/services/port-connectivity.d.ts +15 -6
  189. package/dist/services/port-connectivity.d.ts.map +1 -1
  190. package/dist/services/port-connectivity.js +83 -17
  191. package/dist/services/roof-bearing.js +2 -1
  192. package/dist/services/roof-level.d.ts.map +1 -1
  193. package/dist/services/roof-level.js +12 -2
  194. package/dist/services/roof-move.d.ts +4 -2
  195. package/dist/services/roof-move.d.ts.map +1 -1
  196. package/dist/services/roof-move.js +21 -9
  197. package/dist/services/storey.d.ts +6 -1
  198. package/dist/services/storey.d.ts.map +1 -1
  199. package/dist/services/storey.js +11 -2
  200. package/dist/spatial/usage-field/findings.d.ts +7 -1
  201. package/dist/spatial/usage-field/findings.d.ts.map +1 -1
  202. package/dist/spatial/usage-field/findings.js +42 -10
  203. package/dist/spatial/usage-field/path.d.ts.map +1 -1
  204. package/dist/spatial/usage-field/path.js +28 -18
  205. package/dist/spatial/usage-field/swings.d.ts +1 -0
  206. package/dist/spatial/usage-field/swings.d.ts.map +1 -1
  207. package/dist/spatial/usage-field/walls.d.ts +2 -0
  208. package/dist/spatial/usage-field/walls.d.ts.map +1 -1
  209. package/dist/spatial/usage-field/walls.js +18 -4
  210. package/dist/store/actions/node-actions.d.ts +2 -1
  211. package/dist/store/actions/node-actions.d.ts.map +1 -1
  212. package/dist/store/actions/node-actions.js +23 -5
  213. package/dist/store/derived-node-guard.d.ts.map +1 -1
  214. package/dist/store/derived-node-guard.js +2 -1
  215. package/dist/store/scene-annotations.d.ts +4634 -4632
  216. package/dist/store/scene-annotations.d.ts.map +1 -1
  217. package/dist/systems/document-reconcile.d.ts.map +1 -1
  218. package/dist/systems/document-reconcile.js +1 -2
  219. package/dist/systems/elevator/elevator-geometry.d.ts +25 -0
  220. package/dist/systems/elevator/elevator-geometry.d.ts.map +1 -1
  221. package/dist/systems/elevator/elevator-geometry.js +40 -8
  222. package/dist/systems/elevator/elevator-opening-sync.d.ts.map +1 -1
  223. package/dist/systems/elevator/elevator-opening-sync.js +4 -35
  224. package/dist/systems/elevator/elevator-runtime.d.ts.map +1 -1
  225. package/dist/systems/elevator/elevator-runtime.js +95 -18
  226. package/dist/systems/elevator/elevator-service.d.ts.map +1 -1
  227. package/dist/systems/elevator/elevator-service.js +24 -4
  228. package/dist/systems/roof/roof-elevation.d.ts +11 -6
  229. package/dist/systems/roof/roof-elevation.d.ts.map +1 -1
  230. package/dist/systems/roof/roof-elevation.js +26 -12
  231. package/dist/systems/slab/__fixtures__/floor-step.d.ts +5 -1
  232. package/dist/systems/slab/__fixtures__/floor-step.d.ts.map +1 -1
  233. package/dist/systems/slab/__fixtures__/raised-room.d.ts +2218 -2214
  234. package/dist/systems/slab/__fixtures__/raised-room.d.ts.map +1 -1
  235. package/dist/systems/stair/stair-opening-preview.d.ts +3203 -3202
  236. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  237. package/dist/systems/wall/wall-curve.d.ts +10 -0
  238. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  239. package/dist/systems/wall/wall-curve.js +38 -0
  240. package/dist/systems/wall/wall-frame.d.ts.map +1 -1
  241. package/dist/systems/wall/wall-frame.js +8 -0
  242. package/dist/systems/wall/wall-merge.d.ts +9 -1
  243. package/dist/systems/wall/wall-merge.d.ts.map +1 -1
  244. package/dist/systems/wall/wall-merge.js +38 -6
  245. package/dist/systems/wall/wall-top.d.ts +10 -3
  246. package/dist/systems/wall/wall-top.d.ts.map +1 -1
  247. package/dist/systems/wall/wall-top.js +24 -8
  248. package/dist/systems/wall/wall-topology.d.ts.map +1 -1
  249. package/dist/systems/wall/wall-topology.js +19 -1
  250. package/dist/utils/ensure-scene-openings.d.ts +5595 -5593
  251. package/dist/utils/ensure-scene-openings.d.ts.map +1 -1
  252. package/dist/utils/floor-plate-migration.d.ts +2267 -2266
  253. package/dist/utils/floor-plate-migration.d.ts.map +1 -1
  254. package/dist/utils/measurement-format.d.ts +27 -0
  255. package/dist/utils/measurement-format.d.ts.map +1 -0
  256. package/dist/utils/measurement-format.js +143 -0
  257. package/dist/utils/owned-floor-opening-migration.d.ts +653 -652
  258. package/dist/utils/owned-floor-opening-migration.d.ts.map +1 -1
  259. package/dist/utils/reconcile-structure-on-load.d.ts +1724 -1723
  260. package/dist/utils/reconcile-structure-on-load.d.ts.map +1 -1
  261. package/dist/utils/scene-bounds.d.ts +32 -0
  262. package/dist/utils/scene-bounds.d.ts.map +1 -0
  263. package/dist/utils/scene-bounds.js +201 -0
  264. package/dist/validation/validate-build-json.d.ts.map +1 -1
  265. package/dist/validation/validate-build-json.js +3 -1
  266. package/package.json +1 -1
@@ -110,9 +110,9 @@ export function ownFloorIntentChanges(nodes, updates) {
110
110
  const current = next[old.id];
111
111
  if (old.type !== 'wall' || current?.type !== 'wall' || !old.parentId)
112
112
  continue;
113
- const oldTop = getWallTop(old, old.parentId, nodes, wallSupportForNodes(old, nodes).elevation);
113
+ const oldTop = getWallTop(old, old.parentId, nodes, wallSupportForNodes(old, nodes).elevation, 0);
114
114
  const support = wallSupportForNodes(current, next).elevation;
115
- const newTop = getWallTop(current, current.parentId, next, support);
115
+ const newTop = getWallTop(current, current.parentId, next, support, 0);
116
116
  if (Math.abs(oldTop - newTop) <= 1e-6)
117
117
  continue;
118
118
  if (oldTop - support < MIN_WALL_HEIGHT)
@@ -1 +1 @@
1
- {"version":3,"file":"polygon-boolean.d.ts","sourceRoot":"","sources":["../../src/lib/polygon-boolean.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;AACrC,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAA;AACpD,MAAM,MAAM,YAAY,GAAG,OAAO,EAAE,CAAA;AACpC,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,OAAO,GAAG,YAAY,CAAA;AAoIxD,wBAAgB,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,CAKnE;AAED,wBAAgB,UAAU,CACxB,CAAC,EAAE,YAAY,EACf,CAAC,EAAE,YAAY,EACf,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,YAAY,CAUd;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,YAAY,CA2B3E;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAQhD;AAgCD,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAW/E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAMnF"}
1
+ {"version":3,"file":"polygon-boolean.d.ts","sourceRoot":"","sources":["../../src/lib/polygon-boolean.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;AACrC,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAA;AACpD,MAAM,MAAM,YAAY,GAAG,OAAO,EAAE,CAAA;AACpC,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,OAAO,GAAG,YAAY,CAAA;AAoIxD,wBAAgB,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,CAKnE;AAED,wBAAgB,UAAU,CACxB,CAAC,EAAE,YAAY,EACf,CAAC,EAAE,YAAY,EACf,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,YAAY,CAUd;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,YAAY,CA2B3E;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAQhD;AAgCD,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAW/E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAMnF"}
@@ -1,4 +1,5 @@
1
1
  import clipping from 'polygon-clipping';
2
+ import { isDevelopmentBuild } from './build-mode.js';
2
3
  const SCALE = 10_000;
3
4
  const MIN_AREA = 1e-6;
4
5
  // Relative to the first vertex: absolute products at large coordinates (1e9 m
@@ -98,7 +99,7 @@ function clip(operation, inputs, run, throwOnError = false) {
98
99
  catch (error) {
99
100
  if (throwOnError)
100
101
  throw error;
101
- if (process.env.NODE_ENV !== 'production') {
102
+ if (isDevelopmentBuild()) {
102
103
  const caller = new Error('Polygon clipping caller').stack
103
104
  ?.split('\n')
104
105
  .slice(1)
@@ -0,0 +1,12 @@
1
+ import type { AnyNode, SlabNode } from '../schema/index.js';
2
+ type Nodes = Readonly<Record<string, AnyNode>>;
3
+ /** The level's footprints, largest first (ties by id, so the order is stable). */
4
+ export declare function levelFootprints(nodes: Record<string, AnyNode>, levelId: string): SlabNode[];
5
+ /** A room's separate base plate, only when no other ground room shares it. */
6
+ export declare function roomOwnPlate(nodes: Nodes, zoneId: string): SlabNode | null;
7
+ /** The walking surface of a room: its own elevation, else its plate's. */
8
+ export declare function roomFloorElevation(nodes: Nodes, zoneId: string): number;
9
+ /** The walking surface of a room the separator closes, else zero. */
10
+ export declare function separatorFloorElevation(nodes: Nodes, separatorId: string): number;
11
+ export {};
12
+ //# sourceMappingURL=room-floor-elevation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-floor-elevation.d.ts","sourceRoot":"","sources":["../../src/lib/room-floor-elevation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAY,MAAM,WAAW,CAAA;AAG5D,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAK9C,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE,CAW3F;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAW1E;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAUvE;AAED,qEAAqE;AACrE,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAKjF"}
@@ -0,0 +1,41 @@
1
+ import { area } from './polygon-boolean.js';
2
+ const isRoom = (node) => node?.type === 'zone' && node.spaceRole === 'room';
3
+ const isGroundRoom = (node) => isRoom(node) && node.floor?.support !== 'open';
4
+ /** The level's footprints, largest first (ties by id, so the order is stable). */
5
+ export function levelFootprints(nodes, levelId) {
6
+ return Object.values(nodes)
7
+ .filter((node) => node.type === 'slab' && node.plateRole === 'base' && node.parentId === levelId)
8
+ .sort((a, b) => area([{ outer: b.polygon, holes: b.holes }]) -
9
+ area([{ outer: a.polygon, holes: a.holes }]) || a.id.localeCompare(b.id));
10
+ }
11
+ /** A room's separate base plate, only when no other ground room shares it. */
12
+ export function roomOwnPlate(nodes, zoneId) {
13
+ const zone = nodes[zoneId];
14
+ if (!isRoom(zone) || !zone.floor?.footprint || zone.floor.support === 'open')
15
+ return null;
16
+ const plate = zone.parentId
17
+ ? levelFootprints(nodes, zone.parentId).find((plate) => plate.zoneIds?.includes(zoneId))
18
+ : null;
19
+ if (!plate)
20
+ return null;
21
+ const alone = !(plate.zoneIds ?? []).some((id) => id !== zoneId && isGroundRoom(nodes[id]));
22
+ return alone ? plate : null;
23
+ }
24
+ /** The walking surface of a room: its own elevation, else its plate's. */
25
+ export function roomFloorElevation(nodes, zoneId) {
26
+ const zone = nodes[zoneId];
27
+ if (zone?.type !== 'zone')
28
+ return 0;
29
+ const own = roomOwnPlate(nodes, zoneId);
30
+ if (own)
31
+ return own.elevation;
32
+ if (typeof zone.floor?.elevation === 'number')
33
+ return zone.floor.elevation;
34
+ const plate = Object.values(nodes).find((node) => node.type === 'slab' && node.zoneIds?.includes(zoneId));
35
+ return plate?.type === 'slab' ? (plate.elevation ?? 0.05) : 0.05;
36
+ }
37
+ /** The walking surface of a room the separator closes, else zero. */
38
+ export function separatorFloorElevation(nodes, separatorId) {
39
+ const zone = Object.values(nodes).find((node) => node.type === 'zone' && node.boundarySeparatorIds.includes(separatorId));
40
+ return zone ? roomFloorElevation(nodes, zone.id) : 0;
41
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"room-floor-feasibility.d.ts","sourceRoot":"","sources":["../../src/lib/room-floor-feasibility.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAsB,MAAM,WAAW,CAAA;AAC5D,OAAO,EAEL,0BAA0B,EAC1B,kBAAkB,EACnB,MAAM,sBAAsB,CAAA;AAgB7B,eAAO,MAAM,uBAAuB,QAAQ,CAAA;AAC5C,OAAO,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,CAAA;AAEzD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EACA,wBAAwB,GACxB,gCAAgC,GAChC,uBAAuB,GACvB,gBAAgB,GAChB,gBAAgB,GAChB,mBAAmB,GACnB,mBAAmB,GACnB,oBAAoB,GACpB,oBAAoB,GACpB,iBAAiB,GACjB,kBAAkB,CAAA;IACtB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAID,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,GACb,MAAM,CA8CR;AAID,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,OAAO,EAAE,MAAM,GACd,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAoE7B;AAID,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,MAAM;;;;;;EAa1B;AAwKD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,GACb,MAAM,CAMR;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,CAWR"}
1
+ {"version":3,"file":"room-floor-feasibility.d.ts","sourceRoot":"","sources":["../../src/lib/room-floor-feasibility.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAsB,MAAM,WAAW,CAAA;AAC5D,OAAO,EAEL,0BAA0B,EAC1B,kBAAkB,EACnB,MAAM,sBAAsB,CAAA;AAgB7B,eAAO,MAAM,uBAAuB,QAAQ,CAAA;AAC5C,OAAO,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,CAAA;AAEzD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EACA,wBAAwB,GACxB,gCAAgC,GAChC,uBAAuB,GACvB,gBAAgB,GAChB,gBAAgB,GAChB,mBAAmB,GACnB,mBAAmB,GACnB,oBAAoB,GACpB,oBAAoB,GACpB,iBAAiB,GACjB,kBAAkB,CAAA;IACtB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAID,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,GACb,MAAM,CA8CR;AAID,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,OAAO,EAAE,MAAM,GACd,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAoE7B;AAID,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,MAAM;;;;;;EAa1B;AA2KD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,GACb,MAAM,CAMR;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,CAWR"}
@@ -176,7 +176,7 @@ function computeRoomFloor(nodes, zoneId, proposedElevation) {
176
176
  for (const wall of walls) {
177
177
  const hasOpenings = wall.children.some((id) => nodes[id]?.type === 'door' || nodes[id]?.type === 'window');
178
178
  const support = hasOpenings || wall.height !== undefined ? wallSupportForNodes(wall, candidate) : undefined;
179
- const top = getWallTop(wall, level.id, nodes, support?.elevation ?? 0);
179
+ const top = Math.min(getWallTop(wall, level.id, nodes, support?.elevation ?? 0, 0), getWallTop(wall, level.id, nodes, support?.elevation ?? 0, 1));
180
180
  const openingSpans = hasOpenings && linked
181
181
  ? (roomFace(nodes, zone, floorRoomFaces(boundaries(nodes, zone.parentId)))?.spans ?? [])
182
182
  : spans;
@@ -1 +1 @@
1
- {"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EAGd,MAAM,WAAW,CAAA;AAuBlB,OAAO,EACL,KAAK,aAAa,EAIlB,KAAK,iBAAiB,EAGvB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,KAAK,YAAY,EAAqB,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAG/F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAG/D,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAEzE;AAID,OAAO,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEvF,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IACtC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9B,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,SAAS,GAAG,UAAU,CAAA;IAChC,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,wBAAwB,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAA;CACnE,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;IAC9C,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;CAC9C,CAAA;AA8PD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAkKrC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE;;;;;EAE1E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,CAMxF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,CAWxF;AA+CD,qFAAqF;AACrF,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAED,6DAA6D;AAC7D,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,wBAAgB,uBAAuB,qCAMtC;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,GAAG,EACf,WAAW,EAAE,GAAG,EAChB,OAAO,GAAE,yBAA8B,GACtC,MAAM,IAAI,CAuLZ;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAiBjF"}
1
+ {"version":3,"file":"space-detection.d.ts","sourceRoot":"","sources":["../../src/lib/space-detection.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EAGd,MAAM,WAAW,CAAA;AAuBlB,OAAO,EACL,KAAK,aAAa,EAIlB,KAAK,iBAAiB,EAGvB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,KAAK,YAAY,EAAqB,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAG/F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAG/D,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAEzE;AAID,OAAO,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEvF,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IACtC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9B,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,SAAS,GAAG,UAAU,CAAA;IAChC,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,wBAAwB,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAA;CACnE,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;IAC9C,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;CAC9C,CAAA;AA+PD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAkKrC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE;;;;;EAE1E;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,CAMxF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,CAWxF;AA+CD,qFAAqF;AACrF,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAED,6DAA6D;AAC7D,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED,wBAAgB,uBAAuB,qCAMtC;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,GAAG,EACf,WAAW,EAAE,GAAG,EAChB,OAAO,GAAE,yBAA8B,GACtC,MAAM,IAAI,CAuLZ;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAiBjF"}
@@ -41,6 +41,7 @@ function wallGeometrySignature(wall, nodes, levelId) {
41
41
  : typeof wall.height === 'number'
42
42
  ? wall.height.toFixed(4)
43
43
  : String(wall.height),
44
+ (wall.endHeightOffset ?? 0).toFixed(4),
44
45
  wall.supportSlabId ?? 'elected',
45
46
  (wall.supportOffset ?? 0).toFixed(4),
46
47
  getClampedWallCurveOffset(wall).toFixed(4),
@@ -1 +1 @@
1
- {"version":3,"file":"wall-face-script.d.ts","sourceRoot":"","sources":["../../src/lib/wall-face-script.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,sBAAsB,EAEtB,cAAc,EAGf,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAenE,KAAK,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAEnD,kEAAkE;AAClE,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7E;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,YAAY,CAAA;IACrB,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAKD,iGAAiG;AACjG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAOnF;AAmID;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,EACd,QAAQ,CAAC,EAAE,MAAM,GAChB,oBAAoB,GAAG,IAAI,CAgC7B;AAED,0FAA0F;AAC1F,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAI5E;AAED,mGAAmG;AACnG,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,sBAAsB,EAChC,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,CAAC,EAAE,cAAc,GACxB,cAAc,CAMhB;AAKD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,GACb;IAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAYhF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,MAAM,GACd,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAGzB;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,2BAA2B,CAAA;IACjC,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,IAAI,EAAE,MAAM,GACX,oBAAoB,GAAG,SAAS,CAkBlC"}
1
+ {"version":3,"file":"wall-face-script.d.ts","sourceRoot":"","sources":["../../src/lib/wall-face-script.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,sBAAsB,EAEtB,cAAc,EAGf,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAenE,KAAK,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAEnD,kEAAkE;AAClE,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7E;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,YAAY,CAAA;IACrB,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAKD,iGAAiG;AACjG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAOnF;AA0ID;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,EACd,QAAQ,CAAC,EAAE,MAAM,GAChB,oBAAoB,GAAG,IAAI,CAgC7B;AAED,0FAA0F;AAC1F,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAI5E;AAED,mGAAmG;AACnG,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,sBAAsB,EAChC,MAAM,EAAE,oBAAoB,EAC5B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,QAAQ,CAAC,EAAE,cAAc,GACxB,cAAc,CAMhB;AAKD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,QAAQ,GACb;IAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAYhF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,MAAM,GACd,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAGzB;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,2BAA2B,CAAA;IACjC,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,IAAI,EAAE,MAAM,GACX,oBAAoB,GAAG,SAAS,CAkBlC"}
@@ -1,5 +1,5 @@
1
- import { getWallTop } from '../services/storey.js';
2
- import { isCurvedWall } from '../systems/wall/wall-curve.js';
1
+ import { getWallTopOver } from '../services/storey.js';
2
+ import { getWallCurveLength, isCurvedWall } from '../systems/wall/wall-curve.js';
3
3
  import { parseWallPaintRole } from '../systems/wall/wall-finish.js';
4
4
  import { getWallThickness } from '../systems/wall/wall-footprint.js';
5
5
  import { getWallLocalFaceZ } from '../systems/wall/wall-frame.js';
@@ -56,7 +56,7 @@ function faceFrame(nodes, wallId, face) {
56
56
  const length = Math.hypot(dx, dz);
57
57
  const support = wallSupportForNodes(wall, nodes);
58
58
  const offset = wallFaceBaseOffset(support, face);
59
- const top = getWallTop(wall, wall.parentId, nodes, support.elevation) -
59
+ const top = getWallTopOver(wall, wall.parentId, nodes, support.elevation, 0, getWallCurveLength(wall)) -
60
60
  support.elevation -
61
61
  offset;
62
62
  const station = (point) => ((point.x - wall.start[0]) * dx + (point.y - wall.start[1]) * dz) / length;
@@ -0,0 +1,16 @@
1
+ import type { AnyNodeId } from '../schema/types.js';
2
+ import { type InteractiveState, type WindowInteractiveState } from '../store/use-interactive.js';
3
+ export declare const WINDOW_TOGGLE_ANIMATION_MS = 520;
4
+ export type WindowOpenAnimationOptions = {
5
+ persist?: boolean;
6
+ };
7
+ export declare function isOperableWindowType(windowType: string | undefined): windowType is "awning" | "casement" | "double-hung" | "hopper" | "louvered" | "single-hung" | "sliding" | "tilt-turn";
8
+ export declare function getDisplayedWindowValue(windowId: AnyNodeId, nodeValue: number | undefined, field?: keyof WindowInteractiveState, interactive?: InteractiveState): number;
9
+ export declare function toggleWindowOpenState(windowId: AnyNodeId, options?: WindowOpenAnimationOptions): void;
10
+ export declare function closeWindowOpenState(windowId: AnyNodeId, options?: WindowOpenAnimationOptions): void;
11
+ export declare function openWindowOpenState(windowId: AnyNodeId, options?: WindowOpenAnimationOptions): void;
12
+ export type WindowShutterField = 'shutterOpen' | 'rollerShutterOpen';
13
+ export declare function getDisplayedWindowShutterValue(windowId: AnyNodeId, field: WindowShutterField, nodeValue: number | undefined, state?: InteractiveState): number;
14
+ /** Preview both shutter styles together, independently of the sash. */
15
+ export declare function setWindowShuttersOpenState(windowId: AnyNodeId, on: boolean, options?: WindowOpenAnimationOptions): void;
16
+ //# sourceMappingURL=window-interaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window-interaction.d.ts","sourceRoot":"","sources":["../../src/lib/window-interaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,sBAAsB,EAC5B,MAAM,0BAA0B,CAAA;AAGjC,eAAO,MAAM,0BAA0B,MAAM,CAAA;AAE7C,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,yHAWlE;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,SAAS,EACnB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,KAAK,GAAE,MAAM,sBAAyC,EACtD,WAAW,GAAE,gBAA4C,UAS1D;AAmBD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,0BAA0B,QAkB9F;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,0BAA0B,QAY7F;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,0BAA0B,QAY5F;AAED,MAAM,MAAM,kBAAkB,GAAG,aAAa,GAAG,mBAAmB,CAAA;AAEpE,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,SAAS,EACnB,KAAK,EAAE,kBAAkB,EACzB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,KAAK,GAAE,gBAA4C,GAClD,MAAM,CAER;AAED,uEAAuE;AACvE,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,SAAS,EACnB,EAAE,EAAE,OAAO,EACX,OAAO,CAAC,EAAE,0BAA0B,GACnC,IAAI,CAkBN"}
@@ -0,0 +1,82 @@
1
+ import { useInteractive, } from '../store/use-interactive.js';
2
+ import useScene from '../store/use-scene.js';
3
+ export const WINDOW_TOGGLE_ANIMATION_MS = 520;
4
+ export function isOperableWindowType(windowType) {
5
+ return (windowType === 'sliding' ||
6
+ windowType === 'casement' ||
7
+ windowType === 'awning' ||
8
+ windowType === 'hopper' ||
9
+ windowType === 'tilt-turn' ||
10
+ windowType === 'single-hung' ||
11
+ windowType === 'double-hung' ||
12
+ windowType === 'louvered');
13
+ }
14
+ export function getDisplayedWindowValue(windowId, nodeValue, field = 'operationState', interactive = useInteractive.getState()) {
15
+ const runtimeValue = interactive.windows[windowId]?.[field];
16
+ if (runtimeValue !== undefined)
17
+ return runtimeValue;
18
+ const queuedValue = interactive.windowAnimations[windowId]?.[field]?.from;
19
+ if (queuedValue !== undefined)
20
+ return queuedValue;
21
+ return nodeValue ?? 0;
22
+ }
23
+ function startWindowOpenAnimation(windowId, field, from, to, options) {
24
+ useInteractive.getState().startWindowAnimation(windowId, {
25
+ field,
26
+ from,
27
+ to,
28
+ startedAt: null,
29
+ durationMs: WINDOW_TOGGLE_ANIMATION_MS,
30
+ persist: options?.persist ?? true,
31
+ });
32
+ }
33
+ export function toggleWindowOpenState(windowId, options) {
34
+ const node = useScene.getState().nodes[windowId];
35
+ if (node?.type !== 'window' ||
36
+ node.openingKind === 'opening' ||
37
+ !isOperableWindowType(node.windowType)) {
38
+ return;
39
+ }
40
+ const currentOpenAmount = getDisplayedWindowValue(windowId, node.operationState);
41
+ startWindowOpenAnimation(windowId, 'operationState', currentOpenAmount, currentOpenAmount >= 0.5 ? 0 : 1, options);
42
+ }
43
+ export function closeWindowOpenState(windowId, options) {
44
+ const node = useScene.getState().nodes[windowId];
45
+ if (node?.type !== 'window' ||
46
+ node.openingKind === 'opening' ||
47
+ !isOperableWindowType(node.windowType)) {
48
+ return;
49
+ }
50
+ const currentOpenAmount = getDisplayedWindowValue(windowId, node.operationState);
51
+ startWindowOpenAnimation(windowId, 'operationState', currentOpenAmount, 0, options);
52
+ }
53
+ export function openWindowOpenState(windowId, options) {
54
+ const node = useScene.getState().nodes[windowId];
55
+ if (node?.type !== 'window' ||
56
+ node.openingKind === 'opening' ||
57
+ !isOperableWindowType(node.windowType)) {
58
+ return;
59
+ }
60
+ const currentOpenAmount = getDisplayedWindowValue(windowId, node.operationState);
61
+ startWindowOpenAnimation(windowId, 'operationState', currentOpenAmount, 1, options);
62
+ }
63
+ export function getDisplayedWindowShutterValue(windowId, field, nodeValue, state = useInteractive.getState()) {
64
+ return getDisplayedWindowValue(windowId, nodeValue ?? 1, field, state);
65
+ }
66
+ /** Preview both shutter styles together, independently of the sash. */
67
+ export function setWindowShuttersOpenState(windowId, on, options) {
68
+ const node = useScene.getState().nodes[windowId];
69
+ if (node?.type !== 'window' || node.source)
70
+ return;
71
+ const fields = [];
72
+ if (node.shutters && node.shutters !== 'none')
73
+ fields.push('shutterOpen');
74
+ if (node.rollerShutter === 'box' || node.rollerShutter === 'concealed')
75
+ fields.push('rollerShutterOpen');
76
+ if (!fields.length)
77
+ return;
78
+ useInteractive.getState().setMechanismPart(windowId, 'shutters', on);
79
+ for (const field of fields) {
80
+ startWindowOpenAnimation(windowId, field, getDisplayedWindowShutterValue(windowId, field, node[field]), on ? 1 : 0, options);
81
+ }
82
+ }
@@ -233,7 +233,7 @@ export function deriveZoneQuantityReport(zone, sceneNodes) {
233
233
  const slabs = levelNodes.filter((node) => node.type === 'slab');
234
234
  const wallEffectiveHeight = (wall) => {
235
235
  const support = computeWallSlabSupport(wall, slabs, walls, wall.supportSlabId, undefined, 0, sceneNodes);
236
- return getWallTop(wall, levelId ?? '', sceneNodes, support.elevation) - support.elevation;
236
+ return getWallTop(wall, levelId ?? '', sceneNodes, support.elevation, 0.5) - support.elevation;
237
237
  };
238
238
  const edgeLengths = [zone.polygon, ...(zone.holes ?? [])].flatMap((ring) => ring.map((start, index) => {
239
239
  const end = ring[(index + 1) % ring.length];
@@ -5,5 +5,10 @@ export declare const COLUMN_SHAFT_DEFAULT = "library:concrete-plaster";
5
5
  export declare const COLUMN_BASE_DEFAULT = "library:concrete-plaster";
6
6
  export declare const COLUMN_CAPITAL_DEFAULT = "library:concrete-plaster";
7
7
  export declare const COLUMN_FRAME_DEFAULT = "library:metal-steel";
8
+ /**
9
+ * Written onto newly created columns. The slot defaults above stay the render
10
+ * fallback, so saved columns that never had `slots` keep their look (E-003).
11
+ */
12
+ export declare const NEW_COLUMN_SLOTS: Readonly<Record<ColumnSlotId, string>>;
8
13
  export declare function columnSlots(node: ColumnNode): SlotDeclaration[];
9
14
  //# sourceMappingURL=column.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"column.d.ts","sourceRoot":"","sources":["../../src/node-slots/column.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;AAEjE,eAAO,MAAM,oBAAoB,6BAA6B,CAAA;AAC9D,eAAO,MAAM,mBAAmB,6BAA6B,CAAA;AAC7D,eAAO,MAAM,sBAAsB,6BAA6B,CAAA;AAChE,eAAO,MAAM,oBAAoB,wBAAwB,CAAA;AAEzD,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,EAAE,CAuB/D"}
1
+ {"version":3,"file":"column.d.ts","sourceRoot":"","sources":["../../src/node-slots/column.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;AAEjE,eAAO,MAAM,oBAAoB,6BAA6B,CAAA;AAC9D,eAAO,MAAM,mBAAmB,6BAA6B,CAAA;AAC7D,eAAO,MAAM,sBAAsB,6BAA6B,CAAA;AAChE,eAAO,MAAM,oBAAoB,wBAAwB,CAAA;AAEzD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAKnE,CAAA;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,eAAe,EAAE,CAuB/D"}
@@ -2,6 +2,16 @@ export const COLUMN_SHAFT_DEFAULT = 'library:concrete-plaster';
2
2
  export const COLUMN_BASE_DEFAULT = 'library:concrete-plaster';
3
3
  export const COLUMN_CAPITAL_DEFAULT = 'library:concrete-plaster';
4
4
  export const COLUMN_FRAME_DEFAULT = 'library:metal-steel';
5
+ /**
6
+ * Written onto newly created columns. The slot defaults above stay the render
7
+ * fallback, so saved columns that never had `slots` keep their look (E-003).
8
+ */
9
+ export const NEW_COLUMN_SLOTS = {
10
+ shaft: 'library:preset-white',
11
+ base: 'library:preset-white',
12
+ capital: 'library:preset-white',
13
+ frame: 'library:preset-white',
14
+ };
5
15
  export function columnSlots(node) {
6
16
  if (node.source)
7
17
  return node.source.manifest.slots.map((slot) => ({
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod';
2
+ import type { AnyNode } from '../../schema/types.js';
3
+ /**
4
+ * A plugin's solved roof plane, as an architect's roof holds it (`capabilities.roofs`): an outline
5
+ * in its roof's plan, rising from a baseline at a pitch (rise per 12 of run).
6
+ */
7
+ export declare const RoofPlane: z.ZodObject<{
8
+ object: z.ZodDefault<z.ZodLiteral<"node">>;
9
+ name: z.ZodOptional<z.ZodString>;
10
+ parentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
11
+ visible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
12
+ camera: z.ZodOptional<z.ZodObject<{
13
+ position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
14
+ target: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
15
+ mode: z.ZodDefault<z.ZodEnum<{
16
+ orthographic: "orthographic";
17
+ perspective: "perspective";
18
+ }>>;
19
+ fov: z.ZodOptional<z.ZodNumber>;
20
+ zoom: z.ZodOptional<z.ZodNumber>;
21
+ }, z.core.$strip>>;
22
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
23
+ provenance: z.ZodOptional<z.ZodObject<{
24
+ refs: z.ZodArray<z.ZodObject<{
25
+ ns: z.ZodOptional<z.ZodString>;
26
+ id: z.ZodString;
27
+ role: z.ZodOptional<z.ZodEnum<{
28
+ absorbed: "absorbed";
29
+ alias: "alias";
30
+ derived: "derived";
31
+ piece: "piece";
32
+ primary: "primary";
33
+ }>>;
34
+ }, z.core.$strip>>;
35
+ lineage: z.ZodOptional<z.ZodObject<{
36
+ op: z.ZodEnum<{
37
+ attach: "attach";
38
+ convert: "convert";
39
+ duplicate: "duplicate";
40
+ import: "import";
41
+ "make-independent": "make-independent";
42
+ merge: "merge";
43
+ promote: "promote";
44
+ split: "split";
45
+ }>;
46
+ fromIds: z.ZodArray<z.ZodString>;
47
+ }, z.core.$strip>>;
48
+ }, z.core.$strip>>;
49
+ id: z.ZodDefault<z.ZodTemplateLiteral<`roofplane_${string}`>>;
50
+ type: z.ZodDefault<z.ZodLiteral<"test:roof-plane">>;
51
+ polygon: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
52
+ baseline: z.ZodTuple<[z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>], null>;
53
+ baseHeight: z.ZodNumber;
54
+ pitch: z.ZodNumber;
55
+ }, z.core.$strip>;
56
+ export type RoofPlane = z.infer<typeof RoofPlane>;
57
+ /** The plane's surface over its roof's origin at a plan point: its eave, plus the rise of the run off it. */
58
+ export declare function roofPlaneHeightAt(plane: RoofPlane, x: number, z: number): number;
59
+ /** Registers the planes' kind; the test setup restores the registry after each test. */
60
+ export declare function registerRoofPlanes(): void;
61
+ /**
62
+ * A plane over the plan rectangle [x0, z0] to [x1, z1] of its roof, its eave along z0 at `eave`,
63
+ * rising toward z1 at `pitch` in 12.
64
+ */
65
+ export declare function roofPlane(id: string, [x0, z0, x1, z1]: [number, number, number, number], eave: number, { pitch, parentId }?: {
66
+ pitch?: number;
67
+ parentId?: string | null;
68
+ }): AnyNode;
69
+ //# sourceMappingURL=roof-planes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roof-planes.d.ts","sourceRoot":"","sources":["../../../src/registry/__fixtures__/roof-planes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAMjD;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOpB,CAAA;AACF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA;AAEjD,6GAA6G;AAC7G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAIhF;AAOD,wFAAwF;AACxF,wBAAgB,kBAAkB,IAAI,IAAI,CASzC;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClD,IAAI,EAAE,MAAM,EACZ,EAAE,KAAS,EAAE,QAAe,EAAE,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAChF,OAAO,CAiBT"}
@@ -0,0 +1,59 @@
1
+ import { z } from 'zod';
2
+ import { BaseNode, nodeType, objectId } from '../../schema/base.js';
3
+ import { registerNode } from '../registry.js';
4
+ const Pt = z.tuple([z.number(), z.number()]);
5
+ /**
6
+ * A plugin's solved roof plane, as an architect's roof holds it (`capabilities.roofs`): an outline
7
+ * in its roof's plan, rising from a baseline at a pitch (rise per 12 of run).
8
+ */
9
+ export const RoofPlane = BaseNode.extend({
10
+ id: objectId('roofplane'),
11
+ type: nodeType('test:roof-plane'),
12
+ polygon: z.array(Pt),
13
+ baseline: z.tuple([Pt, Pt]),
14
+ baseHeight: z.number(),
15
+ pitch: z.number(),
16
+ });
17
+ /** The plane's surface over its roof's origin at a plan point: its eave, plus the rise of the run off it. */
18
+ export function roofPlaneHeightAt(plane, x, z) {
19
+ const [[ax, az], [bx, bz]] = plane.baseline;
20
+ const run = Math.abs((x - ax) * (bz - az) - (z - az) * (bx - ax)) / Math.hypot(bx - ax, bz - az);
21
+ return plane.baseHeight + (run * plane.pitch) / 12;
22
+ }
23
+ const roofs = {
24
+ outline: (node) => node.polygon,
25
+ heightAt: (node, x, z) => roofPlaneHeightAt(node, x, z),
26
+ };
27
+ /** Registers the planes' kind; the test setup restores the registry after each test. */
28
+ export function registerRoofPlanes() {
29
+ registerNode({
30
+ kind: 'test:roof-plane',
31
+ schemaVersion: 1,
32
+ schema: RoofPlane,
33
+ category: 'structure',
34
+ defaults: () => ({}),
35
+ capabilities: { roofs },
36
+ });
37
+ }
38
+ /**
39
+ * A plane over the plan rectangle [x0, z0] to [x1, z1] of its roof, its eave along z0 at `eave`,
40
+ * rising toward z1 at `pitch` in 12.
41
+ */
42
+ export function roofPlane(id, [x0, z0, x1, z1], eave, { pitch = 6, parentId = null } = {}) {
43
+ return RoofPlane.parse({
44
+ id,
45
+ parentId,
46
+ polygon: [
47
+ [x0, z0],
48
+ [x1, z0],
49
+ [x1, z1],
50
+ [x0, z1],
51
+ ],
52
+ baseline: [
53
+ [x0, z0],
54
+ [x1, z0],
55
+ ],
56
+ baseHeight: eave,
57
+ pitch,
58
+ });
59
+ }
@@ -1,9 +1,10 @@
1
1
  export type { ArcResizeHandle, CornerRadiusHandle, Cursor, EditorApi, EndpointMoveHandle, HandleAnchor, HandleAxis, HandleDescriptor, HandleDragModifiers, HandleList, HandlePlacement, HandlePortal, HandlePreviewSession, LatchHandle, LinearResizeHandle, RadialResizeHandle, TapActionHandle, TranslateHandle, } from './handles.js';
2
2
  export { nodeMechanism, nodeMechanismParts, toggleMechanism, toggleMechanismPart, toggleNodeMechanism, } from './mechanism.js';
3
- export { bakePolicyOf, discoverPlugins, extendPluginDiscovery, floorPlacedCollides, getHostRefFields, getInspectorExtensions, getNodePluginId, getRegistryVersion, getSelectableKinds, hasRegistry3DMoveTool, isDrawnViaTool, isDrawnViaToolKind, isNodeKindEnabled, isPresettable, isPresettableKind, isRegistryMovable, isRegistrySelectable, isSelectionHighlightEnabled, kindsWithBakePolicy, kindsWithFloorplanScope, loadPlugin, nodeRegistry, onRegistryChange, type PluginDiscovery, registerNode, resolveFacingIndicator, setPluginDiscovery, } from './registry.js';
3
+ export { bakePolicyOf, discoverPlugins, extendPluginDiscovery, floorPlacedCollides, getHostRefFields, getInspectorExtensions, getNodePluginId, getRegistryVersion, getSelectableKinds, hasRegistry3DMoveTool, isDrawnViaTool, isDrawnViaToolKind, isNodeDuplicable, isNodeKindEnabled, isPresettable, isPresettableKind, isRegistryMovable, isRegistrySelectable, isSelectionHighlightEnabled, kindsWithBakePolicy, kindsWithFloorplanScope, loadPlugin, nodeRegistry, onRegistryChange, type PluginDiscovery, registerNode, resolveFacingIndicator, setPluginDiscovery, } from './registry.js';
4
4
  export { type CascadeContext, type ChildQuery, cascadeDirty, collectDescendants, type SpatialQuery, } from './relations-resolver.js';
5
+ export { type RoofFaceShape, roofFaceOf, roofFaceShapes, validateRoofRelations } from './roofs.js';
5
6
  export { createSceneApi, type SceneStoreLike, type SceneToolHost } from './scene-api.js';
6
7
  export { type CloneNodesIntoOptions, type CloneNodesIntoResult, cloneNodesInto, collectSubtree, type Subtree, withoutSourceIdentity, } from './subtree.js';
7
- export type { Affordance, AlignmentFootprint, AlignmentFootprintConfig, AnyNodeDefinition, AssemblyHostConfig, AssemblyReference, AssetRef, BakeGeometryAsyncBuilder, BakeGeometryBuilder, BakePolicy, BakeReplaceRenderer, BatchableConfig, Capabilities, CapabilityCtx, CutsContext, CuttableConfig, DimensionTerminator, DimensionTextPosition, DistributionRole, DragAction, DuplicableConfig, DuplicateSubtreeCloneArgs, DuplicateSubtreeCloneResult, EditorCtx, EvaluationContext, ExportAnimationContext, ExportProfile, FaceHostCapability, FaceHostPlacementArgs, FaceHostPlacementResult, FaceHostStoredPlacementArgs, FaceHostStoredValidityArgs, FloorPlacedConfig, FloorPlacedFootprint, FloorPlacedFootprintContext, FloorPlacedFootprintResolver, FloorPlacedFootprintsResolver, FloorplanAffordance, FloorplanAffordanceModifiers, FloorplanAffordancePoint, FloorplanAffordanceSession, FloorplanGeometry, FloorplanMoveTarget, FloorplanMoveTargetSession, FloorplanPalette, FloorplanPoint, FloorplanScope, FloorplanStyle, GeometryContext, GridSnapPositionArgs, GroupMoveSnapArgs, GroupMoveSnapResult, HostableConfig, IconRef, InspectorExtension, Issue, KeyboardAction, KeyboardActions, LazyComponent, LiveTransformLike, McpOverrides, MeasurementContribution, MeasurementFeature, MeasurementFeatureBinding, MeasurementFeatureGeometry, MeasurementSnapKind, MechanismCapability, MechanismPart, Modifiers, MovableConfig, MovableParentFrame, NodeCategory, NodeDefinition, NodePort, NodeQuickAction, NodeQuickActionIcon, NodeQuickActionNodeScope, NodeQuickActionProvider, NodeQuickActionResult, NodeRegistry, PaintCapability, PaintEffectiveMaterialArgs, PaintPatchArgs, PaintPreviewArgs, PaintResolveArgs, PaintScopeId, PaintSurfaceScopes, ParamAction, ParametricDescriptor, ParamField, ParamGroup, ParentFrameSnapMatch, PascalBakeExtras, PascalPartTag, PlacementNotice, Plugin, PortRef, Presentation, QuickMeasurementMetric, QuickMeasurementQuantity, QuickMeasurementReport, ReferenceDeclaration, ReferenceDeletePolicy, ReferenceNamespace, ReferencePath, ReferencePresetPolicy, ReferenceRole, Relations, RendererSource, RevealClears, RevealConfig, RevealLayout, RevealPhase, RevealPlanPoint, RevealStyle, RoofAccessoryConfig, RotatableConfig, ScalableConfig, SceneActionCapability, SceneApi, SelectableConfig, SlotDeclaration, SnapPointKind, SnapProfile, SnappableConfig, SnapServicesLike, SurfacePoint, SurfaceQuery, SurfaceRole, SurfacesConfig, SystemContribution, ToolHint, ToolHintChip, ToolOption, ToolOptionChoice, Vec2, } from './types.js';
8
+ export type { Affordance, AlignmentFootprint, AlignmentFootprintConfig, AnyNodeDefinition, AssemblyHostConfig, AssemblyReference, AssetRef, BakeGeometryAsyncBuilder, BakeGeometryBuilder, BakePolicy, BakeReplaceRenderer, BatchableConfig, Capabilities, CapabilityCtx, CutsContext, CuttableConfig, DimensionTerminator, DimensionTextPosition, DistributionRole, DragAction, DuplicableConfig, DuplicateSubtreeCloneArgs, DuplicateSubtreeCloneResult, EditorCtx, EvaluationContext, ExportAnimationContext, ExportProfile, FaceHostCapability, FaceHostPlacementArgs, FaceHostPlacementResult, FaceHostStoredPlacementArgs, FaceHostStoredValidityArgs, FloorPlacedConfig, FloorPlacedFootprint, FloorPlacedFootprintContext, FloorPlacedFootprintResolver, FloorPlacedFootprintsResolver, FloorplanAffordance, FloorplanAffordanceModifiers, FloorplanAffordancePoint, FloorplanAffordanceSession, FloorplanGeometry, FloorplanMoveTarget, FloorplanMoveTargetSession, FloorplanPalette, FloorplanPoint, FloorplanScope, FloorplanStyle, GeometryContext, GridSnapPositionArgs, GroupMoveSnapArgs, GroupMoveSnapResult, HostableConfig, IconRef, InspectorExtension, Issue, KeyboardAction, KeyboardActions, LazyComponent, LiveTransformLike, McpOverrides, MeasurementContribution, MeasurementFeature, MeasurementFeatureBinding, MeasurementFeatureGeometry, MeasurementSnapKind, MechanismCapability, MechanismPart, Modifiers, MovableConfig, MovableParentFrame, NodeCategory, NodeDefinition, NodePort, NodeQuickAction, NodeQuickActionIcon, NodeQuickActionNodeScope, NodeQuickActionProvider, NodeQuickActionResult, NodeRegistry, PaintCapability, PaintEffectiveMaterialArgs, PaintPatchArgs, PaintPreviewArgs, PaintResolveArgs, PaintScopeId, PaintSurfaceScopes, ParamAction, ParametricDescriptor, ParamField, ParamGroup, ParentFrameSnapMatch, PascalBakeExtras, PascalPartTag, PlacementNotice, Plugin, PortRef, Presentation, QuickMeasurementMetric, QuickMeasurementQuantity, QuickMeasurementReport, ReferenceDeclaration, ReferenceDeletePolicy, ReferenceNamespace, ReferencePath, ReferencePresetPolicy, ReferenceRole, Relations, RendererSource, RevealClears, RevealConfig, RevealLayout, RevealPhase, RevealPlanPoint, RevealStyle, RoofAccessoryConfig, RoofsCapability, RotatableConfig, ScalableConfig, SceneActionCapability, SceneApi, SelectableConfig, SlotDeclaration, SnapPointKind, SnapProfile, SnappableConfig, SnapServicesLike, SurfacePoint, SurfaceQuery, SurfaceRole, SurfacesConfig, SystemContribution, ToolHint, ToolHintChip, ToolOption, ToolOptionChoice, Vec2, } from './types.js';
8
9
  export { validateNodeRelations } from './validate-relations.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export { nodeMechanism, nodeMechanismParts, toggleMechanism, toggleMechanismPart, toggleNodeMechanism, } from './mechanism.js';
2
- export { bakePolicyOf, discoverPlugins, extendPluginDiscovery, floorPlacedCollides, getHostRefFields, getInspectorExtensions, getNodePluginId, getRegistryVersion, getSelectableKinds, hasRegistry3DMoveTool, isDrawnViaTool, isDrawnViaToolKind, isNodeKindEnabled, isPresettable, isPresettableKind, isRegistryMovable, isRegistrySelectable, isSelectionHighlightEnabled, kindsWithBakePolicy, kindsWithFloorplanScope, loadPlugin, nodeRegistry, onRegistryChange, registerNode, resolveFacingIndicator, setPluginDiscovery, } from './registry.js';
2
+ export { bakePolicyOf, discoverPlugins, extendPluginDiscovery, floorPlacedCollides, getHostRefFields, getInspectorExtensions, getNodePluginId, getRegistryVersion, getSelectableKinds, hasRegistry3DMoveTool, isDrawnViaTool, isDrawnViaToolKind, isNodeDuplicable, isNodeKindEnabled, isPresettable, isPresettableKind, isRegistryMovable, isRegistrySelectable, isSelectionHighlightEnabled, kindsWithBakePolicy, kindsWithFloorplanScope, loadPlugin, nodeRegistry, onRegistryChange, registerNode, resolveFacingIndicator, setPluginDiscovery, } from './registry.js';
3
3
  export { cascadeDirty, collectDescendants, } from './relations-resolver.js';
4
+ export { roofFaceOf, roofFaceShapes, validateRoofRelations } from './roofs.js';
4
5
  export { createSceneApi } from './scene-api.js';
5
6
  export { cloneNodesInto, collectSubtree, withoutSourceIdentity, } from './subtree.js';
6
7
  export { validateNodeRelations } from './validate-relations.js';
@@ -81,6 +81,11 @@ export declare function kindsWithBakePolicy(policy: BakePolicy): string[];
81
81
  * chain in `floating-action-menu.tsx`.
82
82
  */
83
83
  export declare function isRegistryMovable(kind: string): boolean;
84
+ /**
85
+ * Whether Duplicate, copy and paste may clone this node: its kind is not
86
+ * `duplicable: false` and its `duplicable.allow` (if any) accepts it.
87
+ */
88
+ export declare function isNodeDuplicable(node: AnyNode): boolean;
84
89
  /**
85
90
  * Whether the kind has a move tool that MOUNTS in the 3D viewport — the
86
91
  * generic `capabilities.movable` mover or a bespoke `affordanceTools.move`.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,MAAM,EACP,MAAM,SAAS,CAAA;AAiChB,6EAA6E;AAC7E,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAKjE;AA8HD,eAAO,MAAM,YAAY,EAAE,YAAY,GAAG;IACxC,SAAS,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAA;IAC3C,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,SAAS,EAAE,MAAM,MAAM,IAAI,CAAA;CACb,CAAA;AAEhB,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,CAEzD;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAI7F;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAQ7C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,6FAA6F;AAC7F,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,iBAAiB,GAAG,SAAS,EAC1C,IAAI,EAAE,OAAO,GACZ,OAAO,CAGT;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,EAAE,CAOvE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAErD;AAED;qFACqF;AACrF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAMhE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOvD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAIvD;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAI3D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAK7D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAIjF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,aAAa,CAAC,MAAM,CAAC,CAE9E;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAE9D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD9D;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;AAMrD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,CAO5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,CAM/D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnD"}
@@ -274,6 +274,16 @@ export function isRegistryMovable(kind) {
274
274
  return true;
275
275
  return false;
276
276
  }
277
+ /**
278
+ * Whether Duplicate, copy and paste may clone this node: its kind is not
279
+ * `duplicable: false` and its `duplicable.allow` (if any) accepts it.
280
+ */
281
+ export function isNodeDuplicable(node) {
282
+ const duplicable = nodeRegistry.get(node.type)?.capabilities.duplicable;
283
+ if (duplicable === false)
284
+ return false;
285
+ return typeof duplicable === 'object' && duplicable.allow ? duplicable.allow({ node }) : true;
286
+ }
277
287
  /**
278
288
  * Whether the kind has a move tool that MOUNTS in the 3D viewport — the
279
289
  * generic `capabilities.movable` mover or a bespoke `affordanceTools.move`.
@@ -0,0 +1,34 @@
1
+ import type { AnyNode, RoofNode } from '../schema/index.js';
2
+ import type { RoofsCapability } from './types.js';
3
+ type Nodes = Readonly<Record<string, AnyNode | undefined>>;
4
+ type Pt = [number, number];
5
+ /**
6
+ * The node's `roofs` capability, when its kind declares one: the node is a face of the roof holding
7
+ * it. Undefined for a roof's segments, which are its masses, and for kinds this runtime has not
8
+ * registered.
9
+ */
10
+ export declare function roofFaceOf(node: AnyNode | undefined): RoofsCapability | undefined;
11
+ /** A face of a roof in the frame of what holds the roof: its level's metres. */
12
+ export type RoofFaceShape = {
13
+ id: string;
14
+ /** The face's outline in that plan, `[x, z]` corners. */
15
+ outline: Pt[];
16
+ /** Its surface at its lowest corner (the eave) and at its highest, over that frame's floor. */
17
+ low: number;
18
+ high: number;
19
+ };
20
+ /**
21
+ * A roof's faces (`capabilities.roofs`), in `children` order, each in the plan and heights of what
22
+ * holds the roof: the roof's turn and position applied to the face's own frame. A face of a kind
23
+ * this runtime has not registered, or one with no area, is not read.
24
+ */
25
+ export declare function roofFaceShapes(roof: RoofNode, nodes: Nodes): RoofFaceShape[];
26
+ /**
27
+ * A roof holds its segments and faces of other kinds (`capabilities.roofs`), nothing else: a child
28
+ * a write adds to it, of a registered kind that is neither, is refused. What it held before stays,
29
+ * so a roof saved before the rule still edits, and so does a kind this runtime has not registered
30
+ * (a plugin loaded elsewhere).
31
+ */
32
+ export declare function validateRoofRelations(roof: AnyNode, nodes: Nodes, before?: Nodes): void;
33
+ export {};
34
+ //# sourceMappingURL=roofs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roofs.d.ts","sourceRoot":"","sources":["../../src/registry/roofs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,CAAC,CAAA;AAC1D,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAE1B;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,CAEjF;AAED,gFAAgF;AAChF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,yDAAyD;IACzD,OAAO,EAAE,EAAE,EAAE,CAAA;IACb,+FAA+F;IAC/F,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,aAAa,EAAE,CA0B5E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,CAavF"}