@vgai/engine 0.3.0 → 0.4.0-canary.20260715.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -2
- package/schemas/engine-api.json +124 -0
- package/schemas/engine-api.md +53 -0
- package/schemas/engine-capabilities.json +124 -0
- package/schemas/inputmap.schema.json +314 -0
- package/schemas/mat.schema.json +286 -0
- package/schemas/prefab.schema.json +10148 -0
- package/schemas/scn2d.schema.json +475 -0
- package/schemas/vgai-game.schema.json +383 -0
- package/schemas/vscn.schema.json +11007 -0
- package/src/adapter/{world-kind.ts → adapter-surface.ts} +6 -6
- package/src/adapter/authoring.ts +67 -0
- package/src/adapter/game-adapter.ts +8 -8
- package/src/adapter/host-context.ts +2 -4
- package/src/adapter/index.ts +3 -1
- package/src/adapter/system-adapter.ts +73 -0
- package/src/adapter/vgai-scene-game-adapter.ts +239 -180
- package/src/animation/xstate-animation-binding.ts +300 -262
- package/src/animation/xstate-animation-meta.ts +50 -13
- package/src/character/cloth-sim.ts +533 -0
- package/src/character/spring-chain.ts +307 -0
- package/src/core/game-loop.ts +41 -3
- package/src/core/seeded-random.ts +161 -0
- package/src/core/system-runner.ts +20 -3
- package/src/core/types.ts +37 -0
- package/src/data/data-asset.ts +1 -1
- package/src/dev/performance-profiler.ts +213 -0
- package/src/dev/webgl-gpu-timer.ts +53 -0
- package/src/ecs/component-manager.ts +45 -12
- package/src/ecs/game-component.ts +95 -11
- package/src/humanoid/bake.operation.ts +326 -0
- package/src/humanoid/body.ts +663 -0
- package/src/humanoid/clips.ts +149 -0
- package/src/humanoid/compose.ts +209 -0
- package/src/humanoid/generate.ts +189 -0
- package/src/humanoid/index.ts +36 -0
- package/src/humanoid/schema.ts +108 -0
- package/src/humanoid/skeleton.ts +345 -0
- package/src/index.ts +5 -5
- package/src/input/input-manager.ts +701 -22
- package/src/input/input-types.ts +5 -2
- package/src/manifest/index.ts +5 -5
- package/src/manifest/load.ts +125 -72
- package/src/manifest/schema.ts +362 -255
- package/src/react/game-state.tsx +135 -32
- package/src/react/root-adapter.tsx +49 -0
- package/src/react/unmanaged-root-detector.ts +66 -0
- package/src/react/use-data.ts +12 -2
- package/src/runtime/create-runtime.ts +100 -282
- package/src/runtime/debug-bridge.ts +483 -0
- package/src/runtime/debug-registry.ts +856 -0
- package/src/runtime/game.ts +342 -93
- package/src/runtime/gameplay-rng-trap.ts +134 -0
- package/src/runtime/input-router.ts +7 -7
- package/src/runtime/mount-game.ts +40 -38
- package/src/runtime/mount-manifest.ts +169 -37
- package/src/runtime/render-control.ts +13 -13
- package/src/runtime/render-seed.ts +1 -1
- package/src/runtime/state-bridge.ts +24 -10
- package/src/runtime/types.ts +110 -28
- package/src/scene/asset-registry.ts +22 -0
- package/src/scene/component-registry.ts +14 -3
- package/src/scene/defaults.ts +1 -0
- package/src/scene/light-camera-factory.ts +11 -3
- package/src/scene/scene-apply.ts +55 -4
- package/src/scene/scene-loader.ts +10 -27
- package/src/scene/scene-types.ts +0 -1
- package/src/scene/schema/index.ts +0 -34
- package/src/scene/schema/light.ts +16 -1
- package/src/scene/schema/material.ts +96 -91
- package/src/scene/schema/scene-file.ts +1 -7
- package/src/scene/user-data.ts +14 -1
- package/src/setup/setup-renderer.ts +1 -1
- package/src/tools/define-tool.ts +50 -11
- package/src/world2d/authoring-2d.ts +17 -1
- package/src/world2d/collision-2d.ts +1 -1
- package/src/world2d/pixi-game-adapter.ts +19 -17
- package/src/world2d/scene2d-loader.ts +1 -0
- package/src/world2d/types.ts +8 -2
- package/dist/adapter/authoring.d.ts +0 -404
- package/dist/adapter/authoring.d.ts.map +0 -1
- package/dist/adapter/authoring.js +0 -22
- package/dist/adapter/colyseus-networking-adapter.d.ts +0 -43
- package/dist/adapter/colyseus-networking-adapter.d.ts.map +0 -1
- package/dist/adapter/colyseus-networking-adapter.js +0 -38
- package/dist/adapter/first-party-systems.d.ts +0 -38
- package/dist/adapter/first-party-systems.d.ts.map +0 -1
- package/dist/adapter/first-party-systems.js +0 -77
- package/dist/adapter/game-adapter.d.ts +0 -133
- package/dist/adapter/game-adapter.d.ts.map +0 -1
- package/dist/adapter/game-adapter.js +0 -10
- package/dist/adapter/host-context.d.ts +0 -73
- package/dist/adapter/host-context.d.ts.map +0 -1
- package/dist/adapter/host-context.js +0 -16
- package/dist/adapter/index.d.ts +0 -22
- package/dist/adapter/index.d.ts.map +0 -1
- package/dist/adapter/index.js +0 -15
- package/dist/adapter/ingest/game-contract.d.ts +0 -53
- package/dist/adapter/ingest/game-contract.d.ts.map +0 -1
- package/dist/adapter/ingest/game-contract.js +0 -30
- package/dist/adapter/ingest/overlay-applier.d.ts +0 -118
- package/dist/adapter/ingest/overlay-applier.d.ts.map +0 -1
- package/dist/adapter/ingest/overlay-applier.js +0 -132
- package/dist/adapter/ingest/overlay-apply.d.ts +0 -60
- package/dist/adapter/ingest/overlay-apply.d.ts.map +0 -1
- package/dist/adapter/ingest/overlay-apply.js +0 -101
- package/dist/adapter/ingest/overlay-file.d.ts +0 -79
- package/dist/adapter/ingest/overlay-file.d.ts.map +0 -1
- package/dist/adapter/ingest/overlay-file.js +0 -66
- package/dist/adapter/ingest/overlay-report.d.ts +0 -113
- package/dist/adapter/ingest/overlay-report.d.ts.map +0 -1
- package/dist/adapter/ingest/overlay-report.js +0 -103
- package/dist/adapter/ingest/scene-capture.d.ts +0 -97
- package/dist/adapter/ingest/scene-capture.d.ts.map +0 -1
- package/dist/adapter/ingest/scene-capture.js +0 -248
- package/dist/adapter/ingest/upstream-pin.d.ts +0 -47
- package/dist/adapter/ingest/upstream-pin.d.ts.map +0 -1
- package/dist/adapter/ingest/upstream-pin.js +0 -50
- package/dist/adapter/loop-gate-report.d.ts +0 -34
- package/dist/adapter/loop-gate-report.d.ts.map +0 -1
- package/dist/adapter/loop-gate-report.js +0 -37
- package/dist/adapter/rapier-physics-adapter.d.ts +0 -12
- package/dist/adapter/rapier-physics-adapter.d.ts.map +0 -1
- package/dist/adapter/rapier-physics-adapter.js +0 -46
- package/dist/adapter/system-adapter.d.ts +0 -133
- package/dist/adapter/system-adapter.d.ts.map +0 -1
- package/dist/adapter/system-adapter.js +0 -13
- package/dist/adapter/transform.d.ts +0 -18
- package/dist/adapter/transform.d.ts.map +0 -1
- package/dist/adapter/transform.js +0 -1
- package/dist/adapter/vgai-scene-game-adapter.d.ts +0 -116
- package/dist/adapter/vgai-scene-game-adapter.d.ts.map +0 -1
- package/dist/adapter/vgai-scene-game-adapter.js +0 -714
- package/dist/adapter/world-kind.d.ts +0 -30
- package/dist/adapter/world-kind.d.ts.map +0 -1
- package/dist/adapter/world-kind.js +0 -18
- package/dist/ai/navigation.d.ts +0 -64
- package/dist/ai/navigation.d.ts.map +0 -1
- package/dist/ai/navigation.js +0 -133
- package/dist/animation/anim-graph-types.d.ts +0 -25
- package/dist/animation/anim-graph-types.d.ts.map +0 -1
- package/dist/animation/anim-graph-types.js +0 -1
- package/dist/animation/animation-clock.d.ts +0 -213
- package/dist/animation/animation-clock.d.ts.map +0 -1
- package/dist/animation/animation-clock.js +0 -301
- package/dist/animation/blend-node.d.ts +0 -22
- package/dist/animation/blend-node.d.ts.map +0 -1
- package/dist/animation/blend-node.js +0 -97
- package/dist/animation/camera-ownership.d.ts +0 -250
- package/dist/animation/camera-ownership.d.ts.map +0 -1
- package/dist/animation/camera-ownership.js +0 -169
- package/dist/animation/cinematic-cues.d.ts +0 -200
- package/dist/animation/cinematic-cues.d.ts.map +0 -1
- package/dist/animation/cinematic-cues.js +0 -213
- package/dist/animation/clip-map.d.ts +0 -12
- package/dist/animation/clip-map.d.ts.map +0 -1
- package/dist/animation/clip-map.js +0 -37
- package/dist/animation/gsap-registration.d.ts +0 -119
- package/dist/animation/gsap-registration.d.ts.map +0 -1
- package/dist/animation/gsap-registration.js +0 -92
- package/dist/animation/theatre-clock-binding.d.ts +0 -89
- package/dist/animation/theatre-clock-binding.d.ts.map +0 -1
- package/dist/animation/theatre-clock-binding.js +0 -29
- package/dist/animation/theatre-director.d.ts +0 -242
- package/dist/animation/theatre-director.d.ts.map +0 -1
- package/dist/animation/theatre-director.js +0 -235
- package/dist/animation/theatre-object-binding.d.ts +0 -305
- package/dist/animation/theatre-object-binding.d.ts.map +0 -1
- package/dist/animation/theatre-object-binding.js +0 -351
- package/dist/animation/xstate-animation-binding.d.ts +0 -111
- package/dist/animation/xstate-animation-binding.d.ts.map +0 -1
- package/dist/animation/xstate-animation-binding.js +0 -307
- package/dist/animation/xstate-animation-meta.d.ts +0 -228
- package/dist/animation/xstate-animation-meta.d.ts.map +0 -1
- package/dist/animation/xstate-animation-meta.js +0 -221
- package/dist/assets.d.ts +0 -26
- package/dist/assets.d.ts.map +0 -1
- package/dist/assets.js +0 -55
- package/dist/audio/index.d.ts +0 -4
- package/dist/audio/index.d.ts.map +0 -1
- package/dist/audio/index.js +0 -24
- package/dist/audio/tone-clock-binding.d.ts +0 -75
- package/dist/audio/tone-clock-binding.d.ts.map +0 -1
- package/dist/audio/tone-clock-binding.js +0 -29
- package/dist/audio/tone-context.d.ts +0 -114
- package/dist/audio/tone-context.d.ts.map +0 -1
- package/dist/audio/tone-context.js +0 -39
- package/dist/audio/tone-offline-render.d.ts +0 -90
- package/dist/audio/tone-offline-render.d.ts.map +0 -1
- package/dist/audio/tone-offline-render.js +0 -56
- package/dist/audio/wav-encode.d.ts +0 -38
- package/dist/audio/wav-encode.d.ts.map +0 -1
- package/dist/audio/wav-encode.js +0 -97
- package/dist/core/game-loop.d.ts +0 -21
- package/dist/core/game-loop.d.ts.map +0 -1
- package/dist/core/game-loop.js +0 -130
- package/dist/core/system-runner.d.ts +0 -120
- package/dist/core/system-runner.d.ts.map +0 -1
- package/dist/core/system-runner.js +0 -286
- package/dist/core/types.d.ts +0 -58
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js +0 -25
- package/dist/data/data-asset.d.ts +0 -101
- package/dist/data/data-asset.d.ts.map +0 -1
- package/dist/data/data-asset.js +0 -122
- package/dist/data/data-check-core.d.ts +0 -110
- package/dist/data/data-check-core.d.ts.map +0 -1
- package/dist/data/data-check-core.js +0 -178
- package/dist/data/data-ref.d.ts +0 -79
- package/dist/data/data-ref.d.ts.map +0 -1
- package/dist/data/data-ref.js +0 -130
- package/dist/data/vite-plugin-data.d.ts +0 -79
- package/dist/data/vite-plugin-data.d.ts.map +0 -1
- package/dist/data/vite-plugin-data.js +0 -217
- package/dist/dev/console-bridge.d.ts +0 -22
- package/dist/dev/console-bridge.d.ts.map +0 -1
- package/dist/dev/console-bridge.js +0 -71
- package/dist/dev/debug-draw.d.ts +0 -24
- package/dist/dev/debug-draw.d.ts.map +0 -1
- package/dist/dev/debug-draw.js +0 -73
- package/dist/dev/logger.d.ts +0 -30
- package/dist/dev/logger.d.ts.map +0 -1
- package/dist/dev/logger.js +0 -90
- package/dist/ecs/component-manager.d.ts +0 -189
- package/dist/ecs/component-manager.d.ts.map +0 -1
- package/dist/ecs/component-manager.js +0 -676
- package/dist/ecs/game-component.d.ts +0 -97
- package/dist/ecs/game-component.d.ts.map +0 -1
- package/dist/ecs/game-component.js +0 -80
- package/dist/ecs/hmr-swap-report.d.ts +0 -53
- package/dist/ecs/hmr-swap-report.d.ts.map +0 -1
- package/dist/ecs/hmr-swap-report.js +0 -55
- package/dist/index.d.ts +0 -37
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -30
- package/dist/input/input-manager.d.ts +0 -596
- package/dist/input/input-manager.d.ts.map +0 -1
- package/dist/input/input-manager.js +0 -1564
- package/dist/input/input-types.d.ts +0 -171
- package/dist/input/input-types.d.ts.map +0 -1
- package/dist/input/input-types.js +0 -1
- package/dist/input/prompt-labels.d.ts +0 -21
- package/dist/input/prompt-labels.d.ts.map +0 -1
- package/dist/input/prompt-labels.js +0 -121
- package/dist/input/rebind-controller.d.ts +0 -59
- package/dist/input/rebind-controller.d.ts.map +0 -1
- package/dist/input/rebind-controller.js +0 -85
- package/dist/input/schema.d.ts +0 -16
- package/dist/input/schema.d.ts.map +0 -1
- package/dist/input/schema.js +0 -228
- package/dist/loader.d.ts +0 -43
- package/dist/loader.d.ts.map +0 -1
- package/dist/loader.js +0 -59
- package/dist/manifest/index.d.ts +0 -5
- package/dist/manifest/index.d.ts.map +0 -1
- package/dist/manifest/index.js +0 -8
- package/dist/manifest/load-file.d.ts +0 -4
- package/dist/manifest/load-file.d.ts.map +0 -1
- package/dist/manifest/load-file.js +0 -14
- package/dist/manifest/load.d.ts +0 -117
- package/dist/manifest/load.d.ts.map +0 -1
- package/dist/manifest/load.js +0 -255
- package/dist/manifest/schema.d.ts +0 -173
- package/dist/manifest/schema.d.ts.map +0 -1
- package/dist/manifest/schema.js +0 -302
- package/dist/physics/collision-system.d.ts +0 -41
- package/dist/physics/collision-system.d.ts.map +0 -1
- package/dist/physics/collision-system.js +0 -64
- package/dist/physics/physics-registry.d.ts +0 -45
- package/dist/physics/physics-registry.d.ts.map +0 -1
- package/dist/physics/physics-registry.js +0 -65
- package/dist/physics/transform-writer.d.ts +0 -16
- package/dist/physics/transform-writer.d.ts.map +0 -1
- package/dist/physics/transform-writer.js +0 -38
- package/dist/physics/trigger-dispatch.d.ts +0 -24
- package/dist/physics/trigger-dispatch.d.ts.map +0 -1
- package/dist/physics/trigger-dispatch.js +0 -80
- package/dist/react/game-state.d.ts +0 -105
- package/dist/react/game-state.d.ts.map +0 -1
- package/dist/react/game-state.js +0 -144
- package/dist/react/use-data.d.ts +0 -60
- package/dist/react/use-data.d.ts.map +0 -1
- package/dist/react/use-data.js +0 -96
- package/dist/react/use-selection.d.ts +0 -75
- package/dist/react/use-selection.d.ts.map +0 -1
- package/dist/react/use-selection.js +0 -90
- package/dist/render/auto-batcher.d.ts +0 -34
- package/dist/render/auto-batcher.d.ts.map +0 -1
- package/dist/render/auto-batcher.js +0 -140
- package/dist/render/render-batch-system.d.ts +0 -33
- package/dist/render/render-batch-system.d.ts.map +0 -1
- package/dist/render/render-batch-system.js +0 -230
- package/dist/render/render-features.d.ts +0 -47
- package/dist/render/render-features.d.ts.map +0 -1
- package/dist/render/render-features.js +0 -105
- package/dist/render/render-settings.d.ts +0 -36
- package/dist/render/render-settings.d.ts.map +0 -1
- package/dist/render/render-settings.js +0 -51
- package/dist/runtime/create-runtime.d.ts +0 -280
- package/dist/runtime/create-runtime.d.ts.map +0 -1
- package/dist/runtime/create-runtime.js +0 -795
- package/dist/runtime/frame-selector-cache.d.ts +0 -41
- package/dist/runtime/frame-selector-cache.d.ts.map +0 -1
- package/dist/runtime/frame-selector-cache.js +0 -65
- package/dist/runtime/game.d.ts +0 -433
- package/dist/runtime/game.d.ts.map +0 -1
- package/dist/runtime/game.js +0 -569
- package/dist/runtime/input-router.d.ts +0 -78
- package/dist/runtime/input-router.d.ts.map +0 -1
- package/dist/runtime/input-router.js +0 -171
- package/dist/runtime/mount-game.d.ts +0 -129
- package/dist/runtime/mount-game.d.ts.map +0 -1
- package/dist/runtime/mount-game.js +0 -152
- package/dist/runtime/mount-manifest.d.ts +0 -119
- package/dist/runtime/mount-manifest.d.ts.map +0 -1
- package/dist/runtime/mount-manifest.js +0 -204
- package/dist/runtime/render-audio-control.d.ts +0 -110
- package/dist/runtime/render-audio-control.d.ts.map +0 -1
- package/dist/runtime/render-audio-control.js +0 -111
- package/dist/runtime/render-control.d.ts +0 -291
- package/dist/runtime/render-control.d.ts.map +0 -1
- package/dist/runtime/render-control.js +0 -264
- package/dist/runtime/render-seed.d.ts +0 -57
- package/dist/runtime/render-seed.d.ts.map +0 -1
- package/dist/runtime/render-seed.js +0 -74
- package/dist/runtime/scene-ui-bridge.d.ts +0 -69
- package/dist/runtime/scene-ui-bridge.d.ts.map +0 -1
- package/dist/runtime/scene-ui-bridge.js +0 -23
- package/dist/runtime/scene-ui-data.d.ts +0 -13
- package/dist/runtime/scene-ui-data.d.ts.map +0 -1
- package/dist/runtime/scene-ui-data.js +0 -92
- package/dist/runtime/state-bridge.d.ts +0 -47
- package/dist/runtime/state-bridge.d.ts.map +0 -1
- package/dist/runtime/state-bridge.js +0 -53
- package/dist/runtime/types.d.ts +0 -179
- package/dist/runtime/types.d.ts.map +0 -1
- package/dist/runtime/types.js +0 -1
- package/dist/scene/asset-loaders.d.ts +0 -79
- package/dist/scene/asset-loaders.d.ts.map +0 -1
- package/dist/scene/asset-loaders.js +0 -141
- package/dist/scene/asset-paths.d.ts +0 -11
- package/dist/scene/asset-paths.d.ts.map +0 -1
- package/dist/scene/asset-paths.js +0 -108
- package/dist/scene/asset-ref-check.d.ts +0 -88
- package/dist/scene/asset-ref-check.d.ts.map +0 -1
- package/dist/scene/asset-ref-check.js +0 -214
- package/dist/scene/asset-registry.d.ts +0 -30
- package/dist/scene/asset-registry.d.ts.map +0 -1
- package/dist/scene/asset-registry.js +0 -50
- package/dist/scene/collider-dimensions.d.ts +0 -63
- package/dist/scene/collider-dimensions.d.ts.map +0 -1
- package/dist/scene/collider-dimensions.js +0 -98
- package/dist/scene/component-registry.d.ts +0 -17
- package/dist/scene/component-registry.d.ts.map +0 -1
- package/dist/scene/component-registry.js +0 -28
- package/dist/scene/defaults.d.ts +0 -252
- package/dist/scene/defaults.d.ts.map +0 -1
- package/dist/scene/defaults.js +0 -151
- package/dist/scene/geometries/index.d.ts +0 -8
- package/dist/scene/geometries/index.d.ts.map +0 -1
- package/dist/scene/geometries/index.js +0 -7
- package/dist/scene/geometries/terrain.d.ts +0 -2
- package/dist/scene/geometries/terrain.d.ts.map +0 -1
- package/dist/scene/geometries/terrain.js +0 -37
- package/dist/scene/geometry-registry.d.ts +0 -24
- package/dist/scene/geometry-registry.d.ts.map +0 -1
- package/dist/scene/geometry-registry.js +0 -20
- package/dist/scene/instance-registry.d.ts +0 -36
- package/dist/scene/instance-registry.d.ts.map +0 -1
- package/dist/scene/instance-registry.js +0 -55
- package/dist/scene/instancers/grid.d.ts +0 -2
- package/dist/scene/instancers/grid.d.ts.map +0 -1
- package/dist/scene/instancers/grid.js +0 -36
- package/dist/scene/instancers/index.d.ts +0 -8
- package/dist/scene/instancers/index.d.ts.map +0 -1
- package/dist/scene/instancers/index.js +0 -7
- package/dist/scene/light-camera-factory.d.ts +0 -23
- package/dist/scene/light-camera-factory.d.ts.map +0 -1
- package/dist/scene/light-camera-factory.js +0 -68
- package/dist/scene/material-factory.d.ts +0 -17
- package/dist/scene/material-factory.d.ts.map +0 -1
- package/dist/scene/material-factory.js +0 -197
- package/dist/scene/material-registry.d.ts +0 -40
- package/dist/scene/material-registry.d.ts.map +0 -1
- package/dist/scene/material-registry.js +0 -44
- package/dist/scene/materials/index.d.ts +0 -8
- package/dist/scene/materials/index.d.ts.map +0 -1
- package/dist/scene/materials/index.js +0 -7
- package/dist/scene/materials/water.d.ts +0 -2
- package/dist/scene/materials/water.d.ts.map +0 -1
- package/dist/scene/materials/water.js +0 -54
- package/dist/scene/parse.d.ts +0 -23
- package/dist/scene/parse.d.ts.map +0 -1
- package/dist/scene/parse.js +0 -179
- package/dist/scene/particles-factory.d.ts +0 -33
- package/dist/scene/particles-factory.d.ts.map +0 -1
- package/dist/scene/particles-factory.js +0 -282
- package/dist/scene/scene-apply.d.ts +0 -109
- package/dist/scene/scene-apply.d.ts.map +0 -1
- package/dist/scene/scene-apply.js +0 -326
- package/dist/scene/scene-diff-schema.d.ts +0 -285
- package/dist/scene/scene-diff-schema.d.ts.map +0 -1
- package/dist/scene/scene-diff-schema.js +0 -92
- package/dist/scene/scene-diff-types.d.ts +0 -40
- package/dist/scene/scene-diff-types.d.ts.map +0 -1
- package/dist/scene/scene-diff-types.js +0 -14
- package/dist/scene/scene-loader.d.ts +0 -177
- package/dist/scene/scene-loader.d.ts.map +0 -1
- package/dist/scene/scene-loader.js +0 -1213
- package/dist/scene/scene-query.d.ts +0 -11
- package/dist/scene/scene-query.d.ts.map +0 -1
- package/dist/scene/scene-query.js +0 -63
- package/dist/scene/scene-types.d.ts +0 -10
- package/dist/scene/scene-types.d.ts.map +0 -1
- package/dist/scene/scene-types.js +0 -8
- package/dist/scene/scene-version.d.ts +0 -26
- package/dist/scene/scene-version.d.ts.map +0 -1
- package/dist/scene/scene-version.js +0 -34
- package/dist/scene/schema/animation.d.ts +0 -8
- package/dist/scene/schema/animation.d.ts.map +0 -1
- package/dist/scene/schema/animation.js +0 -42
- package/dist/scene/schema/audio.d.ts +0 -13
- package/dist/scene/schema/audio.d.ts.map +0 -1
- package/dist/scene/schema/audio.js +0 -22
- package/dist/scene/schema/camera.d.ts +0 -28
- package/dist/scene/schema/camera.d.ts.map +0 -1
- package/dist/scene/schema/camera.js +0 -17
- package/dist/scene/schema/collider.d.ts +0 -40
- package/dist/scene/schema/collider.d.ts.map +0 -1
- package/dist/scene/schema/collider.js +0 -55
- package/dist/scene/schema/entity-ref.d.ts +0 -31
- package/dist/scene/schema/entity-ref.d.ts.map +0 -1
- package/dist/scene/schema/entity-ref.js +0 -61
- package/dist/scene/schema/entity.d.ts +0 -1036
- package/dist/scene/schema/entity.d.ts.map +0 -1
- package/dist/scene/schema/entity.js +0 -153
- package/dist/scene/schema/environment.d.ts +0 -425
- package/dist/scene/schema/environment.d.ts.map +0 -1
- package/dist/scene/schema/environment.js +0 -357
- package/dist/scene/schema/index.d.ts +0 -39
- package/dist/scene/schema/index.d.ts.map +0 -1
- package/dist/scene/schema/index.js +0 -20
- package/dist/scene/schema/instances.d.ts +0 -14
- package/dist/scene/schema/instances.d.ts.map +0 -1
- package/dist/scene/schema/instances.js +0 -28
- package/dist/scene/schema/joint.d.ts +0 -23
- package/dist/scene/schema/joint.d.ts.map +0 -1
- package/dist/scene/schema/joint.js +0 -23
- package/dist/scene/schema/light.d.ts +0 -38
- package/dist/scene/schema/light.d.ts.map +0 -1
- package/dist/scene/schema/light.js +0 -26
- package/dist/scene/schema/material.d.ts +0 -199
- package/dist/scene/schema/material.d.ts.map +0 -1
- package/dist/scene/schema/material.js +0 -99
- package/dist/scene/schema/mesh.d.ts +0 -48
- package/dist/scene/schema/mesh.d.ts.map +0 -1
- package/dist/scene/schema/mesh.js +0 -82
- package/dist/scene/schema/particles.d.ts +0 -2178
- package/dist/scene/schema/particles.d.ts.map +0 -1
- package/dist/scene/schema/particles.js +0 -321
- package/dist/scene/schema/physics.d.ts +0 -56
- package/dist/scene/schema/physics.d.ts.map +0 -1
- package/dist/scene/schema/physics.js +0 -37
- package/dist/scene/schema/scene-file.d.ts +0 -304
- package/dist/scene/schema/scene-file.d.ts.map +0 -1
- package/dist/scene/schema/scene-file.js +0 -262
- package/dist/scene/schema/shadow.d.ts +0 -28
- package/dist/scene/schema/shadow.d.ts.map +0 -1
- package/dist/scene/schema/shadow.js +0 -20
- package/dist/scene/schema/spline.d.ts +0 -25
- package/dist/scene/schema/spline.d.ts.map +0 -1
- package/dist/scene/schema/spline.js +0 -15
- package/dist/scene/schema/tuples.d.ts +0 -12
- package/dist/scene/schema/tuples.d.ts.map +0 -1
- package/dist/scene/schema/tuples.js +0 -14
- package/dist/scene/schema/ui.d.ts +0 -880
- package/dist/scene/schema/ui.d.ts.map +0 -1
- package/dist/scene/schema/ui.js +0 -506
- package/dist/scene/user-data.d.ts +0 -171
- package/dist/scene/user-data.d.ts.map +0 -1
- package/dist/scene/user-data.js +0 -137
- package/dist/setup/setup-audio.d.ts +0 -20
- package/dist/setup/setup-audio.d.ts.map +0 -1
- package/dist/setup/setup-audio.js +0 -41
- package/dist/setup/setup-particles.d.ts +0 -17
- package/dist/setup/setup-particles.d.ts.map +0 -1
- package/dist/setup/setup-particles.js +0 -16
- package/dist/setup/setup-physics.d.ts +0 -25
- package/dist/setup/setup-physics.d.ts.map +0 -1
- package/dist/setup/setup-physics.js +0 -51
- package/dist/setup/setup-renderer.d.ts +0 -69
- package/dist/setup/setup-renderer.d.ts.map +0 -1
- package/dist/setup/setup-renderer.js +0 -363
- package/dist/tools/define-tool.d.ts +0 -105
- package/dist/tools/define-tool.d.ts.map +0 -1
- package/dist/tools/define-tool.js +0 -82
- package/dist/world2d/authoring-2d.d.ts +0 -76
- package/dist/world2d/authoring-2d.d.ts.map +0 -1
- package/dist/world2d/authoring-2d.js +0 -176
- package/dist/world2d/capture-to-scene2d.d.ts +0 -5
- package/dist/world2d/capture-to-scene2d.d.ts.map +0 -1
- package/dist/world2d/capture-to-scene2d.js +0 -49
- package/dist/world2d/collision-2d.d.ts +0 -52
- package/dist/world2d/collision-2d.d.ts.map +0 -1
- package/dist/world2d/collision-2d.js +0 -70
- package/dist/world2d/components-2d.d.ts +0 -47
- package/dist/world2d/components-2d.d.ts.map +0 -1
- package/dist/world2d/components-2d.js +0 -77
- package/dist/world2d/index.d.ts +0 -34
- package/dist/world2d/index.d.ts.map +0 -1
- package/dist/world2d/index.js +0 -32
- package/dist/world2d/ingest-iframe-2d.d.ts +0 -82
- package/dist/world2d/ingest-iframe-2d.d.ts.map +0 -1
- package/dist/world2d/ingest-iframe-2d.js +0 -166
- package/dist/world2d/ingest2d.d.ts +0 -97
- package/dist/world2d/ingest2d.d.ts.map +0 -1
- package/dist/world2d/ingest2d.js +0 -40
- package/dist/world2d/physics2d-registry.d.ts +0 -24
- package/dist/world2d/physics2d-registry.d.ts.map +0 -1
- package/dist/world2d/physics2d-registry.js +0 -38
- package/dist/world2d/pixi-game-adapter.d.ts +0 -107
- package/dist/world2d/pixi-game-adapter.d.ts.map +0 -1
- package/dist/world2d/pixi-game-adapter.js +0 -211
- package/dist/world2d/pixi-surface.d.ts +0 -39
- package/dist/world2d/pixi-surface.d.ts.map +0 -1
- package/dist/world2d/pixi-surface.js +0 -47
- package/dist/world2d/scene-capture-2d.d.ts +0 -43
- package/dist/world2d/scene-capture-2d.d.ts.map +0 -1
- package/dist/world2d/scene-capture-2d.js +0 -92
- package/dist/world2d/scene2d-loader.d.ts +0 -27
- package/dist/world2d/scene2d-loader.d.ts.map +0 -1
- package/dist/world2d/scene2d-loader.js +0 -274
- package/dist/world2d/schema/entity2d.d.ts +0 -102
- package/dist/world2d/schema/entity2d.d.ts.map +0 -1
- package/dist/world2d/schema/entity2d.js +0 -119
- package/dist/world2d/schema/physics2d.d.ts +0 -46
- package/dist/world2d/schema/physics2d.d.ts.map +0 -1
- package/dist/world2d/schema/physics2d.js +0 -45
- package/dist/world2d/schema/sprite.d.ts +0 -42
- package/dist/world2d/schema/sprite.d.ts.map +0 -1
- package/dist/world2d/schema/sprite.js +0 -63
- package/dist/world2d/schema/tilemap.d.ts +0 -15
- package/dist/world2d/schema/tilemap.d.ts.map +0 -1
- package/dist/world2d/schema/tilemap.js +0 -19
- package/dist/world2d/schema/tuples2d.d.ts +0 -20
- package/dist/world2d/schema/tuples2d.d.ts.map +0 -1
- package/dist/world2d/schema/tuples2d.js +0 -19
- package/dist/world2d/system-adapters-2d.d.ts +0 -16
- package/dist/world2d/system-adapters-2d.d.ts.map +0 -1
- package/dist/world2d/system-adapters-2d.js +0 -37
- package/dist/world2d/transform-writer-2d.d.ts +0 -16
- package/dist/world2d/transform-writer-2d.d.ts.map +0 -1
- package/dist/world2d/transform-writer-2d.js +0 -22
- package/dist/world2d/types.d.ts +0 -53
- package/dist/world2d/types.d.ts.map +0 -1
- package/dist/world2d/types.js +0 -1
- package/src/runtime/scene-ui-bridge.ts +0 -86
- package/src/runtime/scene-ui-data.ts +0 -119
- package/src/scene/schema/ui.ts +0 -602
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
+
import { assertNever } from '../adapter/adapter-surface';
|
|
2
3
|
import type {
|
|
3
4
|
GameAdapter,
|
|
4
5
|
MountedGame,
|
|
@@ -6,8 +7,6 @@ import type {
|
|
|
6
7
|
MountedWorld,
|
|
7
8
|
} from '../adapter/game-adapter';
|
|
8
9
|
import type { HostContext, LoopHandle } from '../adapter/host-context';
|
|
9
|
-
import { type VgaiSceneConfig, VgaiSceneGameAdapter } from '../adapter/vgai-scene-game-adapter';
|
|
10
|
-
import { assertNever } from '../adapter/world-kind';
|
|
11
10
|
import { createAssetCache } from '../assets';
|
|
12
11
|
import { createGameLoop } from '../core/game-loop';
|
|
13
12
|
import { createHostRenderer } from '../setup/setup-renderer';
|
|
@@ -25,7 +24,7 @@ import {
|
|
|
25
24
|
isFirstPartyMounted,
|
|
26
25
|
type WorldInstance,
|
|
27
26
|
} from './game';
|
|
28
|
-
import { createInputRouter, type
|
|
27
|
+
import { createInputRouter, type RouterAdapterRoot, stackOrder } from './input-router';
|
|
29
28
|
|
|
30
29
|
// Re-export the camera-precedence helper from its new home so existing importers
|
|
31
30
|
// (`import { adoptSceneCamera } from '@engine/runtime/create-runtime'`) keep working.
|
|
@@ -35,7 +34,7 @@ export { adoptSceneCamera } from '../adapter/vgai-scene-game-adapter';
|
|
|
35
34
|
* Register a threejs world for a freshly-mounted game onto the Game shell.
|
|
36
35
|
* Shared by `createGameRuntime` and every headless test harness
|
|
37
36
|
* (`test/game-root.test.ts`, `test/frame-order.test.ts`,
|
|
38
|
-
* `test/game-two-
|
|
37
|
+
* `test/game-two-roots.test.ts`) so there is exactly one code path for this
|
|
39
38
|
* wiring (T7.1 slice 1, id-generalized in slice 3 for the two-world proof —
|
|
40
39
|
* `docs/GAME-ROOT-DESIGN.md` §8 stage 3) — `physics`/`collisions`/`camera`/
|
|
41
40
|
* `frame` are populated from the mount's first-party `GameContext`/
|
|
@@ -94,25 +93,14 @@ export function registerThreeWorld(
|
|
|
94
93
|
return world;
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
/** Thin alias kept for existing single-world callers (`createGameRuntime`,
|
|
98
|
-
* `test/game-root.test.ts`, `test/frame-order.test.ts`) — registers the
|
|
99
|
-
* default `'main'` world via the SAME `registerThreeWorld` code path. */
|
|
100
|
-
export function registerDefaultThreeWorld(
|
|
101
|
-
game: GameInternal,
|
|
102
|
-
adapter: GameAdapter,
|
|
103
|
-
mounted: MountedGame,
|
|
104
|
-
): WorldInstance {
|
|
105
|
-
return registerThreeWorld(game, adapter, mounted);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
96
|
/**
|
|
109
97
|
* Register a pixijs world onto the Game shell — the pixi analog of
|
|
110
98
|
* {@link registerThreeWorld}, mirroring the wiring
|
|
111
99
|
* `world2d/pixi-game-adapter.ts`'s `createWorld2DRuntime` performs for its
|
|
112
100
|
* OWN (separate) Game, and `test/game-three-plus-pixi.test.ts` performs by
|
|
113
|
-
* hand onto a SHARED Game. `createGameRuntime`'s
|
|
101
|
+
* hand onto a SHARED Game. `createGameRuntime`'s roots path
|
|
114
102
|
* (T6.1 slice 1) is the first PRODUCTION caller that registers a pixijs
|
|
115
|
-
* world alongside other
|
|
103
|
+
* world alongside other roots on one Game; this is its one wiring code
|
|
116
104
|
* path, so a second/third pixijs world (or a future caller) never
|
|
117
105
|
* re-derives it. `adapter` is typed as the real {@link Pixi2DGameAdapter}
|
|
118
106
|
* shape (T7.5 — previously the generic `GameAdapter`, which forced a cast at
|
|
@@ -132,7 +120,7 @@ export function registerDefaultThreeWorld(
|
|
|
132
120
|
* only via `adapter as unknown as Pixi2DGameAdapter` (a custom module's actual
|
|
133
121
|
* return value is merely `MountedPixiWorld`-shaped, T7.5's cross-kind union),
|
|
134
122
|
* so the "never actually fire" premise no longer holds the moment a custom
|
|
135
|
-
* pixi module world reaches the
|
|
123
|
+
* pixi module world reaches the roots path. Rather than keep the throw (which
|
|
136
124
|
* would re-create exactly the kind of dead end D-X6 named and D-Y1 exists to
|
|
137
125
|
* remove), this now degrades EXACTLY like `registerThreeWorld`'s own foreign-
|
|
138
126
|
* mount handling above (`firstPartyExtras`): `physics2d`/`collisions2d`/
|
|
@@ -194,13 +182,13 @@ export function registerPixiWorld(
|
|
|
194
182
|
* its commits; `GameInternal.runFrame` correctly leaves a world with no
|
|
195
183
|
* `frame` untouched by its opaque-`update` fallback too, since
|
|
196
184
|
* `MountedReactGame` declares no `update`). `adapter` is typed as the real
|
|
197
|
-
* {@link
|
|
185
|
+
* {@link ReactRootAdapter} shape (T7.5, same reasoning as
|
|
198
186
|
* `registerPixiWorld`'s doc comment above) — `WorldInstance.adapter` only
|
|
199
187
|
* needs `.id`, so this passes through with zero cast.
|
|
200
188
|
*/
|
|
201
189
|
export function registerReactWorld(
|
|
202
190
|
game: GameInternal,
|
|
203
|
-
adapter:
|
|
191
|
+
adapter: ReactRootAdapter,
|
|
204
192
|
mounted: MountedReactGame,
|
|
205
193
|
container: HTMLElement,
|
|
206
194
|
opts?: { id?: string | undefined; pausable?: boolean | undefined },
|
|
@@ -217,28 +205,6 @@ export function registerReactWorld(
|
|
|
217
205
|
return world;
|
|
218
206
|
}
|
|
219
207
|
|
|
220
|
-
/**
|
|
221
|
-
* Configuration for {@link createGameRuntime}.
|
|
222
|
-
*
|
|
223
|
-
* The host depends on a {@link GameAdapter}. For convenience, the legacy
|
|
224
|
-
* first-party fields (`setup`/`scenePath`/`sceneData`/…) are accepted and wrapped
|
|
225
|
-
* in a {@link VgaiSceneGameAdapter} when no explicit `adapter` is given — so the
|
|
226
|
-
* host's default implementer is first-party, but the host itself only ever
|
|
227
|
-
* mounts "a GameAdapter".
|
|
228
|
-
*
|
|
229
|
-
* This is the LEGACY (single-world) shape — preserved byte-for-byte (T6.1
|
|
230
|
-
* slice 1, docs/MULTI-WORLD-DESIGN.md §1.A): every existing caller and test
|
|
231
|
-
* passes this shape unmodified. See {@link WorldsRuntimeConfig} for the new
|
|
232
|
-
* multi-world alternative and {@link RuntimeConfig} for the union.
|
|
233
|
-
*/
|
|
234
|
-
export interface LegacyRuntimeConfig extends VgaiSceneConfig {
|
|
235
|
-
canvas: HTMLCanvasElement;
|
|
236
|
-
width?: number | undefined;
|
|
237
|
-
height?: number | undefined;
|
|
238
|
-
/** An explicit game adapter to mount (first-party OR external). */
|
|
239
|
-
adapter?: GameAdapter | undefined;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
208
|
/**
|
|
243
209
|
* A pixijs-shaped adapter — the structural contract `WorldMountSpec`'s
|
|
244
210
|
* `pixijs` variant requires. `PixiSceneGameAdapter` (`world2d/
|
|
@@ -252,17 +218,17 @@ export interface Pixi2DGameAdapter {
|
|
|
252
218
|
}
|
|
253
219
|
|
|
254
220
|
/**
|
|
255
|
-
* One world to mount in the {@link WorldsRuntimeConfig}
|
|
221
|
+
* One world to mount in the {@link WorldsRuntimeConfig} roots path (T6.1
|
|
256
222
|
* slice 1) — the host-facing mirror of `manifest/load.ts`'s
|
|
257
|
-
* `
|
|
223
|
+
* `ResolvedAdapterRoot` (same `id`/`zOrder`/`pausable`/`loop` fields; the
|
|
258
224
|
* manifest-to-host translation itself is the editor's job, not this file's).
|
|
259
225
|
*
|
|
260
226
|
* `react` (T6.2 slice 1, `docs/REACT-WORLD-DESIGN.md`) mounts as a DOM-root
|
|
261
227
|
* layer `<div>` in the SAME stack instead of a canvas — see
|
|
262
|
-
* {@link ReactWorldMountSpec}/{@link
|
|
228
|
+
* {@link ReactWorldMountSpec}/{@link ReactRootAdapter} below.
|
|
263
229
|
*/
|
|
264
230
|
export interface WorldMountSpecBase {
|
|
265
|
-
/** Manifest id — must be unique within one `
|
|
231
|
+
/** Manifest id — must be unique within one `roots` array. */
|
|
266
232
|
readonly id: string;
|
|
267
233
|
/** Canvas stacking order (COMPOSITION-DESIGN D5 §1); ties broken by array
|
|
268
234
|
* order, mirroring `manifest/load.ts`'s `loadGameManifest` sort. Defaults
|
|
@@ -272,7 +238,7 @@ export interface WorldMountSpecBase {
|
|
|
272
238
|
readonly pausable?: boolean | undefined;
|
|
273
239
|
/** `'gated'` (host-driven, default) or `'self-driven'` (this world drives
|
|
274
240
|
* its own loop — D5's "composited, unsynchronized" tier). Carried through
|
|
275
|
-
* for parity with `
|
|
241
|
+
* for parity with `ResolvedAdapterRoot`; T6.1 slice 1 does not yet
|
|
276
242
|
* validate it against the mounted adapter's actual `drivesOwnLoop` (that
|
|
277
243
|
* cross-check, if ever needed, is T7.6's loop-gate surface). */
|
|
278
244
|
readonly loop?: 'gated' | 'self-driven' | undefined;
|
|
@@ -300,7 +266,7 @@ export interface PixiWorldMountSpec extends WorldMountSpecBase {
|
|
|
300
266
|
}
|
|
301
267
|
|
|
302
268
|
/**
|
|
303
|
-
* The host-facing surface handed to a {@link
|
|
269
|
+
* The host-facing surface handed to a {@link ReactRootAdapter}'s `mount`
|
|
304
270
|
* (T6.2 slice 1, `docs/REACT-WORLD-DESIGN.md` §1.B) — the react analog of
|
|
305
271
|
* {@link World2DHost}. `container` is the absolutely-positioned, z-ordered
|
|
306
272
|
* DOM-root layer `<div>` the host already created and stacked (same box/
|
|
@@ -334,7 +300,7 @@ export interface ReactWorldHost {
|
|
|
334
300
|
|
|
335
301
|
/**
|
|
336
302
|
* A live, mounted react world (T6.2 slice 1) — the react analog of
|
|
337
|
-
* {@link MountedGame2D}. React
|
|
303
|
+
* {@link MountedGame2D}. React roots host no ticking components (D8 —
|
|
338
304
|
* `ecs/component-manager.ts` already throws on any attach to a react-kind
|
|
339
305
|
* manager) and render from game state via the T7.4 bridge instead of a
|
|
340
306
|
* per-frame `update`, so this shape carries no `update`/`fixedUpdate`/
|
|
@@ -361,7 +327,7 @@ export interface ReactWorldHost {
|
|
|
361
327
|
* game-adapter.ts`) — `container` is the SAME `ReactWorldHost.container` the
|
|
362
328
|
* adapter's `mount` was handed (identity matters, mirroring `threeRoot()`/
|
|
363
329
|
* `pixiRoot()`'s "same instance the adapter mounted" contract); every
|
|
364
|
-
* `
|
|
330
|
+
* `ReactRootAdapter` implementer echoes it back here so `mounted` alone
|
|
365
331
|
* (with no separately-threaded `container`) satisfies the union
|
|
366
332
|
* `WorldInstanceInit.mounted`/`WorldInstance.mounted` with zero cast.
|
|
367
333
|
*/
|
|
@@ -376,35 +342,30 @@ export interface MountedReactGame extends MountedReactWorld {
|
|
|
376
342
|
* `default-react` resolver branch, T6.2's editor-side follow-up) can satisfy
|
|
377
343
|
* this shape without this file importing react-dom or any editor code.
|
|
378
344
|
*/
|
|
379
|
-
export interface
|
|
345
|
+
export interface ReactRootAdapter {
|
|
380
346
|
readonly id: string;
|
|
381
347
|
mount(host: ReactWorldHost): Promise<MountedReactGame>;
|
|
382
348
|
}
|
|
383
349
|
|
|
384
350
|
export interface ReactWorldMountSpec extends WorldMountSpecBase {
|
|
385
351
|
readonly kind: 'react';
|
|
386
|
-
readonly adapter:
|
|
352
|
+
readonly adapter: ReactRootAdapter;
|
|
387
353
|
}
|
|
388
354
|
|
|
389
355
|
export type WorldMountSpec = ThreeWorldMountSpec | PixiWorldMountSpec | ReactWorldMountSpec;
|
|
390
356
|
|
|
391
357
|
/**
|
|
392
|
-
*
|
|
393
|
-
* 1, docs/MULTI-WORLD-DESIGN.md §1.A; react worlds T6.2 slice 1,
|
|
394
|
-
* docs/REACT-WORLD-DESIGN.md §1.B): mount N worlds (threejs + pixijs + react)
|
|
358
|
+
* Mount N adapter roots (threejs + pixijs + react)
|
|
395
359
|
* on ONE `Game`, stacked in `container` per COMPOSITION-DESIGN D5 §1.
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
* first world" rule) is the default world, so
|
|
399
|
-
* `GameSession.scene`/`.camera`/`.mounted` keep aliasing exactly as they do
|
|
400
|
-
* today.
|
|
360
|
+
* `roots[0]` participates in `Game.defaultWorld`'s existing "first threejs
|
|
361
|
+
* root, else first root" rule.
|
|
401
362
|
*/
|
|
402
363
|
export interface WorldsRuntimeConfig {
|
|
403
364
|
/** The host creates one absolutely-positioned surface per world inside
|
|
404
365
|
* this element (D5 §1) — a canvas for threejs/pixijs, a DOM-root `<div>`
|
|
405
366
|
* layer for react — plus one shared UI overlay above all of them. */
|
|
406
367
|
container: HTMLElement;
|
|
407
|
-
|
|
368
|
+
roots: WorldMountSpec[];
|
|
408
369
|
width?: number | undefined;
|
|
409
370
|
height?: number | undefined;
|
|
410
371
|
/**
|
|
@@ -412,18 +373,20 @@ export interface WorldsRuntimeConfig {
|
|
|
412
373
|
* real `WebGLRenderer` construction for every threejs world in this
|
|
413
374
|
* session (a stand-in renderer is used instead, exactly as
|
|
414
375
|
* `VgaiSceneGameAdapter.mount` already special-cases `host.headless`
|
|
415
|
-
* internally). Pixijs
|
|
376
|
+
* internally). Pixijs roots are unaffected — Pixi already falls back to
|
|
416
377
|
* a 2D canvas renderer with no GPU. Never set `true` in a real host.
|
|
417
378
|
*/
|
|
418
379
|
headless?: boolean | undefined;
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
380
|
+
/** D15 (T-D15.1) — the root seed `ctx.random` boots from on every world
|
|
381
|
+
* mounted onto this session's Game, forwarded to `createGame` BEFORE any
|
|
382
|
+
* world's `mount()`/`setup()` runs (this function constructs the Game
|
|
383
|
+
* first — see `createWorldsGameRuntime`). The manifest-aware boot path
|
|
384
|
+
* (`mount-manifest.ts`'s `mountManifestWorlds`) is the real caller that
|
|
385
|
+
* resolves this from `manifest.determinism`/`?vgai-seed=`/its own
|
|
386
|
+
* explicit-config leg; a caller building `WorldsRuntimeConfig` by hand
|
|
387
|
+
* (a test, a bespoke host) may also set it directly. Omitting it falls
|
|
388
|
+
* back to `createGame`'s own fixed default. */
|
|
389
|
+
seed?: number | undefined;
|
|
427
390
|
}
|
|
428
391
|
|
|
429
392
|
/**
|
|
@@ -434,9 +397,8 @@ function isWorldsConfig(config: RuntimeConfig): config is WorldsRuntimeConfig {
|
|
|
434
397
|
* warm-restart hot reload) are reached by casting `mounted` to `VgaiMountedGame`
|
|
435
398
|
* (the editor does this for HMR/physics-sync — those are inherently first-party).
|
|
436
399
|
*
|
|
437
|
-
* `scene`/`camera`/`mounted` alias the Game's `defaultWorld
|
|
438
|
-
*
|
|
439
|
-
* before; for the worlds path it is the first threejs world (else the first
|
|
400
|
+
* `scene`/`camera`/`mounted` alias the Game's `defaultWorld`: it is the first
|
|
401
|
+
* threejs root (else the first
|
|
440
402
|
* world) by DECLARATION order, per `Game.defaultWorld`'s existing rule —
|
|
441
403
|
* independent of `zOrder`/canvas stacking, which is a rendering-only concern.
|
|
442
404
|
*/
|
|
@@ -451,7 +413,7 @@ export interface GameSession {
|
|
|
451
413
|
/** The mounted game (interface surface). Cast to `VgaiMountedGame` for first-party extras. */
|
|
452
414
|
readonly mounted: MountedGame;
|
|
453
415
|
/** The Game root (T6.1 slice 1) — the multi-world entry point
|
|
454
|
-
* (`game.
|
|
416
|
+
* (`game.roots`/`game.world(id)`/`game.queryByComponent`) for callers
|
|
455
417
|
* that need more than the default-world aliases above. */
|
|
456
418
|
readonly game: Game;
|
|
457
419
|
}
|
|
@@ -459,156 +421,12 @@ export interface GameSession {
|
|
|
459
421
|
/**
|
|
460
422
|
* Bootstrap the game host and mount a game adapter.
|
|
461
423
|
*
|
|
462
|
-
* `createGameRuntime` is the HOST: it owns the
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
* knows nothing about `.vscn`, `GameComponent`, Rapier, or `GameSetupFn` —
|
|
466
|
-
* those live inside the first-party {@link VgaiSceneGameAdapter}, which is
|
|
467
|
-
* the default implementer when no explicit `adapter` is supplied on the
|
|
468
|
-
* legacy path. Dispatches on `config`'s shape: {@link WorldsRuntimeConfig}
|
|
469
|
-
* (`worlds` present) goes through {@link createWorldsGameRuntime};
|
|
470
|
-
* everything else is the byte-compatible legacy single-world path.
|
|
424
|
+
* `createGameRuntime` is the universal HOST: it owns the root surfaces,
|
|
425
|
+
* renderers, loop, and asset cache. Every game — including a one-root game —
|
|
426
|
+
* uses the same explicit adapter-root path.
|
|
471
427
|
*/
|
|
472
|
-
export async function createGameRuntime(config:
|
|
473
|
-
|
|
474
|
-
return createWorldsGameRuntime(config);
|
|
475
|
-
}
|
|
476
|
-
const { canvas, width, height, adapter, ...sceneConfig } = config;
|
|
477
|
-
const w = Math.max(1, width ?? canvas.width);
|
|
478
|
-
const h = Math.max(1, height ?? canvas.height);
|
|
479
|
-
|
|
480
|
-
// --- Host primitives (neutral — no first-party assumptions) ---
|
|
481
|
-
const renderer = createHostRenderer(canvas, w, h);
|
|
482
|
-
const assets = createAssetCache();
|
|
483
|
-
|
|
484
|
-
let uiContainer: HTMLDivElement;
|
|
485
|
-
const existingUi = document.getElementById('example-ui');
|
|
486
|
-
if (existingUi instanceof HTMLDivElement) {
|
|
487
|
-
uiContainer = existingUi;
|
|
488
|
-
} else {
|
|
489
|
-
uiContainer = document.createElement('div');
|
|
490
|
-
uiContainer.id = 'example-ui';
|
|
491
|
-
uiContainer.style.cssText =
|
|
492
|
-
'position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:2;';
|
|
493
|
-
(canvas.parentElement ?? document.getElementById('ui-overlay') ?? document.body).appendChild(
|
|
494
|
-
uiContainer,
|
|
495
|
-
);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
const extraUpdaters = new Set<(dt: number) => void>();
|
|
499
|
-
const loopHandle: LoopHandle = {
|
|
500
|
-
onUpdate(fn) {
|
|
501
|
-
extraUpdaters.add(fn);
|
|
502
|
-
return () => extraUpdaters.delete(fn);
|
|
503
|
-
},
|
|
504
|
-
};
|
|
505
|
-
|
|
506
|
-
// --- Game root (T7.1 slice 1 + slice 2) ---
|
|
507
|
-
// The loop's update callback used to close directly over `mounted`, which
|
|
508
|
-
// only exists after `game.mount(host)` resolves. The Game shell (and thus
|
|
509
|
-
// its `loop`) must exist BEFORE mount so the mount can see `host.game` — so
|
|
510
|
-
// the callback instead consults a mutable ref, set once mount resolves.
|
|
511
|
-
// Behavior is identical: `loop.start()` still only runs after mount, same
|
|
512
|
-
// pause/step/stop semantics below. `drivesOwnLoop` handling now lives
|
|
513
|
-
// INSIDE `game.runFrame` (T7.1 slice 2) rather than being checked here —
|
|
514
|
-
// for today's single first-party (or single opaque host-driven) world this
|
|
515
|
-
// is byte-identical to the old `if (!mountedRef.drivesOwnLoop) mountedRef
|
|
516
|
-
// .update?.(dt)` guard (see `runFrame`'s doc comment in `runtime/game.ts`).
|
|
517
|
-
// `game` is referenced here before its `const` below only textually — this
|
|
518
|
-
// closure isn't invoked until `loop.start()`, well after `game` exists.
|
|
519
|
-
let mountedRef: MountedGame | null = null;
|
|
520
|
-
const loop = createGameLoop({
|
|
521
|
-
fixedTimestep: 1 / 60,
|
|
522
|
-
maxSubSteps: 8,
|
|
523
|
-
update: (dt) => {
|
|
524
|
-
if (mountedRef) game.runFrame(dt);
|
|
525
|
-
for (const fn of extraUpdaters) fn(dt);
|
|
526
|
-
},
|
|
527
|
-
});
|
|
528
|
-
const game = createGame({ loop, assets });
|
|
529
|
-
|
|
530
|
-
const host: HostContext = {
|
|
531
|
-
three: THREE,
|
|
532
|
-
surface: { canvas, width: w, height: h },
|
|
533
|
-
renderer,
|
|
534
|
-
loop: loopHandle,
|
|
535
|
-
assets,
|
|
536
|
-
ui: uiContainer,
|
|
537
|
-
game,
|
|
538
|
-
requestSystem: () => null,
|
|
539
|
-
};
|
|
540
|
-
|
|
541
|
-
// --- Mount the game adapter (first-party default, or an explicit adapter) ---
|
|
542
|
-
const gameAdapter = adapter ?? new VgaiSceneGameAdapter(sceneConfig);
|
|
543
|
-
const mounted = await gameAdapter.mount(host);
|
|
544
|
-
mountedRef = mounted;
|
|
545
|
-
|
|
546
|
-
// Register the default (and, in this slice, only) threejs world now that
|
|
547
|
-
// mount has produced a MountedGame — the world's `threeRoot()` must return
|
|
548
|
-
// the SAME scene instance the adapter mounted (identity is the contract).
|
|
549
|
-
registerDefaultThreeWorld(game, gameAdapter, mounted);
|
|
550
|
-
|
|
551
|
-
// Expose scene & camera for dev tools / e2e tests
|
|
552
|
-
if (import.meta.env?.DEV) {
|
|
553
|
-
const w = window as unknown as Record<string, unknown>;
|
|
554
|
-
w['__vgaiScene'] = mounted.scene;
|
|
555
|
-
w['__vgaiCamera'] = mounted.camera;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
loop.start();
|
|
559
|
-
|
|
560
|
-
function fullCleanup(): void {
|
|
561
|
-
loop.stop();
|
|
562
|
-
mounted.dispose();
|
|
563
|
-
renderer.dispose();
|
|
564
|
-
renderer.forceContextLoss();
|
|
565
|
-
// Retract the dev/e2e globals THIS session published (identity-guarded so
|
|
566
|
-
// a newer session's globals are never clobbered by an older session's
|
|
567
|
-
// stop). Leaving them dangling let e2e waits pass vacuously against a
|
|
568
|
-
// stopped game's scene/camera.
|
|
569
|
-
if (import.meta.env?.DEV) {
|
|
570
|
-
const w = window as unknown as Record<string, unknown>;
|
|
571
|
-
if (w['__vgaiScene'] === mounted.scene) delete w['__vgaiScene'];
|
|
572
|
-
if (w['__vgaiCamera'] === mounted.camera) delete w['__vgaiCamera'];
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
return {
|
|
577
|
-
stop: fullCleanup,
|
|
578
|
-
// D10/T7.6: `Game.play` (`runtime/game.ts`) is the real control surface —
|
|
579
|
-
// it fans out over every `pausable` world (just the one default world on
|
|
580
|
-
// this legacy single-world path) via its loop-gate/audio-gate capability,
|
|
581
|
-
// reporting honestly wherever a world can't actually be gated, and keeps
|
|
582
|
-
// `render` running every substep while paused (the old `loop.timeScale =
|
|
583
|
-
// 0` here starved the accumulator entirely — per D1, zero substeps means
|
|
584
|
-
// zero renders too — which is the bug this replaces, not a behavior to
|
|
585
|
-
// preserve).
|
|
586
|
-
pause() {
|
|
587
|
-
game.play.pause();
|
|
588
|
-
},
|
|
589
|
-
resume() {
|
|
590
|
-
game.play.resume();
|
|
591
|
-
},
|
|
592
|
-
step() {
|
|
593
|
-
game.play.step();
|
|
594
|
-
},
|
|
595
|
-
resize(rw: number, rh: number) {
|
|
596
|
-
const safeWidth = Math.max(1, rw);
|
|
597
|
-
const safeHeight = Math.max(1, rh);
|
|
598
|
-
renderer.setSize(safeWidth, safeHeight);
|
|
599
|
-
mounted.resize?.(safeWidth, safeHeight);
|
|
600
|
-
},
|
|
601
|
-
get scene() {
|
|
602
|
-
return mounted.scene as THREE.Scene;
|
|
603
|
-
},
|
|
604
|
-
get camera() {
|
|
605
|
-
return mounted.camera as THREE.PerspectiveCamera;
|
|
606
|
-
},
|
|
607
|
-
get mounted() {
|
|
608
|
-
return mounted;
|
|
609
|
-
},
|
|
610
|
-
game,
|
|
611
|
-
};
|
|
428
|
+
export async function createGameRuntime(config: WorldsRuntimeConfig): Promise<GameSession> {
|
|
429
|
+
return createWorldsGameRuntime(config);
|
|
612
430
|
}
|
|
613
431
|
|
|
614
432
|
// ---------------------------------------------------------------------------
|
|
@@ -616,7 +434,7 @@ export async function createGameRuntime(config: RuntimeConfig): Promise<GameSess
|
|
|
616
434
|
// ---------------------------------------------------------------------------
|
|
617
435
|
|
|
618
436
|
/** A stand-in `THREE.WebGLRenderer` for headless (`headless:true`) threejs
|
|
619
|
-
*
|
|
437
|
+
* roots — mirrors `VgaiSceneGameAdapter.mount`'s own `headlessComposer`
|
|
620
438
|
* pattern (`adapter/vgai-scene-game-adapter.ts`): a headless first-party
|
|
621
439
|
* mount never calls a render-phase method on `host.renderer` at all, so
|
|
622
440
|
* this only needs to satisfy the handful of calls THIS file itself makes
|
|
@@ -656,11 +474,26 @@ function derivePixiHitTest(
|
|
|
656
474
|
): ((x: number, y: number) => boolean) | undefined {
|
|
657
475
|
if ((mounted as { firstParty?: unknown }).firstParty !== true) return undefined;
|
|
658
476
|
const app = (mounted.ctx as unknown as { app?: unknown }).app as
|
|
659
|
-
| {
|
|
477
|
+
| {
|
|
478
|
+
renderer?: {
|
|
479
|
+
events?: {
|
|
480
|
+
rootBoundary?: {
|
|
481
|
+
rootTarget?: unknown;
|
|
482
|
+
hitTest?: (x: number, y: number) => unknown;
|
|
483
|
+
};
|
|
484
|
+
};
|
|
485
|
+
};
|
|
486
|
+
}
|
|
660
487
|
| undefined;
|
|
661
488
|
const rootBoundary = app?.renderer?.events?.rootBoundary;
|
|
662
489
|
if (!rootBoundary || typeof rootBoundary.hitTest !== 'function') return undefined;
|
|
663
|
-
|
|
490
|
+
// Pixi assigns `rootTarget` lazily on the first render. Pointer movement
|
|
491
|
+
// can reach the host router during that small window (or while a world is
|
|
492
|
+
// tearing down); EventBoundary.hitTest dereferences it unconditionally.
|
|
493
|
+
// An unready boundary cannot claim input, so degrade to no hit instead of
|
|
494
|
+
// surfacing Pixi's internal `undefined.eventMode` exception.
|
|
495
|
+
return (x: number, y: number) =>
|
|
496
|
+
rootBoundary.rootTarget != null && rootBoundary.hitTest!(x, y) != null;
|
|
664
497
|
}
|
|
665
498
|
|
|
666
499
|
/** One already-mounted world, tracked for disposal + the router. `element`
|
|
@@ -668,18 +501,18 @@ function derivePixiHitTest(
|
|
|
668
501
|
* pixijs, or the DOM-root layer `<div>` for react (T6.2 slice 1) — kept
|
|
669
502
|
* under one field name so `fullCleanup`'s disposal loop stays kind-generic
|
|
670
503
|
* (`container.removeChild(entry.element)` needs no branch). */
|
|
671
|
-
interface
|
|
504
|
+
interface MountedAdapterRoot {
|
|
672
505
|
readonly id: string;
|
|
673
506
|
readonly kind: 'threejs' | 'pixijs' | 'react';
|
|
674
507
|
readonly element: HTMLElement;
|
|
675
508
|
readonly mounted: MountedWorld;
|
|
676
|
-
/** Only threejs
|
|
509
|
+
/** Only threejs roots own a renderer this file constructed. */
|
|
677
510
|
readonly renderer: THREE.WebGLRenderer | undefined;
|
|
678
511
|
}
|
|
679
512
|
|
|
680
513
|
interface OneWorldResult {
|
|
681
|
-
readonly mountedEntry:
|
|
682
|
-
readonly routerEntry:
|
|
514
|
+
readonly mountedEntry: MountedAdapterRoot;
|
|
515
|
+
readonly routerEntry: RouterAdapterRoot;
|
|
683
516
|
}
|
|
684
517
|
|
|
685
518
|
/** Shared per-world mount inputs, computed once in `createWorldsGameRuntime`'s
|
|
@@ -694,7 +527,6 @@ interface OneWorldContext {
|
|
|
694
527
|
readonly dpr: number;
|
|
695
528
|
readonly isBottom: boolean;
|
|
696
529
|
readonly headless: boolean;
|
|
697
|
-
readonly uiContainer: HTMLDivElement;
|
|
698
530
|
readonly loopHandle: LoopHandle;
|
|
699
531
|
readonly assets: ReturnType<typeof createAssetCache>;
|
|
700
532
|
}
|
|
@@ -707,7 +539,7 @@ async function mountOneThreeWorld(
|
|
|
707
539
|
spec: ThreeWorldMountSpec,
|
|
708
540
|
ctx: OneWorldContext,
|
|
709
541
|
): Promise<OneWorldResult> {
|
|
710
|
-
const { game, canvas, w, h, dpr, isBottom, headless,
|
|
542
|
+
const { game, canvas, w, h, dpr, isBottom, headless, loopHandle, assets } = ctx;
|
|
711
543
|
const renderer = headless
|
|
712
544
|
? createHeadlessRendererStub()
|
|
713
545
|
: createHostRenderer(canvas, w, h, undefined, {
|
|
@@ -723,7 +555,7 @@ async function mountOneThreeWorld(
|
|
|
723
555
|
// loop above just set. The `renderer.setSize(w, h, false)` line right above
|
|
724
556
|
// this comment does NOT undo that stamp (updateStyle:false only skips
|
|
725
557
|
// TOUCHING style, it can't un-stamp a previous call) — so without this
|
|
726
|
-
// re-assertion, every
|
|
558
|
+
// re-assertion, every roots-path threejs canvas' on-screen size was
|
|
727
559
|
// permanently pinned to whatever `w`/`h` it happened to mount at (usually
|
|
728
560
|
// the manifest's `resolution`, since standalone builds mount before a real
|
|
729
561
|
// container size is known — see `mount-manifest.ts`). Re-asserting here
|
|
@@ -732,14 +564,14 @@ async function mountOneThreeWorld(
|
|
|
732
564
|
// fixes the template-standalone bug (broken at any viewport other than the
|
|
733
565
|
// manifest's `resolution`, which is also Playwright's DEFAULT viewport —
|
|
734
566
|
// why it went unnoticed) and, for free, tri-world's pre-existing
|
|
735
|
-
// resize-staleness (the
|
|
567
|
+
// resize-staleness (the roots-path `resize()` below always calls
|
|
736
568
|
// `setSize(rw, rh, false)`, so nothing else was ever going to update this
|
|
737
569
|
// canvas' CSS after mount). `createHostRenderer`'s own default
|
|
738
570
|
// (`updateStyle:true`) is intentionally left alone — the LEGACY
|
|
739
571
|
// single-canvas path (editor play-mode's non-multi-world branch) still
|
|
740
572
|
// relies on that construction-time stamp + its own later `updateStyle:true`
|
|
741
573
|
// resizes for byte-identical behavior; this fix touches only the
|
|
742
|
-
//
|
|
574
|
+
// roots-path canvas, after the fact.
|
|
743
575
|
canvas.style.width = '100%';
|
|
744
576
|
canvas.style.height = '100%';
|
|
745
577
|
renderer.setPixelRatio(dpr);
|
|
@@ -751,7 +583,6 @@ async function mountOneThreeWorld(
|
|
|
751
583
|
renderer,
|
|
752
584
|
loop: loopHandle,
|
|
753
585
|
assets,
|
|
754
|
-
ui: uiContainer,
|
|
755
586
|
headless,
|
|
756
587
|
game,
|
|
757
588
|
requestSystem: () => null,
|
|
@@ -775,7 +606,7 @@ async function mountOneThreeWorld(
|
|
|
775
606
|
* `canvas.style.width`/`.height` (real CSS px, matching the LOGICAL
|
|
776
607
|
* width/height passed to `resize()`) on every `app.renderer.resize()` call —
|
|
777
608
|
* including the one this world's `mounted.resize?.()` triggers from the
|
|
778
|
-
*
|
|
609
|
+
* roots-path `resize()` below. So while a pixi world's canvas can start
|
|
779
610
|
* pinned to the mount-time `w`/`h` (same as threejs, until PIXI's own
|
|
780
611
|
* construction-time resize runs), it self-heals the moment ANY real
|
|
781
612
|
* `session.resize(rw, rh)` fires — every shipped standalone entry
|
|
@@ -787,12 +618,12 @@ async function mountOnePixiWorld(
|
|
|
787
618
|
spec: PixiWorldMountSpec,
|
|
788
619
|
ctx: Omit<OneWorldContext, 'headless' | 'loopHandle' | 'assets'>,
|
|
789
620
|
): Promise<OneWorldResult> {
|
|
790
|
-
const { game, canvas, w, h, dpr, isBottom
|
|
621
|
+
const { game, canvas, w, h, dpr, isBottom } = ctx;
|
|
791
622
|
const pixiHost: World2DHost = {
|
|
792
623
|
canvas,
|
|
793
624
|
width: w,
|
|
794
625
|
height: h,
|
|
795
|
-
|
|
626
|
+
game,
|
|
796
627
|
dpr,
|
|
797
628
|
transparent: !isBottom,
|
|
798
629
|
preserveDrawingBuffer: true,
|
|
@@ -828,8 +659,7 @@ async function mountOnePixiWorld(
|
|
|
828
659
|
* `createWorldsGameRuntime`'s stack-building loop) but needs no entry in the
|
|
829
660
|
* delegating router's hit-test loop (§1.C — "DOM layers need no entry in the
|
|
830
661
|
* router's hit-test loop"): the layer's own `pointer-events` discipline
|
|
831
|
-
* (this file sets `none` on the layer by default
|
|
832
|
-
* `uiContainer`/HUD rule; the mounted react tree opts specific elements back
|
|
662
|
+
* (this file sets `none` on the layer by default; the mounted React tree opts specific elements back
|
|
833
663
|
* in with `pointer-events:auto`) is what lets its interactive elements claim
|
|
834
664
|
* events NATIVELY, via the real DOM, with zero router involvement — and lets
|
|
835
665
|
* a click over its non-interactive (transparent) area fall through to the
|
|
@@ -849,10 +679,10 @@ async function mountOneReactWorld(
|
|
|
849
679
|
* create its own) so `WorldInstance.reactRoot()` returns the SAME node
|
|
850
680
|
* that is actually positioned in the stack. */
|
|
851
681
|
layer: HTMLElement,
|
|
852
|
-
): Promise<{ mountedEntry:
|
|
682
|
+
): Promise<{ mountedEntry: MountedAdapterRoot }> {
|
|
853
683
|
layer.style.pointerEvents = 'none';
|
|
854
|
-
//
|
|
855
|
-
//
|
|
684
|
+
// An absolutely-positioned layer with no width/height collapses to zero
|
|
685
|
+
// content size, so a child's
|
|
856
686
|
// own position:absolute offsets resolve against a degenerate containing
|
|
857
687
|
// block (found by the T6.2 slice-3 e2e — clicks landed outside the game).
|
|
858
688
|
layer.style.width = '100%';
|
|
@@ -875,21 +705,21 @@ async function mountOneReactWorld(
|
|
|
875
705
|
}
|
|
876
706
|
|
|
877
707
|
/**
|
|
878
|
-
* The
|
|
879
|
-
* 1; react
|
|
708
|
+
* The roots-path implementer behind {@link createGameRuntime} (T6.1 slice
|
|
709
|
+
* 1; react roots added T6.2 slice 1). Builds ONE surface per world — a
|
|
880
710
|
* canvas for threejs/pixijs, a DOM-root `<div>` layer for react — stacked
|
|
881
711
|
* per COMPOSITION-DESIGN D5 §1, z-order/ties exactly matching
|
|
882
712
|
* `manifest/load.ts`'s sort, ONE `Game`, and registers every world onto it
|
|
883
713
|
* via `registerThreeWorld`/`registerPixiWorld`/`registerReactWorld` — the
|
|
884
714
|
* SAME wiring `test/game-three-plus-pixi.test.ts` proves by hand for the
|
|
885
|
-
* three/pixi pair. Worlds MOUNT in `
|
|
715
|
+
* three/pixi pair. Worlds MOUNT in `roots` ARRAY order (GAME-ROOT-DESIGN §4's
|
|
886
716
|
* "manifest declaration order" — the frame/registration axis), independent of
|
|
887
717
|
* `zOrder` (the canvas-stacking/rendering axis) — the two orders can differ
|
|
888
718
|
* and both are honored correctly.
|
|
889
719
|
*/
|
|
890
720
|
|
|
891
721
|
/**
|
|
892
|
-
* Dev/e2e-only `window.__vgaiScene`/`__vgaiCamera` exposure for the
|
|
722
|
+
* Dev/e2e-only `window.__vgaiScene`/`__vgaiCamera` exposure for the roots
|
|
893
723
|
* path's DEFAULT world (E4) — split out of `createWorldsGameRuntime` purely
|
|
894
724
|
* to keep that function's own cyclomatic complexity down. Mirrors the
|
|
895
725
|
* legacy single-world path's identical exposure (above, in this same file),
|
|
@@ -925,15 +755,15 @@ interface MountAllWorldsInputs extends Omit<OneWorldContext, 'canvas' | 'isBotto
|
|
|
925
755
|
}
|
|
926
756
|
|
|
927
757
|
interface MountAllWorldsResult {
|
|
928
|
-
readonly mountedEntries:
|
|
929
|
-
readonly routerEntries:
|
|
758
|
+
readonly mountedEntries: MountedAdapterRoot[];
|
|
759
|
+
readonly routerEntries: RouterAdapterRoot[];
|
|
930
760
|
}
|
|
931
761
|
|
|
932
762
|
/**
|
|
933
763
|
* Mount + register every world spec, in ARRAY (declaration) order — split
|
|
934
764
|
* out of `createWorldsGameRuntime` purely to keep that function's own
|
|
935
765
|
* cyclomatic complexity down (E4, same reason `mountOneThreeWorld`/
|
|
936
|
-
* `mountOnePixiWorld` are already split out). React
|
|
766
|
+
* `mountOnePixiWorld` are already split out). React roots contribute NO
|
|
937
767
|
* router entry (docs/REACT-WORLD-DESIGN.md §1.C — "DOM layers need no entry
|
|
938
768
|
* in the router's hit-test loop"): their layer's own `pointer-events`
|
|
939
769
|
* discipline handles claim/fall-through natively, with zero router
|
|
@@ -945,8 +775,8 @@ async function mountAllWorldSpecs(
|
|
|
945
775
|
inputs: MountAllWorldsInputs,
|
|
946
776
|
): Promise<MountAllWorldsResult> {
|
|
947
777
|
const { surfacesById, ...shared } = inputs;
|
|
948
|
-
const mountedEntries:
|
|
949
|
-
const routerEntries:
|
|
778
|
+
const mountedEntries: MountedAdapterRoot[] = [];
|
|
779
|
+
const routerEntries: RouterAdapterRoot[] = [];
|
|
950
780
|
|
|
951
781
|
for (const spec of mountSpecs) {
|
|
952
782
|
const isBottom = spec.id === bottomId;
|
|
@@ -958,15 +788,15 @@ async function mountAllWorldSpecs(
|
|
|
958
788
|
}
|
|
959
789
|
const canvas = surfacesById.get(spec.id)! as HTMLCanvasElement;
|
|
960
790
|
const oneCtx: OneWorldContext = { ...shared, canvas, isBottom };
|
|
961
|
-
let mountedEntry:
|
|
962
|
-
let routerEntry:
|
|
791
|
+
let mountedEntry: MountedAdapterRoot;
|
|
792
|
+
let routerEntry: RouterAdapterRoot;
|
|
963
793
|
if (spec.kind === 'threejs') {
|
|
964
794
|
({ mountedEntry, routerEntry } = await mountOneThreeWorld(spec, oneCtx));
|
|
965
795
|
} else if (spec.kind === 'pixijs') {
|
|
966
796
|
({ mountedEntry, routerEntry } = await mountOnePixiWorld(spec, oneCtx));
|
|
967
797
|
} else {
|
|
968
798
|
// Exhaustiveness guard (§7.4-2): 'react' was already handled by the
|
|
969
|
-
// early `continue` above, so only a hypothetical 4th `
|
|
799
|
+
// early `continue` above, so only a hypothetical 4th `AdapterSurface` can
|
|
970
800
|
// reach here — fail loudly rather than silently defaulting. `spec`
|
|
971
801
|
// itself (not `spec.kind`) is what TS has narrowed to `never`, since
|
|
972
802
|
// `WorldMountSpec` is a discriminated union at the object level.
|
|
@@ -979,9 +809,9 @@ async function mountAllWorldSpecs(
|
|
|
979
809
|
}
|
|
980
810
|
|
|
981
811
|
async function createWorldsGameRuntime(config: WorldsRuntimeConfig): Promise<GameSession> {
|
|
982
|
-
const { container,
|
|
812
|
+
const { container, roots: specs, width, height, headless = false, seed } = config;
|
|
983
813
|
if (specs.length === 0) {
|
|
984
|
-
throw new Error('createGameRuntime: `
|
|
814
|
+
throw new Error('createGameRuntime: `roots` must contain at least one root.');
|
|
985
815
|
}
|
|
986
816
|
const mountSpecs = specs as (ThreeWorldMountSpec | PixiWorldMountSpec | ReactWorldMountSpec)[];
|
|
987
817
|
|
|
@@ -1034,29 +864,19 @@ async function createWorldsGameRuntime(config: WorldsRuntimeConfig): Promise<Gam
|
|
|
1034
864
|
// too (not just in `mountOneThreeWorld`) means every surface, whatever
|
|
1035
865
|
// kind, starts container-relative from its very first paint, before any
|
|
1036
866
|
// per-kind mount work has even run.
|
|
1037
|
-
|
|
867
|
+
// `contain:layout paint` makes each surface the CONTAINING BLOCK for
|
|
868
|
+
// `position:fixed` descendants (and clips overflow to the world's
|
|
869
|
+
// rectangle): full-screen game UI written the natural way (`fixed;
|
|
870
|
+
// inset:0`) then fills the WORLD, not the page. Without it, `fixed` UI
|
|
871
|
+
// looks correct standalone (surface == window) but escapes over the
|
|
872
|
+
// editor chrome whenever the surface is a sub-rectangle of the page —
|
|
873
|
+
// and toggles behavior when any ancestor gains a transform (e.g. the
|
|
874
|
+
// editor's space-pan). Dogfooded 2026-07-12 via a react shell world.
|
|
875
|
+
surface.style.cssText = `position:absolute;top:0;left:0;width:100%;height:100%;z-index:${i + 1};contain:layout paint;`;
|
|
1038
876
|
container.appendChild(surface);
|
|
1039
877
|
surfacesById.set(entry.id, surface);
|
|
1040
878
|
});
|
|
1041
879
|
|
|
1042
|
-
// One shared UI overlay, above every canvas. I8 render-integration seam
|
|
1043
|
-
// (docs/AI-NATIVE-AUTHORING-IMPLEMENTATION-SPEC.md §15 I8, C1 review note):
|
|
1044
|
-
// the legacy single-world path (above) reuses/stamps a stable `#example-ui`
|
|
1045
|
-
// id so a capture host has a reliable selector for "the HUD/letterbox
|
|
1046
|
-
// overlay" — this worlds path had no such id at all, so a render-mode page
|
|
1047
|
-
// built on `createWorldsGameRuntime` (multi-world manifests, including a
|
|
1048
|
-
// react-HUD-over-threejs cinematic) had no stable selector to composite-
|
|
1049
|
-
// screenshot. `vgai-ui-overlay` is deliberately a DIFFERENT id than the
|
|
1050
|
-
// legacy path's `example-ui` (not reused/aliased) — the two runtime paths
|
|
1051
|
-
// mount genuinely different DOM subtrees, and collapsing them onto one id
|
|
1052
|
-
// would make a caller's selector ambiguous about which mount produced it.
|
|
1053
|
-
const uiContainer = document.createElement('div');
|
|
1054
|
-
uiContainer.id = 'vgai-ui-overlay';
|
|
1055
|
-
uiContainer.style.cssText =
|
|
1056
|
-
`position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;` +
|
|
1057
|
-
`z-index:${stacked.length + 1};`;
|
|
1058
|
-
container.appendChild(uiContainer);
|
|
1059
|
-
|
|
1060
880
|
const assets = createAssetCache();
|
|
1061
881
|
const extraUpdaters = new Set<(dt: number) => void>();
|
|
1062
882
|
const loopHandle: LoopHandle = {
|
|
@@ -1074,7 +894,7 @@ async function createWorldsGameRuntime(config: WorldsRuntimeConfig): Promise<Gam
|
|
|
1074
894
|
for (const fn of extraUpdaters) fn(dt);
|
|
1075
895
|
},
|
|
1076
896
|
});
|
|
1077
|
-
const game = createGame({ loop, assets });
|
|
897
|
+
const game = createGame({ loop, assets, seed });
|
|
1078
898
|
|
|
1079
899
|
// --- Mount + register every world, in ARRAY (declaration) order. ---
|
|
1080
900
|
// Split out into its own top-level function purely to keep
|
|
@@ -1088,7 +908,6 @@ async function createWorldsGameRuntime(config: WorldsRuntimeConfig): Promise<Gam
|
|
|
1088
908
|
h,
|
|
1089
909
|
dpr,
|
|
1090
910
|
headless,
|
|
1091
|
-
uiContainer,
|
|
1092
911
|
loopHandle,
|
|
1093
912
|
assets,
|
|
1094
913
|
});
|
|
@@ -1101,7 +920,7 @@ async function createWorldsGameRuntime(config: WorldsRuntimeConfig): Promise<Gam
|
|
|
1101
920
|
|
|
1102
921
|
// Expose scene & camera for dev tools / e2e tests — mirrors the legacy
|
|
1103
922
|
// single-world path's identical dev-only exposure above, generalized to
|
|
1104
|
-
// the
|
|
923
|
+
// the roots path's DEFAULT world (E4, docs/unified-world-editor/
|
|
1105
924
|
// 27-visual-react-editing.md §7 E4): `mountGameFromManifest`/
|
|
1106
925
|
// `mountManifestWorlds` route every caller (including a single-threejs-
|
|
1107
926
|
// world scaffold project) through THIS path, so a caller migrating off
|
|
@@ -1121,7 +940,6 @@ async function createWorldsGameRuntime(config: WorldsRuntimeConfig): Promise<Gam
|
|
|
1121
940
|
entry.renderer?.forceContextLoss();
|
|
1122
941
|
container.removeChild(entry.element);
|
|
1123
942
|
}
|
|
1124
|
-
container.removeChild(uiContainer);
|
|
1125
943
|
retractDevGlobals();
|
|
1126
944
|
}
|
|
1127
945
|
|
|
@@ -1155,7 +973,7 @@ async function createWorldsGameRuntime(config: WorldsRuntimeConfig): Promise<Gam
|
|
|
1155
973
|
// convenience shaped for the threejs-only past. T7.5 narrows the read via
|
|
1156
974
|
// the `kind` discriminant instead of a blind `.scene`/`.camera` cast
|
|
1157
975
|
// through a nonexistent property (identical behavior to before: still
|
|
1158
|
-
// `undefined` for a
|
|
976
|
+
// `undefined` for a roots-path session whose default world isn't
|
|
1159
977
|
// threejs — real per-world surface routing for that case is T7.6's).
|
|
1160
978
|
get scene() {
|
|
1161
979
|
const m = game.defaultWorld.mounted;
|