@pascal-app/editor 1.0.0-beta.4 → 1.0.0
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/LICENSE +21 -0
- package/bunfig.toml +4 -0
- package/package.json +15 -8
- package/scripts/generate-print-golden-house.ts +89 -0
- package/src/components/editor/alignment-3d-guide-layer.tsx +12 -3
- package/src/components/editor/bake-exporter.tsx +1 -0
- package/src/components/editor/camera-dragging-lifecycle.test.ts +41 -0
- package/src/components/editor/camera-dragging-lifecycle.ts +10 -2
- package/src/components/editor/capture-camera-rig.tsx +59 -0
- package/src/components/editor/custom-camera-controls.tsx +20 -11
- package/src/components/editor/editor-layout-mobile.tsx +6 -6
- package/src/components/editor/editor-layout-v2.tsx +17 -5
- package/src/components/editor/elevation-3d-guide-layer.tsx +3 -2
- package/src/components/editor/export-manager.tsx +175 -33
- package/src/components/editor/first-person/build-collider-world.test.ts +30 -0
- package/src/components/editor/first-person-controls.tsx +182 -57
- package/src/components/editor/floating-action-menu.tsx +55 -55
- package/src/components/editor/floorplan-background-selection.test.ts +31 -4
- package/src/components/editor/floorplan-background-selection.ts +27 -7
- package/src/components/editor/floorplan-panel.tsx +81 -57
- package/src/components/editor/grid.tsx +12 -7
- package/src/components/editor/group-actions.ts +34 -50
- package/src/components/editor/group-floating-action-menu.tsx +30 -15
- package/src/components/editor/group-move-3d.ts +51 -21
- package/src/components/editor/group-transform-shared.test.ts +78 -0
- package/src/components/editor/group-transform-shared.ts +74 -7
- package/src/components/editor/handles/handle-arrow-raycast.test.ts +86 -0
- package/src/components/editor/handles/handle-arrow.tsx +109 -48
- package/src/components/editor/handles/linear-resize-drag.ts +67 -0
- package/src/components/editor/handles/resize-snap.test.ts +46 -0
- package/src/components/editor/handles/resize-snap.ts +10 -1
- package/src/components/editor/handles/use-handle-drag.ts +18 -1
- package/src/components/editor/index.tsx +252 -46
- package/src/components/editor/measurement-pill.tsx +12 -12
- package/src/components/editor/node-action-menu.tsx +42 -1
- package/src/components/editor/node-arrow-handles.tsx +47 -58
- package/src/components/editor/opening-guides-3d-layer.tsx +13 -4
- package/src/components/editor/selection-manager.tsx +132 -47
- package/src/components/editor/site-edge-labels.tsx +2 -1
- package/src/components/editor/snapshot-capture-overlay.tsx +309 -41
- package/src/components/editor/snapshot-capture.test.ts +422 -0
- package/src/components/editor/snapshot-capture.ts +145 -0
- package/src/components/editor/thumbnail-generator.tsx +295 -232
- package/src/components/editor/use-floorplan-background-placement.ts +53 -5
- package/src/components/editor/wall-measurement-label.tsx +3 -2
- package/src/components/editor/wall-move-side-handles.tsx +299 -7
- package/src/components/editor-2d/floorplan-group-action-menu.tsx +23 -16
- package/src/components/editor-2d/floorplan-group-move.tsx +67 -33
- package/src/components/editor-2d/floorplan-registered-tool-layer.tsx +3 -1
- package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +129 -38
- package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +14 -1
- package/src/components/editor-2d/renderers/floorplan-geometry-renderer.test.tsx +16 -0
- package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +2 -0
- package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +52 -3
- package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +196 -1
- package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +204 -114
- package/src/components/systems/ceiling/ceiling-bracket-batch.test.ts +402 -0
- package/src/components/systems/ceiling/ceiling-bracket-batch.ts +371 -0
- package/src/components/systems/ceiling/ceiling-selection-affordance-system.test.ts +347 -0
- package/src/components/systems/ceiling/ceiling-selection-affordance-system.tsx +281 -305
- package/src/components/systems/roof/roof-edit-system.test.tsx +120 -0
- package/src/components/systems/roof/roof-edit-system.tsx +10 -19
- package/src/components/systems/selection-affordance-manager.tsx +59 -9
- package/src/components/systems/selection-affordance-services.ts +19 -0
- package/src/components/systems/stair/stair-edit-system.tsx +5 -2
- package/src/components/tools/fence/fence-drafting.test.ts +100 -0
- package/src/components/tools/fence/fence-drafting.ts +6 -25
- package/src/components/tools/item/draft-creation.test.ts +12 -0
- package/src/components/tools/item/draft-creation.ts +10 -0
- package/src/components/tools/item/face-host-commit.test.ts +65 -0
- package/src/components/tools/item/face-host-commit.ts +56 -0
- package/src/components/tools/item/face-host-preview.test.ts +77 -0
- package/src/components/tools/item/face-host-preview.ts +82 -0
- package/src/components/tools/item/move-tool.tsx +4 -3
- package/src/components/tools/item/placement-math.test.ts +11 -1
- package/src/components/tools/item/placement-math.ts +0 -20
- package/src/components/tools/item/placement-strategies.test.ts +494 -0
- package/src/components/tools/item/placement-strategies.ts +192 -24
- package/src/components/tools/item/placement-surface.test.ts +61 -0
- package/src/components/tools/item/placement-surface.ts +24 -0
- package/src/components/tools/item/placement-types.ts +6 -0
- package/src/components/tools/item/test-face-host.ts +121 -0
- package/src/components/tools/item/use-draft-node.test.tsx +336 -0
- package/src/components/tools/item/use-draft-node.ts +26 -4
- package/src/components/tools/item/use-placement-coordinator.tsx +447 -180
- package/src/components/tools/registered-tool-install-lifecycle.test.tsx +256 -0
- package/src/components/tools/registry/move-registry-node-tool.test.ts +10 -0
- package/src/components/tools/registry/move-registry-node-tool.tsx +306 -110
- package/src/components/tools/registry-tool-context.tsx +30 -0
- package/src/components/tools/select/box-select-tool.tsx +3 -1
- package/src/components/tools/select/marquee-footprint.test.ts +53 -0
- package/src/components/tools/select/marquee-footprint.ts +29 -0
- package/src/components/tools/shared/placement-box.tsx +63 -8
- package/src/components/tools/shared/placement-dimension-guides.tsx +121 -0
- package/src/components/tools/shared/pointer-support-cap.test.ts +319 -17
- package/src/components/tools/shared/pointer-support-cap.ts +45 -8
- package/src/components/tools/site/terrain-brush-cursor.tsx +2 -1
- package/src/components/tools/site/terrain-sculpt-grid.tsx +9 -5
- package/src/components/tools/site/terrain-sculpt-tool.tsx +1 -1
- package/src/components/tools/stair/stair-tool.tsx +127 -74
- package/src/components/tools/tool-manager.tsx +25 -8
- package/src/components/tools/wall/wall-drafting.test.ts +527 -4
- package/src/components/tools/wall/wall-drafting.ts +55 -462
- package/src/components/ui/action-menu/control-modes.tsx +9 -6
- package/src/components/ui/action-menu/index.tsx +11 -1
- package/src/components/ui/command-palette/editor-commands.tsx +12 -13
- package/src/components/ui/command-palette/index.tsx +7 -2
- package/src/components/ui/controls/material-paint-panel.tsx +6 -4
- package/src/components/ui/controls/material-picker.tsx +4 -4
- package/src/components/ui/controls/scene-material-list.tsx +6 -5
- package/src/components/ui/controls/segmented-control.tsx +8 -1
- package/src/components/ui/controls/slider-control.tsx +19 -3
- package/src/components/ui/controls/toggle-control.tsx +18 -5
- package/src/components/ui/controls/tool-options-panel.tsx +126 -0
- package/src/components/ui/floating-level-selector.tsx +23 -6
- package/src/components/ui/helpers/contextual-helper-panel.tsx +9 -0
- package/src/components/ui/helpers/helper-manager.tsx +47 -11
- package/src/components/ui/helpers/item-helper.tsx +1 -1
- package/src/components/ui/helpers/registered-tool-helper.tsx +21 -0
- package/src/components/ui/panels/homogeneous-selection.test.ts +80 -0
- package/src/components/ui/panels/homogeneous-selection.ts +47 -0
- package/src/components/ui/panels/mobile-selection-bar.tsx +11 -5
- package/src/components/ui/panels/multi-field-value.test.ts +209 -0
- package/src/components/ui/panels/multi-field-value.ts +163 -0
- package/src/components/ui/panels/multi-height-mode.tsx +185 -0
- package/src/components/ui/panels/multi-parametric-inspector.tsx +263 -0
- package/src/components/ui/panels/multi-selection-panel.tsx +78 -26
- package/src/components/ui/panels/node-display.ts +4 -0
- package/src/components/ui/panels/panel-manager.tsx +77 -3
- package/src/components/ui/panels/panel-wrapper.tsx +228 -12
- package/src/components/ui/panels/parametric-field-control.tsx +173 -0
- package/src/components/ui/panels/parametric-field-utils.ts +18 -0
- package/src/components/ui/panels/parametric-inspector.tsx +29 -162
- package/src/components/ui/panels/reference-panel.tsx +31 -1
- package/src/components/ui/primitives/shortcut-token.tsx +23 -1
- package/src/components/ui/scene-loader.tsx +35 -0
- package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +7 -2
- package/src/components/ui/sidebar/panels/settings-panel/index.tsx +390 -36
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +31 -23
- package/src/components/ui/sidebar/panels/settings-panel/print-export-button.test.ts +140 -0
- package/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +109 -0
- package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +19 -5
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +128 -46
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +5 -2
- package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +28 -11
- package/src/components/ui/sidebar/panels/site-panel/tree-node.test.ts +8 -0
- package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +22 -7
- package/src/components/ui/sidebar/tab-bar.tsx +9 -1
- package/src/components/ui/sidebar/use-plugin-panels.tsx +17 -2
- package/src/components/viewer/floorplan-compass-button.tsx +50 -0
- package/src/components/viewer/floorplan-preview-geometry.test.ts +107 -0
- package/src/components/viewer/floorplan-preview-geometry.ts +281 -0
- package/src/components/viewer/floorplan-preview-navigation.test.ts +43 -0
- package/src/components/viewer/floorplan-preview-navigation.ts +62 -0
- package/src/components/viewer/floorplan-preview.tsx +1069 -0
- package/src/components/viewer/use-viewer-camera-navigation-sync.ts +140 -0
- package/src/components/viewer/viewer-scene-header.tsx +2 -1
- package/src/components/viewer/viewer-stage-modes.test.ts +38 -0
- package/src/components/viewer/viewer-stage-modes.ts +49 -0
- package/src/components/viewer/viewer-stage-switcher.tsx +95 -0
- package/src/components/viewer/viewer-stage.test.tsx +47 -0
- package/src/components/viewer/viewer-stage.tsx +221 -0
- package/src/components/viewer-overlay.tsx +13 -30
- package/src/components/viewer-zone-system.tsx +6 -2
- package/src/components/walkthrough-hud.tsx +19 -10
- package/src/hooks/use-auto-save.test.ts +122 -1
- package/src/hooks/use-auto-save.ts +119 -13
- package/src/hooks/use-ceiling-events.test.ts +122 -0
- package/src/hooks/use-drag-action.ts +17 -3
- package/src/hooks/use-grid-events.test.ts +240 -0
- package/src/hooks/use-grid-events.ts +190 -11
- package/src/hooks/use-keyboard.test.ts +244 -0
- package/src/hooks/use-keyboard.ts +164 -63
- package/src/hooks/use-registered-tool-enabled.ts +20 -0
- package/src/hooks/use-save-shortcut.ts +33 -0
- package/src/index.tsx +109 -4
- package/src/lib/active-placement-surface.test.ts +16 -0
- package/src/lib/active-placement-surface.ts +14 -0
- package/src/lib/ceiling-surface-raycast.test.ts +64 -0
- package/src/lib/ceiling-surface-raycast.ts +12 -0
- package/src/lib/contextual-help-extension.ts +17 -0
- package/src/lib/contextual-help.test.ts +8 -0
- package/src/lib/contextual-help.ts +8 -0
- package/src/lib/continuation.test.ts +11 -0
- package/src/lib/continuation.ts +8 -1
- package/src/lib/direct-manipulation.test.ts +132 -0
- package/src/lib/direct-manipulation.ts +38 -1
- package/src/lib/editor-api.ts +6 -3
- package/src/lib/elevation-guides.test.ts +28 -1
- package/src/lib/elevation-guides.ts +22 -7
- package/src/lib/floating-menu-scale.test.ts +29 -0
- package/src/lib/floating-menu-scale.ts +14 -0
- package/src/lib/floorplan/apply-alignment.test.ts +47 -2
- package/src/lib/floorplan/apply-alignment.ts +10 -1
- package/src/lib/floorplan/floorplan-export.test.ts +397 -1
- package/src/lib/floorplan/floorplan-export.tsx +111 -16
- package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +26 -0
- package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +32 -24
- package/src/lib/floorplan/floorplan-readonly.test.ts +47 -0
- package/src/lib/floorplan/floorplan-readonly.ts +85 -0
- package/src/lib/floorplan-grid-event-point.test.ts +29 -0
- package/src/lib/floorplan-grid-event-point.ts +13 -0
- package/src/lib/glb-export.test.ts +1169 -21
- package/src/lib/glb-export.ts +629 -101
- package/src/lib/grid-event-presentation.ts +16 -0
- package/src/lib/history.test.ts +523 -77
- package/src/lib/history.ts +133 -14
- package/src/lib/host-tree-children.test.ts +27 -0
- package/src/lib/host-tree-children.ts +79 -0
- package/src/lib/inspector-card-mode.test.ts +92 -0
- package/src/lib/inspector-card-mode.ts +60 -0
- package/src/lib/interaction/hot-set.test.ts +10 -1
- package/src/lib/interaction/hot-set.ts +3 -1
- package/src/lib/interaction/overlay-policy.test.ts +33 -1
- package/src/lib/interaction/overlay-policy.ts +16 -0
- package/src/lib/interaction/registered-drafting.ts +36 -0
- package/src/lib/interaction/scope.ts +31 -0
- package/src/lib/level-print-export.test.ts +484 -0
- package/src/lib/level-print-export.ts +526 -0
- package/src/lib/local-project-presentation-persistence.test.ts +302 -0
- package/src/lib/local-project-presentation-persistence.ts +335 -0
- package/src/lib/material-paint.ts +2 -0
- package/src/lib/measurement-parser.ts +3 -0
- package/src/lib/measurements.test.ts +4 -0
- package/src/lib/model-export.ts +29 -0
- package/src/lib/paint-preview-owner.ts +71 -0
- package/src/lib/paint-scope.test.ts +58 -2
- package/src/lib/paint-scope.ts +8 -2
- package/src/lib/planar-cursor-placement.test.ts +178 -1
- package/src/lib/planar-cursor-placement.ts +61 -5
- package/src/lib/plugin-panels.test.ts +92 -1
- package/src/lib/plugin-panels.ts +48 -0
- package/src/lib/portable-export.test.ts +366 -0
- package/src/lib/portable-export.ts +969 -0
- package/src/lib/print-3mf.test.ts +86 -0
- package/src/lib/print-3mf.ts +161 -0
- package/src/lib/print-content-scope.test.ts +107 -0
- package/src/lib/print-content-scope.ts +90 -0
- package/src/lib/print-export.test.ts +294 -0
- package/src/lib/print-export.ts +735 -0
- package/src/lib/print-feature-thickness.test.ts +147 -0
- package/src/lib/print-feature-thickness.ts +180 -0
- package/src/lib/print-golden-house.test-fixture.ts +352 -0
- package/src/lib/print-golden-house.test.ts +249 -0
- package/src/lib/print-roof-solids.test.ts +133 -0
- package/src/lib/print-roof-solids.ts +630 -0
- package/src/lib/print-shell-compiler-baseline.test.ts +419 -0
- package/src/lib/print-shell-compiler-baseline.ts +225 -0
- package/src/lib/print-shell-compiler-manifold-core.ts +330 -0
- package/src/lib/print-shell-compiler-manifold-worker.ts +187 -0
- package/src/lib/print-shell-compiler-manifold.worker.ts +20 -0
- package/src/lib/print-shell-compiler-mesh-data.ts +32 -0
- package/src/lib/print-shell-compiler-protocol.ts +30 -0
- package/src/lib/print-shell-compiler.ts +273 -0
- package/src/lib/print-wall-solids.test.ts +194 -0
- package/src/lib/print-wall-solids.ts +328 -0
- package/src/lib/rigid-plan-svg-transform.test.ts +35 -0
- package/src/lib/rigid-plan-svg-transform.ts +24 -0
- package/src/lib/scene.ts +22 -8
- package/src/lib/selection-routing.test.ts +125 -6
- package/src/lib/selection-routing.ts +34 -1
- package/src/lib/session-groups.test.ts +88 -0
- package/src/lib/session-groups.ts +201 -0
- package/src/lib/sfx-bus.ts +4 -0
- package/src/lib/sfx-player.ts +8 -0
- package/src/lib/snapping-mode.test.ts +32 -4
- package/src/lib/snapping-mode.ts +11 -7
- package/src/lib/structured-clone-fallback.test.ts +45 -0
- package/src/lib/structured-clone-fallback.ts +24 -0
- package/src/lib/usdz-export.ts +38 -0
- package/src/lib/walkthrough-pointer-lock.ts +47 -0
- package/src/store/live-draft-preview-stores.test.ts +3 -0
- package/src/store/terrain-sculpt-mode.test.ts +3 -6
- package/src/store/tool-mode.test.ts +87 -0
- package/src/store/use-camera-hint-focus.ts +48 -0
- package/src/store/use-editor.tsx +299 -188
- package/src/store/use-floorplan-draft-preview.ts +9 -0
- package/src/store/use-interaction-scope.test.ts +23 -1
- package/src/store/use-interaction-scope.ts +63 -2
- package/src/store/use-placement-preview.ts +56 -3
- package/src/store/use-session-groups.ts +103 -0
- package/src/components/tools/roof/roof-tool.tsx +0 -656
- package/src/components/ui/helpers/roof-helper.tsx +0 -14
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import { Icon } from '@iconify/react'
|
|
4
|
-
import { Copy, Move, Search, Spline, Trash2 } from 'lucide-react'
|
|
4
|
+
import { Copy, Group, Move, PencilRuler, Search, Spline, Trash2, Ungroup } from 'lucide-react'
|
|
5
5
|
import type { MouseEventHandler, PointerEventHandler } from 'react'
|
|
6
6
|
|
|
7
7
|
type NodeActionMenuProps = {
|
|
@@ -10,7 +10,12 @@ type NodeActionMenuProps = {
|
|
|
10
10
|
onDelete?: MouseEventHandler<HTMLButtonElement>
|
|
11
11
|
onDuplicate?: MouseEventHandler<HTMLButtonElement>
|
|
12
12
|
onMove?: MouseEventHandler<HTMLButtonElement>
|
|
13
|
+
onEditMesh?: MouseEventHandler<HTMLButtonElement>
|
|
13
14
|
onCurve?: MouseEventHandler<HTMLButtonElement>
|
|
15
|
+
/** Session group (Ctrl/Cmd+G) — multi-selection floating pill. */
|
|
16
|
+
onGroup?: MouseEventHandler<HTMLButtonElement>
|
|
17
|
+
/** Dissolve session group (Ctrl/Cmd+Shift+G). */
|
|
18
|
+
onUngroup?: MouseEventHandler<HTMLButtonElement>
|
|
14
19
|
onPointerDown?: PointerEventHandler<HTMLDivElement>
|
|
15
20
|
onPointerUp?: PointerEventHandler<HTMLDivElement>
|
|
16
21
|
onPointerEnter?: PointerEventHandler<HTMLDivElement>
|
|
@@ -23,7 +28,10 @@ export function NodeActionMenu({
|
|
|
23
28
|
onDelete,
|
|
24
29
|
onDuplicate,
|
|
25
30
|
onMove,
|
|
31
|
+
onEditMesh,
|
|
26
32
|
onCurve,
|
|
33
|
+
onGroup,
|
|
34
|
+
onUngroup,
|
|
27
35
|
onPointerDown,
|
|
28
36
|
onPointerUp,
|
|
29
37
|
onPointerEnter,
|
|
@@ -59,6 +67,39 @@ export function NodeActionMenu({
|
|
|
59
67
|
<Move className="h-4 w-4" />
|
|
60
68
|
</button>
|
|
61
69
|
)}
|
|
70
|
+
{onEditMesh && (
|
|
71
|
+
<button
|
|
72
|
+
aria-label="Edit mesh"
|
|
73
|
+
className="tooltip-trigger rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
|
|
74
|
+
onClick={onEditMesh}
|
|
75
|
+
title="Edit mesh"
|
|
76
|
+
type="button"
|
|
77
|
+
>
|
|
78
|
+
<PencilRuler className="h-4 w-4" />
|
|
79
|
+
</button>
|
|
80
|
+
)}
|
|
81
|
+
{onGroup && (
|
|
82
|
+
<button
|
|
83
|
+
aria-label="Group selection"
|
|
84
|
+
className="tooltip-trigger rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
|
|
85
|
+
onClick={onGroup}
|
|
86
|
+
title="Group (Ctrl/Cmd+G)"
|
|
87
|
+
type="button"
|
|
88
|
+
>
|
|
89
|
+
<Group className="h-4 w-4" />
|
|
90
|
+
</button>
|
|
91
|
+
)}
|
|
92
|
+
{onUngroup && (
|
|
93
|
+
<button
|
|
94
|
+
aria-label="Ungroup selection"
|
|
95
|
+
className="tooltip-trigger rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
|
|
96
|
+
onClick={onUngroup}
|
|
97
|
+
title="Ungroup (Ctrl/Cmd+Shift+G)"
|
|
98
|
+
type="button"
|
|
99
|
+
>
|
|
100
|
+
<Ungroup className="h-4 w-4" />
|
|
101
|
+
</button>
|
|
102
|
+
)}
|
|
62
103
|
{onCurve && (
|
|
63
104
|
<button
|
|
64
105
|
aria-label="Curve"
|
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
HandleArrow,
|
|
63
63
|
NO_RAYCAST,
|
|
64
64
|
} from './handles/handle-arrow'
|
|
65
|
-
import {
|
|
65
|
+
import { createLinearResizeDragBinding } from './handles/linear-resize-drag'
|
|
66
66
|
import { resolveResizeSnapValue } from './handles/resize-snap'
|
|
67
67
|
import { type HandleDragControls, useHandleDrag } from './handles/use-handle-drag'
|
|
68
68
|
|
|
@@ -235,16 +235,15 @@ export function NodeArrowHandles() {
|
|
|
235
235
|
typeof def.handles === 'function'
|
|
236
236
|
? def.handles(node as never, descriptorSceneApi)
|
|
237
237
|
: (def.handles as HandleDescriptor[])
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
)
|
|
238
|
+
return all.filter((descriptor) => {
|
|
239
|
+
if (descriptor.kind === 'translate') return false
|
|
240
|
+
const visible =
|
|
241
|
+
'visible' in descriptor
|
|
242
|
+
? descriptor.visible?.(node as never, descriptorSceneApi)
|
|
243
|
+
: undefined
|
|
244
|
+
if ('shape' in descriptor && descriptor.shape === 'move-cross') return visible === true
|
|
245
|
+
return visible !== false
|
|
246
|
+
})
|
|
248
247
|
}, [node, def, descriptorSceneApi])
|
|
249
248
|
|
|
250
249
|
const shouldRender =
|
|
@@ -293,18 +292,25 @@ function NodeArrowHandlesForNode({
|
|
|
293
292
|
descriptors: HandleDescriptor[]
|
|
294
293
|
}) {
|
|
295
294
|
const parentId = node.parentId ?? null
|
|
296
|
-
const grandparentId = useScene((state) => {
|
|
297
|
-
if (!parentId) return null
|
|
298
|
-
const parent = state.nodes[parentId as AnyNodeId]
|
|
299
|
-
return parent?.parentId ?? null
|
|
300
|
-
})
|
|
301
295
|
|
|
302
296
|
const portalMode: HandlePortal = descriptors.some((d) => d.portal === 'grandparent')
|
|
303
297
|
? 'grandparent'
|
|
304
298
|
: 'parent'
|
|
305
299
|
|
|
300
|
+
const portalTargetResolver = descriptors.find(
|
|
301
|
+
(descriptor) => descriptor.portalTarget !== undefined,
|
|
302
|
+
)?.portalTarget
|
|
303
|
+
const descriptorSceneApi = useMemo(() => createSceneApi(useScene), [])
|
|
304
|
+
|
|
306
305
|
// Portal target: the mesh we createPortal into.
|
|
307
|
-
const portalTargetId =
|
|
306
|
+
const portalTargetId = useScene((state) => {
|
|
307
|
+
if (portalTargetResolver) {
|
|
308
|
+
return portalTargetResolver(node as never, descriptorSceneApi) ?? null
|
|
309
|
+
}
|
|
310
|
+
const parentId = node.parentId ?? null
|
|
311
|
+
if (!parentId || portalMode === 'parent') return parentId
|
|
312
|
+
return state.nodes[parentId as AnyNodeId]?.parentId ?? null
|
|
313
|
+
})
|
|
308
314
|
// Outer wrapper mirrors this mesh's local pose. For 'parent' mode the
|
|
309
315
|
// outer IS the node (so handles + drag math both live in node-local).
|
|
310
316
|
// For 'grandparent' the outer rides the parent and an inner group adds
|
|
@@ -710,10 +716,17 @@ function LinearArrow({
|
|
|
710
716
|
getPointerRay(event.nativeEvent.clientX, event.nativeEvent.clientY, _resizeRay),
|
|
711
717
|
) / localToWorldScale
|
|
712
718
|
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
?
|
|
716
|
-
|
|
719
|
+
const linearBinding =
|
|
720
|
+
descriptor.kind === 'linear-resize'
|
|
721
|
+
? createLinearResizeDragBinding({
|
|
722
|
+
descriptor,
|
|
723
|
+
initialNode,
|
|
724
|
+
nodeId,
|
|
725
|
+
sceneApi,
|
|
726
|
+
initialModifiers: { altKey: event.nativeEvent.altKey },
|
|
727
|
+
})
|
|
728
|
+
: null
|
|
729
|
+
const overrideId = linearBinding?.overrideId ?? nodeId
|
|
717
730
|
const initialValue = descriptor.currentValue(initialNode)
|
|
718
731
|
const minBound = resolveBound(descriptor.min, Number.NEGATIVE_INFINITY, initialNode, sceneApi)
|
|
719
732
|
const maxBound = resolveBound(descriptor.max, Number.POSITIVE_INFINITY, initialNode, sceneApi)
|
|
@@ -730,14 +743,9 @@ function LinearArrow({
|
|
|
730
743
|
// when the (snapped + clamped) value actually changes, so the cue
|
|
731
744
|
// tracks real size steps instead of every sub-pixel pointer jitter.
|
|
732
745
|
let lastTickValue = initialValue
|
|
733
|
-
let previewOverrideIds = new Set<AnyNodeId>()
|
|
734
|
-
|
|
735
746
|
return {
|
|
736
747
|
overrideId,
|
|
737
|
-
commit:
|
|
738
|
-
descriptor.kind === 'linear-resize' && descriptor.commit
|
|
739
|
-
? (patch) => descriptor.commit?.(initialNode, patch, sceneApi)
|
|
740
|
-
: undefined,
|
|
748
|
+
commit: linearBinding?.commit,
|
|
741
749
|
onBegin: () => {
|
|
742
750
|
// Always claim the handle-drag scope so the HUD knows a resize is the
|
|
743
751
|
// active interaction (keeps the idle select hints off-screen). The
|
|
@@ -755,12 +763,9 @@ function LinearArrow({
|
|
|
755
763
|
descriptor.onDragEnd?.(initialNode as never, sceneApi)
|
|
756
764
|
}
|
|
757
765
|
if (onDrag) useOpeningGuides.getState().clear()
|
|
758
|
-
|
|
759
|
-
useLiveNodeOverrides.getState().clear(previewId)
|
|
760
|
-
useScene.getState().markDirty(previewId)
|
|
761
|
-
}
|
|
766
|
+
linearBinding?.clearPreview()
|
|
762
767
|
},
|
|
763
|
-
move: ({ event: moveEvent, getPointerRay: getMovePointerRay }) => {
|
|
768
|
+
move: ({ event: moveEvent, modifiers, getPointerRay: getMovePointerRay }) => {
|
|
764
769
|
const currentPointer =
|
|
765
770
|
closestAxisParameterToRay(
|
|
766
771
|
_resizeOriginW,
|
|
@@ -772,43 +777,27 @@ function LinearArrow({
|
|
|
772
777
|
const linearDescriptor = descriptor.kind === 'linear-resize' ? descriptor : null
|
|
773
778
|
const snappedNext = resolveResizeSnapValue({
|
|
774
779
|
rawValue: rawNext,
|
|
780
|
+
fallbackValue: lastTickValue,
|
|
775
781
|
gridSnapEnabled: linearDescriptor?.gridSnap === true,
|
|
776
|
-
gridSnapActive: isGridSnapActive(),
|
|
782
|
+
gridSnapActive: isGridSnapActive() && !modifiers.altKey,
|
|
777
783
|
gridSnapStep: useEditor.getState().gridSnapStep,
|
|
778
|
-
magneticSnapActive: isMagneticSnapActive(),
|
|
784
|
+
magneticSnapActive: isMagneticSnapActive() && !modifiers.altKey,
|
|
779
785
|
magneticSnap: linearDescriptor?.magneticSnap
|
|
780
786
|
? (value) => linearDescriptor.magneticSnap?.(initialNode, value, sceneApi) ?? value
|
|
781
787
|
: undefined,
|
|
788
|
+
connectionSnapActive: !modifiers.altKey,
|
|
789
|
+
connectionSnap: linearDescriptor?.connectionSnap
|
|
790
|
+
? (value) => linearDescriptor.connectionSnap?.(initialNode, value, sceneApi) ?? value
|
|
791
|
+
: undefined,
|
|
782
792
|
})
|
|
783
793
|
const next = Math.min(maxBound, Math.max(minBound, snappedNext))
|
|
784
794
|
if (next !== lastTickValue) {
|
|
785
795
|
lastTickValue = next
|
|
786
796
|
sfxEmitter.emit('sfx:resize')
|
|
787
797
|
}
|
|
788
|
-
const patch =
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
const nextPreviewOverrideIds = replacePreviewOverrideIds(
|
|
792
|
-
previewOverrideIds,
|
|
793
|
-
previewEntries,
|
|
794
|
-
(previewId) => {
|
|
795
|
-
useLiveNodeOverrides.getState().clear(previewId)
|
|
796
|
-
useScene.getState().markDirty(previewId)
|
|
797
|
-
},
|
|
798
|
-
)
|
|
799
|
-
useLiveNodeOverrides
|
|
800
|
-
.getState()
|
|
801
|
-
.setMany(
|
|
802
|
-
previewEntries.map(([id, previewPatch]) => [
|
|
803
|
-
id,
|
|
804
|
-
previewPatch as Record<string, unknown>,
|
|
805
|
-
]),
|
|
806
|
-
)
|
|
807
|
-
for (const [previewId] of previewEntries) {
|
|
808
|
-
useScene.getState().markDirty(previewId)
|
|
809
|
-
}
|
|
810
|
-
previewOverrideIds = nextPreviewOverrideIds
|
|
811
|
-
}
|
|
798
|
+
const patch = linearBinding
|
|
799
|
+
? linearBinding.apply(next, modifiers)
|
|
800
|
+
: (descriptor.apply(initialNode as never, next, sceneApi) as Partial<AnyNode>)
|
|
812
801
|
// Let the kind publish live guides for the edge being resized.
|
|
813
802
|
onDrag?.({ ...(initialNode as object), ...patch } as AnyNode, sceneApi)
|
|
814
803
|
return patch
|
|
@@ -53,17 +53,26 @@ const mid = (a: OpeningGuideVec3, b: OpeningGuideVec3): OpeningGuideVec3 => [
|
|
|
53
53
|
export const OpeningGuides3DLayer = memo(function OpeningGuides3DLayer() {
|
|
54
54
|
const guides = useOpeningGuides((s) => s.guides)
|
|
55
55
|
const unit = useViewer((s) => s.unit)
|
|
56
|
+
const metricNotation = useViewer((s) => s.metricNotation)
|
|
56
57
|
if (guides.length === 0) return null
|
|
57
58
|
return (
|
|
58
59
|
<>
|
|
59
60
|
{guides.map((guide) => (
|
|
60
|
-
<OpeningGuide guide={guide} key={guide.id} unit={unit} />
|
|
61
|
+
<OpeningGuide guide={guide} key={guide.id} metricNotation={metricNotation} unit={unit} />
|
|
61
62
|
))}
|
|
62
63
|
</>
|
|
63
64
|
)
|
|
64
65
|
})
|
|
65
66
|
|
|
66
|
-
function OpeningGuide({
|
|
67
|
+
function OpeningGuide({
|
|
68
|
+
guide,
|
|
69
|
+
metricNotation,
|
|
70
|
+
unit,
|
|
71
|
+
}: {
|
|
72
|
+
guide: OpeningGuide3D
|
|
73
|
+
metricNotation: 'meters' | 'millimeters'
|
|
74
|
+
unit: 'metric' | 'imperial'
|
|
75
|
+
}) {
|
|
67
76
|
if (guide.kind === 'badge') {
|
|
68
77
|
return (
|
|
69
78
|
<Html
|
|
@@ -76,7 +85,7 @@ function OpeningGuide({ guide, unit }: { guide: OpeningGuide3D; unit: 'metric' |
|
|
|
76
85
|
className="whitespace-nowrap rounded-[3px] px-[5px] py-[2px] font-sans font-semibold text-[11px] text-white"
|
|
77
86
|
style={{ backgroundColor: BADGE_PILL }}
|
|
78
87
|
>
|
|
79
|
-
{`= ${formatMeasurement(guide.value, unit)}`}
|
|
88
|
+
{`= ${formatMeasurement(guide.value, unit, metricNotation)}`}
|
|
80
89
|
</div>
|
|
81
90
|
</Html>
|
|
82
91
|
)
|
|
@@ -97,7 +106,7 @@ function OpeningGuide({ guide, unit }: { guide: OpeningGuide3D; unit: 'metric' |
|
|
|
97
106
|
className="whitespace-nowrap rounded-[3px] px-[5px] py-[2px] font-medium font-sans text-[11px] text-white"
|
|
98
107
|
style={{ backgroundColor: DIMENSION_PILL }}
|
|
99
108
|
>
|
|
100
|
-
{formatMeasurement(guide.value, unit)}
|
|
109
|
+
{formatMeasurement(guide.value, unit, metricNotation)}
|
|
101
110
|
</div>
|
|
102
111
|
</Html>
|
|
103
112
|
) : null}
|