@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
package/server/project-view.ts
CHANGED
|
@@ -1,64 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
// (docs/CLI-ON-FOLDER-DESIGN.md §1C).
|
|
3
|
-
//
|
|
4
|
-
// A project folder's config view can come from two places: `project.json`
|
|
5
|
-
// itself (legacy, still authoritative when present — including fields like
|
|
6
|
-
// `appId` that have no manifest home) or, when that file is ABSENT, a
|
|
7
|
-
// synthesized `{ name, defaultScene }` view derived from `vgai.game.json`
|
|
8
|
-
// (`name` from the manifest; `defaultScene` from the first world's `scene`,
|
|
9
|
-
// explicitly `null` if that world has none — e.g. an `entry`-based or ingest
|
|
10
|
-
// world — NEVER omitted: a consumer that saw the key simply missing collapsed
|
|
11
|
-
// "not declared" into "guess a path" via `?? 'scenes/default.vscn.json'`,
|
|
12
|
-
// which is what caused `initial-scene.ts` to silently WRITE a placeholder
|
|
13
|
-
// scene for a legal entry-only first world — §7.1-12 / R2b fix 1. `null` is
|
|
14
|
-
// the explicit, typed "no scene declared" the consumer is forced to branch
|
|
15
|
-
// on instead of defaulting through.
|
|
16
|
-
//
|
|
17
|
-
// This is the ONE place the project.json/manifest fallback rule lives —
|
|
18
|
-
// every server route that reads project config goes through `readProjectView`
|
|
19
|
-
// rather than re-implementing the fallback (editor-server.ts's static
|
|
20
|
-
// `/project.json` serve, `GET /__editor/project`, `POST /__editor/open-project`'s
|
|
21
|
-
// existence check, and the recent-projects existence check all call this).
|
|
1
|
+
/** Server-side editor view of the single v2 project configuration. */
|
|
22
2
|
|
|
23
|
-
import { readFile } from 'node:fs/promises';
|
|
24
3
|
import { join } from 'node:path';
|
|
25
4
|
import { loadGameManifestFile } from '../../engine/src/manifest/load-file';
|
|
26
5
|
|
|
27
6
|
export type ProjectView = Record<string, unknown>;
|
|
28
7
|
|
|
29
8
|
/**
|
|
30
|
-
* Read the
|
|
31
|
-
*
|
|
32
|
-
* - `project.json` present -> its parsed contents verbatim (whatever fields
|
|
33
|
-
* it has, including `appId`).
|
|
34
|
-
* - `project.json` absent, `vgai.game.json` present -> synthesized
|
|
35
|
-
* `{ name, defaultScene }`, where `defaultScene` is the first world's
|
|
36
|
-
* `scene` if declared, else explicit `null` (never omitted — appId is
|
|
37
|
-
* omitted, though: it has no manifest home and nothing reads it per
|
|
38
|
-
* docs/CLI-ON-FOLDER-DESIGN.md §1C).
|
|
39
|
-
* - Neither present, or the manifest exists but fails to parse -> `null`.
|
|
40
|
-
* (The hard fail-loud-on-a-broken-manifest behavior lives at the CLI
|
|
41
|
-
* discovery gate, `packages/vgai-cli/src/discovery.ts` — a server route
|
|
42
|
-
* reading a broken manifest degrades to "no project" rather than crashing
|
|
43
|
-
* the request.)
|
|
9
|
+
* Read `vgai.game.json` and derive the editor's focused scene. There is no
|
|
10
|
+
* fallback config file: a missing or invalid manifest is not a project.
|
|
44
11
|
*/
|
|
45
12
|
export async function readProjectView(root: string): Promise<ProjectView | null> {
|
|
46
|
-
try {
|
|
47
|
-
const raw = await readFile(join(root, 'project.json'), 'utf-8');
|
|
48
|
-
return JSON.parse(raw) as ProjectView;
|
|
49
|
-
} catch {
|
|
50
|
-
// project.json absent/unreadable — fall through to the manifest.
|
|
51
|
-
}
|
|
52
|
-
|
|
53
13
|
try {
|
|
54
14
|
const manifest = loadGameManifestFile(join(root, 'vgai.game.json'));
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const view: ProjectView = { name: manifest.name, defaultScene: firstWorld?.scene ?? null };
|
|
61
|
-
return view;
|
|
15
|
+
const firstSceneRoot = manifest.roots.find((candidate) => candidate.scene !== undefined);
|
|
16
|
+
return {
|
|
17
|
+
...manifest,
|
|
18
|
+
defaultScene: firstSceneRoot?.scene ?? null,
|
|
19
|
+
};
|
|
62
20
|
} catch {
|
|
63
21
|
return null;
|
|
64
22
|
}
|
package/server/server-utils.ts
CHANGED
|
@@ -203,9 +203,8 @@ export function isAllowedEditorOrigin(
|
|
|
203
203
|
* editor server — otherwise the exact version-skew class Phase B exists to
|
|
204
204
|
* kill (an editor silently serving a different engine version than the one
|
|
205
205
|
* the project declares) reappears one layer down, inside script-serving.
|
|
206
|
-
* `packageName`'s `exports` map must publish a `./package.json` entry
|
|
207
|
-
*
|
|
208
|
-
* find it.
|
|
206
|
+
* `packageName`'s `exports` map must publish a `./package.json` entry for
|
|
207
|
+
* `require.resolve` to find it.
|
|
209
208
|
*
|
|
210
209
|
* Returns `null` (never throws) when `packageName` isn't resolvable from
|
|
211
210
|
* `fromDir` — no project open, a pre-Phase-B project with no such
|
|
@@ -337,25 +336,85 @@ export function validateManifestWrite(
|
|
|
337
336
|
* Which editor list a `src/**` add/unlink invalidates, or `null` if it's
|
|
338
337
|
* irrelevant. Feeds the editor-server's second `src/`-scoped chokidar
|
|
339
338
|
* watcher (`startWatcher()` in editor-server.ts) so a NEW
|
|
340
|
-
* `src/tools/*.tool.tsx
|
|
339
|
+
* `src/tools/*.tool.tsx`, project operations, or data/schema files show up
|
|
341
340
|
* in the dock/DATA tab without a full editor reload (spec §7 W4 field note
|
|
342
341
|
* c). `.schema.json` is included on the `data` side: its add/unlink flips the
|
|
343
342
|
* DATA tab between the no-emitted-schema teaching message and real widgets.
|
|
343
|
+
* `stories` (C3, spec §9) is the same physics for a new/removed
|
|
344
|
+
* `*.stories.tsx`/`*.stories.ts` anywhere under `src/` — the Stories tab.
|
|
344
345
|
*
|
|
345
346
|
* `relPath` is project-root-relative with forward slashes (same convention
|
|
346
347
|
* `/__editor/data-files` and `/__editor/tool-files` already use).
|
|
347
348
|
*/
|
|
348
|
-
export function classifyProjectSrcPath(
|
|
349
|
+
export function classifyProjectSrcPath(
|
|
350
|
+
relPath: string,
|
|
351
|
+
): 'tools' | 'data' | 'stories' | 'operations' | null {
|
|
349
352
|
if (relPath.startsWith('src/tools/') && relPath.endsWith('.tool.tsx')) return 'tools';
|
|
353
|
+
if (
|
|
354
|
+
relPath.startsWith('src/operations/') &&
|
|
355
|
+
(relPath.endsWith('.operation.ts') || relPath.endsWith('.operation.js'))
|
|
356
|
+
) {
|
|
357
|
+
return 'operations';
|
|
358
|
+
}
|
|
350
359
|
if (
|
|
351
360
|
relPath.startsWith('src/data/') &&
|
|
352
361
|
(relPath.endsWith('.data.json') || relPath.endsWith('.schema.json'))
|
|
353
362
|
) {
|
|
354
363
|
return 'data';
|
|
355
364
|
}
|
|
365
|
+
// C3 (spec §9) — conventional CSF story files, colocated anywhere under
|
|
366
|
+
// `src/` (not confined to one subfolder like tools/data).
|
|
367
|
+
if (
|
|
368
|
+
relPath.startsWith('src/') &&
|
|
369
|
+
(relPath.endsWith('.stories.tsx') || relPath.endsWith('.stories.ts'))
|
|
370
|
+
) {
|
|
371
|
+
return 'stories';
|
|
372
|
+
}
|
|
356
373
|
return null;
|
|
357
374
|
}
|
|
358
375
|
|
|
376
|
+
// ---------------------------------------------------------------------------
|
|
377
|
+
// Watcher polling resolution (#131)
|
|
378
|
+
// ---------------------------------------------------------------------------
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Chokidar options fragment deciding whether an editor-server watcher polls.
|
|
382
|
+
*
|
|
383
|
+
* #131: on WSL drvfs mounts (`/mnt/<drive>/…`) inotify never fires, so every
|
|
384
|
+
* SSE broadcast the editor UI lives on (`scene-changed`, `asset-moved`,
|
|
385
|
+
* `tool/data/story-files-changed`, manifest validation) was structurally dead
|
|
386
|
+
* there — the owner watched an agent author a scene and the open editor never
|
|
387
|
+
* repainted until a manual browser refresh. dev.ts already auto-polls VITE's
|
|
388
|
+
* watcher on drvfs (`startProjectPollWatcher`) but deliberately never feeds
|
|
389
|
+
* these watchers (see the decoupling note at the srcWatcher construction), so
|
|
390
|
+
* they need their own decision. Chokidar's scoped `usePolling` is safe here
|
|
391
|
+
* where Vite-wide polling was not: these watchers cover only a game project's
|
|
392
|
+
* `public/`+`src/` trees and one manifest file, not the whole engine tree
|
|
393
|
+
* that made drvfs stat-flood starve the event loop (dev.ts field note
|
|
394
|
+
* 2026-07-10).
|
|
395
|
+
*
|
|
396
|
+
* Same env contract as dev.ts's poller: `VGAI_WATCH_POLL=0` forces off
|
|
397
|
+
* anywhere, `=1` forces on (default 1000ms interval), `=<ms>` forces on with
|
|
398
|
+
* that interval. Unset: auto-enable iff `root` sits on a drvfs mount
|
|
399
|
+
* (linux + `/mnt/<drive>/`). Pass `root: null` to opt out of auto-detection
|
|
400
|
+
* (engine-repo-rooted watchers, where `public/` includes the vendored-game
|
|
401
|
+
* trees and polling would be needlessly broad).
|
|
402
|
+
*/
|
|
403
|
+
export function resolveWatcherPollOptions(
|
|
404
|
+
root: string | null,
|
|
405
|
+
env: Record<string, string | undefined> = process.env,
|
|
406
|
+
platform: NodeJS.Platform = process.platform,
|
|
407
|
+
): { usePolling: true; interval: number } | Record<string, never> {
|
|
408
|
+
const raw = env['VGAI_WATCH_POLL'];
|
|
409
|
+
if (raw !== undefined && raw !== '') {
|
|
410
|
+
if (raw === '0') return {};
|
|
411
|
+
const ms = Number(raw);
|
|
412
|
+
return { usePolling: true, interval: Number.isFinite(ms) && ms > 1 ? ms : 1000 };
|
|
413
|
+
}
|
|
414
|
+
const onDrvfs = root !== null && platform === 'linux' && /^\/mnt\/[a-z]\//i.test(root);
|
|
415
|
+
return onDrvfs ? { usePolling: true, interval: 1000 } : {};
|
|
416
|
+
}
|
|
417
|
+
|
|
359
418
|
// ---------------------------------------------------------------------------
|
|
360
419
|
// Command-relay response shaping (SC1)
|
|
361
420
|
// ---------------------------------------------------------------------------
|
|
@@ -364,15 +423,21 @@ export interface CommandResult {
|
|
|
364
423
|
ok?: boolean;
|
|
365
424
|
timedOut?: boolean;
|
|
366
425
|
error?: string;
|
|
367
|
-
/** Optional payload for commands that answer with data (e.g.
|
|
426
|
+
/** Optional payload for commands that answer with data (e.g.
|
|
427
|
+
* `capture-viewport`'s base64 PNG, the Wave 5 debug-seam reads). On the
|
|
428
|
+
* failure path this carries structured markers (e.g. `{ code:
|
|
429
|
+
* 'UNKNOWN_COMMAND_TYPE' }`, registered-name lists) the SDK matches on —
|
|
430
|
+
* never message prose. Keep in sync with `command-listener.ts`'s
|
|
431
|
+
* `CommandResult`. */
|
|
368
432
|
data?: Record<string, unknown>;
|
|
369
433
|
}
|
|
370
434
|
|
|
371
435
|
/** Map a relayed-command result to an HTTP status + body. A timeout (no editor
|
|
372
436
|
* connected) is a distinct 504 error rather than a fake success. (SC1)
|
|
373
|
-
* `data
|
|
374
|
-
*
|
|
375
|
-
*
|
|
437
|
+
* `data` is spread into the response body at the top level — alongside
|
|
438
|
+
* `ok: true` on success (so `HttpEditorTransport.sendCommand` sees it
|
|
439
|
+
* without a second field of indirection) and alongside `ok: false`/`error`
|
|
440
|
+
* on the 400 path (Wave 5: the structured error-marker channel). */
|
|
376
441
|
export function commandResponseFor(result: CommandResult): {
|
|
377
442
|
status: number;
|
|
378
443
|
body: Record<string, unknown>;
|
|
@@ -384,7 +449,7 @@ export function commandResponseFor(result: CommandResult): {
|
|
|
384
449
|
body: { ok: false, error: result.error ?? 'Command timed out — no editor connected.' },
|
|
385
450
|
};
|
|
386
451
|
}
|
|
387
|
-
return { status: 400, body: { ok: false, error: result.error } };
|
|
452
|
+
return { status: 400, body: { ok: false, error: result.error, ...(result.data ?? {}) } };
|
|
388
453
|
}
|
|
389
454
|
|
|
390
455
|
// ---------------------------------------------------------------------------
|
|
@@ -23,6 +23,18 @@ export interface EditorSession {
|
|
|
23
23
|
pid: number;
|
|
24
24
|
/** ISO timestamp of server start. */
|
|
25
25
|
startedAt: string;
|
|
26
|
+
/**
|
|
27
|
+
* Additive (ACCEPTANCE-DRIVER-BUILD-PLAN.md Task 3.4): absent/undefined for
|
|
28
|
+
* every pre-existing editor session (an ordinary `vgai edit` dev server).
|
|
29
|
+
* `'probe'` marks a standalone game-page server booted by `vgai probe` —
|
|
30
|
+
* registered so it shows up in `vgai sessions`/dies via `vgai close`, and so
|
|
31
|
+
* a later `vgai probe` run can warm-reuse it instead of re-booting. Both
|
|
32
|
+
* this writer's `isSession` and the CLI reader's own copy
|
|
33
|
+
* (`packages/vgai-cli/src/editor-sessions.ts`) validate only the fields
|
|
34
|
+
* above and tolerate any extra key, so this addition is backward compatible
|
|
35
|
+
* with entries written by an older build.
|
|
36
|
+
*/
|
|
37
|
+
kind?: string;
|
|
26
38
|
}
|
|
27
39
|
|
|
28
40
|
const REGISTRY_DIR = join(homedir(), '.vgai');
|
package/src/EditorContext.tsx
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ReactNode,
|
|
3
|
+
Suspense,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useRef,
|
|
7
|
+
useSyncExternalStore,
|
|
8
|
+
} from 'react';
|
|
2
9
|
import { connectCommandListener } from './command-listener';
|
|
3
10
|
import { EditorStore } from './editor-store';
|
|
11
|
+
import { setHarnessChatEditorStore } from './harness-chat-editor-context';
|
|
12
|
+
import { EditorSession } from './history/editor-session';
|
|
13
|
+
import type { HistoryCommandSnapshot, HistoryCommands } from './history/history-commands';
|
|
14
|
+
import type { HistoryService, HistorySnapshot } from './history/history-service';
|
|
15
|
+
import { getProjectFileHistory } from './history/project-file-history';
|
|
16
|
+
import { getDataHistoryBackend } from './history/project-root-history-backends';
|
|
17
|
+
import { createHmrStableReactContext } from './hmr-stable-react-context';
|
|
4
18
|
import { initProject } from './initial-scene';
|
|
5
19
|
import { type InteractiveEditScope, InteractiveEditScopeContext } from './interactive-edit-scope';
|
|
20
|
+
import { getCurrentProject } from './project-manager';
|
|
21
|
+
import { startProjectOperationDiscovery } from './project-operations';
|
|
22
|
+
import { startProjectStoryDiscovery } from './project-story-discovery';
|
|
23
|
+
import { startProjectToolDiscovery } from './project-tool-discovery';
|
|
6
24
|
|
|
7
25
|
export interface EditorStats {
|
|
8
26
|
fps: number;
|
|
@@ -17,14 +35,26 @@ interface EditorContextValue {
|
|
|
17
35
|
store: EditorStore;
|
|
18
36
|
stats: EditorStats;
|
|
19
37
|
initPromise: Promise<void>;
|
|
38
|
+
session: EditorSession;
|
|
20
39
|
}
|
|
21
40
|
|
|
22
|
-
const EditorContext =
|
|
41
|
+
const EditorContext = createHmrStableReactContext<EditorContextValue | null>(
|
|
42
|
+
import.meta.hot?.data,
|
|
43
|
+
'EditorContext',
|
|
44
|
+
null,
|
|
45
|
+
);
|
|
23
46
|
|
|
24
47
|
export function EditorProvider({ children }: { children: ReactNode }) {
|
|
25
48
|
const storeRef = useRef<EditorStore | null>(null);
|
|
26
49
|
if (!storeRef.current) storeRef.current = new EditorStore();
|
|
27
50
|
|
|
51
|
+
const sessionRef = useRef<EditorSession | null>(null);
|
|
52
|
+
if (!sessionRef.current) {
|
|
53
|
+
const project = getCurrentProject();
|
|
54
|
+
sessionRef.current = new EditorSession(project?.rootPath ?? 'unknown-project');
|
|
55
|
+
}
|
|
56
|
+
storeRef.current.attachHistory(sessionRef.current.history);
|
|
57
|
+
|
|
28
58
|
const statsRef = useRef<EditorStats | null>(null);
|
|
29
59
|
if (!statsRef.current) {
|
|
30
60
|
statsRef.current = {
|
|
@@ -57,9 +87,56 @@ export function EditorProvider({ children }: { children: ReactNode }) {
|
|
|
57
87
|
return connectCommandListener(storeRef.current!);
|
|
58
88
|
}, []);
|
|
59
89
|
|
|
90
|
+
// W0 (docs/EDITOR-WORKSPACE-SHELL-TODO.md §7.2/§9): project-tool discovery
|
|
91
|
+
// is EDITOR-INIT lifecycle, not a bottom-dock side effect — it runs (and
|
|
92
|
+
// keeps re-running on project change / tool-file add/unlink) whether or
|
|
93
|
+
// not the Dockview workspace is mounted. WorkspaceDock only consumes the
|
|
94
|
+
// discovered registrations.
|
|
95
|
+
useEffect(() => startProjectToolDiscovery(), []);
|
|
96
|
+
|
|
97
|
+
useEffect(() => startProjectOperationDiscovery(), []);
|
|
98
|
+
|
|
99
|
+
// CSF stories may exist without a currently mounted React root. Discover
|
|
100
|
+
// them at editor init so hierarchy/Inspector story affordances and restored
|
|
101
|
+
// story documents are complete before any story document is opened.
|
|
102
|
+
useEffect(() => startProjectStoryDiscovery(), []);
|
|
103
|
+
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
setHarnessChatEditorStore(storeRef.current);
|
|
106
|
+
return () => setHarnessChatEditorStore(null);
|
|
107
|
+
}, []);
|
|
108
|
+
|
|
109
|
+
useEffect(() => () => sessionRef.current?.dispose(), []);
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
const target = globalThis as typeof globalThis & {
|
|
113
|
+
__vgaiHistoryWriteData?: (path: string, content: string) => Promise<void>;
|
|
114
|
+
};
|
|
115
|
+
const writer = async (path: string, content: string): Promise<void> => {
|
|
116
|
+
await getProjectFileHistory(
|
|
117
|
+
sessionRef.current!.history,
|
|
118
|
+
getDataHistoryBackend(),
|
|
119
|
+
'project-data',
|
|
120
|
+
).write(path, content, {
|
|
121
|
+
label: `Edit ${path.split('/').pop() ?? 'Data'}`,
|
|
122
|
+
kind: 'data',
|
|
123
|
+
contentType: 'application/json',
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
target.__vgaiHistoryWriteData = writer;
|
|
127
|
+
return () => {
|
|
128
|
+
if (target.__vgaiHistoryWriteData === writer) delete target.__vgaiHistoryWriteData;
|
|
129
|
+
};
|
|
130
|
+
}, []);
|
|
131
|
+
|
|
60
132
|
return (
|
|
61
133
|
<EditorContext.Provider
|
|
62
|
-
value={{
|
|
134
|
+
value={{
|
|
135
|
+
store: storeRef.current,
|
|
136
|
+
stats: statsRef.current,
|
|
137
|
+
initPromise: initRef.current,
|
|
138
|
+
session: sessionRef.current,
|
|
139
|
+
}}
|
|
63
140
|
>
|
|
64
141
|
<InteractiveEditScopeContext.Provider value={editScopeRef.current}>
|
|
65
142
|
<Suspense>{children}</Suspense>
|
|
@@ -85,3 +162,30 @@ export function useEditorInit(): Promise<void> {
|
|
|
85
162
|
if (!ctx) throw new Error('useEditorInit must be used within <EditorProvider>');
|
|
86
163
|
return ctx.initPromise;
|
|
87
164
|
}
|
|
165
|
+
|
|
166
|
+
export function useHistoryService(): HistoryService {
|
|
167
|
+
const ctx = useContext(EditorContext);
|
|
168
|
+
if (!ctx) throw new Error('useHistoryService must be used within <EditorProvider>');
|
|
169
|
+
return ctx.session.history;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** History-aware panels may still be rendered in isolated component tests. */
|
|
173
|
+
export function useOptionalHistoryService(): HistoryService | null {
|
|
174
|
+
return useContext(EditorContext)?.session.history ?? null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function useHistoryCommands(): HistoryCommands {
|
|
178
|
+
const ctx = useContext(EditorContext);
|
|
179
|
+
if (!ctx) throw new Error('useHistoryCommands must be used within <EditorProvider>');
|
|
180
|
+
return ctx.session.historyCommands;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function useHistoryCommandSnapshot(): HistoryCommandSnapshot {
|
|
184
|
+
const history = useHistoryCommands();
|
|
185
|
+
return useSyncExternalStore(history.subscribe, history.getSnapshot, history.getSnapshot);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function useHistorySnapshot(): HistorySnapshot {
|
|
189
|
+
const history = useHistoryService();
|
|
190
|
+
return useSyncExternalStore(history.subscribe, history.getSnapshot, history.getSnapshot);
|
|
191
|
+
}
|
package/src/action-registry.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PROJECT_ASSET_COMMANDS } from './asset-workflow/project-asset-commands';
|
|
2
|
+
import { openBuildProfilesDocument } from './components/build-documents';
|
|
3
|
+
import { openDebuggerPanel } from './components/debugger-panel-state';
|
|
4
|
+
import { getEditorMode } from './editor-mode';
|
|
2
5
|
import type { EditorStore } from './editor-store';
|
|
6
|
+
import type { HistoryCommandSnapshot, HistoryCommands } from './history/history-commands';
|
|
7
|
+
import { openUndoHistory } from './workspace-aux-commands';
|
|
8
|
+
import { showWorkspaceNavigator, toggleWorkspaceFocus } from './workspace-dock-controller';
|
|
3
9
|
|
|
4
10
|
export interface EditorAction {
|
|
5
11
|
id: string;
|
|
6
12
|
label: string;
|
|
7
13
|
category: 'action' | 'entity' | 'asset';
|
|
8
14
|
shortcut?: string;
|
|
9
|
-
execute: () => void
|
|
15
|
+
execute: () => void | Promise<void>;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
const RECENT_KEY = 'editor:recent-actions';
|
|
@@ -28,28 +34,34 @@ export function pushRecentAction(id: string): void {
|
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
/** Build the static list of editor command actions. */
|
|
31
|
-
export function buildStaticActions(
|
|
37
|
+
export function buildStaticActions(
|
|
38
|
+
store: EditorStore,
|
|
39
|
+
history: HistoryCommands,
|
|
40
|
+
historySnapshot?: HistoryCommandSnapshot,
|
|
41
|
+
): EditorAction[] {
|
|
32
42
|
const isMac = navigator.platform.includes('Mac');
|
|
33
43
|
const mod = isMac ? '\u2318' : 'Ctrl+';
|
|
34
44
|
|
|
35
45
|
return [
|
|
36
46
|
{
|
|
37
47
|
id: 'editor.undo',
|
|
38
|
-
label: 'Undo',
|
|
48
|
+
label: historySnapshot?.undoLabel ? `Undo ${historySnapshot.undoLabel}` : 'Undo',
|
|
39
49
|
category: 'action',
|
|
40
50
|
shortcut: `${mod}Z`,
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
// H2: shell actions use the project-scoped command service. Its temporary
|
|
52
|
+
// compatibility bridge preserves chronology with producers not yet migrated.
|
|
53
|
+
execute: async () => {
|
|
54
|
+
await history.undo();
|
|
55
|
+
},
|
|
46
56
|
},
|
|
47
57
|
{
|
|
48
58
|
id: 'editor.redo',
|
|
49
|
-
label: 'Redo',
|
|
59
|
+
label: historySnapshot?.redoLabel ? `Redo ${historySnapshot.redoLabel}` : 'Redo',
|
|
50
60
|
category: 'action',
|
|
51
61
|
shortcut: `${mod}\u21E7Z`,
|
|
52
|
-
execute: () =>
|
|
62
|
+
execute: async () => {
|
|
63
|
+
await history.redo();
|
|
64
|
+
},
|
|
53
65
|
},
|
|
54
66
|
{
|
|
55
67
|
id: 'editor.copy',
|
|
@@ -236,21 +248,107 @@ export function buildStaticActions(store: EditorStore): EditorAction[] {
|
|
|
236
248
|
},
|
|
237
249
|
},
|
|
238
250
|
{
|
|
239
|
-
id: '
|
|
240
|
-
label: '
|
|
251
|
+
id: 'view.focusMode',
|
|
252
|
+
label: 'Toggle Focus Mode',
|
|
241
253
|
category: 'action',
|
|
254
|
+
shortcut: `${mod}⇧F`,
|
|
242
255
|
execute: () => {
|
|
243
|
-
|
|
256
|
+
toggleWorkspaceFocus();
|
|
244
257
|
},
|
|
245
258
|
},
|
|
246
259
|
{
|
|
247
|
-
id: '
|
|
248
|
-
label: '
|
|
260
|
+
id: 'view.undoHistory',
|
|
261
|
+
label: 'Undo History',
|
|
249
262
|
category: 'action',
|
|
250
263
|
execute: () => {
|
|
251
|
-
|
|
264
|
+
// Undo History is an on-demand panel, not a permanent tab. Dockview
|
|
265
|
+
// defaults it beside Inspector but preserves a user's later move.
|
|
266
|
+
// §8 naming: 'Undo History', not 'History'.
|
|
267
|
+
openUndoHistory();
|
|
252
268
|
},
|
|
253
269
|
},
|
|
270
|
+
{
|
|
271
|
+
id: 'view.profiler',
|
|
272
|
+
label: 'Open Profiler',
|
|
273
|
+
category: 'action',
|
|
274
|
+
execute: () => openDebuggerPanel('profiler'),
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
id: 'view.state-watch',
|
|
278
|
+
label: 'Open State Watch',
|
|
279
|
+
category: 'action',
|
|
280
|
+
execute: () => openDebuggerPanel('state'),
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
id: 'view.network-debugger',
|
|
284
|
+
label: 'Open Network Diagnostics',
|
|
285
|
+
category: 'action',
|
|
286
|
+
execute: () => openDebuggerPanel('network'),
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
id: 'view.machine-debugger',
|
|
290
|
+
label: 'Open State Machines',
|
|
291
|
+
category: 'action',
|
|
292
|
+
execute: () => openDebuggerPanel('machines'),
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
id: 'view.debug-commands',
|
|
296
|
+
label: 'Open Debug Commands',
|
|
297
|
+
category: 'action',
|
|
298
|
+
execute: () => openDebuggerPanel('commands'),
|
|
299
|
+
},
|
|
300
|
+
...Object.values(PROJECT_ASSET_COMMANDS)
|
|
301
|
+
.filter((command) => command.id !== PROJECT_ASSET_COMMANDS.open.id)
|
|
302
|
+
.map((command) => ({
|
|
303
|
+
id: command.id,
|
|
304
|
+
label: `${command.id
|
|
305
|
+
.replace('project-asset.', '')
|
|
306
|
+
.split('-')
|
|
307
|
+
.map((part) => part[0]?.toUpperCase() + part.slice(1))
|
|
308
|
+
.join(' ')} Project Asset`,
|
|
309
|
+
category: 'asset' as const,
|
|
310
|
+
...(command.shortcut ? { shortcut: command.shortcut.replace('Mod', mod) } : {}),
|
|
311
|
+
execute: () => {
|
|
312
|
+
window.dispatchEvent(
|
|
313
|
+
new CustomEvent('editor:project-asset-command', { detail: { id: command.id } }),
|
|
314
|
+
);
|
|
315
|
+
},
|
|
316
|
+
})),
|
|
317
|
+
// W3 build split (build-documents.tsx): the build actions open the Build
|
|
318
|
+
// Profiles CENTER document (config + the Build trigger); the log streams
|
|
319
|
+
// into the Build Output utility. Server mode only — builds spawn npm
|
|
320
|
+
// scripts server-side (pre-W3 these dispatched an event no tab handled
|
|
321
|
+
// in browser mode).
|
|
322
|
+
...(getEditorMode() === 'server'
|
|
323
|
+
? [
|
|
324
|
+
{
|
|
325
|
+
// Assets and Library are permanent peer navigators; individual
|
|
326
|
+
// results open as center asset documents.
|
|
327
|
+
id: 'view.asset-library',
|
|
328
|
+
label: 'Asset Library',
|
|
329
|
+
category: 'action' as const,
|
|
330
|
+
execute: () => {
|
|
331
|
+
showWorkspaceNavigator('asset-library');
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
id: 'build.web',
|
|
336
|
+
label: 'Build for Web (itch.io)',
|
|
337
|
+
category: 'action' as const,
|
|
338
|
+
execute: () => {
|
|
339
|
+
openBuildProfilesDocument(store);
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
id: 'build.steam',
|
|
344
|
+
label: 'Build for Desktop (Steam)',
|
|
345
|
+
category: 'action' as const,
|
|
346
|
+
execute: () => {
|
|
347
|
+
openBuildProfilesDocument(store);
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
]
|
|
351
|
+
: []),
|
|
254
352
|
];
|
|
255
353
|
}
|
|
256
354
|
|