@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,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editor session registry — the file-backed ledger of live editor dev servers
|
|
3
|
+
* (D12, docs/EDITOR-FIRST-DEV.md). Written by THIS package (dev.ts registers
|
|
4
|
+
* on listen, re-registers on project switch, unregisters on shutdown); read by
|
|
5
|
+
* the vgai CLI (its own light reader in packages/vgai-cli/src/editor-sessions.ts —
|
|
6
|
+
* the CLI deliberately has no editor-package dependency, so the FILE FORMAT
|
|
7
|
+
* here is the contract: keep the two in sync).
|
|
8
|
+
*
|
|
9
|
+
* Format: `~/.vgai/editor-sessions.json`, a JSON array of EditorSession.
|
|
10
|
+
* Entries are best-effort — every reader must PID-liveness-filter (a crashed
|
|
11
|
+
* server can't unregister itself), and writers sweep dead entries on write.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
|
|
18
|
+
export interface EditorSession {
|
|
19
|
+
/** Canonical project root currently open, or null when none. */
|
|
20
|
+
project: string | null;
|
|
21
|
+
port: number;
|
|
22
|
+
/** PID of the dev-server process (dev.ts's own process.pid). */
|
|
23
|
+
pid: number;
|
|
24
|
+
/** ISO timestamp of server start. */
|
|
25
|
+
startedAt: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const REGISTRY_DIR = join(homedir(), '.vgai');
|
|
29
|
+
const REGISTRY_FILE = join(REGISTRY_DIR, 'editor-sessions.json');
|
|
30
|
+
|
|
31
|
+
export function sessionRegistryPath(): string {
|
|
32
|
+
return REGISTRY_FILE;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isSession(v: unknown): v is EditorSession {
|
|
36
|
+
if (typeof v !== 'object' || v === null) return false;
|
|
37
|
+
const s = v as Record<string, unknown>;
|
|
38
|
+
return (
|
|
39
|
+
(typeof s['project'] === 'string' || s['project'] === null) &&
|
|
40
|
+
typeof s['port'] === 'number' &&
|
|
41
|
+
typeof s['pid'] === 'number' &&
|
|
42
|
+
typeof s['startedAt'] === 'string'
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function pidAlive(pid: number): boolean {
|
|
47
|
+
try {
|
|
48
|
+
process.kill(pid, 0);
|
|
49
|
+
return true;
|
|
50
|
+
} catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** All recorded sessions, unvalidated beyond shape (callers liveness-filter). */
|
|
56
|
+
export function readSessions(): EditorSession[] {
|
|
57
|
+
try {
|
|
58
|
+
const raw: unknown = JSON.parse(readFileSync(REGISTRY_FILE, 'utf8'));
|
|
59
|
+
return Array.isArray(raw) ? raw.filter(isSession) : [];
|
|
60
|
+
} catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Sessions whose server process is still alive. */
|
|
66
|
+
export function liveSessions(): EditorSession[] {
|
|
67
|
+
return readSessions().filter((s) => pidAlive(s.pid));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Record (or refresh) this process's session. Sweeps dead entries and any
|
|
72
|
+
* stale claim on the same port while it's here.
|
|
73
|
+
*/
|
|
74
|
+
export function registerSession(session: EditorSession): void {
|
|
75
|
+
try {
|
|
76
|
+
mkdirSync(REGISTRY_DIR, { recursive: true });
|
|
77
|
+
const rest = readSessions().filter(
|
|
78
|
+
(s) => s.pid !== session.pid && s.port !== session.port && pidAlive(s.pid),
|
|
79
|
+
);
|
|
80
|
+
writeFileSync(REGISTRY_FILE, `${JSON.stringify([...rest, session], null, 2)}\n`);
|
|
81
|
+
} catch {
|
|
82
|
+
// Registry is best-effort — never let bookkeeping kill the server.
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function unregisterSession(pid: number): void {
|
|
87
|
+
try {
|
|
88
|
+
const rest = readSessions().filter((s) => s.pid !== pid);
|
|
89
|
+
writeFileSync(REGISTRY_FILE, `${JSON.stringify(rest, null, 2)}\n`);
|
|
90
|
+
} catch {
|
|
91
|
+
// Best-effort (see registerSession).
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createContext, type ReactNode, Suspense, useContext, useEffect, useRef } from 'react';
|
|
2
|
+
import { connectCommandListener } from './command-listener';
|
|
3
|
+
import { EditorStore } from './editor-store';
|
|
4
|
+
import { initProject } from './initial-scene';
|
|
5
|
+
import { type InteractiveEditScope, InteractiveEditScopeContext } from './interactive-edit-scope';
|
|
6
|
+
|
|
7
|
+
export interface EditorStats {
|
|
8
|
+
fps: number;
|
|
9
|
+
frameTime: number;
|
|
10
|
+
drawCalls: number;
|
|
11
|
+
triangles: number;
|
|
12
|
+
cameraPosition: { x: number; y: number; z: number };
|
|
13
|
+
cameraTarget: { x: number; y: number; z: number };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface EditorContextValue {
|
|
17
|
+
store: EditorStore;
|
|
18
|
+
stats: EditorStats;
|
|
19
|
+
initPromise: Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const EditorContext = createContext<EditorContextValue | null>(null);
|
|
23
|
+
|
|
24
|
+
export function EditorProvider({ children }: { children: ReactNode }) {
|
|
25
|
+
const storeRef = useRef<EditorStore | null>(null);
|
|
26
|
+
if (!storeRef.current) storeRef.current = new EditorStore();
|
|
27
|
+
|
|
28
|
+
const statsRef = useRef<EditorStats | null>(null);
|
|
29
|
+
if (!statsRef.current) {
|
|
30
|
+
statsRef.current = {
|
|
31
|
+
fps: 0,
|
|
32
|
+
frameTime: 0,
|
|
33
|
+
drawCalls: 0,
|
|
34
|
+
triangles: 0,
|
|
35
|
+
cameraPosition: { x: 0, y: 0, z: 0 },
|
|
36
|
+
cameraTarget: { x: 0, y: 0, z: 0 },
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const initRef = useRef<Promise<void> | null>(null);
|
|
41
|
+
if (!initRef.current) {
|
|
42
|
+
initRef.current = initProject();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// The shallow undo-gesture seam the shared widget kit consumes instead of
|
|
46
|
+
// this (deep) context — see interactive-edit-scope.ts's doc comment (W3).
|
|
47
|
+
const editScopeRef = useRef<InteractiveEditScope | null>(null);
|
|
48
|
+
if (!editScopeRef.current) {
|
|
49
|
+
const store = storeRef.current;
|
|
50
|
+
editScopeRef.current = {
|
|
51
|
+
begin: () => store.beginInteractiveEdit(),
|
|
52
|
+
end: () => store.endInteractiveEdit(),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
return connectCommandListener(storeRef.current!);
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<EditorContext.Provider
|
|
62
|
+
value={{ store: storeRef.current, stats: statsRef.current, initPromise: initRef.current }}
|
|
63
|
+
>
|
|
64
|
+
<InteractiveEditScopeContext.Provider value={editScopeRef.current}>
|
|
65
|
+
<Suspense>{children}</Suspense>
|
|
66
|
+
</InteractiveEditScopeContext.Provider>
|
|
67
|
+
</EditorContext.Provider>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function useEditorStore(): EditorStore {
|
|
72
|
+
const ctx = useContext(EditorContext);
|
|
73
|
+
if (!ctx) throw new Error('useEditorStore must be used within <EditorProvider>');
|
|
74
|
+
return ctx.store;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function useEditorStats(): EditorStats {
|
|
78
|
+
const ctx = useContext(EditorContext);
|
|
79
|
+
if (!ctx) throw new Error('useEditorStats must be used within <EditorProvider>');
|
|
80
|
+
return ctx.stats;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function useEditorInit(): Promise<void> {
|
|
84
|
+
const ctx = useContext(EditorContext);
|
|
85
|
+
if (!ctx) throw new Error('useEditorInit must be used within <EditorProvider>');
|
|
86
|
+
return ctx.initPromise;
|
|
87
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Achieved-tier verification — T3.4 slice 1 (docs/ADAPTER-AUTHORING-DESIGN.md
|
|
3
|
+
* §1.C). A `{ module }` adapter self-certifies its `capabilities.{local,hosted}`
|
|
4
|
+
* tier at manifest-author time (the loader requires it explicitly — there is no
|
|
5
|
+
* derivable ceiling, `packages/engine/src/manifest/load.ts`'s `resolveCapabilities`).
|
|
6
|
+
* Nothing checks that self-certification against reality UNTIL NOW: this module
|
|
7
|
+
* computes the tier a `MountedGame` ACTUALLY reaches, straight from the
|
|
8
|
+
* `AuthoringAdapter` surface it returned from `mount()`, and logs a shortfall
|
|
9
|
+
* loudly (never silently) when achieved < declared.
|
|
10
|
+
*
|
|
11
|
+
* The three-band mapping (§1.C, "roughly: full authoring incl.
|
|
12
|
+
* transforms+inspector+persistence -> first-party reach; hierarchy-only ->
|
|
13
|
+
* shared-tier reach; no authoring -> opaque-embed reach") is made exact here:
|
|
14
|
+
*
|
|
15
|
+
* - no `authoring` at all -> 'opaque-embed'
|
|
16
|
+
* (docs/CAPABILITY-TIERS.md §b: "None — embed + lifecycle only ... no
|
|
17
|
+
* reachable scene to capture").
|
|
18
|
+
* - `authoring` present, but missing `transforms`, `inspector`, OR
|
|
19
|
+
* `persistence` -> 'shared'
|
|
20
|
+
* (§b: "Full — in-realm capture + editing" is `shared`'s row; a partial
|
|
21
|
+
* authoring surface still reaches in-realm editing on whatever it DOES
|
|
22
|
+
* provide, so it is not honestly opaque, but it has not earned the
|
|
23
|
+
* `first-party` floor's full round-trip either).
|
|
24
|
+
* - `authoring` with ALL of `transforms`+`inspector`+`persistence`
|
|
25
|
+
* -> 'first-party'
|
|
26
|
+
* (§b: "Full — native SceneEntity + gizmo ... .vscn is the source of
|
|
27
|
+
* truth" — a module adapter obviously has no `.vscn`, but this is the
|
|
28
|
+
* ceiling band a custom adapter can claim: full editing + full
|
|
29
|
+
* persistence route, mirrored for a non-first-party mount).
|
|
30
|
+
*
|
|
31
|
+
* `docs/achieved-tier-doc-pin.test.ts`-style coverage lives in
|
|
32
|
+
* `packages/engine/test/capability-tiers-achieved-mapping-doc-pin.test.ts`,
|
|
33
|
+
* pinning this banding's tier names + the doc's per-tier "Inspector / gizmo
|
|
34
|
+
* editing" language against this file, the same way
|
|
35
|
+
* `capability-tiers-doc-pin.test.ts` pins the ceiling table.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import type { MountedGame } from '@engine/adapter';
|
|
39
|
+
import type { Tier } from '@engine/manifest/schema';
|
|
40
|
+
|
|
41
|
+
// Deliberately NO import of `./editor-console` here: that module touches
|
|
42
|
+
// `window` unconditionally at its top level (a house rule this file must
|
|
43
|
+
// respect — `adapter-resolver.ts`, this module's first caller, is imported
|
|
44
|
+
// by headless Node/vitest suites with no `window` stub, e.g.
|
|
45
|
+
// `adapter-resolver.test.ts`/`adapter-resolver-pixi.test.ts`). This module
|
|
46
|
+
// stays a PURE computation + message-formatting library; callers that already
|
|
47
|
+
// own an `editorConsole` import (or a browser environment) do the actual
|
|
48
|
+
// logging (see `adapter-resolver.ts`'s `withAchievedTierCheck` and
|
|
49
|
+
// `ingest-mode.ts`'s embed-only retrofit).
|
|
50
|
+
|
|
51
|
+
/** The exact three achieved bands this slice's check can produce. */
|
|
52
|
+
export type AchievedTier = Extract<Tier, 'first-party' | 'shared' | 'opaque-embed'>;
|
|
53
|
+
|
|
54
|
+
/** Total order over `Tier` — same ranking as `CAPABILITY_CEILINGS`'s consumer
|
|
55
|
+
* (docs/CAPABILITY-TIERS.md §a: `first-party > shared ~= deduped >
|
|
56
|
+
* iframe-reachable > opaque-embed > unsupported`). Duplicated (not imported)
|
|
57
|
+
* because `packages/engine/src/manifest/load.ts`'s `TIER_RANK` is module-private. */
|
|
58
|
+
const TIER_RANK: Record<Tier, number> = {
|
|
59
|
+
'first-party': 5,
|
|
60
|
+
shared: 4,
|
|
61
|
+
deduped: 4,
|
|
62
|
+
'iframe-reachable': 3,
|
|
63
|
+
'opaque-embed': 2,
|
|
64
|
+
unsupported: 1,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Compute the ACHIEVED tier from a mounted game's actual `authoring` surface
|
|
69
|
+
* (§1.C's exact banding — see this file's doc comment). Pure function of the
|
|
70
|
+
* `MountedGame` shape; does not itself log — call {@link reportTierShortfall}
|
|
71
|
+
* with the result to get the structured log this slice's AC requires.
|
|
72
|
+
*/
|
|
73
|
+
export function computeAchievedTier(mounted: Pick<MountedGame, 'authoring'>): AchievedTier {
|
|
74
|
+
const { authoring } = mounted;
|
|
75
|
+
if (!authoring) return 'opaque-embed';
|
|
76
|
+
if (authoring.transforms && authoring.inspector && authoring.persistence) return 'first-party';
|
|
77
|
+
return 'shared';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Structured shortfall payload — ONE shape, greppable, used by BOTH the
|
|
82
|
+
* module-adapter achieved-tier check (adapter-resolver.ts) and the ingest
|
|
83
|
+
* embed-only degradation retrofit (ingest-mode.ts's
|
|
84
|
+
* `enterIngestModeWithGame`), per §1.C: "mirroring the ingest `embedOnly`
|
|
85
|
+
* precedent but carrying the actual enum values ... the existing embed-only
|
|
86
|
+
* fallback gains the same structured tier log." A no-op (`null`) when
|
|
87
|
+
* `achieved` is not below `declared` (over-claiming survives silently right
|
|
88
|
+
* up until it's caught — under-claiming, including exact matches, is never
|
|
89
|
+
* reported as a shortfall).
|
|
90
|
+
*/
|
|
91
|
+
export interface TierShortfallReport {
|
|
92
|
+
worldId: string;
|
|
93
|
+
declaredTier: Tier;
|
|
94
|
+
achievedTier: Tier;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Greppable prefix shared by every shortfall log line this slice produces. */
|
|
98
|
+
export const TIER_SHORTFALL_PREFIX = 'tier-shortfall';
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Compute the shortfall report (or `null` if there is none) — pure, no
|
|
102
|
+
* logging. `formatTierShortfallMessage` turns a non-null report into the ONE
|
|
103
|
+
* log-line shape; callers own the actual `editorConsole.warn(...)` call (see
|
|
104
|
+
* this file's doc comment for why the logging call isn't made HERE).
|
|
105
|
+
*/
|
|
106
|
+
export function computeTierShortfall(
|
|
107
|
+
worldId: string,
|
|
108
|
+
declared: Tier,
|
|
109
|
+
achieved: Tier,
|
|
110
|
+
): TierShortfallReport | null {
|
|
111
|
+
const achievedRank: number = TIER_RANK[achieved];
|
|
112
|
+
const declaredRank: number = TIER_RANK[declared];
|
|
113
|
+
if (achievedRank >= declaredRank) return null;
|
|
114
|
+
return { worldId, declaredTier: declared, achievedTier: achieved };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** The one shared message shape: `tier-shortfall world "<id>" declared "<X>"
|
|
118
|
+
* but only achieved "<Y>" ... tier-shortfall {"worldId":...}` (greppable on
|
|
119
|
+
* the `tier-shortfall` prefix, JSON-parseable on the trailing payload). */
|
|
120
|
+
export function formatTierShortfallMessage(report: TierShortfallReport): string {
|
|
121
|
+
return (
|
|
122
|
+
`${TIER_SHORTFALL_PREFIX} world "${report.worldId}" declared "${report.declaredTier}" but ` +
|
|
123
|
+
`only achieved "${report.achievedTier}" — mounting at the achieved tier ` +
|
|
124
|
+
`(docs/ADAPTER-AUTHORING-DESIGN.md §1.C). ${TIER_SHORTFALL_PREFIX} ${JSON.stringify(report)}`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { timelineRedo, timelineUndo } from './authoring/undo-timeline';
|
|
2
|
+
import type { EditorStore } from './editor-store';
|
|
3
|
+
|
|
4
|
+
export interface EditorAction {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
category: 'action' | 'entity' | 'asset';
|
|
8
|
+
shortcut?: string;
|
|
9
|
+
execute: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const RECENT_KEY = 'editor:recent-actions';
|
|
13
|
+
const MAX_RECENT = 10;
|
|
14
|
+
|
|
15
|
+
export function getRecentActionIds(): string[] {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(localStorage.getItem(RECENT_KEY) ?? '[]') as string[];
|
|
18
|
+
} catch {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function pushRecentAction(id: string): void {
|
|
24
|
+
const recent = getRecentActionIds().filter((r) => r !== id);
|
|
25
|
+
recent.unshift(id);
|
|
26
|
+
if (recent.length > MAX_RECENT) recent.length = MAX_RECENT;
|
|
27
|
+
localStorage.setItem(RECENT_KEY, JSON.stringify(recent));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Build the static list of editor command actions. */
|
|
31
|
+
export function buildStaticActions(store: EditorStore): EditorAction[] {
|
|
32
|
+
const isMac = navigator.platform.includes('Mac');
|
|
33
|
+
const mod = isMac ? '\u2318' : 'Ctrl+';
|
|
34
|
+
|
|
35
|
+
return [
|
|
36
|
+
{
|
|
37
|
+
id: 'editor.undo',
|
|
38
|
+
label: 'Undo',
|
|
39
|
+
category: 'action',
|
|
40
|
+
shortcut: `${mod}Z`,
|
|
41
|
+
// T3.2 slice 2: through the editor-global timeline, NOT `store.undo()`
|
|
42
|
+
// directly \u2014 same reasoning as the Ctrl+Z hotkey (docs/
|
|
43
|
+
// PERSISTENCE-PROVIDER-DESIGN.md \u00A73): whichever adapter (first-party/
|
|
44
|
+
// ingest/UI) recorded the most recent op, not always the first-party store.
|
|
45
|
+
execute: () => timelineUndo(),
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'editor.redo',
|
|
49
|
+
label: 'Redo',
|
|
50
|
+
category: 'action',
|
|
51
|
+
shortcut: `${mod}\u21E7Z`,
|
|
52
|
+
execute: () => timelineRedo(),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'editor.copy',
|
|
56
|
+
label: 'Copy',
|
|
57
|
+
category: 'action',
|
|
58
|
+
shortcut: `${mod}C`,
|
|
59
|
+
execute: () => {
|
|
60
|
+
if (store.selectedEntityIds.size > 0) store.copyEntities();
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'editor.cut',
|
|
65
|
+
label: 'Cut',
|
|
66
|
+
category: 'action',
|
|
67
|
+
shortcut: `${mod}X`,
|
|
68
|
+
execute: () => {
|
|
69
|
+
if (store.selectedEntityIds.size > 0) store.cutEntities();
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 'editor.paste',
|
|
74
|
+
label: 'Paste',
|
|
75
|
+
category: 'action',
|
|
76
|
+
shortcut: `${mod}V`,
|
|
77
|
+
execute: () => {
|
|
78
|
+
if (store.hasClipboard) store.pasteEntities();
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: 'editor.duplicate',
|
|
83
|
+
label: 'Duplicate',
|
|
84
|
+
category: 'action',
|
|
85
|
+
shortcut: `${mod}D`,
|
|
86
|
+
execute: () => {
|
|
87
|
+
for (const id of store.selectedEntityIds) store.duplicateEntity(id);
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 'editor.delete',
|
|
92
|
+
label: 'Delete Selected',
|
|
93
|
+
category: 'action',
|
|
94
|
+
shortcut: 'Del',
|
|
95
|
+
execute: () => {
|
|
96
|
+
if (store.selectedEntityIds.size > 0) store.deleteEntities([...store.selectedEntityIds]);
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 'editor.select-all',
|
|
101
|
+
label: 'Select All',
|
|
102
|
+
category: 'action',
|
|
103
|
+
shortcut: `${mod}A`,
|
|
104
|
+
execute: () => store.selectAll(),
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'editor.deselect',
|
|
108
|
+
label: 'Deselect All',
|
|
109
|
+
category: 'action',
|
|
110
|
+
shortcut: 'Esc',
|
|
111
|
+
execute: () => store.select(null),
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'mode.translate',
|
|
115
|
+
label: 'Translate Mode',
|
|
116
|
+
category: 'action',
|
|
117
|
+
shortcut: 'W',
|
|
118
|
+
execute: () => store.setTransformMode('translate'),
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: 'mode.rotate',
|
|
122
|
+
label: 'Rotate Mode',
|
|
123
|
+
category: 'action',
|
|
124
|
+
shortcut: 'E',
|
|
125
|
+
execute: () => store.setTransformMode('rotate'),
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'mode.scale',
|
|
129
|
+
label: 'Scale Mode',
|
|
130
|
+
category: 'action',
|
|
131
|
+
shortcut: 'R',
|
|
132
|
+
execute: () => store.setTransformMode('scale'),
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'mode.world',
|
|
136
|
+
label: 'World Space',
|
|
137
|
+
category: 'action',
|
|
138
|
+
execute: () => store.setTransformSpace('world'),
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: 'mode.local',
|
|
142
|
+
label: 'Local Space',
|
|
143
|
+
category: 'action',
|
|
144
|
+
execute: () => store.setTransformSpace('local'),
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
id: 'toggle.grid',
|
|
148
|
+
label: 'Toggle Grid',
|
|
149
|
+
category: 'action',
|
|
150
|
+
execute: () => store.toggleGrid(),
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: 'toggle.helpers',
|
|
154
|
+
label: 'Toggle Helpers',
|
|
155
|
+
category: 'action',
|
|
156
|
+
execute: () => store.toggleHelpers(),
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: 'toggle.stats',
|
|
160
|
+
label: 'Toggle Stats Overlay',
|
|
161
|
+
category: 'action',
|
|
162
|
+
execute: () => store.toggleStats(),
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
id: 'toggle.snap',
|
|
166
|
+
label: 'Toggle Snap',
|
|
167
|
+
category: 'action',
|
|
168
|
+
execute: () => store.toggleSnap(),
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 'toggle.surface-snap',
|
|
172
|
+
label: 'Toggle Surface Snap',
|
|
173
|
+
category: 'action',
|
|
174
|
+
execute: () => store.toggleSnapToSurface(),
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: 'shading.solid',
|
|
178
|
+
label: 'Solid Shading',
|
|
179
|
+
category: 'action',
|
|
180
|
+
execute: () => store.setShadingMode('solid'),
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: 'shading.wireframe',
|
|
184
|
+
label: 'Wireframe Shading',
|
|
185
|
+
category: 'action',
|
|
186
|
+
execute: () => store.setShadingMode('wireframe'),
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: 'shading.unlit',
|
|
190
|
+
label: 'Unlit Shading',
|
|
191
|
+
category: 'action',
|
|
192
|
+
execute: () => store.setShadingMode('unlit'),
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
id: 'view.top',
|
|
196
|
+
label: 'Top View',
|
|
197
|
+
category: 'action',
|
|
198
|
+
shortcut: 'Num7',
|
|
199
|
+
execute: () => store.setViewPreset('top'),
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: 'view.front',
|
|
203
|
+
label: 'Front View',
|
|
204
|
+
category: 'action',
|
|
205
|
+
shortcut: 'Num1',
|
|
206
|
+
execute: () => store.setViewPreset('front'),
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
id: 'view.right',
|
|
210
|
+
label: 'Right View',
|
|
211
|
+
category: 'action',
|
|
212
|
+
shortcut: 'Num3',
|
|
213
|
+
execute: () => store.setViewPreset('right'),
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
id: 'view.perspective',
|
|
217
|
+
label: 'Perspective View',
|
|
218
|
+
category: 'action',
|
|
219
|
+
shortcut: 'Num5',
|
|
220
|
+
execute: () => store.setViewPreset('perspective'),
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: 'focus.selected',
|
|
224
|
+
label: 'Focus Selected',
|
|
225
|
+
category: 'action',
|
|
226
|
+
shortcut: 'F',
|
|
227
|
+
execute: () => store.focusOnSelection(),
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
id: 'toggle.console',
|
|
231
|
+
label: 'Toggle Console',
|
|
232
|
+
category: 'action',
|
|
233
|
+
shortcut: '`',
|
|
234
|
+
execute: () => {
|
|
235
|
+
window.dispatchEvent(new CustomEvent('editor:toggle-console'));
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
id: 'build.web',
|
|
240
|
+
label: 'Build for Web (itch.io)',
|
|
241
|
+
category: 'action',
|
|
242
|
+
execute: () => {
|
|
243
|
+
window.dispatchEvent(new CustomEvent('editor:show-build-tab'));
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: 'build.steam',
|
|
248
|
+
label: 'Build for Desktop (Steam)',
|
|
249
|
+
category: 'action',
|
|
250
|
+
execute: () => {
|
|
251
|
+
window.dispatchEvent(new CustomEvent('editor:show-build-tab'));
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Build dynamic entity actions from the current scene. */
|
|
258
|
+
export function buildEntityActions(store: EditorStore): EditorAction[] {
|
|
259
|
+
return store.allEntities().map((entity) => ({
|
|
260
|
+
id: `entity:${entity.id}`,
|
|
261
|
+
label: entity.name,
|
|
262
|
+
category: 'entity' as const,
|
|
263
|
+
execute: () => {
|
|
264
|
+
store.select(entity.id!);
|
|
265
|
+
store.focusOnEntity(entity.id!);
|
|
266
|
+
},
|
|
267
|
+
}));
|
|
268
|
+
}
|