@pascal-app/editor 0.8.0 → 0.9.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/package.json +15 -13
- package/src/components/editor/alignment-3d-guide-layer.tsx +168 -0
- package/src/components/editor/bake-exporter.tsx +47 -0
- package/src/components/editor/custom-camera-controls.tsx +795 -28
- package/src/components/editor/editor-layout-mobile.tsx +8 -3
- package/src/components/editor/editor-layout-v2.tsx +76 -51
- package/src/components/editor/export-manager.tsx +69 -32
- package/src/components/editor/fence-tangent-lines-3d.tsx +87 -0
- package/src/components/editor/first-person/build-collider-world.test.ts +182 -0
- package/src/components/editor/first-person/build-collider-world.ts +228 -83
- package/src/components/editor/first-person-controls.tsx +943 -27
- package/src/components/editor/floating-action-menu.tsx +676 -208
- package/src/components/editor/floating-building-action-menu.tsx +2 -2
- package/src/components/editor/floorplan-background-selection.test.ts +58 -0
- package/src/components/editor/floorplan-background-selection.ts +3 -2
- package/src/components/editor/floorplan-panel.tsx +6916 -12137
- package/src/components/editor/grid.tsx +197 -36
- package/src/components/editor/group-actions.ts +457 -0
- package/src/components/editor/group-floating-action-menu.tsx +130 -0
- package/src/components/editor/group-move-3d.ts +397 -0
- package/src/components/editor/group-rotate-handle.tsx +420 -0
- package/src/components/editor/group-selection-box-3d.tsx +173 -0
- package/src/components/editor/group-transform-shared.test.ts +396 -0
- package/src/components/editor/group-transform-shared.ts +489 -0
- package/src/components/editor/handles/handle-arrow.tsx +581 -0
- package/src/components/editor/handles/use-handle-drag.ts +246 -0
- package/src/components/editor/index.tsx +412 -162
- package/src/components/editor/measurement-pill.tsx +115 -0
- package/src/components/editor/node-action-menu.tsx +14 -1
- package/src/components/editor/node-arrow-handles.tsx +1646 -0
- package/src/components/editor/opening-guides-3d-layer.tsx +144 -0
- package/src/components/editor/quick-measurement-card.tsx +70 -0
- package/src/components/editor/quick-measurement-hud.tsx +28 -0
- package/src/components/editor/riser-diagram-panel.tsx +137 -0
- package/src/components/editor/selection-manager.tsx +1106 -483
- package/src/components/editor/site-edge-labels.tsx +45 -21
- package/src/components/editor/slab-hole-highlights.tsx +474 -0
- package/src/components/editor/snapshot-capture-overlay.tsx +369 -155
- package/src/components/editor/three-context-bridge.ts +22 -0
- package/src/components/editor/thumbnail-generator.tsx +140 -41
- package/src/components/editor/use-floorplan-background-placement.ts +190 -35
- package/src/components/editor/use-floorplan-hit-testing.ts +24 -0
- package/src/components/editor/use-floorplan-scene-data.ts +19 -7
- package/src/components/editor/use-mesh-settle-epoch.ts +26 -0
- package/src/components/editor/wall-measurement-label.tsx +14 -19
- package/src/components/editor/wall-move-side-handles.tsx +870 -0
- package/src/components/editor/wall-opening-highlights.tsx +181 -0
- package/src/components/editor/wall-snap-beacon-layer.tsx +304 -0
- package/src/components/editor-2d/floorplan-action-menu-layer.tsx +15 -6
- package/src/components/editor-2d/floorplan-alignment-guide-layer.tsx +142 -0
- package/src/components/editor-2d/floorplan-cursor-indicator-overlay.tsx +5 -3
- package/src/components/editor-2d/floorplan-group-action-menu.tsx +87 -0
- package/src/components/editor-2d/floorplan-group-move.tsx +701 -0
- package/src/components/editor-2d/floorplan-measurement-tool-layer.test.ts +113 -0
- package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +1656 -0
- package/src/components/editor-2d/floorplan-quick-measure-layer.tsx +212 -0
- package/src/components/editor-2d/floorplan-registry-action-menu.tsx +392 -0
- package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +857 -0
- package/src/components/editor-2d/floorplan-render-context.tsx +62 -0
- package/src/components/editor-2d/floorplan-snap-beacon-layer.tsx +77 -0
- package/src/components/editor-2d/floorplan-wall-move-ghost-layer.tsx +47 -0
- package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +266 -0
- package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +15 -0
- package/src/components/editor-2d/renderers/floorplan-label-angle.ts +14 -0
- package/src/components/editor-2d/renderers/floorplan-measurements-layer.tsx +108 -66
- package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +62 -0
- package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +308 -0
- package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +3325 -0
- package/src/components/editor-2d/renderers/floorplan-stair-layer.tsx +24 -9
- package/src/components/editor-2d/renderers/floorplan-voronoi-layer.tsx +128 -0
- package/src/components/editor-2d/svg-paths.ts +10 -2
- package/src/components/systems/ceiling/ceiling-selection-affordance-system.tsx +439 -57
- package/src/components/systems/ceiling/ceiling-system.tsx +109 -12
- package/src/components/systems/roof/roof-edit-system.tsx +1851 -22
- package/src/components/systems/selection-affordance-manager.tsx +38 -0
- package/src/components/systems/stair/stair-edit-system.tsx +1 -1
- package/src/components/systems/zone/zone-label-editor-system.tsx +14 -1
- package/src/components/systems/zone/zone-system.tsx +42 -13
- package/src/components/tools/elevator/elevator-defaults.ts +8 -0
- package/src/components/tools/elevator/elevator-tool.tsx +375 -0
- package/src/components/tools/elevator/move-elevator-tool.tsx +263 -0
- package/src/components/tools/fence/fence-drafting.ts +141 -27
- package/src/components/tools/item/move-tool.tsx +45 -105
- package/src/components/tools/item/placement-math.test.ts +22 -0
- package/src/components/tools/item/placement-math.ts +59 -7
- package/src/components/tools/item/placement-strategies.ts +432 -16
- package/src/components/tools/item/placement-types.ts +22 -1
- package/src/components/tools/item/use-draft-node.ts +51 -2
- package/src/components/tools/item/use-placement-coordinator.tsx +1399 -256
- package/src/components/tools/registry/move-registry-node-tool.tsx +1064 -0
- package/src/components/tools/roof/roof-tool.tsx +350 -28
- package/src/components/tools/select/box-select-state.ts +88 -0
- package/src/components/tools/select/box-select-tool.tsx +442 -520
- package/src/components/tools/select/marquee-geometry.test.ts +161 -0
- package/src/components/tools/select/marquee-geometry.ts +155 -0
- package/src/components/tools/select/plane-box-select-tool.tsx +570 -0
- package/src/components/tools/select/screen-rectangle-selection.ts +84 -0
- package/src/components/tools/select/select-candidates.test.ts +109 -0
- package/src/components/tools/select/select-candidates.ts +85 -0
- package/src/components/tools/shared/affordance-dispatch.ts +30 -0
- package/src/components/tools/shared/cursor-sphere.tsx +62 -26
- package/src/components/tools/shared/drag-bounding-box.tsx +195 -0
- package/src/components/tools/shared/facing-indicator.tsx +87 -0
- package/src/components/tools/shared/facing-pose-indicator.tsx +54 -0
- package/src/components/tools/shared/floor-stack-preview.ts +25 -0
- package/src/components/tools/shared/fresh-placement-visibility.ts +61 -0
- package/src/components/tools/shared/placement-box-geometry.ts +123 -0
- package/src/components/tools/shared/placement-box.tsx +305 -0
- package/src/components/tools/shared/polygon-editor.tsx +866 -175
- package/src/components/tools/shared/segment-angle.ts +56 -0
- package/src/components/tools/site/site-boundary-editor.tsx +520 -16
- package/src/components/tools/site/site-flag-model.ts +18 -0
- package/src/components/tools/stair/stair-defaults.ts +2 -1
- package/src/components/tools/stair/stair-tool.tsx +342 -37
- package/src/components/tools/tool-manager.tsx +239 -62
- package/src/components/tools/wall/wall-drafting.test.ts +330 -0
- package/src/components/tools/wall/wall-drafting.ts +248 -171
- package/src/components/tools/wall/wall-snap-geometry.test.ts +123 -0
- package/src/components/tools/wall/wall-snap-geometry.ts +331 -0
- package/src/components/tools/zone/zone-boundary-editor.tsx +5 -1
- package/src/components/tools/zone/zone-tool.tsx +86 -82
- package/src/components/ui/action-menu/action-button.tsx +21 -1
- package/src/components/ui/action-menu/camera-actions.tsx +24 -17
- package/src/components/ui/action-menu/control-modes.tsx +40 -170
- package/src/components/ui/action-menu/furnish-tools.tsx +5 -5
- package/src/components/ui/action-menu/index.tsx +3 -117
- package/src/components/ui/action-menu/measurement-control.tsx +188 -0
- package/src/components/ui/action-menu/structure-tools.tsx +27 -93
- package/src/components/ui/action-menu/view-toggles.tsx +279 -90
- package/src/components/ui/command-palette/editor-commands.tsx +20 -15
- package/src/components/ui/command-palette/index.tsx +5 -3
- package/src/components/ui/controls/material-paint-panel.tsx +152 -0
- package/src/components/ui/controls/material-picker.tsx +87 -177
- package/src/components/ui/controls/material-properties-editor.tsx +108 -0
- package/src/components/ui/controls/metric-control.tsx +142 -46
- package/src/components/ui/controls/scene-material-list.tsx +247 -0
- package/src/components/ui/controls/slider-control.tsx +88 -38
- package/src/components/ui/floating-level-selector.tsx +47 -10
- package/src/components/ui/helpers/building-helper.tsx +10 -23
- package/src/components/ui/helpers/contextual-helper-panel.tsx +428 -0
- package/src/components/ui/helpers/helper-manager.tsx +235 -23
- package/src/components/ui/helpers/item-helper.tsx +28 -32
- package/src/components/ui/helpers/registered-tool-helper.tsx +59 -0
- package/src/components/ui/helpers/roof-helper.tsx +10 -12
- package/src/components/ui/icon-ref.tsx +47 -0
- package/src/components/ui/item-catalog/catalog-items.tsx +40 -1
- package/src/components/ui/item-catalog/item-catalog.tsx +16 -36
- package/src/components/ui/level-duplicate-dialog.tsx +2 -1
- package/src/components/ui/panels/node-display.ts +17 -16
- package/src/components/ui/panels/panel-manager.tsx +55 -58
- package/src/components/ui/panels/panel-wrapper.tsx +238 -12
- package/src/components/ui/panels/parametric-inspector.tsx +482 -0
- package/src/components/ui/panels/reference-panel.tsx +54 -19
- package/src/components/ui/primitives/dropdown-menu.tsx +12 -8
- package/src/components/ui/primitives/shortcut-token.tsx +39 -3
- package/src/components/ui/primitives/sidebar.tsx +1 -0
- package/src/components/ui/scene-loader.tsx +1 -3
- package/src/components/ui/sidebar/app-sidebar.tsx +5 -1
- package/src/components/ui/sidebar/icon-rail.tsx +50 -31
- package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +263 -0
- package/src/components/ui/sidebar/panels/items-panel/index.tsx +82 -8
- package/src/components/ui/sidebar/panels/plugins-panel.tsx +218 -0
- package/src/components/ui/sidebar/panels/settings-panel/index.tsx +122 -41
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +66 -7
- package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +267 -0
- package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +3 -1
- package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +9 -5
- package/src/components/ui/sidebar/panels/site-panel/chimney-tree-node.tsx +86 -0
- package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +1 -1
- package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +7 -2
- package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +92 -0
- package/src/components/ui/sidebar/panels/site-panel/elevator-tree-node.tsx +75 -0
- package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +3 -3
- package/src/components/ui/sidebar/panels/site-panel/gutter-tree-node.tsx +86 -0
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +42 -21
- package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +31 -17
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +2 -1
- package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +140 -0
- package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +48 -8
- package/src/components/ui/sidebar/panels/site-panel/shelf-tree-node.tsx +132 -0
- package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +9 -5
- package/src/components/ui/sidebar/panels/site-panel/solar-panel-tree-node.tsx +86 -0
- package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +7 -1
- package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +2 -2
- package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +112 -39
- package/src/components/ui/sidebar/panels/site-panel/tree-structure.ts +36 -0
- package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +1 -1
- package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +7 -2
- package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +3 -3
- package/src/components/ui/sidebar/panels/zone-panel/index.tsx +51 -2
- package/src/components/ui/sidebar/tab-bar.tsx +75 -1
- package/src/components/ui/sidebar/use-plugin-panels.tsx +132 -0
- package/src/components/ui/snap-target-badge.test.tsx +40 -0
- package/src/components/ui/snap-target-badge.tsx +88 -0
- package/src/components/viewer-overlay.tsx +253 -61
- package/src/components/viewer-zone-system.tsx +7 -2
- package/src/hooks/use-auto-save.test.ts +14 -0
- package/src/hooks/use-auto-save.ts +64 -10
- package/src/hooks/use-ceiling-events.ts +176 -0
- package/src/hooks/use-drag-action.ts +127 -0
- package/src/hooks/use-keyboard.ts +493 -95
- package/src/hooks/use-selection.ts +64 -0
- package/src/index.tsx +451 -6
- package/src/lib/active-placement-surface.ts +35 -0
- package/src/lib/ceiling-plan-snap.ts +24 -0
- package/src/lib/constants.ts +6 -2
- package/src/lib/contextual-help.test.ts +112 -0
- package/src/lib/contextual-help.ts +144 -0
- package/src/lib/continuation.ts +64 -0
- package/src/lib/direct-manipulation.test.ts +192 -0
- package/src/lib/direct-manipulation.ts +109 -0
- package/src/lib/editor-api.ts +50 -0
- package/src/lib/elevator-support.ts +96 -0
- package/src/lib/floorplan/apply-alignment.test.ts +25 -0
- package/src/lib/floorplan/apply-alignment.ts +117 -0
- package/src/lib/floorplan/floorplan-export.tsx +364 -0
- package/src/lib/floorplan/geometry.ts +53 -0
- package/src/lib/floorplan/index.ts +10 -0
- package/src/lib/floorplan/items.ts +5 -2
- package/src/lib/floorplan/plan-coords.ts +21 -0
- package/src/lib/floorplan/selection-tool.ts +40 -0
- package/src/lib/floorplan/stairs.ts +12 -1
- package/src/lib/fresh-planar-placement.test.ts +339 -0
- package/src/lib/fresh-planar-placement.ts +130 -0
- package/src/lib/glb-export.test.ts +441 -0
- package/src/lib/glb-export.ts +874 -0
- package/src/lib/history.ts +11 -1
- package/src/lib/interaction/hot-set.test.ts +133 -0
- package/src/lib/interaction/hot-set.ts +67 -0
- package/src/lib/interaction/overlay-policy.test.ts +51 -0
- package/src/lib/interaction/overlay-policy.ts +59 -0
- package/src/lib/interaction/scope.ts +211 -0
- package/src/lib/level-duplication.ts +54 -42
- package/src/lib/level-selection.ts +2 -2
- package/src/lib/material-paint.ts +227 -48
- package/src/lib/measurement-kind.test.ts +30 -0
- package/src/lib/measurement-kind.ts +19 -0
- package/src/lib/measurement-label.test.ts +47 -0
- package/src/lib/measurement-label.ts +68 -0
- package/src/lib/measurement-parser.ts +116 -0
- package/src/lib/measurements.test.ts +183 -0
- package/src/lib/measurements.ts +199 -0
- package/src/lib/paint-scope.test.ts +454 -0
- package/src/lib/paint-scope.ts +461 -0
- package/src/lib/placement-drag-release.ts +23 -0
- package/src/lib/placement-metadata.ts +29 -0
- package/src/lib/planar-cursor-placement.test.ts +100 -0
- package/src/lib/planar-cursor-placement.ts +42 -0
- package/src/lib/plugin-panels.test.ts +19 -0
- package/src/lib/plugin-panels.ts +91 -0
- package/src/lib/quick-measurement.test.ts +77 -0
- package/src/lib/quick-measurement.ts +109 -0
- package/src/lib/roof-duplication.ts +7 -7
- package/src/lib/roof-hover-outline-proxy.ts +22 -0
- package/src/lib/roof-wall-hit.ts +164 -0
- package/src/lib/scene-clipboard.test.ts +196 -0
- package/src/lib/scene-clipboard.ts +332 -0
- package/src/lib/scene.ts +40 -8
- package/src/lib/selection-routing.test.ts +298 -0
- package/src/lib/selection-routing.ts +175 -0
- package/src/lib/sfx/index.ts +1 -0
- package/src/lib/sfx/movement-tick.test.ts +65 -0
- package/src/lib/sfx/movement-tick.ts +18 -0
- package/src/lib/sfx-bus.ts +69 -10
- package/src/lib/sfx-player.test.ts +124 -0
- package/src/lib/sfx-player.ts +148 -55
- package/src/lib/site-boundary.ts +1 -0
- package/src/lib/slab-plan-snap.test.ts +93 -0
- package/src/lib/slab-plan-snap.ts +108 -0
- package/src/lib/snapping-mode.test.ts +138 -0
- package/src/lib/snapping-mode.ts +179 -0
- package/src/lib/stair-duplication.ts +4 -4
- package/src/lib/stair-levels.test.ts +146 -0
- package/src/lib/stair-levels.ts +177 -0
- package/src/lib/surface-plan-snap.test.ts +71 -0
- package/src/lib/surface-plan-snap.ts +256 -0
- package/src/lib/use-linear-display.ts +40 -0
- package/src/lib/world-grid-snap.ts +231 -0
- package/src/lib/zone-content.ts +130 -0
- package/src/store/use-alignment-guides.ts +21 -0
- package/src/store/use-direct-manipulation-feedback.ts +20 -0
- package/src/store/use-editor.tsx +767 -114
- package/src/store/use-facing-pose.ts +44 -0
- package/src/store/use-fence-curve-draft.ts +21 -0
- package/src/store/use-floorplan-draft-preview.ts +101 -0
- package/src/store/use-floorplan-marquee.ts +50 -0
- package/src/store/use-interaction-scope.test.ts +186 -0
- package/src/store/use-interaction-scope.ts +132 -0
- package/src/store/use-measurement-draft.test.ts +530 -0
- package/src/store/use-measurement-draft.ts +543 -0
- package/src/store/use-opening-guides.ts +41 -0
- package/src/store/use-placement-preview.ts +39 -0
- package/src/store/use-quick-measurement-hud.test.ts +53 -0
- package/src/store/use-quick-measurement-hud.ts +77 -0
- package/src/store/use-segment-draft-chain.ts +28 -0
- package/src/store/use-stair-build-preview.ts +43 -0
- package/src/store/use-wall-move-ghosts.ts +36 -0
- package/src/store/use-wall-snap-indicator.ts +34 -0
- package/src/components/editor/first-person/bvh-ecctrl.tsx +0 -860
- package/src/components/editor/preset-thumbnail-generator.tsx +0 -125
- package/src/components/editor-2d/renderers/floorplan-roof-layer.tsx +0 -113
- package/src/components/tools/building/move-building-tool.tsx +0 -157
- package/src/components/tools/ceiling/ceiling-boundary-editor.tsx +0 -43
- package/src/components/tools/ceiling/ceiling-hole-editor.tsx +0 -49
- package/src/components/tools/ceiling/ceiling-tool.tsx +0 -465
- package/src/components/tools/ceiling/move-ceiling-tool.tsx +0 -264
- package/src/components/tools/column/column-tool.tsx +0 -97
- package/src/components/tools/column/move-column-tool.tsx +0 -105
- package/src/components/tools/door/door-math.ts +0 -110
- package/src/components/tools/door/door-tool.tsx +0 -324
- package/src/components/tools/door/move-door-tool.tsx +0 -412
- package/src/components/tools/fence/curve-fence-tool.tsx +0 -178
- package/src/components/tools/fence/fence-tool.tsx +0 -346
- package/src/components/tools/fence/move-fence-endpoint-tool.tsx +0 -441
- package/src/components/tools/fence/move-fence-tool.tsx +0 -302
- package/src/components/tools/item/item-tool.tsx +0 -26
- package/src/components/tools/roof/move-roof-tool.tsx +0 -364
- package/src/components/tools/slab/move-slab-tool.tsx +0 -182
- package/src/components/tools/slab/slab-boundary-editor.tsx +0 -43
- package/src/components/tools/slab/slab-hole-editor.tsx +0 -49
- package/src/components/tools/slab/slab-tool.tsx +0 -322
- package/src/components/tools/spawn/move-spawn-tool.tsx +0 -101
- package/src/components/tools/spawn/spawn-tool.tsx +0 -130
- package/src/components/tools/wall/curve-wall-tool.tsx +0 -178
- package/src/components/tools/wall/move-wall-endpoint-tool.tsx +0 -426
- package/src/components/tools/wall/move-wall-tool.tsx +0 -358
- package/src/components/tools/wall/wall-tool.tsx +0 -332
- package/src/components/tools/window/move-window-tool.tsx +0 -447
- package/src/components/tools/window/window-math.ts +0 -117
- package/src/components/tools/window/window-tool.tsx +0 -332
- package/src/components/ui/helpers/ceiling-helper.tsx +0 -20
- package/src/components/ui/helpers/slab-helper.tsx +0 -20
- package/src/components/ui/helpers/wall-helper.tsx +0 -20
- package/src/components/ui/panels/ceiling-panel.tsx +0 -249
- package/src/components/ui/panels/column-panel.tsx +0 -759
- package/src/components/ui/panels/door-panel.tsx +0 -1299
- package/src/components/ui/panels/fence-panel.tsx +0 -222
- package/src/components/ui/panels/item-panel.tsx +0 -306
- package/src/components/ui/panels/paint-panel.tsx +0 -163
- package/src/components/ui/panels/presets/presets-popover.tsx +0 -511
- package/src/components/ui/panels/roof-panel.tsx +0 -280
- package/src/components/ui/panels/roof-segment-panel.tsx +0 -311
- package/src/components/ui/panels/slab-panel.tsx +0 -250
- package/src/components/ui/panels/spawn-panel.tsx +0 -161
- package/src/components/ui/panels/stair-panel.tsx +0 -577
- package/src/components/ui/panels/stair-segment-panel.tsx +0 -325
- package/src/components/ui/panels/wall-panel.tsx +0 -273
- package/src/components/ui/panels/window-panel.tsx +0 -968
- package/src/contexts/presets-context.tsx +0 -121
- package/src/hooks/use-contextual-tools.ts +0 -61
|
@@ -83,6 +83,14 @@ function getNormalizedFloorplanStairSweepAngle(stair: StairNode) {
|
|
|
83
83
|
return baseSweepAngle
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
function clampFloorplanCircularSweepAngle(sweepAngle: number) {
|
|
87
|
+
if (Math.abs(sweepAngle) >= Math.PI * 2) {
|
|
88
|
+
return Math.sign(sweepAngle || 1) * (Math.PI * 2 - 0.001)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return sweepAngle
|
|
92
|
+
}
|
|
93
|
+
|
|
86
94
|
function getFloorplanStairStepCount(stair: StairNode, minimum: number) {
|
|
87
95
|
return Math.max(minimum, Math.round(stair.stepCount ?? 10))
|
|
88
96
|
}
|
|
@@ -139,7 +147,10 @@ export const FloorplanStairLayer = memo(function FloorplanStairLayer({
|
|
|
139
147
|
const sectorStartAngle = -stair.rotation - normalizedSweepAngle / 2
|
|
140
148
|
const sectorEndAngle = sectorStartAngle + normalizedSweepAngle
|
|
141
149
|
const spiralLandingSweep = getFloorplanSpiralLandingSweep(stair, normalizedSweepAngle)
|
|
142
|
-
const
|
|
150
|
+
const visualSweepAngle = clampFloorplanCircularSweepAngle(
|
|
151
|
+
normalizedSweepAngle + spiralLandingSweep,
|
|
152
|
+
)
|
|
153
|
+
const visualSectorEndAngle = sectorStartAngle + visualSweepAngle
|
|
143
154
|
const stairCenter = {
|
|
144
155
|
x: stair.position[0],
|
|
145
156
|
y: stair.position[2],
|
|
@@ -273,10 +284,12 @@ export const FloorplanStairLayer = memo(function FloorplanStairLayer({
|
|
|
273
284
|
fill={curvedAccent}
|
|
274
285
|
key={`${stair.id}:spiral-arrow`}
|
|
275
286
|
pointerEvents="none"
|
|
276
|
-
points={
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
287
|
+
points={formatSvgPolygonPoints(
|
|
288
|
+
buildSvgArrowHeadPoints(
|
|
289
|
+
arrowPoint,
|
|
290
|
+
tangentAngle,
|
|
291
|
+
clamp(stair.width * 0.18, 0.12, 0.18),
|
|
292
|
+
),
|
|
280
293
|
)}
|
|
281
294
|
/>
|
|
282
295
|
)
|
|
@@ -361,10 +374,12 @@ export const FloorplanStairLayer = memo(function FloorplanStairLayer({
|
|
|
361
374
|
fill={curvedAccent}
|
|
362
375
|
key={`${stair.id}:curved-arrow`}
|
|
363
376
|
pointerEvents="none"
|
|
364
|
-
points={
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
377
|
+
points={formatSvgPolygonPoints(
|
|
378
|
+
buildSvgArrowHeadPoints(
|
|
379
|
+
arrowPoint,
|
|
380
|
+
tangentAngle,
|
|
381
|
+
clamp(stair.width * 0.16, 0.1, 0.16),
|
|
382
|
+
),
|
|
368
383
|
)}
|
|
369
384
|
/>
|
|
370
385
|
)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { collectLevelWallSegments, useScene, WALL_SNAP_DISTANCE_M } from '@pascal-app/core'
|
|
4
|
+
import { useViewer } from '@pascal-app/viewer'
|
|
5
|
+
import { memo, useMemo } from 'react'
|
|
6
|
+
import useEditor from '../../../store/use-editor'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Dev-only 2D debug overlay for the opening (door / window) wall snap.
|
|
10
|
+
*
|
|
11
|
+
* The snap (`findClosestWallInPlan`) attaches to a wall when the cursor is
|
|
12
|
+
* within `WALL_SNAP_DISTANCE_M` of the wall's centerline, picking the
|
|
13
|
+
* nearest such wall. The set of points within that radius of a segment is a
|
|
14
|
+
* **capsule** (stadium): a band of half-width = the snap radius along the
|
|
15
|
+
* wall, with semicircular caps at each end. That capsule IS the wall's
|
|
16
|
+
* (normally invisible) hit target — so this layer draws it directly, one
|
|
17
|
+
* analytic `<path>` per wall, instead of sampling a grid (which produced the
|
|
18
|
+
* stair-stepped boundary the previous version showed). No per-point
|
|
19
|
+
* classification, so it's cheap regardless of plan size.
|
|
20
|
+
*
|
|
21
|
+
* Where two walls sit closer than 2× the radius their capsules overlap; the
|
|
22
|
+
* snap resolves the overlap to the nearer wall (the translucent fills just
|
|
23
|
+
* blend there — a darker patch reads as "either wall is in reach, nearest
|
|
24
|
+
* wins"). Drawing the true bisector-clipped cells would need the expensive
|
|
25
|
+
* per-point pass this rewrite removes, and the hit-area view is what the
|
|
26
|
+
* user asked for.
|
|
27
|
+
*
|
|
28
|
+
* Gated on `useEditor.show2dVoronoi` (developer menu). Renders inside the
|
|
29
|
+
* floor-plan scene `<g>`, so it shares the plan→SVG transform and the scene
|
|
30
|
+
* rotation with every other floor-plan layer.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/** Stable hue per wall id so a wall keeps its colour across re-renders. */
|
|
34
|
+
function wallHue(id: string): number {
|
|
35
|
+
let hash = 0
|
|
36
|
+
for (let i = 0; i < id.length; i++) {
|
|
37
|
+
hash = (hash * 31 + id.charCodeAt(i)) >>> 0
|
|
38
|
+
}
|
|
39
|
+
// Spread hues around the wheel with an offset that avoids a muddy
|
|
40
|
+
// red-orange clump for short, similar ids.
|
|
41
|
+
return (hash * 47) % 360
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const FloorplanVoronoiLayer = memo(function FloorplanVoronoiLayer() {
|
|
45
|
+
const show2dVoronoi = useEditor((s) => s.show2dVoronoi)
|
|
46
|
+
const selectedLevelId = useViewer((s) => s.selection.levelId)
|
|
47
|
+
// Recompute only when the wall geometry on this level changes — not on
|
|
48
|
+
// every scene write. Dragging a door updates the door node every frame;
|
|
49
|
+
// keying the build on this string means the capsule paths don't rebuild
|
|
50
|
+
// for openings, only for wall edits.
|
|
51
|
+
const nodes = useScene((s) => s.nodes)
|
|
52
|
+
const wallsKey = useMemo(() => {
|
|
53
|
+
if (!show2dVoronoi || !selectedLevelId) return ''
|
|
54
|
+
const segments = collectLevelWallSegments(nodes, selectedLevelId)
|
|
55
|
+
return segments
|
|
56
|
+
.map((s) => `${s.wall.id}:${s.start[0]},${s.start[1]},${s.end[0]},${s.end[1]}`)
|
|
57
|
+
.join('|')
|
|
58
|
+
}, [show2dVoronoi, selectedLevelId, nodes])
|
|
59
|
+
|
|
60
|
+
const walls = useMemo(() => {
|
|
61
|
+
if (!show2dVoronoi || !selectedLevelId || !wallsKey) return null
|
|
62
|
+
// Read nodes imperatively: `wallsKey` already encodes every wall change,
|
|
63
|
+
// so this memo is keyed on it rather than on the per-frame `nodes` ref.
|
|
64
|
+
const segments = collectLevelWallSegments(useScene.getState().nodes, selectedLevelId)
|
|
65
|
+
if (segments.length === 0) return null
|
|
66
|
+
|
|
67
|
+
const R = WALL_SNAP_DISTANCE_M
|
|
68
|
+
const r = R.toFixed(3)
|
|
69
|
+
return segments.map((s) => {
|
|
70
|
+
// Capsule outline. Normal = dir rotated +90° = (-dirY, dirX). Offset the
|
|
71
|
+
// segment endpoints ±R along the normal for the long sides, then a
|
|
72
|
+
// semicircular cap (radius R, sweep-flag 0 bulges outward past each end)
|
|
73
|
+
// joins them. Verified winding holds for every orientation because the
|
|
74
|
+
// whole construction is a rigid transform of the axis-aligned case.
|
|
75
|
+
const nx = -s.dirY
|
|
76
|
+
const ny = s.dirX
|
|
77
|
+
const ax = (s.start[0] + nx * R).toFixed(3)
|
|
78
|
+
const ay = (s.start[1] + ny * R).toFixed(3)
|
|
79
|
+
const bx = (s.end[0] + nx * R).toFixed(3)
|
|
80
|
+
const by = (s.end[1] + ny * R).toFixed(3)
|
|
81
|
+
const cx = (s.end[0] - nx * R).toFixed(3)
|
|
82
|
+
const cy = (s.end[1] - ny * R).toFixed(3)
|
|
83
|
+
const dx = (s.start[0] - nx * R).toFixed(3)
|
|
84
|
+
const dy = (s.start[1] - ny * R).toFixed(3)
|
|
85
|
+
const d = `M${ax} ${ay}L${bx} ${by}A${r} ${r} 0 0 0 ${cx} ${cy}L${dx} ${dy}A${r} ${r} 0 0 0 ${ax} ${ay}Z`
|
|
86
|
+
return {
|
|
87
|
+
wallId: s.wall.id,
|
|
88
|
+
d,
|
|
89
|
+
hue: wallHue(s.wall.id),
|
|
90
|
+
x1: s.start[0],
|
|
91
|
+
y1: s.start[1],
|
|
92
|
+
x2: s.end[0],
|
|
93
|
+
y2: s.end[1],
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
}, [show2dVoronoi, selectedLevelId, wallsKey])
|
|
97
|
+
|
|
98
|
+
if (!walls) return null
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<g className="floorplan-voronoi-debug" pointerEvents="none">
|
|
102
|
+
{walls.map(({ wallId, d, hue }) => (
|
|
103
|
+
<path
|
|
104
|
+
d={d}
|
|
105
|
+
fill={`hsla(${hue}, 80%, 55%, 0.22)`}
|
|
106
|
+
key={`hit-${wallId}`}
|
|
107
|
+
stroke={`hsl(${hue}, 85%, 50%)`}
|
|
108
|
+
strokeOpacity={0.5}
|
|
109
|
+
strokeWidth={1}
|
|
110
|
+
vectorEffect="non-scaling-stroke"
|
|
111
|
+
/>
|
|
112
|
+
))}
|
|
113
|
+
{walls.map(({ wallId, hue, x1, y1, x2, y2 }) => (
|
|
114
|
+
<line
|
|
115
|
+
key={`line-${wallId}`}
|
|
116
|
+
stroke={`hsl(${hue}, 85%, 42%)`}
|
|
117
|
+
strokeLinecap="round"
|
|
118
|
+
strokeWidth={2}
|
|
119
|
+
vectorEffect="non-scaling-stroke"
|
|
120
|
+
x1={x1}
|
|
121
|
+
x2={x2}
|
|
122
|
+
y1={y1}
|
|
123
|
+
y2={y2}
|
|
124
|
+
/>
|
|
125
|
+
))}
|
|
126
|
+
</g>
|
|
127
|
+
)
|
|
128
|
+
})
|
|
@@ -103,7 +103,15 @@ export function formatSvgPolygonPoints(points: Point2D[]) {
|
|
|
103
103
|
return points.map((point) => `${toSvgX(point.x)},${toSvgY(point.y)}`).join(' ')
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Three points defining an arrow head — tip + two trailing barbs.
|
|
108
|
+
* Returned as plain `Point2D` objects so consumers can either feed them
|
|
109
|
+
* straight into `formatSvgPolygonPoints` (for SVG `points=""`) or push
|
|
110
|
+
* them onto a `FloorplanGeometry.polygon.points` array. Mixing both
|
|
111
|
+
* downstream paths through a string-returning helper was awkward — see
|
|
112
|
+
* `nodes/src/stair/floorplan.ts` which needs the points as objects.
|
|
113
|
+
*/
|
|
114
|
+
export function buildSvgArrowHeadPoints(point: Point2D, angle: number, size: number): Point2D[] {
|
|
107
115
|
const left = {
|
|
108
116
|
x: point.x - size * Math.cos(angle - Math.PI / 6),
|
|
109
117
|
y: point.y - size * Math.sin(angle - Math.PI / 6),
|
|
@@ -113,7 +121,7 @@ export function buildSvgArrowHeadPoints(point: Point2D, angle: number, size: num
|
|
|
113
121
|
y: point.y - size * Math.sin(angle + Math.PI / 6),
|
|
114
122
|
}
|
|
115
123
|
|
|
116
|
-
return
|
|
124
|
+
return [point, left, right]
|
|
117
125
|
}
|
|
118
126
|
|
|
119
127
|
export { toSvgPoint, toSvgX, toSvgY }
|