@vgai/editor 0.2.0 → 0.4.0-canary.20260715.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/README.md +24 -0
- package/dist/assets/axe-C7YBtOuM.js +30 -0
- package/dist/assets/browserAll-DDtGGE48.js +1 -0
- package/dist/assets/create-runtime-DbTlBlKG.js +1 -0
- package/dist/assets/{game-BI111o5f.js → game-BE0r7DMI.js} +3 -3
- package/dist/assets/game-BdTHR2_X.js +1 -0
- package/dist/assets/{game-pt_1lQLv.js → game-C3iQGSqo.js} +1 -1
- package/dist/assets/game-CcHfYxjP.js +1 -0
- package/dist/assets/game-Cqzj_lpD.js +1 -0
- package/dist/assets/game-DSZdeCHu.js +1 -0
- package/dist/assets/game-Dch9sAPc.js +1 -0
- package/dist/assets/{game-xsOho_wg.js → game-SAFn90pA.js} +3 -3
- package/dist/assets/game-loop-DMIgSMV-.js +1 -0
- package/dist/assets/{game-source-CvidN7AB.js → game-source-Dk83w26t.js} +1 -1
- package/dist/assets/{index-Bp5cecD6.js → index-4idIsHHJ.js} +2 -2
- package/dist/assets/{index-DL7RcQ0n.js → index-C-LhOTBN.js} +1 -1
- package/dist/assets/{index-Cs8xwv3e.js → index-CDkxceqE.js} +1 -1
- package/dist/assets/index-CQEfi217.js +15412 -0
- package/dist/assets/index-Dvi-V0NE.css +1 -0
- package/dist/assets/ingest-siblings-s0P5I1Ub.js +1 -0
- package/dist/assets/mount-manifest-DXMOlF79.js +1 -0
- package/dist/assets/react-18-C9eHn8x1.js +1 -0
- package/dist/assets/webworkerAll-Fn0e-ouF.js +1 -0
- package/dist/assets/world-documents-GM0a9Kv7.js +1 -0
- package/dist/index.html +15 -13
- package/dist/ingest/racing-game/vgai.game.json +5 -4
- package/dist/ingest/simcity/vgai.game.json +5 -4
- package/dist/ingest/tanks/vgai.game.json +5 -4
- package/dist/project-scripts.bundle.js +3917 -0
- package/dist/scenes/untitled.vscn.json +2 -0
- package/dist-server/packaged.mjs +7697 -3435
- package/package.json +31 -4
- package/scripts/probe-reporter.ts +349 -0
- package/scripts/run-probe.ts +2260 -0
- package/server/asset-catalog-audit.ts +268 -0
- package/server/asset-catalog-v2.ts +146 -0
- package/server/asset-library-routes.ts +276 -58
- package/server/canonical-path.ts +1 -1
- package/server/dev.ts +148 -44
- package/server/editor-server.ts +888 -61
- package/server/editor-sse.ts +115 -4
- package/server/harness-chat-service.ts +796 -0
- package/server/local-asset-catalog.ts +157 -22
- package/server/packaged.ts +51 -21
- package/server/process-shutdown.ts +136 -0
- package/server/prod.ts +9 -6
- package/server/project-hmr-files.ts +41 -0
- package/server/project-operations.ts +343 -0
- package/server/project-optimize-deps-entries.ts +4 -4
- package/server/project-output-writer.ts +156 -0
- package/server/project-validation.ts +140 -0
- package/server/project-view.ts +8 -50
- package/server/server-utils.ts +75 -10
- package/server/session-registry.ts +12 -0
- package/src/EditorContext.tsx +107 -3
- package/src/action-registry.ts +115 -17
- package/src/adapter-resolver.ts +213 -478
- package/src/asset-events.ts +64 -1
- package/src/asset-preview.ts +906 -0
- package/src/asset-selection.ts +121 -0
- package/src/asset-workflow/asset-capabilities.ts +259 -0
- package/src/asset-workflow/asset-editor-errors.ts +46 -0
- package/src/asset-workflow/asset-import-pipeline.ts +176 -0
- package/src/asset-workflow/asset-library-query.ts +107 -0
- package/src/asset-workflow/asset-types.ts +192 -0
- package/src/asset-workflow/asset-workflow-quality.ts +65 -0
- package/src/asset-workflow/import-contract.ts +113 -0
- package/src/asset-workflow/model-conversion.ts +126 -0
- package/src/asset-workflow/model-inspection.ts +185 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +153 -0
- package/src/asset-workflow/project-asset-operations.ts +119 -0
- package/src/asset-workflow/thumbnail-system.ts +172 -0
- package/src/authoring/active-systems.ts +15 -0
- package/src/authoring/boundary-authoring-adapter.ts +16 -5
- package/src/authoring/composite-authoring-adapter.ts +305 -124
- package/src/authoring/design-time-layers.ts +300 -117
- package/src/authoring/edit-mode-authoring.ts +278 -293
- package/src/authoring/embed-only-adapter.ts +4 -2
- package/src/authoring/first-party-hierarchy-menu.ts +7 -2
- package/src/authoring/first-party-inspector/AddSectionMenu.tsx +5 -12
- package/src/authoring/first-party-inspector/EnvironmentSection.tsx +53 -126
- package/src/authoring/first-party-inspector/HeaderSection.tsx +54 -65
- package/src/authoring/first-party-inspector/is-first-party-selection.ts +30 -11
- package/src/authoring/first-party-inspector/register.tsx +13 -2
- package/src/authoring/ingest-authoring-adapter.ts +142 -45
- package/src/authoring/mount-failure-report.ts +5 -5
- package/src/authoring/provenance.ts +41 -0
- package/src/authoring/react-dom-authoring-adapter.ts +92 -92
- package/src/authoring/react-inspector-section.tsx +489 -51
- package/src/authoring/react-world-authoring-adapter.ts +541 -306
- package/src/authoring/story-overlay.ts +1 -1
- package/src/authoring/story-types.ts +11 -0
- package/src/authoring/vgai-scene-authoring-adapter.ts +54 -25
- package/src/authoring/viewport-tool-context.ts +78 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +186 -0
- package/src/authoring/world-pan-state.ts +33 -17
- package/src/authoring/world-session-state.ts +1 -1
- package/src/authoring/world2d-authoring-adapter.ts +109 -52
- package/src/availability-tick.ts +56 -0
- package/src/browser-play-entry.ts +5 -5
- package/src/browser-project-scripts.ts +1 -0
- package/src/build-identity.ts +15 -0
- package/src/command-listener.ts +893 -19
- package/src/components/AlignToolbar.tsx +74 -63
- package/src/components/AppRoot.tsx +193 -26
- package/src/components/ApplicationMenus.tsx +272 -0
- package/src/components/AssetBrowser.tsx +1450 -293
- package/src/components/AssetEditorShell.tsx +141 -0
- package/src/components/AssetImportDetails.tsx +218 -0
- package/src/components/AssetLibraryPanel.tsx +14 -0
- package/src/components/CameraInfo.tsx +11 -20
- package/src/components/CenterDocuments.tsx +585 -0
- package/src/components/CommandPalette.tsx +75 -30
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +57 -112
- package/src/components/DebugConsolePanel.tsx +461 -0
- package/src/components/DebuggerPanel.tsx +165 -0
- package/src/components/DefaultEditorLayout.tsx +167 -231
- package/src/components/GameHierarchy.tsx +873 -290
- package/src/components/GamePerformanceOverlay.tsx +46 -0
- package/src/components/HarnessChatPanel.tsx +2352 -0
- package/src/components/HistoryPanel.tsx +226 -0
- package/src/components/Inspector.tsx +153 -99
- package/src/components/InspectorToolSection.tsx +6 -4
- package/src/components/MountFailureBanner.tsx +31 -48
- package/src/components/NetworkSection.tsx +25 -14
- package/src/components/OnlineAssetBrowser.tsx +794 -343
- package/src/components/OverlayReportBanner.tsx +38 -64
- package/src/components/PerformancePanel.tsx +206 -0
- package/src/components/PlayBar.tsx +93 -263
- package/src/components/PrefabSaveDialog.tsx +55 -127
- package/src/components/ProjectHeader.css +60 -0
- package/src/components/ProjectHeader.tsx +170 -105
- package/src/components/ProjectScreen.tsx +246 -184
- package/src/components/ReactCanvasControls.tsx +185 -0
- package/src/components/ResolutionPicker.tsx +85 -0
- package/src/components/RootActivateDialog.tsx +39 -68
- package/src/components/SaveDialog.tsx +55 -127
- package/src/components/SaveStatus.tsx +11 -29
- package/src/components/StartupLoadingScreen.tsx +96 -0
- package/src/components/StateWatchPanel.tsx +302 -0
- package/src/components/StatsOverlay.tsx +12 -5
- package/src/components/StatusBar.tsx +64 -0
- package/src/components/ThemeManagerDialog.css +89 -0
- package/src/components/ThemeManagerDialog.tsx +371 -0
- package/src/components/ToolHost.tsx +26 -15
- package/src/components/Toolbar.tsx +117 -214
- package/src/components/VgaiVoxelLogo.tsx +89 -0
- package/src/components/ViewportOverlay.tsx +97 -172
- package/src/components/ViewportPanel.tsx +130 -31
- package/src/components/WorkspaceDock.tsx +891 -0
- package/src/components/WorldSelectionOverlay.tsx +51 -63
- package/src/components/WorldTextEditor.tsx +9 -5
- package/src/components/asset-documents.tsx +390 -0
- package/src/components/asset-editor-persistence.ts +44 -0
- package/src/components/asset-selection-section.tsx +338 -0
- package/src/components/asset-viewers/AudioViewer.tsx +73 -21
- package/src/components/asset-viewers/GenericJsonViewer.tsx +26 -11
- package/src/components/asset-viewers/ImageViewer.tsx +43 -11
- package/src/components/asset-viewers/InputMapViewer.tsx +512 -134
- package/src/components/asset-viewers/MaterialAssetEditor.tsx +540 -0
- package/src/components/asset-viewers/ModelViewer.tsx +805 -121
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +177 -60
- package/src/components/asset-viewers/SourceAssetViewer.tsx +121 -0
- package/src/components/asset-workflow.css +506 -0
- package/src/components/build-documents.tsx +696 -0
- package/src/components/core-utilities.tsx +75 -0
- package/src/components/data-documents.tsx +364 -0
- package/src/components/{DataPanel.tsx → data-editor.tsx} +138 -288
- package/src/components/debugger-panel-state.ts +57 -0
- package/src/components/inspector-widgets/AlignmentGrid.tsx +8 -14
- package/src/components/inspector-widgets/BorderEditor.tsx +41 -33
- package/src/components/inspector-widgets/ColorPicker.tsx +39 -39
- package/src/components/inspector-widgets/FontPicker.tsx +13 -21
- package/src/components/inspector-widgets/GradientEditor.tsx +11 -19
- package/src/components/inspector-widgets/ScrubbableInput.tsx +6 -3
- package/src/components/inspector-widgets/ShadowEditor.tsx +20 -33
- package/src/components/inspector-widgets/shared.tsx +90 -49
- package/src/components/inspectors/AnimationSection.tsx +39 -40
- package/src/components/inspectors/AudioSection.tsx +28 -39
- package/src/components/inspectors/BoneAttachmentSection.tsx +19 -24
- package/src/components/inspectors/CameraSection.tsx +14 -23
- package/src/components/inspectors/ComponentsSection.tsx +39 -43
- package/src/components/inspectors/JointsSection.tsx +34 -43
- package/src/components/inspectors/LightSection.tsx +90 -35
- package/src/components/inspectors/MaterialSection.tsx +137 -174
- package/src/components/inspectors/MeshSection.tsx +9 -17
- package/src/components/inspectors/NavigationSection.tsx +8 -15
- package/src/components/inspectors/ParticleSection.tsx +91 -76
- package/src/components/inspectors/PhysicsSection.tsx +42 -46
- package/src/components/inspectors/PostProcessingSection.tsx +28 -36
- package/src/components/inspectors/RenderingSection.tsx +12 -20
- package/src/components/inspectors/ShadowSection.tsx +7 -8
- package/src/components/inspectors/SplineSection.tsx +31 -42
- package/src/components/inspectors/TransformSection.tsx +14 -22
- package/src/components/patterns/Dialog.tsx +95 -0
- package/src/components/patterns/Fields.tsx +44 -0
- package/src/components/patterns/List.tsx +25 -0
- package/src/components/patterns/StateSurface.tsx +40 -0
- package/src/components/patterns/Surfaces.tsx +115 -0
- package/src/components/patterns/Tabs.tsx +80 -0
- package/src/components/patterns/Toolbar.tsx +51 -0
- package/src/components/patterns/Tree.tsx +72 -0
- package/src/components/primitives/Button.tsx +46 -0
- package/src/components/primitives/ColorInput.tsx +11 -47
- package/src/components/primitives/EditorIcon.tsx +99 -0
- package/src/components/primitives/FormControls.tsx +71 -0
- package/src/components/primitives/JsonInput.tsx +15 -2
- package/src/components/primitives/Layout.tsx +100 -0
- package/src/components/primitives/Menu.tsx +105 -0
- package/src/components/primitives/NumberInput.tsx +8 -35
- package/src/components/primitives/Panel.tsx +49 -44
- package/src/components/primitives/SectionHeader.tsx +10 -28
- package/src/components/primitives/Text.tsx +46 -0
- package/src/components/primitives/Tooltip.tsx +20 -12
- package/src/components/primitives/Vec3Input.tsx +3 -0
- package/src/components/primitives/banner-tones.ts +33 -0
- package/src/components/primitives/editor-icons.ts +102 -0
- package/src/components/primitives/panel-header-styles.ts +30 -0
- package/src/components/project-operation-documents.tsx +226 -0
- package/src/components/status-contributions.tsx +175 -0
- package/src/components/story-documents-register.ts +15 -0
- package/src/components/story-documents.tsx +1185 -0
- package/src/components/tool-documents.tsx +110 -0
- package/src/components/workspace-dock.css +293 -0
- package/src/components/workspace-history.ts +33 -0
- package/src/components/world-documents.tsx +145 -0
- package/src/components/xstate-documents.tsx +209 -0
- package/src/composite-screenshot.ts +248 -0
- package/src/design-system/index.ts +70 -0
- package/src/design-system-stories/Foundation.stories.tsx +183 -0
- package/src/design-system-stories/Patterns.stories.tsx +251 -0
- package/src/design-system-stories/Workspace.stories.tsx +538 -0
- package/src/doctor/report.ts +57 -13
- package/src/editor-api.ts +295 -31
- package/src/editor-compatibility.ts +200 -0
- package/src/editor-console.ts +35 -17
- package/src/editor-hotkeys.ts +85 -33
- package/src/editor-store.ts +538 -233
- package/src/editor-viewport.ts +160 -34
- package/src/entity-factory.ts +14 -3
- package/src/gizmo-registry.ts +21 -5
- package/src/harness-chat-editor-context.ts +37 -0
- package/src/harness-chat-indicator.ts +68 -0
- package/src/harness-chat-layout.ts +53 -0
- package/src/harness-chat-lifecycle.ts +170 -0
- package/src/harness-chat-reconnect.ts +85 -0
- package/src/harness-chat-types.ts +409 -0
- package/src/hierarchy-drop.ts +50 -0
- package/src/hierarchy-expansion-state.ts +100 -0
- package/src/hierarchy-menu-registry.ts +1 -1
- package/src/hierarchy-projection.ts +76 -0
- package/src/history/editor-session.ts +21 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-service.ts +904 -0
- package/src/history/json-history-resource.ts +165 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +266 -0
- package/src/history/project-root-history-backends.ts +53 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +108 -0
- package/src/history/source-history-backend.ts +374 -0
- package/src/history/types.ts +100 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hosted-example.ts +12 -2
- package/src/hotkeys.ts +89 -18
- package/src/ingest/discovery-react.ts +9 -10
- package/src/ingest/discovery.ts +4 -4
- package/src/ingest/discovery2d.ts +5 -5
- package/src/ingest/games/bloom-composer/vgai.game.json +3 -3
- package/src/ingest/games/embed-bundle/vgai.game.json +3 -3
- package/src/ingest/games/games-fps/vgai.game.json +3 -3
- package/src/ingest/games/iframe-reachable/vgai.game.json +3 -3
- package/src/ingest/games/interactive-cubes/vgai.game.json +3 -3
- package/src/ingest/games/mismatched-three/vgai.game.json +3 -3
- package/src/ingest/games/own-three-bundled/vgai.game.json +3 -3
- package/src/ingest/games/pointerlock-maze/vgai.game.json +7 -4
- package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +3 -3
- package/src/ingest/games-2d/bunnymark/vgai.game.json +3 -3
- package/src/ingest/games-2d/flappy/vgai.game.json +3 -3
- package/src/ingest/games-2d/flappy-pixi/vgai.game.json +3 -3
- package/src/ingest/games-2d/puzzling-potions/vgai.game.json +3 -3
- package/src/ingest/games-2d/tilemap-camera/vgai.game.json +3 -3
- package/src/ingest/games-react/react-rpg/vgai.game.json +3 -3
- package/src/ingest/types.ts +1 -1
- package/src/ingest-mode.ts +47 -52
- package/src/ingest-siblings.ts +23 -33
- package/src/initial-scene.ts +1 -2
- package/src/main.tsx +16 -8
- package/src/manifest-project.ts +10 -12
- package/src/model-thumbnail.ts +261 -26
- package/src/module-mode.ts +44 -50
- package/src/play-log-events.ts +26 -0
- package/src/play-mode.ts +495 -401
- package/src/play-scene-adoption.ts +23 -0
- package/src/playground/main.ts +68 -24
- package/src/playwright-shim.ts +473 -0
- package/src/project-manager.ts +90 -10
- package/src/project-operations.ts +112 -0
- package/src/project-story-discovery.ts +25 -0
- package/src/project-tool-discovery.ts +43 -0
- package/src/scene-serializer.ts +0 -6
- package/src/scene-sync.ts +7 -2
- package/src/script-loader.ts +3 -3
- package/src/skeleton-helper.ts +57 -0
- package/src/storage/seed.ts +68 -8
- package/src/stories/StoryPreviewMount.tsx +265 -0
- package/src/stories/action-stories.fixture.tsx +44 -0
- package/src/stories/button-stories.fixture.tsx +50 -0
- package/src/stories/compose-project-stories.ts +182 -0
- package/src/stories/loader-stories.fixture.tsx +53 -0
- package/src/stories/story-discovery.ts +130 -0
- package/src/stories/story-registry.ts +146 -0
- package/src/theme-css.ts +1049 -0
- package/src/theme-library.ts +238 -0
- package/src/theme-preference.ts +130 -0
- package/src/theme.ts +527 -0
- package/src/tool-loader.ts +80 -24
- package/src/ui-source/inspect.ts +27 -4
- package/src/ui-source/source-write-backend.ts +83 -22
- package/src/widgets/index.ts +9 -18
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-dock-controller.ts +64 -0
- package/src/workspace-document-ids.ts +5 -0
- package/src/workspace-document-registry.ts +367 -0
- package/src/workspace-state-persistence.ts +455 -0
- package/src/workspace-status-registry.ts +110 -0
- package/src/workspace-utility-commands.ts +49 -0
- package/src/workspace-utility-registry.ts +161 -0
- package/src/world-document-routing.ts +16 -0
- package/src/xstate-inspect/XStateMachineInspector.tsx +544 -0
- package/src/xstate-inspect/character-animation-machine.fixture.ts +74 -0
- package/src/xstate-inspect/use-live-actor-state.ts +39 -0
- package/src/xstate-inspect/xstate-graph.ts +265 -0
- package/src/xstate-inspect/xstate-layout.ts +76 -0
- package/src/z-index.ts +26 -0
- package/template/.claude/skills/editor/SKILL.md +129 -90
- package/template/AGENTS.md +1110 -0
- package/template/CLAUDE.md +1 -512
- package/template/IDIOMS.md +50 -0
- package/template/check-idioms.ts +706 -0
- package/template/manifest-entry-modules-plugin.ts +53 -0
- package/template/package.json +13 -4
- package/template/public/scenes/default.scn2d.json +6 -0
- package/template/public/scenes/default.vscn.json +7 -1
- package/template/public/scenes/untitled.vscn.json +10 -0
- package/template/scripts/playtest.ts +40 -0
- package/template/server/loopback.ts +75 -0
- package/template/server/rooms/arena-room.ts +69 -1
- package/template/server/rooms/game-room.ts +68 -1
- package/template/src/data/README.md +9 -4
- package/template/src/data/data-ref.ts +35 -0
- package/template/src/data/tuning.schema.ts +1 -1
- package/template/src/main.ts +41 -62
- package/template/src/manifest-entry-modules.d.ts +3 -0
- package/template/src/operations/README.md +88 -0
- package/template/src/runtime/pixi-adapter.ts +24 -0
- package/template/src/scripts/components/data-spinner.ts +43 -2
- package/template/src/scripts/components/spin-lap-math.ts +27 -0
- package/template/src/tools/README.md +5 -3
- package/template/src/tools/example.tool.tsx +13 -7
- package/template/src/ui/Button.stories.tsx +66 -0
- package/template/src/ui/RebindPanel.tsx +2 -6
- package/template/src/ui/game.tsx +17 -0
- package/template/tests/acceptance/example.spec.ts +64 -0
- package/template/tests/logic/example.test.ts +31 -0
- package/template/tests/logic/room.test.ts +100 -0
- package/template/tests/tsconfig.json +30 -0
- package/template/validate-manifest.ts +5 -5
- package/template/validate-scenes.ts +50 -18
- package/template/vgai.game.json +20 -13
- package/template/vite.config.ts +77 -16
- package/vite-plugin-ui-oid.ts +261 -17
- package/dist/assets/CCDIKSolver-Dz-ysxZF.js +0 -1
- package/dist/assets/SelectionBox-BXsv_6aH.js +0 -1
- package/dist/assets/browser-project-scripts-DOru4L1x.js +0 -2
- package/dist/assets/browserAll-CEkWYlFk.js +0 -1
- package/dist/assets/create-runtime-DYIWr3va.js +0 -1
- package/dist/assets/data-asset-Bb9sIM7i.js +0 -5
- package/dist/assets/game-8SDZPPgH.js +0 -1
- package/dist/assets/game-CevorxyV.js +0 -1
- package/dist/assets/game-Di7XlywD.js +0 -1
- package/dist/assets/game-DjnCaw8R.js +0 -1
- package/dist/assets/game-Q9A0aXSV.js +0 -1
- package/dist/assets/index-CPVV6pjw.js +0 -1
- package/dist/assets/index-CpOnYyeD.js +0 -213
- package/dist/assets/index-Dr8H_6Rl.js +0 -1
- package/dist/assets/index-_bCaipUk.js +0 -13650
- package/dist/assets/ingest-siblings-Dz8eEqrV.js +0 -1
- package/dist/assets/mount-manifest-Bhk0ohsl.js +0 -1
- package/dist/assets/scene-query-BivAHhJu.js +0 -1
- package/dist/assets/webworkerAll-BLrH0F6F.js +0 -1
- package/dist/assets/xstate-animation-binding-1NGLmw6y.js +0 -1
- package/dist/assets/xstate.esm-BgUD33nl.js +0 -3
- package/src/authoring/scene-ui-layer.ts +0 -485
- package/src/authoring/ui-authoring-adapter.ts +0 -325
- package/src/authoring/ui-hierarchy-menu.ts +0 -40
- package/src/authoring/ui-inspector-sections.tsx +0 -156
- package/src/authoring/undo-timeline.ts +0 -145
- package/src/components/BottomPanel.tsx +0 -326
- package/src/components/BuildPanel.tsx +0 -455
- package/src/components/FolderTree.tsx +0 -179
- package/src/components/RightPanel.tsx +0 -166
- package/src/components/WorldContextMenu.tsx +0 -257
- package/src/components/asset-viewers/AssetViewer.tsx +0 -38
- package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +0 -129
- package/src/scene-ui-mode/active-scene-ui.ts +0 -58
- package/src/scene-ui-mode/scene-ui-palette-panel.tsx +0 -152
- package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +0 -29
- package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +0 -74
- package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +0 -49
- package/src/scene-ui-mode/ui-prefab-io.ts +0 -76
- package/src/ui-editor/inspector.tsx +0 -563
- package/src/ui-editor/node-ops.ts +0 -266
- package/src/ui-editor/overlay.tsx +0 -380
- package/src/ui-editor/palette.tsx +0 -114
- package/src/ui-editor/react-store.ts +0 -78
- package/src/ui-editor/timeline-panel.tsx +0 -443
- package/src/ui-editor/ui-edit-store.ts +0 -552
- package/src/ui-editor/ui-prefab.ts +0 -95
- package/template/project.json +0 -9
- package/template/src/scripts/main.ts +0 -94
- package/template/src/ui/DefaultHud.tsx +0 -40
- package/template/src/ui/game-state.tsx +0 -37
- package/template/src/ui/mount-default-hud.tsx +0 -19
- package/template/src/ui/mount-ui.ts +0 -15
- package/vite-plugin-react-world-provider.ts +0 -81
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { GAME_MANIFEST_VERSION } from '../../engine/src/manifest/schema';
|
|
2
|
+
|
|
3
|
+
export interface EditorServerCompatibility {
|
|
4
|
+
apiVersion: 1;
|
|
5
|
+
engineVersion: string | null;
|
|
6
|
+
manifestVersion: number;
|
|
7
|
+
startedAt: string;
|
|
8
|
+
source:
|
|
9
|
+
| { state: 'current' }
|
|
10
|
+
| { state: 'restart-required'; changedPath: string; changedAt: string };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type StartupRecovery =
|
|
14
|
+
| {
|
|
15
|
+
kind: 'retry-editor';
|
|
16
|
+
title: 'Editor server unavailable';
|
|
17
|
+
guidance: string;
|
|
18
|
+
command: 'vgai edit .';
|
|
19
|
+
}
|
|
20
|
+
| {
|
|
21
|
+
kind: 'restart-editor';
|
|
22
|
+
title: 'Restart this editor';
|
|
23
|
+
guidance: string;
|
|
24
|
+
command: 'vgai close . && vgai edit .';
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
kind: 'upgrade-project';
|
|
28
|
+
title: 'Upgrade this project';
|
|
29
|
+
guidance: string;
|
|
30
|
+
command: 'vgai upgrade .';
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
kind: 'use-compatible-editor';
|
|
34
|
+
title: 'Use a compatible editor';
|
|
35
|
+
guidance: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export class ProjectCompatibilityError extends Error {
|
|
39
|
+
readonly recovery: StartupRecovery;
|
|
40
|
+
|
|
41
|
+
constructor(message: string, recovery: StartupRecovery) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = 'ProjectCompatibilityError';
|
|
44
|
+
this.recovery = recovery;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function editorServerUnavailableError(detail?: string): ProjectCompatibilityError {
|
|
49
|
+
return new ProjectCompatibilityError(
|
|
50
|
+
`Could not reach the local editor server${detail ? `: ${detail}` : '.'}`,
|
|
51
|
+
{
|
|
52
|
+
kind: 'retry-editor',
|
|
53
|
+
title: 'Editor server unavailable',
|
|
54
|
+
guidance: 'Make sure the local editor is running, then retry this operation.',
|
|
55
|
+
command: 'vgai edit .',
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function isStartupRecovery(value: unknown): value is StartupRecovery {
|
|
61
|
+
if (!value || typeof value !== 'object') return false;
|
|
62
|
+
const candidate = value as Record<string, unknown>;
|
|
63
|
+
if (typeof candidate['title'] !== 'string' || typeof candidate['guidance'] !== 'string') {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
switch (candidate['kind']) {
|
|
67
|
+
case 'retry-editor':
|
|
68
|
+
return candidate['command'] === 'vgai edit .';
|
|
69
|
+
case 'restart-editor':
|
|
70
|
+
return candidate['command'] === 'vgai close . && vgai edit .';
|
|
71
|
+
case 'upgrade-project':
|
|
72
|
+
return candidate['command'] === 'vgai upgrade .';
|
|
73
|
+
case 'use-compatible-editor':
|
|
74
|
+
return candidate['command'] === undefined;
|
|
75
|
+
default:
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface ProjectIdentity {
|
|
81
|
+
manifestVersion?: unknown;
|
|
82
|
+
engine?: { version?: unknown } | undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const EXACT_SEMVER = /^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
86
|
+
|
|
87
|
+
function compareSemver(a: string, b: string): -1 | 0 | 1 | null {
|
|
88
|
+
const aMatch = EXACT_SEMVER.exec(a);
|
|
89
|
+
const bMatch = EXACT_SEMVER.exec(b);
|
|
90
|
+
if (!aMatch || !bMatch) return null;
|
|
91
|
+
for (let index = 1; index <= 3; index++) {
|
|
92
|
+
const aPart = Number(aMatch[index]);
|
|
93
|
+
const bPart = Number(bMatch[index]);
|
|
94
|
+
if (aPart < bPart) return -1;
|
|
95
|
+
if (aPart > bPart) return 1;
|
|
96
|
+
}
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function missingCompatibilityError(): ProjectCompatibilityError {
|
|
101
|
+
return new ProjectCompatibilityError(
|
|
102
|
+
'The editor page is newer than its local server. The running server does not expose the compatibility handshake this page expects.',
|
|
103
|
+
{
|
|
104
|
+
kind: 'restart-editor',
|
|
105
|
+
title: 'Restart this editor',
|
|
106
|
+
guidance: 'From the project folder, restart the local editor and then reopen this page.',
|
|
107
|
+
command: 'vgai close . && vgai edit .',
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Verify that the browser bundle and its long-running local server still agree. */
|
|
113
|
+
export function assertEditorCompatibility(identity: EditorServerCompatibility): void {
|
|
114
|
+
if (identity.source.state === 'restart-required') {
|
|
115
|
+
throw new ProjectCompatibilityError(
|
|
116
|
+
`The local editor server is stale. ${identity.source.changedPath} changed after this server started at ${identity.startedAt}.`,
|
|
117
|
+
{
|
|
118
|
+
kind: 'restart-editor',
|
|
119
|
+
title: 'Restart this editor',
|
|
120
|
+
guidance:
|
|
121
|
+
'The browser has newer source than the running Node process. From the project folder, restart the editor before retrying.',
|
|
122
|
+
command: 'vgai close . && vgai edit .',
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (identity.manifestVersion !== GAME_MANIFEST_VERSION) {
|
|
128
|
+
throw new ProjectCompatibilityError(
|
|
129
|
+
`The editor page supports project format v${GAME_MANIFEST_VERSION}, but its local server supports v${identity.manifestVersion}.`,
|
|
130
|
+
{
|
|
131
|
+
kind: 'restart-editor',
|
|
132
|
+
title: 'Restart this editor',
|
|
133
|
+
guidance: 'The browser and server are from different editor builds. Restart them together.',
|
|
134
|
+
command: 'vgai close . && vgai edit .',
|
|
135
|
+
},
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Verify the lightweight identity fields before full Zod manifest parsing. */
|
|
141
|
+
export function assertProjectCompatibility(
|
|
142
|
+
project: ProjectIdentity,
|
|
143
|
+
editor: EditorServerCompatibility,
|
|
144
|
+
): void {
|
|
145
|
+
if (
|
|
146
|
+
typeof project.manifestVersion === 'number' &&
|
|
147
|
+
project.manifestVersion !== GAME_MANIFEST_VERSION
|
|
148
|
+
) {
|
|
149
|
+
if (project.manifestVersion < GAME_MANIFEST_VERSION) {
|
|
150
|
+
throw new ProjectCompatibilityError(
|
|
151
|
+
`This project uses manifest format v${project.manifestVersion}; this editor requires v${GAME_MANIFEST_VERSION}.`,
|
|
152
|
+
{
|
|
153
|
+
kind: 'upgrade-project',
|
|
154
|
+
title: 'Upgrade this project',
|
|
155
|
+
guidance:
|
|
156
|
+
'Run the upgrade from the project folder. VGAI reports changes before updating scaffold-managed files.',
|
|
157
|
+
command: 'vgai upgrade .',
|
|
158
|
+
},
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
throw new ProjectCompatibilityError(
|
|
162
|
+
`This project uses manifest format v${project.manifestVersion}, which is newer than this editor's v${GAME_MANIFEST_VERSION} format.`,
|
|
163
|
+
{
|
|
164
|
+
kind: 'use-compatible-editor',
|
|
165
|
+
title: 'Use a compatible editor',
|
|
166
|
+
guidance: 'Open this project with the newer VGAI checkout or installation that created it.',
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const projectEngine = project.engine?.version;
|
|
172
|
+
const editorEngine = editor.engineVersion;
|
|
173
|
+
if (typeof projectEngine !== 'string' || !editorEngine || projectEngine === editorEngine) return;
|
|
174
|
+
|
|
175
|
+
const comparison = compareSemver(projectEngine, editorEngine);
|
|
176
|
+
if (comparison === -1) {
|
|
177
|
+
throw new ProjectCompatibilityError(
|
|
178
|
+
`This project is pinned to @vgai/engine ${projectEngine}, but this editor is running ${editorEngine}.`,
|
|
179
|
+
{
|
|
180
|
+
kind: 'upgrade-project',
|
|
181
|
+
title: 'Upgrade this project',
|
|
182
|
+
guidance:
|
|
183
|
+
'Run the upgrade from the project folder to review template changes and re-pin the engine.',
|
|
184
|
+
command: 'vgai upgrade .',
|
|
185
|
+
},
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
throw new ProjectCompatibilityError(
|
|
190
|
+
`This project is pinned to @vgai/engine ${projectEngine}, but this editor is running ${editorEngine}.`,
|
|
191
|
+
{
|
|
192
|
+
kind: 'use-compatible-editor',
|
|
193
|
+
title: 'Use a compatible editor',
|
|
194
|
+
guidance:
|
|
195
|
+
comparison === 1
|
|
196
|
+
? 'This project targets a newer engine. Open it from the matching newer VGAI checkout or installation.'
|
|
197
|
+
: 'The engine identities differ. Open the project with the exact VGAI version it is pinned to.',
|
|
198
|
+
},
|
|
199
|
+
);
|
|
200
|
+
}
|
package/src/editor-console.ts
CHANGED
|
@@ -123,8 +123,17 @@ export const editorConsole = new EditorConsole();
|
|
|
123
123
|
// anticipates: direct read access to console entries without DOM-scraping
|
|
124
124
|
// `ConsolePanel` (which has no per-entry testids). Same ad-hoc `window.__vgai*`
|
|
125
125
|
// convention as every other dev-only hook in `test-window.ts`.
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
//
|
|
127
|
+
// Guarded on `window`: this module is now imported by `ingest-authoring-adapter.ts`
|
|
128
|
+
// (to report a failed history journal loudly), which is exercised by node-env
|
|
129
|
+
// vitest suites where `window` does not exist. A bare module-scope reference
|
|
130
|
+
// throws `ReferenceError: window is not defined` at COLLECTION time — before any
|
|
131
|
+
// test body runs — so the guard belongs here at the source rather than as a
|
|
132
|
+
// `vi.mock` repeated in every importing test file.
|
|
133
|
+
if (typeof window !== 'undefined') {
|
|
134
|
+
(window as unknown as { __vgaiEditorConsole?: EditorConsole })['__vgaiEditorConsole'] =
|
|
135
|
+
editorConsole;
|
|
136
|
+
}
|
|
128
137
|
|
|
129
138
|
/**
|
|
130
139
|
* Listen for `console-bridge` postMessage events from game iframes (or self)
|
|
@@ -146,22 +155,31 @@ const ENGINE_LEVEL_MAP: Record<string, ConsoleLevel> = {
|
|
|
146
155
|
fatal: 'error',
|
|
147
156
|
};
|
|
148
157
|
|
|
149
|
-
window
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
158
|
+
// Same `window` guard as the test hook above — see the comment there.
|
|
159
|
+
if (typeof window !== 'undefined') {
|
|
160
|
+
window.addEventListener('message', (e: MessageEvent) => {
|
|
161
|
+
// Structured engine-log messages (from engine logger)
|
|
162
|
+
if (e.data?.type === 'engine-log') {
|
|
163
|
+
const level = ENGINE_LEVEL_MAP[e.data.level];
|
|
164
|
+
if (!level) return;
|
|
165
|
+
editorConsole.logStructured(
|
|
166
|
+
level,
|
|
167
|
+
e.data.message,
|
|
168
|
+
'engine',
|
|
169
|
+
e.data.subsystem,
|
|
170
|
+
e.data.metadata,
|
|
171
|
+
);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
157
174
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
});
|
|
175
|
+
// Plain console-bridge messages (from game code)
|
|
176
|
+
if (e.data?.type === 'console-bridge') {
|
|
177
|
+
const level = BRIDGE_LEVEL_MAP[e.data.level];
|
|
178
|
+
if (!level) return;
|
|
179
|
+
editorConsole[level === 'info' ? 'log' : level](e.data.message, 'engine');
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
165
183
|
|
|
166
184
|
/**
|
|
167
185
|
* Connect to the editor SSE endpoint and pipe `server-log` events
|
package/src/editor-hotkeys.ts
CHANGED
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
getActiveAuthoring,
|
|
4
4
|
hasAuthoringOverride,
|
|
5
5
|
} from './authoring/active-adapter';
|
|
6
|
-
import { timelineRedo, timelineUndo } from './authoring/undo-timeline';
|
|
7
6
|
import { resetWorldPan } from './authoring/world-pan-state';
|
|
8
7
|
import {
|
|
9
8
|
boxEditForId,
|
|
@@ -13,7 +12,12 @@ import {
|
|
|
13
12
|
} from './components/world-overlay-gestures';
|
|
14
13
|
import type { EditorStore } from './editor-store';
|
|
15
14
|
import type { EditorViewport } from './editor-viewport';
|
|
15
|
+
import type { HistoryCommands } from './history/history-commands';
|
|
16
16
|
import { installHotkeys, registerHotkeys, setActiveScope } from './hotkeys';
|
|
17
|
+
import { toggleWorkspaceFocus } from './workspace-dock-controller';
|
|
18
|
+
import { saveActiveWorkspaceDocument } from './workspace-document-registry';
|
|
19
|
+
|
|
20
|
+
const AUTHORING_SELECTION_SCOPES = ['viewport', 'hierarchy'] as const;
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
23
|
* D4 (spec27 §6 D4, §8 "Keyboard / undo / pan-zoom" row) — RECONCILED by the
|
|
@@ -62,6 +66,17 @@ import { installHotkeys, registerHotkeys, setActiveScope } from './hotkeys';
|
|
|
62
66
|
// capability-gate behavior (structure/boxEdit absent -> no-op) directly
|
|
63
67
|
// against them, without needing a full `EditorViewport`/canvas fixture.
|
|
64
68
|
|
|
69
|
+
/** Copy is shared with the browser. Claim Cmd/Ctrl+C only when the current
|
|
70
|
+
* selection is copyable by the scene clipboard and the user is not selecting
|
|
71
|
+
* DOM text. Returning false lets the native copy event continue untouched. */
|
|
72
|
+
export function shouldHandleEditorCopy(store: EditorStore): boolean {
|
|
73
|
+
const selection = window.getSelection();
|
|
74
|
+
const hasTextSelection = Boolean(
|
|
75
|
+
selection && !selection.isCollapsed && selection.toString().length > 0,
|
|
76
|
+
);
|
|
77
|
+
return store.selectedEntities.length > 0 && !hasTextSelection;
|
|
78
|
+
}
|
|
79
|
+
|
|
65
80
|
/**
|
|
66
81
|
* D4 (spec27 §6 D4 "Ctrl+D duplicate, Del/Backspace delete — route through
|
|
67
82
|
* adapter.structure.* (capability-gated)"): the pre-D4 `'d'`/`'delete'`/
|
|
@@ -213,46 +228,47 @@ export function registerEditorHotkeys(
|
|
|
213
228
|
store: EditorStore,
|
|
214
229
|
viewport: EditorViewport,
|
|
215
230
|
canvas: HTMLCanvasElement,
|
|
231
|
+
history: HistoryCommands,
|
|
216
232
|
): () => void {
|
|
217
233
|
const unregister = registerHotkeys([
|
|
218
234
|
// --- Global (fire regardless of active panel) ---
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
// adapter (first-party store / ingest / UI) recorded the MOST RECENT op,
|
|
222
|
-
// globally, regardless of which one is currently active (docs/
|
|
223
|
-
// PERSISTENCE-PROVIDER-DESIGN.md §3). Ctrl+Y mirrors Ctrl+Shift+Z (Windows
|
|
224
|
-
// convention) — see `undo-timeline.ts`.
|
|
235
|
+
// H2: one project-scoped async command queue owns shell undo/redo. Ctrl+Y
|
|
236
|
+
// mirrors Ctrl+Shift+Z (Windows convention).
|
|
225
237
|
{
|
|
226
238
|
key: 'z',
|
|
227
239
|
mod: true,
|
|
228
240
|
shift: true,
|
|
229
241
|
scope: 'global',
|
|
230
|
-
action: () =>
|
|
242
|
+
action: () => void history.redo(),
|
|
231
243
|
},
|
|
232
244
|
{
|
|
233
245
|
key: 'y',
|
|
234
246
|
mod: true,
|
|
235
247
|
scope: 'global',
|
|
236
|
-
action: () =>
|
|
248
|
+
action: () => void history.redo(),
|
|
237
249
|
},
|
|
238
250
|
{
|
|
239
251
|
key: 'z',
|
|
240
252
|
mod: true,
|
|
241
253
|
scope: 'global',
|
|
242
|
-
action: () =>
|
|
254
|
+
action: () => void history.undo(),
|
|
243
255
|
},
|
|
244
256
|
{
|
|
245
257
|
key: 'c',
|
|
246
258
|
mod: true,
|
|
247
|
-
scope:
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
259
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
260
|
+
// Native text copy wins whenever the user has selected text in a log,
|
|
261
|
+
// source preview, path label, or other non-input surface. Previously
|
|
262
|
+
// this binding matched first and called preventDefault() even when no
|
|
263
|
+
// entity was selected, which made Copy appear to fail at random across
|
|
264
|
+
// Dockview panels.
|
|
265
|
+
when: () => shouldHandleEditorCopy(store),
|
|
266
|
+
action: () => store.copyEntities(),
|
|
251
267
|
},
|
|
252
268
|
{
|
|
253
269
|
key: 'x',
|
|
254
270
|
mod: true,
|
|
255
|
-
scope:
|
|
271
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
256
272
|
action: () => {
|
|
257
273
|
if (store.selectedEntityIds.size > 0) store.cutEntities();
|
|
258
274
|
},
|
|
@@ -260,7 +276,7 @@ export function registerEditorHotkeys(
|
|
|
260
276
|
{
|
|
261
277
|
key: 'v',
|
|
262
278
|
mod: true,
|
|
263
|
-
scope:
|
|
279
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
264
280
|
action: () => {
|
|
265
281
|
if (store.hasClipboard) store.pasteEntities();
|
|
266
282
|
},
|
|
@@ -268,7 +284,7 @@ export function registerEditorHotkeys(
|
|
|
268
284
|
{
|
|
269
285
|
key: 'd',
|
|
270
286
|
mod: true,
|
|
271
|
-
scope:
|
|
287
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
272
288
|
action: () => duplicateSelection(store),
|
|
273
289
|
},
|
|
274
290
|
// D4 — wrap/unwrap (override-only, capability-gated — see
|
|
@@ -277,34 +293,44 @@ export function registerEditorHotkeys(
|
|
|
277
293
|
key: 'g',
|
|
278
294
|
mod: true,
|
|
279
295
|
alt: true,
|
|
280
|
-
scope:
|
|
296
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
281
297
|
action: () => wrapSelection(store),
|
|
282
298
|
},
|
|
283
299
|
{
|
|
284
300
|
key: 'g',
|
|
285
301
|
mod: true,
|
|
286
302
|
shift: true,
|
|
287
|
-
scope:
|
|
303
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
288
304
|
action: () => unwrapSelection(store),
|
|
289
305
|
},
|
|
290
306
|
// D4 — arrow-nudge (↑↓←→, Shift=×10 — see `nudgeSelection`'s doc comment).
|
|
291
|
-
{ key: 'arrowup', scope: '
|
|
292
|
-
{ key: 'arrowup', shift: true, scope: '
|
|
293
|
-
{ key: 'arrowdown', scope: '
|
|
294
|
-
{
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
307
|
+
{ key: 'arrowup', scope: 'viewport', action: () => nudgeSelection(store, 0, -1) },
|
|
308
|
+
{ key: 'arrowup', shift: true, scope: 'viewport', action: () => nudgeSelection(store, 0, -10) },
|
|
309
|
+
{ key: 'arrowdown', scope: 'viewport', action: () => nudgeSelection(store, 0, 1) },
|
|
310
|
+
{
|
|
311
|
+
key: 'arrowdown',
|
|
312
|
+
shift: true,
|
|
313
|
+
scope: 'viewport',
|
|
314
|
+
action: () => nudgeSelection(store, 0, 10),
|
|
315
|
+
},
|
|
316
|
+
{ key: 'arrowleft', scope: 'viewport', action: () => nudgeSelection(store, -1, 0) },
|
|
317
|
+
{
|
|
318
|
+
key: 'arrowleft',
|
|
319
|
+
shift: true,
|
|
320
|
+
scope: 'viewport',
|
|
321
|
+
action: () => nudgeSelection(store, -10, 0),
|
|
322
|
+
},
|
|
323
|
+
{ key: 'arrowright', scope: 'viewport', action: () => nudgeSelection(store, 1, 0) },
|
|
298
324
|
{
|
|
299
325
|
key: 'arrowright',
|
|
300
326
|
shift: true,
|
|
301
|
-
scope: '
|
|
327
|
+
scope: 'viewport',
|
|
302
328
|
action: () => nudgeSelection(store, 10, 0),
|
|
303
329
|
},
|
|
304
330
|
{
|
|
305
331
|
key: 'a',
|
|
306
332
|
mod: true,
|
|
307
|
-
scope:
|
|
333
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
308
334
|
action: () => {
|
|
309
335
|
if (hasAuthoringOverride()) {
|
|
310
336
|
const a = getActiveAuthoring(store);
|
|
@@ -312,27 +338,39 @@ export function registerEditorHotkeys(
|
|
|
312
338
|
} else store.selectAll();
|
|
313
339
|
},
|
|
314
340
|
},
|
|
315
|
-
{
|
|
341
|
+
{
|
|
342
|
+
key: 's',
|
|
343
|
+
mod: true,
|
|
344
|
+
scope: 'global',
|
|
345
|
+
allowInEditable: true,
|
|
346
|
+
action: () => {
|
|
347
|
+
void saveActiveWorkspaceDocument().then((handled) => {
|
|
348
|
+
// Scene/Game and legacy documents have no document-local editor.
|
|
349
|
+
// Preserve the established scene save path for those surfaces.
|
|
350
|
+
if (handled === null) void store.saveNow();
|
|
351
|
+
});
|
|
352
|
+
},
|
|
353
|
+
},
|
|
316
354
|
// D4 (spec27 §8 "space-pan" row) — Ctrl+0, the conventional "reset
|
|
317
355
|
// zoom/pan to 100%" shortcut (browsers/design tools alike), resets the
|
|
318
356
|
// DOM/react overlay's shared pan translate (`world-pan-state.ts`) back to
|
|
319
357
|
// `(0, 0)`. A no-op when already at rest or when the active surface has
|
|
320
358
|
// no pan-capable world (there is nothing for it to affect either way —
|
|
321
359
|
// `resetWorldPan()` itself no-ops at `(0,0)`).
|
|
322
|
-
{ key: '0', mod: true, scope: '
|
|
360
|
+
{ key: '0', mod: true, scope: 'viewport', action: () => resetWorldPan() },
|
|
323
361
|
{
|
|
324
362
|
key: 'delete',
|
|
325
|
-
scope:
|
|
363
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
326
364
|
action: () => void deleteSelection(store),
|
|
327
365
|
},
|
|
328
366
|
{
|
|
329
367
|
key: 'backspace',
|
|
330
|
-
scope:
|
|
368
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
331
369
|
action: () => void deleteSelection(store),
|
|
332
370
|
},
|
|
333
371
|
{
|
|
334
372
|
key: 'escape',
|
|
335
|
-
scope:
|
|
373
|
+
scope: AUTHORING_SELECTION_SCOPES,
|
|
336
374
|
// While playing, Escape is owned by play-mode (stop on Escape) — don't also
|
|
337
375
|
// clear the editor selection out from under the running game.
|
|
338
376
|
action: () => {
|
|
@@ -350,6 +388,20 @@ export function registerEditorHotkeys(
|
|
|
350
388
|
scope: 'global',
|
|
351
389
|
action: () => window.dispatchEvent(new CustomEvent('editor:toggle-console')),
|
|
352
390
|
},
|
|
391
|
+
// W5 (§6.2 focus/maximize mode) — Ctrl/Cmd+Shift+F. SHORTCUT DECISION,
|
|
392
|
+
// recorded: the benchmarks are Unity's Shift+Space (maximize view under
|
|
393
|
+
// cursor) and VS Code zen's Ctrl+K Z chord — but this registry is
|
|
394
|
+
// single-fire and chord-less, and Space already participates in the
|
|
395
|
+
// overlay's space-pan HOLD gesture (`WorldSelectionOverlay`), so both
|
|
396
|
+
// benchmarks' literal keys would collide. mod+shift+F ("Focus") is free
|
|
397
|
+
// in this registry and unclaimed by Chromium on an app page.
|
|
398
|
+
{
|
|
399
|
+
key: 'f',
|
|
400
|
+
mod: true,
|
|
401
|
+
shift: true,
|
|
402
|
+
scope: 'global',
|
|
403
|
+
action: () => toggleWorkspaceFocus(),
|
|
404
|
+
},
|
|
353
405
|
|
|
354
406
|
// --- Viewport-scoped (only when viewport/canvas is active) ---
|
|
355
407
|
{
|