@vgai/editor 0.2.0 → 0.4.0-canary.20260715.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/assets/axe-C7YBtOuM.js +30 -0
- package/dist/assets/browserAll-DDtGGE48.js +1 -0
- package/dist/assets/create-runtime-DbTlBlKG.js +1 -0
- package/dist/assets/{game-BI111o5f.js → game-BE0r7DMI.js} +3 -3
- package/dist/assets/game-BdTHR2_X.js +1 -0
- package/dist/assets/{game-pt_1lQLv.js → game-C3iQGSqo.js} +1 -1
- package/dist/assets/game-CcHfYxjP.js +1 -0
- package/dist/assets/game-Cqzj_lpD.js +1 -0
- package/dist/assets/game-DSZdeCHu.js +1 -0
- package/dist/assets/game-Dch9sAPc.js +1 -0
- package/dist/assets/{game-xsOho_wg.js → game-SAFn90pA.js} +3 -3
- package/dist/assets/game-loop-DMIgSMV-.js +1 -0
- package/dist/assets/{game-source-CvidN7AB.js → game-source-Dk83w26t.js} +1 -1
- package/dist/assets/{index-Bp5cecD6.js → index-4idIsHHJ.js} +2 -2
- package/dist/assets/{index-DL7RcQ0n.js → index-C-LhOTBN.js} +1 -1
- package/dist/assets/{index-Cs8xwv3e.js → index-CDkxceqE.js} +1 -1
- package/dist/assets/index-CQEfi217.js +15412 -0
- package/dist/assets/index-Dvi-V0NE.css +1 -0
- package/dist/assets/ingest-siblings-s0P5I1Ub.js +1 -0
- package/dist/assets/mount-manifest-DXMOlF79.js +1 -0
- package/dist/assets/react-18-C9eHn8x1.js +1 -0
- package/dist/assets/webworkerAll-Fn0e-ouF.js +1 -0
- package/dist/assets/world-documents-GM0a9Kv7.js +1 -0
- package/dist/index.html +15 -13
- package/dist/ingest/racing-game/vgai.game.json +5 -4
- package/dist/ingest/simcity/vgai.game.json +5 -4
- package/dist/ingest/tanks/vgai.game.json +5 -4
- package/dist/project-scripts.bundle.js +3917 -0
- package/dist/scenes/untitled.vscn.json +2 -0
- package/dist-server/packaged.mjs +7697 -3435
- package/package.json +31 -4
- package/scripts/probe-reporter.ts +349 -0
- package/scripts/run-probe.ts +2260 -0
- package/server/asset-catalog-audit.ts +268 -0
- package/server/asset-catalog-v2.ts +146 -0
- package/server/asset-library-routes.ts +276 -58
- package/server/canonical-path.ts +1 -1
- package/server/dev.ts +148 -44
- package/server/editor-server.ts +888 -61
- package/server/editor-sse.ts +115 -4
- package/server/harness-chat-service.ts +796 -0
- package/server/local-asset-catalog.ts +157 -22
- package/server/packaged.ts +51 -21
- package/server/process-shutdown.ts +136 -0
- package/server/prod.ts +9 -6
- package/server/project-hmr-files.ts +41 -0
- package/server/project-operations.ts +343 -0
- package/server/project-optimize-deps-entries.ts +4 -4
- package/server/project-output-writer.ts +156 -0
- package/server/project-validation.ts +140 -0
- package/server/project-view.ts +8 -50
- package/server/server-utils.ts +75 -10
- package/server/session-registry.ts +12 -0
- package/src/EditorContext.tsx +107 -3
- package/src/action-registry.ts +115 -17
- package/src/adapter-resolver.ts +213 -478
- package/src/asset-events.ts +64 -1
- package/src/asset-preview.ts +906 -0
- package/src/asset-selection.ts +121 -0
- package/src/asset-workflow/asset-capabilities.ts +259 -0
- package/src/asset-workflow/asset-editor-errors.ts +46 -0
- package/src/asset-workflow/asset-import-pipeline.ts +176 -0
- package/src/asset-workflow/asset-library-query.ts +107 -0
- package/src/asset-workflow/asset-types.ts +192 -0
- package/src/asset-workflow/asset-workflow-quality.ts +65 -0
- package/src/asset-workflow/import-contract.ts +113 -0
- package/src/asset-workflow/model-conversion.ts +126 -0
- package/src/asset-workflow/model-inspection.ts +185 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +153 -0
- package/src/asset-workflow/project-asset-operations.ts +119 -0
- package/src/asset-workflow/thumbnail-system.ts +172 -0
- package/src/authoring/active-systems.ts +15 -0
- package/src/authoring/boundary-authoring-adapter.ts +16 -5
- package/src/authoring/composite-authoring-adapter.ts +305 -124
- package/src/authoring/design-time-layers.ts +300 -117
- package/src/authoring/edit-mode-authoring.ts +278 -293
- package/src/authoring/embed-only-adapter.ts +4 -2
- package/src/authoring/first-party-hierarchy-menu.ts +7 -2
- package/src/authoring/first-party-inspector/AddSectionMenu.tsx +5 -12
- package/src/authoring/first-party-inspector/EnvironmentSection.tsx +53 -126
- package/src/authoring/first-party-inspector/HeaderSection.tsx +54 -65
- package/src/authoring/first-party-inspector/is-first-party-selection.ts +30 -11
- package/src/authoring/first-party-inspector/register.tsx +13 -2
- package/src/authoring/ingest-authoring-adapter.ts +142 -45
- package/src/authoring/mount-failure-report.ts +5 -5
- package/src/authoring/provenance.ts +41 -0
- package/src/authoring/react-dom-authoring-adapter.ts +92 -92
- package/src/authoring/react-inspector-section.tsx +489 -51
- package/src/authoring/react-world-authoring-adapter.ts +541 -306
- package/src/authoring/story-overlay.ts +1 -1
- package/src/authoring/story-types.ts +11 -0
- package/src/authoring/vgai-scene-authoring-adapter.ts +54 -25
- package/src/authoring/viewport-tool-context.ts +78 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +186 -0
- package/src/authoring/world-pan-state.ts +33 -17
- package/src/authoring/world-session-state.ts +1 -1
- package/src/authoring/world2d-authoring-adapter.ts +109 -52
- package/src/availability-tick.ts +56 -0
- package/src/browser-play-entry.ts +5 -5
- package/src/browser-project-scripts.ts +1 -0
- package/src/build-identity.ts +15 -0
- package/src/command-listener.ts +893 -19
- package/src/components/AlignToolbar.tsx +74 -63
- package/src/components/AppRoot.tsx +193 -26
- package/src/components/ApplicationMenus.tsx +272 -0
- package/src/components/AssetBrowser.tsx +1450 -293
- package/src/components/AssetEditorShell.tsx +141 -0
- package/src/components/AssetImportDetails.tsx +218 -0
- package/src/components/AssetLibraryPanel.tsx +14 -0
- package/src/components/CameraInfo.tsx +11 -20
- package/src/components/CenterDocuments.tsx +585 -0
- package/src/components/CommandPalette.tsx +75 -30
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +57 -112
- package/src/components/DebugConsolePanel.tsx +461 -0
- package/src/components/DebuggerPanel.tsx +165 -0
- package/src/components/DefaultEditorLayout.tsx +167 -231
- package/src/components/GameHierarchy.tsx +873 -290
- package/src/components/GamePerformanceOverlay.tsx +46 -0
- package/src/components/HarnessChatPanel.tsx +2352 -0
- package/src/components/HistoryPanel.tsx +226 -0
- package/src/components/Inspector.tsx +153 -99
- package/src/components/InspectorToolSection.tsx +6 -4
- package/src/components/MountFailureBanner.tsx +31 -48
- package/src/components/NetworkSection.tsx +25 -14
- package/src/components/OnlineAssetBrowser.tsx +794 -343
- package/src/components/OverlayReportBanner.tsx +38 -64
- package/src/components/PerformancePanel.tsx +206 -0
- package/src/components/PlayBar.tsx +93 -263
- package/src/components/PrefabSaveDialog.tsx +55 -127
- package/src/components/ProjectHeader.css +60 -0
- package/src/components/ProjectHeader.tsx +170 -105
- package/src/components/ProjectScreen.tsx +246 -184
- package/src/components/ReactCanvasControls.tsx +185 -0
- package/src/components/ResolutionPicker.tsx +85 -0
- package/src/components/RootActivateDialog.tsx +39 -68
- package/src/components/SaveDialog.tsx +55 -127
- package/src/components/SaveStatus.tsx +11 -29
- package/src/components/StartupLoadingScreen.tsx +96 -0
- package/src/components/StateWatchPanel.tsx +302 -0
- package/src/components/StatsOverlay.tsx +12 -5
- package/src/components/StatusBar.tsx +64 -0
- package/src/components/ThemeManagerDialog.css +89 -0
- package/src/components/ThemeManagerDialog.tsx +371 -0
- package/src/components/ToolHost.tsx +26 -15
- package/src/components/Toolbar.tsx +117 -214
- package/src/components/VgaiVoxelLogo.tsx +89 -0
- package/src/components/ViewportOverlay.tsx +97 -172
- package/src/components/ViewportPanel.tsx +130 -31
- package/src/components/WorkspaceDock.tsx +891 -0
- package/src/components/WorldSelectionOverlay.tsx +51 -63
- package/src/components/WorldTextEditor.tsx +9 -5
- package/src/components/asset-documents.tsx +390 -0
- package/src/components/asset-editor-persistence.ts +44 -0
- package/src/components/asset-selection-section.tsx +338 -0
- package/src/components/asset-viewers/AudioViewer.tsx +73 -21
- package/src/components/asset-viewers/GenericJsonViewer.tsx +26 -11
- package/src/components/asset-viewers/ImageViewer.tsx +43 -11
- package/src/components/asset-viewers/InputMapViewer.tsx +512 -134
- package/src/components/asset-viewers/MaterialAssetEditor.tsx +540 -0
- package/src/components/asset-viewers/ModelViewer.tsx +805 -121
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +177 -60
- package/src/components/asset-viewers/SourceAssetViewer.tsx +121 -0
- package/src/components/asset-workflow.css +506 -0
- package/src/components/build-documents.tsx +696 -0
- package/src/components/core-utilities.tsx +75 -0
- package/src/components/data-documents.tsx +364 -0
- package/src/components/{DataPanel.tsx → data-editor.tsx} +138 -288
- package/src/components/debugger-panel-state.ts +57 -0
- package/src/components/inspector-widgets/AlignmentGrid.tsx +8 -14
- package/src/components/inspector-widgets/BorderEditor.tsx +41 -33
- package/src/components/inspector-widgets/ColorPicker.tsx +39 -39
- package/src/components/inspector-widgets/FontPicker.tsx +13 -21
- package/src/components/inspector-widgets/GradientEditor.tsx +11 -19
- package/src/components/inspector-widgets/ScrubbableInput.tsx +6 -3
- package/src/components/inspector-widgets/ShadowEditor.tsx +20 -33
- package/src/components/inspector-widgets/shared.tsx +90 -49
- package/src/components/inspectors/AnimationSection.tsx +39 -40
- package/src/components/inspectors/AudioSection.tsx +28 -39
- package/src/components/inspectors/BoneAttachmentSection.tsx +19 -24
- package/src/components/inspectors/CameraSection.tsx +14 -23
- package/src/components/inspectors/ComponentsSection.tsx +39 -43
- package/src/components/inspectors/JointsSection.tsx +34 -43
- package/src/components/inspectors/LightSection.tsx +90 -35
- package/src/components/inspectors/MaterialSection.tsx +137 -174
- package/src/components/inspectors/MeshSection.tsx +9 -17
- package/src/components/inspectors/NavigationSection.tsx +8 -15
- package/src/components/inspectors/ParticleSection.tsx +91 -76
- package/src/components/inspectors/PhysicsSection.tsx +42 -46
- package/src/components/inspectors/PostProcessingSection.tsx +28 -36
- package/src/components/inspectors/RenderingSection.tsx +12 -20
- package/src/components/inspectors/ShadowSection.tsx +7 -8
- package/src/components/inspectors/SplineSection.tsx +31 -42
- package/src/components/inspectors/TransformSection.tsx +14 -22
- package/src/components/patterns/Dialog.tsx +95 -0
- package/src/components/patterns/Fields.tsx +44 -0
- package/src/components/patterns/List.tsx +25 -0
- package/src/components/patterns/StateSurface.tsx +40 -0
- package/src/components/patterns/Surfaces.tsx +115 -0
- package/src/components/patterns/Tabs.tsx +80 -0
- package/src/components/patterns/Toolbar.tsx +51 -0
- package/src/components/patterns/Tree.tsx +72 -0
- package/src/components/primitives/Button.tsx +46 -0
- package/src/components/primitives/ColorInput.tsx +11 -47
- package/src/components/primitives/EditorIcon.tsx +99 -0
- package/src/components/primitives/FormControls.tsx +71 -0
- package/src/components/primitives/JsonInput.tsx +15 -2
- package/src/components/primitives/Layout.tsx +100 -0
- package/src/components/primitives/Menu.tsx +105 -0
- package/src/components/primitives/NumberInput.tsx +8 -35
- package/src/components/primitives/Panel.tsx +49 -44
- package/src/components/primitives/SectionHeader.tsx +10 -28
- package/src/components/primitives/Text.tsx +46 -0
- package/src/components/primitives/Tooltip.tsx +20 -12
- package/src/components/primitives/Vec3Input.tsx +3 -0
- package/src/components/primitives/banner-tones.ts +33 -0
- package/src/components/primitives/editor-icons.ts +102 -0
- package/src/components/primitives/panel-header-styles.ts +30 -0
- package/src/components/project-operation-documents.tsx +226 -0
- package/src/components/status-contributions.tsx +175 -0
- package/src/components/story-documents-register.ts +15 -0
- package/src/components/story-documents.tsx +1185 -0
- package/src/components/tool-documents.tsx +110 -0
- package/src/components/workspace-dock.css +293 -0
- package/src/components/workspace-history.ts +33 -0
- package/src/components/world-documents.tsx +145 -0
- package/src/components/xstate-documents.tsx +209 -0
- package/src/composite-screenshot.ts +248 -0
- package/src/design-system/index.ts +70 -0
- package/src/design-system-stories/Foundation.stories.tsx +183 -0
- package/src/design-system-stories/Patterns.stories.tsx +251 -0
- package/src/design-system-stories/Workspace.stories.tsx +538 -0
- package/src/doctor/report.ts +57 -13
- package/src/editor-api.ts +295 -31
- package/src/editor-compatibility.ts +200 -0
- package/src/editor-console.ts +35 -17
- package/src/editor-hotkeys.ts +85 -33
- package/src/editor-store.ts +538 -233
- package/src/editor-viewport.ts +160 -34
- package/src/entity-factory.ts +14 -3
- package/src/gizmo-registry.ts +21 -5
- package/src/harness-chat-editor-context.ts +37 -0
- package/src/harness-chat-indicator.ts +68 -0
- package/src/harness-chat-layout.ts +53 -0
- package/src/harness-chat-lifecycle.ts +170 -0
- package/src/harness-chat-reconnect.ts +85 -0
- package/src/harness-chat-types.ts +409 -0
- package/src/hierarchy-drop.ts +50 -0
- package/src/hierarchy-expansion-state.ts +100 -0
- package/src/hierarchy-menu-registry.ts +1 -1
- package/src/hierarchy-projection.ts +76 -0
- package/src/history/editor-session.ts +21 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-service.ts +904 -0
- package/src/history/json-history-resource.ts +165 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +266 -0
- package/src/history/project-root-history-backends.ts +53 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +108 -0
- package/src/history/source-history-backend.ts +374 -0
- package/src/history/types.ts +100 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hosted-example.ts +12 -2
- package/src/hotkeys.ts +89 -18
- package/src/ingest/discovery-react.ts +9 -10
- package/src/ingest/discovery.ts +4 -4
- package/src/ingest/discovery2d.ts +5 -5
- package/src/ingest/games/bloom-composer/vgai.game.json +3 -3
- package/src/ingest/games/embed-bundle/vgai.game.json +3 -3
- package/src/ingest/games/games-fps/vgai.game.json +3 -3
- package/src/ingest/games/iframe-reachable/vgai.game.json +3 -3
- package/src/ingest/games/interactive-cubes/vgai.game.json +3 -3
- package/src/ingest/games/mismatched-three/vgai.game.json +3 -3
- package/src/ingest/games/own-three-bundled/vgai.game.json +3 -3
- package/src/ingest/games/pointerlock-maze/vgai.game.json +7 -4
- package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +3 -3
- package/src/ingest/games-2d/bunnymark/vgai.game.json +3 -3
- package/src/ingest/games-2d/flappy/vgai.game.json +3 -3
- package/src/ingest/games-2d/flappy-pixi/vgai.game.json +3 -3
- package/src/ingest/games-2d/puzzling-potions/vgai.game.json +3 -3
- package/src/ingest/games-2d/tilemap-camera/vgai.game.json +3 -3
- package/src/ingest/games-react/react-rpg/vgai.game.json +3 -3
- package/src/ingest/types.ts +1 -1
- package/src/ingest-mode.ts +47 -52
- package/src/ingest-siblings.ts +23 -33
- package/src/initial-scene.ts +1 -2
- package/src/main.tsx +16 -8
- package/src/manifest-project.ts +10 -12
- package/src/model-thumbnail.ts +261 -26
- package/src/module-mode.ts +44 -50
- package/src/play-log-events.ts +26 -0
- package/src/play-mode.ts +495 -401
- package/src/play-scene-adoption.ts +23 -0
- package/src/playground/main.ts +68 -24
- package/src/playwright-shim.ts +473 -0
- package/src/project-manager.ts +90 -10
- package/src/project-operations.ts +112 -0
- package/src/project-story-discovery.ts +25 -0
- package/src/project-tool-discovery.ts +43 -0
- package/src/scene-serializer.ts +0 -6
- package/src/scene-sync.ts +7 -2
- package/src/script-loader.ts +3 -3
- package/src/skeleton-helper.ts +57 -0
- package/src/storage/seed.ts +68 -8
- package/src/stories/StoryPreviewMount.tsx +265 -0
- package/src/stories/action-stories.fixture.tsx +44 -0
- package/src/stories/button-stories.fixture.tsx +50 -0
- package/src/stories/compose-project-stories.ts +182 -0
- package/src/stories/loader-stories.fixture.tsx +53 -0
- package/src/stories/story-discovery.ts +130 -0
- package/src/stories/story-registry.ts +146 -0
- package/src/theme-css.ts +1049 -0
- package/src/theme-library.ts +238 -0
- package/src/theme-preference.ts +130 -0
- package/src/theme.ts +527 -0
- package/src/tool-loader.ts +80 -24
- package/src/ui-source/inspect.ts +27 -4
- package/src/ui-source/source-write-backend.ts +83 -22
- package/src/widgets/index.ts +9 -18
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-dock-controller.ts +64 -0
- package/src/workspace-document-ids.ts +5 -0
- package/src/workspace-document-registry.ts +367 -0
- package/src/workspace-state-persistence.ts +455 -0
- package/src/workspace-status-registry.ts +110 -0
- package/src/workspace-utility-commands.ts +49 -0
- package/src/workspace-utility-registry.ts +161 -0
- package/src/world-document-routing.ts +16 -0
- package/src/xstate-inspect/XStateMachineInspector.tsx +544 -0
- package/src/xstate-inspect/character-animation-machine.fixture.ts +74 -0
- package/src/xstate-inspect/use-live-actor-state.ts +39 -0
- package/src/xstate-inspect/xstate-graph.ts +265 -0
- package/src/xstate-inspect/xstate-layout.ts +76 -0
- package/src/z-index.ts +26 -0
- package/template/.claude/skills/editor/SKILL.md +129 -90
- package/template/AGENTS.md +1110 -0
- package/template/CLAUDE.md +1 -512
- package/template/IDIOMS.md +50 -0
- package/template/check-idioms.ts +706 -0
- package/template/manifest-entry-modules-plugin.ts +53 -0
- package/template/package.json +13 -4
- package/template/public/scenes/default.scn2d.json +6 -0
- package/template/public/scenes/default.vscn.json +7 -1
- package/template/public/scenes/untitled.vscn.json +10 -0
- package/template/scripts/playtest.ts +40 -0
- package/template/server/loopback.ts +75 -0
- package/template/server/rooms/arena-room.ts +69 -1
- package/template/server/rooms/game-room.ts +68 -1
- package/template/src/data/README.md +9 -4
- package/template/src/data/data-ref.ts +35 -0
- package/template/src/data/tuning.schema.ts +1 -1
- package/template/src/main.ts +41 -62
- package/template/src/manifest-entry-modules.d.ts +3 -0
- package/template/src/operations/README.md +88 -0
- package/template/src/runtime/pixi-adapter.ts +24 -0
- package/template/src/scripts/components/data-spinner.ts +43 -2
- package/template/src/scripts/components/spin-lap-math.ts +27 -0
- package/template/src/tools/README.md +5 -3
- package/template/src/tools/example.tool.tsx +13 -7
- package/template/src/ui/Button.stories.tsx +66 -0
- package/template/src/ui/RebindPanel.tsx +2 -6
- package/template/src/ui/game.tsx +17 -0
- package/template/tests/acceptance/example.spec.ts +64 -0
- package/template/tests/logic/example.test.ts +31 -0
- package/template/tests/logic/room.test.ts +100 -0
- package/template/tests/tsconfig.json +30 -0
- package/template/validate-manifest.ts +5 -5
- package/template/validate-scenes.ts +50 -18
- package/template/vgai.game.json +20 -13
- package/template/vite.config.ts +77 -16
- package/vite-plugin-ui-oid.ts +261 -17
- package/dist/assets/CCDIKSolver-Dz-ysxZF.js +0 -1
- package/dist/assets/SelectionBox-BXsv_6aH.js +0 -1
- package/dist/assets/browser-project-scripts-DOru4L1x.js +0 -2
- package/dist/assets/browserAll-CEkWYlFk.js +0 -1
- package/dist/assets/create-runtime-DYIWr3va.js +0 -1
- package/dist/assets/data-asset-Bb9sIM7i.js +0 -5
- package/dist/assets/game-8SDZPPgH.js +0 -1
- package/dist/assets/game-CevorxyV.js +0 -1
- package/dist/assets/game-Di7XlywD.js +0 -1
- package/dist/assets/game-DjnCaw8R.js +0 -1
- package/dist/assets/game-Q9A0aXSV.js +0 -1
- package/dist/assets/index-CPVV6pjw.js +0 -1
- package/dist/assets/index-CpOnYyeD.js +0 -213
- package/dist/assets/index-Dr8H_6Rl.js +0 -1
- package/dist/assets/index-_bCaipUk.js +0 -13650
- package/dist/assets/ingest-siblings-Dz8eEqrV.js +0 -1
- package/dist/assets/mount-manifest-Bhk0ohsl.js +0 -1
- package/dist/assets/scene-query-BivAHhJu.js +0 -1
- package/dist/assets/webworkerAll-BLrH0F6F.js +0 -1
- package/dist/assets/xstate-animation-binding-1NGLmw6y.js +0 -1
- package/dist/assets/xstate.esm-BgUD33nl.js +0 -3
- package/src/authoring/scene-ui-layer.ts +0 -485
- package/src/authoring/ui-authoring-adapter.ts +0 -325
- package/src/authoring/ui-hierarchy-menu.ts +0 -40
- package/src/authoring/ui-inspector-sections.tsx +0 -156
- package/src/authoring/undo-timeline.ts +0 -145
- package/src/components/BottomPanel.tsx +0 -326
- package/src/components/BuildPanel.tsx +0 -455
- package/src/components/FolderTree.tsx +0 -179
- package/src/components/RightPanel.tsx +0 -166
- package/src/components/WorldContextMenu.tsx +0 -257
- package/src/components/asset-viewers/AssetViewer.tsx +0 -38
- package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +0 -129
- package/src/scene-ui-mode/active-scene-ui.ts +0 -58
- package/src/scene-ui-mode/scene-ui-palette-panel.tsx +0 -152
- package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +0 -29
- package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +0 -74
- package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +0 -49
- package/src/scene-ui-mode/ui-prefab-io.ts +0 -76
- package/src/ui-editor/inspector.tsx +0 -563
- package/src/ui-editor/node-ops.ts +0 -266
- package/src/ui-editor/overlay.tsx +0 -380
- package/src/ui-editor/palette.tsx +0 -114
- package/src/ui-editor/react-store.ts +0 -78
- package/src/ui-editor/timeline-panel.tsx +0 -443
- package/src/ui-editor/ui-edit-store.ts +0 -552
- package/src/ui-editor/ui-prefab.ts +0 -95
- package/template/project.json +0 -9
- package/template/src/scripts/main.ts +0 -94
- package/template/src/ui/DefaultHud.tsx +0 -40
- package/template/src/ui/game-state.tsx +0 -37
- package/template/src/ui/mount-default-hud.tsx +0 -19
- package/template/src/ui/mount-ui.ts +0 -15
- package/vite-plugin-react-world-provider.ts +0 -81
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { themeVars } from '../design-system';
|
|
2
|
+
/**
|
|
3
|
+
* Project-tool DOCUMENTS (W3, docs/EDITOR-WORKSPACE-SHELL-TODO.md §7.2/§9 W3
|
|
4
|
+
* — inventory rows B12/T2-behavior/T3): a `placement: 'document'` project
|
|
5
|
+
* tool (including every legacy `'dock'` tool — the W0 alias rule,
|
|
6
|
+
* docs/workspace-shell/W0-INVENTORY.md §2) opens as a CENTER workspace
|
|
7
|
+
* document (kind `'tool'`, title = the tool's own declared title per §8),
|
|
8
|
+
* hosted in the same error-boundaried `ToolHost` the bottom ⚙ tabs used.
|
|
9
|
+
* `placement: 'utility'` tools stay in the bottom area — registered in the
|
|
10
|
+
* workspace-utility registry by the tool-loader itself (see
|
|
11
|
+
* `tool-loader.ts`'s publish step). The ⚙ dock-tab row is gone.
|
|
12
|
+
*
|
|
13
|
+
* Open gesture: one `Open Tool: <title>` command-palette action per
|
|
14
|
+
* discovered document tool (`buildToolActions`) — the fixed-layout menu the
|
|
15
|
+
* ⚙ row used to be, now a searchable command. The template's `Tuning`
|
|
16
|
+
* example tool is the live proof.
|
|
17
|
+
*
|
|
18
|
+
* HMR/lifecycle: the document's CONTENT reads the LIVE tool store — an HMR
|
|
19
|
+
* reload bumps the tool's `version`, which re-keys the mount (fresh
|
|
20
|
+
* component + cleared error boundary, the same physics the dock tabs had);
|
|
21
|
+
* a deleted tool file leaves an honest "no longer available" message in any
|
|
22
|
+
* open document (discovery is the folder scan, D3).
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { useSyncExternalStore } from 'react';
|
|
26
|
+
import type { EditorAction } from '../action-registry';
|
|
27
|
+
import { getDocumentTools, getGlobalTools, subscribeGlobalTools } from '../tool-loader';
|
|
28
|
+
import {
|
|
29
|
+
openWorkspaceDocument,
|
|
30
|
+
type WorkspaceDocumentContentProps,
|
|
31
|
+
} from '../workspace-document-registry';
|
|
32
|
+
import { ToolHost } from './ToolHost';
|
|
33
|
+
|
|
34
|
+
/** The narrow store surface tool documents need (T6.3 tab hand-off). */
|
|
35
|
+
export interface ToolDocumentStore {
|
|
36
|
+
setActiveViewportTab(tab: 'scene' | 'game'): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Stable §7.1 identity for one project tool's document. */
|
|
40
|
+
export function toolDocumentId(toolId: string): string {
|
|
41
|
+
return `tool:${toolId}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Open (or activate) the center document for one document-placement project
|
|
46
|
+
* tool. Returns `false` (opens nothing) when no discovered document tool
|
|
47
|
+
* carries that id — no fabricated documents for deleted/renamed tools.
|
|
48
|
+
*/
|
|
49
|
+
export function openToolDocument(store: ToolDocumentStore, toolId: string): boolean {
|
|
50
|
+
const tool = getDocumentTools().find((t) => t.id === toolId);
|
|
51
|
+
if (!tool) return false;
|
|
52
|
+
openWorkspaceDocument({
|
|
53
|
+
id: toolDocumentId(toolId),
|
|
54
|
+
// §8: the tool's own declared title (`Tuning`), never a tech bucket.
|
|
55
|
+
title: tool.title,
|
|
56
|
+
kind: 'tool',
|
|
57
|
+
provenance: { sourcePath: tool.file },
|
|
58
|
+
Content: ToolDocumentContent,
|
|
59
|
+
closeable: true,
|
|
60
|
+
onActivate: () => store.setActiveViewportTab('scene'),
|
|
61
|
+
});
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** `Open Tool: <title>` palette actions — one per discovered document tool
|
|
66
|
+
* (the B12 discovery gesture). */
|
|
67
|
+
export function buildToolActions(store: ToolDocumentStore): EditorAction[] {
|
|
68
|
+
return getDocumentTools().map((t) => ({
|
|
69
|
+
id: `tool-doc:${t.id}`,
|
|
70
|
+
label: `Open Tool: ${t.title}`,
|
|
71
|
+
category: 'action' as const,
|
|
72
|
+
execute: () => void openToolDocument(store, t.id),
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Content host: resolves the LIVE tool by id on every render (HMR re-key,
|
|
77
|
+
* honest deleted-tool state). */
|
|
78
|
+
export function ToolDocumentContent({ documentId }: WorkspaceDocumentContentProps) {
|
|
79
|
+
useSyncExternalStore(subscribeGlobalTools, getGlobalTools);
|
|
80
|
+
const toolId = documentId.startsWith('tool:') ? documentId.slice('tool:'.length) : documentId;
|
|
81
|
+
const tool = getDocumentTools().find((t) => t.id === toolId);
|
|
82
|
+
if (!tool) {
|
|
83
|
+
return (
|
|
84
|
+
<div
|
|
85
|
+
style={{ padding: 12, fontSize: 12, color: themeVars.content.muted, pointerEvents: 'auto' }}
|
|
86
|
+
>
|
|
87
|
+
This tool is no longer available (its `src/tools/` file was deleted or renamed) — close this
|
|
88
|
+
document.
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return (
|
|
93
|
+
<div
|
|
94
|
+
key={`${tool.id}:${tool.version}`}
|
|
95
|
+
data-testid={`tool-document:${tool.id}`}
|
|
96
|
+
style={{
|
|
97
|
+
flex: 1,
|
|
98
|
+
minHeight: 0,
|
|
99
|
+
display: 'flex',
|
|
100
|
+
flexDirection: 'column',
|
|
101
|
+
pointerEvents: 'auto',
|
|
102
|
+
// B-11: the editor-provided baseline breathing room every hosted
|
|
103
|
+
// surface's content root has by convention (carried from the dock).
|
|
104
|
+
padding: 12,
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
<ToolHost tool={tool} />
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
.dockview-theme-vgai {
|
|
2
|
+
--dv-group-view-background-color: var(--vgai-bg-1);
|
|
3
|
+
--dv-tabs-and-actions-container-background-color: var(--vgai-bg-2);
|
|
4
|
+
--dv-activegroup-visiblepanel-tab-background-color: transparent;
|
|
5
|
+
--dv-activegroup-hiddenpanel-tab-background-color: transparent;
|
|
6
|
+
--dv-inactivegroup-visiblepanel-tab-background-color: transparent;
|
|
7
|
+
--dv-inactivegroup-hiddenpanel-tab-background-color: transparent;
|
|
8
|
+
--dv-activegroup-visiblepanel-tab-color: var(--vgai-text-1);
|
|
9
|
+
--dv-activegroup-hiddenpanel-tab-color: var(--vgai-text-2);
|
|
10
|
+
--dv-inactivegroup-visiblepanel-tab-color: var(--vgai-text-2);
|
|
11
|
+
--dv-inactivegroup-hiddenpanel-tab-color: var(--vgai-text-3);
|
|
12
|
+
--dv-tab-divider-color: var(--vgai-border-1);
|
|
13
|
+
/* The sash paints the separator so the 1px line is centered inside its
|
|
14
|
+
larger 4px hit target instead of sitting on one panel edge. */
|
|
15
|
+
--dv-separator-border: transparent;
|
|
16
|
+
--dv-paneview-header-border-color: var(--vgai-border-1);
|
|
17
|
+
--dv-paneview-active-outline-color: var(--vgai-accent);
|
|
18
|
+
--dv-tabs-and-actions-container-height: var(--vgai-panel-header-height);
|
|
19
|
+
--dv-tabs-and-actions-container-font-size: var(--vgai-font-md);
|
|
20
|
+
--dv-tab-font-size: var(--vgai-font-md);
|
|
21
|
+
--dv-icon-hover-background-color: var(--vgai-bg-3);
|
|
22
|
+
--dv-drag-over-background-color: var(--vgai-accent-muted);
|
|
23
|
+
--dv-drag-over-border-color: var(--vgai-accent);
|
|
24
|
+
--dv-sash-color: transparent;
|
|
25
|
+
--dv-active-sash-color: transparent;
|
|
26
|
+
--dv-active-sash-transition-delay: 0s;
|
|
27
|
+
--dv-active-sash-transition-duration: 0.1s;
|
|
28
|
+
--dv-floating-border: var(--vgai-stroke-resting) solid var(--vgai-border-2);
|
|
29
|
+
--dv-floating-box-shadow: var(--vgai-shadow-lg);
|
|
30
|
+
--dv-floating-titlebar-height: 20px;
|
|
31
|
+
--dv-border-radius: 0;
|
|
32
|
+
--dv-tab-border-radius: 0;
|
|
33
|
+
--dv-tab-margin: 0;
|
|
34
|
+
--dv-spacing-padding: 0;
|
|
35
|
+
--dv-scrollbar-background-color: color-mix(in srgb, var(--vgai-content-primary) 28%, transparent);
|
|
36
|
+
font-family: var(--vgai-font-sans);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.vgai-workspace-dock {
|
|
40
|
+
position: relative;
|
|
41
|
+
flex: 1;
|
|
42
|
+
min-width: 0;
|
|
43
|
+
min-height: 0;
|
|
44
|
+
pointer-events: auto;
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
background: var(--vgai-bg-1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.vgai-workspace-dock > .dockview-theme-vgai {
|
|
50
|
+
width: 100%;
|
|
51
|
+
height: 100%;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.vgai-dock-panel,
|
|
55
|
+
.vgai-dock-document,
|
|
56
|
+
.vgai-dock-document-content {
|
|
57
|
+
min-width: 0;
|
|
58
|
+
min-height: 0;
|
|
59
|
+
width: 100%;
|
|
60
|
+
height: 100%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.vgai-dock-panel,
|
|
64
|
+
.vgai-dock-document,
|
|
65
|
+
.vgai-dock-document-content {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
background: var(--vgai-bg-1);
|
|
70
|
+
pointer-events: auto;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.vgai-dock-document-toolbar {
|
|
74
|
+
flex: 0 0 auto;
|
|
75
|
+
min-height: var(--vgai-local-toolbar-height);
|
|
76
|
+
border-bottom: var(--vgai-stroke-resting) solid var(--vgai-border-1);
|
|
77
|
+
background: var(--vgai-bg-1);
|
|
78
|
+
pointer-events: auto;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.vgai-dock-empty {
|
|
82
|
+
padding: var(--vgai-space-6);
|
|
83
|
+
color: var(--vgai-text-3);
|
|
84
|
+
background: var(--vgai-bg-1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.vgai-dock-tab {
|
|
88
|
+
display: flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
height: 100%;
|
|
91
|
+
min-width: 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.vgai-dock-tab > .dv-default-tab {
|
|
95
|
+
min-width: 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Runtime/world surfaces and file-backed resource documents are different
|
|
99
|
+
navigation families. The adjacent-family selector makes the seam follow
|
|
100
|
+
the actual Dockview rail when the user moves tabs. */
|
|
101
|
+
.dockview-theme-vgai .dv-tab:has(.vgai-dock-tab[data-document-family="world"])
|
|
102
|
+
+ .dv-tab:has(.vgai-dock-tab[data-document-family="resource"])
|
|
103
|
+
.vgai-dock-tab {
|
|
104
|
+
position: relative;
|
|
105
|
+
margin-left: var(--vgai-space-4);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.dockview-theme-vgai
|
|
109
|
+
.dv-tab:has(.vgai-dock-tab[data-document-family="world"])
|
|
110
|
+
+ .dv-tab:has(.vgai-dock-tab[data-document-family="resource"])
|
|
111
|
+
.vgai-dock-tab::before {
|
|
112
|
+
position: absolute;
|
|
113
|
+
top: 50%;
|
|
114
|
+
left: calc(-1 * var(--vgai-space-3));
|
|
115
|
+
width: var(--vgai-stroke-resting);
|
|
116
|
+
height: 16px;
|
|
117
|
+
background: var(--vgai-border-2);
|
|
118
|
+
content: "";
|
|
119
|
+
transform: translateY(-50%);
|
|
120
|
+
pointer-events: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.dockview-theme-vgai .dv-tab {
|
|
124
|
+
padding: 0 10px;
|
|
125
|
+
border-radius: 0;
|
|
126
|
+
font-weight: 400;
|
|
127
|
+
transition:
|
|
128
|
+
background-color 80ms ease,
|
|
129
|
+
color 80ms ease;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.dockview-theme-vgai .dv-tabs-and-actions-container {
|
|
133
|
+
border-bottom: var(--vgai-stroke-resting) solid var(--vgai-border-1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.dockview-theme-vgai .dv-tab.dv-inactive-tab:hover {
|
|
137
|
+
color: var(--vgai-text-1);
|
|
138
|
+
background: var(--vgai-bg-3);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.dockview-theme-vgai .dv-tabs-and-actions-container:not(.dv-single-tab) .dv-tabs-container {
|
|
142
|
+
gap: 2px;
|
|
143
|
+
padding: 0 3px;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Dockview's default separators make the rail resemble stock library tabs.
|
|
147
|
+
The editor uses whitespace and one active marker instead. */
|
|
148
|
+
.dockview-theme-vgai .dv-tabs-container.dv-horizontal .dv-tab:not(:first-child)::before {
|
|
149
|
+
display: none;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Dockview intentionally removes all padding in full-width single-tab mode.
|
|
153
|
+
Keep the full-width hit target, but restore the label inset and make the
|
|
154
|
+
result read as a panel heading rather than one enormous selected tab. */
|
|
155
|
+
.dockview-theme-vgai .dv-tabs-and-actions-container.dv-single-tab.dv-full-width-single-tab
|
|
156
|
+
.dv-tabs-container
|
|
157
|
+
.dv-tab {
|
|
158
|
+
margin: 0;
|
|
159
|
+
padding: 0 12px;
|
|
160
|
+
border-radius: 0;
|
|
161
|
+
font-weight: 600;
|
|
162
|
+
letter-spacing: 0.01em;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.vgai-dock-tab-dirty {
|
|
166
|
+
width: 6px;
|
|
167
|
+
height: 6px;
|
|
168
|
+
margin-right: 6px;
|
|
169
|
+
flex: 0 0 auto;
|
|
170
|
+
border-radius: 50%;
|
|
171
|
+
background: var(--vgai-warn);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.vgai-dock-tab-unsaved {
|
|
175
|
+
gap: 4px;
|
|
176
|
+
padding: 0 5px 0 8px;
|
|
177
|
+
color: var(--vgai-text-1);
|
|
178
|
+
background: var(--vgai-warn-muted);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.vgai-dock-tab-unsaved-label {
|
|
182
|
+
margin-right: 2px;
|
|
183
|
+
color: var(--vgai-warn);
|
|
184
|
+
font-weight: 600;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.vgai-dock-tab-unsaved button {
|
|
188
|
+
height: 20px;
|
|
189
|
+
padding: 0 5px;
|
|
190
|
+
border: var(--vgai-stroke-resting) solid var(--vgai-border-2);
|
|
191
|
+
border-radius: 3px;
|
|
192
|
+
color: var(--vgai-text-1);
|
|
193
|
+
background: var(--vgai-bg-2);
|
|
194
|
+
font: inherit;
|
|
195
|
+
cursor: pointer;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.vgai-dock-tab-unsaved button:hover:not(:disabled),
|
|
199
|
+
.vgai-dock-tab-unsaved button:focus-visible {
|
|
200
|
+
border-color: var(--vgai-accent);
|
|
201
|
+
color: var(--vgai-content-primary);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.vgai-dock-tab-unsaved button:disabled {
|
|
205
|
+
opacity: 0.6;
|
|
206
|
+
cursor: default;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.vgai-dock-tab-badge {
|
|
210
|
+
min-width: 14px;
|
|
211
|
+
height: 14px;
|
|
212
|
+
margin-right: 5px;
|
|
213
|
+
padding: 0 3px;
|
|
214
|
+
border-radius: 7px;
|
|
215
|
+
font-size: 9px;
|
|
216
|
+
line-height: 14px;
|
|
217
|
+
text-align: center;
|
|
218
|
+
color: var(--vgai-bg-0);
|
|
219
|
+
background: var(--vgai-text-2);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.vgai-dock-tab-badge-warn {
|
|
223
|
+
background: var(--vgai-warn);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.vgai-dock-tab-badge-error {
|
|
227
|
+
background: var(--vgai-danger);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.dockview-theme-vgai .dv-tabs-container .dv-tab.dv-active-tab {
|
|
231
|
+
box-shadow: none;
|
|
232
|
+
font-weight: 500;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.dockview-theme-vgai
|
|
236
|
+
.dv-tabs-and-actions-container:not(.dv-single-tab)
|
|
237
|
+
.dv-tabs-container
|
|
238
|
+
.dv-tab.dv-active-tab::before {
|
|
239
|
+
position: absolute;
|
|
240
|
+
right: 10px;
|
|
241
|
+
bottom: 0;
|
|
242
|
+
left: 10px;
|
|
243
|
+
display: block;
|
|
244
|
+
width: auto;
|
|
245
|
+
height: var(--vgai-stroke-active);
|
|
246
|
+
border-radius: 2px 2px 0 0;
|
|
247
|
+
background: var(--vgai-accent);
|
|
248
|
+
content: "";
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.dockview-theme-vgai .dv-split-view-container.dv-horizontal > .dv-sash-container > .dv-sash {
|
|
252
|
+
background: linear-gradient(
|
|
253
|
+
to right,
|
|
254
|
+
transparent 1.5px,
|
|
255
|
+
var(--vgai-border-1) 1.5px 2.5px,
|
|
256
|
+
transparent 2.5px
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.dockview-theme-vgai .dv-split-view-container.dv-vertical > .dv-sash-container > .dv-sash {
|
|
261
|
+
background: linear-gradient(
|
|
262
|
+
to bottom,
|
|
263
|
+
transparent 1.5px,
|
|
264
|
+
var(--vgai-border-1) 1.5px 2.5px,
|
|
265
|
+
transparent 2.5px
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.dockview-theme-vgai .dv-split-view-container.dv-horizontal > .dv-sash-container > .dv-sash:hover,
|
|
270
|
+
.dockview-theme-vgai
|
|
271
|
+
.dv-split-view-container.dv-horizontal
|
|
272
|
+
> .dv-sash-container
|
|
273
|
+
> .dv-sash.dv-active {
|
|
274
|
+
background: linear-gradient(
|
|
275
|
+
to right,
|
|
276
|
+
transparent 1px,
|
|
277
|
+
var(--vgai-accent) 1px 3px,
|
|
278
|
+
transparent 3px
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.dockview-theme-vgai .dv-split-view-container.dv-vertical > .dv-sash-container > .dv-sash:hover,
|
|
283
|
+
.dockview-theme-vgai
|
|
284
|
+
.dv-split-view-container.dv-vertical
|
|
285
|
+
> .dv-sash-container
|
|
286
|
+
> .dv-sash.dv-active {
|
|
287
|
+
background: linear-gradient(
|
|
288
|
+
to bottom,
|
|
289
|
+
transparent 1px,
|
|
290
|
+
var(--vgai-accent) 1px 3px,
|
|
291
|
+
transparent 3px
|
|
292
|
+
);
|
|
293
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace history bridge (W3) — the session `HistoryService` handed to
|
|
3
|
+
* workspace-document content modules (`data-documents.tsx`,
|
|
4
|
+
* `build-documents.tsx`) WITHOUT them importing `EditorContext`.
|
|
5
|
+
*
|
|
6
|
+
* Why not `useOptionalHistoryService()`: `EditorContext`'s import graph
|
|
7
|
+
* pulls the whole editor boot (initial-scene → engine renderer stack), which
|
|
8
|
+
* document-content modules must not drag into their own graph — the old
|
|
9
|
+
* `DataPanel` took `history` as a PROP for exactly this reason, and the
|
|
10
|
+
* headless jsdom tests that mount document content rely on the light graph.
|
|
11
|
+
* `DefaultEditorLayout` (which already lives on the heavy side) sets the
|
|
12
|
+
* live service here; content reads it at commit time. Null (e.g. in tests,
|
|
13
|
+
* or before the layout mounts) degrades to the raw POST/save write paths —
|
|
14
|
+
* the same degrade the old prop-less mounts had.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { HistoryService } from '../history/history-service';
|
|
18
|
+
|
|
19
|
+
let _history: HistoryService | null = null;
|
|
20
|
+
|
|
21
|
+
/** Set (or clear) the live session history service. Returns a cleanup that
|
|
22
|
+
* clears it only if it is still this service. */
|
|
23
|
+
export function setWorkspaceHistoryService(history: HistoryService | null): () => void {
|
|
24
|
+
_history = history;
|
|
25
|
+
return () => {
|
|
26
|
+
if (_history === history) _history = null;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The live session history service, or `null`. */
|
|
31
|
+
export function workspaceHistoryService(): HistoryService | null {
|
|
32
|
+
return _history;
|
|
33
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { themeVars } from '../design-system';
|
|
2
|
+
/**
|
|
3
|
+
* Edit-time documents for manifest worlds that do not use the editor's
|
|
4
|
+
* native Three.js scene renderer. Runtime composition belongs to Game;
|
|
5
|
+
* authoring gives each React/Pixi world its own full-bleed center document.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useEffect, useRef, useSyncExternalStore } from 'react';
|
|
9
|
+
import { getActiveAuthoring } from '../authoring/active-adapter';
|
|
10
|
+
import type { CompositeAuthoringAdapter } from '../authoring/composite-authoring-adapter';
|
|
11
|
+
import {
|
|
12
|
+
type DesignTimeWorldDescriptor,
|
|
13
|
+
designTimeWorldDescriptors,
|
|
14
|
+
mountDesignTimeLayers,
|
|
15
|
+
} from '../authoring/design-time-layers';
|
|
16
|
+
import { resolveViewportToolContext } from '../authoring/viewport-tool-context';
|
|
17
|
+
import type { EditorStore } from '../editor-store';
|
|
18
|
+
import { SCENE_DOCUMENT_ID } from '../workspace-document-ids';
|
|
19
|
+
import {
|
|
20
|
+
activateWorkspaceDocument,
|
|
21
|
+
activeWorkspaceDocumentId,
|
|
22
|
+
closeWorkspaceDocument,
|
|
23
|
+
openWorkspaceDocument,
|
|
24
|
+
type WorkspaceDocumentContentProps,
|
|
25
|
+
} from '../workspace-document-registry';
|
|
26
|
+
import { registerWorldDocumentRoute } from '../world-document-routing';
|
|
27
|
+
import { ReactCanvasControls } from './ReactCanvasControls';
|
|
28
|
+
import { WorldSelectionOverlay } from './WorldSelectionOverlay';
|
|
29
|
+
|
|
30
|
+
export function worldDocumentId(worldId: string): string {
|
|
31
|
+
return `workspace:world:${worldId}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function WorldDocumentContent({
|
|
35
|
+
active,
|
|
36
|
+
composite,
|
|
37
|
+
descriptor,
|
|
38
|
+
store,
|
|
39
|
+
}: WorkspaceDocumentContentProps & {
|
|
40
|
+
composite: CompositeAuthoringAdapter;
|
|
41
|
+
descriptor: DesignTimeWorldDescriptor;
|
|
42
|
+
store: EditorStore;
|
|
43
|
+
}) {
|
|
44
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
45
|
+
const disposeMountRef = useRef<(() => void) | null>(null);
|
|
46
|
+
useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
47
|
+
|
|
48
|
+
// Dockview keeps documents warm. Defer the relatively expensive Pixi/React
|
|
49
|
+
// mount until the world is first visited, then retain it across tab changes
|
|
50
|
+
// so hierarchy identity, story selection, and source editing remain stable.
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (!active || disposeMountRef.current || !containerRef.current) return;
|
|
53
|
+
disposeMountRef.current = mountDesignTimeLayers(containerRef.current, composite, store, [
|
|
54
|
+
descriptor,
|
|
55
|
+
]);
|
|
56
|
+
}, [active, composite, descriptor, store]);
|
|
57
|
+
|
|
58
|
+
useEffect(
|
|
59
|
+
() => () => {
|
|
60
|
+
disposeMountRef.current?.();
|
|
61
|
+
disposeMountRef.current = null;
|
|
62
|
+
},
|
|
63
|
+
[],
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const selectedContext = resolveViewportToolContext(
|
|
67
|
+
getActiveAuthoring(store),
|
|
68
|
+
store.selectedEntityIds,
|
|
69
|
+
);
|
|
70
|
+
const context = selectedContext?.worldId === descriptor.worldId ? selectedContext : null;
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<div
|
|
74
|
+
ref={containerRef}
|
|
75
|
+
data-testid={`world-document:${descriptor.worldId}`}
|
|
76
|
+
style={{
|
|
77
|
+
position: 'absolute',
|
|
78
|
+
inset: 0,
|
|
79
|
+
overflow: 'hidden',
|
|
80
|
+
pointerEvents: 'auto',
|
|
81
|
+
backgroundColor: themeVars.surface.raised,
|
|
82
|
+
backgroundImage:
|
|
83
|
+
`linear-gradient(45deg, ${themeVars.surface.chrome} 25%, transparent 25%, transparent 75%, ${themeVars.surface.chrome} 75%), ` +
|
|
84
|
+
`linear-gradient(45deg, ${themeVars.surface.chrome} 25%, transparent 25%, transparent 75%, ${themeVars.surface.chrome} 75%)`,
|
|
85
|
+
backgroundPosition: '0 0, 8px 8px',
|
|
86
|
+
backgroundSize: '16px 16px',
|
|
87
|
+
}}
|
|
88
|
+
>
|
|
89
|
+
<WorldSelectionOverlay />
|
|
90
|
+
<ReactCanvasControls containerRef={containerRef} context={context} />
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Install one pinned document per non-Three manifest world and map every
|
|
96
|
+
* Three world to the native scene document. Returns the project/rebuild
|
|
97
|
+
* disposer; it closes only the documents installed by this call. */
|
|
98
|
+
export function installWorldDocuments(
|
|
99
|
+
store: EditorStore,
|
|
100
|
+
composite: CompositeAuthoringAdapter,
|
|
101
|
+
): () => void {
|
|
102
|
+
const previouslyActive = activeWorkspaceDocumentId();
|
|
103
|
+
const installedIds: string[] = [];
|
|
104
|
+
const unregisterRoutes: Array<() => void> = [];
|
|
105
|
+
|
|
106
|
+
for (const child of composite.childAdapters()) {
|
|
107
|
+
if (child.role === 'world' && child.kind === 'threejs') {
|
|
108
|
+
unregisterRoutes.push(registerWorldDocumentRoute(child.worldId, SCENE_DOCUMENT_ID));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (const descriptor of designTimeWorldDescriptors(composite)) {
|
|
113
|
+
const id = worldDocumentId(descriptor.worldId);
|
|
114
|
+
unregisterRoutes.push(registerWorldDocumentRoute(descriptor.worldId, id));
|
|
115
|
+
installedIds.push(id);
|
|
116
|
+
const Content = (props: WorkspaceDocumentContentProps) => (
|
|
117
|
+
<WorldDocumentContent
|
|
118
|
+
{...props}
|
|
119
|
+
composite={composite}
|
|
120
|
+
descriptor={descriptor}
|
|
121
|
+
store={store}
|
|
122
|
+
/>
|
|
123
|
+
);
|
|
124
|
+
openWorkspaceDocument({
|
|
125
|
+
id,
|
|
126
|
+
title: descriptor.worldId,
|
|
127
|
+
kind: 'world',
|
|
128
|
+
provenance: {
|
|
129
|
+
rootId: descriptor.worldId,
|
|
130
|
+
...(descriptor.path ? { sourcePath: descriptor.path } : {}),
|
|
131
|
+
},
|
|
132
|
+
Content,
|
|
133
|
+
closeable: false,
|
|
134
|
+
onActivate: () => store.setActiveViewportTab('scene'),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (previouslyActive) activateWorkspaceDocument(previouslyActive);
|
|
139
|
+
else activateWorkspaceDocument(SCENE_DOCUMENT_ID);
|
|
140
|
+
|
|
141
|
+
return () => {
|
|
142
|
+
for (const unregister of unregisterRoutes) unregister();
|
|
143
|
+
for (const id of installedIds) closeWorkspaceDocument(id, { discardDirty: true });
|
|
144
|
+
};
|
|
145
|
+
}
|