@pascal-app/core 1.0.4 → 1.0.5
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.
- package/dist/agent-operations/__fixtures__/add-object-cases.d.ts +102 -90
- package/dist/agent-operations/__fixtures__/add-object-cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/add-object-cases.js +301 -1
- package/dist/agent-operations/__fixtures__/add-stair-cases.d.ts +3 -0
- package/dist/agent-operations/__fixtures__/add-stair-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/add-stair-cases.js +176 -0
- package/dist/agent-operations/__fixtures__/build-room-cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/build-room-cases.js +410 -40
- package/dist/agent-operations/__fixtures__/cases.d.ts +18 -3
- package/dist/agent-operations/__fixtures__/cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/cases.js +183 -4
- package/dist/agent-operations/__fixtures__/corner-window-cases.d.ts +3 -0
- package/dist/agent-operations/__fixtures__/corner-window-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/corner-window-cases.js +155 -0
- package/dist/agent-operations/__fixtures__/design-brief-cases.d.ts +14 -0
- package/dist/agent-operations/__fixtures__/design-brief-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/design-brief-cases.js +709 -0
- package/dist/agent-operations/__fixtures__/finish-cases.d.ts +7 -0
- package/dist/agent-operations/__fixtures__/finish-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/finish-cases.js +758 -0
- package/dist/agent-operations/__fixtures__/lot-info-cases.d.ts +3 -0
- package/dist/agent-operations/__fixtures__/lot-info-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/lot-info-cases.js +370 -0
- package/dist/agent-operations/__fixtures__/merge-windows-cases.d.ts +3 -0
- package/dist/agent-operations/__fixtures__/merge-windows-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/merge-windows-cases.js +321 -0
- package/dist/agent-operations/__fixtures__/native-materials.d.ts +2237 -0
- package/dist/agent-operations/__fixtures__/native-materials.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/native-materials.js +82 -0
- package/dist/agent-operations/__fixtures__/node-read-cases.d.ts +4 -0
- package/dist/agent-operations/__fixtures__/node-read-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/node-read-cases.js +639 -0
- package/dist/agent-operations/__fixtures__/notation-cases.d.ts +24 -0
- package/dist/agent-operations/__fixtures__/notation-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/notation-cases.js +356 -0
- package/dist/agent-operations/__fixtures__/place-items-cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/place-items-cases.js +80 -2
- package/dist/agent-operations/__fixtures__/roof-bearing-cases.d.ts +19726 -0
- package/dist/agent-operations/__fixtures__/roof-bearing-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/roof-bearing-cases.js +106 -0
- package/dist/agent-operations/__fixtures__/roof-cases.d.ts +9 -0
- package/dist/agent-operations/__fixtures__/roof-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/roof-cases.js +382 -0
- package/dist/agent-operations/__fixtures__/room-cases.d.ts +2 -1
- package/dist/agent-operations/__fixtures__/room-cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/room-cases.js +136 -1
- package/dist/agent-operations/__fixtures__/scene-check-cases.d.ts +4 -0
- package/dist/agent-operations/__fixtures__/scene-check-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/scene-check-cases.js +417 -0
- package/dist/agent-operations/__fixtures__/search-assets-cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/search-assets-cases.js +15 -3
- package/dist/agent-operations/__fixtures__/site-cases.d.ts +290 -0
- package/dist/agent-operations/__fixtures__/site-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/site-cases.js +780 -0
- package/dist/agent-operations/__fixtures__/structure-cases.d.ts +1 -0
- package/dist/agent-operations/__fixtures__/structure-cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/structure-cases.js +630 -3
- package/dist/agent-operations/__fixtures__/verify-scene-cases.d.ts +311 -1
- package/dist/agent-operations/__fixtures__/verify-scene-cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/verify-scene-cases.js +59 -11
- package/dist/agent-operations/__fixtures__/view-assets-cases.d.ts +3 -0
- package/dist/agent-operations/__fixtures__/view-assets-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/view-assets-cases.js +155 -0
- package/dist/agent-operations/__fixtures__/view-scene-cases.d.ts +50 -0
- package/dist/agent-operations/__fixtures__/view-scene-cases.d.ts.map +1 -0
- package/dist/agent-operations/__fixtures__/view-scene-cases.js +425 -0
- package/dist/agent-operations/achieved.d.ts +5 -0
- package/dist/agent-operations/achieved.d.ts.map +1 -1
- package/dist/agent-operations/achieved.js +21 -1
- package/dist/agent-operations/add-column.d.ts.map +1 -1
- package/dist/agent-operations/add-column.js +3 -1
- package/dist/agent-operations/add-fence.d.ts +18 -0
- package/dist/agent-operations/add-fence.d.ts.map +1 -0
- package/dist/agent-operations/add-fence.js +48 -0
- package/dist/agent-operations/add-level.d.ts +4 -1
- package/dist/agent-operations/add-level.d.ts.map +1 -1
- package/dist/agent-operations/add-level.js +48 -12
- package/dist/agent-operations/add-object.d.ts +38 -9
- package/dist/agent-operations/add-object.d.ts.map +1 -1
- package/dist/agent-operations/add-object.js +172 -11
- package/dist/agent-operations/add-wall.d.ts +1 -3
- package/dist/agent-operations/add-wall.d.ts.map +1 -1
- package/dist/agent-operations/add-wall.js +35 -9
- package/dist/agent-operations/apply-changes.d.ts +7 -1
- package/dist/agent-operations/apply-changes.d.ts.map +1 -1
- package/dist/agent-operations/apply-changes.js +54 -22
- package/dist/agent-operations/apply-outcome.d.ts +6 -0
- package/dist/agent-operations/apply-outcome.d.ts.map +1 -1
- package/dist/agent-operations/apply-outcome.js +23 -8
- package/dist/agent-operations/asset-views.d.ts +75 -0
- package/dist/agent-operations/asset-views.d.ts.map +1 -0
- package/dist/agent-operations/asset-views.js +234 -0
- package/dist/agent-operations/author-scene.d.ts +157 -0
- package/dist/agent-operations/author-scene.d.ts.map +1 -0
- package/dist/agent-operations/author-scene.js +1076 -0
- package/dist/agent-operations/authored-scene-merge.d.ts +4 -0
- package/dist/agent-operations/authored-scene-merge.d.ts.map +1 -0
- package/dist/agent-operations/authored-scene-merge.js +96 -0
- package/dist/agent-operations/batch.d.ts +22 -0
- package/dist/agent-operations/batch.d.ts.map +1 -0
- package/dist/agent-operations/batch.js +104 -0
- package/dist/agent-operations/ceiling-object-observations.d.ts +31 -0
- package/dist/agent-operations/ceiling-object-observations.d.ts.map +1 -0
- package/dist/agent-operations/ceiling-object-observations.js +111 -0
- package/dist/agent-operations/corner-window.d.ts +19 -0
- package/dist/agent-operations/corner-window.d.ts.map +1 -0
- package/dist/agent-operations/corner-window.js +84 -0
- package/dist/agent-operations/create-roof.d.ts +32 -0
- package/dist/agent-operations/create-roof.d.ts.map +1 -0
- package/dist/agent-operations/create-roof.js +304 -0
- package/dist/agent-operations/create-room.d.ts +2 -0
- package/dist/agent-operations/create-room.d.ts.map +1 -1
- package/dist/agent-operations/create-room.js +73 -5
- package/dist/agent-operations/create-stair.d.ts +6 -28
- package/dist/agent-operations/create-stair.d.ts.map +1 -1
- package/dist/agent-operations/create-stair.js +187 -104
- package/dist/agent-operations/design-brief.d.ts +38 -0
- package/dist/agent-operations/design-brief.d.ts.map +1 -0
- package/dist/agent-operations/design-brief.js +300 -0
- package/dist/agent-operations/designs.d.ts +24 -0
- package/dist/agent-operations/designs.d.ts.map +1 -0
- package/dist/agent-operations/designs.js +48 -0
- package/dist/agent-operations/door-clearance.d.ts +16 -1
- package/dist/agent-operations/door-clearance.d.ts.map +1 -1
- package/dist/agent-operations/door-clearance.js +61 -4
- package/dist/agent-operations/duplicate-level.d.ts.map +1 -1
- package/dist/agent-operations/duplicate-level.js +2 -1
- package/dist/agent-operations/find-by-type.d.ts +14 -7
- package/dist/agent-operations/find-by-type.d.ts.map +1 -1
- package/dist/agent-operations/find-by-type.js +266 -43
- package/dist/agent-operations/furnish-room.d.ts +22 -1
- package/dist/agent-operations/furnish-room.d.ts.map +1 -1
- package/dist/agent-operations/furnish-room.js +66 -19
- package/dist/agent-operations/furniture-kind.d.ts +22 -0
- package/dist/agent-operations/furniture-kind.d.ts.map +1 -0
- package/dist/agent-operations/furniture-kind.js +69 -0
- package/dist/agent-operations/get-node.d.ts +5 -2
- package/dist/agent-operations/get-node.d.ts.map +1 -1
- package/dist/agent-operations/get-node.js +82 -10
- package/dist/agent-operations/hosted-services.d.ts +2 -1
- package/dist/agent-operations/hosted-services.d.ts.map +1 -1
- package/dist/agent-operations/index.d.ts +281 -69
- package/dist/agent-operations/index.d.ts.map +1 -1
- package/dist/agent-operations/index.js +66 -5
- package/dist/agent-operations/item-space.d.ts +22 -0
- package/dist/agent-operations/item-space.d.ts.map +1 -0
- package/dist/agent-operations/item-space.js +69 -0
- package/dist/agent-operations/layout-clearance.d.ts +52 -3
- package/dist/agent-operations/layout-clearance.d.ts.map +1 -1
- package/dist/agent-operations/layout-clearance.js +340 -30
- package/dist/agent-operations/level-height-fill.d.ts +12 -0
- package/dist/agent-operations/level-height-fill.d.ts.map +1 -0
- package/dist/agent-operations/level-height-fill.js +59 -0
- package/dist/agent-operations/level-reads.d.ts +5 -1
- package/dist/agent-operations/level-reads.d.ts.map +1 -1
- package/dist/agent-operations/level-reads.js +10 -3
- package/dist/agent-operations/list-levels.d.ts.map +1 -1
- package/dist/agent-operations/list-levels.js +23 -0
- package/dist/agent-operations/material-preset.d.ts.map +1 -1
- package/dist/agent-operations/material-preset.js +3 -9
- package/dist/agent-operations/material-refs.d.ts +7 -1
- package/dist/agent-operations/material-refs.d.ts.map +1 -1
- package/dist/agent-operations/material-refs.js +10 -5
- package/dist/agent-operations/merge-windows.d.ts +6 -0
- package/dist/agent-operations/merge-windows.d.ts.map +1 -0
- package/dist/agent-operations/merge-windows.js +27 -0
- package/dist/agent-operations/move-roofs.d.ts +9 -0
- package/dist/agent-operations/move-roofs.d.ts.map +1 -0
- package/dist/agent-operations/move-roofs.js +29 -0
- package/dist/agent-operations/paint.d.ts +2 -1
- package/dist/agent-operations/paint.d.ts.map +1 -1
- package/dist/agent-operations/paint.js +163 -53
- package/dist/agent-operations/photo-elevation.d.ts +155 -0
- package/dist/agent-operations/photo-elevation.d.ts.map +1 -0
- package/dist/agent-operations/photo-elevation.js +761 -0
- package/dist/agent-operations/place-in-room.d.ts +29 -0
- package/dist/agent-operations/place-in-room.d.ts.map +1 -0
- package/dist/agent-operations/place-in-room.js +403 -0
- package/dist/agent-operations/place-items.d.ts.map +1 -1
- package/dist/agent-operations/place-items.js +15 -2
- package/dist/agent-operations/plan-geometry.d.ts.map +1 -1
- package/dist/agent-operations/plan-geometry.js +3 -0
- package/dist/agent-operations/point-context.d.ts +139 -0
- package/dist/agent-operations/point-context.d.ts.map +1 -0
- package/dist/agent-operations/point-context.js +1 -0
- package/dist/agent-operations/project-files.d.ts +9 -0
- package/dist/agent-operations/project-files.d.ts.map +1 -0
- package/dist/agent-operations/project-files.js +25 -0
- package/dist/agent-operations/record-made.d.ts +18 -0
- package/dist/agent-operations/record-made.d.ts.map +1 -0
- package/dist/agent-operations/record-made.js +28 -0
- package/dist/agent-operations/roof-footprint.d.ts +24 -0
- package/dist/agent-operations/roof-footprint.d.ts.map +1 -0
- package/dist/agent-operations/roof-footprint.js +242 -0
- package/dist/agent-operations/roof-writes.d.ts +20 -0
- package/dist/agent-operations/roof-writes.d.ts.map +1 -0
- package/dist/agent-operations/roof-writes.js +165 -0
- package/dist/agent-operations/room-findings.d.ts +54 -0
- package/dist/agent-operations/room-findings.d.ts.map +1 -0
- package/dist/agent-operations/room-findings.js +143 -0
- package/dist/agent-operations/room-floor-script.d.ts +23 -0
- package/dist/agent-operations/room-floor-script.d.ts.map +1 -0
- package/dist/agent-operations/room-floor-script.js +54 -0
- package/dist/agent-operations/room-structure.d.ts +2 -2
- package/dist/agent-operations/room-structure.d.ts.map +1 -1
- package/dist/agent-operations/scene-checkpoint.d.ts +94 -0
- package/dist/agent-operations/scene-checkpoint.d.ts.map +1 -0
- package/dist/agent-operations/scene-checkpoint.js +176 -0
- package/dist/agent-operations/scene-queries.d.ts +3750 -3319
- package/dist/agent-operations/scene-queries.d.ts.map +1 -1
- package/dist/agent-operations/scene-queries.js +13 -23
- package/dist/agent-operations/scene-review.d.ts +52 -0
- package/dist/agent-operations/scene-review.d.ts.map +1 -0
- package/dist/agent-operations/scene-review.js +106 -0
- package/dist/agent-operations/scene-view.d.ts +82 -15
- package/dist/agent-operations/scene-view.d.ts.map +1 -1
- package/dist/agent-operations/scene-view.js +408 -51
- package/dist/agent-operations/search-assets.d.ts +2 -2
- package/dist/agent-operations/search-assets.d.ts.map +1 -1
- package/dist/agent-operations/search-assets.js +4 -3
- package/dist/agent-operations/search-materials.d.ts +9 -3
- package/dist/agent-operations/search-materials.d.ts.map +1 -1
- package/dist/agent-operations/search-materials.js +83 -29
- package/dist/agent-operations/set-checkpoint.d.ts +9 -0
- package/dist/agent-operations/set-checkpoint.d.ts.map +1 -0
- package/dist/agent-operations/set-checkpoint.js +31 -0
- package/dist/agent-operations/set-ground-level.d.ts +12 -0
- package/dist/agent-operations/set-ground-level.d.ts.map +1 -0
- package/dist/agent-operations/set-ground-level.js +61 -0
- package/dist/agent-operations/site.d.ts +21 -0
- package/dist/agent-operations/site.d.ts.map +1 -0
- package/dist/agent-operations/site.js +123 -0
- package/dist/agent-operations/types.d.ts +66 -7
- package/dist/agent-operations/types.d.ts.map +1 -1
- package/dist/agent-operations/verify-scene.d.ts +39 -5
- package/dist/agent-operations/verify-scene.d.ts.map +1 -1
- package/dist/agent-operations/verify-scene.js +223 -44
- package/dist/agent-operations/wall-face-script.d.ts +28 -0
- package/dist/agent-operations/wall-face-script.d.ts.map +1 -0
- package/dist/agent-operations/wall-face-script.js +62 -0
- package/dist/agent-operations/wall-object-observations.d.ts +41 -0
- package/dist/agent-operations/wall-object-observations.d.ts.map +1 -0
- package/dist/agent-operations/wall-object-observations.js +249 -0
- package/dist/agent-operations/wall-opening.d.ts +23 -23
- package/dist/agent-operations/wall-opening.d.ts.map +1 -1
- package/dist/agent-operations/wall-skirting.d.ts +24 -0
- package/dist/agent-operations/wall-skirting.d.ts.map +1 -0
- package/dist/agent-operations/wall-skirting.js +85 -0
- package/dist/agent-tools/add-object.d.ts +11 -7
- package/dist/agent-tools/add-object.d.ts.map +1 -1
- package/dist/agent-tools/add-object.js +17 -11
- package/dist/agent-tools/assets.d.ts +8 -0
- package/dist/agent-tools/assets.d.ts.map +1 -1
- package/dist/agent-tools/assets.js +13 -1
- package/dist/agent-tools/author-scene.d.ts +651 -0
- package/dist/agent-tools/author-scene.d.ts.map +1 -0
- package/dist/agent-tools/author-scene.js +252 -0
- package/dist/agent-tools/batch.d.ts +25 -0
- package/dist/agent-tools/batch.d.ts.map +1 -0
- package/dist/agent-tools/batch.js +61 -0
- package/dist/agent-tools/checkpoints.d.ts +13 -0
- package/dist/agent-tools/checkpoints.d.ts.map +1 -0
- package/dist/agent-tools/checkpoints.js +16 -0
- package/dist/agent-tools/clear-scene.d.ts.map +1 -1
- package/dist/agent-tools/collections.d.ts +6 -6
- package/dist/agent-tools/collections.d.ts.map +1 -1
- package/dist/agent-tools/columns.d.ts +18 -18
- package/dist/agent-tools/columns.js +2 -2
- package/dist/agent-tools/corner-window.d.ts +46 -0
- package/dist/agent-tools/corner-window.d.ts.map +1 -0
- package/dist/agent-tools/corner-window.js +47 -0
- package/dist/agent-tools/create-room.d.ts +26 -25
- package/dist/agent-tools/create-room.d.ts.map +1 -1
- package/dist/agent-tools/create-room.js +11 -4
- package/dist/agent-tools/design-brief.d.ts +408 -0
- package/dist/agent-tools/design-brief.d.ts.map +1 -0
- package/dist/agent-tools/design-brief.js +149 -0
- package/dist/agent-tools/designs.d.ts +34 -0
- package/dist/agent-tools/designs.d.ts.map +1 -0
- package/dist/agent-tools/designs.js +50 -0
- package/dist/agent-tools/fences.d.ts +28 -0
- package/dist/agent-tools/fences.d.ts.map +1 -0
- package/dist/agent-tools/fences.js +31 -0
- package/dist/agent-tools/find-by-type.d.ts +8 -1
- package/dist/agent-tools/find-by-type.d.ts.map +1 -1
- package/dist/agent-tools/find-by-type.js +23 -2
- package/dist/agent-tools/furnish-room.d.ts +10 -8
- package/dist/agent-tools/furnish-room.d.ts.map +1 -1
- package/dist/agent-tools/furnish-room.js +3 -1
- package/dist/agent-tools/hosted-services.d.ts +177 -141
- package/dist/agent-tools/hosted-services.d.ts.map +1 -1
- package/dist/agent-tools/hosted-services.js +47 -14
- package/dist/agent-tools/index.d.ts +894 -215
- package/dist/agent-tools/index.d.ts.map +1 -1
- package/dist/agent-tools/index.js +47 -3
- package/dist/agent-tools/levels.d.ts +11 -3
- package/dist/agent-tools/levels.d.ts.map +1 -1
- package/dist/agent-tools/levels.js +16 -5
- package/dist/agent-tools/measurement.d.ts +38 -20
- package/dist/agent-tools/measurement.d.ts.map +1 -1
- package/dist/agent-tools/measurement.js +117 -67
- package/dist/agent-tools/merge-windows.d.ts +10 -0
- package/dist/agent-tools/merge-windows.d.ts.map +1 -0
- package/dist/agent-tools/merge-windows.js +12 -0
- package/dist/agent-tools/nodes.d.ts.map +1 -1
- package/dist/agent-tools/nodes.js +1 -1
- package/dist/agent-tools/notation-inventory.d.ts +16 -0
- package/dist/agent-tools/notation-inventory.d.ts.map +1 -0
- package/dist/agent-tools/notation-inventory.js +105 -0
- package/dist/agent-tools/paint.d.ts +5 -5
- package/dist/agent-tools/paint.d.ts.map +1 -1
- package/dist/agent-tools/paint.js +1 -1
- package/dist/agent-tools/photo-elevation.d.ts +32 -0
- package/dist/agent-tools/photo-elevation.d.ts.map +1 -0
- package/dist/agent-tools/photo-elevation.js +73 -0
- package/dist/agent-tools/place-in-room.d.ts +35 -0
- package/dist/agent-tools/place-in-room.d.ts.map +1 -0
- package/dist/agent-tools/place-in-room.js +61 -0
- package/dist/agent-tools/place-items.d.ts +1 -1
- package/dist/agent-tools/place-items.js +2 -2
- package/dist/agent-tools/project-files.d.ts +189 -0
- package/dist/agent-tools/project-files.d.ts.map +1 -0
- package/dist/agent-tools/project-files.js +99 -0
- package/dist/agent-tools/refusal.d.ts.map +1 -1
- package/dist/agent-tools/retired.d.ts +21 -0
- package/dist/agent-tools/retired.d.ts.map +1 -0
- package/dist/agent-tools/retired.js +29 -0
- package/dist/agent-tools/roofs.d.ts +100 -0
- package/dist/agent-tools/roofs.d.ts.map +1 -0
- package/dist/agent-tools/roofs.js +96 -0
- package/dist/agent-tools/room-structure.d.ts +46 -38
- package/dist/agent-tools/room-structure.d.ts.map +1 -1
- package/dist/agent-tools/room-structure.js +30 -27
- package/dist/agent-tools/search-materials.d.ts +22 -3
- package/dist/agent-tools/search-materials.d.ts.map +1 -1
- package/dist/agent-tools/search-materials.js +13 -14
- package/dist/agent-tools/site.d.ts +27 -0
- package/dist/agent-tools/site.d.ts.map +1 -0
- package/dist/agent-tools/site.js +40 -0
- package/dist/agent-tools/sources.d.ts +12 -0
- package/dist/agent-tools/sources.d.ts.map +1 -0
- package/dist/agent-tools/sources.js +11 -0
- package/dist/agent-tools/stairs.d.ts +48 -28
- package/dist/agent-tools/stairs.d.ts.map +1 -1
- package/dist/agent-tools/stairs.js +65 -22
- package/dist/agent-tools/verify-scene.d.ts.map +1 -1
- package/dist/agent-tools/verify-scene.js +1 -1
- package/dist/agent-tools/view-scene.d.ts +50 -12
- package/dist/agent-tools/view-scene.d.ts.map +1 -1
- package/dist/agent-tools/view-scene.js +74 -31
- package/dist/agent-tools/wall-openings.d.ts +77 -73
- package/dist/agent-tools/wall-openings.d.ts.map +1 -1
- package/dist/agent-tools/wall-openings.js +9 -5
- package/dist/agent-tools/walls.d.ts +4 -4
- package/dist/agent-tools/walls.d.ts.map +1 -1
- package/dist/agent-tools/walls.js +7 -2
- package/dist/building/__fixtures__/wall-opening-cases.d.ts +454 -250
- package/dist/building/__fixtures__/wall-opening-cases.d.ts.map +1 -1
- package/dist/building/__fixtures__/wall-opening-cases.js +62 -2
- package/dist/building/corner-window.d.ts +56 -0
- package/dist/building/corner-window.d.ts.map +1 -0
- package/dist/building/corner-window.js +179 -0
- package/dist/building/ground-level.d.ts +26 -0
- package/dist/building/ground-level.d.ts.map +1 -0
- package/dist/building/ground-level.js +58 -0
- package/dist/building/index.d.ts +5 -0
- package/dist/building/index.d.ts.map +1 -1
- package/dist/building/index.js +5 -0
- package/dist/building/level-duplication.d.ts +7472 -6613
- package/dist/building/level-duplication.d.ts.map +1 -1
- package/dist/building/level-duplication.js +18 -4
- package/dist/building/level-insertion.d.ts +55 -0
- package/dist/building/level-insertion.d.ts.map +1 -0
- package/dist/building/level-insertion.js +35 -0
- package/dist/building/merge-windows.d.ts +58 -0
- package/dist/building/merge-windows.d.ts.map +1 -0
- package/dist/building/merge-windows.js +189 -0
- package/dist/building/opening-style-presets.d.ts +2 -2
- package/dist/building/opening-style-presets.d.ts.map +1 -1
- package/dist/building/photo-elevation.d.ts +125 -0
- package/dist/building/photo-elevation.d.ts.map +1 -0
- package/dist/building/photo-elevation.js +404 -0
- package/dist/building/wall-gaps.d.ts +13 -0
- package/dist/building/wall-gaps.d.ts.map +1 -0
- package/dist/building/wall-gaps.js +158 -0
- package/dist/building/wall-openings.d.ts +154 -119
- package/dist/building/wall-openings.d.ts.map +1 -1
- package/dist/building/wall-openings.js +37 -9
- package/dist/capture/schema.d.ts +22 -22
- package/dist/capture/source.d.ts.map +1 -1
- package/dist/capture/source.js +1 -1
- package/dist/commands/structure/create-zone.d.ts +12 -1
- package/dist/commands/structure/create-zone.d.ts.map +1 -1
- package/dist/commands/structure/create-zone.js +49 -0
- package/dist/commands/structure/divide-zone.d.ts +3 -3
- package/dist/commands/structure/index.d.ts +1 -1
- package/dist/commands/structure/index.d.ts.map +1 -1
- package/dist/commands/structure/index.js +1 -1
- package/dist/commands/structure/set-floor-foundation.d.ts +6 -6
- package/dist/commands/structure/set-zone-intent.d.ts +4 -0
- package/dist/commands/structure/set-zone-intent.d.ts.map +1 -1
- package/dist/commands/structure/set-zone-intent.js +19 -0
- package/dist/commands/structure/shared.d.ts +3642 -3213
- package/dist/commands/structure/shared.d.ts.map +1 -1
- package/dist/commands/structure/zone-wall-merge.d.ts +4149 -3334
- package/dist/commands/structure/zone-wall-merge.d.ts.map +1 -1
- package/dist/contracts/reference-inventory.d.ts.map +1 -1
- package/dist/contracts/reference-inventory.js +106 -26
- package/dist/events/bus.d.ts +22 -3
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/capture-sessions.d.ts +5 -0
- package/dist/events/capture-sessions.d.ts.map +1 -0
- package/dist/events/capture-sessions.js +31 -0
- package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +1 -2
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +4 -6
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +3608 -3179
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/support-host-patch.js +11 -2
- package/dist/hooks/spatial-grid/use-spatial-query.d.ts +3 -3
- package/dist/hooks/spatial-grid/wall-spatial-grid.d.ts.map +1 -1
- package/dist/index.d.ts +37 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -9
- package/dist/lib/__fixtures__/mezzanine.d.ts +11800 -10132
- package/dist/lib/__fixtures__/mezzanine.d.ts.map +1 -1
- package/dist/lib/absorb-wall-separators.d.ts +3642 -3213
- package/dist/lib/absorb-wall-separators.d.ts.map +1 -1
- package/dist/lib/angle-accumulator.d.ts.map +1 -1
- package/dist/lib/artifact-store.d.ts.map +1 -1
- package/dist/lib/below-grade-footprints.d.ts +65 -0
- package/dist/lib/below-grade-footprints.d.ts.map +1 -0
- package/dist/lib/below-grade-footprints.js +181 -0
- package/dist/lib/building-footprint.d.ts +33 -0
- package/dist/lib/building-footprint.d.ts.map +1 -0
- package/dist/lib/building-footprint.js +89 -0
- package/dist/lib/corner-pair.d.ts +1129 -0
- package/dist/lib/corner-pair.d.ts.map +1 -0
- package/dist/lib/corner-pair.js +130 -0
- package/dist/lib/corner-snap.d.ts +54 -0
- package/dist/lib/corner-snap.d.ts.map +1 -0
- package/dist/lib/corner-snap.js +125 -0
- package/dist/lib/critically-damped.d.ts +11 -0
- package/dist/lib/critically-damped.d.ts.map +1 -0
- package/dist/lib/critically-damped.js +14 -0
- package/dist/lib/deepest-drawn.d.ts +18 -0
- package/dist/lib/deepest-drawn.d.ts.map +1 -0
- package/dist/lib/deepest-drawn.js +65 -0
- package/dist/lib/door-operation.d.ts +1 -1
- package/dist/lib/exterior-wall-loops.d.ts +17 -0
- package/dist/lib/exterior-wall-loops.d.ts.map +1 -0
- package/dist/lib/exterior-wall-loops.js +334 -0
- package/dist/lib/finish-script.d.ts +61 -0
- package/dist/lib/finish-script.d.ts.map +1 -0
- package/dist/lib/finish-script.js +86 -0
- package/dist/lib/floor-intent-changes.d.ts.map +1 -1
- package/dist/lib/floor-intent-changes.js +4 -4
- package/dist/lib/floor-plate-paint.d.ts +3 -1
- package/dist/lib/floor-plate-paint.d.ts.map +1 -1
- package/dist/lib/floor-plate-paint.js +24 -4
- package/dist/lib/floor-plates.d.ts +50 -50
- package/dist/lib/floor-script.d.ts +24 -0
- package/dist/lib/floor-script.d.ts.map +1 -0
- package/dist/lib/floor-script.js +51 -0
- package/dist/lib/foundation-construction.d.ts +73 -0
- package/dist/lib/foundation-construction.d.ts.map +1 -0
- package/dist/lib/foundation-construction.js +242 -0
- package/dist/lib/foundation-standard.d.ts +30 -0
- package/dist/lib/foundation-standard.d.ts.map +1 -0
- package/dist/lib/foundation-standard.js +30 -0
- package/dist/lib/foundation-wall.d.ts +36 -0
- package/dist/lib/foundation-wall.d.ts.map +1 -0
- package/dist/lib/foundation-wall.js +66 -0
- package/dist/lib/generic-foundation.d.ts +40 -0
- package/dist/lib/generic-foundation.d.ts.map +1 -0
- package/dist/lib/generic-foundation.js +200 -0
- package/dist/lib/geometry-script-node.d.ts +32 -3
- package/dist/lib/geometry-script-node.d.ts.map +1 -1
- package/dist/lib/geometry-script-node.js +26 -0
- package/dist/lib/grade-standing.d.ts +38 -0
- package/dist/lib/grade-standing.d.ts.map +1 -0
- package/dist/lib/grade-standing.js +137 -0
- package/dist/lib/ground-level.d.ts +20 -0
- package/dist/lib/ground-level.d.ts.map +1 -0
- package/dist/lib/ground-level.js +49 -0
- package/dist/lib/ground-over-part.d.ts +13 -0
- package/dist/lib/ground-over-part.d.ts.map +1 -0
- package/dist/lib/ground-over-part.js +94 -0
- package/dist/lib/ground-seat.d.ts +47 -0
- package/dist/lib/ground-seat.d.ts.map +1 -0
- package/dist/lib/ground-seat.js +61 -0
- package/dist/lib/ground-window.d.ts +39 -0
- package/dist/lib/ground-window.d.ts.map +1 -0
- package/dist/lib/ground-window.js +147 -0
- package/dist/lib/opening-floor-datum.d.ts.map +1 -1
- package/dist/lib/opening-floor-datum.js +2 -3
- package/dist/lib/own-floor-intent.d.ts.map +1 -1
- package/dist/lib/own-floor-intent.js +4 -4
- package/dist/lib/plate-surface.d.ts.map +1 -1
- package/dist/lib/plate-surface.js +3 -1
- package/dist/lib/point-ask.d.ts +9 -0
- package/dist/lib/point-ask.d.ts.map +1 -0
- package/dist/lib/point-ask.js +36 -0
- package/dist/lib/room-drawn-floor.d.ts +1 -1
- package/dist/lib/room-drawn-floor.d.ts.map +1 -1
- package/dist/lib/room-floor-feasibility.d.ts.map +1 -1
- package/dist/lib/room-floor-feasibility.js +3 -3
- package/dist/lib/room-graph.d.ts.map +1 -1
- package/dist/lib/room-graph.js +2 -0
- package/dist/lib/room-name.d.ts +2 -0
- package/dist/lib/room-name.d.ts.map +1 -1
- package/dist/lib/room-name.js +2 -0
- package/dist/lib/room-topology-index.d.ts.map +1 -1
- package/dist/lib/room-topology-index.js +1 -1
- package/dist/lib/room-zone-adoption.d.ts.map +1 -1
- package/dist/lib/script-inputs-key.d.ts +3 -0
- package/dist/lib/script-inputs-key.d.ts.map +1 -0
- package/dist/lib/script-inputs-key.js +13 -0
- package/dist/lib/setback-envelope.d.ts +95 -5
- package/dist/lib/setback-envelope.d.ts.map +1 -1
- package/dist/lib/setback-envelope.js +351 -35
- package/dist/lib/site-flatwork.d.ts +11 -0
- package/dist/lib/site-flatwork.d.ts.map +1 -0
- package/dist/lib/site-flatwork.js +11 -0
- package/dist/lib/site-ground-height.d.ts +13 -0
- package/dist/lib/site-ground-height.d.ts.map +1 -0
- package/dist/lib/site-ground-height.js +16 -0
- package/dist/lib/site-placement.d.ts +362 -0
- package/dist/lib/site-placement.d.ts.map +1 -0
- package/dist/lib/site-placement.js +942 -0
- package/dist/lib/snap-ease.d.ts +20 -0
- package/dist/lib/snap-ease.d.ts.map +1 -0
- package/dist/lib/snap-ease.js +50 -0
- package/dist/lib/structure-kernel.d.ts +1 -1
- package/dist/lib/structure-kernel.d.ts.map +1 -1
- package/dist/lib/structure-kernel.js +2 -0
- package/dist/lib/surface-support-references.d.ts +4 -0
- package/dist/lib/surface-support-references.d.ts.map +1 -0
- package/dist/lib/surface-support-references.js +19 -0
- package/dist/lib/terrain-support-query.d.ts +10 -0
- package/dist/lib/terrain-support-query.d.ts.map +1 -1
- package/dist/lib/terrain-support-query.js +1 -1
- package/dist/lib/wall-face-script.d.ts +66 -0
- package/dist/lib/wall-face-script.d.ts.map +1 -0
- package/dist/lib/wall-face-script.js +235 -0
- package/dist/lib/zone-colors.d.ts +1 -1
- package/dist/lib/zone-colors.d.ts.map +1 -1
- package/dist/lib/zone-quantities.d.ts.map +1 -1
- package/dist/lib/zone-quantities.js +4 -5
- package/dist/material-kinds.d.ts +9 -0
- package/dist/material-kinds.d.ts.map +1 -0
- package/dist/material-kinds.js +30 -0
- package/dist/material-library.d.ts +4 -4
- package/dist/material-library.d.ts.map +1 -1
- package/dist/material-library.js +72 -26
- package/dist/node-slots/index.d.ts +1 -0
- package/dist/node-slots/index.d.ts.map +1 -1
- package/dist/node-slots/index.js +7 -1
- package/dist/node-slots/roof.d.ts +5 -0
- package/dist/node-slots/roof.d.ts.map +1 -0
- package/dist/node-slots/roof.js +12 -0
- package/dist/node-slots/stair.d.ts +2 -0
- package/dist/node-slots/stair.d.ts.map +1 -1
- package/dist/node-slots/stair.js +6 -2
- package/dist/procedural-items/design-placement.d.ts.map +1 -1
- package/dist/procedural-items/design.d.ts +19 -19
- package/dist/procedural-items/fixtures.d.ts +297 -297
- package/dist/procedural-items/fixtures.d.ts.map +1 -1
- package/dist/procedural-items/integration.d.ts +106 -106
- package/dist/procedural-items/joints.d.ts +4 -4
- package/dist/procedural-items/library-colors.d.ts +22 -22
- package/dist/procedural-items/library-colors.d.ts.map +1 -1
- package/dist/procedural-items/motion-controller.d.ts.map +1 -1
- package/dist/procedural-items/node.d.ts +291 -291
- package/dist/procedural-items/query.d.ts +1 -1
- package/dist/procedural-items/query.d.ts.map +1 -1
- package/dist/procedural-items/recipe.d.ts +11 -11
- package/dist/procedural-items/recipe.d.ts.map +1 -1
- package/dist/procedural-items/section.d.ts.map +1 -1
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/scene-api.d.ts +1 -0
- package/dist/registry/scene-api.d.ts.map +1 -1
- package/dist/registry/scene-api.js +3 -0
- package/dist/registry/subtree.d.ts.map +1 -1
- package/dist/registry/subtree.js +2 -0
- package/dist/registry/types.d.ts +120 -1
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/schema/assembly.d.ts +41 -41
- package/dist/schema/asset-url.d.ts +1 -1
- package/dist/schema/asset-url.d.ts.map +1 -1
- package/dist/schema/base.d.ts +9 -9
- package/dist/schema/base.d.ts.map +1 -1
- package/dist/schema/camera.d.ts +1 -1
- package/dist/schema/collection-templates.d.ts +20 -20
- package/dist/schema/collection-templates.d.ts.map +1 -1
- package/dist/schema/geometry-metadata.d.ts +7 -7
- package/dist/schema/geometry-metadata.d.ts.map +1 -1
- package/dist/schema/geometry-source.d.ts +26 -16
- package/dist/schema/geometry-source.d.ts.map +1 -1
- package/dist/schema/geometry-source.js +14 -0
- package/dist/schema/index.d.ts +10 -7
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +10 -7
- package/dist/schema/material.d.ts +33 -33
- package/dist/schema/nodes/barrel-roof.d.ts +3 -0
- package/dist/schema/nodes/barrel-roof.d.ts.map +1 -0
- package/dist/schema/nodes/barrel-roof.js +11 -0
- package/dist/schema/nodes/block.d.ts +8 -8
- package/dist/schema/nodes/box-vent.d.ts +13 -13
- package/dist/schema/nodes/building.d.ts +9 -8
- package/dist/schema/nodes/building.d.ts.map +1 -1
- package/dist/schema/nodes/building.js +2 -0
- package/dist/schema/nodes/cabinet.d.ts +130 -129
- package/dist/schema/nodes/cabinet.d.ts.map +1 -1
- package/dist/schema/nodes/cabinet.js +1 -1
- package/dist/schema/nodes/ceiling.d.ts +15 -15
- package/dist/schema/nodes/chimney.d.ts +23 -23
- package/dist/schema/nodes/column.d.ts +207 -199
- package/dist/schema/nodes/column.d.ts.map +1 -1
- package/dist/schema/nodes/column.js +2 -0
- package/dist/schema/nodes/construction-dimension.d.ts +34 -34
- package/dist/schema/nodes/cupola.d.ts +15 -15
- package/dist/schema/nodes/curtain-wall.d.ts +21 -20
- package/dist/schema/nodes/curtain-wall.d.ts.map +1 -1
- package/dist/schema/nodes/curtain-wall.js +23 -0
- package/dist/schema/nodes/door.d.ts +50 -43
- package/dist/schema/nodes/door.d.ts.map +1 -1
- package/dist/schema/nodes/door.js +19 -0
- package/dist/schema/nodes/dormer.d.ts +37 -36
- package/dist/schema/nodes/dormer.d.ts.map +1 -1
- package/dist/schema/nodes/downspout.d.ts +17 -17
- package/dist/schema/nodes/duct-fitting.d.ts +24 -24
- package/dist/schema/nodes/duct-segment.d.ts +14 -14
- package/dist/schema/nodes/duct-terminal.d.ts +12 -12
- package/dist/schema/nodes/elevator.d.ts +15 -15
- package/dist/schema/nodes/eyebrow-vent.d.ts +13 -13
- package/dist/schema/nodes/fence-feature.d.ts +37 -37
- package/dist/schema/nodes/fence-types.d.ts +32 -0
- package/dist/schema/nodes/fence-types.d.ts.map +1 -0
- package/dist/schema/nodes/fence-types.js +22 -0
- package/dist/schema/nodes/fence.d.ts +43 -72
- package/dist/schema/nodes/fence.d.ts.map +1 -1
- package/dist/schema/nodes/fence.js +4 -20
- package/dist/schema/nodes/floor-opening.d.ts +8 -8
- package/dist/schema/nodes/guide.d.ts +8 -8
- package/dist/schema/nodes/gutter.d.ts +14 -14
- package/dist/schema/nodes/gutter.d.ts.map +1 -1
- package/dist/schema/nodes/gutter.js +6 -5
- package/dist/schema/nodes/hvac-equipment.d.ts +13 -13
- package/dist/schema/nodes/imported-mesh.d.ts +8 -8
- package/dist/schema/nodes/item.d.ts +30 -25
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/lean-to-extension.d.ts +36 -36
- package/dist/schema/nodes/level.d.ts +9 -9
- package/dist/schema/nodes/lineset.d.ts +8 -8
- package/dist/schema/nodes/liquid-line.d.ts +8 -8
- package/dist/schema/nodes/measurement.d.ts +8 -8
- package/dist/schema/nodes/opening-types.d.ts +13 -13
- package/dist/schema/nodes/opening-types.d.ts.map +1 -1
- package/dist/schema/nodes/pipe-fitting.d.ts +15 -15
- package/dist/schema/nodes/pipe-segment.d.ts +11 -11
- package/dist/schema/nodes/pipe-trap.d.ts +9 -9
- package/dist/schema/nodes/ridge-vent.d.ts +14 -14
- package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
- package/dist/schema/nodes/ridge-vent.js +3 -1
- package/dist/schema/nodes/roof-glazing-config.d.ts +90 -0
- package/dist/schema/nodes/roof-glazing-config.d.ts.map +1 -0
- package/dist/schema/nodes/roof-glazing-config.js +34 -0
- package/dist/schema/nodes/roof-glazing.d.ts +57 -0
- package/dist/schema/nodes/roof-glazing.d.ts.map +1 -0
- package/dist/schema/nodes/roof-glazing.js +514 -0
- package/dist/schema/nodes/roof-segment-resize.d.ts +4 -0
- package/dist/schema/nodes/roof-segment-resize.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-resize.js +21 -0
- package/dist/schema/nodes/roof-segment-shape.d.ts +5 -0
- package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment-shape.js +44 -0
- package/dist/schema/nodes/roof-segment-walls.d.ts +1 -1
- package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment-walls.js +24 -0
- package/dist/schema/nodes/roof-segment.d.ts +153 -46
- package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment.js +91 -20
- package/dist/schema/nodes/roof-types.d.ts +14 -0
- package/dist/schema/nodes/roof-types.d.ts.map +1 -0
- package/dist/schema/nodes/roof-types.js +14 -0
- package/dist/schema/nodes/roof.d.ts +49 -49
- package/dist/schema/nodes/scan.d.ts +8 -8
- package/dist/schema/nodes/separator.d.ts +8 -8
- package/dist/schema/nodes/shelf.d.ts +16 -16
- package/dist/schema/nodes/site-facts.d.ts +64 -0
- package/dist/schema/nodes/site-facts.d.ts.map +1 -0
- package/dist/schema/nodes/site-facts.js +73 -0
- package/dist/schema/nodes/site.d.ts +105 -63
- package/dist/schema/nodes/site.d.ts.map +1 -1
- package/dist/schema/nodes/site.js +7 -70
- package/dist/schema/nodes/skylight.d.ts +41 -41
- package/dist/schema/nodes/skylight.d.ts.map +1 -1
- package/dist/schema/nodes/slab.d.ts +21 -21
- package/dist/schema/nodes/solar-panel.d.ts +21 -21
- package/dist/schema/nodes/spawn.d.ts +8 -8
- package/dist/schema/nodes/stair-construction.d.ts +3 -3
- package/dist/schema/nodes/stair-defaults.d.ts +16 -0
- package/dist/schema/nodes/stair-defaults.d.ts.map +1 -0
- package/dist/schema/nodes/stair-defaults.js +15 -0
- package/dist/schema/nodes/stair-segment.d.ts +22 -22
- package/dist/schema/nodes/stair-types.d.ts +29 -0
- package/dist/schema/nodes/stair-types.d.ts.map +1 -0
- package/dist/schema/nodes/stair-types.js +23 -0
- package/dist/schema/nodes/stair.d.ts +51 -75
- package/dist/schema/nodes/stair.d.ts.map +1 -1
- package/dist/schema/nodes/stair.js +6 -20
- package/dist/schema/nodes/structural-grid.d.ts +8 -8
- package/dist/schema/nodes/surface-hole-metadata.d.ts +2 -2
- package/dist/schema/nodes/turbine-vent.d.ts +13 -13
- package/dist/schema/nodes/unit.d.ts +10 -10
- package/dist/schema/nodes/unit.d.ts.map +1 -1
- package/dist/schema/nodes/wall.d.ts +479 -146
- package/dist/schema/nodes/wall.d.ts.map +1 -1
- package/dist/schema/nodes/wall.js +19 -0
- package/dist/schema/nodes/window.d.ts +55 -39
- package/dist/schema/nodes/window.d.ts.map +1 -1
- package/dist/schema/nodes/window.js +10 -0
- package/dist/schema/nodes/zone.d.ts +231 -12
- package/dist/schema/nodes/zone.d.ts.map +1 -1
- package/dist/schema/nodes/zone.js +10 -0
- package/dist/schema/provenance.d.ts +21 -21
- package/dist/schema/scene-material.d.ts +5 -5
- package/dist/schema/site-presentation.d.ts +100 -0
- package/dist/schema/site-presentation.d.ts.map +1 -0
- package/dist/schema/site-presentation.js +83 -0
- package/dist/schema/types.d.ts +1954 -1414
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts.map +1 -1
- package/dist/services/index.d.ts +5 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +5 -1
- package/dist/services/level-height.d.ts.map +1 -1
- package/dist/services/level-height.js +7 -3
- package/dist/services/port-connectivity.d.ts +4 -0
- package/dist/services/port-connectivity.d.ts.map +1 -1
- package/dist/services/port-connectivity.js +35 -0
- package/dist/services/project-file-sink.d.ts +9 -0
- package/dist/services/project-file-sink.d.ts.map +1 -0
- package/dist/services/project-file-sink.js +13 -0
- package/dist/services/roof-bearing.d.ts +62 -0
- package/dist/services/roof-bearing.d.ts.map +1 -0
- package/dist/services/roof-bearing.js +234 -0
- package/dist/services/roof-level.d.ts +121 -0
- package/dist/services/roof-level.d.ts.map +1 -0
- package/dist/services/roof-level.js +280 -0
- package/dist/services/roof-move.d.ts +83 -0
- package/dist/services/roof-move.d.ts.map +1 -0
- package/dist/services/roof-move.js +316 -0
- package/dist/services/stair-surface-snap.d.ts +14 -0
- package/dist/services/stair-surface-snap.d.ts.map +1 -0
- package/dist/services/stair-surface-snap.js +116 -0
- package/dist/services/storey-datum.d.ts +12 -0
- package/dist/services/storey-datum.d.ts.map +1 -0
- package/dist/services/storey-datum.js +18 -0
- package/dist/services/storey.d.ts +51 -5
- package/dist/services/storey.d.ts.map +1 -1
- package/dist/services/storey.js +125 -8
- package/dist/solar-panel-presets.d.ts +2 -2
- package/dist/store/actions/node-actions.d.ts +3613 -3182
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +46 -1
- package/dist/store/derived-node-guard.d.ts.map +1 -1
- package/dist/store/history-control.d.ts +39 -0
- package/dist/store/history-control.d.ts.map +1 -1
- package/dist/store/history-control.js +84 -4
- package/dist/store/scene-annotations.d.ts +7267 -6409
- package/dist/store/scene-annotations.d.ts.map +1 -1
- package/dist/store/scene-preview.d.ts +16 -0
- package/dist/store/scene-preview.d.ts.map +1 -0
- package/dist/store/scene-preview.js +144 -0
- package/dist/store/use-live-node-overrides.d.ts.map +1 -1
- package/dist/store/use-live-terrain.d.ts.map +1 -1
- package/dist/store/use-live-transforms.d.ts.map +1 -1
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +37 -4
- package/dist/systems/elevator/elevator-dispatch.js +1 -1
- package/dist/systems/fence/fence-features.d.ts.map +1 -1
- package/dist/systems/owned-floor-openings.d.ts.map +1 -1
- package/dist/systems/owned-floor-openings.js +24 -3
- package/dist/systems/roof/roof-elevation-system.d.ts.map +1 -1
- package/dist/systems/roof/roof-elevation-system.js +9 -3
- package/dist/systems/roof/roof-elevation.d.ts +5 -0
- package/dist/systems/roof/roof-elevation.d.ts.map +1 -1
- package/dist/systems/roof/roof-elevation.js +91 -62
- package/dist/systems/slab/__fixtures__/floor-step.d.ts +4623 -3516
- package/dist/systems/slab/__fixtures__/floor-step.d.ts.map +1 -1
- package/dist/systems/slab/__fixtures__/raised-room.d.ts +5149 -4076
- package/dist/systems/slab/__fixtures__/raised-room.d.ts.map +1 -1
- package/dist/systems/slab/slab-support.d.ts +6 -3
- package/dist/systems/slab/slab-support.d.ts.map +1 -1
- package/dist/systems/slab/slab-support.js +78 -10
- package/dist/systems/stair/stair-detail-budget.d.ts +2 -2
- package/dist/systems/stair/stair-detail-budget.d.ts.map +1 -1
- package/dist/systems/stair/stair-footprint.d.ts +6 -0
- package/dist/systems/stair/stair-footprint.d.ts.map +1 -1
- package/dist/systems/stair/stair-footprint.js +27 -14
- package/dist/systems/stair/stair-layout.d.ts +2 -2
- package/dist/systems/stair/stair-opening-preview.d.ts +3643 -3214
- package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
- package/dist/systems/stair/stair-presets.d.ts +73 -65
- package/dist/systems/stair/stair-presets.d.ts.map +1 -1
- package/dist/systems/stair/stair-presets.js +16 -9
- package/dist/systems/stair/stair-rail-path.d.ts +1 -1
- package/dist/systems/stair/stair-rise-query.d.ts +16 -0
- package/dist/systems/stair/stair-rise-query.d.ts.map +1 -1
- package/dist/systems/stair/stair-rise-query.js +57 -7
- package/dist/systems/stair/stair-sizing.d.ts +101 -99
- package/dist/systems/stair/stair-sizing.d.ts.map +1 -1
- package/dist/systems/wall/wall-assembly.d.ts +11 -0
- package/dist/systems/wall/wall-assembly.d.ts.map +1 -1
- package/dist/systems/wall/wall-assembly.js +21 -0
- package/dist/systems/wall/wall-curve.d.ts +5 -0
- package/dist/systems/wall/wall-curve.d.ts.map +1 -1
- package/dist/systems/wall/wall-curve.js +13 -0
- package/dist/systems/wall/wall-frame.d.ts.map +1 -1
- package/dist/systems/wall/wall-frame.js +8 -0
- package/dist/systems/wall/wall-room-sides.d.ts +8 -0
- package/dist/systems/wall/wall-room-sides.d.ts.map +1 -1
- package/dist/systems/wall/wall-room-sides.js +60 -7
- package/dist/systems/wall/wall-top.d.ts +7 -4
- package/dist/systems/wall/wall-top.d.ts.map +1 -1
- package/dist/systems/wall/wall-top.js +14 -6
- package/dist/systems/wall/wall-topology.d.ts +4 -0
- package/dist/systems/wall/wall-topology.d.ts.map +1 -1
- package/dist/systems/wall/wall-topology.js +4 -2
- package/dist/systems/wall/wall-trim.d.ts +7 -0
- package/dist/systems/wall/wall-trim.d.ts.map +1 -0
- package/dist/systems/wall/wall-trim.js +10 -0
- package/dist/utils/clone-scene-graph.d.ts.map +1 -1
- package/dist/utils/clone-scene-graph.js +8 -0
- package/dist/utils/ensure-scene-openings.d.ts +7420 -6562
- package/dist/utils/ensure-scene-openings.d.ts.map +1 -1
- package/dist/utils/floor-piece-adoption.d.ts +2 -2
- package/dist/utils/floor-plate-migration.d.ts +3746 -3317
- package/dist/utils/floor-plate-migration.d.ts.map +1 -1
- package/dist/utils/floor-plate-migration.js +2 -2
- package/dist/utils/heal-scene-graph.d.ts +12 -0
- package/dist/utils/heal-scene-graph.d.ts.map +1 -1
- package/dist/utils/heal-scene-graph.js +40 -23
- package/dist/utils/legacy-wall-datums.d.ts.map +1 -1
- package/dist/utils/legacy-wall-datums.js +2 -2
- package/dist/utils/owned-floor-opening-migration.d.ts +3642 -3213
- package/dist/utils/owned-floor-opening-migration.d.ts.map +1 -1
- package/dist/utils/reconcile-structure-on-load.d.ts +3730 -7777
- package/dist/utils/reconcile-structure-on-load.d.ts.map +1 -1
- package/dist/utils/scene-migrations.d.ts +1 -1
- package/dist/utils/scene-migrations.d.ts.map +1 -1
- package/dist/utils/scene-migrations.js +1 -1
- package/dist/utils/semantic-equal.d.ts +3 -0
- package/dist/utils/semantic-equal.d.ts.map +1 -0
- package/dist/utils/semantic-equal.js +26 -0
- package/dist/utils/structure-id.d.ts.map +1 -1
- package/dist/utils/types.d.ts.map +1 -1
- package/dist/utils/wall-face-migration.d.ts +1 -1
- package/dist/utils/wall-face-migration.d.ts.map +1 -1
- package/package.json +36 -10
|
@@ -0,0 +1,1076 @@
|
|
|
1
|
+
import { refuse } from '../agent-tools/refusal.js';
|
|
2
|
+
import { doorTypeFields } from '../building/door-types.js';
|
|
3
|
+
import { DOOR_STYLES, doorStyleLook, getWindowStyleOverrides, WINDOW_STYLES, } from '../building/opening-style-presets.js';
|
|
4
|
+
import { windowTakesStyle, windowTypeFields } from '../building/window-types.js';
|
|
5
|
+
import { floorRoomFaces } from '../lib/floor-room-faces.js';
|
|
6
|
+
import { matchScriptSlotsToLibrary, requireMeasured, scriptedSize, scriptSource, } from '../lib/geometry-script-node.js';
|
|
7
|
+
import { detectSpacesForLevel } from '../lib/space-detection.js';
|
|
8
|
+
import { reconcileSceneStructure } from '../lib/structure-reconcile.js';
|
|
9
|
+
import { wallFaceScriptInputs } from '../lib/wall-face-script.js';
|
|
10
|
+
import { nearestLibraryColorRef } from '../procedural-items/library-colors.js';
|
|
11
|
+
import { ColumnNode, DoorNode, LevelNode, SlabNode, WallNode, WindowNode, ZoneNode, } from '../schema/index.js';
|
|
12
|
+
import { DoorType, WindowType } from '../schema/nodes/opening-types.js';
|
|
13
|
+
import { resolveCeilingHeight } from '../services/level-height.js';
|
|
14
|
+
import { CEILING_DRAW_OFFSET } from '../services/storey.js';
|
|
15
|
+
import { getWallLocalFaceZ } from '../systems/wall/wall-frame.js';
|
|
16
|
+
import { roomFaceCover } from '../systems/wall/wall-room-sides.js';
|
|
17
|
+
import { migrateRoomZones } from '../utils/room-zone-migration.js';
|
|
18
|
+
import { addObject } from './add-object.js';
|
|
19
|
+
import { authoredSceneChanges } from './authored-scene-merge.js';
|
|
20
|
+
import { paint } from './paint.js';
|
|
21
|
+
import { pointInPolygon, projectWorldPointToWallLocalX } from './plan-geometry.js';
|
|
22
|
+
import { resolveInlinePaintMaterial } from './scene-materials.js';
|
|
23
|
+
import { setWallSkirting } from './wall-skirting.js';
|
|
24
|
+
const JOIN_REACH = 0.3;
|
|
25
|
+
const THIN_SLAB = 0.02;
|
|
26
|
+
const MANY_SLABS = 20;
|
|
27
|
+
const MANY_REGIONS = 24;
|
|
28
|
+
const HEX = /^#[0-9a-f]{6}$/i;
|
|
29
|
+
const GLASS = 'library:preset-glass';
|
|
30
|
+
/**
|
|
31
|
+
* Explicit payload keys retain their identities across revisions; derived nodes use the
|
|
32
|
+
* conversion's retained seed. A changed payload never remints every existing wall or item.
|
|
33
|
+
*/
|
|
34
|
+
function idFactory(seed, previous = {}) {
|
|
35
|
+
const counts = new Map();
|
|
36
|
+
return (kind, key) => {
|
|
37
|
+
const n = (counts.get(kind) ?? 0) + 1;
|
|
38
|
+
counts.set(kind, n);
|
|
39
|
+
if (key && previous[key]?.startsWith(`${kind}_`))
|
|
40
|
+
return previous[key];
|
|
41
|
+
let hash = 0x811c9dc5;
|
|
42
|
+
for (const ch of `${seed}:${kind}:${key ?? n}`)
|
|
43
|
+
hash = Math.imul(hash ^ ch.charCodeAt(0), 0x01000193) >>> 0;
|
|
44
|
+
return `${kind}_as${hash.toString(16).padStart(8, '0')}`;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function payloadSeed(payload) {
|
|
48
|
+
let hash = 0x811c9dc5;
|
|
49
|
+
for (const ch of JSON.stringify(payload))
|
|
50
|
+
hash = Math.imul(hash ^ ch.charCodeAt(0), 0x01000193) >>> 0;
|
|
51
|
+
return hash.toString(16);
|
|
52
|
+
}
|
|
53
|
+
const dist = (a, b) => Math.hypot(a[0] - b[0], a[1] - b[1]);
|
|
54
|
+
const metres = (value) => `${value.toFixed(2)} m`;
|
|
55
|
+
/**
|
|
56
|
+
* Where a wall end meets another wall's centerline: the projection onto that line, as long as it
|
|
57
|
+
* lands on the wall or within reach past its ends. The line, not the segment, so a partition
|
|
58
|
+
* stopping short of a wall extends to it, and the wall it meets does not slide to the partition.
|
|
59
|
+
*/
|
|
60
|
+
function nearestOnSegment(p, a, b) {
|
|
61
|
+
const len = Math.hypot(b[0] - a[0], b[1] - a[1]) || 1;
|
|
62
|
+
const t = ((p[0] - a[0]) * (b[0] - a[0]) + (p[1] - a[1]) * (b[1] - a[1])) / (len * len);
|
|
63
|
+
if (t * len < -JOIN_REACH || (t - 1) * len > JOIN_REACH)
|
|
64
|
+
return { point: [p[0], p[1]], distance: Number.POSITIVE_INFINITY };
|
|
65
|
+
const q = [a[0] + t * (b[0] - a[0]), a[1] + t * (b[1] - a[1])];
|
|
66
|
+
return { point: q, distance: dist(p, q) };
|
|
67
|
+
}
|
|
68
|
+
const cross = (o, a, b) => (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
|
|
69
|
+
/** Whether two segments cross each other's interior (touching ends and shared edges do not). */
|
|
70
|
+
function segmentsCross(a, b, c, d) {
|
|
71
|
+
const [d1, d2, d3, d4] = [cross(c, d, a), cross(c, d, b), cross(a, b, c), cross(a, b, d)];
|
|
72
|
+
return d1 * d2 < 0 && d3 * d4 < 0;
|
|
73
|
+
}
|
|
74
|
+
/** Whether two polygons share interior area: a slab flush against a wall's face does not. */
|
|
75
|
+
function polygonsOverlap(a, b) {
|
|
76
|
+
if (a.some((p) => pointInPolygon(p, b, false)) || b.some((p) => pointInPolygon(p, a, false)))
|
|
77
|
+
return true;
|
|
78
|
+
for (let i = 0; i < a.length; i++)
|
|
79
|
+
for (let j = 0; j < b.length; j++)
|
|
80
|
+
if (segmentsCross(a[i], a[(i + 1) % a.length], b[j], b[(j + 1) % b.length]))
|
|
81
|
+
return true;
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
/** A wall's footprint, pulled in by a few millimetres so a slab meeting its face is not on it. */
|
|
85
|
+
function wallFootprint(wall) {
|
|
86
|
+
const inset = 0.005;
|
|
87
|
+
const [dx, dz] = [wall.end[0] - wall.start[0], wall.end[1] - wall.start[1]];
|
|
88
|
+
const len = Math.hypot(dx, dz) || 1;
|
|
89
|
+
const [ux, uz] = [dx / len, dz / len];
|
|
90
|
+
const half = Math.max(wall.thickness / 2 - inset, 0.001);
|
|
91
|
+
const s = [wall.start[0] + ux * inset, wall.start[1] + uz * inset];
|
|
92
|
+
const e = [wall.end[0] - ux * inset, wall.end[1] - uz * inset];
|
|
93
|
+
return [
|
|
94
|
+
[s[0] - uz * half, s[1] + ux * half],
|
|
95
|
+
[e[0] - uz * half, e[1] + ux * half],
|
|
96
|
+
[e[0] + uz * half, e[1] - ux * half],
|
|
97
|
+
[s[0] + uz * half, s[1] - ux * half],
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
function toLocal(frame, world) {
|
|
101
|
+
const [dx, dy, dz] = [
|
|
102
|
+
world[0] - frame.position[0],
|
|
103
|
+
world[1] - frame.position[1],
|
|
104
|
+
world[2] - frame.position[2],
|
|
105
|
+
];
|
|
106
|
+
const [c, s] = [Math.cos(frame.yaw), Math.sin(frame.yaw)];
|
|
107
|
+
return [c * dx - s * dz, dy, s * dx + c * dz];
|
|
108
|
+
}
|
|
109
|
+
const MATTE = { roughness: 0.9, metalness: 0 };
|
|
110
|
+
/**
|
|
111
|
+
* The finish a payload value writes. A library or scene ref passes through; a hex colour is kept
|
|
112
|
+
* as an exact native material, one scene material per distinct colour and surface across the
|
|
113
|
+
* payload, named by them. A host that keeps no scene materials gets the nearest library colour,
|
|
114
|
+
* said once.
|
|
115
|
+
*/
|
|
116
|
+
function finishPool(context, say) {
|
|
117
|
+
const materials = context.materials
|
|
118
|
+
? { ...context.materials }
|
|
119
|
+
: undefined;
|
|
120
|
+
const created = [];
|
|
121
|
+
let snapped = false;
|
|
122
|
+
return {
|
|
123
|
+
materials,
|
|
124
|
+
created,
|
|
125
|
+
ref(value, surface = MATTE) {
|
|
126
|
+
if (value.startsWith('library:') || value.startsWith('scene:'))
|
|
127
|
+
return { ref: value };
|
|
128
|
+
if (!HEX.test(value))
|
|
129
|
+
return { error: `${value} is no colour: give #rrggbb or library:<id>.` };
|
|
130
|
+
const hex = value.toLowerCase();
|
|
131
|
+
if (!materials) {
|
|
132
|
+
if (!snapped)
|
|
133
|
+
say('this host keeps no scene materials: colours written as the nearest library colour');
|
|
134
|
+
snapped = true;
|
|
135
|
+
return { ref: nearestLibraryColorRef(hex).ref };
|
|
136
|
+
}
|
|
137
|
+
const resolved = resolveInlinePaintMaterial(materials, {
|
|
138
|
+
properties: {
|
|
139
|
+
color: hex,
|
|
140
|
+
roughness: surface.roughness,
|
|
141
|
+
metalness: surface.metalness,
|
|
142
|
+
opacity: 1,
|
|
143
|
+
transparent: false,
|
|
144
|
+
side: 'front',
|
|
145
|
+
},
|
|
146
|
+
}, surface.roughness === MATTE.roughness && surface.metalness === MATTE.metalness
|
|
147
|
+
? hex
|
|
148
|
+
: `${hex}, roughness ${+surface.roughness.toFixed(2)}, metalness ${+surface.metalness.toFixed(2)}`);
|
|
149
|
+
if (resolved.created) {
|
|
150
|
+
materials[resolved.sceneMaterial.id] = resolved.sceneMaterial;
|
|
151
|
+
created.push(resolved.sceneMaterial);
|
|
152
|
+
}
|
|
153
|
+
return { ref: resolved.ref };
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const isDoorType = (type) => DoorType.options.includes(type);
|
|
158
|
+
const isWindowType = (type) => WindowType.options.includes(type);
|
|
159
|
+
const isDoorStyle = (style) => DOOR_STYLES.includes(style);
|
|
160
|
+
const isWindowStyle = (style) => WINDOW_STYLES.includes(style);
|
|
161
|
+
const CEILING_POINT_CODE = `export const mount = 'ceiling'
|
|
162
|
+
export default function build({ THREE }) {
|
|
163
|
+
const material = new THREE.MeshStandardMaterial({ color: '#ffffff' })
|
|
164
|
+
material.name = 'slot_body'
|
|
165
|
+
return new THREE.Mesh(new THREE.CylinderGeometry(0.03, 0.03, 0.008, 24), material)
|
|
166
|
+
}`;
|
|
167
|
+
/** Candidate modules, compiled by the host before room derivation decides which points are used. */
|
|
168
|
+
export function authorSceneCeilingPoints(payload) {
|
|
169
|
+
return payload.levels.flatMap((level, index) => level.lights.flatMap((light, i) => light.fixture ? [] : [{ id: `light/${index}/${i}`, code: CEILING_POINT_CODE }]));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The rooms whose floor finish is a module, by their zone once the write made it: the host reads
|
|
173
|
+
* each room's floor (`floorScriptInputs`), compiles the module for it and writes it with
|
|
174
|
+
* `setRoomFloorScript`, which core cannot do without a three.js runtime. A room whose seed found
|
|
175
|
+
* no enclosure has no zone and is already a defect.
|
|
176
|
+
*/
|
|
177
|
+
export function authorSceneFloorScripts(payload, report) {
|
|
178
|
+
return payload.levels.flatMap((level, index) => level.rooms.flatMap((room, i) => {
|
|
179
|
+
const roomId = `room/${index}/${i}`;
|
|
180
|
+
const zoneId = report.ids[roomId];
|
|
181
|
+
return room.floorCode && zoneId ? [{ roomId, zoneId, code: room.floorCode }] : [];
|
|
182
|
+
}));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Which faces the payload's face modules build on, and why the others cannot be: a wall's own
|
|
186
|
+
* `faceLeft` (face a) and `faceRight` (face b), then each room's `wallCode` on the faces its floor
|
|
187
|
+
* meets (the spans of the room the zone was derived from, the faces `setWallSkirting` runs along),
|
|
188
|
+
* where a wall's own module wins. A face with nothing to build on (a curved or curtain wall) or
|
|
189
|
+
* that no room looks into is a `no_face` defect.
|
|
190
|
+
*/
|
|
191
|
+
function resolveFaceScripts(payload, ids, nodes) {
|
|
192
|
+
const scripts = [];
|
|
193
|
+
const defects = [];
|
|
194
|
+
const warnings = [];
|
|
195
|
+
const side = (face) => (face === 'a' ? 'left' : 'right');
|
|
196
|
+
const add = (wallId, face, nodeId, code, toHeight) => scripts.push({ wallId, face, nodeId, code, ...(toHeight === undefined ? {} : { toHeight }) });
|
|
197
|
+
const flat = 'is curved, a curtain wall or has no height';
|
|
198
|
+
payload.levels.forEach((level, index) => {
|
|
199
|
+
const walls = (level.walls ?? []).flatMap((spec) => {
|
|
200
|
+
const nodeId = ids[spec.id];
|
|
201
|
+
return nodeId && nodes[nodeId]?.type === 'wall' ? [{ spec, nodeId }] : [];
|
|
202
|
+
});
|
|
203
|
+
const owned = new Set();
|
|
204
|
+
for (const { spec, nodeId } of walls) {
|
|
205
|
+
for (const [face, module] of [
|
|
206
|
+
['a', spec.faceLeft],
|
|
207
|
+
['b', spec.faceRight],
|
|
208
|
+
]) {
|
|
209
|
+
if (!module)
|
|
210
|
+
continue;
|
|
211
|
+
owned.add(`${nodeId}/${face}`);
|
|
212
|
+
const id = `${spec.id}/${face}`;
|
|
213
|
+
if (!wallFaceScriptInputs(nodes, nodeId, face, module.toHeight))
|
|
214
|
+
defects.push({
|
|
215
|
+
id,
|
|
216
|
+
code: 'no_face',
|
|
217
|
+
message: `Wall ${spec.id} ${flat}: its ${side(face)} face has nothing a script can build on and keeps its paint.`,
|
|
218
|
+
});
|
|
219
|
+
else if (roomFaceCover(nodes, nodeId)[face] === 'none')
|
|
220
|
+
defects.push({
|
|
221
|
+
id,
|
|
222
|
+
code: 'no_face',
|
|
223
|
+
message: `No room looks into the ${side(face)} face of wall ${spec.id} (left and right as seen from its start to its end): its face script was not written.`,
|
|
224
|
+
});
|
|
225
|
+
else
|
|
226
|
+
add(spec.id, face, nodeId, module.code, module.toHeight);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const byRoom = new Map();
|
|
230
|
+
for (const [i, room] of level.rooms.entries()) {
|
|
231
|
+
const roomId = `room/${index}/${i}`;
|
|
232
|
+
const zone = nodes[ids[roomId] ?? ''];
|
|
233
|
+
if (!room.wallCode || zone?.type !== 'zone')
|
|
234
|
+
continue;
|
|
235
|
+
const boundaries = Object.values(nodes).filter((n) => n.parentId === zone.parentId && (n.type === 'wall' || n.type === 'separator'));
|
|
236
|
+
const zoneWalls = [...zone.boundaryWallIds].sort().join();
|
|
237
|
+
const derived = floorRoomFaces(boundaries).find((r) => [...new Set(r.spans.filter((s) => s.kind === 'wall').map((s) => s.boundaryId))]
|
|
238
|
+
.sort()
|
|
239
|
+
.join() === zoneWalls && pointInPolygon(room.seed, r.referencePolygon));
|
|
240
|
+
const faces = new Set((derived?.spans ?? [])
|
|
241
|
+
.filter((s) => s.kind === 'wall' && s.t1 > s.t0)
|
|
242
|
+
.map((s) => `${s.boundaryId}/${s.face}`));
|
|
243
|
+
if (!faces.size) {
|
|
244
|
+
defects.push({
|
|
245
|
+
id: roomId,
|
|
246
|
+
code: 'no_face',
|
|
247
|
+
message: `No wall face looks into "${room.name}": its wallCode was not written.`,
|
|
248
|
+
});
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
for (const { spec, nodeId } of walls) {
|
|
252
|
+
for (const face of ['a', 'b']) {
|
|
253
|
+
const key = `${nodeId}/${face}`;
|
|
254
|
+
if (!faces.has(key) || owned.has(key))
|
|
255
|
+
continue;
|
|
256
|
+
const other = byRoom.get(key);
|
|
257
|
+
if (other) {
|
|
258
|
+
if (other.code !== room.wallCode || other.toHeight !== room.wallToHeight)
|
|
259
|
+
warnings.push({
|
|
260
|
+
id: `${spec.id}/${face}`,
|
|
261
|
+
code: 'face_shared',
|
|
262
|
+
message: `The ${side(face)} face of wall ${spec.id} looks into "${other.name}" and "${room.name}": it is built by "${other.name}"'s wallCode.`,
|
|
263
|
+
});
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
byRoom.set(key, { name: room.name, code: room.wallCode, toHeight: room.wallToHeight });
|
|
267
|
+
if (!wallFaceScriptInputs(nodes, nodeId, face, room.wallToHeight))
|
|
268
|
+
defects.push({
|
|
269
|
+
id: `${spec.id}/${face}`,
|
|
270
|
+
code: 'no_face',
|
|
271
|
+
message: `Wall ${spec.id} ${flat}: "${room.name}"'s wallCode was not written on its ${side(face)} face, which keeps its paint.`,
|
|
272
|
+
});
|
|
273
|
+
else
|
|
274
|
+
add(spec.id, face, nodeId, room.wallCode, room.wallToHeight);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
return { scripts, defects, warnings };
|
|
280
|
+
}
|
|
281
|
+
/** Below this share a floor or face finish leaves enough of its host bare to be worth a warning. */
|
|
282
|
+
const FINISH_COVERED = 0.98;
|
|
283
|
+
const figure = (value) => String(Math.round(value * 100) / 100);
|
|
284
|
+
/** A bare patch on a floor, by the edges of the floor's bounds it runs along, and its extent. */
|
|
285
|
+
function floorPatch({ min, max }, polygon) {
|
|
286
|
+
const reach = 0.05;
|
|
287
|
+
const xs = polygon.map(([x]) => x);
|
|
288
|
+
const zs = polygon.map(([, z]) => z);
|
|
289
|
+
const touches = {
|
|
290
|
+
north: min[1] <= Math.min(...zs) + reach,
|
|
291
|
+
south: max[1] >= Math.max(...zs) - reach,
|
|
292
|
+
west: min[0] <= Math.min(...xs) + reach,
|
|
293
|
+
east: max[0] >= Math.max(...xs) - reach,
|
|
294
|
+
};
|
|
295
|
+
const sides = Object.keys(touches).filter((side) => touches[side]);
|
|
296
|
+
const ns = sides.filter((side) => side === 'north' || side === 'south');
|
|
297
|
+
const ew = sides.filter((side) => side === 'west' || side === 'east');
|
|
298
|
+
const where = sides.length === 0
|
|
299
|
+
? 'inside the floor'
|
|
300
|
+
: sides.length === 1
|
|
301
|
+
? `along the ${sides[0]} edge`
|
|
302
|
+
: sides.length > 2
|
|
303
|
+
? 'over most of the floor'
|
|
304
|
+
: ns.length === 1
|
|
305
|
+
? `in the ${ns[0]}-${ew[0]} corner`
|
|
306
|
+
: `across the floor from ${sides[0]} to ${sides[1]}`;
|
|
307
|
+
return `${where} (${figure(max[0] - min[0])} × ${figure(max[1] - min[1])} m, x ${figure(min[0])} to ${figure(max[0])}, z ${figure(min[1])} to ${figure(max[1])})`;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* The `finish_gaps` warning for a floor or face script whose build leaves part of its host bare:
|
|
311
|
+
* its `coverage` under FINISH_COVERED with at least one bare patch, each named by where it lies.
|
|
312
|
+
* Joints make no patch, so a tiled finish is never warned for its joints alone. Null otherwise.
|
|
313
|
+
*/
|
|
314
|
+
export function authorSceneFinishGaps(id, manifest, host) {
|
|
315
|
+
const { coverage, uncovered } = manifest;
|
|
316
|
+
if (coverage === undefined || coverage >= FINISH_COVERED || !uncovered?.length)
|
|
317
|
+
return null;
|
|
318
|
+
const share = `${Math.round(coverage * 100)}%`;
|
|
319
|
+
const message = 'room' in host
|
|
320
|
+
? `The floor finish of "${host.room}" covers ${share} of its floor: uncovered ${uncovered.map((patch) => floorPatch(patch, host.polygon)).join('; ')}.`
|
|
321
|
+
: `The finish on the ${host.face === 'a' ? 'left' : 'right'} face of wall ${host.wall} covers ${share} of the face: uncovered ${uncovered
|
|
322
|
+
.map(({ min, max }) => `${figure(min[0])} to ${figure(max[0])} m along the wall from its start, ${figure(min[1])} to ${figure(max[1])} m up (${figure(max[0] - min[0])} × ${figure(max[1] - min[1])} m)`)
|
|
323
|
+
.join('; ')}.`;
|
|
324
|
+
return { id, code: 'finish_gaps', message };
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* The wall faces whose finish is a module, once the write made the walls and the rooms: the host
|
|
328
|
+
* reads each face (`wallFaceScriptInputs`), compiles the module for it and writes it with
|
|
329
|
+
* `setWallFaceScript`, which core cannot do without a three.js runtime. The faces that cannot take
|
|
330
|
+
* one are already `no_face` defects in the operation's report.
|
|
331
|
+
*/
|
|
332
|
+
export function authorSceneFaceScripts(payload, report, nodes) {
|
|
333
|
+
return resolveFaceScripts(payload, report.ids, nodes).scripts;
|
|
334
|
+
}
|
|
335
|
+
export function authorScene(scene, input, context) {
|
|
336
|
+
const { payload } = input;
|
|
337
|
+
const sourceKeys = new Set();
|
|
338
|
+
const claimSourceKey = (key) => {
|
|
339
|
+
if (sourceKeys.has(key))
|
|
340
|
+
refuse('duplicate_source_id', `Source id "${key}" is repeated. Give every wall and item a unique id across all levels; opening and generated-part keys must also remain distinct.`, { id: key, mutationApplied: false });
|
|
341
|
+
sourceKeys.add(key);
|
|
342
|
+
};
|
|
343
|
+
payload.levels.forEach((level, index) => {
|
|
344
|
+
claimSourceKey(`level/${index}`);
|
|
345
|
+
for (const [kind, parts] of [
|
|
346
|
+
['room', level.rooms],
|
|
347
|
+
['slab', level.slabs],
|
|
348
|
+
['column', level.columns],
|
|
349
|
+
['light', level.lights],
|
|
350
|
+
])
|
|
351
|
+
parts?.forEach((_, i) => {
|
|
352
|
+
claimSourceKey(`${kind}/${index}/${i}`);
|
|
353
|
+
});
|
|
354
|
+
for (const wall of level.walls ?? []) {
|
|
355
|
+
claimSourceKey(wall.id);
|
|
356
|
+
wall.openings?.forEach((_, i) => {
|
|
357
|
+
claimSourceKey(`${wall.id}/${i}`);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
for (const item of level.items ?? [])
|
|
361
|
+
claimSourceKey(item.id);
|
|
362
|
+
});
|
|
363
|
+
const buildings = Object.values(scene).filter((n) => n.type === 'building');
|
|
364
|
+
const selected = input.buildingId ?? (context.activeLevelId ? scene[context.activeLevelId]?.parentId : undefined);
|
|
365
|
+
const building = selected
|
|
366
|
+
? buildings.find((node) => node.id === selected)
|
|
367
|
+
: buildings.length === 1
|
|
368
|
+
? buildings[0]
|
|
369
|
+
: undefined;
|
|
370
|
+
if (!building)
|
|
371
|
+
refuse('no_building', 'The scene has no building to put the levels in.');
|
|
372
|
+
const existingLevels = Object.values(scene).filter((n) => n.type === 'level' && n.parentId === building.id);
|
|
373
|
+
const saved = building.metadata?.authorSceneState;
|
|
374
|
+
const previous = saved?.version === 1 &&
|
|
375
|
+
saved.buildingId === building.id &&
|
|
376
|
+
saved.nodes &&
|
|
377
|
+
saved.ids &&
|
|
378
|
+
typeof saved.seed === 'string'
|
|
379
|
+
? saved
|
|
380
|
+
: undefined;
|
|
381
|
+
const converted = Boolean(previous) || existingLevels.some((l) => l.metadata?.authorScene);
|
|
382
|
+
if (converted && !input.replace)
|
|
383
|
+
refuse('conversion_exists', 'This scene already holds a conversion. Pass replace: true to write over it.');
|
|
384
|
+
if (!previous &&
|
|
385
|
+
(converted ||
|
|
386
|
+
existingLevels.some((level) => Object.values(scene).some((node) => node.parentId === level.id))))
|
|
387
|
+
refuse('existing_design', 'This building already contains work without a retained conversion baseline. Use its native edit tools or convert into a separate building; existing geometry will not be replaced.', { mutationApplied: false });
|
|
388
|
+
const seed = previous?.seed ?? `${building.id}:${payloadSeed(payload)}`;
|
|
389
|
+
const mint = idFactory(seed, previous?.ids);
|
|
390
|
+
const report = {
|
|
391
|
+
levels: 0,
|
|
392
|
+
walls: 0,
|
|
393
|
+
doors: 0,
|
|
394
|
+
windows: 0,
|
|
395
|
+
rooms: 0,
|
|
396
|
+
roomsNamed: 0,
|
|
397
|
+
slabs: 0,
|
|
398
|
+
columns: 0,
|
|
399
|
+
items: 0,
|
|
400
|
+
lights: 0,
|
|
401
|
+
floorScripts: 0,
|
|
402
|
+
faceScripts: 0,
|
|
403
|
+
snapped: [],
|
|
404
|
+
defaults: [],
|
|
405
|
+
warnings: [],
|
|
406
|
+
defects: [],
|
|
407
|
+
notes: [...payload.notes],
|
|
408
|
+
ids: {},
|
|
409
|
+
};
|
|
410
|
+
const defect = (id, code, message) => report.defects.push({ id, code, message });
|
|
411
|
+
const warn = (id, code, message) => report.warnings.push({ id, code, message });
|
|
412
|
+
const say = (sentence) => report.defaults.push(sentence);
|
|
413
|
+
const finishes = finishPool(context, say);
|
|
414
|
+
const finishRef = (value, id, surface) => {
|
|
415
|
+
if (!value)
|
|
416
|
+
return undefined;
|
|
417
|
+
const got = finishes.ref(value, surface);
|
|
418
|
+
if ('error' in got) {
|
|
419
|
+
defect(id, 'invalid_color', got.error);
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
return got.ref;
|
|
423
|
+
};
|
|
424
|
+
const exactSlots = (compiled, id) => {
|
|
425
|
+
const slots = matchScriptSlotsToLibrary(compiled.manifest);
|
|
426
|
+
for (const slot of compiled.manifest.slots) {
|
|
427
|
+
// Glass keeps the glass add_object writes, drawn see-through and letting light pass. A
|
|
428
|
+
// scene material carries no emission, so an emissive slot keeps the module's own material
|
|
429
|
+
// (the library match leaves it alone) and a bulb stays lit.
|
|
430
|
+
if (!slot.color || slot.emissive || slots[slot.id] === GLASS)
|
|
431
|
+
continue;
|
|
432
|
+
const ref = finishRef(slot.color, id, {
|
|
433
|
+
roughness: slot.roughness ?? MATTE.roughness,
|
|
434
|
+
metalness: slot.metalness ?? MATTE.metalness,
|
|
435
|
+
});
|
|
436
|
+
if (ref)
|
|
437
|
+
slots[slot.id] = ref;
|
|
438
|
+
}
|
|
439
|
+
return slots;
|
|
440
|
+
};
|
|
441
|
+
const paintContext = (levelId) => ({
|
|
442
|
+
...context,
|
|
443
|
+
activeLevelId: levelId,
|
|
444
|
+
...(finishes.materials ? { materials: finishes.materials } : {}),
|
|
445
|
+
});
|
|
446
|
+
// A separate candidate contains only its building and ancestors, never another building's work.
|
|
447
|
+
const draft = {};
|
|
448
|
+
let ancestor = building;
|
|
449
|
+
while (ancestor && !draft[ancestor.id]) {
|
|
450
|
+
draft[ancestor.id] = { ...ancestor, children: [] };
|
|
451
|
+
ancestor = ancestor.parentId ? scene[ancestor.parentId] : undefined;
|
|
452
|
+
}
|
|
453
|
+
const scaffoldIds = new Set(Object.keys(draft));
|
|
454
|
+
const levelNodes = [];
|
|
455
|
+
const itemNodeIds = new Map();
|
|
456
|
+
const itemFrames = new Map();
|
|
457
|
+
const skirtings = [];
|
|
458
|
+
let untypedWindows = 0;
|
|
459
|
+
payload.levels.forEach((level, index) => {
|
|
460
|
+
const levelNode = LevelNode.parse({
|
|
461
|
+
object: 'node',
|
|
462
|
+
type: 'level',
|
|
463
|
+
id: mint('level', `level/${index}`),
|
|
464
|
+
parentId: building.id,
|
|
465
|
+
visible: true,
|
|
466
|
+
metadata: { authorScene: { elevation: level.elevation } },
|
|
467
|
+
name: level.name,
|
|
468
|
+
level: index,
|
|
469
|
+
children: [],
|
|
470
|
+
});
|
|
471
|
+
draft[levelNode.id] = levelNode;
|
|
472
|
+
report.ids[`level/${index}`] = levelNode.id;
|
|
473
|
+
levelNodes.push(levelNode);
|
|
474
|
+
const place = (node) => {
|
|
475
|
+
draft[node.id] = node;
|
|
476
|
+
levelNode.children.push(node.id);
|
|
477
|
+
};
|
|
478
|
+
// ---------- walls, joined ----------
|
|
479
|
+
const walls = (level.walls ?? []).map((w) => ({
|
|
480
|
+
spec: w,
|
|
481
|
+
start: [...w.start],
|
|
482
|
+
end: [...w.end],
|
|
483
|
+
}));
|
|
484
|
+
for (const w of walls) {
|
|
485
|
+
for (const end of ['start', 'end']) {
|
|
486
|
+
const pt = w[end];
|
|
487
|
+
let best = null;
|
|
488
|
+
for (const o of walls) {
|
|
489
|
+
if (o === w)
|
|
490
|
+
continue;
|
|
491
|
+
const near = nearestOnSegment(pt, o.start, o.end);
|
|
492
|
+
if (near.distance < JOIN_REACH && (!best || near.distance < best.distance))
|
|
493
|
+
best = near;
|
|
494
|
+
}
|
|
495
|
+
if (best && best.distance > 0.001) {
|
|
496
|
+
report.snapped.push({
|
|
497
|
+
id: w.spec.id,
|
|
498
|
+
end,
|
|
499
|
+
movedM: Math.round(best.distance * 1000) / 1000,
|
|
500
|
+
});
|
|
501
|
+
w[end] = best.point;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
const wallNodes = new Map();
|
|
506
|
+
for (const w of walls) {
|
|
507
|
+
if (dist(w.start, w.end) < 0.05) {
|
|
508
|
+
defect(w.spec.id, 'wall_too_short', 'The wall is shorter than 5 cm after joining.');
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
const node = WallNode.parse({
|
|
512
|
+
object: 'node',
|
|
513
|
+
type: 'wall',
|
|
514
|
+
id: mint('wall', w.spec.id),
|
|
515
|
+
parentId: levelNode.id,
|
|
516
|
+
visible: true,
|
|
517
|
+
metadata: { authorScene: { id: w.spec.id } },
|
|
518
|
+
children: [],
|
|
519
|
+
start: w.start,
|
|
520
|
+
end: w.end,
|
|
521
|
+
height: w.spec.height,
|
|
522
|
+
thickness: w.spec.thickness,
|
|
523
|
+
});
|
|
524
|
+
place(node);
|
|
525
|
+
wallNodes.set(w.spec.id, { ...w, node });
|
|
526
|
+
if (w.spec.skirting)
|
|
527
|
+
skirtings.push({
|
|
528
|
+
id: w.spec.id,
|
|
529
|
+
nodeId: node.id,
|
|
530
|
+
levelId: levelNode.id,
|
|
531
|
+
skirting: w.spec.skirting,
|
|
532
|
+
});
|
|
533
|
+
report.ids[w.spec.id] = node.id;
|
|
534
|
+
report.walls++;
|
|
535
|
+
// ---------- its openings ----------
|
|
536
|
+
const length = dist(w.start, w.end);
|
|
537
|
+
(w.spec.openings ?? []).forEach((o, i) => {
|
|
538
|
+
const id = `${w.spec.id}/${i}`;
|
|
539
|
+
// A module supplies geometry; the declared type still describes how the opening works.
|
|
540
|
+
let compiled;
|
|
541
|
+
if (o.code) {
|
|
542
|
+
compiled = input.compiled[id];
|
|
543
|
+
if (!compiled) {
|
|
544
|
+
defect(id, 'compile_failed', input.compileErrors?.[id] ?? 'The module did not compile.');
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
if (compiled.mount !== 'wall') {
|
|
548
|
+
defect(id, 'wrong_mount', `A ${o.kind}'s module uses mount 'wall', not '${compiled.mount}'.`);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
try {
|
|
552
|
+
requireMeasured(compiled, { label: o.name ?? id, tool: 'author_scene' });
|
|
553
|
+
}
|
|
554
|
+
catch (error) {
|
|
555
|
+
const e = error;
|
|
556
|
+
defect(id, e.code ?? 'unmeasurable_object', e.message ?? String(error));
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
if (o.style)
|
|
560
|
+
say(`${o.kind} ${id}: style ignored, its module builds it`);
|
|
561
|
+
}
|
|
562
|
+
const [width, height] = compiled ? scriptedSize(compiled.manifest) : [o.width, o.height];
|
|
563
|
+
if (width > length + 0.01) {
|
|
564
|
+
defect(id, 'opening_wider_than_wall', `${o.kind} ${width.toFixed(2)} m wide on a ${length.toFixed(2)} m wall.`);
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
const x = Math.min(Math.max(o.along, width / 2), length - width / 2);
|
|
568
|
+
if (Math.abs(x - o.along) > 0.01)
|
|
569
|
+
say(`${o.kind} ${id}: moved ${Math.abs(x - o.along).toFixed(2)} m along the wall to fit inside it`);
|
|
570
|
+
const common = {
|
|
571
|
+
object: 'node',
|
|
572
|
+
id: mint(o.kind, id),
|
|
573
|
+
parentId: node.id,
|
|
574
|
+
visible: true,
|
|
575
|
+
metadata: { authorScene: { id, color: o.color ?? null } },
|
|
576
|
+
wallId: node.id,
|
|
577
|
+
width,
|
|
578
|
+
height,
|
|
579
|
+
rotation: [0, 0, 0],
|
|
580
|
+
...(o.name ? { name: o.name } : {}),
|
|
581
|
+
...(compiled
|
|
582
|
+
? {
|
|
583
|
+
source: scriptSource(compiled, { category: o.kind }),
|
|
584
|
+
slots: exactSlots(compiled, id),
|
|
585
|
+
}
|
|
586
|
+
: {}),
|
|
587
|
+
};
|
|
588
|
+
let opening;
|
|
589
|
+
if (o.kind === 'door') {
|
|
590
|
+
const type = o.type;
|
|
591
|
+
if (type && !isDoorType(type))
|
|
592
|
+
defect(id, 'type_mismatch', `${type} is a window type; the door is written hinged.`);
|
|
593
|
+
const style = o.style && !compiled ? o.style : undefined;
|
|
594
|
+
if (style && !isDoorStyle(style))
|
|
595
|
+
defect(id, 'style_mismatch', `${style} is a window style; the door keeps its panel leaf.`);
|
|
596
|
+
const hingesSide = o.hinge === 'end' ? 'right' : 'left';
|
|
597
|
+
const handleSide = hingesSide === 'right' ? 'left' : 'right';
|
|
598
|
+
if (o.hinge)
|
|
599
|
+
say(`door ${id}: handle set opposite the hinge (${handleSide})`);
|
|
600
|
+
opening = DoorNode.parse({
|
|
601
|
+
...common,
|
|
602
|
+
type: 'door',
|
|
603
|
+
position: [x, height / 2, 0],
|
|
604
|
+
...(type && isDoorType(type) ? doorTypeFields(type) : {}),
|
|
605
|
+
...(style && isDoorStyle(style) ? doorStyleLook(style) : {}),
|
|
606
|
+
...(o.leaves ? { leafCount: o.leaves } : {}),
|
|
607
|
+
hingesSide,
|
|
608
|
+
handleSide,
|
|
609
|
+
...(o.swing ? { swingDirection: o.swing === 'back' ? 'outward' : 'inward' } : {}),
|
|
610
|
+
});
|
|
611
|
+
report.doors++;
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
const type = o.type;
|
|
615
|
+
if (type && !isWindowType(type))
|
|
616
|
+
defect(id, 'type_mismatch', `${type} is a door type; the window is written fixed.`);
|
|
617
|
+
const windowType = type && isWindowType(type) ? type : undefined;
|
|
618
|
+
if (!windowType && !compiled)
|
|
619
|
+
untypedWindows++;
|
|
620
|
+
const style = o.style && !compiled ? o.style : undefined;
|
|
621
|
+
if (style && !isWindowStyle(style))
|
|
622
|
+
defect(id, 'style_mismatch', `${style} is a door style; the window keeps a single pane.`);
|
|
623
|
+
const takesStyle = windowTakesStyle(windowType ?? 'fixed');
|
|
624
|
+
if (style && isWindowStyle(style) && !takesStyle)
|
|
625
|
+
say(`window ${id}: style ${style} dropped, a ${windowType} window draws its own sashes`);
|
|
626
|
+
opening = WindowNode.parse({
|
|
627
|
+
...common,
|
|
628
|
+
type: 'window',
|
|
629
|
+
position: [x, o.sill + height / 2, 0],
|
|
630
|
+
...(windowType ? windowTypeFields(windowType) : {}),
|
|
631
|
+
...(style && isWindowStyle(style) && takesStyle ? getWindowStyleOverrides(style) : {}),
|
|
632
|
+
});
|
|
633
|
+
report.windows++;
|
|
634
|
+
}
|
|
635
|
+
const panel = o.kind === 'door' ? finishRef(o.color, id) : undefined;
|
|
636
|
+
const frame = finishRef(o.frameColor ?? o.color, id);
|
|
637
|
+
if (panel || frame)
|
|
638
|
+
opening = {
|
|
639
|
+
...opening,
|
|
640
|
+
slots: {
|
|
641
|
+
...('slots' in opening ? opening.slots : {}),
|
|
642
|
+
...(panel ? { panel } : {}),
|
|
643
|
+
...(frame ? { frame } : {}),
|
|
644
|
+
},
|
|
645
|
+
};
|
|
646
|
+
draft[opening.id] = opening;
|
|
647
|
+
report.ids[id] = opening.id;
|
|
648
|
+
node.children.push(opening.id);
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
// ---------- slabs and columns ----------
|
|
652
|
+
const slabs = level.slabs ?? [];
|
|
653
|
+
if (slabs.length > MANY_SLABS)
|
|
654
|
+
warn(`level/${index}`, 'many_slabs', `${slabs.length} slabs on "${level.name}": Pascal builds floor plates, caps and ceilings itself; a slab is a terrace, a platform, a balcony.`);
|
|
655
|
+
slabs.forEach((s, i) => {
|
|
656
|
+
const id = `slab/${index}/${i}`;
|
|
657
|
+
const label = s.name ? `"${s.name}"` : `slab ${i}`;
|
|
658
|
+
const polygon = s.polygon;
|
|
659
|
+
// A slab over a wall's footprint, higher than half the wall: a cap, which would lift the
|
|
660
|
+
// wall onto it. Pascal caps its walls itself.
|
|
661
|
+
const lifted = [...wallNodes.values()].find((w) => s.top > w.spec.height / 2 &&
|
|
662
|
+
polygonsOverlap(polygon, wallFootprint({ ...w, thickness: w.spec.thickness })));
|
|
663
|
+
if (lifted) {
|
|
664
|
+
defect(id, 'slab_over_wall', `${label} overlaps wall ${lifted.spec.id} with its top at ${metres(s.top)}, above half the wall's ${metres(lifted.spec.height)}: it would lift the wall onto it. Pascal builds a wall's cap itself; fold it into the wall.`);
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
if (s.thickness < THIN_SLAB)
|
|
668
|
+
warn(id, 'thin_slab', `${label} is ${(s.thickness * 1000).toFixed(0)} mm thick: a slab is a terrace, a platform, a balcony; a finish goes on the room's floor.`);
|
|
669
|
+
const finish = finishRef(s.finish, id);
|
|
670
|
+
const node = SlabNode.parse({
|
|
671
|
+
object: 'node',
|
|
672
|
+
type: 'slab',
|
|
673
|
+
id: mint('slab', id),
|
|
674
|
+
parentId: levelNode.id,
|
|
675
|
+
visible: true,
|
|
676
|
+
metadata: { authorScene: { finish: s.finish ?? null } },
|
|
677
|
+
...(s.name ? { name: s.name } : {}),
|
|
678
|
+
polygon: s.polygon,
|
|
679
|
+
elevation: s.top,
|
|
680
|
+
thickness: s.thickness,
|
|
681
|
+
...(finish ? { slots: { surface: finish } } : {}),
|
|
682
|
+
...(s.railing?.length
|
|
683
|
+
? { railing: s.railing.map((r) => ({ start: r.start, end: r.end })) }
|
|
684
|
+
: {}),
|
|
685
|
+
});
|
|
686
|
+
place(node);
|
|
687
|
+
report.ids[id] = node.id;
|
|
688
|
+
report.slabs++;
|
|
689
|
+
});
|
|
690
|
+
(level.columns ?? []).forEach((c, i) => {
|
|
691
|
+
const node = ColumnNode.parse({
|
|
692
|
+
object: 'node',
|
|
693
|
+
type: 'column',
|
|
694
|
+
id: mint('column', `column/${index}/${i}`),
|
|
695
|
+
parentId: levelNode.id,
|
|
696
|
+
visible: true,
|
|
697
|
+
metadata: { authorScene: { color: c.color ?? null } },
|
|
698
|
+
...(c.name ? { name: c.name } : {}),
|
|
699
|
+
position: [c.position[0], 0, c.position[1]],
|
|
700
|
+
crossSection: 'square',
|
|
701
|
+
width: c.width,
|
|
702
|
+
depth: c.depth,
|
|
703
|
+
height: c.height,
|
|
704
|
+
baseHeight: 0,
|
|
705
|
+
capitalHeight: 0,
|
|
706
|
+
});
|
|
707
|
+
place(node);
|
|
708
|
+
report.ids[`column/${index}/${i}`] = node.id;
|
|
709
|
+
report.columns++;
|
|
710
|
+
});
|
|
711
|
+
// ---------- items, hosts first ----------
|
|
712
|
+
const pending = [...(level.items ?? [])];
|
|
713
|
+
let progress = true;
|
|
714
|
+
while (pending.length && progress) {
|
|
715
|
+
progress = false;
|
|
716
|
+
for (const item of [...pending]) {
|
|
717
|
+
const hostItemId = item.host ? itemNodeIds.get(item.host) : undefined;
|
|
718
|
+
const hostWall = item.host && !hostItemId ? wallNodes.get(item.host) : undefined;
|
|
719
|
+
if (item.host && !hostItemId && !hostWall)
|
|
720
|
+
continue;
|
|
721
|
+
pending.splice(pending.indexOf(item), 1);
|
|
722
|
+
progress = true;
|
|
723
|
+
const compiled = input.compiled[item.id];
|
|
724
|
+
if (!compiled) {
|
|
725
|
+
defect(item.id, 'compile_failed', input.compileErrors?.[item.id] ?? 'The module did not compile.');
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
const world = [item.position[0], item.position[1], item.position[2]];
|
|
729
|
+
const yaw = (item.rotation * Math.PI) / 180;
|
|
730
|
+
let placed;
|
|
731
|
+
if (hostWall) {
|
|
732
|
+
// On the wall as place_items puts a wall-side item there: along it from its start, the
|
|
733
|
+
// payload's height for its bottom, on the face nearest the point, facing the room.
|
|
734
|
+
const [width, height] = scriptedSize(compiled.manifest);
|
|
735
|
+
const wallHeight = hostWall.spec.height;
|
|
736
|
+
if (height > wallHeight) {
|
|
737
|
+
defect(item.id, 'item_too_tall', `"${item.name}" is ${metres(height)} tall; wall ${item.host} is ${metres(wallHeight)}.`);
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
const length = dist(hostWall.start, hostWall.end);
|
|
741
|
+
const along = projectWorldPointToWallLocalX(hostWall, world);
|
|
742
|
+
const x = Math.max(width / 2, Math.min(length - width / 2, along));
|
|
743
|
+
const y = Math.max(0, Math.min(wallHeight - height, world[1]));
|
|
744
|
+
const [dx, dz] = [
|
|
745
|
+
hostWall.end[0] - hostWall.start[0],
|
|
746
|
+
hostWall.end[1] - hostWall.start[1],
|
|
747
|
+
];
|
|
748
|
+
// The wall's left (its local +z) is its front.
|
|
749
|
+
const localZ = (-dz * (world[0] - hostWall.start[0]) + dx * (world[2] - hostWall.start[1])) / length;
|
|
750
|
+
const left = localZ >= 0;
|
|
751
|
+
const faceZ = getWallLocalFaceZ(hostWall.node, left ? 'a' : 'b');
|
|
752
|
+
const offset = (localZ - faceZ) * (left ? 1 : -1);
|
|
753
|
+
const z = faceZ + (left ? 1 : -1) * Math.max(0, offset);
|
|
754
|
+
if (offset < -1e-9)
|
|
755
|
+
say(`${item.id}: point inside wall ${item.host}, moved to its nearest face`);
|
|
756
|
+
if (item.rotation)
|
|
757
|
+
say(`${item.id}: rotation ignored on wall ${item.host}, it faces the room`);
|
|
758
|
+
const [ux, uz] = [dx / length, dz / length];
|
|
759
|
+
placed = {
|
|
760
|
+
compiled: { ...compiled, mount: 'wall-side' },
|
|
761
|
+
parentId: hostWall.node.id,
|
|
762
|
+
position: [x, y, z],
|
|
763
|
+
rotation: left ? 0 : 180,
|
|
764
|
+
side: left ? 'front' : 'back',
|
|
765
|
+
wallT: x / length,
|
|
766
|
+
frame: {
|
|
767
|
+
position: [
|
|
768
|
+
hostWall.start[0] + ux * x - uz * z,
|
|
769
|
+
y,
|
|
770
|
+
hostWall.start[1] + uz * x + ux * z,
|
|
771
|
+
],
|
|
772
|
+
yaw: -Math.atan2(dz, dx) + (left ? 0 : Math.PI),
|
|
773
|
+
},
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
const host = hostItemId ? itemFrames.get(item.host) : undefined;
|
|
778
|
+
placed = {
|
|
779
|
+
compiled,
|
|
780
|
+
parentId: hostItemId ?? levelNode.id,
|
|
781
|
+
position: host ? toLocal(host, world) : world,
|
|
782
|
+
rotation: host ? item.rotation - (host.yaw * 180) / Math.PI : item.rotation,
|
|
783
|
+
frame: { position: world, yaw },
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
try {
|
|
787
|
+
const outcome = addObject(draft, {
|
|
788
|
+
compiled: { ...placed.compiled, nodeId: mint('item', item.id) },
|
|
789
|
+
name: item.name,
|
|
790
|
+
category: item.category,
|
|
791
|
+
reason: `author_scene: ${item.name}`,
|
|
792
|
+
position: placed.position,
|
|
793
|
+
rotation: placed.rotation,
|
|
794
|
+
parentId: placed.parentId,
|
|
795
|
+
...(placed.side ? { side: placed.side } : {}),
|
|
796
|
+
}, { ...context, activeLevelId: levelNode.id });
|
|
797
|
+
for (const { node, parentId } of outcome.changes?.create ?? []) {
|
|
798
|
+
draft[node.id] = {
|
|
799
|
+
...node,
|
|
800
|
+
slots: exactSlots(compiled, item.id),
|
|
801
|
+
...(placed.wallT === undefined ? {} : { wallT: placed.wallT }),
|
|
802
|
+
};
|
|
803
|
+
const parent = draft[parentId ?? levelNode.id];
|
|
804
|
+
parent.children = [...(parent.children ?? []), node.id];
|
|
805
|
+
itemNodeIds.set(item.id, node.id);
|
|
806
|
+
itemFrames.set(item.id, placed.frame);
|
|
807
|
+
report.ids[item.id] = node.id;
|
|
808
|
+
report.items++;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
catch (error) {
|
|
812
|
+
const e = error;
|
|
813
|
+
defect(item.id, e.code ?? 'item_refused', e.message ?? String(error));
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
for (const item of pending)
|
|
818
|
+
defect(item.id, 'host_missing', `Its host ${item.host} was not placed.`);
|
|
819
|
+
// ---------- wall paint, through the editor's paint: both faces, or each its own ----------
|
|
820
|
+
for (const w of walls) {
|
|
821
|
+
const node = wallNodes.get(w.spec.id)?.node;
|
|
822
|
+
if (!node)
|
|
823
|
+
continue;
|
|
824
|
+
const faces = {
|
|
825
|
+
a: w.spec.colorLeft ?? w.spec.color,
|
|
826
|
+
b: w.spec.colorRight ?? w.spec.color,
|
|
827
|
+
};
|
|
828
|
+
const coats = [];
|
|
829
|
+
if (faces.a && faces.a === faces.b) {
|
|
830
|
+
const ref = finishRef(faces.a, w.spec.id);
|
|
831
|
+
if (ref)
|
|
832
|
+
coats.push({ material: ref });
|
|
833
|
+
}
|
|
834
|
+
else
|
|
835
|
+
for (const face of ['a', 'b']) {
|
|
836
|
+
const ref = finishRef(faces[face], w.spec.id);
|
|
837
|
+
if (ref)
|
|
838
|
+
coats.push({ role: face, material: ref });
|
|
839
|
+
}
|
|
840
|
+
for (const coat of coats) {
|
|
841
|
+
try {
|
|
842
|
+
const { changes } = paint(draft, { targets: [node.id], ...coat }, paintContext(levelNode.id));
|
|
843
|
+
for (const u of changes?.update ?? [])
|
|
844
|
+
draft[u.id] = { ...draft[u.id], ...u.data };
|
|
845
|
+
}
|
|
846
|
+
catch (error) {
|
|
847
|
+
defect(w.spec.id, 'paint_refused', error.message);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
});
|
|
852
|
+
report.levels = levelNodes.length;
|
|
853
|
+
if (untypedWindows)
|
|
854
|
+
say(`${untypedWindows} window${untypedWindows === 1 ? ' has' : 's have'} no type: written fixed (cannot open); give type`);
|
|
855
|
+
// ---------- which face of each wall looks into a room: read from the plan, as the editor does ----------
|
|
856
|
+
for (const levelNode of levelNodes) {
|
|
857
|
+
const boundaries = Object.values(draft).filter((n) => n.parentId === levelNode.id && (n.type === 'wall' || n.type === 'separator'));
|
|
858
|
+
for (const { wallId, ...sides } of detectSpacesForLevel(levelNode.id, boundaries).wallUpdates)
|
|
859
|
+
draft[wallId] = { ...draft[wallId], ...sides };
|
|
860
|
+
}
|
|
861
|
+
// ---------- rooms: Pascal's own derivation, then the payload's names and floors ----------
|
|
862
|
+
const { nodes: withZones, createdZoneIds } = migrateRoomZones(draft);
|
|
863
|
+
const zones = createdZoneIds.map((id) => ZoneNode.parse(withZones[id]));
|
|
864
|
+
for (const zone of zones) {
|
|
865
|
+
draft[zone.id] = zone;
|
|
866
|
+
const level = draft[zone.parentId];
|
|
867
|
+
draft[zone.parentId] = { ...level, children: [...level.children, zone.id] };
|
|
868
|
+
report.rooms++;
|
|
869
|
+
}
|
|
870
|
+
const claimed = new Map();
|
|
871
|
+
payload.levels.forEach((level, index) => {
|
|
872
|
+
const levelNode = levelNodes[index];
|
|
873
|
+
for (const [i, room] of level.rooms.entries()) {
|
|
874
|
+
const id = `room/${index}/${i}`;
|
|
875
|
+
const zone = zones.find((z) => z.parentId === levelNode.id && pointInPolygon(room.seed, z.polygon));
|
|
876
|
+
// Two seeds in one enclosure: the walls do not separate the rooms the payload names.
|
|
877
|
+
if (zone && claimed.has(zone.id)) {
|
|
878
|
+
defect(id, 'room_shares_enclosure', `"${room.name}" and "${claimed.get(zone.id)}" are one enclosure: no wall separates them.`);
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
if (!zone) {
|
|
882
|
+
defect(id, 'room_not_enclosed', `No closed room around (${room.seed[0]}, ${room.seed[1]}) "${room.name}": its walls do not meet.`);
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
if (room.floorRegions.length > MANY_REGIONS)
|
|
886
|
+
warn(id, 'many_regions', `"${room.name}" has ${room.floorRegions.length} floor regions: regions are fixed polygons that do not follow a resize; use one floor finish.`);
|
|
887
|
+
const finish = finishRef(room.floor, id);
|
|
888
|
+
const regions = room.floorRegions.map((r, k) => ({
|
|
889
|
+
id: `region_${k}`,
|
|
890
|
+
polygon: r.polygon,
|
|
891
|
+
finish: finishRef(r.finish, id) ?? r.finish,
|
|
892
|
+
}));
|
|
893
|
+
draft[zone.id] = ZoneNode.parse({
|
|
894
|
+
...zone,
|
|
895
|
+
name: room.name,
|
|
896
|
+
spaceRole: 'room',
|
|
897
|
+
...(finish || regions.length
|
|
898
|
+
? {
|
|
899
|
+
floor: {
|
|
900
|
+
...zone.floor,
|
|
901
|
+
...(finish ? { finish } : {}),
|
|
902
|
+
...(regions.length ? { regions } : {}),
|
|
903
|
+
},
|
|
904
|
+
}
|
|
905
|
+
: {}),
|
|
906
|
+
metadata: { ...zone.metadata, authorScene: { seed: room.seed } },
|
|
907
|
+
});
|
|
908
|
+
claimed.set(zone.id, room.name);
|
|
909
|
+
report.ids[id] = zone.id;
|
|
910
|
+
report.roomsNamed++;
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
// ---------- floors and ceilings, as the editor derives them on load ----------
|
|
914
|
+
const structure = reconcileSceneStructure({
|
|
915
|
+
nodes: draft,
|
|
916
|
+
levelIds: levelNodes.map((l) => l.id),
|
|
917
|
+
mintId: (kind) => mint(kind),
|
|
918
|
+
});
|
|
919
|
+
const written = { ...structure.nodes };
|
|
920
|
+
// ---------- skirting, native on each wall, along the faces its rooms stand on ----------
|
|
921
|
+
for (const { id, nodeId, levelId, skirting } of skirtings) {
|
|
922
|
+
const finish = finishRef(skirting.color, id);
|
|
923
|
+
try {
|
|
924
|
+
const { changes } = setWallSkirting(written, {
|
|
925
|
+
wallIds: [nodeId],
|
|
926
|
+
height: skirting.height,
|
|
927
|
+
depth: skirting.depth,
|
|
928
|
+
...(finish ? { finish } : {}),
|
|
929
|
+
}, paintContext(levelId));
|
|
930
|
+
for (const u of changes?.update ?? [])
|
|
931
|
+
written[u.id] = { ...written[u.id], ...u.data };
|
|
932
|
+
}
|
|
933
|
+
catch (error) {
|
|
934
|
+
const e = error;
|
|
935
|
+
defect(id, 'skirting_refused', e.code === 'side_unknown'
|
|
936
|
+
? `No room stands on either face of wall ${id}: its skirting was not written.`
|
|
937
|
+
: `Wall ${id}: ${e.message ?? String(error)}`);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
// ---------- face modules: which faces they build on is known now; the host compiles them ----------
|
|
941
|
+
const faces = resolveFaceScripts(payload, report.ids, written);
|
|
942
|
+
report.defects.push(...faces.defects);
|
|
943
|
+
report.warnings.push(...faces.warnings);
|
|
944
|
+
// Ceilings exist only after structure reconciliation; lights can now use their room's host.
|
|
945
|
+
payload.levels.forEach((level, index) => {
|
|
946
|
+
const levelNode = levelNodes[index];
|
|
947
|
+
for (const [i, light] of level.lights.entries()) {
|
|
948
|
+
const id = `light/${index}/${i}`;
|
|
949
|
+
const at = [light.position[0], light.position[1], light.position[2]];
|
|
950
|
+
let hostId = light.fixture ? itemNodeIds.get(light.fixture) : undefined;
|
|
951
|
+
let hostFrame = light.fixture ? itemFrames.get(light.fixture) : undefined;
|
|
952
|
+
const room = !light.fixture
|
|
953
|
+
? Object.values(written).find((node) => node.type === 'zone' &&
|
|
954
|
+
node.spaceRole === 'room' &&
|
|
955
|
+
node.parentId === levelNode.id &&
|
|
956
|
+
pointInPolygon([at[0], at[2]], node.polygon) &&
|
|
957
|
+
!node.holes.some((hole) => pointInPolygon([at[0], at[2]], hole)))
|
|
958
|
+
: undefined;
|
|
959
|
+
const ceiling = room
|
|
960
|
+
? Object.values(written).find((node) => node.type === 'ceiling' && node.zoneId === room.id && node.parentId === levelNode.id)
|
|
961
|
+
: undefined;
|
|
962
|
+
if (ceiling) {
|
|
963
|
+
const compiled = input.compiled[id];
|
|
964
|
+
if (!compiled) {
|
|
965
|
+
defect(id, 'compile_failed', input.compileErrors?.[id] ?? 'The ceiling point module did not compile.');
|
|
966
|
+
continue;
|
|
967
|
+
}
|
|
968
|
+
try {
|
|
969
|
+
const outcome = addObject(written, {
|
|
970
|
+
compiled: { ...compiled, nodeId: mint('item', id) },
|
|
971
|
+
name: `Ceiling point in ${room.name}`,
|
|
972
|
+
category: 'light',
|
|
973
|
+
reason: 'author_scene: ceiling point for a light without a fixture',
|
|
974
|
+
parentId: ceiling.id,
|
|
975
|
+
position: [at[0], 0, at[2]],
|
|
976
|
+
rotation: 0,
|
|
977
|
+
}, { ...context, activeLevelId: levelNode.id });
|
|
978
|
+
const node = outcome.changes.create[0].node;
|
|
979
|
+
written[node.id] = { ...node, slots: exactSlots(compiled, id) };
|
|
980
|
+
written[ceiling.id] = { ...ceiling, children: [...ceiling.children, node.id] };
|
|
981
|
+
hostId = node.id;
|
|
982
|
+
hostFrame = {
|
|
983
|
+
position: [at[0], resolveCeilingHeight(ceiling, written) - CEILING_DRAW_OFFSET, at[2]],
|
|
984
|
+
yaw: 0,
|
|
985
|
+
};
|
|
986
|
+
report.ids[id] = node.id;
|
|
987
|
+
report.items++;
|
|
988
|
+
say(`light at [${at.join(', ')}] has no fixture: a ceiling point in ${room.name}`);
|
|
989
|
+
}
|
|
990
|
+
catch (error) {
|
|
991
|
+
const e = error;
|
|
992
|
+
defect(id, e.code ?? 'item_refused', e.message ?? String(error));
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
if (!hostId) {
|
|
997
|
+
let best = null;
|
|
998
|
+
for (const item of level.items ?? []) {
|
|
999
|
+
const frame = itemFrames.get(item.id);
|
|
1000
|
+
if (!frame)
|
|
1001
|
+
continue;
|
|
1002
|
+
const d = Math.hypot(frame.position[0] - at[0], frame.position[2] - at[2]);
|
|
1003
|
+
if (!best || d < best.d)
|
|
1004
|
+
best = { key: item.id, d };
|
|
1005
|
+
}
|
|
1006
|
+
if (!best) {
|
|
1007
|
+
defect(id, 'light_unhosted', 'No item on this level to hold the light; Pascal keeps lights inside objects.');
|
|
1008
|
+
continue;
|
|
1009
|
+
}
|
|
1010
|
+
hostId = itemNodeIds.get(best.key);
|
|
1011
|
+
hostFrame = itemFrames.get(best.key);
|
|
1012
|
+
say(`light at [${at.join(', ')}] has no fixture: ${!light.fixture ? 'no room contains its point; ' : ''}hosted on the nearest item ${best.key} (${best.d.toFixed(2)} m away); moving that item moves the light`);
|
|
1013
|
+
}
|
|
1014
|
+
const hostNode = written[hostId];
|
|
1015
|
+
const interactive = hostNode.asset.interactive ?? { controls: [], effects: [] };
|
|
1016
|
+
const controls = interactive.controls.some((c) => c.kind === 'toggle')
|
|
1017
|
+
? interactive.controls
|
|
1018
|
+
: [...interactive.controls, { kind: 'toggle', label: 'Lights', default: true }];
|
|
1019
|
+
const effects = [
|
|
1020
|
+
...interactive.effects,
|
|
1021
|
+
{
|
|
1022
|
+
kind: 'light',
|
|
1023
|
+
color: light.color,
|
|
1024
|
+
intensityRange: [0, light.intensity],
|
|
1025
|
+
offset: toLocal(hostFrame, at),
|
|
1026
|
+
},
|
|
1027
|
+
];
|
|
1028
|
+
written[hostNode.id] = {
|
|
1029
|
+
...hostNode,
|
|
1030
|
+
asset: { ...hostNode.asset, interactive: { controls, effects } },
|
|
1031
|
+
};
|
|
1032
|
+
report.lights++;
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
const nodes = Object.fromEntries(Object.entries(written).filter(([id]) => !scaffoldIds.has(id)));
|
|
1036
|
+
const candidate = {
|
|
1037
|
+
version: 1,
|
|
1038
|
+
buildingId: building.id,
|
|
1039
|
+
seed,
|
|
1040
|
+
ids: report.ids,
|
|
1041
|
+
nodes,
|
|
1042
|
+
};
|
|
1043
|
+
const outcome = {
|
|
1044
|
+
result: report,
|
|
1045
|
+
candidate,
|
|
1046
|
+
buildingId: building.id,
|
|
1047
|
+
changes: finishes.created.length ? { materials: finishes.created } : {},
|
|
1048
|
+
};
|
|
1049
|
+
return input.prepareOnly ? outcome : finalizeAuthorScene(scene, outcome);
|
|
1050
|
+
}
|
|
1051
|
+
/** Commit the complete candidate after the host has compiled all of its finishes. */
|
|
1052
|
+
export function finalizeAuthorScene(scene, outcome) {
|
|
1053
|
+
const building = scene[outcome.buildingId];
|
|
1054
|
+
if (building?.type !== 'building')
|
|
1055
|
+
refuse('no_building', 'The target building no longer exists.');
|
|
1056
|
+
const previous = building.metadata?.authorSceneState;
|
|
1057
|
+
const base = previous?.nodes ??
|
|
1058
|
+
Object.fromEntries(Object.values(scene)
|
|
1059
|
+
.filter((node) => node.type === 'level' && node.parentId === building.id)
|
|
1060
|
+
.map((node) => [node.id, node]));
|
|
1061
|
+
const changes = authoredSceneChanges(scene, base, outcome.candidate.nodes);
|
|
1062
|
+
return {
|
|
1063
|
+
...outcome,
|
|
1064
|
+
changes: {
|
|
1065
|
+
...changes,
|
|
1066
|
+
...(outcome.changes?.materials ? { materials: outcome.changes.materials } : {}),
|
|
1067
|
+
update: [
|
|
1068
|
+
...(changes.update ?? []),
|
|
1069
|
+
{
|
|
1070
|
+
id: building.id,
|
|
1071
|
+
data: { metadata: { ...building.metadata, authorSceneState: outcome.candidate } },
|
|
1072
|
+
},
|
|
1073
|
+
],
|
|
1074
|
+
},
|
|
1075
|
+
};
|
|
1076
|
+
}
|