@pascal-app/editor 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +18 -15
- package/src/components/editor/action-menu-button.tsx +4 -1
- package/src/components/editor/alignment-3d-guide-layer.tsx +102 -11
- package/src/components/editor/bake-thumbnail.tsx +3 -2
- package/src/components/editor/custom-camera-controls.tsx +20 -8
- package/src/components/editor/elevation-3d-guide-layer.tsx +1 -1
- package/src/components/editor/first-person-controls.tsx +72 -61
- package/src/components/editor/floating-action-menu.tsx +27 -9
- package/src/components/editor/floating-building-action-menu.tsx +1 -1
- package/src/components/editor/floorplan-panel.test.ts +220 -0
- package/src/components/editor/floorplan-panel.tsx +285 -132
- package/src/components/editor/footprint-height-handle.tsx +1 -1
- package/src/components/editor/grid.tsx +24 -15
- package/src/components/editor/group-actions.ts +19 -1
- package/src/components/editor/group-floating-action-menu.tsx +1 -1
- package/src/components/editor/group-move-3d.ts +27 -2
- package/src/components/editor/group-selection-box-3d.tsx +4 -1
- package/src/components/editor/group-transform-shared.ts +20 -0
- package/src/components/editor/index.tsx +130 -20
- package/src/components/editor/inspector-extension-actions.tsx +36 -0
- package/src/components/editor/localized-html.tsx +22 -0
- package/src/components/editor/node-action-menu.tsx +46 -12
- package/src/components/editor/node-arrow-handles.tsx +1 -2
- package/src/components/editor/open-wall-ends-3d-layer.tsx +1 -1
- package/src/components/editor/opening-guides-3d-layer.tsx +1 -1
- package/src/components/editor/registry-action-contributions.test.tsx +67 -6
- package/src/components/editor/registry-action-contributions.tsx +115 -15
- package/src/components/editor/riser-diagram-panel.tsx +59 -9
- package/src/components/editor/room-controls.tsx +1 -1
- package/src/components/editor/room-handles-2d.tsx +156 -6
- package/src/components/editor/room-handles.tsx +241 -51
- package/src/components/editor/room-highlight.tsx +2 -0
- package/src/components/editor/room-labels.tsx +29 -15
- package/src/components/editor/selection-manager.tsx +15 -102
- package/src/components/editor/separator-end-grip.tsx +74 -0
- package/src/components/editor/site-edge-labels.tsx +1 -1
- package/src/components/editor/thumbnail-generator.test.ts +15 -6
- package/src/components/editor/thumbnail-generator.tsx +26 -1
- package/src/components/editor/use-floorplan-background-placement.ts +55 -52
- package/src/components/editor/views/view-bar.tsx +111 -26
- package/src/components/editor/wall-measurement-label.tsx +1 -1
- package/src/components/editor/wall-move-side-handles.tsx +5 -1
- package/src/components/editor/wall-pull-grip.tsx +193 -0
- package/src/components/editor/wall-snap-beacon-layer.tsx +81 -1
- package/src/components/editor-2d/floorplan-adjacent-walls-layer.test.ts +76 -0
- package/src/components/editor-2d/floorplan-adjacent-walls-layer.tsx +186 -0
- package/src/components/editor-2d/floorplan-alignment-guide-layer.tsx +63 -3
- package/src/components/editor-2d/floorplan-group-move.tsx +31 -3
- package/src/components/editor-2d/floorplan-measurement-tool-layer.test.ts +6 -0
- package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +22 -13
- package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +11 -3
- package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +7 -1
- package/src/components/editor-2d/floorplan-snap-beacon-layer.tsx +96 -4
- package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.tsx +52 -12
- package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +12 -1
- package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +197 -37
- package/src/components/procedural-items/inspector.tsx +59 -12
- package/src/components/systems/ceiling/ceiling-bracket-batch.test.ts +2 -0
- package/src/components/systems/ceiling/ceiling-system.test.ts +141 -0
- package/src/components/systems/ceiling/ceiling-system.tsx +53 -18
- package/src/components/tools/distribution/distribution-run-tool.tsx +50 -26
- package/src/components/tools/item/placement-history.test.tsx +1 -1
- package/src/components/tools/item/placement-strategies.test.ts +64 -1
- package/src/components/tools/item/placement-strategies.ts +5 -9
- package/src/components/tools/item/use-placement-coordinator.tsx +30 -34
- package/src/components/tools/registry/item-surface-move.test.ts +11 -0
- package/src/components/tools/select/select-candidates.test.ts +45 -0
- package/src/components/tools/select/select-candidates.ts +13 -2
- package/src/components/tools/shared/cursor-sphere.tsx +10 -3
- package/src/components/tools/shared/draft-measurement-label.tsx +1 -1
- package/src/components/tools/shared/placement-box.tsx +1 -1
- package/src/components/tools/shared/placement-dimension-guides.tsx +1 -1
- package/src/components/tools/site/terrain-brush-cursor.tsx +1 -1
- package/src/components/tools/wall/wall-drafting.test.ts +299 -23
- package/src/components/tools/wall/wall-drafting.ts +132 -24
- package/src/components/tools/wall/wall-pull-snap.test.ts +274 -0
- package/src/components/tools/wall/wall-pull-snap.ts +563 -0
- package/src/components/tools/wall/wall-snap-geometry.test.ts +113 -1
- package/src/components/tools/wall/wall-snap-geometry.ts +137 -0
- package/src/components/tools/zone/zone-tool.tsx +3 -3
- package/src/components/ui/action-menu/action-button.tsx +2 -0
- package/src/components/ui/action-menu/camera-actions.tsx +8 -7
- package/src/components/ui/action-menu/control-modes.tsx +9 -5
- package/src/components/ui/action-menu/follow-pascal-pill.tsx +3 -1
- package/src/components/ui/action-menu/follow-pascal-toggle.tsx +7 -1
- package/src/components/ui/action-menu/furnish-tools.tsx +7 -6
- package/src/components/ui/action-menu/index.tsx +1 -0
- package/src/components/ui/action-menu/measurement-control.tsx +35 -29
- package/src/components/ui/action-menu/point-ask-button.tsx +4 -3
- package/src/components/ui/action-menu/structure-tools.tsx +25 -23
- package/src/components/ui/action-menu/view-toggles.test.ts +18 -0
- package/src/components/ui/action-menu/view-toggles.tsx +256 -51
- package/src/components/ui/build-panel/build-panel.tsx +163 -25
- package/src/components/ui/command-palette/editor-commands.tsx +38 -11
- package/src/components/ui/controls/finish-swatch.tsx +45 -19
- package/src/components/ui/controls/material-picker.tsx +24 -17
- package/src/components/ui/controls/metric-control.test.ts +52 -0
- package/src/components/ui/controls/metric-control.tsx +62 -24
- package/src/components/ui/controls/segmented-control.tsx +5 -2
- package/src/components/ui/controls/slider-control.test.tsx +23 -0
- package/src/components/ui/controls/slider-control.tsx +30 -14
- package/src/components/ui/floating-level-selector.tsx +100 -48
- package/src/components/ui/helpers/building-helper.tsx +5 -3
- package/src/components/ui/helpers/contextual-helper-panel.tsx +97 -37
- package/src/components/ui/helpers/helper-manager.test.tsx +53 -3
- package/src/components/ui/helpers/helper-manager.tsx +82 -57
- package/src/components/ui/helpers/item-helper.tsx +6 -4
- package/src/components/ui/helpers/registered-tool-helper.tsx +3 -1
- package/src/components/ui/level-duplicate-dialog.tsx +32 -23
- package/src/components/ui/level-wall-copy-prompt.tsx +124 -0
- package/src/components/ui/panels/collections/collections-popover.tsx +11 -11
- package/src/components/ui/panels/deck-boards-fields.tsx +136 -0
- package/src/components/ui/panels/floor-foundation-panel.tsx +113 -38
- package/src/components/ui/panels/floor-opening-panel.tsx +73 -25
- package/src/components/ui/panels/inspector-extensions.tsx +66 -0
- package/src/components/ui/panels/mobile-panel-sheet.tsx +3 -1
- package/src/components/ui/panels/mobile-selection-bar.tsx +8 -6
- package/src/components/ui/panels/multi-field-value.test.ts +27 -0
- package/src/components/ui/panels/multi-field-value.ts +20 -1
- package/src/components/ui/panels/multi-height-mode.tsx +8 -7
- package/src/components/ui/panels/multi-parametric-inspector.tsx +122 -34
- package/src/components/ui/panels/multi-selection-panel.tsx +75 -35
- package/src/components/ui/panels/node-display.ts +35 -24
- package/src/components/ui/panels/panel-manager.tsx +5 -3
- package/src/components/ui/panels/panel-wrapper.tsx +22 -109
- package/src/components/ui/panels/parametric-field-control.tsx +13 -10
- package/src/components/ui/panels/parametric-inspector.tsx +18 -12
- package/src/components/ui/panels/reference-panel.tsx +51 -35
- package/src/components/ui/panels/room-construction-rows.tsx +464 -65
- package/src/components/ui/panels/room-name-options.test.ts +36 -3
- package/src/components/ui/panels/room-name-options.ts +110 -11
- package/src/components/ui/panels/room-openings-field.tsx +21 -12
- package/src/components/ui/panels/room-panel.tsx +206 -99
- package/src/components/ui/panels/shape-choice.tsx +7 -5
- package/src/components/ui/panels/wall-region-list.tsx +7 -7
- package/src/components/ui/primitives/shortcut-token.tsx +10 -6
- package/src/components/ui/sidebar/icon-rail.tsx +11 -9
- package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +10 -10
- package/src/components/ui/sidebar/panels/items-panel/index.tsx +10 -9
- package/src/components/ui/sidebar/panels/settings-panel/index.tsx +3 -0
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +102 -32
- package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +4 -3
- package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/chimney-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/collection-tree-node.tsx +7 -5
- package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/default-names.ts +75 -0
- package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/elevator-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/gutter-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +117 -64
- package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +36 -3
- package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +7 -4
- package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +8 -2
- package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +8 -5
- package/src/components/ui/sidebar/panels/site-panel/shelf-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +8 -3
- package/src/components/ui/sidebar/panels/site-panel/solar-panel-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +8 -7
- package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +7 -6
- package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +16 -1
- package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +15 -8
- package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +4 -2
- package/src/components/ui/sidebar/panels/site-panel/zone-membership-checkbox.tsx +3 -1
- package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +18 -8
- package/src/components/ui/sidebar/panels/zone-panel/index.tsx +25 -14
- package/src/components/ui/sidebar/tab-bar.tsx +4 -1
- package/src/components/ui/sidebar/use-plugin-panels.tsx +19 -10
- package/src/components/ui/snap-target-badge.tsx +7 -6
- package/src/components/ui/wall-type/wall-type-editor-dialog.tsx +721 -0
- package/src/components/ui/wall-type/wall-type-menu.tsx +167 -0
- package/src/components/viewer/floorplan-compass-button.tsx +12 -3
- package/src/components/viewer/floorplan-preview.tsx +27 -19
- package/src/components/viewer/render-settings-menu.tsx +294 -0
- package/src/components/viewer/sky-control.tsx +710 -0
- package/src/components/viewer/use-viewer-ui-sounds.test.ts +15 -0
- package/src/components/viewer/use-viewer-ui-sounds.ts +46 -0
- package/src/components/viewer/viewer-controls-bar.tsx +278 -260
- package/src/components/viewer/viewer-hover-label.tsx +12 -4
- package/src/components/viewer/viewer-rooms.tsx +61 -4
- package/src/components/viewer/viewer-scene-header.tsx +28 -17
- package/src/components/viewer/viewer-stage-switcher.tsx +4 -2
- package/src/components/viewer-overlay.tsx +8 -0
- package/src/components/walkthrough-hud.tsx +75 -2
- package/src/hooks/use-keyboard.test.ts +85 -4
- package/src/hooks/use-keyboard.ts +65 -7
- package/src/hooks/use-selected-room.ts +12 -1
- package/src/i18n/floor-footprint-name.ts +30 -0
- package/src/i18n/level-name.ts +39 -0
- package/src/i18n/locales/en/messages.po +15117 -0
- package/src/i18n/locales/en/messages.ts +1 -0
- package/src/i18n/locales/en-XA/messages.ts +1 -0
- package/src/i18n/locales/es/messages.po +37501 -0
- package/src/i18n/locales/es/messages.ts +1 -0
- package/src/i18n/locales/fr/messages.po +37501 -0
- package/src/i18n/locales/fr/messages.ts +1 -0
- package/src/i18n/locales/ja/messages.po +37501 -0
- package/src/i18n/locales/ja/messages.ts +1 -0
- package/src/i18n/locales/zh-CN/messages.po +37501 -0
- package/src/i18n/locales/zh-CN/messages.ts +1 -0
- package/src/i18n/locales.test.ts +63 -0
- package/src/i18n/locales.ts +32 -0
- package/src/i18n/message-slot.tsx +25 -0
- package/src/i18n/node-messages.ts +169 -0
- package/src/i18n/pseudo-locale.ts +17 -0
- package/src/i18n/published-entry.test.ts +17 -0
- package/src/i18n/scene-theme-name.ts +16 -0
- package/src/index.tsx +156 -4
- package/src/lib/add-storey.test.ts +3 -3
- package/src/lib/contextual-help.test.ts +20 -1
- package/src/lib/contextual-help.ts +95 -19
- package/src/lib/continuation.ts +38 -11
- package/src/lib/floor-footprints.test.ts +2 -1
- package/src/lib/floor-foundation-support.test.ts +7 -3
- package/src/lib/floorplan/dimension-drive.test.ts +36 -2
- package/src/lib/floorplan/dimension-drive.ts +68 -3
- package/src/lib/floorplan/floorplan-export.test.ts +16 -5
- package/src/lib/floorplan/floorplan-export.tsx +13 -16
- package/src/lib/floorplan/floorplan-extension.test.ts +11 -12
- package/src/lib/floorplan/floorplan-extension.ts +37 -18
- package/src/lib/floorplan/floorplan-mode.test.ts +13 -6
- package/src/lib/floorplan/floorplan-mode.ts +14 -12
- package/src/lib/floorplan/floorplan-plugin-install.test.tsx +1 -1
- package/src/lib/floorplan/floorplan-readonly.ts +3 -3
- package/src/lib/floorplan/schedules.ts +10 -6
- package/src/lib/floorplan/site-plan/site-annotations.test.ts +46 -1
- package/src/lib/floorplan/site-plan/site-annotations.ts +3 -0
- package/src/lib/floorplan/site-plan/site-parts.ts +6 -3
- package/src/lib/geometry-script/author.test.ts +114 -0
- package/src/lib/geometry-script/author.ts +55 -23
- package/src/lib/geometry-script/client.ts +3 -0
- package/src/lib/geometry-script/finish-scripts.ts +7 -7
- package/src/lib/glb-export.test.ts +327 -0
- package/src/lib/glb-export.ts +70 -2
- package/src/lib/grid-frame.test.ts +56 -3
- package/src/lib/grid-frame.ts +28 -1
- package/src/lib/history.test.ts +2 -1
- package/src/lib/hud-title.ts +48 -24
- package/src/lib/ifc-export.test.ts +41 -1
- package/src/lib/inspector-card-mode.test.ts +3 -31
- package/src/lib/inspector-card-mode.ts +5 -10
- package/src/lib/inspector-expanded.test.ts +13 -0
- package/src/lib/inspector-expanded.ts +13 -1
- package/src/lib/keyboard-pan.test.ts +7 -0
- package/src/lib/keyboard-pan.ts +9 -2
- package/src/lib/layer-thickness.test.ts +22 -0
- package/src/lib/layer-thickness.ts +79 -0
- package/src/lib/lot/drop-in.test.ts +59 -1
- package/src/lib/lot/drop-in.ts +42 -50
- package/src/lib/material-swatch-style.ts +24 -0
- package/src/lib/measurement-parser.ts +7 -3
- package/src/lib/measurements.test.ts +17 -0
- package/src/lib/measurements.ts +20 -5
- package/src/lib/mezzanine-selection.test.ts +3 -1
- package/src/lib/orbit-near-plane.test.ts +12 -0
- package/src/lib/orbit-near-plane.ts +13 -0
- package/src/lib/paint-regions.test.ts +8 -5
- package/src/lib/paint-scope.test.ts +53 -0
- package/src/lib/paint-scope.ts +18 -4
- package/src/lib/panel-rows.ts +17 -8
- package/src/lib/reference-scale.ts +83 -0
- package/src/lib/room-built-on.test.ts +26 -12
- package/src/lib/room-built-on.ts +20 -2
- package/src/lib/room-construction.test.ts +28 -1
- package/src/lib/room-construction.ts +14 -0
- package/src/lib/room-controls-phase6.test.ts +140 -0
- package/src/lib/room-handle-drag.ts +557 -42
- package/src/lib/room-name-catalog.test.ts +8 -0
- package/src/lib/room-name-catalog.ts +8 -1
- package/src/lib/room-name-messages.test.ts +132 -0
- package/src/lib/room-name-messages.ts +147 -0
- package/src/lib/room-name-storage.test.ts +334 -0
- package/src/lib/room-push-dimensions.test.ts +37 -0
- package/src/lib/room-push-dimensions.ts +226 -2
- package/src/lib/room-selection.test.ts +23 -6
- package/src/lib/scene-clipboard.test.ts +70 -49
- package/src/lib/scene-clipboard.ts +9 -4
- package/src/lib/selection-cycle.ts +63 -0
- package/src/lib/separator-edit.test.ts +431 -0
- package/src/lib/separator-edit.ts +179 -0
- package/src/lib/separator-lines.ts +38 -0
- package/src/lib/sfx-bus.ts +27 -1
- package/src/lib/sfx-player.ts +16 -0
- package/src/lib/tool-cursor-icon.ts +5 -1
- package/src/lib/tool-shortcuts.ts +130 -0
- package/src/lib/viewer-selection.test.ts +28 -24
- package/src/lib/viewer-selection.ts +20 -5
- package/src/lib/wall-draw-variant.test.ts +7 -6
- package/src/lib/wall-draw-variant.ts +107 -6
- package/src/lib/wall-nudge.test.ts +44 -0
- package/src/lib/wall-nudge.ts +131 -0
- package/src/lib/wall-parallel-snap.test.ts +83 -0
- package/src/lib/wall-parallel-snap.ts +176 -0
- package/src/lib/wall-placement-pointer.test.ts +23 -0
- package/src/lib/wall-placement-pointer.ts +18 -0
- package/src/lib/wall-pull.test.ts +245 -0
- package/src/lib/wall-pull.ts +209 -0
- package/src/lib/wall-push-line-up.test.ts +132 -0
- package/src/lib/wall-region-list.ts +14 -5
- package/src/lib/wall-run-snap.test.ts +188 -0
- package/src/lib/wall-run-snap.ts +83 -0
- package/src/lib/wall-type.test.ts +125 -0
- package/src/lib/wall-type.ts +119 -0
- package/src/lib/window-interaction.test.ts +42 -0
- package/src/lib/window-interaction.ts +47 -5
- package/src/lib/world-grid-snap.test.ts +139 -2
- package/src/lib/world-grid-snap.ts +102 -105
- package/src/store/use-alignment-guides.ts +27 -1
- package/src/store/use-editor.tsx +48 -0
- package/src/store/use-floorplan-annotation-visibility.test.ts +64 -0
- package/src/store/use-floorplan-annotation-visibility.ts +47 -22
- package/src/store/use-wall-snap-indicator.ts +15 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type AnyNode,
|
|
3
3
|
type AnyNodeId,
|
|
4
|
+
doorPositionForFacing,
|
|
4
5
|
emitter,
|
|
5
6
|
nodeRegistry,
|
|
6
7
|
pauseSpaceDetection,
|
|
@@ -34,12 +35,15 @@ import { isActive } from '../lib/interaction/scope'
|
|
|
34
35
|
import { paintRegionModeActive } from '../lib/paint-region-mode'
|
|
35
36
|
import { popRoomSelection } from '../lib/room-selection-commands'
|
|
36
37
|
import { copySelectedNodesToEditorClipboard } from '../lib/scene-clipboard'
|
|
38
|
+
import { cycleSelectionAtPointer, trackSelectionCyclePointer } from '../lib/selection-cycle'
|
|
37
39
|
import { sfxEmitter } from '../lib/sfx-bus'
|
|
38
40
|
import { openSidebarPanel } from '../lib/sidebar-panel'
|
|
39
41
|
import { activeSiteNode, clampBrushRadius } from '../lib/terrain-sculpt'
|
|
42
|
+
import { armToolShortcut, toolShortcutForKey } from '../lib/tool-shortcuts'
|
|
40
43
|
import { isTypingTarget } from '../lib/typing-target'
|
|
41
44
|
import { leaveUnitFocus } from '../lib/units'
|
|
42
|
-
import {
|
|
45
|
+
import { subscribeWallKindReset } from '../lib/wall-draw-variant'
|
|
46
|
+
import { isWallNudgeKey, nudgeSelectedWall } from '../lib/wall-nudge'
|
|
43
47
|
import useDeleteConfirmation from '../store/use-delete-confirmation'
|
|
44
48
|
import useEditor, { getActiveContinuationContext, getActiveSnapContext } from '../store/use-editor'
|
|
45
49
|
import useInteractionScope, {
|
|
@@ -49,6 +53,14 @@ import useInteractionScope, {
|
|
|
49
53
|
import { groupCurrentSelection, ungroupCurrentSelection } from '../store/use-session-groups'
|
|
50
54
|
import { activeViewLayout } from '../store/view-layout'
|
|
51
55
|
|
|
56
|
+
const pickKeyFields = (e: KeyboardEvent) => ({
|
|
57
|
+
code: e.code,
|
|
58
|
+
shiftKey: e.shiftKey,
|
|
59
|
+
metaKey: e.metaKey,
|
|
60
|
+
ctrlKey: e.ctrlKey,
|
|
61
|
+
altKey: e.altKey,
|
|
62
|
+
})
|
|
63
|
+
|
|
52
64
|
export function hasSceneKeyboardFocus(): boolean {
|
|
53
65
|
const layout = activeViewLayout(useEditor.getState())
|
|
54
66
|
return isSceneView(layout.panes[layout.focus])
|
|
@@ -208,13 +220,12 @@ export const runHistoryShortcut = (direction: 'undo' | 'redo') => {
|
|
|
208
220
|
}
|
|
209
221
|
|
|
210
222
|
/**
|
|
211
|
-
* B: the wall tool on
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* host may drop the armed tool when the panel changes.
|
|
223
|
+
* B: the wall tool on the Rooms shape picked last (Rectangle, Polygon or Walls,
|
|
224
|
+
* kept with the editor preferences; Rectangle until one is picked), with the
|
|
225
|
+
* Build panel showing, so the lit tile says what is in hand. The panel opens
|
|
226
|
+
* before the tool is armed: a host may drop the armed tool when the panel changes.
|
|
215
227
|
*/
|
|
216
228
|
export const armWallToolFromShortcut = () => {
|
|
217
|
-
selectWallDrawVariant('rectangle')
|
|
218
229
|
openSidebarPanel(['build'])
|
|
219
230
|
useEditor.getState().armToolMode({ mode: 'build', tool: 'wall' })
|
|
220
231
|
}
|
|
@@ -257,6 +268,8 @@ export const isToolOwnedRotation = () => {
|
|
|
257
268
|
(editor.tool === 'door' ||
|
|
258
269
|
editor.tool === 'window' ||
|
|
259
270
|
editor.tool === 'roof' ||
|
|
271
|
+
editor.tool === 'stair' ||
|
|
272
|
+
editor.tool === 'elevator' ||
|
|
260
273
|
// The item tool is mounted for the build mode, but it only owns R/T
|
|
261
274
|
// when a catalog item is actually selected and a placement draft can
|
|
262
275
|
// exist. Without this check, selecting an existing item in the 2D plan
|
|
@@ -312,6 +325,7 @@ export const useKeyboard = ({
|
|
|
312
325
|
if (disabled) {
|
|
313
326
|
return
|
|
314
327
|
}
|
|
328
|
+
trackSelectionCyclePointer()
|
|
315
329
|
|
|
316
330
|
// True while an active placement tool owns R/T. Door/window tools flip the
|
|
317
331
|
// draft, item / lean-to placement rotates its draft, and the roof tool turns
|
|
@@ -467,6 +481,18 @@ export const useKeyboard = ({
|
|
|
467
481
|
}
|
|
468
482
|
}
|
|
469
483
|
|
|
484
|
+
// Drafting tools on Shift with D / W / S / R, where the bare key pans or
|
|
485
|
+
// rotates (lib/tool-shortcuts). An armed placement keeps Shift+R as its own R.
|
|
486
|
+
const toolShortcut = isVersionPreviewMode
|
|
487
|
+
? null
|
|
488
|
+
: toolShortcutForKey({ ...pickKeyFields(e), repeat: false })
|
|
489
|
+
if (toolShortcut && !(toolShortcut === 'roof' && isToolOwnedRotation())) {
|
|
490
|
+
e.preventDefault()
|
|
491
|
+
// A held chord repeats: arm once, and never let a repeat fall through to bare R.
|
|
492
|
+
if (!e.repeat) armToolShortcut(toolShortcut)
|
|
493
|
+
return
|
|
494
|
+
}
|
|
495
|
+
|
|
470
496
|
if (e.key === 'Escape') {
|
|
471
497
|
e.preventDefault()
|
|
472
498
|
|
|
@@ -585,6 +611,31 @@ export const useKeyboard = ({
|
|
|
585
611
|
}
|
|
586
612
|
}
|
|
587
613
|
}
|
|
614
|
+
} else if (isWallNudgeKey(e.key) && !e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) {
|
|
615
|
+
// Bare arrows nudge a selected wall an inch in the floor plan.
|
|
616
|
+
const editor = useEditor.getState()
|
|
617
|
+
if (
|
|
618
|
+
isVersionPreviewMode ||
|
|
619
|
+
editor.mode !== 'select' ||
|
|
620
|
+
useInteractionScope.getState().scope.kind !== 'idle' ||
|
|
621
|
+
editor.isFirstPersonMode
|
|
622
|
+
) {
|
|
623
|
+
return
|
|
624
|
+
}
|
|
625
|
+
if (nudgeSelectedWall(e.key)) e.preventDefault()
|
|
626
|
+
} else if (e.key === 'Tab' && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
|
627
|
+
// Tab steps the selection to the next object under the pointer in the
|
|
628
|
+
// floor plan (Shift+Tab back): a wall hidden under another is reachable.
|
|
629
|
+
const editor = useEditor.getState()
|
|
630
|
+
if (
|
|
631
|
+
isVersionPreviewMode ||
|
|
632
|
+
editor.mode !== 'select' ||
|
|
633
|
+
useInteractionScope.getState().scope.kind !== 'idle' ||
|
|
634
|
+
editor.isFirstPersonMode
|
|
635
|
+
) {
|
|
636
|
+
return
|
|
637
|
+
}
|
|
638
|
+
if (cycleSelectionAtPointer(e.shiftKey)) e.preventDefault()
|
|
588
639
|
} else if (
|
|
589
640
|
(e.key === 'r' || e.key === 'R') &&
|
|
590
641
|
!e.metaKey &&
|
|
@@ -600,7 +651,7 @@ export const useKeyboard = ({
|
|
|
600
651
|
// open/close toggle lives on E. Windows still use R to toggle
|
|
601
652
|
// their open/closed state.
|
|
602
653
|
//
|
|
603
|
-
// Skipped while
|
|
654
|
+
// Skipped while a placement tool (item, door, window, roof, stair…) owns rotation.
|
|
604
655
|
// The user can still have a node selected during placement; without this
|
|
605
656
|
// guard both the draft and the selection would rotate.
|
|
606
657
|
//
|
|
@@ -637,6 +688,11 @@ export const useKeyboard = ({
|
|
|
637
688
|
useScene.getState().updateNode(node.id, {
|
|
638
689
|
side: node.side === 'front' ? 'back' : 'front',
|
|
639
690
|
rotation: [node.rotation[0], node.rotation[1] + Math.PI, node.rotation[2]],
|
|
691
|
+
position: doorPositionForFacing(node, [
|
|
692
|
+
node.rotation[0],
|
|
693
|
+
node.rotation[1] + Math.PI,
|
|
694
|
+
node.rotation[2],
|
|
695
|
+
]),
|
|
640
696
|
})
|
|
641
697
|
if (node.parentId) {
|
|
642
698
|
useScene.getState().dirtyNodes.add(node.parentId as AnyNodeId)
|
|
@@ -847,7 +903,9 @@ export const useKeyboard = ({
|
|
|
847
903
|
window.addEventListener('keydown', handleSessionGroupKeyDown, true)
|
|
848
904
|
window.addEventListener('keydown', handleKeyDown)
|
|
849
905
|
window.addEventListener('keyup', handleKeyUp)
|
|
906
|
+
const unsubscribeWallKind = subscribeWallKindReset()
|
|
850
907
|
return () => {
|
|
908
|
+
unsubscribeWallKind()
|
|
851
909
|
window.removeEventListener('keydown', handleSessionGroupKeyDown, true)
|
|
852
910
|
window.removeEventListener('keydown', handleKeyDown)
|
|
853
911
|
window.removeEventListener('keyup', handleKeyUp)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { type AnyNode, type AnyNodeId, useScene } from '@pascal-app/core'
|
|
3
|
+
import { type AnyNode, type AnyNodeId, nodeRegistry, useScene } from '@pascal-app/core'
|
|
4
4
|
import { useViewer } from '@pascal-app/viewer'
|
|
5
5
|
import { useCallback, useSyncExternalStore } from 'react'
|
|
6
|
+
import { getFloorplanNodeExtension } from '../lib/floorplan/floorplan-extension'
|
|
6
7
|
import { selectionEnabled } from '../lib/interaction/scope'
|
|
7
8
|
import {
|
|
8
9
|
type RoomKey,
|
|
@@ -134,8 +135,18 @@ export function hoverRoomFromHit(
|
|
|
134
135
|
return !!room
|
|
135
136
|
}
|
|
136
137
|
|
|
138
|
+
/**
|
|
139
|
+
* The room a plan hit picks first. A kind whose plan extension declares
|
|
140
|
+
* `planHitSelectsNode` (a wall: a thin band between two rooms whose interiors
|
|
141
|
+
* are clickable in their own right) keeps the hit: picking a room by which
|
|
142
|
+
* half of the band the pointer landed on made thin partitions take several
|
|
143
|
+
* clicks. 3D keeps them room-first, where a room's floor is often hidden
|
|
144
|
+
* behind its walls.
|
|
145
|
+
*/
|
|
137
146
|
export function resolvePlanRoomHit(nodeId: string | null, point: readonly [number, number]) {
|
|
138
147
|
const node = nodeId ? useScene.getState().nodes[nodeId as AnyNodeId] : null
|
|
148
|
+
if (node && getFloorplanNodeExtension(nodeRegistry.get(node.type))?.planHitSelectsNode)
|
|
149
|
+
return null
|
|
139
150
|
const levelId = node?.parentId ?? useViewer.getState().selection.levelId
|
|
140
151
|
return levelId ? resolveEditorRoomHit(node ?? null, levelId, point, '2d') : null
|
|
141
152
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AnyNode,
|
|
3
|
+
floorFootprintNaming,
|
|
4
|
+
type PascalI18n,
|
|
5
|
+
type SlabNode,
|
|
6
|
+
} from '@pascal-app/core'
|
|
7
|
+
import { displayRoomName } from '../lib/room-name-messages'
|
|
8
|
+
|
|
9
|
+
/** `floorFootprintName` in the UI language; MCP and agents keep core's English. */
|
|
10
|
+
export function localizedFloorFootprintName(
|
|
11
|
+
nodes: Readonly<Record<string, AnyNode>>,
|
|
12
|
+
plate: SlabNode,
|
|
13
|
+
i18n: PascalI18n,
|
|
14
|
+
): string {
|
|
15
|
+
const naming = floorFootprintNaming(nodes, plate)
|
|
16
|
+
switch (naming.kind) {
|
|
17
|
+
case 'named':
|
|
18
|
+
return naming.name
|
|
19
|
+
case 'room':
|
|
20
|
+
return i18n._({
|
|
21
|
+
id: 'editor.floorFootprint.room',
|
|
22
|
+
message: '{room} floor',
|
|
23
|
+
values: { room: displayRoomName(naming.room, i18n) },
|
|
24
|
+
})
|
|
25
|
+
case 'shared':
|
|
26
|
+
return i18n._({ id: 'editor.floorFootprint.shared', message: 'Shared floor' })
|
|
27
|
+
case 'area':
|
|
28
|
+
return i18n._({ id: 'editor.floorFootprint.area', message: 'Floor area' })
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { getDefaultLevelName, levelDisplayNumber, type PascalI18n } from '@pascal-app/core'
|
|
2
|
+
|
|
3
|
+
type DisplayLevel = {
|
|
4
|
+
level?: number
|
|
5
|
+
name?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** The level's own name, or undefined while it carries a generated default. */
|
|
9
|
+
export function authoredLevelName(level: DisplayLevel): string | undefined {
|
|
10
|
+
const levelNumber = level.level ?? 0
|
|
11
|
+
const name = level.name?.trim()
|
|
12
|
+
return name && name !== `Level ${levelNumber}` && name !== getDefaultLevelName(levelNumber)
|
|
13
|
+
? name
|
|
14
|
+
: undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function localizedLevelName(level: DisplayLevel, i18n: PascalI18n, locale: string): string {
|
|
18
|
+
const levelNumber = level.level ?? 0
|
|
19
|
+
const authoredName = authoredLevelName(level)
|
|
20
|
+
if (authoredName) return authoredName
|
|
21
|
+
if (levelNumber === 0) {
|
|
22
|
+
return i18n._({ id: 'core.level.groundFloor', message: 'Ground floor' })
|
|
23
|
+
}
|
|
24
|
+
if (levelNumber === -1) {
|
|
25
|
+
return i18n._({ id: 'core.level.basement', message: 'Basement' })
|
|
26
|
+
}
|
|
27
|
+
if (levelNumber < -1) {
|
|
28
|
+
return i18n._({
|
|
29
|
+
id: 'core.level.basementNumber',
|
|
30
|
+
message: 'Basement {number}',
|
|
31
|
+
values: { number: -levelNumber },
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
return i18n._({
|
|
35
|
+
id: 'core.level.floorNumber',
|
|
36
|
+
message: 'Floor {number}',
|
|
37
|
+
values: { number: levelDisplayNumber(levelNumber, locale) },
|
|
38
|
+
})
|
|
39
|
+
}
|