@pascal-app/nodes 0.1.1 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +67 -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 +9 -1
- package/dist/fence/lift.d.ts +15 -0
- package/dist/fence/lift.d.ts.map +1 -0
- package/dist/fence/lift.js +23 -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 +41 -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { resolveLevelId, useLiveNodeOverrides, useScene } from '@pascal-app/core';
|
|
3
|
+
import { resolveCeilingHeight, resolveLevelId, useLiveNodeOverrides, useScene, } from '@pascal-app/core';
|
|
4
4
|
import { PolygonEditor } from '@pascal-app/editor';
|
|
5
5
|
import { useViewer } from '@pascal-app/viewer';
|
|
6
6
|
import { useCallback, useEffect } from 'react';
|
|
@@ -40,6 +40,6 @@ export const CeilingHoleEditor = ({ ceilingId, holeIndex }) => {
|
|
|
40
40
|
}, [ceilingId]);
|
|
41
41
|
if (!(ceiling && hole) || hole.length < 3)
|
|
42
42
|
return null;
|
|
43
|
-
return (_jsx(PolygonEditor, { allowEdgeMove: true, allowPolygonMove: true, color: "#ef4444", levelId: resolveLevelId(ceiling, useScene.getState().nodes), minVertices: 3, onPolygonChange: handlePolygonChange, onPolygonPreview: handlePolygonPreview, polygon: hole, surfaceHeight: ceiling
|
|
43
|
+
return (_jsx(PolygonEditor, { allowEdgeMove: true, allowPolygonMove: true, color: "#ef4444", levelId: resolveLevelId(ceiling, useScene.getState().nodes), minVertices: 3, onPolygonChange: handlePolygonChange, onPolygonPreview: handlePolygonPreview, polygon: hole, surfaceHeight: resolveCeilingHeight(ceiling, useScene.getState().nodes) }));
|
|
44
44
|
};
|
|
45
45
|
export default CeilingHoleEditor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/ceiling/move-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,WAAW,
|
|
1
|
+
{"version":3,"file":"move-tool.d.ts","sourceRoot":"","sources":["../../src/ceiling/move-tool.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,WAAW,EAWjB,MAAM,kBAAkB,CAAA;AAgFzB,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAwK3D,CAAA;AAiHD,eAAe,eAAe,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { collectAlignmentAnchors, emitter, polygonAnchors, resolveAlignment, sceneRegistry, snapScalar, useLiveTransforms, useScene, } from '@pascal-app/core';
|
|
3
|
+
import { collectAlignmentAnchors, emitter, polygonAnchors, resolveAlignment, resolveCeilingHeight, sceneRegistry, snapScalar, useLiveTransforms, useScene, } from '@pascal-app/core';
|
|
4
4
|
import { CursorSphere, consumePlacementDragRelease, isAlignmentGuideActive, isMagneticSnapActive, markToolCancelConsumed, triggerSFX, useAlignmentGuides, useEditor, } from '@pascal-app/editor';
|
|
5
5
|
import { useViewer } from '@pascal-app/viewer';
|
|
6
6
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
@@ -65,7 +65,8 @@ export const MoveCeilingTool = ({ node }) => {
|
|
|
65
65
|
const originalPolygonRef = useRef(node.polygon.map(([x, z]) => [x, z]));
|
|
66
66
|
const originalHolesRef = useRef((node.holes ?? []).map((hole) => hole.map(([x, z]) => [x, z])));
|
|
67
67
|
const originalCenterRef = useRef(getPolygonCenter(originalPolygonRef.current));
|
|
68
|
-
|
|
68
|
+
// Resolved once at drag start — the ceiling plane can't change mid-move.
|
|
69
|
+
const heightRef = useRef(resolveCeilingHeight(node, useScene.getState().nodes));
|
|
69
70
|
const dragAnchorRef = useRef(null);
|
|
70
71
|
const previousGridPosRef = useRef(null);
|
|
71
72
|
const deltaRef = useRef([0, 0]);
|
|
@@ -198,7 +199,7 @@ export const MoveCeilingTool = ({ node }) => {
|
|
|
198
199
|
window.removeEventListener('pointerup', onPlacementDragPointerUp);
|
|
199
200
|
};
|
|
200
201
|
}, [exitMoveMode, node.id]);
|
|
201
|
-
return (_jsx(CeilingMovePreview, { ceilingId: node.id, cursorLocalPos: cursorLocalPos, height:
|
|
202
|
+
return (_jsx(CeilingMovePreview, { ceilingId: node.id, cursorLocalPos: cursorLocalPos, height: heightRef.current, originalHoles: originalHolesRef.current, originalPolygon: originalPolygonRef.current }));
|
|
202
203
|
};
|
|
203
204
|
/**
|
|
204
205
|
* Translucent fill + bright outline showing where the ceiling will land
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/ceiling/panel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../src/ceiling/panel.tsx"],"names":[],"mappings":"AA2BA;;;;;;;GAOG;AACH,wBAAgB,YAAY,uCA0V3B;AAED,eAAe,YAAY,CAAA"}
|
package/dist/ceiling/panel.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useScene } from '@pascal-app/core';
|
|
4
|
-
import { ActionButton, ActionGroup, holeEditScope, PanelSection, PanelWrapper, SliderControl, triggerSFX, useEditingHole, useEditor, useInteractionScope, } from '@pascal-app/editor';
|
|
3
|
+
import { getCeilingClampBound, resolveCeilingHeight, useScene, } from '@pascal-app/core';
|
|
4
|
+
import { ActionButton, ActionGroup, formatLinearMeasurement, holeEditScope, PanelSection, PanelWrapper, SegmentedControl, SliderControl, triggerSFX, useEditingHole, useEditor, useInteractionScope, } from '@pascal-app/editor';
|
|
5
5
|
import { useViewer } from '@pascal-app/viewer';
|
|
6
6
|
import { Edit, Move, Plus, Trash2 } from 'lucide-react';
|
|
7
7
|
import { useCallback, useEffect, useRef } from 'react';
|
|
@@ -15,19 +15,64 @@ import { useCallback, useEffect, useRef } from 'react';
|
|
|
15
15
|
*/
|
|
16
16
|
export function CeilingPanel() {
|
|
17
17
|
const selectedId = useViewer((s) => s.selection.selectedIds[0]);
|
|
18
|
+
const unit = useViewer((s) => s.unit);
|
|
18
19
|
const setSelection = useViewer((s) => s.setSelection);
|
|
19
20
|
const editingHole = useEditingHole();
|
|
20
21
|
const setMovingNode = useEditor((s) => s.setMovingNode);
|
|
21
22
|
const node = useScene((s) => selectedId ? s.nodes[selectedId] : undefined);
|
|
23
|
+
// Ceilings no longer drive the storey height — the stored level height
|
|
24
|
+
// does — so height writes clamp under min(storey plane, lowest covering
|
|
25
|
+
// slab underside from the level above) − margin instead of poking into
|
|
26
|
+
// the level above or a deck hanging from it (clamp, never ask).
|
|
27
|
+
// Selector returns a primitive, so recomputing per store update is
|
|
28
|
+
// re-render-safe.
|
|
29
|
+
const maxHeight = useScene((s) => {
|
|
30
|
+
const parent = node?.parentId ? s.nodes[node.parentId] : undefined;
|
|
31
|
+
return parent?.type === 'level'
|
|
32
|
+
? getCeilingClampBound(parent.id, s.nodes, node?.polygon ?? [])
|
|
33
|
+
: 6;
|
|
34
|
+
});
|
|
35
|
+
// Effective height: the stored custom height, or — for follows-mode
|
|
36
|
+
// ceilings (absent `height`) — the live level-top bound. Primitive
|
|
37
|
+
// selector so it tracks level-height / covering-slab edits.
|
|
38
|
+
const resolvedHeight = useScene((s) => {
|
|
39
|
+
const ceiling = selectedId
|
|
40
|
+
? s.nodes[selectedId]
|
|
41
|
+
: undefined;
|
|
42
|
+
return ceiling?.type === 'ceiling' ? resolveCeilingHeight(ceiling, s.nodes) : 2.5;
|
|
43
|
+
});
|
|
22
44
|
// Panel slider-drag fix recipe (plans/editor-node-registry.md): stable
|
|
23
45
|
// handler refs so slider drags don't trigger Maximum update depth.
|
|
24
46
|
const nodeRef = useRef(node);
|
|
25
47
|
nodeRef.current = node;
|
|
48
|
+
const maxHeightRef = useRef(maxHeight);
|
|
49
|
+
maxHeightRef.current = maxHeight;
|
|
50
|
+
const resolvedHeightRef = useRef(resolvedHeight);
|
|
51
|
+
resolvedHeightRef.current = resolvedHeight;
|
|
26
52
|
const handleUpdate = useCallback((updates) => {
|
|
27
53
|
if (!selectedId)
|
|
28
54
|
return;
|
|
29
55
|
useScene.getState().updateNode(selectedId, updates);
|
|
30
56
|
}, [selectedId]);
|
|
57
|
+
const handleHeightChange = useCallback((proposed) => {
|
|
58
|
+
handleUpdate({ height: Math.min(proposed, maxHeightRef.current) });
|
|
59
|
+
}, [handleUpdate]);
|
|
60
|
+
const handleTopModeChange = useCallback((mode) => {
|
|
61
|
+
const n = nodeRef.current;
|
|
62
|
+
if (!n)
|
|
63
|
+
return;
|
|
64
|
+
const isCustom = n.height != null;
|
|
65
|
+
if (mode === 'custom' && !isCustom) {
|
|
66
|
+
// Seed from the current resolved height so the surface doesn't
|
|
67
|
+
// jump at the moment of detaching from the level top.
|
|
68
|
+
handleUpdate({ height: Math.min(resolvedHeightRef.current, maxHeightRef.current) });
|
|
69
|
+
}
|
|
70
|
+
else if (mode === 'storey' && isCustom) {
|
|
71
|
+
// Absent `height` = follows the level top; the store strips
|
|
72
|
+
// undefined keys.
|
|
73
|
+
handleUpdate({ height: undefined });
|
|
74
|
+
}
|
|
75
|
+
}, [handleUpdate]);
|
|
31
76
|
const handleClose = useCallback(() => {
|
|
32
77
|
setSelection({ selectedIds: [] });
|
|
33
78
|
useInteractionScope
|
|
@@ -122,7 +167,24 @@ export function CeilingPanel() {
|
|
|
122
167
|
return Math.abs(area) / 2;
|
|
123
168
|
};
|
|
124
169
|
const area = calculateArea(node.polygon);
|
|
125
|
-
|
|
170
|
+
const isFollows = node.height == null;
|
|
171
|
+
// Clean preset values per display system; imperial stores exact meters
|
|
172
|
+
// for 8'0" / 8'6" / 9'0" ceilings.
|
|
173
|
+
const heightPresets = unit === 'imperial'
|
|
174
|
+
? [
|
|
175
|
+
{ label: 'Low (8\'0")', height: 2.4384 },
|
|
176
|
+
{ label: 'Standard (8\'6")', height: 2.5908 },
|
|
177
|
+
{ label: 'High (9\'0")', height: 2.7432 },
|
|
178
|
+
]
|
|
179
|
+
: [
|
|
180
|
+
{ label: 'Low (2.4m)', height: 2.4 },
|
|
181
|
+
{ label: 'Standard (2.5m)', height: 2.5 },
|
|
182
|
+
{ label: 'High (3.0m)', height: 3.0 },
|
|
183
|
+
];
|
|
184
|
+
return (_jsxs(PanelWrapper, { icon: "/icons/ceiling.webp", onClose: handleClose, title: node.name || 'Ceiling', width: 320, children: [_jsxs(PanelSection, { title: "Height", children: [_jsx(SegmentedControl, { onChange: handleTopModeChange, options: [
|
|
185
|
+
{ label: 'Follows level', value: 'storey' },
|
|
186
|
+
{ label: 'Custom height', value: 'custom' },
|
|
187
|
+
], value: isFollows ? 'storey' : 'custom' }), isFollows ? (_jsxs("div", { className: "px-1 text-[11px] text-muted-foreground", children: ["Currently ", formatLinearMeasurement(resolvedHeight, unit)] })) : (_jsx(SliderControl, { label: "Height", max: Math.min(6, maxHeight), min: 0, onChange: handleHeightChange, precision: 3, step: 0.01, unit: "m", value: Math.round((node.height ?? resolvedHeight) * 1000) / 1000 })), _jsx("div", { className: "mt-2 grid grid-cols-3 gap-1.5 px-1 pb-1", children: heightPresets.map((preset) => (_jsx(ActionButton, { label: preset.label, onClick: () => handleHeightChange(preset.height) }, preset.label))) })] }), _jsx(PanelSection, { title: "Info", children: _jsxs("div", { className: "flex items-center justify-between px-2 py-1 text-muted-foreground text-sm", children: [_jsx("span", { children: "Area" }), _jsxs("span", { className: "font-mono text-white", children: [area.toFixed(2), " m\u00B2"] })] }) }), _jsxs(PanelSection, { title: "Holes", children: [node.holes && node.holes.length > 0 ? (_jsx("div", { className: "flex flex-col gap-1 pb-2", children: node.holes.map((hole, index) => {
|
|
126
188
|
const holeArea = calculateArea(hole);
|
|
127
189
|
const isEditing = editingHole?.nodeId === selectedId && editingHole?.holeIndex === index;
|
|
128
190
|
const source = node.holeMetadata?.[index]?.source ?? 'manual';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/ceiling/renderer.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,WAAW,
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/ceiling/renderer.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,WAAW,EAOjB,MAAM,kBAAkB,CAAA;AAiBzB,eAAO,MAAM,eAAe,GAAI,UAAU;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,gCAwG9D,CAAA;AAED,eAAe,eAAe,CAAA"}
|
package/dist/ceiling/renderer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { getMaterialPresetByRef, resolveMaterial, useLiveTransforms, useRegistry, useScene, } from '@pascal-app/core';
|
|
3
|
+
import { getMaterialPresetByRef, resolveCeilingHeight, resolveMaterial, useLiveTransforms, useRegistry, useScene, } from '@pascal-app/core';
|
|
4
4
|
import { createSurfaceRoleMaterial, NodeRenderer, resolveSurfaceColor, useViewer, } from '@pascal-app/viewer';
|
|
5
5
|
import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
|
|
6
6
|
import { BackSide } from 'three/webgpu';
|
|
@@ -31,7 +31,11 @@ export const CeilingRenderer = ({ node }) => {
|
|
|
31
31
|
// ceiling slot references re-tints it live.
|
|
32
32
|
const sceneMaterials = useScene((s) => s.materials);
|
|
33
33
|
const liveTransform = useLiveTransforms((s) => s.get(node.id));
|
|
34
|
-
|
|
34
|
+
// Resolved height: explicit when stored, else the live level-top bound
|
|
35
|
+
// (primitive selector, so follows-mode ceilings track level-height edits
|
|
36
|
+
// and covering-slab changes without a node write).
|
|
37
|
+
const resolvedHeight = useScene((s) => resolveCeilingHeight(node, s.nodes));
|
|
38
|
+
const ceilingY = resolvedHeight - 0.01 + (liveTransform?.position[1] ?? 0);
|
|
35
39
|
const position = [
|
|
36
40
|
liveTransform?.position[0] ?? 0,
|
|
37
41
|
ceilingY,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/ceiling/tool.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/ceiling/tool.tsx"],"names":[],"mappings":"AAqDA,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAuW/B,CAAA;AAED,eAAe,WAAW,CAAA"}
|
package/dist/ceiling/tool.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { DEFAULT_ANGLE_STEP, emitter, snapPointAlongAngleRay, snapPointToGrid, useScene, } from '@pascal-app/core';
|
|
4
|
-
import { CursorSphere, clearCeilingSnapFeedback, EDITOR_LAYER, isAngleSnapActive, isGridSnapActive, markToolCancelConsumed, resolveCeilingPlanPointSnap, triggerSFX, useEditor, } from '@pascal-app/editor';
|
|
4
|
+
import { CursorSphere, clearCeilingSnapFeedback, EDITOR_LAYER, isAngleSnapActive, isGridSnapActive, markToolCancelConsumed, resolveCeilingPlanPointSnap, triggerSFX, useEditor, useFloorplanDraftPreview, } from '@pascal-app/editor';
|
|
5
5
|
import { useViewer } from '@pascal-app/viewer';
|
|
6
6
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
7
7
|
import { BufferGeometry, DoubleSide, Shape, Vector3 } from 'three';
|
|
@@ -52,6 +52,16 @@ export const CeilingTool = () => {
|
|
|
52
52
|
useEditor.getState().setDraftVertexCount(points.length);
|
|
53
53
|
}, [points.length]);
|
|
54
54
|
useEffect(() => () => useEditor.getState().setDraftVertexCount(0), []);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
useFloorplanDraftPreview.getState().setPolygonDraft('ceiling', points);
|
|
57
|
+
}, [points]);
|
|
58
|
+
useEffect(() => () => {
|
|
59
|
+
const draftPreview = useFloorplanDraftPreview.getState();
|
|
60
|
+
if (draftPreview.polygonDraftType === 'ceiling') {
|
|
61
|
+
draftPreview.setPolygonDraft(null, []);
|
|
62
|
+
}
|
|
63
|
+
draftPreview.setCursorPoint(null);
|
|
64
|
+
}, []);
|
|
55
65
|
const verticalGeo = useMemo(() => new BufferGeometry().setFromPoints([
|
|
56
66
|
new Vector3(0, 0, 0),
|
|
57
67
|
new Vector3(0, CEILING_HEIGHT - GRID_OFFSET, 0),
|
|
@@ -81,6 +91,7 @@ export const CeilingTool = () => {
|
|
|
81
91
|
fallbackPoint: orthoPoint,
|
|
82
92
|
levelId: currentLevelId,
|
|
83
93
|
}).point;
|
|
94
|
+
useFloorplanDraftPreview.getState().setCursorPoint(displayPoint);
|
|
84
95
|
setSnappedCursorPosition(displayPoint);
|
|
85
96
|
if (points.length > 0 &&
|
|
86
97
|
previousSnappedPointRef.current &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/chimney/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EAGpB,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAqUtC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,OAAO,WAAW,
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/chimney/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EAGpB,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAqUtC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,OAAO,WAAW,CAqEhE,CAAA"}
|
|
@@ -369,6 +369,7 @@ export const chimneyDefinition = {
|
|
|
369
369
|
kind: 'parametric',
|
|
370
370
|
module: () => import('./renderer'),
|
|
371
371
|
},
|
|
372
|
+
preview: () => import('./preview'),
|
|
372
373
|
tool: () => import('./tool'),
|
|
373
374
|
toolHints: [
|
|
374
375
|
{ key: 'Left click', label: 'Place chimney on roof' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/chimney/tool.tsx"],"names":[],"mappings":"AA4CA,QAAA,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/chimney/tool.tsx"],"names":[],"mappings":"AA4CA,QAAA,MAAM,WAAW,mCAwJhB,CAAA;AAED,eAAe,WAAW,CAAA"}
|
package/dist/chimney/tool.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { ChimneyNode, emitter, sceneRegistry, useScene, } from '@pascal-app/core';
|
|
4
|
-
import { triggerSFX } from '@pascal-app/editor';
|
|
4
|
+
import { triggerSFX, usePlacementPreview } from '@pascal-app/editor';
|
|
5
5
|
import { useViewer } from '@pascal-app/viewer';
|
|
6
6
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
7
7
|
import * as THREE from 'three';
|
|
@@ -79,6 +79,12 @@ const ChimneyTool = () => {
|
|
|
79
79
|
setSegmentXform(xform);
|
|
80
80
|
setHitLocal([hit.localX, hit.localY, hit.localZ]);
|
|
81
81
|
setPreviewSegment(hit.segment);
|
|
82
|
+
usePlacementPreview.getState().set(ChimneyNode.parse({
|
|
83
|
+
...previewNode,
|
|
84
|
+
parentId: hit.segment.id,
|
|
85
|
+
position: [hit.localX, hit.localY, hit.localZ],
|
|
86
|
+
roofSegmentId: hit.segment.id,
|
|
87
|
+
}), hit.segment);
|
|
82
88
|
publishRoofSurfacePlacementGuides({
|
|
83
89
|
roof: event.node,
|
|
84
90
|
segment: hit.segment,
|
|
@@ -103,6 +109,9 @@ const ChimneyTool = () => {
|
|
|
103
109
|
state.dirtyNodes.add(hit.segment.id);
|
|
104
110
|
setSelection({ selectedIds: [chimney.id] });
|
|
105
111
|
triggerSFX('sfx:item-place');
|
|
112
|
+
const placementPreview = usePlacementPreview.getState();
|
|
113
|
+
if (placementPreview.node?.id === previewNode.id)
|
|
114
|
+
placementPreview.clear();
|
|
106
115
|
clearRoofSurfacePlacementGuides();
|
|
107
116
|
event.stopPropagation();
|
|
108
117
|
};
|
|
@@ -113,6 +122,9 @@ const ChimneyTool = () => {
|
|
|
113
122
|
emitter.off('roof:move', updatePreview);
|
|
114
123
|
emitter.off('roof:enter', updatePreview);
|
|
115
124
|
emitter.off('roof:click', onClick);
|
|
125
|
+
const placementPreview = usePlacementPreview.getState();
|
|
126
|
+
if (placementPreview.node?.id === previewNode.id)
|
|
127
|
+
placementPreview.clear();
|
|
116
128
|
clearRoofSurfacePlacementGuides();
|
|
117
129
|
};
|
|
118
130
|
}, [activeBuildingId, setSelection, previewNode]);
|
|
@@ -120,6 +132,9 @@ const ChimneyTool = () => {
|
|
|
120
132
|
setSegmentXform(null);
|
|
121
133
|
setHitLocal(null);
|
|
122
134
|
setPreviewSegment(null);
|
|
135
|
+
const placementPreview = usePlacementPreview.getState();
|
|
136
|
+
if (placementPreview.node?.id === previewNode.id)
|
|
137
|
+
placementPreview.clear();
|
|
123
138
|
clearRoofSurfacePlacementGuides();
|
|
124
139
|
} }), activeBuildingId && segmentXform && hitLocal && previewSegment && (_jsx("group", { position: segmentXform.position, quaternion: segmentXform.quaternion, children: _jsx("group", { position: [hitLocal[0], 0, hitLocal[2]], children: _jsx(ChimneyPreview, { node: previewNode, segment: previewSegment }) }) }))] }));
|
|
125
140
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/column/definition.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/column/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAA;AAUzB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AA0SrC;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,OAAO,UAAU,CAgG9D,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ColumnNode as ColumnNodeSchema, } from '@pascal-app/core';
|
|
2
|
-
import {
|
|
2
|
+
import { collectStructuralGridAxes, resolveStructuralGridSnap, } from '../structural-grid/coordination';
|
|
3
|
+
import { buildColumnFloorplan, computeColumnFloorplanLevelData } from './floorplan';
|
|
3
4
|
import { columnResizeAffordance, columnRotateAffordance } from './floorplan-affordances';
|
|
4
5
|
import { columnFloorplanMoveTarget } from './floorplan-move';
|
|
5
6
|
import { columnPaint } from './paint';
|
|
@@ -272,6 +273,10 @@ function columnHandles(node) {
|
|
|
272
273
|
handles.push(columnRotateHandle(), columnMoveHandle());
|
|
273
274
|
return handles;
|
|
274
275
|
}
|
|
276
|
+
function resolveColumnStructuralGridMoveSnap({ candidatePosition, nodes, levelId, }) {
|
|
277
|
+
const snap = resolveStructuralGridSnap([candidatePosition[0], candidatePosition[2]], collectStructuralGridAxes(nodes, levelId));
|
|
278
|
+
return snap ? [snap.point[0], candidatePosition[1], snap.point[1]] : null;
|
|
279
|
+
}
|
|
275
280
|
/**
|
|
276
281
|
* Column — Stage A registration. Wrap-export of the legacy
|
|
277
282
|
* `ColumnRenderer` (no system — column geometry is computed inline in
|
|
@@ -309,7 +314,11 @@ export const columnDefinition = {
|
|
|
309
314
|
// Generic 3D translate-on-XZ via `MoveRegistryNodeTool` (grid snap + the
|
|
310
315
|
// mode-driven snapping the overhaul standardised). 2D move keeps using
|
|
311
316
|
// `floorplanMoveTarget`, which wins the 2D move dispatch.
|
|
312
|
-
movable: {
|
|
317
|
+
movable: {
|
|
318
|
+
axes: ['x', 'z'],
|
|
319
|
+
gridSnap: true,
|
|
320
|
+
groupMoveSnap: resolveColumnStructuralGridMoveSnap,
|
|
321
|
+
},
|
|
313
322
|
slots: (node) => columnSlots(node),
|
|
314
323
|
paint: columnPaint,
|
|
315
324
|
// Slab elevation lift via the generic `<FloorElevationSystem>` + the
|
|
@@ -337,6 +346,7 @@ export const columnDefinition = {
|
|
|
337
346
|
kind: 'parametric',
|
|
338
347
|
module: () => import('./renderer'),
|
|
339
348
|
},
|
|
349
|
+
preview: () => import('./renderer').then(({ ColumnPreview }) => ({ default: ColumnPreview })),
|
|
340
350
|
// Registry-driven placement tool — renders a translucent `ColumnPreview`
|
|
341
351
|
// ghost at the cursor (mirroring the shelf build tool) instead of the
|
|
342
352
|
// bare sphere the legacy editor-side `ColumnTool` showed. `ToolManager`'s
|
|
@@ -346,6 +356,8 @@ export const columnDefinition = {
|
|
|
346
356
|
{ key: 'Left click', label: 'Place column' },
|
|
347
357
|
{ key: 'Esc', label: 'Cancel' },
|
|
348
358
|
],
|
|
359
|
+
computeFloorplanLevelData: computeColumnFloorplanLevelData,
|
|
360
|
+
floorplanDependsOnSiblings: true,
|
|
349
361
|
floorplan: buildColumnFloorplan,
|
|
350
362
|
// 2D body move routes through this kind-specific target so the column
|
|
351
363
|
// aligns by its footprint *edges* (and snaps flush to wall faces) instead
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/column/floorplan-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"floorplan-affordances.d.ts","sourceRoot":"","sources":["../../src/column/floorplan-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,mBAAmB,EAGzB,MAAM,kBAAkB,CAAA;AAazB;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EACC,OAAO,GACP,OAAO,GACP,SAAS,GACT,QAAQ,GACR,aAAa,GACb,aAAa,GACb,qBAAqB,GACrB,kBAAkB,CAAA;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC3B,CAAA;AAED,eAAO,MAAM,sBAAsB,EAAE,mBAAmB,CAAC,UAAU,CAoFlE,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,EAAE,mBAAmB,CAAC,UAAU,CAgClE,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { useScene, } from '@pascal-app/core';
|
|
1
|
+
import { useLiveNodeOverrides, useScene, } from '@pascal-app/core';
|
|
2
|
+
import { isAngleSnapActive } from '@pascal-app/editor';
|
|
2
3
|
import { rotateAffordanceDelta } from '../shared/rotate-affordance';
|
|
3
4
|
// Floor minimums — mirror the 3D handles in `column/definition.ts` so a
|
|
4
5
|
// drag can't push a value past what the renderer accepts.
|
|
@@ -22,9 +23,10 @@ export const columnResizeAffordance = {
|
|
|
22
23
|
const initialBraceBottomSpread = node.braceBottomSpread ?? Math.max(node.width * 3, 1.2);
|
|
23
24
|
const initialBraceTopSpread = node.braceTopSpread ?? 0.12;
|
|
24
25
|
let lastPatch = {};
|
|
25
|
-
const
|
|
26
|
+
const previewPatch = (patch) => {
|
|
26
27
|
lastPatch = patch;
|
|
27
|
-
|
|
28
|
+
useLiveNodeOverrides.getState().set(columnId, patch);
|
|
29
|
+
useScene.getState().markDirty(columnId);
|
|
28
30
|
};
|
|
29
31
|
return {
|
|
30
32
|
affectedIds: [columnId],
|
|
@@ -33,42 +35,42 @@ export const columnResizeAffordance = {
|
|
|
33
35
|
const projDelta = currentProj - initialProj;
|
|
34
36
|
switch (dim) {
|
|
35
37
|
case 'width':
|
|
36
|
-
|
|
38
|
+
previewPatch({
|
|
37
39
|
width: Math.max(MIN_COLUMN_WIDTH, initialWidth + 2 * projDelta),
|
|
38
40
|
});
|
|
39
41
|
return;
|
|
40
42
|
case 'depth':
|
|
41
|
-
|
|
43
|
+
previewPatch({
|
|
42
44
|
depth: Math.max(MIN_COLUMN_DEPTH, initialDepth + 2 * projDelta),
|
|
43
45
|
});
|
|
44
46
|
return;
|
|
45
47
|
case 'uniform': {
|
|
46
48
|
const next = Math.max(MIN_COLUMN_WIDTH, initialWidth + 2 * projDelta);
|
|
47
|
-
|
|
49
|
+
previewPatch({ width: next, depth: next });
|
|
48
50
|
return;
|
|
49
51
|
}
|
|
50
52
|
case 'radius':
|
|
51
|
-
|
|
53
|
+
previewPatch({
|
|
52
54
|
radius: Math.max(MIN_COLUMN_RADIUS, initialRadius + projDelta),
|
|
53
55
|
});
|
|
54
56
|
return;
|
|
55
57
|
case 'brace-width':
|
|
56
|
-
|
|
58
|
+
previewPatch({
|
|
57
59
|
braceWidth: Math.max(MIN_BRACE_DIMENSION, initialBraceWidth + 2 * projDelta),
|
|
58
60
|
});
|
|
59
61
|
return;
|
|
60
62
|
case 'brace-depth':
|
|
61
|
-
|
|
63
|
+
previewPatch({
|
|
62
64
|
braceDepth: Math.max(MIN_BRACE_DIMENSION, initialBraceDepth + 2 * projDelta),
|
|
63
65
|
});
|
|
64
66
|
return;
|
|
65
67
|
case 'brace-bottom-spread':
|
|
66
|
-
|
|
68
|
+
previewPatch({
|
|
67
69
|
braceBottomSpread: Math.max(MIN_BRACE_BOTTOM_SPREAD, initialBraceBottomSpread + 2 * projDelta),
|
|
68
70
|
});
|
|
69
71
|
return;
|
|
70
72
|
case 'brace-top-spread':
|
|
71
|
-
|
|
73
|
+
previewPatch({
|
|
72
74
|
braceTopSpread: Math.max(MIN_BRACE_TOP_SPREAD, initialBraceTopSpread + 2 * projDelta),
|
|
73
75
|
});
|
|
74
76
|
return;
|
|
@@ -79,6 +81,7 @@ export const columnResizeAffordance = {
|
|
|
79
81
|
},
|
|
80
82
|
commit() {
|
|
81
83
|
if (Object.keys(lastPatch).length > 0) {
|
|
84
|
+
useLiveNodeOverrides.getState().clear(columnId);
|
|
82
85
|
useScene.getState().updateNode(columnId, lastPatch);
|
|
83
86
|
}
|
|
84
87
|
},
|
|
@@ -104,21 +107,23 @@ export const columnRotateAffordance = {
|
|
|
104
107
|
let lastRotation = initialRotation;
|
|
105
108
|
return {
|
|
106
109
|
affectedIds: [columnId],
|
|
107
|
-
apply({ planPoint
|
|
110
|
+
apply({ planPoint }) {
|
|
108
111
|
const delta = rotateAffordanceDelta({
|
|
109
112
|
center: [cx, cz],
|
|
110
113
|
initialAngle,
|
|
111
114
|
planPoint,
|
|
112
|
-
free:
|
|
115
|
+
free: !isAngleSnapActive(),
|
|
113
116
|
});
|
|
114
117
|
const newRotation = initialRotation - delta;
|
|
115
118
|
lastRotation = newRotation;
|
|
116
|
-
|
|
119
|
+
useLiveNodeOverrides.getState().set(columnId, { rotation: newRotation });
|
|
120
|
+
useScene.getState().markDirty(columnId);
|
|
117
121
|
},
|
|
118
122
|
canCommit() {
|
|
119
123
|
return true;
|
|
120
124
|
},
|
|
121
125
|
commit() {
|
|
126
|
+
useLiveNodeOverrides.getState().clear(columnId);
|
|
122
127
|
useScene.getState().updateNode(columnId, { rotation: lastRotation });
|
|
123
128
|
},
|
|
124
129
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floorplan-move.d.ts","sourceRoot":"","sources":["../../src/column/floorplan-move.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,UAAU,EAEf,KAAK,mBAAmB,EAMzB,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"floorplan-move.d.ts","sourceRoot":"","sources":["../../src/column/floorplan-move.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,UAAU,EAEf,KAAK,mBAAmB,EAMzB,MAAM,kBAAkB,CAAA;AAgBzB;;;;;;;GAOG;AAEH,eAAO,MAAM,yBAAyB,EAAE,mBAAmB,CAAC,UAAU,CAsErE,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { collectAlignmentAnchors, movingFootprintAnchors, sceneRegistry, useLiveTransforms, useScene, } from '@pascal-app/core';
|
|
2
2
|
import { applyFloorplanAlignment, getFloorStackPreviewPosition, isGridSnapActive, isMagneticSnapActive, triggerSFX, useEditor, } from '@pascal-app/editor';
|
|
3
3
|
import { createFloorplanCursorResolver } from '../shared/floorplan-cursor';
|
|
4
|
+
import { collectStructuralGridAxes, resolveStructuralGridSnap, } from '../structural-grid/coordination';
|
|
4
5
|
/**
|
|
5
6
|
* 2D floor-plan move handler for column. Columns need the same footprint-edge
|
|
6
7
|
* alignment as shelf / item, but they must preview through live transforms and
|
|
@@ -33,9 +34,13 @@ export const columnFloorplanMoveTarget = ({ node, nodes }) => {
|
|
|
33
34
|
const gridSnapped = resolveCursor(planPoint, { snap });
|
|
34
35
|
// Figma-style alignment layered on the active snap mode.
|
|
35
36
|
const { point: snapped } = applyFloorplanAlignment(gridSnapped, movingFootprintAnchors(node, gridSnapped[0], gridSnapped[1], rotationY), candidates, { applySnap: isMagneticSnapActive() });
|
|
36
|
-
const
|
|
37
|
+
const structuralSnap = isGridSnapActive() || isMagneticSnapActive()
|
|
38
|
+
? resolveStructuralGridSnap(snapped, collectStructuralGridAxes(nodes, node.parentId))
|
|
39
|
+
: null;
|
|
40
|
+
const coordinated = structuralSnap?.point ?? snapped;
|
|
41
|
+
const next = [coordinated[0], originalPosition[1], coordinated[1]];
|
|
37
42
|
lastPosition = next;
|
|
38
|
-
const snapKey = `${
|
|
43
|
+
const snapKey = `${coordinated[0]},${coordinated[1]}`;
|
|
39
44
|
if (snapKey !== lastSnapKey) {
|
|
40
45
|
triggerSFX('sfx:grid-snap');
|
|
41
46
|
lastSnapKey = snapKey;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type { ColumnNode, FloorplanGeometry, GeometryContext } from '@pascal-app/core';
|
|
1
|
+
import type { AnyNode, ColumnNode, FloorplanGeometry, FloorplanPoint, GeometryContext, StructuralGridNode } from '@pascal-app/core';
|
|
2
|
+
export type ColumnFloorplanLevelData = {
|
|
3
|
+
structuralGrids: StructuralGridNode[];
|
|
4
|
+
};
|
|
5
|
+
export declare function computeColumnFloorplanLevelData({ siblings, nodes, }: {
|
|
6
|
+
siblings: readonly ColumnNode[];
|
|
7
|
+
nodes: Record<string, AnyNode>;
|
|
8
|
+
}): ColumnFloorplanLevelData;
|
|
2
9
|
/**
|
|
3
10
|
* Stage C floor-plan builder for column. Inlined from the legacy
|
|
4
11
|
* `getColumnPlanFootprint` helper in `floorplan-panel.tsx`. The
|
|
@@ -12,4 +19,5 @@ import type { ColumnNode, FloorplanGeometry, GeometryContext } from '@pascal-app
|
|
|
12
19
|
* dragging the body, and a rotate-arrow at the front-right corner.
|
|
13
20
|
*/
|
|
14
21
|
export declare function buildColumnFloorplan(node: ColumnNode, ctx: GeometryContext): FloorplanGeometry | null;
|
|
22
|
+
export declare function getColumnFloorplanFootprint(node: ColumnNode): FloorplanPoint[];
|
|
15
23
|
//# sourceMappingURL=floorplan.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/column/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,
|
|
1
|
+
{"version":3,"file":"floorplan.d.ts","sourceRoot":"","sources":["../../src/column/floorplan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,kBAAkB,EACnB,MAAM,kBAAkB,CAAA;AAsBzB,MAAM,MAAM,wBAAwB,GAAG;IACrC,eAAe,EAAE,kBAAkB,EAAE,CAAA;CACtC,CAAA;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B,GAAG,wBAAwB,CAI3B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,eAAe,GACnB,iBAAiB,GAAG,IAAI,CAiL1B;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,UAAU,GAAG,cAAc,EAAE,CAE9E"}
|
package/dist/column/floorplan.js
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
+
import { floorplanGeometryMetadata } from '@pascal-app/editor';
|
|
2
|
+
import { collectStructuralGridAxes, resolveStructuralGridReference, } from '../structural-grid/coordination';
|
|
1
3
|
// Offsets for the floor-plan selection arrows. Resize chevrons hug the
|
|
2
4
|
// footprint a hair off the rim; the rotate-arrow corner sits a bit
|
|
3
5
|
// further out so it doesn't crowd the resize arrows.
|
|
4
6
|
const RESIZE_ARROW_OFFSET = 0.12;
|
|
5
7
|
const ROTATE_ARROW_CORNER_OFFSET = 0.22;
|
|
8
|
+
const GRID_REFERENCE_OFFSET = 0.16;
|
|
9
|
+
const GRID_REFERENCE_FONT_SIZE = 0.13;
|
|
6
10
|
const ROUND_CROSS_SECTIONS = new Set([
|
|
7
11
|
'round',
|
|
8
12
|
'octagonal',
|
|
9
13
|
'sixteen-sided',
|
|
10
14
|
]);
|
|
15
|
+
export function computeColumnFloorplanLevelData({ siblings, nodes, }) {
|
|
16
|
+
return {
|
|
17
|
+
structuralGrids: collectStructuralGridAxes(nodes, siblings[0]?.parentId),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
11
20
|
/**
|
|
12
21
|
* Stage C floor-plan builder for column. Inlined from the legacy
|
|
13
22
|
* `getColumnPlanFootprint` helper in `floorplan-panel.tsx`. The
|
|
@@ -21,8 +30,8 @@ const ROUND_CROSS_SECTIONS = new Set([
|
|
|
21
30
|
* dragging the body, and a rotate-arrow at the front-right corner.
|
|
22
31
|
*/
|
|
23
32
|
export function buildColumnFloorplan(node, ctx) {
|
|
24
|
-
const
|
|
25
|
-
if (
|
|
33
|
+
const points = getColumnFloorplanFootprint(node);
|
|
34
|
+
if (points.length < 3)
|
|
26
35
|
return null;
|
|
27
36
|
const view = ctx.viewState;
|
|
28
37
|
const palette = view?.palette;
|
|
@@ -31,7 +40,6 @@ export function buildColumnFloorplan(node, ctx) {
|
|
|
31
40
|
const showSelectedChrome = isSelected || isHighlighted;
|
|
32
41
|
const stroke = showSelectedChrome && palette ? palette.selectedStroke : '#374151';
|
|
33
42
|
const fill = showSelectedChrome ? '#fed7aa' : '#9ca3af';
|
|
34
|
-
const points = polygon.map((p) => [p.x, p.y]);
|
|
35
43
|
const children = [
|
|
36
44
|
{
|
|
37
45
|
kind: 'polygon',
|
|
@@ -40,8 +48,53 @@ export function buildColumnFloorplan(node, ctx) {
|
|
|
40
48
|
stroke,
|
|
41
49
|
strokeWidth: showSelectedChrome ? 0.03 : 0.02,
|
|
42
50
|
opacity: 0.92,
|
|
51
|
+
metadata: floorplanGeometryMetadata({ annotationObstacle: 'bounds' }),
|
|
43
52
|
},
|
|
44
53
|
];
|
|
54
|
+
const { halfX, halfZ } = columnPlanHalfExtents(node);
|
|
55
|
+
const centerMarkHalf = Math.min(0.09, Math.max(0.035, Math.min(halfX, halfZ) * 0.45));
|
|
56
|
+
const centerX = node.position[0];
|
|
57
|
+
const centerZ = node.position[2];
|
|
58
|
+
children.push({
|
|
59
|
+
kind: 'line',
|
|
60
|
+
x1: centerX - centerMarkHalf,
|
|
61
|
+
y1: centerZ - centerMarkHalf,
|
|
62
|
+
x2: centerX + centerMarkHalf,
|
|
63
|
+
y2: centerZ + centerMarkHalf,
|
|
64
|
+
stroke,
|
|
65
|
+
strokeWidth: 0.9,
|
|
66
|
+
vectorEffect: 'non-scaling-stroke',
|
|
67
|
+
pointerEvents: 'none',
|
|
68
|
+
metadata: floorplanGeometryMetadata({ annotationRole: 'column-center' }),
|
|
69
|
+
}, {
|
|
70
|
+
kind: 'line',
|
|
71
|
+
x1: centerX - centerMarkHalf,
|
|
72
|
+
y1: centerZ + centerMarkHalf,
|
|
73
|
+
x2: centerX + centerMarkHalf,
|
|
74
|
+
y2: centerZ - centerMarkHalf,
|
|
75
|
+
stroke,
|
|
76
|
+
strokeWidth: 0.9,
|
|
77
|
+
vectorEffect: 'non-scaling-stroke',
|
|
78
|
+
pointerEvents: 'none',
|
|
79
|
+
metadata: floorplanGeometryMetadata({ annotationRole: 'column-center' }),
|
|
80
|
+
});
|
|
81
|
+
const levelData = ctx.levelData;
|
|
82
|
+
const gridReference = resolveStructuralGridReference([centerX, centerZ], levelData?.structuralGrids ?? []);
|
|
83
|
+
if (gridReference) {
|
|
84
|
+
children.push({
|
|
85
|
+
kind: 'text',
|
|
86
|
+
x: centerX,
|
|
87
|
+
y: centerZ + halfZ + GRID_REFERENCE_OFFSET,
|
|
88
|
+
text: gridReference,
|
|
89
|
+
fontSize: GRID_REFERENCE_FONT_SIZE,
|
|
90
|
+
fill: stroke,
|
|
91
|
+
fontWeight: 700,
|
|
92
|
+
textAnchor: 'middle',
|
|
93
|
+
dominantBaseline: 'middle',
|
|
94
|
+
upright: true,
|
|
95
|
+
metadata: floorplanGeometryMetadata({ annotationRole: 'column-center' }),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
45
98
|
// Hatch overlay on selected — same `<defs>` pattern as the wall.
|
|
46
99
|
if (isSelected && palette) {
|
|
47
100
|
children.push({
|
|
@@ -117,7 +170,6 @@ export function buildColumnFloorplan(node, ctx) {
|
|
|
117
170
|
// Rotate-arrow at the +X / +Z corner — matches the 3D
|
|
118
171
|
// `columnRotateHandle` corner placement so users see the rotation
|
|
119
172
|
// affordance in the same quadrant across views.
|
|
120
|
-
const { halfX, halfZ } = columnPlanHalfExtents(node);
|
|
121
173
|
const cornerLocalX = halfX + ROTATE_ARROW_CORNER_OFFSET;
|
|
122
174
|
const cornerLocalZ = halfZ + ROTATE_ARROW_CORNER_OFFSET;
|
|
123
175
|
const [cornerWorldX, cornerWorldZ] = rotatePlanVector(cornerLocalX, cornerLocalZ, rot);
|
|
@@ -132,6 +184,9 @@ export function buildColumnFloorplan(node, ctx) {
|
|
|
132
184
|
}
|
|
133
185
|
return { kind: 'group', children };
|
|
134
186
|
}
|
|
187
|
+
export function getColumnFloorplanFootprint(node) {
|
|
188
|
+
return getColumnPlanFootprint(node).map((point) => [point.x, point.y]);
|
|
189
|
+
}
|
|
135
190
|
/**
|
|
136
191
|
* XZ half-extents for the column's plan footprint. Mirrors the 3D
|
|
137
192
|
* `columnFootprintHalf` so side-arrows + rotate-arrow ring the same
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/column/tool.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/column/tool.tsx"],"names":[],"mappings":"AAoDA;;;;;;;;;;GAUG;AACH,QAAA,MAAM,UAAU,0CA0Jf,CAAA;AAED,eAAe,UAAU,CAAA"}
|