@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,127 @@
|
|
|
1
|
+
import type { ExtraDepsResolution2D } from '@engine/world2d/ingest2d';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `IngestGame` descriptor — the mountable shape `ingest-mode.ts`
|
|
5
|
+
* (`enterIngestModeWithGame`) and `authoring/ingest-game-adapter.ts`
|
|
6
|
+
* (`mountIngestGame`) consume, regardless of where it came from.
|
|
7
|
+
*
|
|
8
|
+
* T3.3 slice 3 (docs/CLI-ON-FOLDER-DESIGN.md §1E) moved this type out of the
|
|
9
|
+
* now-deleted `ingest/games/registry.ts` (the static `INGEST_GAMES` array) —
|
|
10
|
+
* it used to be registry-specific; now it is the common contract BOTH
|
|
11
|
+
* discovery frontends build: `ingest/discovery.ts`'s glob-based discovery of
|
|
12
|
+
* the in-tree fixture games under `ingest/games/<id>/vgai.game.json`, and
|
|
13
|
+
* `adapter-resolver.ts`'s `resolveIngestDescriptor`, which builds the same
|
|
14
|
+
* shape from an arbitrary manifest's `ingest-three` world (the CLI-on-folder
|
|
15
|
+
* route, for a game folder never registered in source).
|
|
16
|
+
*
|
|
17
|
+
* D-W1/D-W2 (docs/WAVE4-FTUE-HARDENING-DESIGN.md) add the PREBUILT-BUNDLE
|
|
18
|
+
* iframe-reachable fields (`bundleUrl`/`baseHref`/`assetBaseUrl`/`bodyHtml`/
|
|
19
|
+
* `extraDeps`) — the three-side mirror of `IngestGame2D`'s Track-P fields
|
|
20
|
+
* (`@engine/world2d/ingest2d.ts`) — and widen `embedHtml` to admit a LAZY
|
|
21
|
+
* thunk alongside its original plain-string form (see that field's own doc
|
|
22
|
+
* comment for why both shapes must keep working).
|
|
23
|
+
*/
|
|
24
|
+
export interface IngestGame {
|
|
25
|
+
/** Stable id (used by the launcher + conformance test; == the manifest world id). */
|
|
26
|
+
id: string;
|
|
27
|
+
/** Human label shown in the editor's "Ingest game" menu (== the manifest's game name). */
|
|
28
|
+
name: string;
|
|
29
|
+
/** One-line description (== the manifest world's optional `description`, or `''`). */
|
|
30
|
+
description: string;
|
|
31
|
+
/**
|
|
32
|
+
* Dynamically import + run the unmodified game module (shared-`three`/deduped path).
|
|
33
|
+
* Omitted for `embedHtml`/`iframeReachableSrc` games (opaque-embed/iframe-reachable).
|
|
34
|
+
*/
|
|
35
|
+
load?: () => Promise<unknown>;
|
|
36
|
+
/**
|
|
37
|
+
* Self-contained HTML for an OPAQUE prebuilt bundle (its own inlined renderer,
|
|
38
|
+
* `three` unreachable). The host runs it in an iframe at the embed-only floor
|
|
39
|
+
* (Tier 0–1): hosted + sized + disposed, but its scene is NOT introspectable.
|
|
40
|
+
* Mutually exclusive with `load`. See docs/ADAPTER-ARCHITECTURE.md §2.3.
|
|
41
|
+
*
|
|
42
|
+
* Two shapes, both legal (D-W2, docs/WAVE4-FTUE-HARDENING-DESIGN.md):
|
|
43
|
+
* - a plain `string` — the file's contents ALREADY READ (the in-tree
|
|
44
|
+
* fixture glob route, `ingest/discovery.ts`, which Vite reads eagerly at
|
|
45
|
+
* build/dev time via `import.meta.glob(..., { query: '?raw' })`); or
|
|
46
|
+
* - a lazy `() => Promise<string>` thunk — a MANIFEST-DRIVEN external
|
|
47
|
+
* folder (`adapter-resolver.ts`'s `resolveIngestDescriptor`), which reads
|
|
48
|
+
* the declared `entryHtml` file's bytes through the
|
|
49
|
+
* `/project-game-static/` route only when the game is actually mounted,
|
|
50
|
+
* never eagerly at resolve time (mirrors `bundleUrl`'s own laziness).
|
|
51
|
+
* `enterIngestModeWithGame` (ingest-mode.ts) resolves either form to a
|
|
52
|
+
* plain string before handing it to `mountIngestGameEmbed`.
|
|
53
|
+
*/
|
|
54
|
+
embedHtml?: string | (() => Promise<string>);
|
|
55
|
+
/**
|
|
56
|
+
* Source of a PREBUILT bundle whose `three` is REACHABLE. The host runs it in a
|
|
57
|
+
* same-origin iframe whose importmap resolves `three` to the HOST instance (blob
|
|
58
|
+
* re-export), captures its live scene in-realm, and edits it fully (tier 2–3).
|
|
59
|
+
* Mutually exclusive with `load`/`embedHtml`. See ingest-iframe-reachable-adapter.ts.
|
|
60
|
+
*/
|
|
61
|
+
iframeReachableSrc?: string;
|
|
62
|
+
/** Capture timeout (ms) before degrading to embed-only — short for the
|
|
63
|
+
* mismatched-three demo whose `three` is deliberately unreachable. */
|
|
64
|
+
captureTimeoutMs?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Map of game-relative-path substring → served asset URL. The ingest adapter
|
|
67
|
+
* installs a `THREE.DefaultLoadingManager` URL modifier that rewrites any
|
|
68
|
+
* requested URL containing a key to its value.
|
|
69
|
+
*/
|
|
70
|
+
assets?: Record<string, string>;
|
|
71
|
+
/**
|
|
72
|
+
* Element ids the game expects to already exist in the DOM (e.g. an FPS game's
|
|
73
|
+
* `#blocker`/`#instructions` overlay). The host creates hidden stub elements
|
|
74
|
+
* with these ids before running the game, so DOM-dependent games stay
|
|
75
|
+
* unmodified (study §4D).
|
|
76
|
+
*/
|
|
77
|
+
domStubs?: string[];
|
|
78
|
+
/**
|
|
79
|
+
* The game's own manifest `version` (D9, docs/DECISIONS-PENDING.md §D9 —
|
|
80
|
+
* orphan/mismatch detection), when this descriptor was built straight from
|
|
81
|
+
* a manifest that has one. `ingest/discovery.ts`'s in-tree fixture route
|
|
82
|
+
* sets this from the parsed manifest's `version`; `adapter-resolver.ts`'s
|
|
83
|
+
* `resolveIngestDescriptor` (the CLI-on-folder / manifest-world route)
|
|
84
|
+
* cannot — it only has a `ResolvedWorldEntry`, not the manifest's top-level
|
|
85
|
+
* `version` — so `ingest-mode.ts`'s `enterIngestModeFromManifestWorld`
|
|
86
|
+
* threads the resolved manifest's `version` through as an explicit
|
|
87
|
+
* parameter instead, taking precedence over this field where both exist.
|
|
88
|
+
*/
|
|
89
|
+
gameVersion?: string;
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------
|
|
92
|
+
// D-W1 (docs/WAVE4-FTUE-HARDENING-DESIGN.md) — IFRAME-REACHABLE
|
|
93
|
+
// PREBUILT-BUNDLE mount fields, the three-side mirror of `IngestGame2D`'s
|
|
94
|
+
// Track-P fields (`@engine/world2d/ingest2d.ts`). Populated only when
|
|
95
|
+
// `iframeReachableSrc`/`load` are both absent and the world's manifest
|
|
96
|
+
// strategy is `iframe-reachable` with a `bundleUrl` (see
|
|
97
|
+
// `adapter-resolver.ts`'s `resolveIngestDescriptor`). The bundle MUST
|
|
98
|
+
// externalize `three` (a bare, un-rewritten `import 'three'`) — same bar
|
|
99
|
+
// as pixi's D-X5/D-Z4 — so it resolves through the importmap below to the
|
|
100
|
+
// HOST's `three`, not an inlined copy the capture trap can't see.
|
|
101
|
+
// ---------------------------------------------------------------------
|
|
102
|
+
/**
|
|
103
|
+
* Absolute URL of the externalized built game bundle, mounted via
|
|
104
|
+
* `<script type="module" src=...>` instead of an inline source string
|
|
105
|
+
* (`mountIngestGameIframeReachableBundle`, `ingest-iframe-reachable-adapter.ts`).
|
|
106
|
+
*/
|
|
107
|
+
bundleUrl?: string;
|
|
108
|
+
/** `<base href>` for the iframe so the game's relative asset URLs resolve. */
|
|
109
|
+
baseHref?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Host-side asset URL remap forced onto the host THREE's
|
|
112
|
+
* `DefaultLoadingManager.setURLModifier` — the three analog of pixi's
|
|
113
|
+
* `Assets.init` basePath wrap (a document.write iframe keeps the PARENT's
|
|
114
|
+
* `window.location`, so a relative asset request would otherwise resolve
|
|
115
|
+
* against the parent page, not the served bundle dir).
|
|
116
|
+
*/
|
|
117
|
+
assetBaseUrl?: string;
|
|
118
|
+
/** DOM injected into the iframe body before the bundle's script boots (e.g. a `<div id="game-root">` it expects to find). */
|
|
119
|
+
bodyHtml?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Lazily resolve this game's bare-specifier -> extraDeps resolution (D-Z3,
|
|
122
|
+
* the SAME `ExtraDepsResolution2D` shape the pixi/world2d side uses —
|
|
123
|
+
* namespaces + verbatim URLs) via the editor's host-namespace registry.
|
|
124
|
+
* Absent means no extra externalized deps beyond `three` itself.
|
|
125
|
+
*/
|
|
126
|
+
extraDeps?: () => Promise<ExtraDepsResolution2D>;
|
|
127
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure row-flattening for `IngestHierarchy` (no React) — D-W4 (F14/F18,
|
|
3
|
+
* docs/WAVE4-FTUE-HARDENING-DESIGN.md §D-W4), extracted the same way
|
|
4
|
+
* `hierarchy-rows.ts` extracts `SceneHierarchy`'s equivalent, so the
|
|
5
|
+
* key/collapse/cycle-guard logic is unit-testable without rendering.
|
|
6
|
+
*
|
|
7
|
+
* §0.5's ground truth: an ingested game's structural ids
|
|
8
|
+
* (`ingest:<path>:<type>:<name>`, `@engine/adapter/ingest/overlay-apply.ts`'s
|
|
9
|
+
* `assignStructuralIds`) are baked ONCE at capture and are the overlay
|
|
10
|
+
* PERSISTENCE key (overlay-apply.ts:45-51) — never touched here. But
|
|
11
|
+
* `IngestHierarchy` re-reads the LIVE `Object3D` tree every render
|
|
12
|
+
* (`adapter.hierarchy.node(id)`), and a live game can reorder or clone
|
|
13
|
+
* subtrees after capture, so the SAME baked id can legitimately show up in
|
|
14
|
+
* more than one place in a single walk — `EditorNode.id` alone is no longer
|
|
15
|
+
* a safe React key, and naively recursing `childIds` with no guard can loop
|
|
16
|
+
* forever if a stale/duplicated id ever points back at one of its own
|
|
17
|
+
* ancestors.
|
|
18
|
+
*
|
|
19
|
+
* Wave-7 (docs/WAVE7-HIERARCHY-CAP-DESIGN.md §1 D-C1..D-C6): per-parent
|
|
20
|
+
* child cap, copied from `hierarchy-rows.ts`'s `flattenVisibleRows`/
|
|
21
|
+
* `CHILD_CAP`/`MORE_ID_PREFIX` (same constants, no drift). Unlike
|
|
22
|
+
* first-party (which only caps in play mode), the adapter panel's tree is
|
|
23
|
+
* BY DEFINITION a live game scene graph, so `capEnabled` defaults to
|
|
24
|
+
* `false` here (matching this function's PRE-cap behavior byte-for-byte —
|
|
25
|
+
* every existing caller/test that doesn't pass the new params keeps working
|
|
26
|
+
* unchanged) and `IngestHierarchy` explicitly turns it on for the browse
|
|
27
|
+
* view. Search bypasses the cap by calling with `capEnabled=false` (D-C4) —
|
|
28
|
+
* the exact same "flatten UNCAPPED, filter flat" shape this module already
|
|
29
|
+
* used for search before the cap existed.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import type { EditorNode, HierarchyProvider } from '@engine/adapter';
|
|
33
|
+
import { CHILD_CAP, MORE_ID_PREFIX } from './hierarchy-rows';
|
|
34
|
+
|
|
35
|
+
/** One flattened, render-ready row over an ingested game's live hierarchy. */
|
|
36
|
+
export interface IngestRow {
|
|
37
|
+
readonly node: EditorNode;
|
|
38
|
+
readonly depth: number;
|
|
39
|
+
/**
|
|
40
|
+
* Render key material: the walk path (root index, then child index at
|
|
41
|
+
* each level) — NOT `node.id` alone. Stays unique across a render even
|
|
42
|
+
* when the id scheme collides, because it is derived from POSITION in
|
|
43
|
+
* the walk, not from the adapter's (potentially stale/duplicated) data.
|
|
44
|
+
*/
|
|
45
|
+
readonly pathKey: string;
|
|
46
|
+
readonly hasChildren: boolean;
|
|
47
|
+
/** True when an ANCESTOR's `pathKey` is in the caller's collapsed-set —
|
|
48
|
+
* i.e. this row is inside a collapsed subtree (F18). The row itself is
|
|
49
|
+
* still included in the returned array (so a search can still find it);
|
|
50
|
+
* the component filters it out when not searching. */
|
|
51
|
+
readonly hiddenByCollapse: boolean;
|
|
52
|
+
/** Present on a synthetic "… N more" row that reveals capped siblings
|
|
53
|
+
* (D-C2) — `parentPathKey` is the capped parent's `pathKey`, `hidden` is
|
|
54
|
+
* how many of its children are not shown. Never present on a real row. */
|
|
55
|
+
readonly more?: { readonly parentPathKey: string; readonly hidden: number };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Backstop against a childIds list this guard's own dedup somehow doesn't
|
|
60
|
+
* anticipate (e.g. a very deep but genuinely acyclic live tree) — ingested
|
|
61
|
+
* games are not expected to nest anywhere near this deep; this is a second,
|
|
62
|
+
* independent safety net, not the primary guard (see `visited` below).
|
|
63
|
+
*/
|
|
64
|
+
const MAX_DEPTH = 500;
|
|
65
|
+
|
|
66
|
+
/** How many of a parent's children to walk (D-C1/D-C3) — split out of `walk`
|
|
67
|
+
* below purely to keep that function's cognitive-complexity score down. */
|
|
68
|
+
function childLimit(
|
|
69
|
+
capEnabled: boolean,
|
|
70
|
+
revealed: ReadonlyMap<string, number>,
|
|
71
|
+
parentPathKey: string,
|
|
72
|
+
): number {
|
|
73
|
+
return capEnabled
|
|
74
|
+
? Math.max(CHILD_CAP, revealed.get(parentPathKey) ?? CHILD_CAP)
|
|
75
|
+
: Number.POSITIVE_INFINITY;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The synthetic "… N more" row for a capped parent (D-C2) — a render-only
|
|
79
|
+
* stub, never fed back to the adapter. Split out of `walk` below purely to
|
|
80
|
+
* keep that function's cognitive-complexity score down. */
|
|
81
|
+
function buildMoreRow(
|
|
82
|
+
parentPathKey: string,
|
|
83
|
+
depth: number,
|
|
84
|
+
parentId: string,
|
|
85
|
+
hiddenByCollapse: boolean,
|
|
86
|
+
hidden: number,
|
|
87
|
+
): IngestRow {
|
|
88
|
+
return {
|
|
89
|
+
node: {
|
|
90
|
+
id: `${MORE_ID_PREFIX}${parentPathKey}`,
|
|
91
|
+
label: '',
|
|
92
|
+
kind: 'object',
|
|
93
|
+
parentId,
|
|
94
|
+
childIds: [],
|
|
95
|
+
flags: {},
|
|
96
|
+
},
|
|
97
|
+
depth,
|
|
98
|
+
pathKey: `${parentPathKey}/__more__`,
|
|
99
|
+
hasChildren: false,
|
|
100
|
+
hiddenByCollapse,
|
|
101
|
+
more: { parentPathKey, hidden },
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Flatten an ingest adapter's hierarchy into display rows.
|
|
107
|
+
*
|
|
108
|
+
* F14 cycle/dup guard: `visited` tracks every `node.id` already emitted in
|
|
109
|
+
* THIS walk. A live game reordering/cloning objects can make the same baked
|
|
110
|
+
* id reachable from more than one place (a real duplicate) or, in principle,
|
|
111
|
+
* from one of its own descendants (a cycle) — either way the id is stale
|
|
112
|
+
* data describing the CURRENT live scene, not a second logical node. The
|
|
113
|
+
* chosen semantics: render the first occurrence encountered (root-first,
|
|
114
|
+
* then depth-first child order) and silently skip every later one — no
|
|
115
|
+
* second row, and a cycle can never recurse forever. `collapsedKeys` is
|
|
116
|
+
* keyed by `pathKey`, not `node.id` (F18) — a walk-path is stable for "this
|
|
117
|
+
* position in the tree shape", which is what "collapsed" means to a user
|
|
118
|
+
* looking at the panel; keying by id would let a stale/reused id apply a
|
|
119
|
+
* collapse to the WRONG node after a live reorder, or fail to distinguish
|
|
120
|
+
* two positions that happen to share a duplicated id.
|
|
121
|
+
*
|
|
122
|
+
* D-C1/D-C3 cap: when `capEnabled`, each parent's children are limited to
|
|
123
|
+
* `max(CHILD_CAP, revealed.get(parentPathKey) ?? CHILD_CAP)` and a synthetic
|
|
124
|
+
* more-row is appended when some are hidden (D-C2). D-C5: children beyond
|
|
125
|
+
* the limit are never walked, so never added to `visited` — a duplicate id
|
|
126
|
+
* whose first structural occurrence was capped away still renders at its
|
|
127
|
+
* next reachable occurrence (the dedup guard's "once, not zero times"
|
|
128
|
+
* guarantee holds). D-C6: a COLLAPSED parent (its own `pathKey` is in
|
|
129
|
+
* `collapsedKeys`) contributes no child rows and no more-row at all when
|
|
130
|
+
* capped — the walk stops at the parent itself rather than descending and
|
|
131
|
+
* relying on `hiddenByCollapse` filtering, since a more-row would otherwise
|
|
132
|
+
* still need suppressing. Uncapped calls (search, D-C4) are unaffected:
|
|
133
|
+
* collapse only ever gates recursion when `capEnabled`, so a collapsed
|
|
134
|
+
* subtree's matches stay reachable when searching, exactly as before.
|
|
135
|
+
*/
|
|
136
|
+
export function flattenIngestRows(
|
|
137
|
+
hierarchy: Pick<HierarchyProvider, 'roots' | 'node'>,
|
|
138
|
+
collapsedKeys: ReadonlySet<string>,
|
|
139
|
+
revealed: ReadonlyMap<string, number> = new Map(),
|
|
140
|
+
capEnabled = false,
|
|
141
|
+
): IngestRow[] {
|
|
142
|
+
const rows: IngestRow[] = [];
|
|
143
|
+
const visited = new Set<string>();
|
|
144
|
+
|
|
145
|
+
const walk = (node: EditorNode, depth: number, pathKey: string, parentHidden: boolean): void => {
|
|
146
|
+
if (visited.has(node.id) || depth > MAX_DEPTH) return;
|
|
147
|
+
visited.add(node.id);
|
|
148
|
+
|
|
149
|
+
const hasChildren = node.childIds.length > 0;
|
|
150
|
+
rows.push({ node, depth, pathKey, hasChildren, hiddenByCollapse: parentHidden });
|
|
151
|
+
|
|
152
|
+
const isCollapsed = collapsedKeys.has(pathKey);
|
|
153
|
+
if (capEnabled && isCollapsed) return; // D-C6: nothing of a collapsed subtree renders.
|
|
154
|
+
|
|
155
|
+
const childHidden = parentHidden || isCollapsed;
|
|
156
|
+
const shown = Math.min(node.childIds.length, childLimit(capEnabled, revealed, pathKey));
|
|
157
|
+
|
|
158
|
+
for (let i = 0; i < shown; i++) {
|
|
159
|
+
const child = hierarchy.node(node.childIds[i]!);
|
|
160
|
+
if (child) walk(child, depth + 1, `${pathKey}.${i}`, childHidden);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (capEnabled && node.childIds.length > shown) {
|
|
164
|
+
rows.push(
|
|
165
|
+
buildMoreRow(pathKey, depth + 1, node.id, childHidden, node.childIds.length - shown),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
hierarchy.roots().forEach((root, i) => {
|
|
171
|
+
walk(root, 0, `r${i}`, false);
|
|
172
|
+
});
|
|
173
|
+
return rows;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Stable React key for a row — walk path + id, so it never collides even
|
|
177
|
+
* when the underlying id scheme does (F14). */
|
|
178
|
+
export function ingestRowKey(row: Pick<IngestRow, 'pathKey' | 'node'>): string {
|
|
179
|
+
return `${row.pathKey}:${row.node.id}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Wave-18 (docs/WAVE18-INGEST-HIERARCHY-VIRTUALIZATION-DESIGN.md): the pure
|
|
184
|
+
* start/end row-index math for `IngestHierarchy`'s scroll-windowed rendering.
|
|
185
|
+
* Kept here (not inlined in the component) for two reasons: it is
|
|
186
|
+
* unit-testable standalone with no React/jsdom involved, and a tamper test
|
|
187
|
+
* can `vi.mock` this ONE function to neutralize windowing (return the full
|
|
188
|
+
* range) and prove the render-bounding behavior actually depends on it, not
|
|
189
|
+
* on some other accidental cap.
|
|
190
|
+
*
|
|
191
|
+
* `overscan` extra rows are kept rendered on each side of the visible band
|
|
192
|
+
* so a fast scroll or keyboard nav doesn't flash empty space before the next
|
|
193
|
+
* paint catches up. `end` is clamped to `totalRows`; `start` is clamped to 0
|
|
194
|
+
* (never negative near the top of the list).
|
|
195
|
+
*/
|
|
196
|
+
export function ingestRowWindow(
|
|
197
|
+
totalRows: number,
|
|
198
|
+
scrollTop: number,
|
|
199
|
+
viewportPx: number,
|
|
200
|
+
rowH: number,
|
|
201
|
+
overscan: number,
|
|
202
|
+
): { start: number; end: number } {
|
|
203
|
+
const start = Math.max(0, Math.floor(scrollTop / rowH) - overscan);
|
|
204
|
+
const visibleCount = Math.ceil(viewportPx / rowH) + overscan * 2;
|
|
205
|
+
const end = Math.min(totalRows, start + visibleCount);
|
|
206
|
+
return { start, end };
|
|
207
|
+
}
|