@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
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { resolveUrl } from '@engine/loader';
|
|
2
2
|
import { parsePrefabFile, parseSceneFile } from '@engine/scene/parse';
|
|
3
3
|
import type { PrefabFile, SceneFile } from '@engine/scene/scene-types';
|
|
4
|
-
import { use, useCallback, useEffect,
|
|
4
|
+
import { use, useCallback, useEffect, useState, useSyncExternalStore } from 'react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
connectAssetEvents,
|
|
8
|
+
connectSceneEvents,
|
|
9
|
+
decideExternalSceneChangeAction,
|
|
10
|
+
} from '../asset-events';
|
|
11
|
+
import { installAssetSelectionAutoClear } from '../asset-selection';
|
|
7
12
|
import { getActiveAuthoring, hasAuthoringOverride } from '../authoring/active-adapter';
|
|
13
|
+
import {
|
|
14
|
+
switchFocusedWorld,
|
|
15
|
+
WORLD_FOCUS_REQUEST_EVENT,
|
|
16
|
+
type WorldFocusRequest,
|
|
17
|
+
} from '../authoring/edit-mode-authoring';
|
|
8
18
|
import {
|
|
9
19
|
findOwningRootGroupId,
|
|
10
20
|
ROOT_ACTIVATION_REQUEST_EVENT,
|
|
@@ -12,24 +22,30 @@ import {
|
|
|
12
22
|
requestRootActivation,
|
|
13
23
|
} from '../authoring/root-activation';
|
|
14
24
|
import { watchExternalSceneChanges } from '../browser-external-watch';
|
|
15
|
-
import {
|
|
25
|
+
import { themeVars } from '../design-system';
|
|
26
|
+
import { useEditorInit, useEditorStore, useHistoryService } from '../EditorContext';
|
|
16
27
|
import { readProjectTextFile, saveFile } from '../editor-api';
|
|
17
28
|
import { editorConsole } from '../editor-console';
|
|
18
29
|
import { getEditorMode } from '../editor-mode';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { UIPrefabDialogHost } from '../scene-ui-mode/ui-prefab-dialog-host';
|
|
30
|
+
import type { HistoryService } from '../history/history-service';
|
|
31
|
+
import { getProjectFileHistory } from '../history/project-file-history';
|
|
22
32
|
import { getStorageBackend } from '../storage';
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
33
|
+
import { installAuxiliaryEvents } from '../workspace-aux-commands';
|
|
34
|
+
import { installUtilityAutoOpen, installUtilityEvents } from '../workspace-utility-commands';
|
|
35
|
+
import { ensureBuildContributionsRegistered } from './build-documents';
|
|
36
|
+
import { useCenterDocuments } from './CenterDocuments';
|
|
37
|
+
import { CommandPalette } from './CommandPalette';
|
|
38
|
+
import { ensureCoreUtilitiesRegistered } from './core-utilities';
|
|
39
|
+
import { configureDataDocumentStore, startDataAssetDiscovery } from './data-documents';
|
|
25
40
|
import { MountFailureBanner } from './MountFailureBanner';
|
|
26
|
-
import { NetworkSection } from './NetworkSection';
|
|
27
|
-
import { PlayBar, type Resolution } from './PlayBar';
|
|
28
41
|
import { PrefabSaveDialog } from './PrefabSaveDialog';
|
|
29
42
|
import { ProjectHeader } from './ProjectHeader';
|
|
30
|
-
import { RightPanel } from './RightPanel';
|
|
31
43
|
import { RootActivateDialog } from './RootActivateDialog';
|
|
32
|
-
import {
|
|
44
|
+
import { StatusBar } from './StatusBar';
|
|
45
|
+
import { ensureCoreStatusContributionsRegistered } from './status-contributions';
|
|
46
|
+
import { WorkspaceDock } from './WorkspaceDock';
|
|
47
|
+
import { setWorkspaceHistoryService } from './workspace-history';
|
|
48
|
+
import { configureXStateInspector } from './xstate-documents';
|
|
33
49
|
|
|
34
50
|
/** Load a scene from a URL into the store. */
|
|
35
51
|
export async function openSceneFromAsset(
|
|
@@ -52,14 +68,33 @@ export async function openSceneFromAsset(
|
|
|
52
68
|
export async function saveMaterialToServer(
|
|
53
69
|
material: import('@engine/scene/scene-types').MaterialFile,
|
|
54
70
|
path: string,
|
|
71
|
+
history?: HistoryService,
|
|
55
72
|
): Promise<boolean> {
|
|
56
73
|
const content = JSON.stringify(material, null, 2);
|
|
74
|
+
if (history) {
|
|
75
|
+
return getProjectFileHistory(history).write(path, content, {
|
|
76
|
+
label: `Edit ${path.split('/').pop() ?? 'Material'}`,
|
|
77
|
+
kind: 'material',
|
|
78
|
+
contentType: 'application/json',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
57
81
|
return saveFile(path, content);
|
|
58
82
|
}
|
|
59
83
|
|
|
60
84
|
/** Save a PrefabFile to disk via the editor server API. */
|
|
61
|
-
export async function savePrefabToServer(
|
|
85
|
+
export async function savePrefabToServer(
|
|
86
|
+
prefab: PrefabFile,
|
|
87
|
+
path: string,
|
|
88
|
+
history?: HistoryService,
|
|
89
|
+
): Promise<boolean> {
|
|
62
90
|
const content = JSON.stringify(prefab, null, 2);
|
|
91
|
+
if (history) {
|
|
92
|
+
return getProjectFileHistory(history).write(path, content, {
|
|
93
|
+
label: `Save ${path.split('/').pop() ?? 'Prefab'}`,
|
|
94
|
+
kind: 'prefab',
|
|
95
|
+
contentType: 'application/json',
|
|
96
|
+
});
|
|
97
|
+
}
|
|
63
98
|
return saveFile(path, content);
|
|
64
99
|
}
|
|
65
100
|
|
|
@@ -91,165 +126,48 @@ export async function fetchPrefabFile(url: string): Promise<PrefabFile | null> {
|
|
|
91
126
|
}
|
|
92
127
|
}
|
|
93
128
|
|
|
94
|
-
/** Game panel — a container div that play-mode.ts fills with a canvas. */
|
|
95
|
-
function GamePanel({ style }: { style?: React.CSSProperties }) {
|
|
96
|
-
const store = useEditorStore();
|
|
97
|
-
const outerRef = useRef<HTMLDivElement>(null);
|
|
98
|
-
const [resolution, setResolution] = useState<Resolution>({
|
|
99
|
-
label: 'Fill',
|
|
100
|
-
width: null,
|
|
101
|
-
height: null,
|
|
102
|
-
});
|
|
103
|
-
const [containerSize, setContainerSize] = useState({ width: 0, height: 0 });
|
|
104
|
-
|
|
105
|
-
// Callback ref so setGameContainer is called even when the element swaps (fill ↔ device)
|
|
106
|
-
const prevRef = useRef<HTMLDivElement | null>(null);
|
|
107
|
-
const canvasRef = useCallback((el: HTMLDivElement | null) => {
|
|
108
|
-
if (el === prevRef.current) return;
|
|
109
|
-
// Move game canvas to new container
|
|
110
|
-
if (prevRef.current && el) {
|
|
111
|
-
while (prevRef.current.firstChild) el.appendChild(prevRef.current.firstChild);
|
|
112
|
-
}
|
|
113
|
-
prevRef.current = el;
|
|
114
|
-
setGameContainer(el);
|
|
115
|
-
}, []);
|
|
116
|
-
|
|
117
|
-
// Track outer container size for scale calculation
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
const el = outerRef.current;
|
|
120
|
-
if (!el) return;
|
|
121
|
-
const observer = new ResizeObserver(([entry]) => {
|
|
122
|
-
if (!entry) return;
|
|
123
|
-
setContainerSize({ width: entry.contentRect.width, height: entry.contentRect.height });
|
|
124
|
-
});
|
|
125
|
-
observer.observe(el);
|
|
126
|
-
return () => observer.disconnect();
|
|
127
|
-
}, []);
|
|
128
|
-
|
|
129
|
-
// Resize the game renderer when resolution or container size changes
|
|
130
|
-
const isFill = resolution.width === null;
|
|
131
|
-
useEffect(() => {
|
|
132
|
-
if (isFill) {
|
|
133
|
-
// Fill mode: resize to match available container space
|
|
134
|
-
if (containerSize.width > 0 && containerSize.height > 0) {
|
|
135
|
-
resizeGame(containerSize.width, containerSize.height);
|
|
136
|
-
}
|
|
137
|
-
} else {
|
|
138
|
-
resizeGame(resolution.width!, resolution.height!);
|
|
139
|
-
}
|
|
140
|
-
}, [isFill, resolution.width, resolution.height, containerSize.width, containerSize.height]);
|
|
141
|
-
|
|
142
|
-
// Scale: fit the device resolution into the available space, never upscale
|
|
143
|
-
let scale = 1;
|
|
144
|
-
if (!isFill && containerSize.width > 0 && containerSize.height > 0) {
|
|
145
|
-
const scaleX = containerSize.width / resolution.width!;
|
|
146
|
-
const scaleY = containerSize.height / resolution.height!;
|
|
147
|
-
scale = Math.min(scaleX, scaleY, 1);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return (
|
|
151
|
-
<div style={{ overflow: 'hidden', position: 'relative', flexDirection: 'column', ...style }}>
|
|
152
|
-
<div
|
|
153
|
-
ref={outerRef}
|
|
154
|
-
style={{
|
|
155
|
-
flex: 1,
|
|
156
|
-
overflow: 'hidden',
|
|
157
|
-
display: 'flex',
|
|
158
|
-
alignItems: 'center',
|
|
159
|
-
justifyContent: 'center',
|
|
160
|
-
position: 'relative',
|
|
161
|
-
}}
|
|
162
|
-
>
|
|
163
|
-
{isFill ? (
|
|
164
|
-
<div ref={canvasRef} aria-hidden="true" style={{ position: 'absolute', inset: 0 }} />
|
|
165
|
-
) : (
|
|
166
|
-
/* Wrapper sized to the scaled dimensions so flexbox centering works.
|
|
167
|
-
The inner canvasRef is full device resolution, CSS-scaled down. */
|
|
168
|
-
<div
|
|
169
|
-
style={{
|
|
170
|
-
width: resolution.width! * scale,
|
|
171
|
-
height: resolution.height! * scale,
|
|
172
|
-
overflow: 'hidden',
|
|
173
|
-
}}
|
|
174
|
-
>
|
|
175
|
-
<div
|
|
176
|
-
ref={canvasRef}
|
|
177
|
-
aria-hidden="true"
|
|
178
|
-
style={{
|
|
179
|
-
width: resolution.width!,
|
|
180
|
-
height: resolution.height!,
|
|
181
|
-
transformOrigin: 'top left',
|
|
182
|
-
transform: `scale(${scale})`,
|
|
183
|
-
}}
|
|
184
|
-
/>
|
|
185
|
-
</div>
|
|
186
|
-
)}
|
|
187
|
-
{/* Same overlay ViewportPanel renders on the Scene tab (T-R1a #6) — the
|
|
188
|
-
Game tab is where play auto-switches to, so it must render here too,
|
|
189
|
-
not only on the Scene-tab viewport it would otherwise be hidden behind. */}
|
|
190
|
-
{store.playState !== 'stopped' && <NetworkSection />}
|
|
191
|
-
</div>
|
|
192
|
-
<PlayBar resolution={resolution} onResolutionChange={setResolution} scale={scale} />
|
|
193
|
-
</div>
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function ViewportTabBar({
|
|
198
|
-
active,
|
|
199
|
-
onChange,
|
|
200
|
-
showGame,
|
|
201
|
-
}: {
|
|
202
|
-
active: 'scene' | 'game';
|
|
203
|
-
onChange: (tab: 'scene' | 'game') => void;
|
|
204
|
-
showGame: boolean;
|
|
205
|
-
}) {
|
|
206
|
-
const tabStyle = (isActive: boolean): React.CSSProperties => ({
|
|
207
|
-
background: 'none',
|
|
208
|
-
border: 'none',
|
|
209
|
-
padding: '4px 8px',
|
|
210
|
-
cursor: 'pointer',
|
|
211
|
-
fontSize: 11,
|
|
212
|
-
fontWeight: 600,
|
|
213
|
-
textTransform: 'uppercase',
|
|
214
|
-
color: isActive ? '#c5c8ce' : '#666',
|
|
215
|
-
borderBottom: isActive ? '2px solid #579eff' : '2px solid transparent',
|
|
216
|
-
marginBottom: -1,
|
|
217
|
-
pointerEvents: 'auto',
|
|
218
|
-
});
|
|
219
|
-
return (
|
|
220
|
-
<div
|
|
221
|
-
style={{
|
|
222
|
-
display: 'flex',
|
|
223
|
-
gap: 2,
|
|
224
|
-
background: '#2c2c2c',
|
|
225
|
-
borderBottom: '1px solid #333',
|
|
226
|
-
flexShrink: 0,
|
|
227
|
-
pointerEvents: 'auto',
|
|
228
|
-
}}
|
|
229
|
-
>
|
|
230
|
-
<button type="button" style={tabStyle(active === 'scene')} onClick={() => onChange('scene')}>
|
|
231
|
-
Viewport
|
|
232
|
-
</button>
|
|
233
|
-
{showGame && (
|
|
234
|
-
<button type="button" style={tabStyle(active === 'game')} onClick={() => onChange('game')}>
|
|
235
|
-
Game
|
|
236
|
-
</button>
|
|
237
|
-
)}
|
|
238
|
-
</div>
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
129
|
export function DefaultEditorLayout({
|
|
243
130
|
onReturnToProjectScreen,
|
|
244
131
|
}: {
|
|
245
132
|
onReturnToProjectScreen?: (() => void) | undefined;
|
|
246
133
|
}) {
|
|
247
134
|
const store = useEditorStore();
|
|
135
|
+
const history = useHistoryService();
|
|
248
136
|
use(useEditorInit()); // suspends until project is detected
|
|
249
137
|
|
|
250
138
|
// Subscribe to store changes
|
|
251
139
|
useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
252
|
-
|
|
140
|
+
// W1 — install the center workspace documents (scene + Game) and keep the
|
|
141
|
+
// document registry synced with the store's activeViewportTab (T6.3 gate).
|
|
142
|
+
useCenterDocuments(store);
|
|
143
|
+
// W3 (workspace-shell §9/W3) — the shell contributions the new center
|
|
144
|
+
// documents ride on:
|
|
145
|
+
// - data-asset discovery (folder-scan store behind the per-file data
|
|
146
|
+
// documents + the palette's Open Data Asset actions), plus the store
|
|
147
|
+
// bridge the Data Assets navigation document opens siblings through;
|
|
148
|
+
// - the XState selected-live-entity Inspector section (§4.3 — matches
|
|
149
|
+
// ONLY a real live `bindXStateAnimation` binding; no demo anywhere);
|
|
150
|
+
// - the Build Output utility + build-progress status contribution
|
|
151
|
+
// (server mode only — builds spawn npm scripts server-side).
|
|
152
|
+
// W4 (workspace-shell §9/W4) — status-bar contributions register BEFORE the
|
|
153
|
+
// build ensure below so the order-0 items sequence save-status first; the
|
|
154
|
+
// utility auto-open watcher (save/build failure → the correct Dockview
|
|
155
|
+
// panel) is per-store. Core utilities register before the host reconciles.
|
|
156
|
+
useEffect(() => ensureCoreStatusContributionsRegistered(), []);
|
|
157
|
+
useEffect(() => ensureCoreUtilitiesRegistered(), []);
|
|
158
|
+
useEffect(() => installUtilityAutoOpen(store), [store]);
|
|
159
|
+
useEffect(() => installUtilityEvents(), []);
|
|
160
|
+
useEffect(() => installAuxiliaryEvents(), []);
|
|
161
|
+
useEffect(() => startDataAssetDiscovery(), []);
|
|
162
|
+
useEffect(() => configureDataDocumentStore(store), [store]);
|
|
163
|
+
useEffect(() => setWorkspaceHistoryService(history), [history]);
|
|
164
|
+
useEffect(() => configureXStateInspector(store), [store]);
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
if (getEditorMode() === 'server') ensureBuildContributionsRegistered();
|
|
167
|
+
}, []);
|
|
168
|
+
// W2 (§5.1) — an ENTITY selection change drops the asset selection, so the
|
|
169
|
+
// Inspector goes back to being purely entity-contextual (asset-selection.ts).
|
|
170
|
+
useEffect(() => installAssetSelectionAutoClear(store), [store]);
|
|
253
171
|
const [prefabSaveState, setPrefabSaveState] = useState<{ entityId: string; name: string } | null>(
|
|
254
172
|
null,
|
|
255
173
|
);
|
|
@@ -270,6 +188,20 @@ export function DefaultEditorLayout({
|
|
|
270
188
|
return () => window.removeEventListener(ROOT_ACTIVATION_REQUEST_EVENT, handler);
|
|
271
189
|
}, []);
|
|
272
190
|
|
|
191
|
+
// A4 (focus-switch) — the world-focus twin of the root-activation dialog
|
|
192
|
+
// above: `requestWorldFocus` dispatches this when the store is dirty; the
|
|
193
|
+
// same RootActivateDialog renders with world copy, and confirm runs the
|
|
194
|
+
// actual switch.
|
|
195
|
+
const [pendingWorldFocus, setPendingWorldFocus] = useState<WorldFocusRequest | null>(null);
|
|
196
|
+
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
const handler = (e: Event) => {
|
|
199
|
+
setPendingWorldFocus((e as CustomEvent<WorldFocusRequest>).detail);
|
|
200
|
+
};
|
|
201
|
+
window.addEventListener(WORLD_FOCUS_REQUEST_EVENT, handler);
|
|
202
|
+
return () => window.removeEventListener(WORLD_FOCUS_REQUEST_EVENT, handler);
|
|
203
|
+
}, []);
|
|
204
|
+
|
|
273
205
|
// Listen for "save as prefab" events from the hierarchy context menu
|
|
274
206
|
useEffect(() => {
|
|
275
207
|
const handler = (e: Event) => {
|
|
@@ -288,15 +220,24 @@ export function DefaultEditorLayout({
|
|
|
288
220
|
setPrefabSaveState(null);
|
|
289
221
|
return;
|
|
290
222
|
}
|
|
291
|
-
|
|
223
|
+
const save = history
|
|
224
|
+
? store.savePrefabAndConvertInstance(
|
|
225
|
+
prefabSaveState.entityId,
|
|
226
|
+
path,
|
|
227
|
+
JSON.stringify(prefab, null, 2),
|
|
228
|
+
)
|
|
229
|
+
: savePrefabToServer(prefab, path);
|
|
230
|
+
save.then((ok) => {
|
|
292
231
|
if (ok) {
|
|
293
|
-
|
|
294
|
-
|
|
232
|
+
if (!history) {
|
|
233
|
+
const servingPath = `/${path}`;
|
|
234
|
+
store.convertToPrefabInstance(prefabSaveState.entityId, servingPath);
|
|
235
|
+
}
|
|
295
236
|
}
|
|
296
237
|
setPrefabSaveState(null);
|
|
297
238
|
});
|
|
298
239
|
},
|
|
299
|
-
[store, prefabSaveState],
|
|
240
|
+
[store, prefabSaveState, history],
|
|
300
241
|
);
|
|
301
242
|
|
|
302
243
|
// A4 (D8) — the SINGLE choke point for the asset-browser's scene/prefab
|
|
@@ -339,10 +280,13 @@ export function DefaultEditorLayout({
|
|
|
339
280
|
|
|
340
281
|
// Subscribe to server-sent asset move events (file watcher)
|
|
341
282
|
useEffect(() => {
|
|
342
|
-
return connectAssetEvents(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
283
|
+
return connectAssetEvents(
|
|
284
|
+
(event) => {
|
|
285
|
+
store.applyAssetMove(event.oldPath, event.newPath);
|
|
286
|
+
window.dispatchEvent(new CustomEvent('editor:assets-changed'));
|
|
287
|
+
},
|
|
288
|
+
() => window.dispatchEvent(new CustomEvent('editor:assets-changed')),
|
|
289
|
+
);
|
|
346
290
|
}, [store]);
|
|
347
291
|
|
|
348
292
|
// Subscribe to server-sent scene file changes (live sync from disk). This channel
|
|
@@ -358,15 +302,41 @@ export function DefaultEditorLayout({
|
|
|
358
302
|
// ITS `applyExternal` would feed a foreign `SceneFile` into e.g. an ingest
|
|
359
303
|
// overlay's apply, so fall back to `store.applyExternalUpdate` directly there,
|
|
360
304
|
// preserving its existing play-state-guarded queueing behavior unchanged.
|
|
305
|
+
//
|
|
306
|
+
// run-3 friction #1: a hand edit landing while the editor holds UNSAVED
|
|
307
|
+
// first-party changes used to be silently diff-merged into the live scene —
|
|
308
|
+
// a real external edit and the user's own in-flight edits would interleave
|
|
309
|
+
// with no warning. Own-echo (this editor's own autosave reflected back
|
|
310
|
+
// through the watcher) is checked FIRST via `isOwnEchoContent` so a plain
|
|
311
|
+
// echo never triggers the notice; only a GENUINE external change while
|
|
312
|
+
// dirty is held back, with a loud (never blocking — no window.prompt)
|
|
313
|
+
// console notice telling the user how to pick it up. Clean documents keep
|
|
314
|
+
// applying automatically, same as before. Scoped to the non-override path
|
|
315
|
+
// only — ingest/world2d/UI overrides have their own dirty/reload contracts.
|
|
361
316
|
const onSceneChanged = useCallback(
|
|
362
317
|
(event: { path: string; content: string }) => {
|
|
363
318
|
const currentPath = store.savePath;
|
|
364
|
-
|
|
365
|
-
const
|
|
366
|
-
|
|
319
|
+
const hasOverride = hasAuthoringOverride();
|
|
320
|
+
const action = decideExternalSceneChangeAction({
|
|
321
|
+
currentPath,
|
|
322
|
+
eventPath: event.path,
|
|
323
|
+
isDirty: store.isDirty,
|
|
324
|
+
isOwnEcho: store.isOwnEchoContent(event.content),
|
|
325
|
+
hasOverride,
|
|
326
|
+
});
|
|
327
|
+
if (action === 'skip') return;
|
|
328
|
+
if (action === 'notice') {
|
|
329
|
+
editorConsole.warn(
|
|
330
|
+
`${currentPath} changed on disk while you have unsaved changes — ` +
|
|
331
|
+
'it will NOT auto-reload over unsaved work. Save (Ctrl/Cmd+S) or ' +
|
|
332
|
+
'discard your edits to pick up the external change.',
|
|
333
|
+
'scene',
|
|
334
|
+
);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
367
337
|
try {
|
|
368
338
|
const doc = parseSceneFile(JSON.parse(event.content));
|
|
369
|
-
if (
|
|
339
|
+
if (hasOverride) {
|
|
370
340
|
store.applyExternalUpdate(doc, event.content);
|
|
371
341
|
} else {
|
|
372
342
|
getActiveAuthoring(store).persistence?.applyExternal?.(doc, event.content);
|
|
@@ -399,6 +369,9 @@ export function DefaultEditorLayout({
|
|
|
399
369
|
return (
|
|
400
370
|
<>
|
|
401
371
|
<div
|
|
372
|
+
className="vgai-editor-shell"
|
|
373
|
+
data-editor-hotkey-scope="workspace"
|
|
374
|
+
data-editor-hotkey-fallback
|
|
402
375
|
style={{
|
|
403
376
|
position: 'absolute',
|
|
404
377
|
top: 0,
|
|
@@ -408,9 +381,9 @@ export function DefaultEditorLayout({
|
|
|
408
381
|
display: 'flex',
|
|
409
382
|
flexDirection: 'column',
|
|
410
383
|
pointerEvents: 'none',
|
|
411
|
-
fontFamily:
|
|
384
|
+
fontFamily: themeVars.typography.sans,
|
|
412
385
|
fontSize: '13px',
|
|
413
|
-
color:
|
|
386
|
+
color: themeVars.content.primary,
|
|
414
387
|
}}
|
|
415
388
|
>
|
|
416
389
|
<ProjectHeader onReturnToProjectScreen={onReturnToProjectScreen} />
|
|
@@ -429,56 +402,7 @@ export function DefaultEditorLayout({
|
|
|
429
402
|
minHeight: 0,
|
|
430
403
|
}}
|
|
431
404
|
>
|
|
432
|
-
{
|
|
433
|
-
(bare single-scene edit, ingested game, multi-world composite):
|
|
434
|
-
`hasAuthoringOverride()` no longer selects between two panels. */}
|
|
435
|
-
<GameHierarchy />
|
|
436
|
-
{/* E1.a (spec-27 §7 E1) — the scene-UI palette (+ prefab
|
|
437
|
-
instantiate list), visible only while a scene-UI child is
|
|
438
|
-
installed (renders null otherwise — the component's own gate). */}
|
|
439
|
-
<SceneUIPalettePanel />
|
|
440
|
-
{/* Viewport + Game area — two independent panels, tab-switched */}
|
|
441
|
-
<div
|
|
442
|
-
style={{
|
|
443
|
-
flex: 1,
|
|
444
|
-
display: 'flex',
|
|
445
|
-
flexDirection: 'column',
|
|
446
|
-
position: 'relative',
|
|
447
|
-
pointerEvents: 'none',
|
|
448
|
-
}}
|
|
449
|
-
>
|
|
450
|
-
<ViewportTabBar
|
|
451
|
-
active={store.activeViewportTab}
|
|
452
|
-
onChange={(tab) => store.setActiveViewportTab(tab)}
|
|
453
|
-
showGame={isPlaying}
|
|
454
|
-
/>
|
|
455
|
-
{/* Viewport panel (editor) — all overlays are inside ViewportPanel */}
|
|
456
|
-
<div
|
|
457
|
-
style={{
|
|
458
|
-
flex: 1,
|
|
459
|
-
position: 'relative',
|
|
460
|
-
display: store.activeViewportTab === 'scene' ? 'block' : 'none',
|
|
461
|
-
}}
|
|
462
|
-
>
|
|
463
|
-
<ViewportPanel />
|
|
464
|
-
</div>
|
|
465
|
-
{/* Game panel — always mounted, hidden when not playing/active */}
|
|
466
|
-
<GamePanel
|
|
467
|
-
style={{
|
|
468
|
-
flex: 1,
|
|
469
|
-
position: 'relative',
|
|
470
|
-
display: isPlaying && store.activeViewportTab === 'game' ? 'flex' : 'none',
|
|
471
|
-
flexDirection: 'column',
|
|
472
|
-
pointerEvents: 'auto',
|
|
473
|
-
...(isPlaying && store.playState === 'playing'
|
|
474
|
-
? { outline: '2px solid #4ec9b0', outlineOffset: -2 }
|
|
475
|
-
: isPlaying
|
|
476
|
-
? { outline: '2px solid #dcdcaa', outlineOffset: -2 }
|
|
477
|
-
: {}),
|
|
478
|
-
}}
|
|
479
|
-
/>
|
|
480
|
-
</div>
|
|
481
|
-
<RightPanel />
|
|
405
|
+
<WorkspaceDock onOpenScene={handleOpenScene} />
|
|
482
406
|
</div>
|
|
483
407
|
{prefabSaveState && (
|
|
484
408
|
<PrefabSaveDialog
|
|
@@ -487,10 +411,6 @@ export function DefaultEditorLayout({
|
|
|
487
411
|
onCancel={() => setPrefabSaveState(null)}
|
|
488
412
|
/>
|
|
489
413
|
)}
|
|
490
|
-
{/* E1.c (spec-27 §7 E1) — the scene-UI "Save as Prefab" dialog
|
|
491
|
-
(hierarchy context-menu, `ui-prefab-hierarchy-menu.ts`); a
|
|
492
|
-
self-contained host, renders nothing until that menu item fires. */}
|
|
493
|
-
<UIPrefabDialogHost />
|
|
494
414
|
{pendingRootActivation && (
|
|
495
415
|
<RootActivateDialog
|
|
496
416
|
label={pendingRootActivation.label}
|
|
@@ -502,8 +422,24 @@ export function DefaultEditorLayout({
|
|
|
502
422
|
onCancel={() => setPendingRootActivation(null)}
|
|
503
423
|
/>
|
|
504
424
|
)}
|
|
425
|
+
{pendingWorldFocus && (
|
|
426
|
+
<RootActivateDialog
|
|
427
|
+
label={pendingWorldFocus.worldId}
|
|
428
|
+
title="Switch focused world?"
|
|
429
|
+
onConfirm={() => {
|
|
430
|
+
const { worldId, scenePath } = pendingWorldFocus;
|
|
431
|
+
setPendingWorldFocus(null);
|
|
432
|
+
void switchFocusedWorld(store, worldId, scenePath);
|
|
433
|
+
}}
|
|
434
|
+
onCancel={() => setPendingWorldFocus(null)}
|
|
435
|
+
/>
|
|
436
|
+
)}
|
|
437
|
+
{/* Global command surface: this must live at the shell root. Mounting
|
|
438
|
+
it inside the Scene document made Cmd/Ctrl+K invisible whenever
|
|
439
|
+
Game, Story, asset, data, or tool documents were active. */}
|
|
440
|
+
{store.commandPaletteOpen && <CommandPalette onClose={() => store.closeCommandPalette()} />}
|
|
505
441
|
</div>
|
|
506
|
-
{bottomEl && createPortal(<
|
|
442
|
+
{bottomEl && createPortal(<StatusBar />, bottomEl)}
|
|
507
443
|
</>
|
|
508
444
|
);
|
|
509
445
|
}
|