@pascal-app/nodes 0.1.1 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/building/definition.js +1 -1
- package/dist/cabinet/definition.d.ts.map +1 -1
- package/dist/cabinet/definition.js +809 -72
- package/dist/cabinet/geometry.d.ts.map +1 -1
- package/dist/cabinet/geometry.js +4 -0
- package/dist/cabinet/move-frame.js +3 -3
- package/dist/cabinet/panel.d.ts.map +1 -1
- package/dist/cabinet/panel.js +1 -0
- package/dist/cabinet/placement-snap.d.ts +8 -0
- package/dist/cabinet/placement-snap.d.ts.map +1 -0
- package/dist/cabinet/placement-snap.js +19 -0
- package/dist/cabinet/presets.js +8 -8
- package/dist/cabinet/quick-actions.d.ts.map +1 -1
- package/dist/cabinet/quick-actions.js +9 -3
- package/dist/cabinet/resize-limits.d.ts +11 -0
- package/dist/cabinet/resize-limits.d.ts.map +1 -0
- package/dist/cabinet/resize-limits.js +22 -0
- package/dist/cabinet/run-layout.d.ts +8 -2
- package/dist/cabinet/run-layout.d.ts.map +1 -1
- package/dist/cabinet/run-layout.js +59 -7
- package/dist/cabinet/run-ops.d.ts +44 -3
- package/dist/cabinet/run-ops.d.ts.map +1 -1
- package/dist/cabinet/run-ops.js +646 -110
- package/dist/cabinet/run-panel.d.ts +2 -1
- package/dist/cabinet/run-panel.d.ts.map +1 -1
- package/dist/cabinet/run-panel.js +38 -4
- package/dist/cabinet/stack-transitions.js +4 -4
- package/dist/cabinet/tool.d.ts.map +1 -1
- package/dist/cabinet/tool.js +95 -17
- package/dist/cabinet/wall-snap.d.ts.map +1 -1
- package/dist/cabinet/wall-snap.js +2 -6
- package/dist/ceiling/boundary-editor.d.ts.map +1 -1
- package/dist/ceiling/boundary-editor.js +2 -2
- package/dist/ceiling/definition.d.ts +1 -1
- package/dist/ceiling/definition.d.ts.map +1 -1
- package/dist/ceiling/definition.js +36 -5
- package/dist/ceiling/floorplan-affordances.d.ts +4 -4
- package/dist/ceiling/floorplan-move.d.ts +4 -4
- package/dist/ceiling/floorplan-move.d.ts.map +1 -1
- package/dist/ceiling/floorplan-move.js +5 -4
- package/dist/ceiling/hole-editor.d.ts.map +1 -1
- package/dist/ceiling/hole-editor.js +2 -2
- package/dist/ceiling/move-tool.d.ts.map +1 -1
- package/dist/ceiling/move-tool.js +4 -3
- package/dist/ceiling/panel.d.ts.map +1 -1
- package/dist/ceiling/panel.js +65 -3
- package/dist/ceiling/renderer.d.ts.map +1 -1
- package/dist/ceiling/renderer.js +6 -2
- package/dist/ceiling/tool.d.ts.map +1 -1
- package/dist/ceiling/tool.js +12 -1
- package/dist/chimney/definition.d.ts.map +1 -1
- package/dist/chimney/definition.js +1 -0
- package/dist/chimney/tool.d.ts.map +1 -1
- package/dist/chimney/tool.js +16 -1
- package/dist/column/definition.d.ts.map +1 -1
- package/dist/column/definition.js +14 -2
- package/dist/column/floorplan-affordances.d.ts.map +1 -1
- package/dist/column/floorplan-affordances.js +19 -14
- package/dist/column/floorplan-move.d.ts.map +1 -1
- package/dist/column/floorplan-move.js +7 -2
- package/dist/column/floorplan.d.ts +9 -1
- package/dist/column/floorplan.d.ts.map +1 -1
- package/dist/column/floorplan.js +59 -4
- package/dist/column/tool.d.ts.map +1 -1
- package/dist/column/tool.js +33 -7
- package/dist/construction-dimension/definition.d.ts +4 -0
- package/dist/construction-dimension/definition.d.ts.map +1 -0
- package/dist/construction-dimension/definition.js +83 -0
- package/dist/construction-dimension/drawing-coordination.d.ts +7 -0
- package/dist/construction-dimension/drawing-coordination.d.ts.map +1 -0
- package/dist/construction-dimension/drawing-coordination.js +54 -0
- package/dist/construction-dimension/floorplan-affordances.d.ts +4 -0
- package/dist/construction-dimension/floorplan-affordances.d.ts.map +1 -0
- package/dist/construction-dimension/floorplan-affordances.js +114 -0
- package/dist/construction-dimension/floorplan-tool.d.ts +21 -0
- package/dist/construction-dimension/floorplan-tool.d.ts.map +1 -0
- package/dist/construction-dimension/floorplan-tool.js +557 -0
- package/dist/construction-dimension/floorplan.d.ts +3 -0
- package/dist/construction-dimension/floorplan.d.ts.map +1 -0
- package/dist/construction-dimension/floorplan.js +457 -0
- package/dist/construction-dimension/geometry.d.ts +31 -0
- package/dist/construction-dimension/geometry.d.ts.map +1 -0
- package/dist/construction-dimension/geometry.js +144 -0
- package/dist/construction-dimension/index.d.ts +4 -0
- package/dist/construction-dimension/index.d.ts.map +1 -0
- package/dist/construction-dimension/index.js +3 -0
- package/dist/construction-dimension/panel.d.ts +2 -0
- package/dist/construction-dimension/panel.d.ts.map +1 -0
- package/dist/construction-dimension/panel.js +128 -0
- package/dist/construction-dimension/parametrics.d.ts +3 -0
- package/dist/construction-dimension/parametrics.d.ts.map +1 -0
- package/dist/construction-dimension/parametrics.js +4 -0
- package/dist/construction-dimension/schema.d.ts +2 -0
- package/dist/construction-dimension/schema.d.ts.map +1 -0
- package/dist/construction-dimension/schema.js +1 -0
- package/dist/door/contextual-dimensions.d.ts +3 -0
- package/dist/door/contextual-dimensions.d.ts.map +1 -0
- package/dist/door/contextual-dimensions.js +7 -0
- package/dist/door/definition.d.ts.map +1 -1
- package/dist/door/definition.js +13 -8
- package/dist/door/floorplan-affordances.d.ts +2 -5
- package/dist/door/floorplan-affordances.d.ts.map +1 -1
- package/dist/door/floorplan-affordances.js +9 -18
- package/dist/door/floorplan.d.ts +3 -4
- package/dist/door/floorplan.d.ts.map +1 -1
- package/dist/door/floorplan.js +88 -6
- package/dist/door/move-tool.d.ts.map +1 -1
- package/dist/door/move-tool.js +2 -2
- package/dist/door/panel.d.ts.map +1 -1
- package/dist/door/panel.js +3 -1
- package/dist/door/schema.d.ts +1 -1
- package/dist/door/schema.d.ts.map +1 -1
- package/dist/door/schema.js +1 -1
- package/dist/door/tool.d.ts.map +1 -1
- package/dist/door/tool.js +63 -6
- package/dist/dormer/definition.d.ts.map +1 -1
- package/dist/dormer/definition.js +1 -0
- package/dist/dormer/tool.d.ts.map +1 -1
- package/dist/dormer/tool.js +23 -1
- package/dist/duct-segment/tool.d.ts.map +1 -1
- package/dist/duct-segment/tool.js +20 -9
- package/dist/duct-terminal/tool.d.ts.map +1 -1
- package/dist/duct-terminal/tool.js +9 -6
- package/dist/elevator/floorplan-affordances.d.ts +2 -6
- package/dist/elevator/floorplan-affordances.d.ts.map +1 -1
- package/dist/elevator/floorplan-affordances.js +13 -12
- package/dist/fence/actions/move-endpoint.d.ts.map +1 -1
- package/dist/fence/actions/move-endpoint.js +29 -1
- package/dist/fence/definition.d.ts.map +1 -1
- package/dist/fence/definition.js +74 -14
- package/dist/fence/floorplan-affordances.d.ts.map +1 -1
- package/dist/fence/floorplan-affordances.js +48 -11
- package/dist/fence/floorplan-move.d.ts.map +1 -1
- package/dist/fence/floorplan-move.js +38 -3
- package/dist/fence/geometry.d.ts.map +1 -1
- package/dist/fence/geometry.js +15 -1
- package/dist/fence/lift.d.ts +38 -0
- package/dist/fence/lift.d.ts.map +1 -0
- package/dist/fence/lift.js +51 -0
- package/dist/fence/move-tool.d.ts.map +1 -1
- package/dist/fence/move-tool.js +25 -5
- package/dist/fence/system.d.ts +3 -0
- package/dist/fence/system.d.ts.map +1 -0
- package/dist/fence/system.js +46 -0
- package/dist/fence/tool.d.ts.map +1 -1
- package/dist/fence/tool.js +103 -32
- package/dist/hvac-equipment/tool.d.ts.map +1 -1
- package/dist/hvac-equipment/tool.js +8 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/item/definition.d.ts.map +1 -1
- package/dist/item/definition.js +7 -1
- package/dist/item/floorplan-move.d.ts.map +1 -1
- package/dist/item/floorplan-move.js +50 -43
- package/dist/item/floorplan.d.ts +1 -0
- package/dist/item/floorplan.d.ts.map +1 -1
- package/dist/item/floorplan.js +49 -0
- package/dist/item/renderer.d.ts +3 -0
- package/dist/item/renderer.d.ts.map +1 -1
- package/dist/item/renderer.js +96 -8
- package/dist/level/definition.d.ts.map +1 -1
- package/dist/level/definition.js +7 -3
- package/dist/lineset/tool.d.ts.map +1 -1
- package/dist/lineset/tool.js +5 -1
- package/dist/liquid-line/tool.d.ts.map +1 -1
- package/dist/liquid-line/tool.js +7 -1
- package/dist/measurement/definition.d.ts.map +1 -1
- package/dist/measurement/definition.js +5 -0
- package/dist/measurement/floorplan.d.ts.map +1 -1
- package/dist/measurement/floorplan.js +11 -10
- package/dist/measurement/index.d.ts +1 -1
- package/dist/measurement/index.d.ts.map +1 -1
- package/dist/measurement/index.js +1 -1
- package/dist/measurement/resolve.d.ts +5 -0
- package/dist/measurement/resolve.d.ts.map +1 -1
- package/dist/measurement/resolve.js +2 -2
- package/dist/measurement/surface-query.js +5 -5
- package/dist/measurement/tool.d.ts +6 -1
- package/dist/measurement/tool.d.ts.map +1 -1
- package/dist/measurement/tool.js +7 -11
- package/dist/pipe-segment/tool.d.ts.map +1 -1
- package/dist/pipe-segment/tool.js +22 -19
- package/dist/roof-segment/floorplan-affordances.d.ts.map +1 -1
- package/dist/roof-segment/floorplan-affordances.js +14 -8
- package/dist/shared/construction-dimension-standards.d.ts +34 -0
- package/dist/shared/construction-dimension-standards.d.ts.map +1 -0
- package/dist/shared/construction-dimension-standards.js +18 -0
- package/dist/shared/construction-length.d.ts +10 -0
- package/dist/shared/construction-length.d.ts.map +1 -0
- package/dist/shared/construction-length.js +57 -0
- package/dist/shared/dimension-string.d.ts +20 -0
- package/dist/shared/dimension-string.d.ts.map +1 -0
- package/dist/shared/dimension-string.js +19 -0
- package/dist/shared/draft-axis-guides.d.ts +36 -0
- package/dist/shared/draft-axis-guides.d.ts.map +1 -0
- package/dist/shared/draft-axis-guides.js +107 -0
- package/dist/shared/move-roof-tool.d.ts.map +1 -1
- package/dist/shared/move-roof-tool.js +17 -3
- package/dist/shared/opening-documentation-fields.d.ts +16 -0
- package/dist/shared/opening-documentation-fields.d.ts.map +1 -0
- package/dist/shared/opening-documentation-fields.js +54 -0
- package/dist/shared/opening-documentation.d.ts +47 -0
- package/dist/shared/opening-documentation.d.ts.map +1 -0
- package/dist/shared/opening-documentation.js +300 -0
- package/dist/shared/opening-guides-runtime.d.ts.map +1 -1
- package/dist/shared/opening-guides-runtime.js +3 -2
- package/dist/shared/opening-placement-dimensions.d.ts.map +1 -1
- package/dist/shared/opening-placement-dimensions.js +14 -5
- package/dist/shared/wall-opening-ceiling.d.ts +30 -0
- package/dist/shared/wall-opening-ceiling.d.ts.map +1 -0
- package/dist/shared/wall-opening-ceiling.js +29 -0
- package/dist/shelf/floorplan-affordances.d.ts.map +1 -1
- package/dist/shelf/floorplan-affordances.js +10 -5
- package/dist/shelf/floorplan-move.d.ts +2 -16
- package/dist/shelf/floorplan-move.d.ts.map +1 -1
- package/dist/shelf/floorplan-move.js +19 -40
- package/dist/shelf/tool.d.ts.map +1 -1
- package/dist/shelf/tool.js +8 -3
- package/dist/site/recessed-slab-ground-holes.d.ts.map +1 -1
- package/dist/site/recessed-slab-ground-holes.js +1 -4
- package/dist/site/renderer.d.ts.map +1 -1
- package/dist/site/renderer.js +118 -28
- package/dist/site/terrain-drape.d.ts +91 -0
- package/dist/site/terrain-drape.d.ts.map +1 -0
- package/dist/site/terrain-drape.js +205 -0
- package/dist/site/terrain-geometry.d.ts +131 -0
- package/dist/site/terrain-geometry.d.ts.map +1 -0
- package/dist/site/terrain-geometry.js +259 -0
- package/dist/site/terrain-mesh.d.ts +49 -0
- package/dist/site/terrain-mesh.d.ts.map +1 -0
- package/dist/site/terrain-mesh.js +122 -0
- package/dist/site/terrain-renderer.d.ts +28 -0
- package/dist/site/terrain-renderer.d.ts.map +1 -0
- package/dist/site/terrain-renderer.js +69 -0
- package/dist/skylight/definition.d.ts.map +1 -1
- package/dist/skylight/definition.js +1 -0
- package/dist/skylight/tool.d.ts.map +1 -1
- package/dist/skylight/tool.js +16 -1
- package/dist/slab/definition.d.ts.map +1 -1
- package/dist/slab/definition.js +87 -10
- package/dist/slab/elevation-limit.d.ts +43 -0
- package/dist/slab/elevation-limit.d.ts.map +1 -0
- package/dist/slab/elevation-limit.js +124 -0
- package/dist/slab/floorplan-affordances.d.ts +16 -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 +98 -5
- package/dist/slab/panel.d.ts.map +1 -1
- package/dist/slab/panel.js +82 -4
- package/dist/slab/parametrics.d.ts +1 -1
- package/dist/slab/parametrics.d.ts.map +1 -1
- package/dist/slab/parametrics.js +13 -1
- package/dist/slab/placement-ownership.d.ts +3 -0
- package/dist/slab/placement-ownership.d.ts.map +1 -0
- package/dist/slab/placement-ownership.js +3 -0
- package/dist/slab/quick-measurement.d.ts.map +1 -1
- package/dist/slab/quick-measurement.js +3 -2
- package/dist/slab/system.d.ts.map +1 -1
- package/dist/slab/system.js +14 -4
- package/dist/slab/tool.d.ts.map +1 -1
- package/dist/slab/tool.js +81 -23
- package/dist/solar-panel/definition.d.ts.map +1 -1
- package/dist/solar-panel/definition.js +1 -0
- package/dist/solar-panel/tool.d.ts.map +1 -1
- package/dist/solar-panel/tool.js +17 -1
- package/dist/spawn/definition.d.ts.map +1 -1
- package/dist/spawn/definition.js +1 -0
- package/dist/spawn/floorplan-affordances.d.ts.map +1 -1
- package/dist/spawn/floorplan-affordances.js +7 -4
- package/dist/spawn/floorplan-move.d.ts.map +1 -1
- package/dist/spawn/floorplan-move.js +8 -6
- package/dist/spawn/renderer.d.ts +4 -0
- package/dist/spawn/renderer.d.ts.map +1 -1
- package/dist/spawn/renderer.js +32 -18
- package/dist/spawn/tool.d.ts +2 -2
- package/dist/spawn/tool.d.ts.map +1 -1
- package/dist/spawn/tool.js +78 -11
- package/dist/stair/definition.d.ts.map +1 -1
- package/dist/stair/definition.js +15 -7
- package/dist/stair/destination.d.ts +16 -0
- package/dist/stair/destination.d.ts.map +1 -0
- package/dist/stair/destination.js +24 -0
- package/dist/stair/documentation.d.ts +8 -0
- package/dist/stair/documentation.d.ts.map +1 -0
- package/dist/stair/documentation.js +245 -0
- package/dist/stair/floor-stack.d.ts.map +1 -1
- package/dist/stair/floor-stack.js +38 -0
- package/dist/stair/floorplan-affordances.d.ts.map +1 -1
- package/dist/stair/floorplan-affordances.js +28 -9
- package/dist/stair/floorplan-move.d.ts +3 -5
- package/dist/stair/floorplan-move.d.ts.map +1 -1
- package/dist/stair/floorplan-move.js +14 -16
- package/dist/stair/floorplan.d.ts.map +1 -1
- package/dist/stair/floorplan.js +27 -14
- package/dist/stair/panel.d.ts.map +1 -1
- package/dist/stair/panel.js +35 -2
- package/dist/stair/renderer.d.ts.map +1 -1
- package/dist/stair/renderer.js +4 -3
- package/dist/structural-grid/coordination.d.ts +16 -0
- package/dist/structural-grid/coordination.d.ts.map +1 -0
- package/dist/structural-grid/coordination.js +105 -0
- package/dist/structural-grid/definition.d.ts +4 -0
- package/dist/structural-grid/definition.d.ts.map +1 -0
- package/dist/structural-grid/definition.js +51 -0
- package/dist/structural-grid/floorplan-tool.d.ts +16 -0
- package/dist/structural-grid/floorplan-tool.d.ts.map +1 -0
- package/dist/structural-grid/floorplan-tool.js +183 -0
- package/dist/structural-grid/floorplan.d.ts +3 -0
- package/dist/structural-grid/floorplan.d.ts.map +1 -0
- package/dist/structural-grid/floorplan.js +61 -0
- package/dist/structural-grid/index.d.ts +2 -0
- package/dist/structural-grid/index.d.ts.map +1 -0
- package/dist/structural-grid/index.js +1 -0
- package/dist/structural-grid/schema.d.ts +2 -0
- package/dist/structural-grid/schema.d.ts.map +1 -0
- package/dist/structural-grid/schema.js +1 -0
- package/dist/wall/construction-dimensions.d.ts +32 -0
- package/dist/wall/construction-dimensions.d.ts.map +1 -0
- package/dist/wall/construction-dimensions.js +1031 -0
- package/dist/wall/contextual-dimensions.d.ts +13 -0
- package/dist/wall/contextual-dimensions.d.ts.map +1 -0
- package/dist/wall/contextual-dimensions.js +221 -0
- package/dist/wall/definition.d.ts.map +1 -1
- package/dist/wall/definition.js +20 -1
- package/dist/wall/floorplan-affordances.d.ts.map +1 -1
- package/dist/wall/floorplan-affordances.js +23 -8
- package/dist/wall/floorplan-overrides.d.ts +9 -6
- package/dist/wall/floorplan-overrides.d.ts.map +1 -1
- package/dist/wall/floorplan-overrides.js +20 -11
- package/dist/wall/floorplan.d.ts +12 -3
- package/dist/wall/floorplan.d.ts.map +1 -1
- package/dist/wall/floorplan.js +121 -79
- package/dist/wall/measurement.d.ts.map +1 -1
- package/dist/wall/measurement.js +17 -4
- package/dist/wall/move-endpoint-tool.d.ts.map +1 -1
- package/dist/wall/move-endpoint-tool.js +74 -27
- package/dist/wall/move-shared.d.ts.map +1 -1
- package/dist/wall/move-shared.js +3 -2
- package/dist/wall/move-tool.d.ts.map +1 -1
- package/dist/wall/move-tool.js +15 -3
- package/dist/wall/paint.d.ts.map +1 -1
- package/dist/wall/paint.js +10 -6
- package/dist/wall/panel.d.ts.map +1 -1
- package/dist/wall/panel.js +32 -5
- package/dist/wall/parametrics.d.ts.map +1 -1
- package/dist/wall/parametrics.js +2 -0
- package/dist/wall/preview.d.ts +8 -0
- package/dist/wall/preview.d.ts.map +1 -0
- package/dist/wall/preview.js +39 -0
- package/dist/wall/quick-measurement.d.ts.map +1 -1
- package/dist/wall/quick-measurement.js +3 -2
- package/dist/wall/renderer.d.ts.map +1 -1
- package/dist/wall/renderer.js +7 -5
- package/dist/wall/system.d.ts +1 -1
- package/dist/wall/system.d.ts.map +1 -1
- package/dist/wall/system.js +37 -2
- package/dist/wall/tool.d.ts.map +1 -1
- package/dist/wall/tool.js +148 -96
- package/dist/wall/treatment-level-data.d.ts +14 -0
- package/dist/wall/treatment-level-data.d.ts.map +1 -0
- package/dist/wall/treatment-level-data.js +31 -0
- package/dist/wall/treatments.d.ts +8 -2
- package/dist/wall/treatments.d.ts.map +1 -1
- package/dist/wall/treatments.js +58 -15
- package/dist/window/contextual-dimensions.d.ts +3 -0
- package/dist/window/contextual-dimensions.d.ts.map +1 -0
- package/dist/window/contextual-dimensions.js +7 -0
- package/dist/window/definition.d.ts.map +1 -1
- package/dist/window/definition.js +15 -10
- package/dist/window/floorplan-affordances.d.ts +2 -5
- package/dist/window/floorplan-affordances.d.ts.map +1 -1
- package/dist/window/floorplan-affordances.js +9 -15
- package/dist/window/floorplan-move.d.ts.map +1 -1
- package/dist/window/floorplan-move.js +1 -1
- package/dist/window/floorplan.d.ts.map +1 -1
- package/dist/window/floorplan.js +7 -1
- package/dist/window/move-tool.d.ts.map +1 -1
- package/dist/window/move-tool.js +3 -3
- package/dist/window/panel.d.ts.map +1 -1
- package/dist/window/panel.js +4 -1
- package/dist/window/schema.d.ts +1 -1
- package/dist/window/schema.d.ts.map +1 -1
- package/dist/window/schema.js +1 -1
- package/dist/window/tool.d.ts.map +1 -1
- package/dist/window/tool.js +64 -7
- package/dist/window/window-math.d.ts +7 -3
- package/dist/window/window-math.d.ts.map +1 -1
- package/dist/window/window-math.js +8 -3
- package/dist/zone/contextual-dimensions.d.ts +3 -0
- package/dist/zone/contextual-dimensions.d.ts.map +1 -0
- package/dist/zone/contextual-dimensions.js +43 -0
- package/dist/zone/definition.d.ts.map +1 -1
- package/dist/zone/definition.js +9 -1
- package/dist/zone/floorplan-affordances.d.ts +36 -0
- package/dist/zone/floorplan-affordances.d.ts.map +1 -1
- package/dist/zone/floorplan.d.ts.map +1 -1
- package/dist/zone/floorplan.js +59 -3
- package/dist/zone/quantities-panel.d.ts.map +1 -1
- package/dist/zone/quantities-panel.js +48 -4
- package/dist/zone/room-clear-dimensions.d.ts +3 -0
- package/dist/zone/room-clear-dimensions.d.ts.map +1 -0
- package/dist/zone/room-clear-dimensions.js +406 -0
- package/dist/zone/room-documentation.d.ts +11 -0
- package/dist/zone/room-documentation.d.ts.map +1 -0
- package/dist/zone/room-documentation.js +97 -0
- package/package.json +7 -7
|
@@ -10,8 +10,9 @@ import { cabinetPaint } from './paint';
|
|
|
10
10
|
import { cabinetModuleParametrics, cabinetParametrics } from './parametrics';
|
|
11
11
|
import useCabinetPlacementType from './placement-type';
|
|
12
12
|
import { cabinetQuickActions } from './quick-actions';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { cabinetConnectedDepthBounds, cabinetResizeUpperBound, MAX_CABINET_DEPTH, MAX_CABINET_WIDTH, MIN_CABINET_DEPTH, MIN_CABINET_WIDTH, } from './resize-limits';
|
|
14
|
+
import { moduleSideOpen, sortRunModules } from './run-layout';
|
|
15
|
+
import { backAlignedRunDepthOverrides, backAlignZ, buildWallCornerDepthIndex, bumpCabinetRunLayoutRevision, cabinetMetadataRecord, cabinetModulesForRun, totalCabinetHeight as cabinetTotalHeight, cornerSourceWidthOverridesForDerivedDepth, previewCornerRunsFromRunSources, resolveCabinetType, runModuleBaseY, syncCornerRunsFromRunSources, syncCornerRunsFromSourceModule, wallChildOf, wallCornerWidthOverridesForDepthTargets, } from './run-ops';
|
|
15
16
|
import { cabinetSceneAction } from './scene-action';
|
|
16
17
|
import { CabinetModuleNode, CabinetNode } from './schema';
|
|
17
18
|
import { cabinetSlots } from './slots';
|
|
@@ -131,10 +132,9 @@ const SIDE_HANDLE_OFFSET = 0.18;
|
|
|
131
132
|
const HEIGHT_HANDLE_OFFSET = 0.22;
|
|
132
133
|
const ROTATE_CORNER_OFFSET = 0.32;
|
|
133
134
|
const ROTATE_RING_OFFSET = 0.04;
|
|
134
|
-
const MIN_CABINET_WIDTH = 0.3;
|
|
135
|
-
const MIN_CABINET_DEPTH = 0.3;
|
|
136
135
|
const MIN_CABINET_CARCASS_HEIGHT = 0.4;
|
|
137
136
|
const CABINET_ADJACENCY_EPSILON = 1e-4;
|
|
137
|
+
const CABINET_DEPTH_SNAP_THRESHOLD = 0.02;
|
|
138
138
|
function isCabinetModule(node) {
|
|
139
139
|
return node?.type === 'cabinet-module';
|
|
140
140
|
}
|
|
@@ -370,6 +370,17 @@ function cabinetLocalBounds(node, nodes) {
|
|
|
370
370
|
includeChildRunBounds(child, nodes, bounds);
|
|
371
371
|
}
|
|
372
372
|
}
|
|
373
|
+
if (isCabinetModule(node) && nodes) {
|
|
374
|
+
for (const childId of node.children ?? []) {
|
|
375
|
+
const child = nodes[childId];
|
|
376
|
+
if (isCabinetModule(child)) {
|
|
377
|
+
includeCabinetModuleBounds(child, nodes, [0, 0, 0], bounds);
|
|
378
|
+
}
|
|
379
|
+
else if (isCabinetRun(child)) {
|
|
380
|
+
includeChildRunBounds(child, nodes, bounds);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
373
384
|
const width = Math.max(0.01, bounds.maxX - bounds.minX);
|
|
374
385
|
const height = Math.max(0.01, bounds.maxY - bounds.minY);
|
|
375
386
|
const depth = Math.max(0.01, bounds.maxZ - bounds.minZ);
|
|
@@ -412,22 +423,260 @@ function cabinetModuleSideOpen(module, side, sceneApi) {
|
|
|
412
423
|
return true;
|
|
413
424
|
return moduleSideOpen(cabinetModulesForRun(parent, sceneApi.nodes()), module.id, side, CABINET_ADJACENCY_EPSILON);
|
|
414
425
|
}
|
|
415
|
-
function
|
|
426
|
+
function cabinetModuleConnectedNeighbor(module, side, sceneApi) {
|
|
427
|
+
const parent = module.parentId ? sceneApi.get(module.parentId) : undefined;
|
|
428
|
+
if (!isCabinetRun(parent))
|
|
429
|
+
return undefined;
|
|
430
|
+
const modules = sortRunModules(cabinetModulesForRun(parent, sceneApi.nodes()));
|
|
431
|
+
const index = modules.findIndex((entry) => entry.id === module.id);
|
|
432
|
+
if (index < 0 || cabinetModuleSideOpen(module, side, sceneApi))
|
|
433
|
+
return undefined;
|
|
434
|
+
return side === 'left' ? modules[index - 1] : modules[index + 1];
|
|
435
|
+
}
|
|
436
|
+
function cabinetWidthConnectedNeighbor(module, side, sceneApi) {
|
|
437
|
+
const parent = module.parentId ? sceneApi.get(module.parentId) : undefined;
|
|
438
|
+
if (isCabinetRun(parent))
|
|
439
|
+
return cabinetModuleConnectedNeighbor(module, side, sceneApi);
|
|
440
|
+
if (!isCabinetModule(parent))
|
|
441
|
+
return undefined;
|
|
442
|
+
if (wallChildOf(parent, sceneApi.nodes())?.id !== module.id)
|
|
443
|
+
return undefined;
|
|
444
|
+
const connectedHost = cabinetModuleConnectedNeighbor(parent, side, sceneApi);
|
|
445
|
+
if (!connectedHost || isCabinetWidthFiller(connectedHost))
|
|
446
|
+
return undefined;
|
|
447
|
+
return wallChildOf(connectedHost, sceneApi.nodes()) ?? undefined;
|
|
448
|
+
}
|
|
449
|
+
function cabinetModuleRunLocalCenterX(module, sceneApi) {
|
|
450
|
+
const parent = module.parentId ? sceneApi.get(module.parentId) : undefined;
|
|
451
|
+
if (isCabinetRun(parent))
|
|
452
|
+
return module.position[0];
|
|
453
|
+
if (!isCabinetModule(parent))
|
|
454
|
+
return null;
|
|
455
|
+
const run = parent.parentId ? sceneApi.get(parent.parentId) : undefined;
|
|
456
|
+
return isCabinetRun(run) ? parent.position[0] + module.position[0] : null;
|
|
457
|
+
}
|
|
458
|
+
function cabinetWallWidthGap(module, side, sceneApi) {
|
|
459
|
+
const parent = module.parentId ? sceneApi.get(module.parentId) : undefined;
|
|
460
|
+
const isWallModule = (isCabinetRun(parent) && parent.runTier === 'wall') ||
|
|
461
|
+
(isCabinetModule(parent) && wallChildOf(parent, sceneApi.nodes())?.id === module.id);
|
|
462
|
+
if (!isWallModule)
|
|
463
|
+
return 0;
|
|
464
|
+
const connected = cabinetWidthConnectedNeighbor(module, side, sceneApi);
|
|
465
|
+
if (!connected || isCabinetWidthFiller(connected))
|
|
466
|
+
return 0;
|
|
467
|
+
const moduleCenter = cabinetModuleRunLocalCenterX(module, sceneApi);
|
|
468
|
+
const connectedCenter = cabinetModuleRunLocalCenterX(connected, sceneApi);
|
|
469
|
+
if (moduleCenter === null || connectedCenter === null)
|
|
470
|
+
return 0;
|
|
471
|
+
const direction = side === 'right' ? 1 : -1;
|
|
472
|
+
return Math.max(0, direction * (connectedCenter - moduleCenter) - (module.width + connected.width) / 2);
|
|
473
|
+
}
|
|
474
|
+
function isCabinetWidthFiller(module) {
|
|
475
|
+
return (module.moduleKind === 'corner-filler' ||
|
|
476
|
+
module.name === 'Corner Filler' ||
|
|
477
|
+
module.name === 'Wall Bridge Filler' ||
|
|
478
|
+
module.name === 'Corner Wall Filler');
|
|
479
|
+
}
|
|
480
|
+
function cabinetNodeAttachedToAncestor(node, ancestorId, nodes) {
|
|
481
|
+
let current = node;
|
|
482
|
+
const visited = new Set();
|
|
483
|
+
while (current.parentId) {
|
|
484
|
+
const currentId = current.id;
|
|
485
|
+
if (visited.has(currentId))
|
|
486
|
+
return false;
|
|
487
|
+
visited.add(currentId);
|
|
488
|
+
const parent = nodes[current.parentId];
|
|
489
|
+
if (parent?.type !== 'cabinet' && parent?.type !== 'cabinet-module')
|
|
490
|
+
return false;
|
|
491
|
+
if (!(parent.children ?? []).includes(currentId))
|
|
492
|
+
return false;
|
|
493
|
+
if (parent.id === ancestorId)
|
|
494
|
+
return true;
|
|
495
|
+
current = parent;
|
|
496
|
+
}
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
function cabinetSubtreeHasNamedFiller(root, name, sceneApi) {
|
|
500
|
+
const pending = [...(root.children ?? [])];
|
|
501
|
+
const visited = new Set();
|
|
502
|
+
while (pending.length > 0) {
|
|
503
|
+
const id = pending.pop();
|
|
504
|
+
if (visited.has(id))
|
|
505
|
+
continue;
|
|
506
|
+
visited.add(id);
|
|
507
|
+
const node = sceneApi.get(id);
|
|
508
|
+
if (!node)
|
|
509
|
+
continue;
|
|
510
|
+
if (node.type === 'cabinet-module' && isCabinetWidthFiller(node) && node.name === name) {
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
if (node.type === 'cabinet' || node.type === 'cabinet-module') {
|
|
514
|
+
pending.push(...(node.children ?? []));
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
519
|
+
function wallCabinetSideHasFiller(hostModule, side, sceneApi) {
|
|
520
|
+
const hostRun = hostModule.parentId
|
|
521
|
+
? sceneApi.get(hostModule.parentId)
|
|
522
|
+
: undefined;
|
|
523
|
+
if (!hostRun || !isCabinetRun(hostRun))
|
|
524
|
+
return false;
|
|
525
|
+
const connected = cabinetModuleConnectedNeighbor(hostModule, side, sceneApi);
|
|
526
|
+
if (connected &&
|
|
527
|
+
isCabinetWidthFiller(connected) &&
|
|
528
|
+
cabinetSubtreeHasNamedFiller(connected, 'Corner Wall Filler', sceneApi)) {
|
|
529
|
+
return true;
|
|
530
|
+
}
|
|
531
|
+
const nodes = sceneApi.nodes();
|
|
532
|
+
for (const candidate of Object.values(nodes)) {
|
|
533
|
+
if (candidate?.type !== 'cabinet')
|
|
534
|
+
continue;
|
|
535
|
+
const derived = cabinetMetadataRecord(candidate.metadata).cabinetCornerDerivedRun;
|
|
536
|
+
if (!derived || typeof derived !== 'object' || Array.isArray(derived))
|
|
537
|
+
continue;
|
|
538
|
+
if (derived.role !== 'bridge' ||
|
|
539
|
+
derived.side !== side ||
|
|
540
|
+
derived.sourceModuleId !== hostModule.id ||
|
|
541
|
+
derived.sourceRunId !== hostRun.id ||
|
|
542
|
+
!cabinetNodeAttachedToAncestor(candidate, hostRun.id, nodes)) {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
if (cabinetModulesForRun(candidate, nodes).some((entry) => entry.name === 'Wall Bridge Filler')) {
|
|
546
|
+
return true;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
function cabinetModuleSideHasCornerFiller(module, side, sceneApi) {
|
|
552
|
+
const parent = module.parentId ? sceneApi.get(module.parentId) : undefined;
|
|
553
|
+
if (isCabinetModule(parent)) {
|
|
554
|
+
return wallCabinetSideHasFiller(parent, side, sceneApi);
|
|
555
|
+
}
|
|
556
|
+
if (!isCabinetRun(parent))
|
|
557
|
+
return false;
|
|
558
|
+
const connected = cabinetModuleConnectedNeighbor(module, side, sceneApi);
|
|
559
|
+
if (connected && isCabinetWidthFiller(connected)) {
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
for (const candidate of Object.values(sceneApi.nodes())) {
|
|
563
|
+
if (candidate?.type !== 'cabinet')
|
|
564
|
+
continue;
|
|
565
|
+
const derived = cabinetMetadataRecord(candidate.metadata).cabinetCornerDerivedRun;
|
|
566
|
+
if (!derived || typeof derived !== 'object' || Array.isArray(derived))
|
|
567
|
+
continue;
|
|
568
|
+
if (candidate.parentId !== parent.id ||
|
|
569
|
+
!(parent.children ?? []).includes(candidate.id) ||
|
|
570
|
+
derived.role !== 'base-leg' ||
|
|
571
|
+
derived.side !== side ||
|
|
572
|
+
derived.sourceModuleId !== module.id ||
|
|
573
|
+
derived.sourceRunId !== parent.id) {
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
if (cabinetModulesForRun(candidate, sceneApi.nodes()).some((entry) => entry.moduleKind === 'corner-filler')) {
|
|
577
|
+
return true;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
function connectedCabinetWidthResize(module, side, delta, sceneApi) {
|
|
583
|
+
const connected = cabinetWidthConnectedNeighbor(module, side, sceneApi);
|
|
584
|
+
if (!connected || isCabinetWidthFiller(connected))
|
|
585
|
+
return null;
|
|
586
|
+
const direction = side === 'right' ? 1 : -1;
|
|
587
|
+
return {
|
|
588
|
+
module: connected,
|
|
589
|
+
patch: {
|
|
590
|
+
width: connected.width - delta,
|
|
591
|
+
position: [
|
|
592
|
+
connected.position[0] + (direction * delta) / 2,
|
|
593
|
+
connected.position[1],
|
|
594
|
+
connected.position[2],
|
|
595
|
+
],
|
|
596
|
+
},
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
function wallCabinetWidthOverride(module, width, sceneApi) {
|
|
600
|
+
const parent = module.parentId
|
|
601
|
+
? sceneApi.get(module.parentId)
|
|
602
|
+
: undefined;
|
|
603
|
+
if (!parent || !isCabinetRun(parent) || resolveCabinetType(module, parent) !== 'base')
|
|
604
|
+
return null;
|
|
605
|
+
const wallChild = wallChildOf(module, sceneApi.nodes());
|
|
606
|
+
return wallChild ? [wallChild.id, { width }] : null;
|
|
607
|
+
}
|
|
608
|
+
function parentRunGeometryPreviewOverride(node, sceneApi) {
|
|
609
|
+
if (!isCabinetModule(node) || !node.parentId)
|
|
610
|
+
return null;
|
|
611
|
+
const parent = sceneApi.get(node.parentId);
|
|
612
|
+
return isCabinetRun(parent) ? [parent.id, {}] : null;
|
|
613
|
+
}
|
|
614
|
+
function sharedDepthBounds(referenceDepth, targets, nodes) {
|
|
615
|
+
const depthOwners = targets.flatMap((target) => {
|
|
616
|
+
if (!isCabinetRun(target))
|
|
617
|
+
return [target];
|
|
618
|
+
const modules = cabinetModulesForRun(target, nodes);
|
|
619
|
+
return modules.length > 0 ? [target, ...modules] : [target];
|
|
620
|
+
});
|
|
621
|
+
const minDelta = Math.max(...depthOwners.map((target) => MIN_CABINET_DEPTH - target.depth));
|
|
622
|
+
const maxDelta = Math.min(...depthOwners.map((target) => cabinetResizeUpperBound(target.depth, MAX_CABINET_DEPTH) - target.depth));
|
|
623
|
+
return {
|
|
624
|
+
min: referenceDepth + minDelta,
|
|
625
|
+
max: referenceDepth + maxDelta,
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
function depthDeltaRunOverrides(run, nodes, depthDelta) {
|
|
629
|
+
const overrides = [];
|
|
630
|
+
for (const module of cabinetModulesForRun(run, nodes)) {
|
|
631
|
+
const depth = module.depth + depthDelta;
|
|
632
|
+
const positionZ = backAnchoredModuleZ(module.position[2], module.depth, depth);
|
|
633
|
+
const parentShiftZ = positionZ - module.position[2];
|
|
634
|
+
overrides.push([
|
|
635
|
+
module.id,
|
|
636
|
+
{
|
|
637
|
+
depth,
|
|
638
|
+
position: [module.position[0], module.position[1], positionZ],
|
|
639
|
+
},
|
|
640
|
+
]);
|
|
641
|
+
for (const childId of module.children ?? []) {
|
|
642
|
+
const child = nodes[childId];
|
|
643
|
+
if (child?.type !== 'cabinet')
|
|
644
|
+
continue;
|
|
645
|
+
overrides.push([
|
|
646
|
+
child.id,
|
|
647
|
+
{
|
|
648
|
+
position: [child.position[0], child.position[1], child.position[2] - parentShiftZ],
|
|
649
|
+
},
|
|
650
|
+
]);
|
|
651
|
+
}
|
|
652
|
+
const wallChild = wallChildOf(module, nodes);
|
|
653
|
+
if (wallChild) {
|
|
654
|
+
overrides.push([
|
|
655
|
+
wallChild.id,
|
|
656
|
+
{
|
|
657
|
+
position: [
|
|
658
|
+
wallChild.position[0],
|
|
659
|
+
wallChild.position[1],
|
|
660
|
+
backAlignZ(depth, wallChild.depth),
|
|
661
|
+
],
|
|
662
|
+
},
|
|
663
|
+
]);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return overrides;
|
|
667
|
+
}
|
|
668
|
+
function commitRunResize(run, patch, sceneApi, options = {}) {
|
|
416
669
|
sceneApi.update(run.id, patch);
|
|
417
670
|
const nextRun = { ...run, ...patch };
|
|
418
671
|
const syncDepth = typeof patch.depth === 'number';
|
|
419
672
|
const syncHeight = typeof patch.carcassHeight === 'number';
|
|
420
673
|
const syncPosition = patch.showPlinth !== undefined || typeof patch.plinthHeight === 'number';
|
|
421
674
|
if (syncDepth || syncHeight || syncPosition) {
|
|
675
|
+
const depthOverrides = new Map(syncDepth ? backAlignedRunDepthOverrides(run, sceneApi.nodes(), nextRun.depth) : []);
|
|
422
676
|
for (const module of cabinetModulesForRun(run, sceneApi.nodes())) {
|
|
423
677
|
const modulePatch = {};
|
|
424
678
|
if (syncDepth) {
|
|
425
|
-
modulePatch
|
|
426
|
-
modulePatch.position = [
|
|
427
|
-
module.position[0],
|
|
428
|
-
module.position[1],
|
|
429
|
-
backAnchoredModuleZ(module.position[2], module.depth, nextRun.depth),
|
|
430
|
-
];
|
|
679
|
+
Object.assign(modulePatch, depthOverrides.get(module.id));
|
|
431
680
|
}
|
|
432
681
|
if (syncHeight) {
|
|
433
682
|
modulePatch.carcassHeight = Math.max(nextRun.carcassHeight, minCabinetCarcassHeightForStack(module));
|
|
@@ -453,19 +702,37 @@ function commitRunResize(run, patch, sceneApi) {
|
|
|
453
702
|
}
|
|
454
703
|
}
|
|
455
704
|
}
|
|
705
|
+
if (syncDepth) {
|
|
706
|
+
for (const [id, depthPatch] of depthOverrides) {
|
|
707
|
+
if (sceneApi.get(id)?.type !== 'cabinet')
|
|
708
|
+
continue;
|
|
709
|
+
sceneApi.update(id, depthPatch);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
456
712
|
}
|
|
457
713
|
if (syncDepth || syncHeight || syncPosition) {
|
|
458
714
|
bumpCabinetRunLayoutRevision(sceneApi, nextRun);
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
sceneApi,
|
|
465
|
-
});
|
|
466
|
-
}
|
|
715
|
+
syncCornerRunsFromRunSources({
|
|
716
|
+
baseLayout: options.cornerSync ?? 'full',
|
|
717
|
+
run: nextRun,
|
|
718
|
+
sceneApi,
|
|
719
|
+
});
|
|
467
720
|
}
|
|
468
721
|
}
|
|
722
|
+
function commitRunDepthDelta(run, depth, sceneApi, options = {}) {
|
|
723
|
+
const depthDelta = depth - run.depth;
|
|
724
|
+
for (const [id, patch] of depthDeltaRunOverrides(run, sceneApi.nodes(), depthDelta)) {
|
|
725
|
+
sceneApi.update(id, patch);
|
|
726
|
+
}
|
|
727
|
+
sceneApi.update(run.id, { depth });
|
|
728
|
+
const nextRun = { ...run, depth };
|
|
729
|
+
bumpCabinetRunLayoutRevision(sceneApi, nextRun);
|
|
730
|
+
syncCornerRunsFromRunSources({
|
|
731
|
+
baseLayout: options.cornerSync ?? 'full',
|
|
732
|
+
run: nextRun,
|
|
733
|
+
sceneApi,
|
|
734
|
+
});
|
|
735
|
+
}
|
|
469
736
|
function commitModuleResize(module, patch, sceneApi) {
|
|
470
737
|
const nodes = sceneApi.nodes();
|
|
471
738
|
const parent = module.parentId ? nodes[module.parentId] : undefined;
|
|
@@ -479,23 +746,13 @@ function commitModuleResize(module, patch, sceneApi) {
|
|
|
479
746
|
}
|
|
480
747
|
if (typeof patch.width === 'number') {
|
|
481
748
|
sceneApi.update(module.id, patch);
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
width: patch.width
|
|
486
|
-
|
|
487
|
-
wallChild.position[0],
|
|
488
|
-
wallChild.position[1],
|
|
489
|
-
backAlignZ(patch.depth ?? module.depth, wallChild.depth),
|
|
490
|
-
],
|
|
491
|
-
});
|
|
749
|
+
if (resolveCabinetType(module, parentRun) === 'base') {
|
|
750
|
+
const wallChild = wallChildOf(module, sceneApi.nodes());
|
|
751
|
+
if (wallChild) {
|
|
752
|
+
sceneApi.update(wallChild.id, { width: patch.width });
|
|
753
|
+
}
|
|
492
754
|
}
|
|
493
755
|
bumpCabinetRunLayoutRevision(sceneApi, parentRun);
|
|
494
|
-
syncCornerRunsFromSourceModule({
|
|
495
|
-
module: sceneApi.get(module.id) ?? module,
|
|
496
|
-
run: sceneApi.get(parentRun.id) ?? parentRun,
|
|
497
|
-
sceneApi,
|
|
498
|
-
});
|
|
499
756
|
return;
|
|
500
757
|
}
|
|
501
758
|
const modulePatch = { ...patch };
|
|
@@ -509,8 +766,6 @@ function commitModuleResize(module, patch, sceneApi) {
|
|
|
509
766
|
sceneApi.update(module.id, modulePatch);
|
|
510
767
|
if (resolveCabinetType(module, parentRun) === 'base') {
|
|
511
768
|
const runPatch = {};
|
|
512
|
-
if (typeof patch.depth === 'number')
|
|
513
|
-
runPatch.depth = patch.depth;
|
|
514
769
|
if (typeof patch.carcassHeight === 'number') {
|
|
515
770
|
runPatch.carcassHeight = patch.carcassHeight;
|
|
516
771
|
}
|
|
@@ -558,17 +813,71 @@ function cabinetWidthHandle(side) {
|
|
|
558
813
|
kind: 'linear-resize',
|
|
559
814
|
axis: 'x',
|
|
560
815
|
anchor: side === 'right' ? 'min' : 'max',
|
|
561
|
-
min:
|
|
816
|
+
min: (node, sceneApi) => {
|
|
817
|
+
if (!isCabinetModule(node))
|
|
818
|
+
return MIN_CABINET_WIDTH;
|
|
819
|
+
const gap = cabinetWallWidthGap(node, side, sceneApi);
|
|
820
|
+
const connected = cabinetWidthConnectedNeighbor(node, side, sceneApi);
|
|
821
|
+
if (!connected || isCabinetWidthFiller(connected))
|
|
822
|
+
return MIN_CABINET_WIDTH - gap;
|
|
823
|
+
const connectedMax = cabinetResizeUpperBound(connected.width, MAX_CABINET_WIDTH);
|
|
824
|
+
return Math.max(MIN_CABINET_WIDTH - gap, node.width - (connectedMax - connected.width));
|
|
825
|
+
},
|
|
826
|
+
max: (node, sceneApi) => {
|
|
827
|
+
const ownMax = cabinetResizeUpperBound(node.width, MAX_CABINET_WIDTH);
|
|
828
|
+
if (!isCabinetModule(node))
|
|
829
|
+
return ownMax;
|
|
830
|
+
const gap = cabinetWallWidthGap(node, side, sceneApi);
|
|
831
|
+
const connected = cabinetWidthConnectedNeighbor(node, side, sceneApi);
|
|
832
|
+
if (!connected || isCabinetWidthFiller(connected))
|
|
833
|
+
return ownMax - gap;
|
|
834
|
+
return Math.min(ownMax - gap, node.width + connected.width - MIN_CABINET_WIDTH);
|
|
835
|
+
},
|
|
562
836
|
currentValue: (node) => node.width,
|
|
563
|
-
apply: (node, width) =>
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
837
|
+
apply: (node, width, sceneApi) => {
|
|
838
|
+
const gap = isCabinetModule(node) ? cabinetWallWidthGap(node, side, sceneApi) : 0;
|
|
839
|
+
const effectiveWidth = width + gap;
|
|
840
|
+
return {
|
|
841
|
+
width: effectiveWidth,
|
|
842
|
+
position: [
|
|
843
|
+
node.position[0] + (sign * (effectiveWidth - node.width)) / 2,
|
|
844
|
+
node.position[1],
|
|
845
|
+
node.position[2],
|
|
846
|
+
],
|
|
847
|
+
};
|
|
848
|
+
},
|
|
849
|
+
previewOverrides: (node, width, sceneApi) => {
|
|
850
|
+
if (!isCabinetModule(node))
|
|
851
|
+
return [];
|
|
852
|
+
const overrides = [];
|
|
853
|
+
const parentRunOverride = parentRunGeometryPreviewOverride(node, sceneApi);
|
|
854
|
+
if (parentRunOverride)
|
|
855
|
+
overrides.push(parentRunOverride);
|
|
856
|
+
const gap = cabinetWallWidthGap(node, side, sceneApi);
|
|
857
|
+
const selectedWallOverride = wallCabinetWidthOverride(node, width + gap, sceneApi);
|
|
858
|
+
if (selectedWallOverride)
|
|
859
|
+
overrides.push(selectedWallOverride);
|
|
860
|
+
const connectedResize = connectedCabinetWidthResize(node, side, width - node.width, sceneApi);
|
|
861
|
+
if (connectedResize) {
|
|
862
|
+
overrides.push([
|
|
863
|
+
connectedResize.module.id,
|
|
864
|
+
connectedResize.patch,
|
|
865
|
+
]);
|
|
866
|
+
const connectedWallOverride = wallCabinetWidthOverride(connectedResize.module, connectedResize.patch.width, sceneApi);
|
|
867
|
+
if (connectedWallOverride)
|
|
868
|
+
overrides.push(connectedWallOverride);
|
|
869
|
+
}
|
|
870
|
+
return overrides;
|
|
871
|
+
},
|
|
872
|
+
commit: (node, patch, sceneApi) => {
|
|
873
|
+
const connectedResize = isCabinetModule(node) && typeof patch.width === 'number'
|
|
874
|
+
? connectedCabinetWidthResize(node, side, patch.width - node.width - cabinetWallWidthGap(node, side, sceneApi), sceneApi)
|
|
875
|
+
: null;
|
|
876
|
+
commitCabinetResize(node, patch, sceneApi);
|
|
877
|
+
if (connectedResize) {
|
|
878
|
+
commitCabinetResize(connectedResize.module, connectedResize.patch, sceneApi);
|
|
879
|
+
}
|
|
880
|
+
},
|
|
572
881
|
visible: (node, sceneApi) => !isCabinetModule(node) || cabinetModuleSideOpen(node, side, sceneApi),
|
|
573
882
|
placement: {
|
|
574
883
|
position: (node) => [
|
|
@@ -580,23 +889,439 @@ function cabinetWidthHandle(side) {
|
|
|
580
889
|
},
|
|
581
890
|
};
|
|
582
891
|
}
|
|
892
|
+
function cabinetDepthResizePatch(node, depth) {
|
|
893
|
+
return {
|
|
894
|
+
depth,
|
|
895
|
+
position: [node.position[0], node.position[1], node.position[2] + (depth - node.depth) / 2],
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
function snapCabinetDepth(node, requestedDepth, sceneApi) {
|
|
899
|
+
if (!isCabinetModule(node))
|
|
900
|
+
return requestedDepth;
|
|
901
|
+
let snappedDepth = requestedDepth;
|
|
902
|
+
let closestDistance = Number.POSITIVE_INFINITY;
|
|
903
|
+
for (const side of ['left', 'right']) {
|
|
904
|
+
const connected = cabinetWidthConnectedNeighbor(node, side, sceneApi);
|
|
905
|
+
if (!connected || isCabinetWidthFiller(connected))
|
|
906
|
+
continue;
|
|
907
|
+
const distance = Math.abs(requestedDepth - connected.depth);
|
|
908
|
+
if (distance <= CABINET_DEPTH_SNAP_THRESHOLD && distance < closestDistance) {
|
|
909
|
+
snappedDepth = connected.depth;
|
|
910
|
+
closestDistance = distance;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
return snappedDepth;
|
|
914
|
+
}
|
|
583
915
|
function cabinetDepthHandle() {
|
|
584
916
|
return {
|
|
585
917
|
kind: 'linear-resize',
|
|
586
918
|
axis: 'z',
|
|
587
919
|
anchor: 'min',
|
|
588
920
|
min: MIN_CABINET_DEPTH,
|
|
921
|
+
max: (node) => cabinetResizeUpperBound(node.depth, MAX_CABINET_DEPTH),
|
|
589
922
|
currentValue: (node) => node.depth,
|
|
590
|
-
apply:
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
923
|
+
apply: cabinetDepthResizePatch,
|
|
924
|
+
magneticSnap: snapCabinetDepth,
|
|
925
|
+
previewOverrides: (node, _depth, sceneApi) => {
|
|
926
|
+
const parentRunOverride = parentRunGeometryPreviewOverride(node, sceneApi);
|
|
927
|
+
return parentRunOverride ? [parentRunOverride] : [];
|
|
928
|
+
},
|
|
594
929
|
commit: commitCabinetResize,
|
|
595
930
|
placement: {
|
|
596
931
|
position: (node) => [0, cabinetTotalHeight(node) / 2, node.depth / 2 + SIDE_HANDLE_OFFSET],
|
|
597
932
|
},
|
|
598
933
|
};
|
|
599
934
|
}
|
|
935
|
+
function cornerBaseSourceRunId(node) {
|
|
936
|
+
const value = cabinetMetadataRecord(node.metadata).cabinetCornerDerivedRun;
|
|
937
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
938
|
+
return null;
|
|
939
|
+
const role = value.role;
|
|
940
|
+
const sourceRunId = value.sourceRunId;
|
|
941
|
+
return role === 'base-leg' && typeof sourceRunId === 'string' ? sourceRunId : null;
|
|
942
|
+
}
|
|
943
|
+
function connectedBaseRuns(node, sceneApi) {
|
|
944
|
+
const runs = new Map();
|
|
945
|
+
for (const candidate of Object.values(sceneApi.nodes())) {
|
|
946
|
+
if (isCabinetRun(candidate) && candidate.runTier === 'base') {
|
|
947
|
+
runs.set(candidate.id, candidate);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
runs.set(node.id, node);
|
|
951
|
+
const neighbors = new Map();
|
|
952
|
+
const connect = (a, b) => {
|
|
953
|
+
const aNeighbors = neighbors.get(a) ?? new Set();
|
|
954
|
+
const bNeighbors = neighbors.get(b) ?? new Set();
|
|
955
|
+
aNeighbors.add(b);
|
|
956
|
+
bNeighbors.add(a);
|
|
957
|
+
neighbors.set(a, aNeighbors);
|
|
958
|
+
neighbors.set(b, bNeighbors);
|
|
959
|
+
};
|
|
960
|
+
for (const run of runs.values()) {
|
|
961
|
+
const sourceRunId = cornerBaseSourceRunId(run);
|
|
962
|
+
if (sourceRunId && runs.has(sourceRunId))
|
|
963
|
+
connect(sourceRunId, run.id);
|
|
964
|
+
}
|
|
965
|
+
const connected = [];
|
|
966
|
+
const pending = [node.id];
|
|
967
|
+
const visited = new Set();
|
|
968
|
+
while (pending.length > 0) {
|
|
969
|
+
const id = pending.shift();
|
|
970
|
+
if (visited.has(id))
|
|
971
|
+
continue;
|
|
972
|
+
visited.add(id);
|
|
973
|
+
const run = runs.get(id);
|
|
974
|
+
if (run)
|
|
975
|
+
connected.push(run);
|
|
976
|
+
for (const neighbor of neighbors.get(id) ?? [])
|
|
977
|
+
pending.push(neighbor);
|
|
978
|
+
}
|
|
979
|
+
return connected;
|
|
980
|
+
}
|
|
981
|
+
function cabinetRunFrontCenter(run, sceneApi) {
|
|
982
|
+
const modules = cabinetModulesForRun(run, sceneApi.nodes());
|
|
983
|
+
if (modules.length === 0) {
|
|
984
|
+
return [0, cabinetTotalHeight(run) / 2, run.depth / 2 + SIDE_HANDLE_OFFSET];
|
|
985
|
+
}
|
|
986
|
+
const minX = Math.min(...modules.map((module) => module.position[0] - module.width / 2));
|
|
987
|
+
const maxX = Math.max(...modules.map((module) => module.position[0] + module.width / 2));
|
|
988
|
+
const maxZ = Math.max(...modules.map((module) => module.position[2] + module.depth / 2));
|
|
989
|
+
return [(minX + maxX) / 2, cabinetTotalHeight(run) / 2, maxZ + SIDE_HANDLE_OFFSET];
|
|
990
|
+
}
|
|
991
|
+
function cabinetRunPointInSelectedFrame(selected, target, point, sceneApi) {
|
|
992
|
+
const nodes = sceneApi.nodes();
|
|
993
|
+
const selectedWorld = cabinetDuplicateWorldPose(selected, nodes);
|
|
994
|
+
const targetWorld = cabinetDuplicateWorldPose(target, nodes);
|
|
995
|
+
if (!selectedWorld || !targetWorld)
|
|
996
|
+
return [point[0], point[1], point[2]];
|
|
997
|
+
const worldPoint = composeCabinetDuplicatePose(targetWorld.position, targetWorld.rotation, point, 0).position;
|
|
998
|
+
const dx = worldPoint[0] - selectedWorld.position[0];
|
|
999
|
+
const dz = worldPoint[2] - selectedWorld.position[2];
|
|
1000
|
+
const cos = Math.cos(selectedWorld.rotation);
|
|
1001
|
+
const sin = Math.sin(selectedWorld.rotation);
|
|
1002
|
+
return [cos * dx - sin * dz, worldPoint[1] - selectedWorld.position[1], sin * dx + cos * dz];
|
|
1003
|
+
}
|
|
1004
|
+
function cabinetRootRun(node, sceneApi) {
|
|
1005
|
+
let current = node;
|
|
1006
|
+
let root = isCabinetRun(current) ? current : null;
|
|
1007
|
+
const visited = new Set();
|
|
1008
|
+
while (current.parentId && !visited.has(current.parentId)) {
|
|
1009
|
+
visited.add(current.parentId);
|
|
1010
|
+
const parent = sceneApi.get(current.parentId);
|
|
1011
|
+
if (!isCabinetRun(parent) && !isCabinetModule(parent))
|
|
1012
|
+
break;
|
|
1013
|
+
current = parent;
|
|
1014
|
+
if (isCabinetRun(current))
|
|
1015
|
+
root = current;
|
|
1016
|
+
}
|
|
1017
|
+
return root;
|
|
1018
|
+
}
|
|
1019
|
+
function cabinetWallTargets(node, sceneApi) {
|
|
1020
|
+
const root = cabinetRootRun(node, sceneApi);
|
|
1021
|
+
if (!root)
|
|
1022
|
+
return [];
|
|
1023
|
+
const targets = [];
|
|
1024
|
+
const visited = new Set();
|
|
1025
|
+
const visit = (current) => {
|
|
1026
|
+
if (visited.has(current.id))
|
|
1027
|
+
return;
|
|
1028
|
+
visited.add(current.id);
|
|
1029
|
+
if (isCabinetRun(current) && current.runTier === 'wall') {
|
|
1030
|
+
targets.push(current);
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
const parent = current.parentId ? sceneApi.get(current.parentId) : undefined;
|
|
1034
|
+
if (isCabinetModule(current) && isCabinetModule(parent)) {
|
|
1035
|
+
if (!isHoodOnlyCabinet(current))
|
|
1036
|
+
targets.push(current);
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
for (const childId of current.children ?? []) {
|
|
1040
|
+
const child = sceneApi.get(childId);
|
|
1041
|
+
if (isCabinetRun(child) || isCabinetModule(child))
|
|
1042
|
+
visit(child);
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
visit(root);
|
|
1046
|
+
return targets;
|
|
1047
|
+
}
|
|
1048
|
+
function cabinetWallDepthPreview(targets, depth, sceneApi, adjustCornerWidths, widthMode, cornerIndex) {
|
|
1049
|
+
const overrides = new Map();
|
|
1050
|
+
const liveTargets = targets.map((target) => sceneApi.get(target.id) ?? target);
|
|
1051
|
+
const depthDelta = depth - (liveTargets[0]?.depth ?? depth);
|
|
1052
|
+
for (const live of liveTargets) {
|
|
1053
|
+
const nextDepth = live.depth + depthDelta;
|
|
1054
|
+
if (isCabinetRun(live)) {
|
|
1055
|
+
overrides.set(live.id, { depth: nextDepth });
|
|
1056
|
+
for (const [id, patch] of depthDeltaRunOverrides(live, sceneApi.nodes(), depthDelta)) {
|
|
1057
|
+
overrides.set(id, { ...(overrides.get(id) ?? {}), ...patch });
|
|
1058
|
+
}
|
|
1059
|
+
continue;
|
|
1060
|
+
}
|
|
1061
|
+
overrides.set(live.id, cabinetDepthResizePatch(live, nextDepth));
|
|
1062
|
+
}
|
|
1063
|
+
if (adjustCornerWidths) {
|
|
1064
|
+
for (const [id, patch] of wallCornerWidthOverridesForDepthTargets({
|
|
1065
|
+
cornerIndex,
|
|
1066
|
+
depth,
|
|
1067
|
+
nodes: sceneApi.nodes(),
|
|
1068
|
+
targets: liveTargets,
|
|
1069
|
+
widthMode,
|
|
1070
|
+
})) {
|
|
1071
|
+
const existing = overrides.get(id);
|
|
1072
|
+
const cornerPatch = patch;
|
|
1073
|
+
const merged = { ...(existing ?? {}), ...cornerPatch };
|
|
1074
|
+
if (existing?.position && cornerPatch.position) {
|
|
1075
|
+
merged.position = [cornerPatch.position[0], cornerPatch.position[1], existing.position[2]];
|
|
1076
|
+
}
|
|
1077
|
+
overrides.set(id, merged);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
return [...overrides];
|
|
1081
|
+
}
|
|
1082
|
+
function commitCabinetWallDepth(targets, depth, sceneApi, adjustCornerWidths, widthMode, cornerIndex) {
|
|
1083
|
+
const preview = cabinetWallDepthPreview(targets, depth, sceneApi, adjustCornerWidths, widthMode, cornerIndex);
|
|
1084
|
+
for (const [id, patch] of preview) {
|
|
1085
|
+
sceneApi.update(id, patch);
|
|
1086
|
+
}
|
|
1087
|
+
const bumpedRuns = new Set();
|
|
1088
|
+
for (const [id] of preview) {
|
|
1089
|
+
const live = sceneApi.get(id);
|
|
1090
|
+
if (isCabinetRun(live)) {
|
|
1091
|
+
if (!bumpedRuns.has(live.id)) {
|
|
1092
|
+
bumpedRuns.add(live.id);
|
|
1093
|
+
bumpCabinetRunLayoutRevision(sceneApi, live);
|
|
1094
|
+
}
|
|
1095
|
+
continue;
|
|
1096
|
+
}
|
|
1097
|
+
const parent = live?.parentId ? sceneApi.get(live.parentId) : undefined;
|
|
1098
|
+
if (isCabinetRun(parent) && !bumpedRuns.has(parent.id)) {
|
|
1099
|
+
bumpedRuns.add(parent.id);
|
|
1100
|
+
bumpCabinetRunLayoutRevision(sceneApi, parent);
|
|
1101
|
+
}
|
|
1102
|
+
else if (isCabinetModule(parent)) {
|
|
1103
|
+
sceneApi.markDirty(parent.id);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
function cabinetWallDepthBounds(targets, sceneApi, adjustCornerWidths, widthMode, cornerIndex) {
|
|
1108
|
+
const liveTargets = targets.map((target) => sceneApi.get(target.id) ?? target);
|
|
1109
|
+
const currentDepth = liveTargets[0]?.depth ?? MIN_CABINET_DEPTH;
|
|
1110
|
+
const sharedBounds = sharedDepthBounds(currentDepth, liveTargets, sceneApi.nodes());
|
|
1111
|
+
let min = sharedBounds.min;
|
|
1112
|
+
let max = sharedBounds.max;
|
|
1113
|
+
if (!adjustCornerWidths)
|
|
1114
|
+
return { min, max };
|
|
1115
|
+
const baselineAdjustments = new Map(wallCornerWidthOverridesForDepthTargets({
|
|
1116
|
+
clampWidths: false,
|
|
1117
|
+
cornerIndex,
|
|
1118
|
+
depth: currentDepth,
|
|
1119
|
+
nodes: sceneApi.nodes(),
|
|
1120
|
+
targets: liveTargets,
|
|
1121
|
+
widthMode,
|
|
1122
|
+
}));
|
|
1123
|
+
const unitAdjustments = wallCornerWidthOverridesForDepthTargets({
|
|
1124
|
+
clampWidths: false,
|
|
1125
|
+
cornerIndex,
|
|
1126
|
+
depth: currentDepth + 1,
|
|
1127
|
+
nodes: sceneApi.nodes(),
|
|
1128
|
+
targets: liveTargets,
|
|
1129
|
+
widthMode,
|
|
1130
|
+
});
|
|
1131
|
+
for (const [id, patch] of unitAdjustments) {
|
|
1132
|
+
const cabinetPatch = patch;
|
|
1133
|
+
if (typeof cabinetPatch.width !== 'number')
|
|
1134
|
+
continue;
|
|
1135
|
+
const node = sceneApi.get(id);
|
|
1136
|
+
if (!isCabinetModule(node))
|
|
1137
|
+
continue;
|
|
1138
|
+
const baselinePatch = baselineAdjustments.get(id);
|
|
1139
|
+
const baselineWidth = typeof baselinePatch?.width === 'number' ? baselinePatch.width : node.width;
|
|
1140
|
+
const factor = cabinetPatch.width - baselineWidth;
|
|
1141
|
+
if (Math.abs(factor) <= CABINET_ADJACENCY_EPSILON)
|
|
1142
|
+
continue;
|
|
1143
|
+
const minWidth = node.name === 'Wall Bridge Filler'
|
|
1144
|
+
? 0
|
|
1145
|
+
: node.name?.includes('Filler')
|
|
1146
|
+
? 0.05
|
|
1147
|
+
: MIN_CABINET_WIDTH;
|
|
1148
|
+
const maxWidth = cabinetResizeUpperBound(baselineWidth, MAX_CABINET_WIDTH);
|
|
1149
|
+
const firstDepth = currentDepth + (minWidth - baselineWidth) / factor;
|
|
1150
|
+
const secondDepth = currentDepth + (maxWidth - baselineWidth) / factor;
|
|
1151
|
+
min = Math.max(min, Math.min(firstDepth, secondDepth));
|
|
1152
|
+
max = Math.min(max, Math.max(firstDepth, secondDepth));
|
|
1153
|
+
}
|
|
1154
|
+
return {
|
|
1155
|
+
min: Math.min(currentDepth, min),
|
|
1156
|
+
max: Math.max(currentDepth, max),
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
function cabinetWallGroupDepthHandles(selected, sceneApi) {
|
|
1160
|
+
const targets = cabinetWallTargets(selected, sceneApi);
|
|
1161
|
+
if (targets.length < 2)
|
|
1162
|
+
return [];
|
|
1163
|
+
const cornerIndex = buildWallCornerDepthIndex(sceneApi.nodes());
|
|
1164
|
+
const groups = [];
|
|
1165
|
+
for (const target of targets) {
|
|
1166
|
+
const rotation = cabinetDuplicateWorldPose(target, sceneApi.nodes())?.rotation ?? target.rotation;
|
|
1167
|
+
const group = groups.find((candidate) => Math.abs(Math.atan2(Math.sin(rotation - candidate.rotation), Math.cos(rotation - candidate.rotation))) < 1e-3);
|
|
1168
|
+
if (group)
|
|
1169
|
+
group.targets.push(target);
|
|
1170
|
+
else
|
|
1171
|
+
groups.push({ rotation, targets: [target] });
|
|
1172
|
+
}
|
|
1173
|
+
const selectedRotation = cabinetDuplicateWorldPose(selected, sceneApi.nodes())?.rotation ?? 0;
|
|
1174
|
+
return groups.map((group) => {
|
|
1175
|
+
const representative = group.targets[0];
|
|
1176
|
+
const relativeRotation = group.rotation - selectedRotation;
|
|
1177
|
+
const frontX = Math.sin(relativeRotation);
|
|
1178
|
+
const frontZ = Math.cos(relativeRotation);
|
|
1179
|
+
const axis = Math.abs(frontX) > Math.abs(frontZ) ? 'x' : 'z';
|
|
1180
|
+
const positive = axis === 'x' ? frontX >= 0 : frontZ >= 0;
|
|
1181
|
+
const adjustCornerWidths = true;
|
|
1182
|
+
const widthMode = Math.abs(frontX) < 1e-3 && frontZ > 0 ? 'corner-pair' : 'bridge';
|
|
1183
|
+
const depthBounds = () => cabinetWallDepthBounds(group.targets, sceneApi, adjustCornerWidths, widthMode, cornerIndex);
|
|
1184
|
+
const clampedDepth = (requestedDepth, liveSceneApi) => {
|
|
1185
|
+
const bounds = cabinetWallDepthBounds(group.targets, liveSceneApi, adjustCornerWidths, widthMode, cornerIndex);
|
|
1186
|
+
return Math.min(bounds.max, Math.max(bounds.min, requestedDepth));
|
|
1187
|
+
};
|
|
1188
|
+
return {
|
|
1189
|
+
kind: 'linear-resize',
|
|
1190
|
+
axis,
|
|
1191
|
+
anchor: positive ? 'min' : 'max',
|
|
1192
|
+
min: () => depthBounds().min,
|
|
1193
|
+
max: () => depthBounds().max,
|
|
1194
|
+
currentValue: () => sceneApi.get(representative.id)?.depth ??
|
|
1195
|
+
representative.depth,
|
|
1196
|
+
overrideTarget: () => representative.id,
|
|
1197
|
+
apply: (_node, depth) => ({ depth }),
|
|
1198
|
+
previewOverrides: (_node, depth, liveSceneApi) => cabinetWallDepthPreview(group.targets, clampedDepth(depth, liveSceneApi), liveSceneApi, adjustCornerWidths, widthMode, cornerIndex),
|
|
1199
|
+
commit: (_node, patch, liveSceneApi) => {
|
|
1200
|
+
if (typeof patch.depth === 'number') {
|
|
1201
|
+
commitCabinetWallDepth(group.targets, clampedDepth(patch.depth, liveSceneApi), liveSceneApi, adjustCornerWidths, widthMode, cornerIndex);
|
|
1202
|
+
}
|
|
1203
|
+
},
|
|
1204
|
+
placement: {
|
|
1205
|
+
position: (node, liveSceneApi) => {
|
|
1206
|
+
const points = group.targets.map((target) => {
|
|
1207
|
+
const liveTarget = liveSceneApi.get(target.id) ?? target;
|
|
1208
|
+
const point = isCabinetRun(liveTarget)
|
|
1209
|
+
? cabinetRunFrontCenter(liveTarget, liveSceneApi)
|
|
1210
|
+
: [
|
|
1211
|
+
0,
|
|
1212
|
+
cabinetTotalHeight(liveTarget) / 2,
|
|
1213
|
+
liveTarget.depth / 2 + SIDE_HANDLE_OFFSET,
|
|
1214
|
+
];
|
|
1215
|
+
return cabinetRunPointInSelectedFrame(node, liveTarget, point, liveSceneApi);
|
|
1216
|
+
});
|
|
1217
|
+
return [
|
|
1218
|
+
points.reduce((sum, point) => sum + point[0], 0) / points.length,
|
|
1219
|
+
points.reduce((sum, point) => sum + point[1], 0) / points.length,
|
|
1220
|
+
points.reduce((sum, point) => sum + point[2], 0) / points.length,
|
|
1221
|
+
];
|
|
1222
|
+
},
|
|
1223
|
+
rotationY: () => (axis === 'x' ? relativeRotation - Math.PI / 2 : relativeRotation),
|
|
1224
|
+
},
|
|
1225
|
+
};
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
function cabinetConnectedRunDepthHandle(selected, target, sceneApi) {
|
|
1229
|
+
const nodes = sceneApi.nodes();
|
|
1230
|
+
const selectedWorld = cabinetDuplicateWorldPose(selected, nodes);
|
|
1231
|
+
const targetWorld = cabinetDuplicateWorldPose(target, nodes);
|
|
1232
|
+
const relativeRotation = (targetWorld?.rotation ?? 0) - (selectedWorld?.rotation ?? 0);
|
|
1233
|
+
const frontX = Math.sin(relativeRotation);
|
|
1234
|
+
const frontZ = Math.cos(relativeRotation);
|
|
1235
|
+
const axis = Math.abs(frontX) > Math.abs(frontZ) ? 'x' : 'z';
|
|
1236
|
+
const positive = axis === 'x' ? frontX >= 0 : frontZ >= 0;
|
|
1237
|
+
const targetDepthBounds = (liveSceneApi) => {
|
|
1238
|
+
const liveTarget = liveSceneApi.get(target.id) ?? target;
|
|
1239
|
+
const compensatedWidths = [];
|
|
1240
|
+
const derived = cabinetMetadataRecord(liveTarget.metadata).cabinetCornerDerivedRun;
|
|
1241
|
+
if (derived && typeof derived === 'object' && !Array.isArray(derived)) {
|
|
1242
|
+
const role = derived.role;
|
|
1243
|
+
const side = derived.side;
|
|
1244
|
+
const turnSide = derived.turnSide;
|
|
1245
|
+
const sourceModuleId = derived.sourceModuleId;
|
|
1246
|
+
const sourceModule = role === 'base-leg' &&
|
|
1247
|
+
(turnSide === side || (turnSide !== 'left' && turnSide !== 'right')) &&
|
|
1248
|
+
typeof sourceModuleId === 'string'
|
|
1249
|
+
? liveSceneApi.get(sourceModuleId)
|
|
1250
|
+
: undefined;
|
|
1251
|
+
if (sourceModule?.type === 'cabinet-module') {
|
|
1252
|
+
compensatedWidths.push(sourceModule.width);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
for (const childId of liveTarget.children ?? []) {
|
|
1256
|
+
const child = liveSceneApi.get(childId);
|
|
1257
|
+
if (child?.type !== 'cabinet')
|
|
1258
|
+
continue;
|
|
1259
|
+
const childDerived = cabinetMetadataRecord(child.metadata).cabinetCornerDerivedRun;
|
|
1260
|
+
if (!childDerived || typeof childDerived !== 'object' || Array.isArray(childDerived))
|
|
1261
|
+
continue;
|
|
1262
|
+
if (childDerived.role !== 'base-leg' ||
|
|
1263
|
+
childDerived.sourceRunId !== target.id) {
|
|
1264
|
+
continue;
|
|
1265
|
+
}
|
|
1266
|
+
const connectedModule = cabinetModulesForRun(child, liveSceneApi.nodes()).find((module) => module.name === 'Base Cabinet');
|
|
1267
|
+
if (connectedModule)
|
|
1268
|
+
compensatedWidths.push(connectedModule.width);
|
|
1269
|
+
}
|
|
1270
|
+
const connectedBounds = cabinetConnectedDepthBounds(liveTarget.depth, compensatedWidths);
|
|
1271
|
+
const deltaBounds = sharedDepthBounds(liveTarget.depth, [liveTarget], liveSceneApi.nodes());
|
|
1272
|
+
return {
|
|
1273
|
+
min: Math.max(connectedBounds.min, deltaBounds.min),
|
|
1274
|
+
max: Math.min(connectedBounds.max, deltaBounds.max),
|
|
1275
|
+
};
|
|
1276
|
+
};
|
|
1277
|
+
const clampedDepth = (depth, liveSceneApi) => {
|
|
1278
|
+
const bounds = targetDepthBounds(liveSceneApi);
|
|
1279
|
+
return Math.min(bounds.max, Math.max(bounds.min, depth));
|
|
1280
|
+
};
|
|
1281
|
+
return {
|
|
1282
|
+
kind: 'linear-resize',
|
|
1283
|
+
axis,
|
|
1284
|
+
anchor: positive ? 'min' : 'max',
|
|
1285
|
+
min: (_node, liveSceneApi) => targetDepthBounds(liveSceneApi).min,
|
|
1286
|
+
max: (_node, liveSceneApi) => targetDepthBounds(liveSceneApi).max,
|
|
1287
|
+
currentValue: (node) => node.id === target.id
|
|
1288
|
+
? node.depth
|
|
1289
|
+
: (sceneApi.get(target.id)?.depth ?? target.depth),
|
|
1290
|
+
overrideTarget: () => target.id,
|
|
1291
|
+
apply: (_node, depth) => ({ depth }),
|
|
1292
|
+
previewOverrides: (_node, depth, liveSceneApi) => {
|
|
1293
|
+
const liveTarget = liveSceneApi.get(target.id) ?? target;
|
|
1294
|
+
const nextDepth = clampedDepth(depth, liveSceneApi);
|
|
1295
|
+
const moduleOverrides = depthDeltaRunOverrides(liveTarget, liveSceneApi.nodes(), nextDepth - liveTarget.depth);
|
|
1296
|
+
const sourceOverrides = cornerSourceWidthOverridesForDerivedDepth(liveTarget, liveSceneApi.nodes(), nextDepth);
|
|
1297
|
+
return previewCornerRunsFromRunSources({
|
|
1298
|
+
baseLayout: 'width-only',
|
|
1299
|
+
initialOverrides: [...moduleOverrides, ...sourceOverrides],
|
|
1300
|
+
run: { ...liveTarget, depth: nextDepth },
|
|
1301
|
+
sceneApi: liveSceneApi,
|
|
1302
|
+
});
|
|
1303
|
+
},
|
|
1304
|
+
commit: (_node, patch, liveSceneApi) => {
|
|
1305
|
+
if (typeof patch.depth !== 'number')
|
|
1306
|
+
return;
|
|
1307
|
+
const liveTarget = liveSceneApi.get(target.id) ?? target;
|
|
1308
|
+
const nextDepth = clampedDepth(patch.depth, liveSceneApi);
|
|
1309
|
+
for (const [id, sourcePatch] of cornerSourceWidthOverridesForDerivedDepth(liveTarget, liveSceneApi.nodes(), nextDepth)) {
|
|
1310
|
+
liveSceneApi.update(id, sourcePatch);
|
|
1311
|
+
}
|
|
1312
|
+
commitRunDepthDelta(liveTarget, nextDepth, liveSceneApi, {
|
|
1313
|
+
cornerSync: 'width-only',
|
|
1314
|
+
});
|
|
1315
|
+
},
|
|
1316
|
+
placement: {
|
|
1317
|
+
position: (node, liveSceneApi) => {
|
|
1318
|
+
const liveTarget = liveSceneApi.get(target.id) ?? target;
|
|
1319
|
+
return cabinetRunPointInSelectedFrame(node, liveTarget, cabinetRunFrontCenter(liveTarget, liveSceneApi), liveSceneApi);
|
|
1320
|
+
},
|
|
1321
|
+
rotationY: () => (axis === 'x' ? relativeRotation - Math.PI / 2 : relativeRotation),
|
|
1322
|
+
},
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
600
1325
|
function cabinetHeightHandle() {
|
|
601
1326
|
return {
|
|
602
1327
|
kind: 'linear-resize',
|
|
@@ -655,9 +1380,18 @@ function cabinetRotateHandle() {
|
|
|
655
1380
|
},
|
|
656
1381
|
};
|
|
657
1382
|
}
|
|
658
|
-
function cabinetHandles(node) {
|
|
1383
|
+
function cabinetHandles(node, sceneApi) {
|
|
659
1384
|
if ((node.children ?? []).length > 0) {
|
|
660
|
-
|
|
1385
|
+
const connectedRuns = sceneApi && node.runTier === 'base' ? connectedBaseRuns(node, sceneApi) : [];
|
|
1386
|
+
const depthHandles = sceneApi
|
|
1387
|
+
? connectedRuns.map((run) => cabinetConnectedRunDepthHandle(node, run, sceneApi))
|
|
1388
|
+
: [];
|
|
1389
|
+
const wallDepthHandles = sceneApi ? cabinetWallGroupDepthHandles(node, sceneApi) : [];
|
|
1390
|
+
return [
|
|
1391
|
+
...depthHandles,
|
|
1392
|
+
...wallDepthHandles,
|
|
1393
|
+
cabinetRotateHandle(),
|
|
1394
|
+
];
|
|
661
1395
|
}
|
|
662
1396
|
const handles = [
|
|
663
1397
|
cabinetDepthHandle(),
|
|
@@ -673,16 +1407,21 @@ function isHoodOnlyCabinet(node) {
|
|
|
673
1407
|
const stack = stackForCabinet(node);
|
|
674
1408
|
return stack.length > 0 && stack.every((compartment) => isHoodCompartmentType(compartment.type));
|
|
675
1409
|
}
|
|
676
|
-
function cabinetModuleHandles(
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1410
|
+
function cabinetModuleHandles() {
|
|
1411
|
+
return [
|
|
1412
|
+
{
|
|
1413
|
+
...cabinetWidthHandle('left'),
|
|
1414
|
+
visible: (node, sceneApi) => !isCabinetWidthFiller(node) && !cabinetModuleSideHasCornerFiller(node, 'left', sceneApi),
|
|
1415
|
+
},
|
|
1416
|
+
{
|
|
1417
|
+
...cabinetWidthHandle('right'),
|
|
1418
|
+
visible: (node, sceneApi) => !isCabinetWidthFiller(node) && !cabinetModuleSideHasCornerFiller(node, 'right', sceneApi),
|
|
1419
|
+
},
|
|
1420
|
+
{
|
|
1421
|
+
...cabinetDepthHandle(),
|
|
1422
|
+
visible: (node) => !isCabinetWidthFiller(node),
|
|
1423
|
+
},
|
|
681
1424
|
];
|
|
682
|
-
if (!isHoodOnlyCabinet(node)) {
|
|
683
|
-
handles.splice(1, 0, cabinetDepthHandle(), cabinetHeightHandle());
|
|
684
|
-
}
|
|
685
|
-
return handles;
|
|
686
1425
|
}
|
|
687
1426
|
export const cabinetDefinition = {
|
|
688
1427
|
kind: 'cabinet',
|
|
@@ -701,8 +1440,8 @@ export const cabinetDefinition = {
|
|
|
701
1440
|
rotation: 0,
|
|
702
1441
|
runTier: 'base',
|
|
703
1442
|
children: [],
|
|
704
|
-
width: 0.
|
|
705
|
-
depth: 0.
|
|
1443
|
+
width: 0.5,
|
|
1444
|
+
depth: 0.5,
|
|
706
1445
|
carcassHeight: 0.72,
|
|
707
1446
|
operationState: 0,
|
|
708
1447
|
plinthHeight: 0.1,
|
|
@@ -814,6 +1553,7 @@ export const cabinetDefinition = {
|
|
|
814
1553
|
floorplan: buildCabinetFloorplan,
|
|
815
1554
|
floorplanSiblingOverrides: cabinetFloorplanSiblingOverrides,
|
|
816
1555
|
floorplanAffectedIds: cabinetFloorplanAffectedIds,
|
|
1556
|
+
quickActionNodeScope: 'level',
|
|
817
1557
|
quickActions: cabinetQuickActions,
|
|
818
1558
|
// Corner-derived leg runs hide their own tree rows; their modules are
|
|
819
1559
|
// flattened into the source run's hierarchy.
|
|
@@ -876,8 +1616,8 @@ export const cabinetModuleDefinition = {
|
|
|
876
1616
|
rotation: 0,
|
|
877
1617
|
children: [],
|
|
878
1618
|
cabinetType: 'base',
|
|
879
|
-
width: 0.
|
|
880
|
-
depth: 0.
|
|
1619
|
+
width: 0.5,
|
|
1620
|
+
depth: 0.5,
|
|
881
1621
|
carcassHeight: 0.72,
|
|
882
1622
|
operationState: 0,
|
|
883
1623
|
plinthHeight: 0,
|
|
@@ -932,13 +1672,9 @@ export const cabinetModuleDefinition = {
|
|
|
932
1672
|
},
|
|
933
1673
|
collides: true,
|
|
934
1674
|
},
|
|
935
|
-
dragBounds: (node) => {
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
return {
|
|
939
|
-
size: [n.width, height, n.depth],
|
|
940
|
-
center: [0, height / 2, 0],
|
|
941
|
-
};
|
|
1675
|
+
dragBounds: (node, nodes) => {
|
|
1676
|
+
const bounds = cabinetLocalBounds(node, nodes);
|
|
1677
|
+
return { size: bounds.size, center: bounds.center };
|
|
942
1678
|
},
|
|
943
1679
|
paint: cabinetPaint,
|
|
944
1680
|
sceneAction: cabinetSceneAction,
|
|
@@ -983,6 +1719,7 @@ export const cabinetModuleDefinition = {
|
|
|
983
1719
|
// 2D ↔ 3D parity: module position is run-local, so the generic overlay's
|
|
984
1720
|
// plan-space translate would corrupt it on any rotated / offset run.
|
|
985
1721
|
floorplanMoveTarget: cabinetModuleFloorplanMoveTarget,
|
|
1722
|
+
quickActionNodeScope: 'level',
|
|
986
1723
|
quickActions: cabinetQuickActions,
|
|
987
1724
|
tree: {
|
|
988
1725
|
label: cabinetTreeLabel,
|