@pascal-app/editor 1.0.6 → 1.1.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/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 +110 -42
- package/src/components/editor/duplicate-node.ts +2 -1
- package/src/components/editor/elevation-3d-guide-layer.tsx +1 -1
- package/src/components/editor/first-person-controls.tsx +77 -68
- package/src/components/editor/fit-scene-framing.test.ts +318 -0
- package/src/components/editor/fit-scene-framing.ts +142 -0
- package/src/components/editor/floating-action-menu.tsx +31 -11
- package/src/components/editor/floating-building-action-menu.tsx +1 -1
- package/src/components/editor/floor-openings-overlay.tsx +1 -1
- package/src/components/editor/floor-region-controls.tsx +2 -2
- package/src/components/editor/floorplan-panel.test.ts +220 -0
- package/src/components/editor/floorplan-panel.tsx +458 -140
- package/src/components/editor/floorplan-wall-typing-keys.test.tsx +152 -0
- package/src/components/editor/floorplan-wall-typing-keys.ts +79 -0
- package/src/components/editor/footprint-height-handle.tsx +2 -2
- 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 +23 -1
- package/src/components/editor/index.tsx +150 -20
- package/src/components/editor/inspector-extension-actions.tsx +36 -0
- package/src/components/editor/localized-html.tsx +22 -0
- package/src/components/editor/measurement-pill.tsx +1 -1
- package/src/components/editor/node-action-menu.tsx +46 -12
- package/src/components/editor/node-arrow-handles.tsx +2 -3
- package/src/components/editor/open-wall-ends-3d-layer.tsx +2 -3
- package/src/components/editor/open-wall-ends-hint.tsx +1 -1
- package/src/components/editor/opening-guides-3d-layer.tsx +1 -1
- package/src/components/editor/quick-measurement-card.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 +4 -3
- package/src/components/editor/room-handles-2d.tsx +158 -7
- package/src/components/editor/room-handles.tsx +244 -54
- package/src/components/editor/room-highlight.tsx +2 -0
- package/src/components/editor/room-labels.tsx +33 -17
- 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 +7 -3
- 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 +31 -15
- package/src/components/editor/wall-move-side-handles.tsx +15 -7
- package/src/components/editor/wall-pull-grip.tsx +193 -0
- package/src/components/editor/wall-region-handles.tsx +2 -2
- package/src/components/editor/wall-snap-beacon-layer.tsx +134 -33
- 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 +32 -4
- package/src/components/editor-2d/floorplan-measurement-tool-layer.test.ts +6 -0
- package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +33 -24
- package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +12 -5
- package/src/components/editor-2d/floorplan-registry-action-menu.tsx +2 -1
- package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +29 -5
- 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-draft-measurement.tsx +7 -1
- package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +13 -1
- package/src/components/editor-2d/renderers/floorplan-placement-typing-hud.test.tsx +35 -0
- package/src/components/editor-2d/renderers/floorplan-placement-typing-hud.tsx +65 -0
- package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +34 -1
- package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +211 -39
- 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/systems/roof/roof-edit-system.test.tsx +15 -1
- package/src/components/systems/roof/roof-edit-system.tsx +30 -19
- package/src/components/tools/distribution/distribution-run-tool.test.tsx +371 -3
- package/src/components/tools/distribution/distribution-run-tool.tsx +200 -58
- package/src/components/tools/item/move-tool.tsx +1 -6
- 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 +31 -35
- package/src/components/tools/paint-region/wall-paint-region-tool.tsx +1 -1
- package/src/components/tools/registry/item-surface-move.test.ts +11 -0
- package/src/components/tools/registry/move-registry-node-tool.test.ts +42 -1
- package/src/components/tools/registry/move-registry-node-tool.tsx +38 -14
- 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 +2 -6
- package/src/components/tools/shared/placement-coordinate-input.tsx +94 -0
- package/src/components/tools/shared/placement-dimension-guides.tsx +1 -1
- package/src/components/tools/shared/segment-angle.ts +0 -4
- package/src/components/tools/site/terrain-brush-cursor.tsx +1 -1
- package/src/components/tools/tool-manager.tsx +1 -24
- 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/wall/wall-typed-entry.test.ts +99 -0
- package/src/components/tools/wall/wall-typed-entry.ts +70 -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 +47 -19
- package/src/components/ui/controls/tool-options-panel.tsx +74 -44
- 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 +106 -3
- package/src/components/ui/helpers/helper-manager.tsx +136 -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 +114 -39
- package/src/components/ui/panels/floor-opening-panel.tsx +74 -26
- 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 +34 -28
- 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 +11 -10
- package/src/components/ui/panels/multi-parametric-inspector.tsx +122 -34
- package/src/components/ui/panels/multi-selection-panel.tsx +76 -36
- package/src/components/ui/panels/node-display.ts +35 -24
- package/src/components/ui/panels/panel-manager.tsx +9 -5
- package/src/components/ui/panels/panel-wrapper.tsx +63 -127
- 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 +465 -66
- 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 +22 -13
- package/src/components/ui/panels/room-panel.tsx +207 -100
- 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/right-stack.test.ts +13 -6
- package/src/components/ui/right-stack.tsx +21 -10
- 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/settings-panel/load-build-dialog.tsx +1 -5
- 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 +5 -3
- 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 +118 -72
- 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 +9 -4
- 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 +19 -9
- 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 +62 -5
- 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 +15849 -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 +39331 -0
- package/src/i18n/locales/es/messages.ts +1 -0
- package/src/i18n/locales/fr/messages.po +39331 -0
- package/src/i18n/locales/fr/messages.ts +1 -0
- package/src/i18n/locales/ja/messages.po +39331 -0
- package/src/i18n/locales/ja/messages.ts +1 -0
- package/src/i18n/locales/zh-CN/messages.po +39331 -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 +224 -45
- package/src/lib/add-storey.test.ts +3 -3
- package/src/lib/contextual-help.test.ts +20 -1
- package/src/lib/contextual-help.ts +101 -19
- package/src/lib/continuation.ts +38 -11
- package/src/lib/elevation-guides.ts +21 -6
- package/src/lib/elevator-support.ts +1 -72
- package/src/lib/floor-footprints.test.ts +3 -2
- package/src/lib/floor-footprints.ts +1 -9
- package/src/lib/floor-foundation-support.test.ts +15 -6
- package/src/lib/floor-opening-draft.ts +1 -1
- package/src/lib/floor-region-session.ts +1 -1
- 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/open-wall-ends.ts +2 -1
- 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/gesture-lifecycle.ts +3 -1
- 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/interaction/scope.ts +1 -0
- 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/level-selection.test.ts +18 -2
- package/src/lib/level-selection.ts +31 -8
- package/src/lib/linear-display.ts +1 -1
- package/src/lib/live-gesture-round-trip.test.ts +1 -1
- 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-label.test.ts +1 -1
- package/src/lib/measurement-parser.ts +7 -3
- package/src/lib/measurements.test.ts +24 -6
- package/src/lib/measurements.ts +1 -203
- package/src/lib/mezzanine-selection.test.ts +3 -1
- package/src/lib/node-action-movement.test.tsx +115 -0
- package/src/lib/node-action-movement.ts +2 -0
- 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/placement-metadata.ts +4 -0
- package/src/lib/point-ask/describe-target.ts +6 -8
- package/src/lib/point-ask/region.ts +1 -1
- package/src/lib/print-shell-compiler.ts +12 -1
- package/src/lib/print-wall-solids.test.ts +11 -0
- package/src/lib/print-wall-solids.ts +9 -0
- package/src/lib/reference-scale.ts +83 -0
- package/src/lib/room-assembly-overlay.ts +1 -1
- package/src/lib/room-built-on.test.ts +28 -17
- package/src/lib/room-built-on.ts +21 -17
- package/src/lib/room-construction-commands.ts +3 -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 +141 -1
- package/src/lib/room-handle-drag.ts +554 -58
- 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 +38 -1
- package/src/lib/room-push-dimensions.ts +226 -2
- package/src/lib/room-selection.test.ts +23 -6
- package/src/lib/scene-bounds.test.ts +144 -0
- package/src/lib/scene-bounds.ts +79 -15
- package/src/lib/scene-clipboard.test.ts +70 -49
- package/src/lib/scene-clipboard.ts +11 -5
- 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/snapping-mode.test.ts +23 -1
- 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 +21 -6
- 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 +17 -6
- 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 +44 -0
- 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 +53 -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-placement-typing.test.ts +165 -0
- package/src/store/use-placement-typing.ts +186 -0
- package/src/store/use-wall-snap-indicator.ts +15 -2
- package/src/components/tools/elevator/elevator-defaults.ts +0 -8
- package/src/components/tools/elevator/elevator-tool.tsx +0 -372
- package/src/components/tools/elevator/move-elevator-tool.tsx +0 -262
- package/src/lib/door-interaction.ts +0 -102
- package/src/lib/measurement-label.ts +0 -68
- package/src/lib/window-interaction.ts +0 -100
|
@@ -10,7 +10,9 @@ import {
|
|
|
10
10
|
type AnyNode,
|
|
11
11
|
type AnyNodeId,
|
|
12
12
|
type BuildingNode,
|
|
13
|
+
floorPlateRoom,
|
|
13
14
|
getRoofSegmentDeckReach,
|
|
15
|
+
isOutdoorRoomType,
|
|
14
16
|
type LevelNode,
|
|
15
17
|
migrateSiteMetadata,
|
|
16
18
|
type RoofSegmentNode,
|
|
@@ -201,7 +203,7 @@ function coveredShare(ring: readonly Pt[], covers: readonly Pt[][]): number {
|
|
|
201
203
|
|
|
202
204
|
/**
|
|
203
205
|
* The level's outdoor slabs in site metres: porches, decks, patios and
|
|
204
|
-
* landings (a generator `metadata.porch`,
|
|
206
|
+
* landings (a generator `metadata.porch`, an outdoor room’s plate, or a
|
|
205
207
|
* slab lying outside the house's walls) and the flatwork. The house's own
|
|
206
208
|
* floors (the storey slab, a raised platform, the garage pad) and a porch
|
|
207
209
|
* cover's beam are not outdoor parts. `roofs` decides which are covered.
|
|
@@ -247,7 +249,8 @@ export function outdoorParts(
|
|
|
247
249
|
// a porch cover's beam box is not a floor
|
|
248
250
|
if (/beam/i.test(floor) || /beam/i.test(slab.name ?? '')) continue
|
|
249
251
|
const porch = meta.porch as { policy?: string; entrance?: string } | undefined
|
|
250
|
-
const
|
|
252
|
+
const roomType = floorPlateRoom(child, (id) => scene.nodes[id])?.roomType
|
|
253
|
+
const outdoorFloor = isOutdoorRoomType(roomType)
|
|
251
254
|
if (!porch && !outdoorFloor) {
|
|
252
255
|
// a hand-drawn slab: the house's floor when it lies under the walls
|
|
253
256
|
if (HOUSE_FLOORS.has(floor)) continue
|
|
@@ -257,7 +260,7 @@ export function outdoorParts(
|
|
|
257
260
|
)
|
|
258
261
|
if (walls.length === 0 || walls.some((w) => pointInPolygon(w, c[0], c[1]))) continue
|
|
259
262
|
}
|
|
260
|
-
const wood =
|
|
263
|
+
const wood = roomType === 'deck'
|
|
261
264
|
const policy = porch?.policy ?? ''
|
|
262
265
|
const kind: OutdoorKind =
|
|
263
266
|
policy === 'deck' || (wood && policy !== 'full' && policy !== 'entry')
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
2
|
+
import {
|
|
3
|
+
type AnyNode,
|
|
4
|
+
type ArtifactStore,
|
|
5
|
+
artifactUrl,
|
|
6
|
+
BuildingNode,
|
|
7
|
+
GeometryArtifactManifest,
|
|
8
|
+
generateId,
|
|
9
|
+
ItemNode,
|
|
10
|
+
LevelNode,
|
|
11
|
+
scriptSource,
|
|
12
|
+
} from '@pascal-app/core'
|
|
13
|
+
import {
|
|
14
|
+
captureRegistryVersions,
|
|
15
|
+
effectIds,
|
|
16
|
+
openDetachedScene,
|
|
17
|
+
SceneEnvironmentDisposedError,
|
|
18
|
+
type SceneSnapshot,
|
|
19
|
+
} from '@pascal-app/core/runtime'
|
|
20
|
+
import { compileAndStoreGeometryScript } from './author'
|
|
21
|
+
|
|
22
|
+
// A compile of an object for a detached scene reads the scene and mints the object's id before
|
|
23
|
+
// its first await: the scene records those reads and allocates that id in its synchronous scope,
|
|
24
|
+
// and a compile that resolves after the scene is disposed reaches nothing of it.
|
|
25
|
+
|
|
26
|
+
const sha = 'a'.repeat(64)
|
|
27
|
+
const compiled = {
|
|
28
|
+
sha256: sha,
|
|
29
|
+
script: 'b'.repeat(64),
|
|
30
|
+
language: 'three' as const,
|
|
31
|
+
mount: 'floor' as const,
|
|
32
|
+
params: {},
|
|
33
|
+
manifest: GeometryArtifactManifest.parse({
|
|
34
|
+
bounds: { min: [-0.5, 0, -0.5], max: [0.5, 1, 0.5] },
|
|
35
|
+
triangles: 12,
|
|
36
|
+
}),
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function scene() {
|
|
40
|
+
const screen = ItemNode.parse({
|
|
41
|
+
id: 'item_screen',
|
|
42
|
+
parentId: 'level_0',
|
|
43
|
+
name: 'Screen',
|
|
44
|
+
source: scriptSource(compiled),
|
|
45
|
+
asset: {
|
|
46
|
+
id: 'script_screen',
|
|
47
|
+
category: 'screen',
|
|
48
|
+
name: 'Screen',
|
|
49
|
+
thumbnail: '',
|
|
50
|
+
source: 'mine',
|
|
51
|
+
src: artifactUrl(sha),
|
|
52
|
+
dimensions: [1, 1, 1],
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
const level = LevelNode.parse({ id: 'level_0', parentId: 'building_0', children: [screen.id] })
|
|
56
|
+
const building = BuildingNode.parse({ id: 'building_0', children: [level.id] })
|
|
57
|
+
const snapshot = {
|
|
58
|
+
nodes: Object.fromEntries([building, level, screen].map((node) => [node.id, node])),
|
|
59
|
+
rootNodeIds: [building.id],
|
|
60
|
+
collections: {},
|
|
61
|
+
materials: {},
|
|
62
|
+
installedPlugins: [],
|
|
63
|
+
} as unknown as SceneSnapshot
|
|
64
|
+
return openDetachedScene(snapshot, {
|
|
65
|
+
base: { kind: 'authority', seq: 1 },
|
|
66
|
+
context: {
|
|
67
|
+
activeLevelId: 'level_0',
|
|
68
|
+
selection: [],
|
|
69
|
+
units: 'metric',
|
|
70
|
+
catalogVersion: 'test',
|
|
71
|
+
registryVersions: captureRegistryVersions(),
|
|
72
|
+
},
|
|
73
|
+
ids: effectIds('effect_compile'),
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const artifacts = {
|
|
78
|
+
url: () => null,
|
|
79
|
+
put: async (hash: string) => hash,
|
|
80
|
+
text: async () => 'export default function build() {}',
|
|
81
|
+
} as unknown as ArtifactStore
|
|
82
|
+
|
|
83
|
+
describe('compileAndStoreGeometryScript on a detached scene', () => {
|
|
84
|
+
test('reads the node it rebuilds before the first await', async () => {
|
|
85
|
+
const detached = scene()
|
|
86
|
+
const compiling = detached.run(() =>
|
|
87
|
+
compileAndStoreGeometryScript(
|
|
88
|
+
{ nodeId: 'item_screen', params: {} },
|
|
89
|
+
{ nodes: detached.reader().nodes as Record<string, AnyNode>, artifacts },
|
|
90
|
+
),
|
|
91
|
+
)
|
|
92
|
+
expect(detached.dependencies()).toContainEqual(
|
|
93
|
+
expect.objectContaining({ kind: 'node', id: 'item_screen' }),
|
|
94
|
+
)
|
|
95
|
+
detached.dispose()
|
|
96
|
+
const error = await compiling.catch((thrown: unknown) => thrown)
|
|
97
|
+
expect(error).not.toBeInstanceOf(SceneEnvironmentDisposedError)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test("mints a new object's id in the scene's scope, before the first await", async () => {
|
|
101
|
+
const detached = scene()
|
|
102
|
+
const next = detached.run(() => {
|
|
103
|
+
void compileAndStoreGeometryScript(
|
|
104
|
+
{ code: 'export default function build() {}', kind: 'item' },
|
|
105
|
+
{ nodes: detached.reader().nodes as Record<string, AnyNode>, artifacts },
|
|
106
|
+
).catch(() => {})
|
|
107
|
+
return generateId('item')
|
|
108
|
+
})
|
|
109
|
+
const ids = effectIds('effect_compile')
|
|
110
|
+
ids('item')
|
|
111
|
+
expect(next as string).toBe(ids('item'))
|
|
112
|
+
detached.dispose()
|
|
113
|
+
})
|
|
114
|
+
})
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type AnyNode,
|
|
2
3
|
type AnyNodeId,
|
|
4
|
+
type ArtifactStore,
|
|
3
5
|
type CompiledGeometryScript,
|
|
4
6
|
GEOMETRY_SCRIPT_MIME_TYPES,
|
|
5
7
|
GeometryArtifactMetadata,
|
|
@@ -41,28 +43,46 @@ export function configureBlenderScriptBuilder(next: BlenderScriptBuilder | null)
|
|
|
41
43
|
blenderBuilder = next
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
/**
|
|
47
|
+
* What a compile reads from the scene and the artifact service it stores to. By default the
|
|
48
|
+
* editor's own; a detached scene passes its tracked nodes, so the reads are recorded there.
|
|
49
|
+
*/
|
|
50
|
+
export type GeometryScriptScene = {
|
|
51
|
+
nodes?: Readonly<Record<string, AnyNode>>
|
|
52
|
+
artifacts?: ArtifactStore
|
|
53
|
+
}
|
|
54
|
+
|
|
44
55
|
/**
|
|
45
56
|
* The editor's compile step for `add_object`: runs the module (a three.js one
|
|
46
57
|
* in the worker, a bpy one through the host's Blender builder) and stores the
|
|
47
58
|
* GLB and the module text, so the core operation can reference both by hash.
|
|
48
59
|
* Without `code`, the node's stored script is rebuilt; either way an edit keeps
|
|
49
60
|
* the node's param values it does not override.
|
|
61
|
+
*
|
|
62
|
+
* Everything it reads from the scene, and the id of a new object, are taken
|
|
63
|
+
* synchronously, before the first await: a detached scene records reads and
|
|
64
|
+
* mints ids only inside its synchronous scope, and is disposed by the time a
|
|
65
|
+
* late compile resolves.
|
|
50
66
|
*/
|
|
51
|
-
export async function compileAndStoreGeometryScript(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
export async function compileAndStoreGeometryScript(
|
|
68
|
+
input: {
|
|
69
|
+
code?: string
|
|
70
|
+
language?: GeometryScriptLanguage
|
|
71
|
+
nodeId?: string
|
|
72
|
+
params?: Record<string, GeometryScriptParamValue>
|
|
73
|
+
kind?: 'item' | 'door' | 'window' | 'column'
|
|
74
|
+
inputs?: Record<string, unknown>
|
|
75
|
+
name?: string
|
|
76
|
+
description?: string
|
|
77
|
+
category?: string
|
|
78
|
+
tags?: string[]
|
|
79
|
+
provenance?: GeometryArtifactMetadata
|
|
80
|
+
},
|
|
81
|
+
scene: GeometryScriptScene = {},
|
|
82
|
+
): Promise<CompiledGeometryScript> {
|
|
83
|
+
const nodes = scene.nodes ?? useScene.getState().nodes
|
|
84
|
+
const artifacts = scene.artifacts ?? getArtifactStore()
|
|
85
|
+
const node = input.nodeId ? nodes[input.nodeId as AnyNodeId] : undefined
|
|
66
86
|
const language = editedScriptLanguage(node, input)
|
|
67
87
|
const params = editedScriptParams(node, input.params)
|
|
68
88
|
const kind =
|
|
@@ -71,12 +91,16 @@ export async function compileAndStoreGeometryScript(input: {
|
|
|
71
91
|
? node.type
|
|
72
92
|
: 'item')
|
|
73
93
|
const nodeId = input.nodeId ?? generateId(kind)
|
|
94
|
+
const authored = isScriptedNode(node) ? scriptedObjectMeta(node) : {}
|
|
95
|
+
const script = input.code === undefined ? authoredScript(nodes, input.nodeId) : null
|
|
74
96
|
const metadata = GeometryArtifactMetadata.parse({
|
|
75
|
-
...
|
|
97
|
+
...authored,
|
|
76
98
|
...input.provenance,
|
|
77
99
|
...GeometryReuseFields.parse(input),
|
|
78
100
|
kind,
|
|
79
101
|
})
|
|
102
|
+
|
|
103
|
+
const code = input.code ?? (await readScript(artifacts, script!, input.nodeId!))
|
|
80
104
|
if (language === 'bpy') {
|
|
81
105
|
if (!blenderBuilder) throw new Error('This editor cannot run Blender (bpy) scripts')
|
|
82
106
|
return { ...(await blenderBuilder({ code, params, nodeId, metadata })), nodeId }
|
|
@@ -87,10 +111,9 @@ export async function compileAndStoreGeometryScript(input: {
|
|
|
87
111
|
inputs: input.inputs,
|
|
88
112
|
})
|
|
89
113
|
const context = { nodeId, metadata: { ...metadata, mount: compiled.mount } }
|
|
90
|
-
const store = getArtifactStore()
|
|
91
114
|
const [sha256] = await Promise.all([
|
|
92
|
-
|
|
93
|
-
|
|
115
|
+
artifacts.put(compiled.sha256, glb, 'model/gltf-binary', context),
|
|
116
|
+
artifacts.put(
|
|
94
117
|
compiled.script,
|
|
95
118
|
new TextEncoder().encode(code),
|
|
96
119
|
GEOMETRY_SCRIPT_MIME_TYPES.three,
|
|
@@ -100,15 +123,24 @@ export async function compileAndStoreGeometryScript(input: {
|
|
|
100
123
|
return { ...compiled, sha256, nodeId }
|
|
101
124
|
}
|
|
102
125
|
|
|
103
|
-
/** The
|
|
104
|
-
|
|
126
|
+
/** The hash of an authored object's script, read from the scene. */
|
|
127
|
+
function authoredScript(nodes: Readonly<Record<string, AnyNode>>, nodeId: string | undefined) {
|
|
105
128
|
if (!nodeId) throw new Error('Pass the code to build a new object')
|
|
106
|
-
|
|
107
|
-
|
|
129
|
+
return authoredObject(nodes as Record<string, AnyNode>, nodeId).source.script
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function readScript(artifacts: ArtifactStore, script: string, nodeId: string) {
|
|
133
|
+
const code = await artifacts.text(script)
|
|
108
134
|
if (code === null) throw new Error(`The script of ${nodeId} could not be read`)
|
|
109
135
|
return code
|
|
110
136
|
}
|
|
111
137
|
|
|
138
|
+
/** The module text of an authored object, read back from the artifact store. */
|
|
139
|
+
export async function storedScript(nodeId: string | undefined): Promise<string> {
|
|
140
|
+
const script = authoredScript(useScene.getState().nodes, nodeId)
|
|
141
|
+
return readScript(getArtifactStore(), script, nodeId!)
|
|
142
|
+
}
|
|
143
|
+
|
|
112
144
|
const rebuildGeneration = new Map<string, number>()
|
|
113
145
|
|
|
114
146
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { GeometryScriptParamValue } from '@pascal-app/core'
|
|
2
|
+
import { sdfChecksOn } from '@pascal-app/core/usage-field'
|
|
2
3
|
import type { GeometryScriptCompileOutput } from '@pascal-app/geometry-script'
|
|
3
4
|
import type { GeometryScriptWorkerRequest, GeometryScriptWorkerResponse } from './protocol'
|
|
4
5
|
|
|
@@ -148,6 +149,8 @@ export async function compileGeometryScriptInWorker(input: {
|
|
|
148
149
|
code: input.code,
|
|
149
150
|
params: input.params,
|
|
150
151
|
inputs: input.inputs,
|
|
152
|
+
// the sandbox is its own context: the flag travels with the request, only when it is on
|
|
153
|
+
...(sdfChecksOn() ? { usageShape: true } : {}),
|
|
151
154
|
}
|
|
152
155
|
return new Promise((resolve, reject) => {
|
|
153
156
|
const timeout = setTimeout(() => {
|
|
@@ -17,9 +17,9 @@ import {
|
|
|
17
17
|
import { compileGeometryScriptInWorker } from './client'
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Runs a finish script (a room's floor, a wall's face) in the sandbox for what it
|
|
21
|
-
* stores the GLB and the module text, answering the compile with the stored hashes
|
|
22
|
-
* (`setRoomFloorScript` and `setWallFaceScript` take it with its `inputs`).
|
|
20
|
+
* Runs a finish script (a room's floor, a slab's surface, a wall's face) in the sandbox for what it
|
|
21
|
+
* finishes and stores the GLB and the module text, answering the compile with the stored hashes
|
|
22
|
+
* (`setRoomFloorScript`, `setSlabSurfaceScript` and `setWallFaceScript` take it with its `inputs`).
|
|
23
23
|
*/
|
|
24
24
|
export async function compileAndStoreFinishScript(
|
|
25
25
|
input: FinishScriptTarget & {
|
|
@@ -65,10 +65,10 @@ const SETTLE_MS = 150
|
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* Keeps every finish script built for what it finishes: after a scene change settles, each script
|
|
68
|
-
* whose room's floor the structure re-derived, or whose wall face changed,
|
|
69
|
-
* sandbox. The new build is written outside history, as the reconcile's derived
|
|
70
|
-
* only while its floor or face is still the one it was built for; undo brings back
|
|
71
|
-
* wall and the script built for it together.
|
|
68
|
+
* whose room's floor the structure re-derived, whose slab was reshaped, or whose wall face changed,
|
|
69
|
+
* runs again in the sandbox. The new build is written outside history, as the reconcile's derived
|
|
70
|
+
* writes are, and only while its floor or face is still the one it was built for; undo brings back
|
|
71
|
+
* the room, slab or wall and the script built for it together.
|
|
72
72
|
*/
|
|
73
73
|
export function initFinishScriptRefresh(): () => void {
|
|
74
74
|
let timer: ReturnType<typeof setTimeout> | null = null
|
|
@@ -33,7 +33,9 @@ export type GestureSpec = {
|
|
|
33
33
|
kind: string
|
|
34
34
|
/**
|
|
35
35
|
* Drops the gesture's own in-flight state (draft, preview, listeners,
|
|
36
|
-
* pending frames).
|
|
36
|
+
* pending frames). Runs once, on cancel only. Undo and redo cancel before
|
|
37
|
+
* they jump, so this must record no history: a gesture that previews
|
|
38
|
+
* through scene writes under paused history reverts them here, then resumes.
|
|
37
39
|
*/
|
|
38
40
|
onCancel: (reason: GestureCancelReason) => void
|
|
39
41
|
/** A scope the owner begins for the gesture and releases only while it is still this one. */
|