@pascal-app/editor 1.0.3 → 1.0.4
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 +11 -9
- package/src/components/editor/action-menu-button.tsx +83 -0
- package/src/components/editor/bake-thumbnail.tsx +315 -4
- package/src/components/editor/capture-level-picker.tsx +72 -0
- package/src/components/editor/custom-camera-controls.tsx +202 -57
- package/src/components/editor/delete-confirmation-dialog.tsx +297 -7
- package/src/components/editor/duplicate-node.ts +244 -0
- package/src/components/editor/editor-layout-mobile.tsx +36 -25
- package/src/components/editor/editor-layout-v2.tsx +131 -58
- package/src/components/editor/export-manager.tsx +34 -8
- package/src/components/editor/first-person/build-collider-world.test.ts +51 -0
- package/src/components/editor/first-person/build-collider-world.ts +6 -2
- package/src/components/editor/first-person/mechanism-targets.test.ts +75 -0
- package/src/components/editor/first-person/mechanism-targets.ts +36 -0
- package/src/components/editor/first-person-controls.tsx +205 -2
- package/src/components/editor/floating-action-menu.tsx +63 -207
- package/src/components/editor/floor-aware-camera-controls.test.ts +442 -0
- package/src/components/editor/floor-aware-camera-controls.ts +324 -0
- package/src/components/editor/floor-openings-overlay.tsx +243 -0
- package/src/components/editor/floor-region-controls.tsx +846 -0
- package/src/components/editor/floor-region-webgpu-materials.test.ts +12 -0
- package/src/components/editor/floor-surface.test.ts +165 -0
- package/src/components/editor/floor-surface.ts +182 -0
- package/src/components/editor/floorplan-background-selection.test.ts +11 -2
- package/src/components/editor/floorplan-background-selection.ts +1 -3
- package/src/components/editor/floorplan-panel.tsx +344 -342
- package/src/components/editor/footprint-height-handle.tsx +204 -0
- package/src/components/editor/group-actions.ts +54 -2
- package/src/components/editor/handles/handle-hit-priority.test.tsx +63 -0
- package/src/components/editor/handles/handle-hit-priority.tsx +37 -0
- package/src/components/editor/handles/swallow-next-click.test.ts +28 -0
- package/src/components/editor/handles/use-handle-drag.ts +269 -197
- package/src/components/editor/index.tsx +294 -169
- package/src/components/editor/join-walls-pill.tsx +44 -0
- package/src/components/editor/node-action-menu.tsx +68 -70
- package/src/components/editor/node-arrow-handles.tsx +25 -6
- package/src/components/editor/open-wall-ends-3d-layer.tsx +273 -0
- package/src/components/editor/open-wall-ends-hint.tsx +89 -0
- package/src/components/editor/quick-measurement-hud.tsx +3 -2
- package/src/components/editor/registry-action-contributions.test.tsx +63 -0
- package/src/components/editor/registry-action-contributions.tsx +80 -1
- package/src/components/editor/room-controls.tsx +847 -0
- package/src/components/editor/room-floor-highlight.tsx +128 -0
- package/src/components/editor/room-handles-2d.tsx +354 -0
- package/src/components/editor/room-handles.tsx +675 -0
- package/src/components/editor/room-highlight.tsx +225 -0
- package/src/components/editor/room-labels.test.ts +357 -0
- package/src/components/editor/room-labels.tsx +990 -0
- package/src/components/editor/room-transform-ghost.tsx +256 -0
- package/src/components/editor/room-webgpu-materials.test.ts +27 -0
- package/src/components/editor/selection-manager.tsx +451 -317
- package/src/components/editor/slab-hole-highlights.tsx +3 -0
- package/src/components/editor/snapshot-capture-overlay.tsx +4 -0
- package/src/components/editor/snapshot-capture.test.ts +52 -4
- package/src/components/editor/snapshot-capture.ts +30 -5
- package/src/components/editor/thumbnail-generator.test.ts +308 -0
- package/src/components/editor/thumbnail-generator.tsx +1035 -229
- package/src/components/editor/use-floorplan-background-placement.ts +31 -11
- package/src/components/editor/vector-edge-extractor.tsx +121 -0
- package/src/components/editor/views/host-view.tsx +61 -0
- package/src/components/editor/views/plugins-view.tsx +670 -0
- package/src/components/editor/views/scene-region.tsx +59 -0
- package/src/components/editor/views/use-editor-views.ts +57 -0
- package/src/components/editor/views/view-bar.tsx +220 -0
- package/src/components/editor/wall-justification.test.ts +140 -0
- package/src/components/editor/wall-move-side-handles.tsx +43 -142
- package/src/components/editor/wall-push-arrow.tsx +92 -0
- package/src/components/editor/wall-region-handles.tsx +509 -0
- package/src/components/editor/wall-snap-beacon-layer.tsx +3 -0
- package/src/components/editor-2d/floorplan-cursor-indicator-overlay.tsx +8 -4
- package/src/components/editor-2d/floorplan-open-wall-ends-layer.test.tsx +86 -0
- package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +290 -0
- package/src/components/editor-2d/floorplan-registry-action-menu.tsx +11 -1
- package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +113 -102
- package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.test.ts +156 -0
- package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.tsx +278 -0
- package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +77 -0
- package/src/components/editor-2d/renderers/{floorplan-draft-wall-measurement.tsx → floorplan-draft-measurement.tsx} +8 -8
- package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +4 -1
- package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +38 -8
- package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +291 -227
- package/src/components/editor-2d/svg-paths.ts +12 -15
- package/src/components/procedural-items/inspector.tsx +40 -15
- package/src/components/systems/ceiling/ceiling-selection-affordance-system.test.ts +97 -14
- package/src/components/systems/ceiling/ceiling-selection-affordance-system.tsx +18 -18
- package/src/components/systems/zone/zone-system.test.ts +47 -0
- package/src/components/systems/zone/zone-system.tsx +29 -68
- package/src/components/tools/item/placement-history.test.tsx +474 -0
- package/src/components/tools/item/placement-strategies.ts +8 -4
- package/src/components/tools/item/use-draft-node.test.tsx +432 -1
- package/src/components/tools/item/use-draft-node.ts +166 -95
- package/src/components/tools/item/use-placement-coordinator.tsx +93 -46
- package/src/components/tools/paint-region/use-paint-tint.ts +37 -0
- package/src/components/tools/paint-region/wall-paint-region-tool.tsx +466 -0
- package/src/components/tools/registry/move-registry-node-tool.tsx +3 -1
- package/src/components/tools/select/box-select-tool.tsx +2 -12
- package/src/components/tools/select/plane-box-select-tool.test.tsx +79 -0
- package/src/components/tools/select/plane-box-select-tool.tsx +35 -22
- package/src/components/tools/select/select-candidates.test.ts +37 -4
- package/src/components/tools/select/select-candidates.ts +15 -11
- package/src/components/tools/shared/cursor-sphere.tsx +36 -12
- package/src/components/tools/site/site-boundary-editor.tsx +1 -2
- package/src/components/tools/stair/stair-defaults.ts +0 -3
- package/src/components/tools/stair/stair-tool.tsx +90 -42
- package/src/components/tools/tool-manager.tsx +46 -20
- package/src/components/tools/wall/wall-drafting.test.ts +19 -4
- package/src/components/tools/zone/zone-tool.tsx +4 -12
- package/src/components/ui/action-menu/action-button.tsx +3 -0
- package/src/components/ui/action-menu/camera-actions.tsx +2 -1
- package/src/components/ui/action-menu/control-modes.tsx +2 -35
- package/src/components/ui/action-menu/measurement-control.tsx +3 -10
- package/src/components/ui/build-panel/build-panel.tsx +235 -0
- package/src/components/ui/command-palette/editor-commands.tsx +4 -30
- package/src/components/ui/command-palette/index.tsx +5 -24
- package/src/components/ui/controls/finish-swatch.tsx +110 -0
- package/src/components/ui/controls/material-paint-panel.tsx +97 -26
- package/src/components/ui/controls/material-picker.tsx +4 -1
- package/src/components/ui/controls/scene-material-list.tsx +4 -32
- package/src/components/ui/controls/select-control.tsx +65 -0
- package/src/components/ui/floating-level-selector.tsx +9 -14
- package/src/components/ui/helpers/building-helper.tsx +4 -1
- package/src/components/ui/helpers/contextual-helper-panel.tsx +154 -70
- package/src/components/ui/helpers/helper-manager.test.tsx +69 -0
- package/src/components/ui/helpers/helper-manager.tsx +325 -14
- package/src/components/ui/helpers/item-helper.tsx +8 -0
- package/src/components/ui/helpers/registered-tool-helper.tsx +8 -1
- package/src/components/ui/icon-ref.tsx +45 -1
- package/src/components/ui/level-duplicate-dialog.tsx +1 -1
- package/src/components/ui/node-icon-image.tsx +16 -0
- package/src/components/ui/panels/collections/collections-popover.tsx +20 -14
- package/src/components/ui/panels/floor-foundation-panel.tsx +551 -0
- package/src/components/ui/panels/floor-opening-panel.tsx +143 -0
- package/src/components/ui/panels/mobile-panel-sheet.tsx +2 -2
- package/src/components/ui/panels/mobile-selection-bar.tsx +2 -2
- package/src/components/ui/panels/multi-field-value.test.ts +26 -3
- package/src/components/ui/panels/multi-field-value.ts +6 -3
- package/src/components/ui/panels/multi-parametric-inspector.tsx +52 -2
- package/src/components/ui/panels/multi-selection-panel.tsx +43 -4
- package/src/components/ui/panels/node-display.ts +8 -3
- package/src/components/ui/panels/panel-manager.tsx +103 -68
- package/src/components/ui/panels/panel-wrapper.tsx +78 -36
- package/src/components/ui/panels/parametric-field-control.tsx +1 -1
- package/src/components/ui/panels/parametric-inspector.tsx +4 -4
- package/src/components/ui/panels/reference-panel.tsx +2 -3
- package/src/components/ui/panels/room-construction-rows.tsx +774 -0
- package/src/components/ui/panels/room-name-options.test.ts +55 -0
- package/src/components/ui/panels/room-name-options.ts +47 -0
- package/src/components/ui/panels/room-openings-field.tsx +110 -0
- package/src/components/ui/panels/room-panel.tsx +725 -0
- package/src/components/ui/panels/shape-choice.tsx +58 -0
- package/src/components/ui/panels/wall-region-list.tsx +109 -0
- package/src/components/ui/primitives/color-dot.tsx +36 -24
- package/src/components/ui/primitives/sidebar.tsx +2 -0
- package/src/components/ui/right-stack.test.ts +29 -0
- package/src/components/ui/right-stack.tsx +145 -0
- package/src/components/ui/sidebar/icon-rail.tsx +5 -0
- package/src/components/ui/sidebar/panels/settings-panel/index.tsx +31 -4
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +5 -5
- package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +4 -4
- package/src/components/ui/sidebar/panels/site-panel/chimney-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/collection-tree-node.tsx +197 -0
- package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/elevator-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +24 -11
- package/src/components/ui/sidebar/panels/site-panel/gutter-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +176 -211
- package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +30 -8
- package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +1 -3
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +4 -1
- package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +1 -3
- package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +1 -4
- package/src/components/ui/sidebar/panels/site-panel/shelf-tree-node.tsx +1 -3
- package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +21 -13
- package/src/components/ui/sidebar/panels/site-panel/solar-panel-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +0 -27
- package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +2 -3
- package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +1 -5
- package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +9 -4
- package/src/components/ui/sidebar/panels/zone-panel/index.tsx +0 -2
- package/src/components/ui/sidebar/tab-bar.tsx +10 -0
- package/src/components/ui/sidebar/use-plugin-panels.tsx +15 -5
- package/src/components/viewer/floorplan-compass-button.tsx +9 -1
- package/src/components/viewer/floorplan-preview.tsx +5 -6
- package/src/components/viewer/viewer-hover-label.tsx +34 -0
- package/src/components/viewer/viewer-rooms.tsx +175 -0
- package/src/components/viewer/viewer-scene-header.tsx +181 -145
- package/src/components/viewer/viewer-selection-manager.tsx +124 -0
- package/src/components/viewer/viewer-stage.tsx +2 -2
- package/src/components/viewer-zone-system.tsx +3 -8
- package/src/hooks/use-auto-save.integration.test.tsx +123 -9
- package/src/hooks/use-auto-save.ts +34 -8
- package/src/hooks/use-keyboard.test.ts +178 -3
- package/src/hooks/use-keyboard.ts +89 -71
- package/src/hooks/use-open-wall-ends.test.ts +99 -0
- package/src/hooks/use-open-wall-ends.ts +238 -0
- package/src/hooks/use-placement-notice.test.ts +48 -0
- package/src/hooks/use-placement-notice.ts +42 -0
- package/src/hooks/use-selected-room.ts +143 -0
- package/src/index.tsx +246 -39
- package/src/lib/ceiling-edit-session.test.ts +321 -0
- package/src/lib/ceiling-edit-session.ts +206 -0
- package/src/lib/ceiling-region-session.test.ts +179 -0
- package/src/lib/continuation.test.ts +19 -1
- package/src/lib/continuation.ts +25 -4
- package/src/lib/door-interaction.ts +14 -0
- package/src/lib/editor-level-display.test.ts +96 -0
- package/src/lib/editor-level-display.ts +48 -0
- package/src/lib/editor-views.ts +144 -0
- package/src/lib/export-geometry-wait.test.ts +90 -0
- package/src/lib/floor-edit-session.ts +153 -0
- package/src/lib/floor-footprints.test.ts +563 -0
- package/src/lib/floor-footprints.ts +395 -0
- package/src/lib/floor-foundation-support.test.ts +283 -0
- package/src/lib/floor-opening-draft.ts +218 -0
- package/src/lib/floor-openings.test.ts +216 -0
- package/src/lib/floor-region-geometry.ts +191 -0
- package/src/lib/floor-region-session.test.ts +485 -0
- package/src/lib/floor-region-session.ts +589 -0
- package/src/lib/floor-region-snap.ts +101 -0
- package/src/lib/floor-step-hover.test.ts +32 -0
- package/src/lib/floorplan/annotation-visibility.ts +17 -0
- package/src/lib/floorplan/dimension-drive.test.ts +360 -0
- package/src/lib/floorplan/dimension-drive.ts +479 -0
- package/src/lib/floorplan/floorplan-export.test.ts +12 -8
- package/src/lib/floorplan/floorplan-export.tsx +32 -8
- package/src/lib/floorplan/floorplan-extension.ts +32 -0
- package/src/lib/floorplan/floorplan-mode.test.ts +4 -0
- package/src/lib/floorplan/floorplan-mode.ts +2 -0
- package/src/lib/floorplan/floorplan-pdfkit-document.ts +339 -18
- package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +138 -8
- package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +56 -25
- package/src/lib/floorplan/floorplan-plugin-install.test.tsx +138 -0
- package/src/lib/floorplan/floorplan-readonly.ts +6 -0
- package/src/lib/floorplan/geometry.ts +13 -6
- package/src/lib/floorplan/index.ts +0 -9
- package/src/lib/floorplan/items.ts +5 -2
- package/src/lib/floorplan/marks.test.ts +213 -0
- package/src/lib/floorplan/marks.ts +238 -0
- package/src/lib/floorplan/open-wall-ends.test.ts +268 -0
- package/src/lib/floorplan/open-wall-ends.ts +162 -0
- package/src/lib/floorplan/pdf-fonts/GeistMono-Bold.ttf +0 -0
- package/src/lib/floorplan/pdf-fonts/GeistMono-Regular.ttf +0 -0
- package/src/lib/floorplan/pdf-fonts/LICENSE-GeistMono.txt +92 -0
- package/src/lib/floorplan/pdf-fonts/LICENSE-LiberationSans.txt +102 -0
- package/src/lib/floorplan/pdf-fonts/LiberationSans-Bold.ttf +0 -0
- package/src/lib/floorplan/pdf-fonts/LiberationSans-Regular.ttf +0 -0
- package/src/lib/floorplan/schedules.test.ts +189 -0
- package/src/lib/floorplan/schedules.ts +339 -0
- package/src/lib/floorplan/sheet-export.test.ts +100 -0
- package/src/lib/floorplan/sheet-export.ts +318 -0
- package/src/lib/floorplan/site-plan/build-site-plan-drawing.ts +779 -0
- package/src/lib/floorplan/site-plan/contours.test.ts +43 -0
- package/src/lib/floorplan/site-plan/contributors.ts +97 -0
- package/src/lib/floorplan/site-plan/coverage.ts +232 -0
- package/src/lib/floorplan/site-plan/drawing-type-switch.test.ts +15 -0
- package/src/lib/floorplan/site-plan/drawing-type-switch.tsx +86 -0
- package/src/lib/floorplan/site-plan/front-edge.test.ts +103 -0
- package/src/lib/floorplan/site-plan/front-edge.ts +156 -0
- package/src/lib/floorplan/site-plan/geometry.test.ts +275 -0
- package/src/lib/floorplan/site-plan/geometry.ts +557 -0
- package/src/lib/floorplan/site-plan/index.ts +71 -0
- package/src/lib/floorplan/site-plan/site-annotations.test.ts +366 -0
- package/src/lib/floorplan/site-plan/site-annotations.ts +1083 -0
- package/src/lib/floorplan/site-plan/site-parts.ts +379 -0
- package/src/lib/floorplan/site-plan/site-plan-layer.tsx +138 -0
- package/src/lib/floorplan/site-plan/street-name.test.ts +69 -0
- package/src/lib/floorplan/site-plan/street-name.ts +302 -0
- package/src/lib/floorplan/site-plan/yards.test.ts +69 -0
- package/src/lib/floorplan/types.ts +1 -27
- package/src/lib/fresh-planar-placement.test.ts +36 -0
- package/src/lib/fresh-planar-placement.ts +59 -36
- package/src/lib/geometry-script/author.ts +152 -0
- package/src/lib/geometry-script/client.ts +152 -0
- package/src/lib/geometry-script/protocol.ts +12 -0
- package/src/lib/gesture-lifecycle.test.ts +595 -0
- package/src/lib/gesture-lifecycle.ts +290 -0
- package/src/lib/glb-export-zone-holes.test.ts +41 -0
- package/src/lib/glb-export.test.ts +485 -0
- package/src/lib/glb-export.ts +237 -119
- package/src/lib/history.test.ts +6 -0
- package/src/lib/history.ts +7 -0
- package/src/lib/hud-title.ts +109 -0
- package/src/lib/hydration-gated-storage.ts +49 -0
- package/src/lib/ifc-export.test.ts +174 -0
- package/src/lib/ifc-export.ts +201 -0
- package/src/lib/ifc-parts.ts +15 -0
- package/src/lib/inspector-expanded.test.ts +44 -0
- package/src/lib/inspector-expanded.ts +36 -0
- package/src/lib/interaction/scope.ts +18 -0
- package/src/lib/keyboard-pan.test.ts +129 -7
- package/src/lib/keyboard-pan.ts +161 -12
- package/src/lib/live-gesture-round-trip.test.ts +360 -0
- package/src/lib/lot/__fixtures__/map-dossier-miami-shores.json +1 -0
- package/src/lib/lot/__fixtures__/map-dossier-stpete.json +1 -0
- package/src/lib/lot/clean-ring.test.ts +186 -0
- package/src/lib/lot/clean-ring.ts +217 -0
- package/src/lib/lot/dossier.test.ts +202 -0
- package/src/lib/lot/dossier.ts +498 -0
- package/src/lib/lot/drop-in.test.ts +326 -0
- package/src/lib/lot/drop-in.ts +407 -0
- package/src/lib/lot/index.ts +43 -0
- package/src/lib/lot/lot-patch.test.ts +340 -0
- package/src/lib/lot/lot-patch.ts +394 -0
- package/src/lib/lot/parcel-provider.ts +43 -0
- package/src/lib/lot/terrain.test.ts +161 -0
- package/src/lib/lot/terrain.ts +266 -0
- package/src/lib/material-catalog-model.ts +3 -1
- package/src/lib/material-paint-panel-model.ts +9 -5
- package/src/lib/material-paint.ts +4 -0
- package/src/lib/mezzanine-actions.test.ts +342 -0
- package/src/lib/mezzanine-draft.test.ts +501 -0
- package/src/lib/mezzanine-draft.ts +278 -0
- package/src/lib/mezzanine-messages.ts +26 -0
- package/src/lib/mezzanine-selection.test.ts +207 -0
- package/src/lib/mezzanine-stairs.ts +46 -0
- package/src/lib/model-export.ts +3 -1
- package/src/lib/node-action-movement.ts +17 -6
- package/src/lib/node-display-label.ts +37 -0
- package/src/lib/orbit-floor-clearance.test.ts +165 -0
- package/src/lib/orbit-floor-clearance.ts +106 -0
- package/src/lib/paint-commit-route.test.ts +37 -0
- package/src/lib/paint-commit-route.ts +17 -0
- package/src/lib/paint-eyedropper.test.tsx +165 -0
- package/src/lib/paint-eyedropper.ts +99 -0
- package/src/lib/paint-pass-through.test.ts +111 -0
- package/src/lib/paint-pass-through.ts +76 -0
- package/src/lib/paint-region-hover.ts +25 -0
- package/src/lib/paint-region-mode.ts +154 -0
- package/src/lib/paint-regions.test.ts +166 -0
- package/src/lib/paint-regions.ts +192 -0
- package/src/lib/paint-scope.test.ts +317 -35
- package/src/lib/paint-scope.ts +266 -25
- package/src/lib/panel-rows.ts +21 -0
- package/src/lib/parametric-node-update.ts +1 -1
- package/src/lib/plate-paint-affected.test.ts +300 -0
- package/src/lib/plate-paint-affected.ts +177 -0
- package/src/lib/plugin-chat.ts +50 -0
- package/src/lib/plugin-panels.test.ts +25 -0
- package/src/lib/plugin-panels.ts +94 -0
- package/src/lib/print-shell-compiler.ts +1 -0
- package/src/lib/registered-draft-snap.ts +12 -0
- package/src/lib/roof-duplication.ts +10 -2
- package/src/lib/room-assembly-overlay.test.ts +275 -0
- package/src/lib/room-assembly-overlay.ts +266 -0
- package/src/lib/room-built-on.test.ts +379 -0
- package/src/lib/room-built-on.ts +138 -0
- package/src/lib/room-construction-commands.ts +712 -0
- package/src/lib/room-construction.test.ts +746 -0
- package/src/lib/room-construction.ts +385 -0
- package/src/lib/room-controls-phase6.test.ts +630 -0
- package/src/lib/room-divide-session.ts +523 -0
- package/src/lib/room-handle-drag.ts +1068 -0
- package/src/lib/room-name-catalog.test.ts +90 -0
- package/src/lib/room-name-catalog.ts +168 -0
- package/src/lib/room-push-dimensions.test.ts +311 -0
- package/src/lib/room-push-dimensions.ts +251 -0
- package/src/lib/room-selection-commands.ts +62 -0
- package/src/lib/room-selection.test.ts +973 -0
- package/src/lib/room-selection.ts +417 -0
- package/src/lib/room-structure-commands.ts +94 -0
- package/src/lib/room-structure.test.ts +921 -0
- package/src/lib/room-transform-session.ts +570 -0
- package/src/lib/room-zone-routing.test.ts +294 -0
- package/src/lib/room-zone-routing.ts +197 -0
- package/src/lib/scene-clipboard.test.ts +364 -0
- package/src/lib/scene-clipboard.ts +229 -48
- package/src/lib/scene-material-refs.test.ts +79 -0
- package/src/lib/scene-material-refs.ts +79 -0
- package/src/lib/scene.test.ts +24 -36
- package/src/lib/scene.ts +33 -57
- package/src/lib/selection-routing.test.ts +129 -45
- package/src/lib/selection-routing.ts +53 -74
- package/src/lib/session-writes.test.ts +120 -0
- package/src/lib/session-writes.ts +205 -0
- package/src/lib/sidebar-panel.ts +62 -0
- package/src/lib/site-boundary.test.ts +4 -6
- package/src/lib/site-boundary.ts +1 -1
- package/src/lib/snapping-mode.test.ts +4 -0
- package/src/lib/snapping-mode.ts +8 -1
- package/src/lib/terrace-draft.test.ts +145 -0
- package/src/lib/terrace-draft.ts +213 -0
- package/src/lib/tool-cursor-icon.test.ts +16 -0
- package/src/lib/tool-cursor-icon.ts +11 -0
- package/src/lib/typing-target.ts +9 -0
- package/src/lib/units.ts +77 -39
- package/src/lib/vector-edges.test.ts +58 -0
- package/src/lib/vector-edges.ts +400 -0
- package/src/lib/viewer-selection.test.ts +577 -0
- package/src/lib/viewer-selection.ts +569 -0
- package/src/lib/wall-draw-variant.test.ts +71 -0
- package/src/lib/wall-draw-variant.ts +91 -0
- package/src/lib/wall-paint-region-session.ts +246 -0
- package/src/lib/wall-paint-region.test.ts +373 -0
- package/src/lib/wall-polygon-draft.test.ts +262 -0
- package/src/lib/wall-polygon-draft.ts +286 -0
- package/src/lib/wall-push.test.ts +453 -0
- package/src/lib/wall-region-face.ts +352 -0
- package/src/lib/wall-region-handles.test.ts +304 -0
- package/src/lib/wall-region-handles.ts +368 -0
- package/src/lib/wall-region-list.test.ts +119 -0
- package/src/lib/wall-region-list.ts +136 -0
- package/src/lib/wall-region-snap.ts +110 -0
- package/src/lib/window-interaction.ts +14 -0
- package/src/lib/zone-content.ts +4 -1
- package/src/lib/zone-name.test.ts +17 -0
- package/src/lib/zone-name.ts +17 -0
- package/src/store/opens-in-select-mode.test.ts +223 -0
- package/src/store/paint-mode.test.ts +188 -0
- package/src/store/terrain-sculpt-mode.test.ts +19 -21
- package/src/store/tool-mode.test.ts +137 -6
- package/src/store/use-delete-confirmation.ts +28 -1
- package/src/store/use-drawing-view.test.ts +24 -3
- package/src/store/use-drawing-view.ts +29 -1
- package/src/store/use-editor.tsx +432 -321
- package/src/store/use-floorplan-draft-preview.ts +13 -0
- package/src/store/use-floorplan-marquee.ts +12 -2
- package/src/store/use-quick-measurement-hud.ts +3 -3
- package/src/store/use-stair-build-preview.ts +13 -5
- package/src/store/use-wall-move-ghosts.ts +4 -2
- package/src/store/use-wall-region-handles-selection.test.ts +222 -0
- package/src/store/use-wall-region-handles-selection.ts +139 -0
- package/src/store/view-layout.test.ts +175 -0
- package/src/store/view-layout.ts +196 -0
- package/src/test-utils/immediate-animation-frames.ts +16 -0
- package/src/test-utils/live-gesture-round-trip.ts +224 -0
- package/src/test-utils/selection-harness.ts +82 -0
- package/src/components/editor-2d/renderers/floorplan-stair-layer.tsx +0 -499
- package/src/components/systems/zone/zone-label-editor-system.tsx +0 -333
- package/src/components/tools/fence/fence-drafting.test.ts +0 -100
- package/src/components/tools/fence/fence-drafting.ts +0 -266
- package/src/components/ui/sidebar/panels/plugins-panel.tsx +0 -218
- package/src/components/viewer/viewer-units-panel.tsx +0 -116
- package/src/lib/floorplan/stairs.ts +0 -489
- package/src/lib/level-duplication.test.ts +0 -144
- package/src/lib/level-duplication.ts +0 -195
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { emitter } from '@pascal-app/core'
|
|
2
|
+
import useEditor from '../store/use-editor'
|
|
3
|
+
import type { ContinuationMode } from './continuation'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* How the wall tool draws, picked from the Build panel's Rooms group before
|
|
7
|
+
* drawing starts. Stored as the wall's continuation mode (persisted with the
|
|
8
|
+
* editor preferences), so the choice survives tool switches and reloads.
|
|
9
|
+
*/
|
|
10
|
+
export type WallDrawVariant = 'rectangle' | 'polygon' | 'walls'
|
|
11
|
+
|
|
12
|
+
export type WallDrawVariantInfo = {
|
|
13
|
+
id: WallDrawVariant
|
|
14
|
+
/** The wall continuation mode the tool reads. */
|
|
15
|
+
mode: ContinuationMode
|
|
16
|
+
/** Tile label. */
|
|
17
|
+
label: string
|
|
18
|
+
/** The name the HUD shows while the variant is armed. */
|
|
19
|
+
title: string
|
|
20
|
+
iconSrc: string
|
|
21
|
+
/** Caption under the Rooms tiles: a bold lead, then the rest. */
|
|
22
|
+
caption: { lead: string; rest: string }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const WALL_DRAW_VARIANTS: readonly WallDrawVariantInfo[] = [
|
|
26
|
+
{
|
|
27
|
+
id: 'rectangle',
|
|
28
|
+
mode: 'rectangle',
|
|
29
|
+
label: 'Rectangle',
|
|
30
|
+
title: 'Rectangle room',
|
|
31
|
+
iconSrc: '/icons/room.webp',
|
|
32
|
+
caption: {
|
|
33
|
+
lead: 'Click two corners',
|
|
34
|
+
rest: 'on the grid. Walls, floor and ceiling are created together.',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'polygon',
|
|
39
|
+
mode: 'room',
|
|
40
|
+
label: 'Polygon',
|
|
41
|
+
title: 'Polygon room',
|
|
42
|
+
iconSrc: '/icons/polygon-room.webp',
|
|
43
|
+
caption: {
|
|
44
|
+
lead: 'Click each corner,',
|
|
45
|
+
rest: 'then the first one again to close. For L-shapes and angled rooms.',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'walls',
|
|
50
|
+
mode: 'single',
|
|
51
|
+
label: 'Walls',
|
|
52
|
+
title: 'Walls',
|
|
53
|
+
iconSrc: '/icons/wall.webp',
|
|
54
|
+
caption: {
|
|
55
|
+
lead: 'Draw one wall at a time.',
|
|
56
|
+
rest: 'Close a loop and it becomes a room; leave it open for partitions.',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
export const WALL_DRAW_IDLE_CAPTION =
|
|
62
|
+
'Pick a shape to start. Every room brings its own walls, floor and ceiling.'
|
|
63
|
+
|
|
64
|
+
export function getWallDrawVariantInfo(variant: WallDrawVariant): WallDrawVariantInfo {
|
|
65
|
+
return WALL_DRAW_VARIANTS.find((info) => info.id === variant) ?? WALL_DRAW_VARIANTS[1]!
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function wallDrawVariantOf(mode: ContinuationMode): WallDrawVariant {
|
|
69
|
+
return WALL_DRAW_VARIANTS.find((info) => info.mode === mode)?.id ?? 'polygon'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function getWallDrawVariant(): WallDrawVariant {
|
|
73
|
+
return wallDrawVariantOf(useEditor.getState().getContinuation('wall'))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function useWallDrawVariant(): WallDrawVariant {
|
|
77
|
+
return useEditor((state) => wallDrawVariantOf(state.getContinuation('wall')))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Pick how the wall tool draws. Callers arm the wall tool themselves; switching
|
|
82
|
+
* while it is armed drops the in-flight draft so a half-drawn chain never
|
|
83
|
+
* finishes as a rectangle.
|
|
84
|
+
*/
|
|
85
|
+
export function selectWallDrawVariant(variant: WallDrawVariant): void {
|
|
86
|
+
const editor = useEditor.getState()
|
|
87
|
+
const { mode } = getWallDrawVariantInfo(variant)
|
|
88
|
+
if (editor.getContinuation('wall') === mode) return
|
|
89
|
+
if (editor.mode === 'build' && editor.tool === 'wall') emitter.emit('tool:cancel')
|
|
90
|
+
editor.setContinuation('wall', mode)
|
|
91
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { type AnyNodeId, useScene, type WallFace } from '@pascal-app/core'
|
|
2
|
+
import { create } from 'zustand'
|
|
3
|
+
import useEditor from '../store/use-editor'
|
|
4
|
+
import { beginGesture, type GestureHandle } from './gesture-lifecycle'
|
|
5
|
+
import { hasActivePaintMaterial } from './material-paint'
|
|
6
|
+
import { isPaintErasing, usePaintRegionMode } from './paint-region-mode'
|
|
7
|
+
import {
|
|
8
|
+
addWallRegion,
|
|
9
|
+
type RegionWriteResult,
|
|
10
|
+
WALL_REGION_CAP_MESSAGE,
|
|
11
|
+
type WallRegionBounds,
|
|
12
|
+
wallFaceHasRoom,
|
|
13
|
+
} from './paint-regions'
|
|
14
|
+
import type { WallFaceExtent } from './wall-region-face'
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_WAINSCOT_HEIGHT,
|
|
17
|
+
faceBaseAt,
|
|
18
|
+
MIN_WALL_REGION_SIZE,
|
|
19
|
+
snapWallRegionValue,
|
|
20
|
+
type WallFaceBaseRuns,
|
|
21
|
+
type WallRegionSnap,
|
|
22
|
+
type WallRegionSnapTargets,
|
|
23
|
+
wallRegionSnapTargets,
|
|
24
|
+
} from './wall-region-snap'
|
|
25
|
+
|
|
26
|
+
// The wall half of "Paint part of a surface": hover → press anywhere on a face
|
|
27
|
+
// → drag to the opposite corner → release paints one rectangle, as one undo
|
|
28
|
+
// step. Pure over face coordinates — the 3D tool resolves the pointer to a
|
|
29
|
+
// `WallRegionHit` and renders `preview`.
|
|
30
|
+
|
|
31
|
+
export const WALL_PAINT_REGION_HANDLE = 'paint-region'
|
|
32
|
+
export const PICK_MATERIAL_MESSAGE = 'Pick a material first'
|
|
33
|
+
|
|
34
|
+
/** The pointer on one wall face. `u` / `v` are raw (unsnapped) face coordinates. */
|
|
35
|
+
export type WallRegionHit = {
|
|
36
|
+
wallId: string
|
|
37
|
+
face: WallFace
|
|
38
|
+
u: number
|
|
39
|
+
v: number
|
|
40
|
+
/** Reference chord length. */
|
|
41
|
+
length: number
|
|
42
|
+
extent: WallFaceExtent
|
|
43
|
+
runs: WallFaceBaseRuns
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type WallRegionPreview = {
|
|
47
|
+
wallId: string
|
|
48
|
+
face: WallFace
|
|
49
|
+
/** What a release now would paint (absent bounds run to the edge); null = nothing. */
|
|
50
|
+
bounds: WallRegionBounds | null
|
|
51
|
+
/** The pressed corner, or where a press would put it. */
|
|
52
|
+
corner: [number, number]
|
|
53
|
+
/** The readout: width × height. */
|
|
54
|
+
measure: { values: number[]; u: number; v: number } | null
|
|
55
|
+
pressed: boolean
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
type Gesture = {
|
|
59
|
+
owner: GestureHandle
|
|
60
|
+
hit: WallRegionHit
|
|
61
|
+
targets: WallRegionSnapTargets
|
|
62
|
+
corner: [number, number]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const useWallPaintRegionSession = create<{ preview: WallRegionPreview | null }>(() => ({
|
|
66
|
+
preview: null,
|
|
67
|
+
}))
|
|
68
|
+
|
|
69
|
+
let gesture: Gesture | null = null
|
|
70
|
+
|
|
71
|
+
export function isWallRegionGestureActive() {
|
|
72
|
+
return gesture !== null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function clamp(value: number, low: number, high: number) {
|
|
76
|
+
return Math.min(Math.max(value, low), Math.max(low, high))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Room the face has above its base at `u`. */
|
|
80
|
+
function faceHeightAt(hit: WallRegionHit, u: number) {
|
|
81
|
+
return hit.extent.top - faceBaseAt(hit.runs, u)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function targetsFor(hit: WallRegionHit): WallRegionSnapTargets {
|
|
85
|
+
const nodes = useScene.getState().nodes
|
|
86
|
+
const wall = nodes[hit.wallId as AnyNodeId]
|
|
87
|
+
if (wall?.type !== 'wall') return { u: [0, hit.length], v: [0, DEFAULT_WAINSCOT_HEIGHT] }
|
|
88
|
+
const targets = wallRegionSnapTargets(wall, hit.face, nodes, hit.runs)
|
|
89
|
+
return { ...targets, v: [...targets.v, faceHeightAt(hit, hit.u)] }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** The pointer on the face, snapped and held inside it. */
|
|
93
|
+
function snapped(hit: WallRegionHit, targets: WallRegionSnapTargets, snap: WallRegionSnap) {
|
|
94
|
+
const u = clamp(snapWallRegionValue(hit.u, targets.u, snap).value, 0, hit.length)
|
|
95
|
+
const v = clamp(snapWallRegionValue(hit.v, targets.v, snap).value, 0, faceHeightAt(hit, u))
|
|
96
|
+
return { ...hit, u, v }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The box between the pressed corner and the pointer, or null when it would paint a sliver. */
|
|
100
|
+
export function wallRegionBoundsFor(state: {
|
|
101
|
+
hit: WallRegionHit
|
|
102
|
+
corner: [number, number]
|
|
103
|
+
}): WallRegionBounds | null {
|
|
104
|
+
const { hit } = state
|
|
105
|
+
const [au, av] = state.corner
|
|
106
|
+
const bu = clamp(hit.u, 0, hit.length)
|
|
107
|
+
const bv = clamp(hit.v, 0, faceHeightAt(hit, bu))
|
|
108
|
+
const u0 = Math.min(au, bu)
|
|
109
|
+
const u1 = Math.max(au, bu)
|
|
110
|
+
const v0 = Math.min(av, bv)
|
|
111
|
+
const v1 = Math.max(av, bv)
|
|
112
|
+
if (u1 - u0 < MIN_WALL_REGION_SIZE || v1 - v0 < MIN_WALL_REGION_SIZE) return null
|
|
113
|
+
const bounds: WallRegionBounds = {}
|
|
114
|
+
// A bound on the face's edge is left open, so the region follows the edge.
|
|
115
|
+
if (u0 > 1e-6) bounds.u0 = u0
|
|
116
|
+
if (u1 < hit.length - 1e-6) bounds.u1 = u1
|
|
117
|
+
if (v0 > 1e-6) bounds.v0 = v0
|
|
118
|
+
if (v1 < faceHeightAt(hit, (u0 + u1) / 2) - 1e-6) bounds.v1 = v1
|
|
119
|
+
return bounds
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function previewOf(state: Omit<Gesture, 'owner'>, pressed: boolean): WallRegionPreview {
|
|
123
|
+
const { hit, corner } = state
|
|
124
|
+
const base = { wallId: hit.wallId, face: hit.face, corner, pressed }
|
|
125
|
+
if (!pressed) return { ...base, bounds: null, measure: null }
|
|
126
|
+
const [au, av] = corner
|
|
127
|
+
return {
|
|
128
|
+
...base,
|
|
129
|
+
bounds: wallRegionBoundsFor(state),
|
|
130
|
+
measure: {
|
|
131
|
+
values: [Math.abs(hit.u - au), Math.abs(hit.v - av)],
|
|
132
|
+
u: (au + hit.u) / 2,
|
|
133
|
+
v: (av + hit.v) / 2,
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function track(hit: WallRegionHit, snap: WallRegionSnap): Omit<Gesture, 'owner'> {
|
|
139
|
+
const targets = targetsFor(hit)
|
|
140
|
+
const at = snapped(hit, targets, snap)
|
|
141
|
+
return { hit: at, targets, corner: [at.u, at.v] }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Pointer over the canvas with no gesture live: preview where a press would start the box. */
|
|
145
|
+
export function hoverWallRegion(hit: WallRegionHit | null, snap: WallRegionSnap) {
|
|
146
|
+
if (gesture) return
|
|
147
|
+
useWallPaintRegionSession.setState({
|
|
148
|
+
preview: hit ? previewOf(track(hit, snap), false) : null,
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Starts a gesture at any point of a face, or refuses it with a notice.
|
|
154
|
+
* Returns whether it started. The gesture lives under the lifecycle owner: a
|
|
155
|
+
* sub-mode, mode, level or selection change, its scope replaced, its wall
|
|
156
|
+
* deleted or any history command cancels it; `onHostCancel` lets the pointer
|
|
157
|
+
* surface drop its press.
|
|
158
|
+
*/
|
|
159
|
+
export function pressWallRegion(
|
|
160
|
+
hit: WallRegionHit,
|
|
161
|
+
snap: WallRegionSnap,
|
|
162
|
+
onHostCancel?: () => void,
|
|
163
|
+
): boolean {
|
|
164
|
+
const regionMode = usePaintRegionMode.getState()
|
|
165
|
+
regionMode.setNotice(null)
|
|
166
|
+
const editor = useEditor.getState()
|
|
167
|
+
if (isPaintErasing() || !hasActivePaintMaterial(editor.activePaintMaterial)) {
|
|
168
|
+
regionMode.setNotice(PICK_MATERIAL_MESSAGE)
|
|
169
|
+
return false
|
|
170
|
+
}
|
|
171
|
+
const wall = useScene.getState().nodes[hit.wallId as AnyNodeId]
|
|
172
|
+
if (wall?.type !== 'wall' || useScene.getState().readOnly) return false
|
|
173
|
+
if (!wallFaceHasRoom(wall, hit.face)) {
|
|
174
|
+
regionMode.setNotice(WALL_REGION_CAP_MESSAGE)
|
|
175
|
+
return false
|
|
176
|
+
}
|
|
177
|
+
gesture?.owner.cancel()
|
|
178
|
+
const tracked = track(hit, snap)
|
|
179
|
+
const owner = beginGesture({
|
|
180
|
+
kind: 'wall-paint-region',
|
|
181
|
+
scope: { kind: 'handle-drag', nodeId: hit.wallId, handle: WALL_PAINT_REGION_HANDLE },
|
|
182
|
+
paintSubMode: true,
|
|
183
|
+
stale: () => {
|
|
184
|
+
const state = useScene.getState()
|
|
185
|
+
return state.readOnly || state.nodes[hit.wallId as AnyNodeId]?.type !== 'wall'
|
|
186
|
+
},
|
|
187
|
+
onCancel: () => {
|
|
188
|
+
if (gesture?.owner === owner) gesture = null
|
|
189
|
+
useWallPaintRegionSession.setState({ preview: null })
|
|
190
|
+
onHostCancel?.()
|
|
191
|
+
},
|
|
192
|
+
})
|
|
193
|
+
gesture = { ...tracked, owner }
|
|
194
|
+
useWallPaintRegionSession.setState({ preview: previewOf(gesture, true) })
|
|
195
|
+
return true
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** The live gesture's lifecycle handle (the surface captures its pointer through it). */
|
|
199
|
+
export function activeWallRegionGesture(): GestureHandle | null {
|
|
200
|
+
return gesture?.owner ?? null
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** The pointer moved with the button held; `hit` is on the pressed face. */
|
|
204
|
+
export function dragWallRegion(hit: WallRegionHit, snap: WallRegionSnap) {
|
|
205
|
+
if (!gesture || hit.wallId !== gesture.hit.wallId || hit.face !== gesture.hit.face) return
|
|
206
|
+
gesture.hit = snapped(hit, gesture.targets, snap)
|
|
207
|
+
useWallPaintRegionSession.setState({ preview: previewOf(gesture, true) })
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Ends the gesture and paints its region. Null when nothing was committed. */
|
|
211
|
+
export function releaseWallRegion(): RegionWriteResult | null {
|
|
212
|
+
const current = gesture
|
|
213
|
+
if (!current) return null
|
|
214
|
+
gesture = null
|
|
215
|
+
useWallPaintRegionSession.setState({ preview: null })
|
|
216
|
+
const bounds = wallRegionBoundsFor(current)
|
|
217
|
+
if (!bounds) {
|
|
218
|
+
current.owner.end()
|
|
219
|
+
return null
|
|
220
|
+
}
|
|
221
|
+
const paint = useEditor.getState().activePaintMaterial
|
|
222
|
+
const result =
|
|
223
|
+
current.owner.finish(() =>
|
|
224
|
+
addWallRegion(current.hit.wallId, current.hit.face, bounds, {
|
|
225
|
+
material: paint?.material,
|
|
226
|
+
materialPreset: paint?.materialPreset,
|
|
227
|
+
}),
|
|
228
|
+
) ?? null
|
|
229
|
+
if (result && !result.ok) usePaintRegionMode.getState().setNotice(result.message)
|
|
230
|
+
return result
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Drops the gesture without writing anything. Returns whether one was live. */
|
|
234
|
+
export function cancelWallRegion(): boolean {
|
|
235
|
+
const current = gesture
|
|
236
|
+
if (!current) return false
|
|
237
|
+
current.owner.cancel()
|
|
238
|
+
gesture = null
|
|
239
|
+
useWallPaintRegionSession.setState({ preview: null })
|
|
240
|
+
return true
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** The wall the live gesture draws on, if any. */
|
|
244
|
+
export function activeWallRegionTarget(): { wallId: string; face: WallFace } | null {
|
|
245
|
+
return gesture ? { wallId: gesture.hit.wallId, face: gesture.hit.face } : null
|
|
246
|
+
}
|