@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,238 @@
|
|
|
1
|
+
import { type EditorTheme, type EditorThemeId, editorThemes, isEditorThemeId } from './theme';
|
|
2
|
+
|
|
3
|
+
export const CUSTOM_EDITOR_THEMES_STORAGE_KEY = 'vgai.editor.custom-themes.v1';
|
|
4
|
+
export const CUSTOM_EDITOR_THEME_SCHEMA_VERSION = 1 as const;
|
|
5
|
+
|
|
6
|
+
export interface CustomEditorThemeDocument {
|
|
7
|
+
readonly schemaVersion: typeof CUSTOM_EDITOR_THEME_SCHEMA_VERSION;
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly theme: EditorTheme;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface EditorThemeChoice {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
readonly kind: 'built-in' | 'custom';
|
|
16
|
+
readonly theme: EditorTheme;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const BUILT_IN_NAMES: Record<EditorThemeId, string> = {
|
|
20
|
+
'graphite-dark': 'Graphite Dark',
|
|
21
|
+
'midnight-high-contrast': 'Midnight High Contrast',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const THEME_STRING_PATHS = [
|
|
25
|
+
'id',
|
|
26
|
+
'color.surface.shell',
|
|
27
|
+
'color.surface.panel',
|
|
28
|
+
'color.surface.chrome',
|
|
29
|
+
'color.surface.raised',
|
|
30
|
+
'color.surface.inset',
|
|
31
|
+
'color.surface.overlay',
|
|
32
|
+
'color.boundary.default',
|
|
33
|
+
'color.boundary.strong',
|
|
34
|
+
'color.content.primary',
|
|
35
|
+
'color.content.muted',
|
|
36
|
+
'color.content.dim',
|
|
37
|
+
'color.content.onAccent',
|
|
38
|
+
'color.accent.default',
|
|
39
|
+
'color.accent.muted',
|
|
40
|
+
'color.semantic.danger',
|
|
41
|
+
'color.semantic.dangerMuted',
|
|
42
|
+
'color.semantic.dangerFaint',
|
|
43
|
+
'color.semantic.warning',
|
|
44
|
+
'color.semantic.warningMuted',
|
|
45
|
+
'color.semantic.success',
|
|
46
|
+
'color.semantic.successMuted',
|
|
47
|
+
'color.semantic.dynamic',
|
|
48
|
+
'color.semantic.dynamicMuted',
|
|
49
|
+
'color.neutralOverlay.hover',
|
|
50
|
+
'color.neutralOverlay.active',
|
|
51
|
+
'color.scrim',
|
|
52
|
+
'typography.sans',
|
|
53
|
+
'typography.mono',
|
|
54
|
+
'shape.small',
|
|
55
|
+
'shape.medium',
|
|
56
|
+
'shape.large',
|
|
57
|
+
'shape.full',
|
|
58
|
+
'elevation.small',
|
|
59
|
+
'elevation.medium',
|
|
60
|
+
'elevation.large',
|
|
61
|
+
] as const;
|
|
62
|
+
|
|
63
|
+
let cachedCustomThemes: readonly CustomEditorThemeDocument[] | null = null;
|
|
64
|
+
let cachedChoices: readonly EditorThemeChoice[] | null = null;
|
|
65
|
+
const listeners = new Set<() => void>();
|
|
66
|
+
|
|
67
|
+
function storage(): Storage | null {
|
|
68
|
+
try {
|
|
69
|
+
return typeof window === 'undefined' ? null : window.localStorage;
|
|
70
|
+
} catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function valueAtPath(value: unknown, path: string): unknown {
|
|
76
|
+
let current = value;
|
|
77
|
+
for (const key of path.split('.')) {
|
|
78
|
+
if (!current || typeof current !== 'object') return undefined;
|
|
79
|
+
current = (current as Record<string, unknown>)[key];
|
|
80
|
+
}
|
|
81
|
+
return current;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function parseCustomEditorThemeDocument(value: unknown): CustomEditorThemeDocument {
|
|
85
|
+
if (!value || typeof value !== 'object') throw new Error('Theme file must contain an object.');
|
|
86
|
+
const record = value as Record<string, unknown>;
|
|
87
|
+
if (record['schemaVersion'] !== CUSTOM_EDITOR_THEME_SCHEMA_VERSION) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Unsupported theme schema version. Expected ${CUSTOM_EDITOR_THEME_SCHEMA_VERSION}.`,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
if (typeof record['name'] !== 'string' || !record['name'].trim()) {
|
|
93
|
+
throw new Error('Theme name must be a non-empty string.');
|
|
94
|
+
}
|
|
95
|
+
for (const path of THEME_STRING_PATHS) {
|
|
96
|
+
const field = valueAtPath(record['theme'], path);
|
|
97
|
+
if (typeof field !== 'string' || !field.trim()) {
|
|
98
|
+
throw new Error(`Theme field “${path}” must be a non-empty string.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
schemaVersion: CUSTOM_EDITOR_THEME_SCHEMA_VERSION,
|
|
103
|
+
name: record['name'].trim(),
|
|
104
|
+
theme: structuredClone(record['theme']) as EditorTheme,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function readCustomThemes(): readonly CustomEditorThemeDocument[] {
|
|
109
|
+
const raw = storage()?.getItem(CUSTOM_EDITOR_THEMES_STORAGE_KEY);
|
|
110
|
+
if (!raw) return [];
|
|
111
|
+
try {
|
|
112
|
+
const parsed: unknown = JSON.parse(raw);
|
|
113
|
+
if (!Array.isArray(parsed)) return [];
|
|
114
|
+
const valid: CustomEditorThemeDocument[] = [];
|
|
115
|
+
for (const item of parsed) {
|
|
116
|
+
try {
|
|
117
|
+
const document = parseCustomEditorThemeDocument(item);
|
|
118
|
+
if (
|
|
119
|
+
!isEditorThemeId(document.theme.id) &&
|
|
120
|
+
!valid.some((entry) => entry.theme.id === document.theme.id)
|
|
121
|
+
) {
|
|
122
|
+
valid.push(document);
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
// One malformed user record must not make every saved theme unavailable.
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return valid;
|
|
129
|
+
} catch {
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function customThemes(): readonly CustomEditorThemeDocument[] {
|
|
135
|
+
cachedCustomThemes ??= readCustomThemes();
|
|
136
|
+
return cachedCustomThemes;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function emit(): void {
|
|
140
|
+
cachedChoices = null;
|
|
141
|
+
for (const listener of listeners) listener();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function writeCustomThemes(themes: readonly CustomEditorThemeDocument[]): void {
|
|
145
|
+
cachedCustomThemes = themes;
|
|
146
|
+
storage()?.setItem(CUSTOM_EDITOR_THEMES_STORAGE_KEY, JSON.stringify(themes));
|
|
147
|
+
emit();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function uniqueThemeId(seed = 'custom-theme'): string {
|
|
151
|
+
const slug =
|
|
152
|
+
seed
|
|
153
|
+
.toLowerCase()
|
|
154
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
155
|
+
.replace(/^-|-$/g, '') || 'custom-theme';
|
|
156
|
+
const occupied = new Set(editorThemeLibrarySnapshot().map((choice) => choice.id));
|
|
157
|
+
if (!occupied.has(slug)) return slug;
|
|
158
|
+
let suffix = 2;
|
|
159
|
+
while (occupied.has(`${slug}-${suffix}`)) suffix += 1;
|
|
160
|
+
return `${slug}-${suffix}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function editorThemeLibrarySnapshot(): readonly EditorThemeChoice[] {
|
|
164
|
+
cachedChoices ??= [
|
|
165
|
+
...Object.entries(editorThemes).map(([id, theme]) => ({
|
|
166
|
+
id,
|
|
167
|
+
name: BUILT_IN_NAMES[id as EditorThemeId],
|
|
168
|
+
kind: 'built-in' as const,
|
|
169
|
+
theme,
|
|
170
|
+
})),
|
|
171
|
+
...customThemes().map((document) => ({
|
|
172
|
+
id: document.theme.id,
|
|
173
|
+
name: document.name,
|
|
174
|
+
kind: 'custom' as const,
|
|
175
|
+
theme: document.theme,
|
|
176
|
+
})),
|
|
177
|
+
];
|
|
178
|
+
return cachedChoices;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function subscribeEditorThemeLibrary(listener: () => void): () => void {
|
|
182
|
+
listeners.add(listener);
|
|
183
|
+
return () => listeners.delete(listener);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function resolveEditorTheme(id: string): EditorThemeChoice | undefined {
|
|
187
|
+
return editorThemeLibrarySnapshot().find((choice) => choice.id === id);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function duplicateEditorTheme(sourceId: string, requestedName?: string): EditorThemeChoice {
|
|
191
|
+
const source = resolveEditorTheme(sourceId);
|
|
192
|
+
if (!source) throw new Error(`Unknown editor theme “${sourceId}”.`);
|
|
193
|
+
const name = requestedName?.trim() || `${source.name} Copy`;
|
|
194
|
+
const id = uniqueThemeId(name);
|
|
195
|
+
const document: CustomEditorThemeDocument = {
|
|
196
|
+
schemaVersion: CUSTOM_EDITOR_THEME_SCHEMA_VERSION,
|
|
197
|
+
name,
|
|
198
|
+
theme: { ...structuredClone(source.theme), id },
|
|
199
|
+
};
|
|
200
|
+
writeCustomThemes([...customThemes(), document]);
|
|
201
|
+
return resolveEditorTheme(id)!;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function saveCustomEditorTheme(document: CustomEditorThemeDocument): EditorThemeChoice {
|
|
205
|
+
const parsed = parseCustomEditorThemeDocument(document);
|
|
206
|
+
if (isEditorThemeId(parsed.theme.id)) throw new Error('Built-in themes cannot be overwritten.');
|
|
207
|
+
const themes = [...customThemes()];
|
|
208
|
+
const index = themes.findIndex((entry) => entry.theme.id === parsed.theme.id);
|
|
209
|
+
if (index >= 0) themes[index] = parsed;
|
|
210
|
+
else themes.push(parsed);
|
|
211
|
+
writeCustomThemes(themes);
|
|
212
|
+
return resolveEditorTheme(parsed.theme.id)!;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function importCustomEditorTheme(value: unknown): EditorThemeChoice {
|
|
216
|
+
const parsed = parseCustomEditorThemeDocument(value);
|
|
217
|
+
const id = uniqueThemeId(parsed.name);
|
|
218
|
+
return saveCustomEditorTheme({ ...parsed, theme: { ...parsed.theme, id } });
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function deleteCustomEditorTheme(id: string): boolean {
|
|
222
|
+
const themes = customThemes();
|
|
223
|
+
const next = themes.filter((entry) => entry.theme.id !== id);
|
|
224
|
+
if (next.length === themes.length) return false;
|
|
225
|
+
writeCustomThemes(next);
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Re-read records after another tab changes localStorage. */
|
|
230
|
+
export function refreshEditorThemeLibraryFromStorage(): void {
|
|
231
|
+
cachedCustomThemes = readCustomThemes();
|
|
232
|
+
emit();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function resetEditorThemeLibraryForTests(): void {
|
|
236
|
+
cachedCustomThemes = null;
|
|
237
|
+
cachedChoices = null;
|
|
238
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { applyEditorTheme, type EditorTheme } from './theme';
|
|
2
|
+
import {
|
|
3
|
+
CUSTOM_EDITOR_THEMES_STORAGE_KEY,
|
|
4
|
+
refreshEditorThemeLibraryFromStorage,
|
|
5
|
+
resolveEditorTheme,
|
|
6
|
+
subscribeEditorThemeLibrary,
|
|
7
|
+
} from './theme-library';
|
|
8
|
+
|
|
9
|
+
const STORAGE_KEY = 'vgai.editor.theme.v1';
|
|
10
|
+
export const DEFAULT_EDITOR_THEME_ID = 'graphite-dark';
|
|
11
|
+
|
|
12
|
+
let cachedThemeId: string | null = null;
|
|
13
|
+
let installedRoot: HTMLElement | null = null;
|
|
14
|
+
let previewTheme: EditorTheme | null = null;
|
|
15
|
+
let removeStorageListener: (() => void) | null = null;
|
|
16
|
+
const listeners = new Set<() => void>();
|
|
17
|
+
|
|
18
|
+
function storage(): Storage | null {
|
|
19
|
+
try {
|
|
20
|
+
return typeof window === 'undefined' ? null : window.localStorage;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function readStoredThemeId(): string {
|
|
27
|
+
return resolveThemeId(storage()?.getItem(STORAGE_KEY));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveThemeId(value: string | null | undefined): string {
|
|
31
|
+
return value && resolveEditorTheme(value) ? value : DEFAULT_EDITOR_THEME_ID;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function fallBackFromMissingTheme(): void {
|
|
35
|
+
if (resolveEditorTheme(editorThemeSnapshot())) return;
|
|
36
|
+
cachedThemeId = DEFAULT_EDITOR_THEME_ID;
|
|
37
|
+
storage()?.setItem(STORAGE_KEY, DEFAULT_EDITOR_THEME_ID);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function editorThemeSnapshot(): string {
|
|
41
|
+
cachedThemeId ??= readStoredThemeId();
|
|
42
|
+
return cachedThemeId;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function subscribeEditorTheme(listener: () => void): () => void {
|
|
46
|
+
listeners.add(listener);
|
|
47
|
+
return () => listeners.delete(listener);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function emit(): void {
|
|
51
|
+
for (const listener of listeners) listener();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function applyCurrentTheme(): void {
|
|
55
|
+
if (!installedRoot) return;
|
|
56
|
+
const theme = previewTheme ?? resolveEditorTheme(editorThemeSnapshot())?.theme;
|
|
57
|
+
if (theme) applyEditorTheme(installedRoot, theme);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function setEditorThemePreference(themeId: string): void {
|
|
61
|
+
if (!resolveEditorTheme(themeId)) throw new Error(`Unknown editor theme “${themeId}”.`);
|
|
62
|
+
previewTheme = null;
|
|
63
|
+
if (editorThemeSnapshot() === themeId) {
|
|
64
|
+
applyCurrentTheme();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
cachedThemeId = themeId;
|
|
68
|
+
storage()?.setItem(STORAGE_KEY, themeId);
|
|
69
|
+
applyCurrentTheme();
|
|
70
|
+
emit();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Temporarily paint an unsaved draft without changing the persisted choice. */
|
|
74
|
+
export function previewEditorTheme(theme: EditorTheme): void {
|
|
75
|
+
previewTheme = theme;
|
|
76
|
+
applyCurrentTheme();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Return from a draft preview to the currently persisted library theme. */
|
|
80
|
+
export function clearEditorThemePreview(): void {
|
|
81
|
+
previewTheme = null;
|
|
82
|
+
applyCurrentTheme();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Install persisted theming and cross-tab synchronization on one editor root. */
|
|
86
|
+
export function installEditorTheme(root: HTMLElement): () => void {
|
|
87
|
+
installedRoot = root;
|
|
88
|
+
applyCurrentTheme();
|
|
89
|
+
|
|
90
|
+
removeStorageListener?.();
|
|
91
|
+
if (typeof window !== 'undefined') {
|
|
92
|
+
const onStorage = (event: StorageEvent) => {
|
|
93
|
+
if (event.key === CUSTOM_EDITOR_THEMES_STORAGE_KEY) {
|
|
94
|
+
refreshEditorThemeLibraryFromStorage();
|
|
95
|
+
fallBackFromMissingTheme();
|
|
96
|
+
} else if (event.key === STORAGE_KEY) {
|
|
97
|
+
cachedThemeId = resolveThemeId(event.newValue);
|
|
98
|
+
} else return;
|
|
99
|
+
previewTheme = null;
|
|
100
|
+
applyCurrentTheme();
|
|
101
|
+
emit();
|
|
102
|
+
};
|
|
103
|
+
window.addEventListener('storage', onStorage);
|
|
104
|
+
removeStorageListener = () => window.removeEventListener('storage', onStorage);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return () => {
|
|
108
|
+
if (installedRoot === root) installedRoot = null;
|
|
109
|
+
removeStorageListener?.();
|
|
110
|
+
removeStorageListener = null;
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Test-only process reset; production callers should never clear the preference implicitly. */
|
|
115
|
+
export function resetEditorThemePreferenceForTests(): void {
|
|
116
|
+
cachedThemeId = null;
|
|
117
|
+
installedRoot = null;
|
|
118
|
+
previewTheme = null;
|
|
119
|
+
removeStorageListener?.();
|
|
120
|
+
removeStorageListener = null;
|
|
121
|
+
listeners.clear();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Library changes made in this tab immediately repaint a selected custom
|
|
125
|
+
// theme and update every menu/dialog subscriber.
|
|
126
|
+
subscribeEditorThemeLibrary(() => {
|
|
127
|
+
fallBackFromMissingTheme();
|
|
128
|
+
applyCurrentTheme();
|
|
129
|
+
emit();
|
|
130
|
+
});
|