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