@vgai/editor 0.2.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/LICENSE +661 -0
- package/README.md +35 -0
- package/dist/a/b/c/test-nested.json +1 -0
- package/dist/assets/CCDIKSolver-Dz-ysxZF.js +1 -0
- package/dist/assets/SelectionBox-BXsv_6aH.js +1 -0
- package/dist/assets/browser-project-scripts-DOru4L1x.js +2 -0
- package/dist/assets/browserAll-CEkWYlFk.js +1 -0
- package/dist/assets/collision-world-DniMB0qq.glb +0 -0
- package/dist/assets/create-runtime-DYIWr3va.js +1 -0
- package/dist/assets/data-asset-Bb9sIM7i.js +5 -0
- package/dist/assets/esbuild-BHljloGq.wasm +0 -0
- package/dist/assets/fake-three-BMTQ9rl_.js +1 -0
- package/dist/assets/game-8SDZPPgH.js +1 -0
- package/dist/assets/game-BI111o5f.js +10 -0
- package/dist/assets/game-CevorxyV.js +1 -0
- package/dist/assets/game-Di1H0gFj.js +1 -0
- package/dist/assets/game-Di7XlywD.js +1 -0
- package/dist/assets/game-DjnCaw8R.js +1 -0
- package/dist/assets/game-Q9A0aXSV.js +1 -0
- package/dist/assets/game-pt_1lQLv.js +1 -0
- package/dist/assets/game-source-CvidN7AB.js +1 -0
- package/dist/assets/game-xsOho_wg.js +83 -0
- package/dist/assets/index-Bp5cecD6.js +12 -0
- package/dist/assets/index-CPVV6pjw.js +1 -0
- package/dist/assets/index-CpOnYyeD.js +213 -0
- package/dist/assets/index-Cs8xwv3e.js +1 -0
- package/dist/assets/index-DL7RcQ0n.js +27 -0
- package/dist/assets/index-Dr8H_6Rl.js +1 -0
- package/dist/assets/index-_bCaipUk.js +13650 -0
- package/dist/assets/ingest-siblings-Dz8eEqrV.js +1 -0
- package/dist/assets/mount-manifest-Bhk0ohsl.js +1 -0
- package/dist/assets/recast-navigation.wasm-compat-CvP4UGK6.js +1 -0
- package/dist/assets/scene-query-BivAHhJu.js +1 -0
- package/dist/assets/stats.module--VATS4Kh.js +1 -0
- package/dist/assets/webworkerAll-BLrH0F6F.js +1 -0
- package/dist/assets/xstate-animation-binding-1NGLmw6y.js +1 -0
- package/dist/assets/xstate.esm-BgUD33nl.js +3 -0
- package/dist/index.html +37 -0
- package/dist/ingest/racing-game/UPSTREAM.md +68 -0
- package/dist/ingest/racing-game/a/Inter-Black.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Black.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-BlackItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-BlackItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Bold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Bold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-BoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-BoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLight.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLight.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLightItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLightItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Italic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Italic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Light.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Light.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-LightItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-LightItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Medium.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Medium.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-MediumItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-MediumItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Regular.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Regular.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Thin.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Thin.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ThinItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ThinItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-italic.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-roman.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/index.css +1 -0
- package/dist/ingest/racing-game/images/bronze.png +0 -0
- package/dist/ingest/racing-game/images/gold.png +0 -0
- package/dist/ingest/racing-game/images/silver.png +0 -0
- package/dist/ingest/racing-game/index.html +15 -0
- package/dist/ingest/racing-game/models/chassis-draco.glb +0 -0
- package/dist/ingest/racing-game/models/track-draco.glb +0 -0
- package/dist/ingest/racing-game/models/wheel-draco.glb +0 -0
- package/dist/ingest/racing-game/rg-entry.js +1 -0
- package/dist/ingest/racing-game/sounds/accelerate.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/boost.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/crash.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/engine.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/honk.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/tire-brake.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/train.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/water.mp3 +0 -0
- package/dist/ingest/racing-game/textures/cursor.svg +3 -0
- package/dist/ingest/racing-game/textures/dikhololo_night_1k.hdr +0 -0
- package/dist/ingest/racing-game/textures/heightmap_1024.png +0 -0
- package/dist/ingest/racing-game/textures/mask.svg +11 -0
- package/dist/ingest/racing-game/textures/no_sound.png +0 -0
- package/dist/ingest/racing-game/three-r139.module.js +50617 -0
- package/dist/ingest/racing-game/vendor.js +179 -0
- package/dist/ingest/racing-game/vgai.game.json +20 -0
- package/dist/ingest/simcity/UPSTREAM.md +65 -0
- package/dist/ingest/simcity/favicon.ico +0 -0
- package/dist/ingest/simcity/fonts/Bebas-Regular.otf +0 -0
- package/dist/ingest/simcity/fonts/Digitalt.otf +0 -0
- package/dist/ingest/simcity/fonts/Stanberry.ttf +0 -0
- package/dist/ingest/simcity/icons/bulldozer-color.png +0 -0
- package/dist/ingest/simcity/icons/bulldozer.png +0 -0
- package/dist/ingest/simcity/icons/calendar.png +0 -0
- package/dist/ingest/simcity/icons/factory-color.png +0 -0
- package/dist/ingest/simcity/icons/factory.png +0 -0
- package/dist/ingest/simcity/icons/house-color.png +0 -0
- package/dist/ingest/simcity/icons/house.png +0 -0
- package/dist/ingest/simcity/icons/job.png +0 -0
- package/dist/ingest/simcity/icons/office.png +0 -0
- package/dist/ingest/simcity/icons/pause-color.png +0 -0
- package/dist/ingest/simcity/icons/pause.png +0 -0
- package/dist/ingest/simcity/icons/person.png +0 -0
- package/dist/ingest/simcity/icons/play-color.png +0 -0
- package/dist/ingest/simcity/icons/play.png +0 -0
- package/dist/ingest/simcity/icons/power-color.png +0 -0
- package/dist/ingest/simcity/icons/power-line-color.png +0 -0
- package/dist/ingest/simcity/icons/power.png +0 -0
- package/dist/ingest/simcity/icons/road-color.png +0 -0
- package/dist/ingest/simcity/icons/road.png +0 -0
- package/dist/ingest/simcity/icons/select-color.png +0 -0
- package/dist/ingest/simcity/icons/select.png +0 -0
- package/dist/ingest/simcity/icons/store-color.png +0 -0
- package/dist/ingest/simcity/index.html +94 -0
- package/dist/ingest/simcity/index.js +58 -0
- package/dist/ingest/simcity/main.css +233 -0
- package/dist/ingest/simcity/models/armored-truck.glb +0 -0
- package/dist/ingest/simcity/models/building-block-4floor-corner.glb +0 -0
- package/dist/ingest/simcity/models/building-block-4floor-short.glb +0 -0
- package/dist/ingest/simcity/models/building-block-5floor.glb +0 -0
- package/dist/ingest/simcity/models/building-burger-joint.glb +0 -0
- package/dist/ingest/simcity/models/building-cafe.glb +0 -0
- package/dist/ingest/simcity/models/building-casino.glb +0 -0
- package/dist/ingest/simcity/models/building-cinema.glb +0 -0
- package/dist/ingest/simcity/models/building-house-block-big.glb +0 -0
- package/dist/ingest/simcity/models/building-house-family-large.glb +0 -0
- package/dist/ingest/simcity/models/building-house-family-small.glb +0 -0
- package/dist/ingest/simcity/models/building-office-balcony.glb +0 -0
- package/dist/ingest/simcity/models/building-office-big.glb +0 -0
- package/dist/ingest/simcity/models/building-office-pyramid.glb +0 -0
- package/dist/ingest/simcity/models/building-office-tall.glb +0 -0
- package/dist/ingest/simcity/models/building-office.glb +0 -0
- package/dist/ingest/simcity/models/building-restaurant.glb +0 -0
- package/dist/ingest/simcity/models/building-skyscraper.glb +0 -0
- package/dist/ingest/simcity/models/car-ambulance-pickup.glb +0 -0
- package/dist/ingest/simcity/models/car-baywatch.glb +0 -0
- package/dist/ingest/simcity/models/car-hippie-van.glb +0 -0
- package/dist/ingest/simcity/models/car-passenger-race.glb +0 -0
- package/dist/ingest/simcity/models/car-passenger.glb +0 -0
- package/dist/ingest/simcity/models/car-police.glb +0 -0
- package/dist/ingest/simcity/models/car-taxi.glb +0 -0
- package/dist/ingest/simcity/models/car-tow-truck.glb +0 -0
- package/dist/ingest/simcity/models/car-truck-dump.glb +0 -0
- package/dist/ingest/simcity/models/car-veteran.glb +0 -0
- package/dist/ingest/simcity/models/construction-small.glb +0 -0
- package/dist/ingest/simcity/models/data-center.glb +0 -0
- package/dist/ingest/simcity/models/industry-factory-old.glb +0 -0
- package/dist/ingest/simcity/models/industry-factory.glb +0 -0
- package/dist/ingest/simcity/models/industry-refinery.glb +0 -0
- package/dist/ingest/simcity/models/industry-warehouse.glb +0 -0
- package/dist/ingest/simcity/models/power_line_pole_modified.glb +0 -0
- package/dist/ingest/simcity/models/tile-plain_grass.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-curve.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-end.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-intersection-t.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-intersection.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-straight.glb +0 -0
- package/dist/ingest/simcity/models/truck.glb +0 -0
- package/dist/ingest/simcity/statusIcons/no-power.png +0 -0
- package/dist/ingest/simcity/statusIcons/no-road-access.png +0 -0
- package/dist/ingest/simcity/textures/base.png +0 -0
- package/dist/ingest/simcity/textures/grid.png +0 -0
- package/dist/ingest/simcity/textures/specular.png +0 -0
- package/dist/ingest/simcity/three-r155.module.js +51466 -0
- package/dist/ingest/simcity/vgai.game.json +20 -0
- package/dist/ingest/tanks/UPSTREAM.md +69 -0
- package/dist/ingest/tanks/index.html +214 -0
- package/dist/ingest/tanks/models/pixelTank.fbx +0 -0
- package/dist/ingest/tanks/tanks-entry.js +92 -0
- package/dist/ingest/tanks/three-r170.module.js +54571 -0
- package/dist/ingest/tanks/vgai.game.json +20 -0
- package/dist/inputmaps/default.inputmap.json +41 -0
- package/dist/jsm/libs/draco/gltf/draco_decoder.js +33 -0
- package/dist/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/dist/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/dist/scenes/untitled.vscn.json +29 -0
- package/dist/textures/waternormals.jpg +0 -0
- package/dist-server/packaged.mjs +18155 -0
- package/package.json +36 -0
- package/server/asset-library-routes.ts +833 -0
- package/server/canonical-path.ts +50 -0
- package/server/cloud-asset-catalog.ts +101 -0
- package/server/dev.ts +350 -0
- package/server/editor-server.ts +1537 -0
- package/server/editor-sse.ts +73 -0
- package/server/game-globals-shadow.ts +58 -0
- package/server/local-asset-catalog.ts +163 -0
- package/server/packaged.ts +571 -0
- package/server/prod.ts +75 -0
- package/server/project-optimize-deps-entries.ts +149 -0
- package/server/project-view.ts +65 -0
- package/server/server-utils.ts +430 -0
- package/server/session-registry.ts +93 -0
- package/src/EditorContext.tsx +87 -0
- package/src/achieved-tier.ts +126 -0
- package/src/action-registry.ts +268 -0
- package/src/adapter-resolver.ts +1858 -0
- package/src/asset-events.ts +100 -0
- package/src/authoring/active-adapter.ts +98 -0
- package/src/authoring/active-systems.ts +50 -0
- package/src/authoring/boundary-authoring-adapter.ts +178 -0
- package/src/authoring/composite-authoring-adapter.ts +891 -0
- package/src/authoring/design-time-layers.ts +776 -0
- package/src/authoring/edit-mode-authoring.ts +643 -0
- package/src/authoring/embed-only-adapter.ts +57 -0
- package/src/authoring/ephemeral-persistence.ts +26 -0
- package/src/authoring/eyedropper-session.ts +69 -0
- package/src/authoring/first-party-hierarchy-menu.ts +74 -0
- package/src/authoring/first-party-inspector/AddSectionMenu.tsx +118 -0
- package/src/authoring/first-party-inspector/EnvironmentSection.tsx +550 -0
- package/src/authoring/first-party-inspector/HeaderSection.tsx +329 -0
- package/src/authoring/first-party-inspector/is-first-party-selection.ts +44 -0
- package/src/authoring/first-party-inspector/register.tsx +108 -0
- package/src/authoring/ingest-authoring-adapter.ts +475 -0
- package/src/authoring/ingest-capture.ts +94 -0
- package/src/authoring/ingest-game-adapter.ts +291 -0
- package/src/authoring/ingest-iframe-adapter.ts +38 -0
- package/src/authoring/ingest-iframe-reachable-adapter.ts +401 -0
- package/src/authoring/ingest-overlay.ts +193 -0
- package/src/authoring/layered-pick.ts +87 -0
- package/src/authoring/mount-failure-report.ts +112 -0
- package/src/authoring/overlay-report.ts +52 -0
- package/src/authoring/project-scenes.ts +111 -0
- package/src/authoring/react-dom-authoring-adapter.ts +795 -0
- package/src/authoring/react-inspector-section.tsx +1041 -0
- package/src/authoring/react-world-authoring-adapter.ts +2400 -0
- package/src/authoring/root-activation.ts +61 -0
- package/src/authoring/scene-ui-layer.ts +485 -0
- package/src/authoring/story-overlay.ts +48 -0
- package/src/authoring/ui-authoring-adapter.ts +325 -0
- package/src/authoring/ui-hierarchy-menu.ts +40 -0
- package/src/authoring/ui-inspector-sections.tsx +156 -0
- package/src/authoring/undo-timeline.ts +145 -0
- package/src/authoring/vgai-scene-authoring-adapter.ts +746 -0
- package/src/authoring/viewport-pick-context.ts +31 -0
- package/src/authoring/viewport-raycast.ts +80 -0
- package/src/authoring/world-overlay.ts +76 -0
- package/src/authoring/world-pan-state.ts +115 -0
- package/src/authoring/world-session-state.ts +102 -0
- package/src/authoring/world2d-authoring-adapter.ts +313 -0
- package/src/browser-external-watch.ts +98 -0
- package/src/browser-play-entry.ts +112 -0
- package/src/browser-project-scripts.ts +112 -0
- package/src/browser-transpile.ts +246 -0
- package/src/browser-watch-reload.ts +100 -0
- package/src/command-listener.ts +326 -0
- package/src/components/AlignToolbar.tsx +189 -0
- package/src/components/AppRoot.tsx +73 -0
- package/src/components/AssetBrowser.tsx +502 -0
- package/src/components/BottomPanel.tsx +326 -0
- package/src/components/BuildPanel.tsx +455 -0
- package/src/components/CameraInfo.tsx +56 -0
- package/src/components/CommandPalette.tsx +265 -0
- package/src/components/ConsolePanel.tsx +272 -0
- package/src/components/DataPanel.tsx +1268 -0
- package/src/components/DefaultEditorLayout.tsx +509 -0
- package/src/components/FolderTree.tsx +179 -0
- package/src/components/GameHierarchy.tsx +1349 -0
- package/src/components/Inspector.tsx +671 -0
- package/src/components/InspectorToolSection.tsx +74 -0
- package/src/components/MountFailureBanner.tsx +110 -0
- package/src/components/NetworkSection.tsx +109 -0
- package/src/components/OnlineAssetBrowser.tsx +448 -0
- package/src/components/OverlayReportBanner.tsx +122 -0
- package/src/components/PlayBar.tsx +356 -0
- package/src/components/PrefabSaveDialog.tsx +201 -0
- package/src/components/ProjectHeader.tsx +174 -0
- package/src/components/ProjectScreen.tsx +1004 -0
- package/src/components/RightPanel.tsx +166 -0
- package/src/components/RootActivateDialog.tsx +105 -0
- package/src/components/SaveDialog.tsx +197 -0
- package/src/components/SaveStatus.tsx +69 -0
- package/src/components/StatsOverlay.tsx +35 -0
- package/src/components/ToolHost.tsx +80 -0
- package/src/components/Toolbar.tsx +307 -0
- package/src/components/ViewportOverlay.tsx +234 -0
- package/src/components/ViewportPanel.tsx +369 -0
- package/src/components/WorldContextMenu.tsx +257 -0
- package/src/components/WorldSelectionOverlay.tsx +2003 -0
- package/src/components/WorldTextEditor.tsx +86 -0
- package/src/components/asset-viewers/AssetViewer.tsx +38 -0
- package/src/components/asset-viewers/AudioViewer.tsx +149 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +77 -0
- package/src/components/asset-viewers/ImageViewer.tsx +65 -0
- package/src/components/asset-viewers/InputMapViewer.tsx +206 -0
- package/src/components/asset-viewers/ModelViewer.tsx +180 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +236 -0
- package/src/components/data-csv.ts +301 -0
- package/src/components/entity-name-commit.ts +18 -0
- package/src/components/inspector-property-grouping.ts +65 -0
- package/src/components/inspector-widgets/AlignmentGrid.tsx +188 -0
- package/src/components/inspector-widgets/BorderEditor.tsx +305 -0
- package/src/components/inspector-widgets/ColorPicker.tsx +548 -0
- package/src/components/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/components/inspector-widgets/FontPicker.tsx +196 -0
- package/src/components/inspector-widgets/GradientEditor.tsx +277 -0
- package/src/components/inspector-widgets/ScrubbableInput.tsx +152 -0
- package/src/components/inspector-widgets/ShadowEditor.tsx +332 -0
- package/src/components/inspector-widgets/color-utils.ts +202 -0
- package/src/components/inspector-widgets/gallery-main.tsx +167 -0
- package/src/components/inspector-widgets/index.ts +22 -0
- package/src/components/inspector-widgets/shared.tsx +135 -0
- package/src/components/inspectors/AnimationSection.tsx +143 -0
- package/src/components/inspectors/AudioSection.tsx +215 -0
- package/src/components/inspectors/BoneAttachmentSection.tsx +82 -0
- package/src/components/inspectors/CameraSection.tsx +105 -0
- package/src/components/inspectors/ComponentsSection.tsx +358 -0
- package/src/components/inspectors/JointsSection.tsx +255 -0
- package/src/components/inspectors/LightSection.tsx +116 -0
- package/src/components/inspectors/MaterialSection.tsx +1189 -0
- package/src/components/inspectors/MeshSection.tsx +99 -0
- package/src/components/inspectors/NavigationSection.tsx +58 -0
- package/src/components/inspectors/ParticleSection.tsx +681 -0
- package/src/components/inspectors/PhysicsSection.tsx +326 -0
- package/src/components/inspectors/PostProcessingSection.tsx +1290 -0
- package/src/components/inspectors/RenderingSection.tsx +109 -0
- package/src/components/inspectors/ShadowSection.tsx +84 -0
- package/src/components/inspectors/SplineSection.tsx +191 -0
- package/src/components/inspectors/TransformSection.tsx +191 -0
- package/src/components/inspectors/json-schema-fields.ts +281 -0
- package/src/components/inspectors/multi-edit-utils.ts +49 -0
- package/src/components/inspectors/zod-fields.ts +184 -0
- package/src/components/primitives/ColorInput.tsx +109 -0
- package/src/components/primitives/JsonInput.tsx +98 -0
- package/src/components/primitives/NumberInput.tsx +164 -0
- package/src/components/primitives/Panel.tsx +68 -0
- package/src/components/primitives/SectionHeader.tsx +45 -0
- package/src/components/primitives/Tooltip.tsx +82 -0
- package/src/components/primitives/Vec3Input.tsx +62 -0
- package/src/components/world-overlay-gestures.ts +1438 -0
- package/src/doctor/data-checks.ts +285 -0
- package/src/doctor/report.ts +386 -0
- package/src/editor-api.ts +700 -0
- package/src/editor-console.ts +194 -0
- package/src/editor-hotkeys.ts +441 -0
- package/src/editor-layers.ts +2 -0
- package/src/editor-mode.ts +28 -0
- package/src/editor-store.ts +2225 -0
- package/src/editor-viewport.ts +1924 -0
- package/src/entity-factory.ts +221 -0
- package/src/game-globals-prelude.ts +27 -0
- package/src/gated-globals.ts +131 -0
- package/src/generated/setup-by-example.generated.ts +53 -0
- package/src/gizmo-registry.ts +608 -0
- package/src/handle-system.ts +221 -0
- package/src/hierarchy-menu-registry.ts +70 -0
- package/src/hierarchy-rows.ts +73 -0
- package/src/hosted-example.ts +160 -0
- package/src/hotkeys.ts +142 -0
- package/src/ingest/discovery-react.ts +132 -0
- package/src/ingest/discovery.ts +205 -0
- package/src/ingest/discovery2d.ts +204 -0
- package/src/ingest/esm-entry-resolution.ts +102 -0
- package/src/ingest/games/bloom-composer/game.js +99 -0
- package/src/ingest/games/bloom-composer/vgai.game.json +21 -0
- package/src/ingest/games/embed-bundle/embed.html +10 -0
- package/src/ingest/games/embed-bundle/vgai.game.json +21 -0
- package/src/ingest/games/games-fps/assets/collision-world.glb +0 -0
- package/src/ingest/games/games-fps/game.js +479 -0
- package/src/ingest/games/games-fps/vgai.game.json +24 -0
- package/src/ingest/games/iframe-reachable/game-source.js +58 -0
- package/src/ingest/games/iframe-reachable/vgai.game.json +21 -0
- package/src/ingest/games/interactive-cubes/game.js +139 -0
- package/src/ingest/games/interactive-cubes/vgai.game.json +21 -0
- package/src/ingest/games/mismatched-three/fake-three.js +38 -0
- package/src/ingest/games/mismatched-three/game.js +10 -0
- package/src/ingest/games/mismatched-three/vgai.game.json +22 -0
- package/src/ingest/games/own-three-bundled/game.js +43 -0
- package/src/ingest/games/own-three-bundled/vgai.game.json +21 -0
- package/src/ingest/games/pointerlock-maze/game.js +288 -0
- package/src/ingest/games/pointerlock-maze/vgai.game.json +22 -0
- package/src/ingest/games-2d/_fixtures/first-party-scene.scn2d.json +124 -0
- package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +25 -0
- package/src/ingest/games-2d/bunnymark/game.ts +88 -0
- package/src/ingest/games-2d/bunnymark/vgai.game.json +21 -0
- package/src/ingest/games-2d/flappy/game.ts +148 -0
- package/src/ingest/games-2d/flappy/vgai.game.json +21 -0
- package/src/ingest/games-2d/flappy-pixi/vgai.game.json +25 -0
- package/src/ingest/games-2d/puzzling-potions/vgai.game.json +25 -0
- package/src/ingest/games-2d/tilemap-camera/game.ts +115 -0
- package/src/ingest/games-2d/tilemap-camera/vgai.game.json +21 -0
- package/src/ingest/games-react/react-rpg/entry.tsx +185 -0
- package/src/ingest/games-react/react-rpg/shims.d.ts +26 -0
- package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +129 -0
- package/src/ingest/games-react/react-rpg/vgai.game.json +21 -0
- package/src/ingest/host-namespace-registry.ts +196 -0
- package/src/ingest/types.ts +127 -0
- package/src/ingest-hierarchy-rows.ts +207 -0
- package/src/ingest-mode.ts +2092 -0
- package/src/ingest-siblings.ts +466 -0
- package/src/initial-scene.ts +194 -0
- package/src/inspector-section-registry.ts +117 -0
- package/src/interactive-edit-scope.ts +34 -0
- package/src/main.tsx +23 -0
- package/src/manifest-project.ts +43 -0
- package/src/model-thumbnail.ts +156 -0
- package/src/module-mode.ts +513 -0
- package/src/navmesh-handler.ts +94 -0
- package/src/packaged-runtime.ts +49 -0
- package/src/play-mode.ts +1148 -0
- package/src/playground/main.ts +206 -0
- package/src/project-manager.ts +173 -0
- package/src/scene-diff.ts +112 -0
- package/src/scene-serializer.ts +144 -0
- package/src/scene-sync.ts +587 -0
- package/src/scene-ui-mode/active-scene-ui.ts +58 -0
- package/src/scene-ui-mode/scene-ui-palette-panel.tsx +152 -0
- package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +29 -0
- package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +74 -0
- package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +49 -0
- package/src/scene-ui-mode/ui-prefab-io.ts +76 -0
- package/src/script-loader.ts +143 -0
- package/src/storage/fsa-storage.ts +55 -0
- package/src/storage/handle-storage.ts +150 -0
- package/src/storage/handle-store.ts +116 -0
- package/src/storage/http-storage.ts +137 -0
- package/src/storage/index.ts +147 -0
- package/src/storage/mem-storage.ts +135 -0
- package/src/storage/opfs-storage.ts +25 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/seed.ts +106 -0
- package/src/storage/types.ts +110 -0
- package/src/tool-loader.ts +291 -0
- package/src/ui-editor/inspector.tsx +563 -0
- package/src/ui-editor/node-ops.ts +266 -0
- package/src/ui-editor/overlay.tsx +380 -0
- package/src/ui-editor/palette.tsx +114 -0
- package/src/ui-editor/react-store.ts +78 -0
- package/src/ui-editor/timeline-panel.tsx +443 -0
- package/src/ui-editor/ui-edit-store.ts +552 -0
- package/src/ui-editor/ui-prefab.ts +95 -0
- package/src/ui-source/inspect.ts +544 -0
- package/src/ui-source/oid-transform.ts +133 -0
- package/src/ui-source/source-write-backend.ts +203 -0
- package/src/ui-source/tailwind-map.ts +174 -0
- package/src/ui-source/writer.ts +1175 -0
- package/src/widgets/index.ts +73 -0
- package/template/.claude/skills/editor/SKILL.md +252 -0
- package/template/CLAUDE.md +512 -0
- package/template/LICENSE +30 -0
- package/template/emit-schemas.ts +42 -0
- package/template/index.html +17 -0
- package/template/package.json +53 -0
- package/template/project.json +9 -0
- package/template/public/audio/ambient-arena.wav +0 -0
- package/template/public/audio/ambient-music.wav +0 -0
- package/template/public/audio/ambient-nature.wav +0 -0
- package/template/public/audio/ambient-wind.wav +0 -0
- package/template/public/inputmaps/default.inputmap.json +41 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/template/public/jsm/libs/draco/gltf/draco_encoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/template/public/scenes/default.vscn.json +43 -0
- package/template/public/scenes/untitled.vscn.json +29 -0
- package/template/public/textures/waternormals.jpg +0 -0
- package/template/server/colyseus-setup.ts +85 -0
- package/template/server/main.ts +34 -0
- package/template/server/rooms/arena-room.ts +420 -0
- package/template/server/rooms/game-room.ts +162 -0
- package/template/server/rooms.ts +15 -0
- package/template/server/tsconfig.json +19 -0
- package/template/src/data/README.md +40 -0
- package/template/src/data/assets.ts +31 -0
- package/template/src/data/tuning.data.json +5 -0
- package/template/src/data/tuning.schema.json +21 -0
- package/template/src/data/tuning.schema.ts +34 -0
- package/template/src/data/tuning.ts +24 -0
- package/template/src/main.ts +157 -0
- package/template/src/scripts/components/data-spinner.ts +45 -0
- package/template/src/scripts/components/scene-camera.ts +40 -0
- package/template/src/scripts/main.ts +94 -0
- package/template/src/scripts/registry.ts +46 -0
- package/template/src/tools/README.md +14 -0
- package/template/src/tools/example.tool.tsx +91 -0
- package/template/src/tools/spin.tool.tsx +101 -0
- package/template/src/ui/Button.tsx +27 -0
- package/template/src/ui/DefaultHud.tsx +40 -0
- package/template/src/ui/KeyHint.tsx +25 -0
- package/template/src/ui/Panel.tsx +52 -0
- package/template/src/ui/RebindPanel.tsx +129 -0
- package/template/src/ui/Slider.tsx +28 -0
- package/template/src/ui/StatusDot.tsx +22 -0
- package/template/src/ui/Toggle.tsx +19 -0
- package/template/src/ui/game-state.tsx +37 -0
- package/template/src/ui/index.ts +7 -0
- package/template/src/ui/mount-default-hud.tsx +19 -0
- package/template/src/ui/mount-ui.ts +15 -0
- package/template/tsconfig.json +36 -0
- package/template/validate-asset-content.ts +78 -0
- package/template/validate-manifest.ts +55 -0
- package/template/validate-scenes.ts +211 -0
- package/template/vgai.game.json +21 -0
- package/template/vite.config.ts +128 -0
- package/vite-plugin-example-assets.ts +60 -0
- package/vite-plugin-game-globals.ts +46 -0
- package/vite-plugin-game-static.ts +71 -0
- package/vite-plugin-project-game-static.ts +84 -0
- package/vite-plugin-react-game-static.ts +98 -0
- package/vite-plugin-react-world-provider.ts +81 -0
- package/vite-plugin-react-world-runtime.ts +76 -0
- package/vite-plugin-ui-oid.ts +561 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mount-failure report — D-W3 (docs/WAVE4-FTUE-HARDENING-DESIGN.md §D-W3,
|
|
3
|
+
* F9): every manifest world's auto-launch route degrades to exactly one
|
|
4
|
+
* `editorConsole.error` line today (§0.4 — ground truth: the console panel
|
|
5
|
+
* isn't even the default bottom tab, and the default Untitled scene is
|
|
6
|
+
* already showing by the time a manifest route fails, so a broken world
|
|
7
|
+
* mounts to what LOOKS like a normal empty project). This module is the
|
|
8
|
+
* loud, structured half of the fix: a global "last mount failure" slot every
|
|
9
|
+
* manifest-route catch block populates, that a dismissible banner
|
|
10
|
+
* (`../components/MountFailureBanner.tsx`) reads.
|
|
11
|
+
*
|
|
12
|
+
* D-V5 (docs/WAVE5-MULTIWORLD-INGEST-DESIGN.md, F24 composite): a composite
|
|
13
|
+
* manifest (one ingest world + siblings, `ingest-siblings.ts`) can fail
|
|
14
|
+
* SEVERAL worlds independently in one mount attempt (a `default-three`
|
|
15
|
+
* sibling, a throwing `default-react` sibling, …) — a single-slot "last
|
|
16
|
+
* failure wins" model would silently drop every failure but the latest, the
|
|
17
|
+
* exact F9 anti-pattern this module exists to close. This generalizes the
|
|
18
|
+
* single slot to an ORDERED LIST (`addMountFailureReport`, deduped by
|
|
19
|
+
* `worldId` — a re-attempt for the SAME world replaces that world's entry in
|
|
20
|
+
* place, keeping list order stable — and `getMountFailureReports()`), while
|
|
21
|
+
* freezing the ORIGINAL single-slot surface byte-for-byte for every existing
|
|
22
|
+
* (wave-4) call site: `setMountFailureReport(report)` still means "replace
|
|
23
|
+
* EVERYTHING with this one entry", `setMountFailureReport(null)` still means
|
|
24
|
+
* "clear everything", and `getMountFailureReport()` still returns the LAST
|
|
25
|
+
* entry (or `null`) — so no wave-4 caller or test needed to change meaning
|
|
26
|
+
* when this module gained multi-entry support.
|
|
27
|
+
*
|
|
28
|
+
* Same plain module-level-singleton shape as `./overlay-report.ts`'s
|
|
29
|
+
* "current report" slot (that file's header comment has the full rationale
|
|
30
|
+
* for why a bare get/set needs no subscribe of its own): the banner
|
|
31
|
+
* re-renders off `EditorStore.subscribe`, which `ingest-mode.ts`/
|
|
32
|
+
* `module-mode.ts` already broadcast via `store.notifyIngestEdit()` right
|
|
33
|
+
* after every successful mount — and a FAILED mount still runs inside the
|
|
34
|
+
* same routing functions that call `store.notifyIngestEdit()` on the
|
|
35
|
+
* success path, so the store is always live and subscribed-to by the time a
|
|
36
|
+
* route's catch block runs. No new broadcast channel needed.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/** One manifest world's mount failure — the exact fields the banner shows. */
|
|
40
|
+
export interface MountFailureReport {
|
|
41
|
+
/** The failing world's manifest id (`ResolvedWorldEntry.id`), or the
|
|
42
|
+
* `?ingest=<id>` URL-fallback route's discovered game/folder id. */
|
|
43
|
+
readonly worldId: string;
|
|
44
|
+
/** The world's render substrate kind (`ResolvedWorldEntry.kind`, e.g.
|
|
45
|
+
* `'threejs'`/`'pixijs'`/`'react'`) — or, for the URL-fallback route
|
|
46
|
+
* (which has no `ResolvedWorldEntry` to read a kind from), the same
|
|
47
|
+
* vocabulary inferred from which fixture glob resolved the id. */
|
|
48
|
+
readonly kind: string;
|
|
49
|
+
/** The resolved adapter identity (`ResolvedAdapter['identity']` — e.g.
|
|
50
|
+
* `'ingest-three'`/`'ingest-pixi'`/`'ingest-react'`/`'module'`). */
|
|
51
|
+
readonly identity: string;
|
|
52
|
+
/** The caught error's message — never the raw `Error` object (never
|
|
53
|
+
* fabricated; empty only if the thrown value truly stringifies empty). */
|
|
54
|
+
readonly message: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** D-V5: an ORDERED list now backs the slot (insertion order — the order
|
|
58
|
+
* worlds actually failed in, which for a composite's sibling loop is
|
|
59
|
+
* manifest order). Every existing (wave-4) accessor below is a thin view
|
|
60
|
+
* over this same array — never a second, parallel source of truth. */
|
|
61
|
+
let _reports: MountFailureReport[] = [];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* D-V5: append one world's failure, deduped by `worldId` — a re-attempt for
|
|
65
|
+
* a world that already has an entry REPLACES it in place (keeps list order
|
|
66
|
+
* stable: retrying world B in `[A, B]` yields `[A, B']`, never `[A, B]` moved
|
|
67
|
+
* to the end). The multi-entry sibling-mount surface
|
|
68
|
+
* (`MountFailureBanner`/`getMountFailureReports`) reads this.
|
|
69
|
+
*/
|
|
70
|
+
export function addMountFailureReport(report: MountFailureReport): void {
|
|
71
|
+
const index = _reports.findIndex((r) => r.worldId === report.worldId);
|
|
72
|
+
if (index === -1) {
|
|
73
|
+
_reports.push(report);
|
|
74
|
+
} else {
|
|
75
|
+
_reports[index] = report;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** D-V5: every mount failure from the current attempt, oldest first. */
|
|
80
|
+
export function getMountFailureReports(): readonly MountFailureReport[] {
|
|
81
|
+
return _reports;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* BACK-COMPAT FROZEN (D-V5): every existing (wave-4) call site's meaning is
|
|
86
|
+
* unchanged — `report` REPLACES the entire list with that one entry;
|
|
87
|
+
* `null` clears it. Composite routes that can fail more than one world use
|
|
88
|
+
* {@link addMountFailureReport} instead; single-world routes (unmodified
|
|
89
|
+
* this wave) keep calling this exactly as before.
|
|
90
|
+
*/
|
|
91
|
+
export function setMountFailureReport(report: MountFailureReport | null): void {
|
|
92
|
+
_reports = report ? [report] : [];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** BACK-COMPAT FROZEN (D-V5): the LAST entry (wave-4's "latest failure
|
|
96
|
+
* wins" semantics), or `null` when the list is empty. New callers that want
|
|
97
|
+
* every failure should read {@link getMountFailureReports} instead. */
|
|
98
|
+
export function getMountFailureReport(): MountFailureReport | null {
|
|
99
|
+
return _reports.length > 0 ? _reports[_reports.length - 1]! : null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Build a `MountFailureReport['message']` from a caught value the same way
|
|
104
|
+
* every route's existing `editorConsole.error` line already stringifies it
|
|
105
|
+
* (`` `...failed: ${err}` `` — kept byte-for-byte at each call site so the
|
|
106
|
+
* console's full trace is unchanged) — an `Error`'s own `.message` reads
|
|
107
|
+
* better in a one-line banner than its `String(err)` form (`"Error: <msg>"`),
|
|
108
|
+
* so the banner uses this instead of the console's template-literal form.
|
|
109
|
+
*/
|
|
110
|
+
export function formatMountFailureMessage(err: unknown): string {
|
|
111
|
+
return err instanceof Error ? err.message : String(err);
|
|
112
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overlay apply report — D9 (docs/DECISIONS-PENDING.md §D9): decide + surface
|
|
3
|
+
* what happens when a saved ingest overlay is reapplied onto a scene that may
|
|
4
|
+
* have moved on since the overlay was authored (a vendored game bump, or a
|
|
5
|
+
* dynamic subtree that never respawned).
|
|
6
|
+
*
|
|
7
|
+
* The report TYPE + pure build/format/log helpers moved engine-side (T3.8) —
|
|
8
|
+
* `@engine/adapter/ingest/overlay-report.ts` is now the canonical, dependency-
|
|
9
|
+
* free module (its header has the full design rationale); this file
|
|
10
|
+
* re-exports them unchanged so every existing import site here keeps working
|
|
11
|
+
* byte-for-byte, and adds the one genuinely editor-only piece: the reactive
|
|
12
|
+
* "active report" slot the ingest hierarchy's inline banner reads.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
buildOverlayApplyReport,
|
|
17
|
+
formatOverlayApplyReportMessage,
|
|
18
|
+
logOverlayApplyReport,
|
|
19
|
+
OVERLAY_REPORT_PREFIX,
|
|
20
|
+
type OverlayApplyReport,
|
|
21
|
+
overlayReportWarrants,
|
|
22
|
+
} from '@engine/adapter/ingest/overlay-report';
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
buildOverlayApplyReport,
|
|
26
|
+
formatOverlayApplyReportMessage,
|
|
27
|
+
logOverlayApplyReport,
|
|
28
|
+
OVERLAY_REPORT_PREFIX,
|
|
29
|
+
overlayReportWarrants,
|
|
30
|
+
type OverlayApplyReport,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Reactive "current report" slot for the editor's inline banner (design §5).
|
|
35
|
+
// A plain module-level singleton — same shape as `./active-systems.ts`'s
|
|
36
|
+
// `setActiveSystems`/`getActiveSystems`. The banner component re-renders off
|
|
37
|
+
// the SAME `store.notifyIngestEdit()` broadcast `ingest-mode.ts` already
|
|
38
|
+
// fires right after install, so this slot needs no separate subscribe/notify
|
|
39
|
+
// of its own.
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
let _current: OverlayApplyReport | null = null;
|
|
43
|
+
|
|
44
|
+
/** Install (or clear, with `null`) the report for the ingest session the UI banner reads. */
|
|
45
|
+
export function setActiveOverlayReport(report: OverlayApplyReport | null): void {
|
|
46
|
+
_current = report;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The active ingest session's overlay report, or `null` (no session / nothing to report). */
|
|
50
|
+
export function getActiveOverlayReport(): OverlayApplyReport | null {
|
|
51
|
+
return _current;
|
|
52
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project scene-file discovery (A4, D8 — docs/unified-world-editor/
|
|
3
|
+
* 26-unified-editor-spec.md §2 A4). Every `*.vscn.json` under the project is a
|
|
4
|
+
* potential hierarchy root; `VgaiSceneAuthoringAdapter.rootGroups` needs the
|
|
5
|
+
* full list to build its "Scenes" radio group.
|
|
6
|
+
*
|
|
7
|
+
* `RootGroupsProvider.groups()` is SYNCHRONOUS (the contract), so this module
|
|
8
|
+
* fetches the list ONCE, caches it at MODULE scope, and lets a caller register
|
|
9
|
+
* a callback to run when the async result actually lands (the adapter passes
|
|
10
|
+
* `store.notifyIngestEdit`, so the hierarchy panel re-renders once the list
|
|
11
|
+
* arrives instead of showing an empty group forever).
|
|
12
|
+
*
|
|
13
|
+
* The module-scope cache is deliberately shared, not per-adapter-instance:
|
|
14
|
+
* `active-adapter.ts` memoizes ONE bare `VgaiSceneAuthoringAdapter` per store,
|
|
15
|
+
* but `edit-mode-authoring.ts`'s composite construction builds its OWN
|
|
16
|
+
* SEPARATE `VgaiSceneAuthoringAdapter` instance for the focused world — a
|
|
17
|
+
* per-instance cache would mean two independent fetches (and, in principle,
|
|
18
|
+
* two different in-flight results racing each other) for the exact same
|
|
19
|
+
* project. A single module-scope cache means both agree, and only one fetch
|
|
20
|
+
* ever goes out per project session.
|
|
21
|
+
*
|
|
22
|
+
* Browser-mode floor: no `/__editor/*` server exists, so this recursively
|
|
23
|
+
* walks the active `StorageBackend` (OPFS/File-System-Access) instead —
|
|
24
|
+
* mirrors the server's own `findFiles` recursive walk, just through the
|
|
25
|
+
* backend-agnostic seam instead of `node:fs`.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { getEditorMode } from '../editor-mode';
|
|
29
|
+
import { getStorageBackend } from '../storage';
|
|
30
|
+
|
|
31
|
+
let cache: string[] | null = null;
|
|
32
|
+
let pending: Promise<string[]> | null = null;
|
|
33
|
+
const pendingListeners = new Set<() => void>();
|
|
34
|
+
|
|
35
|
+
/** Synchronous cached read — `[]` until the first load resolves. */
|
|
36
|
+
export function getCachedProjectScenes(): string[] {
|
|
37
|
+
return cache ?? [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Kick off (idempotently) loading the project's `*.vscn.json` list. Safe to
|
|
42
|
+
* call on every render/every `rootGroups.groups()` call: a no-op once
|
|
43
|
+
* cached, and de-dupes a fetch already in flight. `onLoaded` fires exactly
|
|
44
|
+
* once, only for a call that actually had to wait (never for an
|
|
45
|
+
* already-cached read, and never more than once per registered listener).
|
|
46
|
+
*/
|
|
47
|
+
export function ensureProjectScenesLoaded(onLoaded: () => void): void {
|
|
48
|
+
if (cache !== null) return;
|
|
49
|
+
pendingListeners.add(onLoaded);
|
|
50
|
+
if (pending) return;
|
|
51
|
+
pending = fetchProjectScenes()
|
|
52
|
+
.then((scenes) => {
|
|
53
|
+
cache = scenes;
|
|
54
|
+
return scenes;
|
|
55
|
+
})
|
|
56
|
+
.finally(() => {
|
|
57
|
+
pending = null;
|
|
58
|
+
const listeners = [...pendingListeners];
|
|
59
|
+
pendingListeners.clear();
|
|
60
|
+
for (const l of listeners) l();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Drop the cached list. Not currently wired into any production project-open
|
|
66
|
+
* path (every existing call site re-navigates the page on project switch, so
|
|
67
|
+
* the module cache always starts fresh for a new session) — exported for
|
|
68
|
+
* tests and as the correct hook for a future in-session project-switch flow.
|
|
69
|
+
*/
|
|
70
|
+
export function resetProjectScenesCache(): void {
|
|
71
|
+
cache = null;
|
|
72
|
+
pending = null;
|
|
73
|
+
pendingListeners.clear();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function fetchProjectScenes(): Promise<string[]> {
|
|
77
|
+
return getEditorMode() === 'browser' ? listFromStorageBackend() : listFromServer();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function listFromServer(): Promise<string[]> {
|
|
81
|
+
try {
|
|
82
|
+
const res = await fetch('/__editor/scenes');
|
|
83
|
+
if (!res.ok) return [];
|
|
84
|
+
const data = (await res.json()) as { scenes?: unknown };
|
|
85
|
+
return Array.isArray(data.scenes)
|
|
86
|
+
? data.scenes.filter((s): s is string => typeof s === 'string')
|
|
87
|
+
: [];
|
|
88
|
+
} catch {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function listFromStorageBackend(): Promise<string[]> {
|
|
94
|
+
const backend = getStorageBackend();
|
|
95
|
+
const results: string[] = [];
|
|
96
|
+
const walk = async (dir: string): Promise<void> => {
|
|
97
|
+
let entries: Awaited<ReturnType<typeof backend.list>>;
|
|
98
|
+
try {
|
|
99
|
+
entries = await backend.list(dir);
|
|
100
|
+
} catch {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
for (const e of entries) {
|
|
104
|
+
if (e.name.startsWith('.')) continue;
|
|
105
|
+
if (e.type === 'dir') await walk(e.path);
|
|
106
|
+
else if (e.name.endsWith('.vscn.json')) results.push(e.path);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
await walk('');
|
|
110
|
+
return results.sort();
|
|
111
|
+
}
|