@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
|
@@ -3,20 +3,30 @@ import { DEFAULTS } from '@engine/scene/defaults';
|
|
|
3
3
|
import { parseMaterialFile } from '@engine/scene/parse';
|
|
4
4
|
import type { MaterialFile, SceneEntity, SceneMaterial } from '@engine/scene/scene-types';
|
|
5
5
|
import { useEffect, useRef, useState } from 'react';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
|
+
Checkbox,
|
|
9
|
+
ColorInput,
|
|
10
|
+
DisclosureIcon,
|
|
11
|
+
NumberInput,
|
|
12
|
+
SectionHeader,
|
|
13
|
+
Select,
|
|
14
|
+
TextInput,
|
|
15
|
+
Tooltip,
|
|
16
|
+
themeVars,
|
|
17
|
+
} from '../../design-system';
|
|
18
|
+
import { useEditorStore, useOptionalHistoryService } from '../../EditorContext';
|
|
19
|
+
import { getProjectFileHistory } from '../../history/project-file-history';
|
|
7
20
|
import { clearMaterialRefCache } from '../../scene-sync';
|
|
8
21
|
import { saveMaterialToServer } from '../DefaultEditorLayout';
|
|
9
|
-
import {
|
|
10
|
-
import { NumberInput } from '../primitives/NumberInput';
|
|
11
|
-
import { SectionHeader } from '../primitives/SectionHeader';
|
|
12
|
-
import { Tooltip } from '../primitives/Tooltip';
|
|
22
|
+
import { fieldLabelStyle, groupLabelStyle, mixedStyle } from '../inspector-widgets/shared';
|
|
13
23
|
import type { SectionProps } from './multi-edit-utils';
|
|
14
24
|
import { commonBool, commonNum, commonStr } from './multi-edit-utils';
|
|
15
25
|
|
|
16
26
|
const matTypes: SceneMaterial['type'][] = ['standard', 'physical', 'basic', 'toon'];
|
|
17
27
|
const sideOptions: SceneMaterial['side'][] = ['front', 'back', 'double'];
|
|
18
28
|
|
|
19
|
-
const labelStyle: React.CSSProperties =
|
|
29
|
+
const labelStyle: React.CSSProperties = fieldLabelStyle;
|
|
20
30
|
|
|
21
31
|
function TextureInput({
|
|
22
32
|
value,
|
|
@@ -60,9 +70,9 @@ function TextureInput({
|
|
|
60
70
|
display: 'flex',
|
|
61
71
|
alignItems: 'center',
|
|
62
72
|
gap: 4,
|
|
63
|
-
border: dragOver ?
|
|
64
|
-
background: dragOver ?
|
|
65
|
-
borderRadius:
|
|
73
|
+
border: dragOver ? `1px dashed ${themeVars.accent.default}` : '1px solid transparent',
|
|
74
|
+
background: dragOver ? themeVars.accent.muted : undefined,
|
|
75
|
+
borderRadius: themeVars.shape.small,
|
|
66
76
|
padding: 1,
|
|
67
77
|
}}
|
|
68
78
|
>
|
|
@@ -75,8 +85,8 @@ function TextureInput({
|
|
|
75
85
|
width: 48,
|
|
76
86
|
height: 48,
|
|
77
87
|
objectFit: 'cover',
|
|
78
|
-
borderRadius:
|
|
79
|
-
border:
|
|
88
|
+
borderRadius: themeVars.shape.small,
|
|
89
|
+
border: `1px solid ${themeVars.boundary.default}`,
|
|
80
90
|
flexShrink: 0,
|
|
81
91
|
}}
|
|
82
92
|
/>
|
|
@@ -86,14 +96,16 @@ function TextureInput({
|
|
|
86
96
|
style={{
|
|
87
97
|
width: 48,
|
|
88
98
|
height: 48,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
99
|
+
// Recessed-well surface \u2014 unified on themeVars.surface.inset (I-31; this was one
|
|
100
|
+
// of three competing "recessed panel" grays).
|
|
101
|
+
background: themeVars.surface.inset,
|
|
102
|
+
borderRadius: themeVars.shape.small,
|
|
103
|
+
border: `1px solid ${themeVars.boundary.default}`,
|
|
92
104
|
display: 'flex',
|
|
93
105
|
alignItems: 'center',
|
|
94
106
|
justifyContent: 'center',
|
|
95
107
|
fontSize: 16,
|
|
96
|
-
color:
|
|
108
|
+
color: themeVars.content.dim,
|
|
97
109
|
flexShrink: 0,
|
|
98
110
|
}}
|
|
99
111
|
>
|
|
@@ -101,43 +113,27 @@ function TextureInput({
|
|
|
101
113
|
</div>
|
|
102
114
|
)}
|
|
103
115
|
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
104
|
-
<
|
|
116
|
+
<TextInput
|
|
117
|
+
className="vgai-input"
|
|
105
118
|
value={value ?? ''}
|
|
106
119
|
placeholder="path/to/texture.png"
|
|
107
120
|
onChange={(e) => {
|
|
108
121
|
setImgError(false);
|
|
109
122
|
onChange(e.target.value || undefined);
|
|
110
123
|
}}
|
|
111
|
-
style={{
|
|
112
|
-
width: '100%',
|
|
113
|
-
background: '#1e1e1e',
|
|
114
|
-
color: '#c5c8ce',
|
|
115
|
-
border: '1px solid #333',
|
|
116
|
-
borderRadius: 2,
|
|
117
|
-
padding: '2px 4px',
|
|
118
|
-
fontSize: 11,
|
|
119
|
-
}}
|
|
124
|
+
style={{ width: '100%' }}
|
|
120
125
|
/>
|
|
121
126
|
{value && (
|
|
122
|
-
<
|
|
127
|
+
<Button
|
|
123
128
|
type="button"
|
|
124
129
|
onClick={() => {
|
|
125
130
|
setImgError(false);
|
|
126
131
|
onChange(undefined);
|
|
127
132
|
}}
|
|
128
|
-
style={{
|
|
129
|
-
alignSelf: 'flex-start',
|
|
130
|
-
background: '#333',
|
|
131
|
-
color: '#c5c8ce',
|
|
132
|
-
border: '1px solid #444',
|
|
133
|
-
borderRadius: 3,
|
|
134
|
-
padding: '1px 6px',
|
|
135
|
-
cursor: 'pointer',
|
|
136
|
-
fontSize: 10,
|
|
137
|
-
}}
|
|
133
|
+
style={{ alignSelf: 'flex-start' }}
|
|
138
134
|
>
|
|
139
135
|
Clear
|
|
140
|
-
</
|
|
136
|
+
</Button>
|
|
141
137
|
)}
|
|
142
138
|
</div>
|
|
143
139
|
</div>
|
|
@@ -164,7 +160,7 @@ function FeatureToggle({
|
|
|
164
160
|
}, [enabled]);
|
|
165
161
|
|
|
166
162
|
return (
|
|
167
|
-
<div style={{ borderTop:
|
|
163
|
+
<div style={{ borderTop: `1px solid ${themeVars.boundary.default}`, paddingTop: 4 }}>
|
|
168
164
|
<div
|
|
169
165
|
style={{
|
|
170
166
|
display: 'flex',
|
|
@@ -175,12 +171,16 @@ function FeatureToggle({
|
|
|
175
171
|
}}
|
|
176
172
|
onClick={() => setExpanded(!expanded)}
|
|
177
173
|
>
|
|
178
|
-
<
|
|
179
|
-
{expanded ? '
|
|
174
|
+
<DisclosureIcon
|
|
175
|
+
direction={expanded ? 'down' : 'right'}
|
|
176
|
+
tone="muted"
|
|
177
|
+
style={{ width: 10 }}
|
|
178
|
+
/>
|
|
179
|
+
<span style={{ fontSize: 11, color: themeVars.content.primary, flex: 1, fontWeight: 600 }}>
|
|
180
|
+
{label}
|
|
180
181
|
</span>
|
|
181
|
-
<
|
|
182
|
-
|
|
183
|
-
type="checkbox"
|
|
182
|
+
<Checkbox
|
|
183
|
+
className="vgai-checkbox"
|
|
184
184
|
checked={enabled}
|
|
185
185
|
onChange={(e) => {
|
|
186
186
|
e.stopPropagation();
|
|
@@ -526,56 +526,56 @@ function PhysicalFeaturesMulti({ entities, ids }: { entities: SceneEntity[]; ids
|
|
|
526
526
|
|
|
527
527
|
return (
|
|
528
528
|
<>
|
|
529
|
-
<div style={{ borderTop:
|
|
529
|
+
<div style={{ borderTop: `1px solid ${themeVars.boundary.default}`, paddingTop: 4 }}>
|
|
530
530
|
<label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>
|
|
531
|
-
<
|
|
532
|
-
|
|
531
|
+
<Checkbox
|
|
532
|
+
className="vgai-checkbox"
|
|
533
533
|
checked={hasClearcoat ?? false}
|
|
534
534
|
ref={(el) => {
|
|
535
535
|
if (el) el.indeterminate = hasClearcoat === null;
|
|
536
536
|
}}
|
|
537
537
|
onChange={(e) => toggleFeature('clearcoat', e.target.checked)}
|
|
538
538
|
/>
|
|
539
|
-
<span style={{ color:
|
|
539
|
+
<span style={{ color: themeVars.content.primary }}>Clearcoat</span>
|
|
540
540
|
</label>
|
|
541
541
|
</div>
|
|
542
542
|
<div>
|
|
543
543
|
<label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>
|
|
544
|
-
<
|
|
545
|
-
|
|
544
|
+
<Checkbox
|
|
545
|
+
className="vgai-checkbox"
|
|
546
546
|
checked={hasTransmission ?? false}
|
|
547
547
|
ref={(el) => {
|
|
548
548
|
if (el) el.indeterminate = hasTransmission === null;
|
|
549
549
|
}}
|
|
550
550
|
onChange={(e) => toggleFeature('transmission', e.target.checked)}
|
|
551
551
|
/>
|
|
552
|
-
<span style={{ color:
|
|
552
|
+
<span style={{ color: themeVars.content.primary }}>Transmission</span>
|
|
553
553
|
</label>
|
|
554
554
|
</div>
|
|
555
555
|
<div>
|
|
556
556
|
<label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>
|
|
557
|
-
<
|
|
558
|
-
|
|
557
|
+
<Checkbox
|
|
558
|
+
className="vgai-checkbox"
|
|
559
559
|
checked={hasSheen ?? false}
|
|
560
560
|
ref={(el) => {
|
|
561
561
|
if (el) el.indeterminate = hasSheen === null;
|
|
562
562
|
}}
|
|
563
563
|
onChange={(e) => toggleFeature('sheen', e.target.checked)}
|
|
564
564
|
/>
|
|
565
|
-
<span style={{ color:
|
|
565
|
+
<span style={{ color: themeVars.content.primary }}>Sheen</span>
|
|
566
566
|
</label>
|
|
567
567
|
</div>
|
|
568
568
|
<div>
|
|
569
569
|
<label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11 }}>
|
|
570
|
-
<
|
|
571
|
-
|
|
570
|
+
<Checkbox
|
|
571
|
+
className="vgai-checkbox"
|
|
572
572
|
checked={hasIridescence ?? false}
|
|
573
573
|
ref={(el) => {
|
|
574
574
|
if (el) el.indeterminate = hasIridescence === null;
|
|
575
575
|
}}
|
|
576
576
|
onChange={(e) => toggleFeature('iridescence', e.target.checked)}
|
|
577
577
|
/>
|
|
578
|
-
<span style={{ color:
|
|
578
|
+
<span style={{ color: themeVars.content.primary }}>Iridescence</span>
|
|
579
579
|
</label>
|
|
580
580
|
</div>
|
|
581
581
|
</>
|
|
@@ -584,12 +584,23 @@ function PhysicalFeaturesMulti({ entities, ids }: { entities: SceneEntity[]; ids
|
|
|
584
584
|
|
|
585
585
|
export function MaterialSection({ entities, ids }: SectionProps) {
|
|
586
586
|
const store = useEditorStore();
|
|
587
|
+
const history = useOptionalHistoryService();
|
|
587
588
|
const multi = entities.length > 1;
|
|
588
589
|
const entity = entities[0]!;
|
|
589
590
|
const materialRef = entity.materialRef;
|
|
590
591
|
|
|
591
592
|
// Hooks must be unconditional — single-entity-only features gated with !multi below
|
|
592
593
|
const [refMat, setRefMat] = useState<SceneMaterial | null>(null);
|
|
594
|
+
const [materialRevision, setMaterialRevision] = useState(0);
|
|
595
|
+
useEffect(
|
|
596
|
+
() =>
|
|
597
|
+
history
|
|
598
|
+
? getProjectFileHistory(history).subscribeAll((path) => {
|
|
599
|
+
if (path === materialRef) setMaterialRevision((value) => value + 1);
|
|
600
|
+
})
|
|
601
|
+
: () => {},
|
|
602
|
+
[history, materialRef],
|
|
603
|
+
);
|
|
593
604
|
useEffect(() => {
|
|
594
605
|
if (multi || !materialRef) {
|
|
595
606
|
setRefMat(null);
|
|
@@ -599,11 +610,10 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
599
610
|
.then((r) => (r.ok ? r.json() : null))
|
|
600
611
|
.then((json) => (json === null ? null : parseMaterialFile(json, materialRef)))
|
|
601
612
|
.then((file) => setRefMat(file?.material ?? null))
|
|
602
|
-
.catch((
|
|
603
|
-
console.error(`[MaterialSection] invalid material ref "${materialRef}":`, err);
|
|
613
|
+
.catch((_err) => {
|
|
604
614
|
setRefMat(null);
|
|
605
615
|
});
|
|
606
|
-
}, [multi, materialRef]);
|
|
616
|
+
}, [multi, materialRef, materialRevision]);
|
|
607
617
|
|
|
608
618
|
const [savingAs, setSavingAs] = useState(false);
|
|
609
619
|
const defaultName = entity.name.toLowerCase().replace(/\s+/g, '-');
|
|
@@ -643,23 +653,15 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
643
653
|
{/* Type */}
|
|
644
654
|
<div>
|
|
645
655
|
<div style={labelStyle}>Type</div>
|
|
646
|
-
<
|
|
656
|
+
<Select
|
|
657
|
+
className="vgai-select"
|
|
647
658
|
value={matType ?? ''}
|
|
648
659
|
onChange={(e) => update({ type: e.target.value as SceneMaterial['type'] })}
|
|
649
|
-
style={{
|
|
650
|
-
width: '100%',
|
|
651
|
-
background: '#1e1e1e',
|
|
652
|
-
color: matType === null ? '#666' : '#c5c8ce',
|
|
653
|
-
fontStyle: matType === null ? 'italic' : 'normal',
|
|
654
|
-
border: '1px solid #333',
|
|
655
|
-
borderRadius: 2,
|
|
656
|
-
padding: '3px 4px',
|
|
657
|
-
fontSize: 12,
|
|
658
|
-
}}
|
|
660
|
+
style={{ width: '100%', ...mixedStyle(matType === null) }}
|
|
659
661
|
>
|
|
660
662
|
{matType === null && (
|
|
661
663
|
<option value="" disabled>
|
|
662
|
-
|
|
664
|
+
—
|
|
663
665
|
</option>
|
|
664
666
|
)}
|
|
665
667
|
{matTypes.map((t) => (
|
|
@@ -667,7 +669,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
667
669
|
{t}
|
|
668
670
|
</option>
|
|
669
671
|
))}
|
|
670
|
-
</
|
|
672
|
+
</Select>
|
|
671
673
|
</div>
|
|
672
674
|
|
|
673
675
|
{/* Color */}
|
|
@@ -701,15 +703,17 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
701
703
|
</div>
|
|
702
704
|
<div>
|
|
703
705
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
704
|
-
<
|
|
705
|
-
|
|
706
|
+
<Checkbox
|
|
707
|
+
className="vgai-checkbox"
|
|
706
708
|
checked={flatShading ?? false}
|
|
707
709
|
ref={(el) => {
|
|
708
710
|
if (el) el.indeterminate = flatShading === null;
|
|
709
711
|
}}
|
|
710
712
|
onChange={(e) => update({ flatShading: e.target.checked })}
|
|
711
713
|
/>
|
|
712
|
-
<span style={{ fontSize: 11, color:
|
|
714
|
+
<span style={{ fontSize: 11, color: themeVars.content.primary }}>
|
|
715
|
+
Flat Shading
|
|
716
|
+
</span>
|
|
713
717
|
</div>
|
|
714
718
|
</div>
|
|
715
719
|
</>
|
|
@@ -742,15 +746,15 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
742
746
|
</div>
|
|
743
747
|
<div>
|
|
744
748
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
745
|
-
<
|
|
746
|
-
|
|
749
|
+
<Checkbox
|
|
750
|
+
className="vgai-checkbox"
|
|
747
751
|
checked={transparent ?? false}
|
|
748
752
|
ref={(el) => {
|
|
749
753
|
if (el) el.indeterminate = transparent === null;
|
|
750
754
|
}}
|
|
751
755
|
onChange={(e) => update({ transparent: e.target.checked })}
|
|
752
756
|
/>
|
|
753
|
-
<span style={{ fontSize: 11, color:
|
|
757
|
+
<span style={{ fontSize: 11, color: themeVars.content.primary }}>Transparent</span>
|
|
754
758
|
</div>
|
|
755
759
|
</div>
|
|
756
760
|
|
|
@@ -759,23 +763,15 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
759
763
|
<Tooltip text="Which faces to render" position="right">
|
|
760
764
|
<div style={labelStyle}>Side</div>
|
|
761
765
|
</Tooltip>
|
|
762
|
-
<
|
|
766
|
+
<Select
|
|
767
|
+
className="vgai-select"
|
|
763
768
|
value={side ?? ''}
|
|
764
769
|
onChange={(e) => update({ side: e.target.value as SceneMaterial['side'] })}
|
|
765
|
-
style={{
|
|
766
|
-
width: '100%',
|
|
767
|
-
background: '#1e1e1e',
|
|
768
|
-
color: side === null ? '#666' : '#c5c8ce',
|
|
769
|
-
fontStyle: side === null ? 'italic' : 'normal',
|
|
770
|
-
border: '1px solid #333',
|
|
771
|
-
borderRadius: 2,
|
|
772
|
-
padding: '3px 4px',
|
|
773
|
-
fontSize: 12,
|
|
774
|
-
}}
|
|
770
|
+
style={{ width: '100%', ...mixedStyle(side === null) }}
|
|
775
771
|
>
|
|
776
772
|
{side === null && (
|
|
777
773
|
<option value="" disabled>
|
|
778
|
-
|
|
774
|
+
—
|
|
779
775
|
</option>
|
|
780
776
|
)}
|
|
781
777
|
{sideOptions.map((s) => (
|
|
@@ -783,7 +779,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
783
779
|
{s}
|
|
784
780
|
</option>
|
|
785
781
|
))}
|
|
786
|
-
</
|
|
782
|
+
</Select>
|
|
787
783
|
</div>
|
|
788
784
|
|
|
789
785
|
{/* Physical material feature toggles (multi-entity) */}
|
|
@@ -799,7 +795,9 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
799
795
|
if (!mat)
|
|
800
796
|
return (
|
|
801
797
|
<SectionHeader label="Material">
|
|
802
|
-
<div style={{ padding: 4, fontSize: 11, color:
|
|
798
|
+
<div style={{ padding: 4, fontSize: 11, color: themeVars.content.dim }}>
|
|
799
|
+
Loading material...
|
|
800
|
+
</div>
|
|
803
801
|
</SectionHeader>
|
|
804
802
|
);
|
|
805
803
|
|
|
@@ -814,7 +812,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
814
812
|
name: entity.materialRef.split('/').pop()?.replace('.mat.json', '') ?? 'Material',
|
|
815
813
|
material: updated,
|
|
816
814
|
};
|
|
817
|
-
saveMaterialToServer(file, entity.materialRef).then((ok) => {
|
|
815
|
+
saveMaterialToServer(file, entity.materialRef, history ?? undefined).then((ok) => {
|
|
818
816
|
if (ok) {
|
|
819
817
|
setRefMat(updated);
|
|
820
818
|
clearMaterialRefCache();
|
|
@@ -839,7 +837,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
839
837
|
name: entity.materialRef.split('/').pop()?.replace('.mat.json', '') ?? 'Material',
|
|
840
838
|
material: next,
|
|
841
839
|
};
|
|
842
|
-
saveMaterialToServer(file, entity.materialRef).then((ok) => {
|
|
840
|
+
saveMaterialToServer(file, entity.materialRef, history ?? undefined).then((ok) => {
|
|
843
841
|
if (ok) {
|
|
844
842
|
setRefMat(next);
|
|
845
843
|
clearMaterialRefCache();
|
|
@@ -855,9 +853,12 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
855
853
|
if (!savePath.trim()) return;
|
|
856
854
|
const path = savePath.trim();
|
|
857
855
|
const file: MaterialFile = { version: 1, name: defaultName, material: mat };
|
|
858
|
-
const
|
|
856
|
+
const content = JSON.stringify(file, null, 2);
|
|
857
|
+
const ok = history
|
|
858
|
+
? await store.saveMaterialAsReference(id, path, content)
|
|
859
|
+
: await saveMaterialToServer(file, path);
|
|
859
860
|
if (ok) {
|
|
860
|
-
store.updateEntity(id, { materialRef: path, material: undefined });
|
|
861
|
+
if (!history) store.updateEntity(id, { materialRef: path, material: undefined });
|
|
861
862
|
setSavingAs(false);
|
|
862
863
|
}
|
|
863
864
|
};
|
|
@@ -885,15 +886,7 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
885
886
|
}
|
|
886
887
|
};
|
|
887
888
|
|
|
888
|
-
|
|
889
|
-
background: '#333',
|
|
890
|
-
color: '#c5c8ce',
|
|
891
|
-
border: '1px solid #444',
|
|
892
|
-
borderRadius: 3,
|
|
893
|
-
padding: '2px 6px',
|
|
894
|
-
cursor: 'pointer',
|
|
895
|
-
fontSize: 10,
|
|
896
|
-
};
|
|
889
|
+
// Shared compact chrome button (I-8/I-10) — the old per-file literal.
|
|
897
890
|
|
|
898
891
|
return (
|
|
899
892
|
<SectionHeader label="Material">
|
|
@@ -907,18 +900,23 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
907
900
|
<div
|
|
908
901
|
style={{
|
|
909
902
|
padding: '4px 6px',
|
|
910
|
-
|
|
911
|
-
|
|
903
|
+
// Info-banner tint band (shared with the prefab banner) — no
|
|
904
|
+
// token slot exists for tinted panel backgrounds; deliberate
|
|
905
|
+
// literal, text/buttons reconciled onto text-1/themeVars.accent.default (I-5).
|
|
906
|
+
background: themeVars.accent.muted,
|
|
907
|
+
borderRadius: themeVars.shape.small,
|
|
912
908
|
display: 'flex',
|
|
913
909
|
alignItems: 'center',
|
|
914
910
|
gap: 4,
|
|
915
911
|
}}
|
|
916
912
|
>
|
|
917
|
-
<span style={{ fontSize: 10, color:
|
|
913
|
+
<span style={{ fontSize: 10, color: themeVars.content.primary, fontWeight: 600 }}>
|
|
914
|
+
Shared
|
|
915
|
+
</span>
|
|
918
916
|
<span
|
|
919
917
|
style={{
|
|
920
918
|
fontSize: 10,
|
|
921
|
-
color:
|
|
919
|
+
color: themeVars.accent.default,
|
|
922
920
|
flex: 1,
|
|
923
921
|
overflow: 'hidden',
|
|
924
922
|
textOverflow: 'ellipsis',
|
|
@@ -928,9 +926,10 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
928
926
|
>
|
|
929
927
|
{entity.materialRef.split('/').pop()?.replace('.mat.json', '')}
|
|
930
928
|
</span>
|
|
931
|
-
<
|
|
929
|
+
<Button
|
|
932
930
|
type="button"
|
|
933
|
-
|
|
931
|
+
variant="outline"
|
|
932
|
+
size="compact"
|
|
934
933
|
onClick={() => {
|
|
935
934
|
window.dispatchEvent(
|
|
936
935
|
new CustomEvent('editor:open-asset', { detail: { path: entity.materialRef } }),
|
|
@@ -938,35 +937,28 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
938
937
|
}}
|
|
939
938
|
>
|
|
940
939
|
Open
|
|
941
|
-
</
|
|
942
|
-
<
|
|
940
|
+
</Button>
|
|
941
|
+
<Button type="button" size="compact" onClick={handleMakeUnique}>
|
|
943
942
|
Make Unique
|
|
944
|
-
</
|
|
943
|
+
</Button>
|
|
945
944
|
</div>
|
|
946
945
|
)}
|
|
947
946
|
|
|
948
947
|
{/* Type */}
|
|
949
948
|
<div>
|
|
950
949
|
<div style={labelStyle}>Type</div>
|
|
951
|
-
<
|
|
950
|
+
<Select
|
|
951
|
+
className="vgai-select"
|
|
952
952
|
value={mat.type}
|
|
953
953
|
onChange={(e) => update({ type: e.target.value as SceneMaterial['type'] })}
|
|
954
|
-
style={{
|
|
955
|
-
width: '100%',
|
|
956
|
-
background: '#1e1e1e',
|
|
957
|
-
color: '#c5c8ce',
|
|
958
|
-
border: '1px solid #333',
|
|
959
|
-
borderRadius: 2,
|
|
960
|
-
padding: '3px 4px',
|
|
961
|
-
fontSize: 12,
|
|
962
|
-
}}
|
|
954
|
+
style={{ width: '100%' }}
|
|
963
955
|
>
|
|
964
956
|
{matTypes.map((t) => (
|
|
965
957
|
<option key={t} value={t}>
|
|
966
958
|
{t}
|
|
967
959
|
</option>
|
|
968
960
|
))}
|
|
969
|
-
</
|
|
961
|
+
</Select>
|
|
970
962
|
</div>
|
|
971
963
|
|
|
972
964
|
{/* Color */}
|
|
@@ -1000,12 +992,12 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
1000
992
|
</div>
|
|
1001
993
|
<div>
|
|
1002
994
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
1003
|
-
<
|
|
1004
|
-
|
|
995
|
+
<Checkbox
|
|
996
|
+
className="vgai-checkbox"
|
|
1005
997
|
checked={mat.flatShading ?? false}
|
|
1006
998
|
onChange={(e) => update({ flatShading: e.target.checked })}
|
|
1007
999
|
/>
|
|
1008
|
-
<span style={{ fontSize: 11, color:
|
|
1000
|
+
<span style={{ fontSize: 11, color: themeVars.content.primary }}>Flat Shading</span>
|
|
1009
1001
|
</div>
|
|
1010
1002
|
</div>
|
|
1011
1003
|
</>
|
|
@@ -1045,12 +1037,12 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
1045
1037
|
</div>
|
|
1046
1038
|
<div>
|
|
1047
1039
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
|
|
1048
|
-
<
|
|
1049
|
-
|
|
1040
|
+
<Checkbox
|
|
1041
|
+
className="vgai-checkbox"
|
|
1050
1042
|
checked={mat.transparent ?? false}
|
|
1051
1043
|
onChange={(e) => update({ transparent: e.target.checked })}
|
|
1052
1044
|
/>
|
|
1053
|
-
<span style={{ fontSize: 11, color:
|
|
1045
|
+
<span style={{ fontSize: 11, color: themeVars.content.primary }}>Transparent</span>
|
|
1054
1046
|
</div>
|
|
1055
1047
|
</div>
|
|
1056
1048
|
|
|
@@ -1059,39 +1051,22 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
1059
1051
|
<Tooltip text="Which faces to render" position="right">
|
|
1060
1052
|
<div style={labelStyle}>Side</div>
|
|
1061
1053
|
</Tooltip>
|
|
1062
|
-
<
|
|
1054
|
+
<Select
|
|
1055
|
+
className="vgai-select"
|
|
1063
1056
|
value={mat.side ?? 'front'}
|
|
1064
1057
|
onChange={(e) => setField('side', e.target.value)}
|
|
1065
|
-
style={{
|
|
1066
|
-
width: '100%',
|
|
1067
|
-
background: '#1e1e1e',
|
|
1068
|
-
color: '#c5c8ce',
|
|
1069
|
-
border: '1px solid #333',
|
|
1070
|
-
borderRadius: 2,
|
|
1071
|
-
padding: '3px 4px',
|
|
1072
|
-
fontSize: 12,
|
|
1073
|
-
}}
|
|
1058
|
+
style={{ width: '100%' }}
|
|
1074
1059
|
>
|
|
1075
1060
|
{sideOptions.map((s) => (
|
|
1076
1061
|
<option key={s} value={s}>
|
|
1077
1062
|
{s}
|
|
1078
1063
|
</option>
|
|
1079
1064
|
))}
|
|
1080
|
-
</
|
|
1065
|
+
</Select>
|
|
1081
1066
|
</div>
|
|
1082
1067
|
|
|
1083
1068
|
{/* Texture Maps */}
|
|
1084
|
-
<div
|
|
1085
|
-
style={{
|
|
1086
|
-
fontSize: 10,
|
|
1087
|
-
color: '#8c8c8c',
|
|
1088
|
-
fontWeight: 700,
|
|
1089
|
-
marginTop: 4,
|
|
1090
|
-
textTransform: 'uppercase',
|
|
1091
|
-
}}
|
|
1092
|
-
>
|
|
1093
|
-
Textures
|
|
1094
|
-
</div>
|
|
1069
|
+
<div style={{ ...groupLabelStyle, marginTop: 4 }}>Textures</div>
|
|
1095
1070
|
<div>
|
|
1096
1071
|
<div style={labelStyle}>Map</div>
|
|
1097
1072
|
<TextureInput value={mat.map} onChange={(v) => setField('map', v)} />
|
|
@@ -1136,9 +1111,8 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
1136
1111
|
|
|
1137
1112
|
{/* Save as / Assign material */}
|
|
1138
1113
|
{!hasRef && !savingAs && (
|
|
1139
|
-
<
|
|
1114
|
+
<Button
|
|
1140
1115
|
type="button"
|
|
1141
|
-
style={btnStyle}
|
|
1142
1116
|
onClick={() => {
|
|
1143
1117
|
setSavingAs(true);
|
|
1144
1118
|
setSavePath(`materials/${defaultName}.mat.json`);
|
|
@@ -1146,12 +1120,12 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
1146
1120
|
}}
|
|
1147
1121
|
>
|
|
1148
1122
|
Save as Material...
|
|
1149
|
-
</
|
|
1123
|
+
</Button>
|
|
1150
1124
|
)}
|
|
1151
1125
|
{!hasRef && savingAs && (
|
|
1152
1126
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
1153
1127
|
<div style={labelStyle}>Save path (relative to public/)</div>
|
|
1154
|
-
<
|
|
1128
|
+
<TextInput
|
|
1155
1129
|
ref={saveInputRef}
|
|
1156
1130
|
value={savePath}
|
|
1157
1131
|
onChange={(e) => setSavePath(e.target.value)}
|
|
@@ -1159,27 +1133,16 @@ export function MaterialSection({ entities, ids }: SectionProps) {
|
|
|
1159
1133
|
if (e.key === 'Enter') handleSaveAsMaterial();
|
|
1160
1134
|
if (e.key === 'Escape') setSavingAs(false);
|
|
1161
1135
|
}}
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
background: '#1e1e1e',
|
|
1165
|
-
color: '#c5c8ce',
|
|
1166
|
-
border: '1px solid #5b9bd5',
|
|
1167
|
-
borderRadius: 2,
|
|
1168
|
-
padding: '3px 4px',
|
|
1169
|
-
fontSize: 11,
|
|
1170
|
-
}}
|
|
1136
|
+
className="vgai-input"
|
|
1137
|
+
style={{ width: '100%', borderColor: themeVars.accent.default }}
|
|
1171
1138
|
/>
|
|
1172
1139
|
<div style={{ display: 'flex', gap: 4 }}>
|
|
1173
|
-
<button
|
|
1174
|
-
type="button"
|
|
1175
|
-
style={{ ...btnStyle, color: '#60a5fa' }}
|
|
1176
|
-
onClick={handleSaveAsMaterial}
|
|
1177
|
-
>
|
|
1140
|
+
<Button type="button" variant="primary" size="compact" onClick={handleSaveAsMaterial}>
|
|
1178
1141
|
Save
|
|
1179
|
-
</
|
|
1180
|
-
<
|
|
1142
|
+
</Button>
|
|
1143
|
+
<Button type="button" onClick={() => setSavingAs(false)}>
|
|
1181
1144
|
Cancel
|
|
1182
|
-
</
|
|
1145
|
+
</Button>
|
|
1183
1146
|
</div>
|
|
1184
1147
|
</div>
|
|
1185
1148
|
)}
|