@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
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
export interface PerformanceTiming {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly ms: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface PerformanceFrame {
|
|
7
|
+
readonly id: number;
|
|
8
|
+
readonly timestamp: number;
|
|
9
|
+
readonly intervalMs: number;
|
|
10
|
+
readonly cpuMs: number;
|
|
11
|
+
readonly phases: readonly PerformanceTiming[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PerformanceSnapshot {
|
|
15
|
+
readonly enabled: boolean;
|
|
16
|
+
readonly recording: boolean;
|
|
17
|
+
readonly fps: number;
|
|
18
|
+
readonly cpuMs: number;
|
|
19
|
+
readonly p95Ms: number;
|
|
20
|
+
readonly p99Ms: number;
|
|
21
|
+
readonly frames: readonly PerformanceFrame[];
|
|
22
|
+
readonly phases: readonly PerformanceTiming[];
|
|
23
|
+
readonly systems: readonly PerformanceTiming[];
|
|
24
|
+
readonly components: readonly PerformanceTiming[];
|
|
25
|
+
readonly render: {
|
|
26
|
+
readonly gpuMs: number | null;
|
|
27
|
+
readonly drawCalls: number;
|
|
28
|
+
readonly triangles: number;
|
|
29
|
+
readonly geometries: number;
|
|
30
|
+
readonly textures: number;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const now = () => globalThis.performance?.now() ?? Date.now();
|
|
35
|
+
|
|
36
|
+
function percentile(values: readonly number[], fraction: number): number {
|
|
37
|
+
if (values.length === 0) return 0;
|
|
38
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
39
|
+
return sorted[Math.min(sorted.length - 1, Math.floor((sorted.length - 1) * fraction))] ?? 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Game-owned, bounded external store for browser-native performance diagnostics. */
|
|
43
|
+
export function createPerformanceProfiler(initiallyEnabled = false) {
|
|
44
|
+
const listeners = new Set<() => void>();
|
|
45
|
+
const frames: PerformanceFrame[] = [];
|
|
46
|
+
const currentPhases = new Map<string, number>();
|
|
47
|
+
const currentSystems = new Map<string, number>();
|
|
48
|
+
const currentComponents = new Map<string, number>();
|
|
49
|
+
let enabled = initiallyEnabled;
|
|
50
|
+
let recording = false;
|
|
51
|
+
let frameId = 0;
|
|
52
|
+
let frameStart = 0;
|
|
53
|
+
let lastFrameStart = 0;
|
|
54
|
+
let phaseStart = 0;
|
|
55
|
+
let systemStart = 0;
|
|
56
|
+
let componentStart = 0;
|
|
57
|
+
let render = {
|
|
58
|
+
gpuMs: null as number | null,
|
|
59
|
+
drawCalls: 0,
|
|
60
|
+
triangles: 0,
|
|
61
|
+
geometries: 0,
|
|
62
|
+
textures: 0,
|
|
63
|
+
};
|
|
64
|
+
let snapshot: PerformanceSnapshot = {
|
|
65
|
+
enabled,
|
|
66
|
+
recording,
|
|
67
|
+
fps: 0,
|
|
68
|
+
cpuMs: 0,
|
|
69
|
+
p95Ms: 0,
|
|
70
|
+
p99Ms: 0,
|
|
71
|
+
frames,
|
|
72
|
+
phases: [],
|
|
73
|
+
systems: [],
|
|
74
|
+
components: [],
|
|
75
|
+
render,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
function publish(): void {
|
|
79
|
+
const latest = frames.at(-1);
|
|
80
|
+
const intervals = frames.map((frame) => frame.intervalMs).filter((value) => value > 0);
|
|
81
|
+
snapshot = {
|
|
82
|
+
enabled,
|
|
83
|
+
recording,
|
|
84
|
+
fps: latest?.intervalMs ? 1000 / latest.intervalMs : 0,
|
|
85
|
+
cpuMs: latest?.cpuMs ?? 0,
|
|
86
|
+
p95Ms: percentile(intervals, 0.95),
|
|
87
|
+
p99Ms: percentile(intervals, 0.99),
|
|
88
|
+
frames,
|
|
89
|
+
phases: latest?.phases ?? [],
|
|
90
|
+
systems: [...currentSystems].map(([name, ms]) => ({ name, ms })).sort((a, b) => b.ms - a.ms),
|
|
91
|
+
components: [...currentComponents]
|
|
92
|
+
.map(([name, ms]) => ({ name, ms }))
|
|
93
|
+
.sort((a, b) => b.ms - a.ms),
|
|
94
|
+
render,
|
|
95
|
+
};
|
|
96
|
+
for (const listener of listeners) listener();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
get enabled() {
|
|
101
|
+
return enabled;
|
|
102
|
+
},
|
|
103
|
+
set enabled(value: boolean) {
|
|
104
|
+
if (enabled === value) return;
|
|
105
|
+
enabled = value;
|
|
106
|
+
publish();
|
|
107
|
+
},
|
|
108
|
+
get recording() {
|
|
109
|
+
return recording;
|
|
110
|
+
},
|
|
111
|
+
startRecording() {
|
|
112
|
+
enabled = true;
|
|
113
|
+
recording = true;
|
|
114
|
+
frames.length = 0;
|
|
115
|
+
publish();
|
|
116
|
+
},
|
|
117
|
+
stopRecording() {
|
|
118
|
+
recording = false;
|
|
119
|
+
publish();
|
|
120
|
+
},
|
|
121
|
+
clear() {
|
|
122
|
+
frames.length = 0;
|
|
123
|
+
publish();
|
|
124
|
+
},
|
|
125
|
+
beginFrame() {
|
|
126
|
+
if (!enabled) return;
|
|
127
|
+
currentPhases.clear();
|
|
128
|
+
currentSystems.clear();
|
|
129
|
+
currentComponents.clear();
|
|
130
|
+
render = { gpuMs: null, drawCalls: 0, triangles: 0, geometries: 0, textures: 0 };
|
|
131
|
+
frameStart = now();
|
|
132
|
+
},
|
|
133
|
+
beginPhase() {
|
|
134
|
+
if (!enabled) return;
|
|
135
|
+
phaseStart = now();
|
|
136
|
+
},
|
|
137
|
+
endPhase(name: string) {
|
|
138
|
+
if (!enabled) return;
|
|
139
|
+
const elapsed = now() - phaseStart;
|
|
140
|
+
currentPhases.set(name, (currentPhases.get(name) ?? 0) + elapsed);
|
|
141
|
+
if (recording)
|
|
142
|
+
performance.measure(`vgai.phase.${name}`, { start: phaseStart, duration: elapsed });
|
|
143
|
+
},
|
|
144
|
+
systemObserver: {
|
|
145
|
+
beginSystem() {
|
|
146
|
+
if (!enabled) return;
|
|
147
|
+
systemStart = now();
|
|
148
|
+
},
|
|
149
|
+
endSystem(scope: string, phase: string, name: string) {
|
|
150
|
+
if (!enabled) return;
|
|
151
|
+
const end = now();
|
|
152
|
+
const key = `${scope} / ${phase} / ${name}`;
|
|
153
|
+
currentSystems.set(key, (currentSystems.get(key) ?? 0) + end - systemStart);
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
beginComponent() {
|
|
157
|
+
if (!recording) return;
|
|
158
|
+
componentStart = now();
|
|
159
|
+
},
|
|
160
|
+
endComponent(name: string) {
|
|
161
|
+
if (!recording) return;
|
|
162
|
+
currentComponents.set(name, (currentComponents.get(name) ?? 0) + now() - componentStart);
|
|
163
|
+
},
|
|
164
|
+
reportRender(stats: {
|
|
165
|
+
gpuMs: number | null;
|
|
166
|
+
drawCalls: number;
|
|
167
|
+
triangles: number;
|
|
168
|
+
geometries: number;
|
|
169
|
+
textures: number;
|
|
170
|
+
}) {
|
|
171
|
+
if (!enabled) return;
|
|
172
|
+
render = {
|
|
173
|
+
gpuMs: stats.gpuMs ?? render.gpuMs,
|
|
174
|
+
drawCalls: render.drawCalls + stats.drawCalls,
|
|
175
|
+
triangles: render.triangles + stats.triangles,
|
|
176
|
+
geometries: render.geometries + stats.geometries,
|
|
177
|
+
textures: render.textures + stats.textures,
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
endFrame() {
|
|
181
|
+
if (!enabled) return;
|
|
182
|
+
const timestamp = now();
|
|
183
|
+
const intervalMs = lastFrameStart === 0 ? 0 : frameStart - lastFrameStart;
|
|
184
|
+
lastFrameStart = frameStart;
|
|
185
|
+
const frame: PerformanceFrame = {
|
|
186
|
+
id: ++frameId,
|
|
187
|
+
timestamp,
|
|
188
|
+
intervalMs,
|
|
189
|
+
cpuMs: timestamp - frameStart,
|
|
190
|
+
phases: [...currentPhases].map(([name, ms]) => ({ name, ms })).sort((a, b) => b.ms - a.ms),
|
|
191
|
+
};
|
|
192
|
+
frames.push(frame);
|
|
193
|
+
if (frames.length > 600) frames.splice(0, frames.length - 600);
|
|
194
|
+
if (recording)
|
|
195
|
+
performance.measure('vgai.frame', { start: frameStart, duration: frame.cpuMs });
|
|
196
|
+
publish();
|
|
197
|
+
},
|
|
198
|
+
subscribe(listener: () => void) {
|
|
199
|
+
listeners.add(listener);
|
|
200
|
+
return () => {
|
|
201
|
+
listeners.delete(listener);
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
getSnapshot() {
|
|
205
|
+
return snapshot;
|
|
206
|
+
},
|
|
207
|
+
exportJSON() {
|
|
208
|
+
return JSON.stringify({ version: 1, capturedAt: new Date().toISOString(), frames }, null, 2);
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export type PerformanceProfiler = ReturnType<typeof createPerformanceProfiler>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
interface DisjointTimerQueryExtension {
|
|
2
|
+
readonly TIME_ELAPSED_EXT: number;
|
|
3
|
+
readonly GPU_DISJOINT_EXT: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** Non-blocking WebGL2 timer query; results are consumed on later frames. */
|
|
7
|
+
export function createWebGLGpuTimer(context: WebGLRenderingContext | WebGL2RenderingContext) {
|
|
8
|
+
const gl = context as WebGL2RenderingContext;
|
|
9
|
+
const extension = gl.getExtension(
|
|
10
|
+
'EXT_disjoint_timer_query_webgl2',
|
|
11
|
+
) as DisjointTimerQueryExtension | null;
|
|
12
|
+
const supported = extension !== null && typeof gl.createQuery === 'function';
|
|
13
|
+
const pending: WebGLQuery[] = [];
|
|
14
|
+
let active: WebGLQuery | null = null;
|
|
15
|
+
let latestMs: number | null = null;
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
begin() {
|
|
19
|
+
if (!supported || active) return;
|
|
20
|
+
active = gl.createQuery();
|
|
21
|
+
if (active) gl.beginQuery(extension!.TIME_ELAPSED_EXT, active);
|
|
22
|
+
},
|
|
23
|
+
end() {
|
|
24
|
+
if (!supported || !active) return;
|
|
25
|
+
gl.endQuery(extension!.TIME_ELAPSED_EXT);
|
|
26
|
+
pending.push(active);
|
|
27
|
+
active = null;
|
|
28
|
+
},
|
|
29
|
+
poll(): number | null {
|
|
30
|
+
if (!supported) return null;
|
|
31
|
+
if (gl.getParameter(extension!.GPU_DISJOINT_EXT)) {
|
|
32
|
+
for (const query of pending.splice(0)) gl.deleteQuery(query);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
while (pending.length > 0) {
|
|
36
|
+
const query = pending[0]!;
|
|
37
|
+
if (!gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)) break;
|
|
38
|
+
pending.shift();
|
|
39
|
+
latestMs = (gl.getQueryParameter(query, gl.QUERY_RESULT) as number) / 1_000_000;
|
|
40
|
+
gl.deleteQuery(query);
|
|
41
|
+
}
|
|
42
|
+
return latestMs;
|
|
43
|
+
},
|
|
44
|
+
dispose() {
|
|
45
|
+
if (active) {
|
|
46
|
+
gl.endQuery(extension!.TIME_ELAPSED_EXT);
|
|
47
|
+
gl.deleteQuery(active);
|
|
48
|
+
active = null;
|
|
49
|
+
}
|
|
50
|
+
for (const query of pending.splice(0)) gl.deleteQuery(query);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -2,23 +2,28 @@ import type * as PIXI from 'pixi.js';
|
|
|
2
2
|
import type * as THREE from 'three';
|
|
3
3
|
import { PHASE_ORDER, type SystemPhaseName } from '../core/types';
|
|
4
4
|
import type { PhysicsRefs, PhysicsRegistry } from '../physics/physics-registry';
|
|
5
|
-
import { isFirstPartyMounted, type WorldInstance
|
|
5
|
+
import { type AdapterSurface, isFirstPartyMounted, type WorldInstance } from '../runtime/game';
|
|
6
6
|
import type { GameContext } from '../runtime/types';
|
|
7
7
|
import type { Physics2DRefs, Physics2DRegistry } from '../world2d/physics2d-registry';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
GameComponent,
|
|
10
|
+
type GameComponentClass,
|
|
11
|
+
linkGameComponentHmrClasses,
|
|
12
|
+
type NodeOf,
|
|
13
|
+
} from './game-component';
|
|
9
14
|
import { logHmrSwapMiss } from './hmr-swap-report';
|
|
10
15
|
|
|
11
16
|
/**
|
|
12
|
-
* The manager's node/instance types, widened over every `
|
|
13
|
-
* slice 2, D8 §3). `NodeOf<
|
|
17
|
+
* The manager's node/instance types, widened over every `AdapterSurface` (T7.2
|
|
18
|
+
* slice 2, D8 §3). `NodeOf<AdapterSurface>` distributes to `THREE.Object3D |
|
|
14
19
|
* PIXI.Container` (react contributes `never`, which drops out of the
|
|
15
20
|
* union) — this is what lets a single manager instance be constructed for
|
|
16
21
|
* ANY one kind (threejs, pixijs, or react) while still type-checking
|
|
17
22
|
* `attach()` calls made with a default-kind (`GameComponent`, K =
|
|
18
23
|
* 'threejs') instance, unmodified, from every existing call site.
|
|
19
24
|
*/
|
|
20
|
-
type AnyNode = NodeOf<
|
|
21
|
-
type AnyComponent = GameComponent<
|
|
25
|
+
type AnyNode = NodeOf<AdapterSurface>;
|
|
26
|
+
type AnyComponent = GameComponent<AdapterSurface>;
|
|
22
27
|
|
|
23
28
|
/**
|
|
24
29
|
* Optional identity a caller of `attach()` can supply for a component instance
|
|
@@ -42,10 +47,10 @@ export interface RegistryAttachInfo {
|
|
|
42
47
|
* ctx` identity (the same probe `isFirstPartyMounted` narrows for) rather
|
|
43
48
|
* than by id, so it works unmodified whether this manager belongs to the
|
|
44
49
|
* default world or a second/third registered world (`test/
|
|
45
|
-
* game-two-
|
|
50
|
+
* game-two-roots.test.ts`).
|
|
46
51
|
*
|
|
47
52
|
* WORLD-WIRING STATE (T7.2 slice 2 — was a KNOWN GAP in slice 1, now closed
|
|
48
|
-
* two ways): `ctx.game`/`ctx.
|
|
53
|
+
* two ways): `ctx.game`/`ctx.roots` exist from the start of `mount()`, but
|
|
49
54
|
* the `WorldInstance` itself is constructed by `registerThreeWorld` in
|
|
50
55
|
* `create-runtime.ts` only AFTER `mount()` returns — i.e. AFTER
|
|
51
56
|
* scene-authored components have already been attached by the scene loader
|
|
@@ -65,7 +70,7 @@ export interface RegistryAttachInfo {
|
|
|
65
70
|
*/
|
|
66
71
|
function resolveWorldInstance(ctx: GameContext): WorldInstance | undefined {
|
|
67
72
|
if (!ctx.game) return undefined;
|
|
68
|
-
for (const w of ctx.game.
|
|
73
|
+
for (const w of ctx.game.roots) {
|
|
69
74
|
if (isFirstPartyMounted(w.mounted) && w.mounted.ctx === ctx) return w;
|
|
70
75
|
}
|
|
71
76
|
return undefined;
|
|
@@ -98,7 +103,7 @@ function describeNode(node: AnyNode): string {
|
|
|
98
103
|
* `test/system-runs-before-component-tick.test.ts`).
|
|
99
104
|
*
|
|
100
105
|
* Kind (T7.2 slice 2, D8 §3): a manager is constructed for exactly ONE
|
|
101
|
-
* `
|
|
106
|
+
* `AdapterSurface` (`opts.kind`, default `'threejs'` — every existing call site
|
|
102
107
|
* omits it and gets the same manager slice 1 built). `attach()` enforces two
|
|
103
108
|
* rules against that kind, loudly:
|
|
104
109
|
* - a `'react'`-kind manager throws on EVERY attach (react entities host no
|
|
@@ -118,9 +123,9 @@ function describeNode(node: AnyNode): string {
|
|
|
118
123
|
export function createComponentManager(
|
|
119
124
|
ctx: GameContext,
|
|
120
125
|
physics?: PhysicsRegistry,
|
|
121
|
-
opts?: { kind?:
|
|
126
|
+
opts?: { kind?: AdapterSurface; physics2d?: Physics2DRegistry },
|
|
122
127
|
) {
|
|
123
|
-
const kind:
|
|
128
|
+
const kind: AdapterSurface = opts?.kind ?? 'threejs';
|
|
124
129
|
const physics2d = opts?.physics2d;
|
|
125
130
|
|
|
126
131
|
const byPhase = new Map<SystemPhaseName, AnyComponent[]>();
|
|
@@ -322,9 +327,12 @@ export function createComponentManager(
|
|
|
322
327
|
// flushed). Failures are loud — logged with the component name —
|
|
323
328
|
// never swallowed silently.
|
|
324
329
|
try {
|
|
330
|
+
ctx.game?.profiler.beginComponent();
|
|
325
331
|
inst.update(dt, ctx);
|
|
326
332
|
} catch (err) {
|
|
327
333
|
console.error(`[component-manager] ${inst.constructor.name}.update() threw:`, err);
|
|
334
|
+
} finally {
|
|
335
|
+
ctx.game?.profiler.endComponent(inst.constructor.name);
|
|
328
336
|
}
|
|
329
337
|
}
|
|
330
338
|
} finally {
|
|
@@ -362,6 +370,7 @@ export function createComponentManager(
|
|
|
362
370
|
if (!isMatch) return false;
|
|
363
371
|
const oldPhase = (inst.constructor as typeof GameComponent).phase ?? 'gameLogic';
|
|
364
372
|
const newPhase = (NewClass as unknown as typeof GameComponent).phase ?? 'gameLogic';
|
|
373
|
+
linkGameComponentHmrClasses(inst.constructor as unknown as GameComponentClass, NewClass);
|
|
365
374
|
Object.setPrototypeOf(inst, NewClass.prototype);
|
|
366
375
|
migratePhase(inst, oldPhase, newPhase);
|
|
367
376
|
reparseSchemaOnSwap(inst, NewClass, name);
|
|
@@ -601,6 +610,30 @@ export function createComponentManager(
|
|
|
601
610
|
return byEntity.get(node) ?? [];
|
|
602
611
|
},
|
|
603
612
|
|
|
613
|
+
/**
|
|
614
|
+
* Get the first attached instance of a given component class on an
|
|
615
|
+
* entity node — the typed single-component sibling of `getComponents`
|
|
616
|
+
* (issue #99: `onTriggerEnter`'s `other` is a raw node; this is how a
|
|
617
|
+
* handler asks "does my trigger partner have a `Collectible` (or
|
|
618
|
+
* whatever marker) component?" instead of an untyped `getComponents`
|
|
619
|
+
* walk or a fragile `other.name === '...'` display-name check).
|
|
620
|
+
* Matches via `instanceof`, so a subclass of `cls` is returned too
|
|
621
|
+
* (same subclass handling as `queryByComponent`). Same ordering as
|
|
622
|
+
* `getComponents` (attach order for that node) and, like
|
|
623
|
+
* `getComponents`, does NOT exclude instances pending-detach this tick
|
|
624
|
+
* — a caller inside a phase tick that cares should filter itself, same
|
|
625
|
+
* as any other `getComponents` consumer. `undefined` if the node has no
|
|
626
|
+
* attached instance of `cls`.
|
|
627
|
+
*/
|
|
628
|
+
getComponent<T extends AnyComponent>(node: AnyNode, cls: new () => T): T | undefined {
|
|
629
|
+
const instances = byEntity.get(node);
|
|
630
|
+
if (!instances) return undefined;
|
|
631
|
+
for (const inst of instances) {
|
|
632
|
+
if (inst instanceof cls) return inst;
|
|
633
|
+
}
|
|
634
|
+
return undefined;
|
|
635
|
+
},
|
|
636
|
+
|
|
604
637
|
/**
|
|
605
638
|
* Query all live attached instances of a given component class within
|
|
606
639
|
* THIS manager — the per-world half of the §5 cross-world query
|
|
@@ -4,30 +4,30 @@ import type * as PIXI from 'pixi.js';
|
|
|
4
4
|
import type * as THREE from 'three';
|
|
5
5
|
import type { z } from 'zod';
|
|
6
6
|
import type { SystemPhaseName } from '../core/types';
|
|
7
|
-
import type {
|
|
7
|
+
import type { AdapterSurface, WorldInstance } from '../runtime/game';
|
|
8
8
|
import type { GameContext } from '../runtime/types';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Map a {@link
|
|
11
|
+
* Map a {@link AdapterSurface} to its native world node type (T7.2, D8 —
|
|
12
12
|
* `docs/GAME-COMPONENT-GENERALIZATION.md` §2). `react` maps to `never`: react
|
|
13
13
|
* entities host no GameComponents (they render from game state via the T7.4
|
|
14
14
|
* state bridge instead).
|
|
15
15
|
*/
|
|
16
|
-
export type NodeOf<K extends
|
|
16
|
+
export type NodeOf<K extends AdapterSurface> = K extends 'threejs'
|
|
17
17
|
? THREE.Object3D
|
|
18
18
|
: K extends 'pixijs'
|
|
19
19
|
? PIXI.Container
|
|
20
20
|
: never;
|
|
21
21
|
|
|
22
|
-
/** Map a {@link
|
|
23
|
-
export type BodyOf<K extends
|
|
22
|
+
/** Map a {@link AdapterSurface} to its native Rapier rigid-body type. */
|
|
23
|
+
export type BodyOf<K extends AdapterSurface> = K extends 'threejs'
|
|
24
24
|
? RAPIER3D.RigidBody
|
|
25
25
|
: K extends 'pixijs'
|
|
26
26
|
? RAPIER2D.RigidBody
|
|
27
27
|
: never;
|
|
28
28
|
|
|
29
|
-
/** Map a {@link
|
|
30
|
-
export type ColliderOf<K extends
|
|
29
|
+
/** Map a {@link AdapterSurface} to its native Rapier collider type. */
|
|
30
|
+
export type ColliderOf<K extends AdapterSurface> = K extends 'threejs'
|
|
31
31
|
? RAPIER3D.Collider
|
|
32
32
|
: K extends 'pixijs'
|
|
33
33
|
? RAPIER2D.Collider
|
|
@@ -54,13 +54,97 @@ export type ColliderOf<K extends WorldKind> = K extends 'threejs'
|
|
|
54
54
|
* State lives on `this` (instance properties). On HMR, the engine swaps the
|
|
55
55
|
* prototype via Object.setPrototypeOf — instance state survives, method bodies
|
|
56
56
|
* update to the new code.
|
|
57
|
+
*
|
|
58
|
+
* `update` is deliberately mandatory, not optional like `init`/`dispose`
|
|
59
|
+
* (owner decision, issue #101): components are for BEHAVIOR. If your
|
|
60
|
+
* subclass's `update(dt, ctx)` body is empty, that is a signal the class may
|
|
61
|
+
* not need to be a component at all — a plain state-holder with only
|
|
62
|
+
* `init`/event methods (score/hits counters, etc.) usually belongs as a
|
|
63
|
+
* plain object or a static-scenery/UI object instead (see the "GameComponents
|
|
64
|
+
* are for things with behavior only" rule).
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Cross-copy brand (`Symbol.for` is process-global, so every physical copy of
|
|
68
|
+
* the engine shares ONE symbol): `x.prototype instanceof GameComponent` is
|
|
69
|
+
* FALSE when a project resolves TWO copies of the engine at once — the
|
|
70
|
+
* published `@vgai/engine/*` subpaths next to the `@engine/*` source alias,
|
|
71
|
+
* exactly what a scaffolded project's node-side scripts do (meteor-dodge
|
|
72
|
+
* dry-run friction: `validate-scenes --components` reported every field of a
|
|
73
|
+
* pristine scaffold's `SceneCamera` as unknown). Structural checks
|
|
74
|
+
* (`isGameComponentClass`) test this brand as well as `instanceof`.
|
|
57
75
|
*/
|
|
58
|
-
export
|
|
76
|
+
export const GAME_COMPONENT_BRAND = Symbol.for('vgai.GameComponent');
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* HMR class lineage. A true component hot-swap deliberately replaces a live
|
|
80
|
+
* instance's prototype with the newly imported class, but other already-live
|
|
81
|
+
* project modules can still hold the previous class object. Native
|
|
82
|
+
* `instanceof PreviousClass` would then become false even though the object is
|
|
83
|
+
* still the same component under the same hot-reload lineage. That broke both
|
|
84
|
+
* ordinary trigger guards (`component instanceof PlayerController`) and the
|
|
85
|
+
* canonical React-state selector (`game.queryByComponent(PlayerController)`).
|
|
86
|
+
*
|
|
87
|
+
* Keep this as class-to-class lineage rather than a string/name registry:
|
|
88
|
+
* minified classes, aliases, and two unrelated components with the same name
|
|
89
|
+
* remain distinct. The WeakMap owns no game/entity state and introduces no
|
|
90
|
+
* second identity model; it records only the exact constructor pairs the
|
|
91
|
+
* existing HMR boundary has actually swapped.
|
|
92
|
+
*/
|
|
93
|
+
type HmrComponentConstructor = abstract new (...args: never[]) => object;
|
|
94
|
+
|
|
95
|
+
const hmrLineages = new WeakMap<HmrComponentConstructor, Set<HmrComponentConstructor>>();
|
|
96
|
+
|
|
97
|
+
/** @internal Called only by ComponentManager's successful HMR swap path. */
|
|
98
|
+
export function linkGameComponentHmrClasses(
|
|
99
|
+
previous: HmrComponentConstructor,
|
|
100
|
+
next: HmrComponentConstructor,
|
|
101
|
+
): void {
|
|
102
|
+
const previousLineage = hmrLineages.get(previous);
|
|
103
|
+
const nextLineage = hmrLineages.get(next);
|
|
104
|
+
const merged = new Set<HmrComponentConstructor>([previous, next]);
|
|
105
|
+
if (previousLineage) {
|
|
106
|
+
for (const member of previousLineage) merged.add(member);
|
|
107
|
+
}
|
|
108
|
+
if (nextLineage) {
|
|
109
|
+
for (const member of nextLineage) merged.add(member);
|
|
110
|
+
}
|
|
111
|
+
for (const member of merged) hmrLineages.set(member, merged);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function classesShareHmrLineage(a: HmrComponentConstructor, b: HmrComponentConstructor): boolean {
|
|
115
|
+
return a === b || hmrLineages.get(a)?.has(b) === true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export abstract class GameComponent<K extends AdapterSurface = 'threejs'> {
|
|
59
119
|
/** Which phase this component's update runs in. Override in subclasses. */
|
|
60
120
|
static phase: SystemPhaseName = 'gameLogic';
|
|
61
121
|
|
|
122
|
+
/** See {@link GAME_COMPONENT_BRAND} — inherited by every subclass. */
|
|
123
|
+
static readonly [GAME_COMPONENT_BRAND] = true;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Preserve ordinary JavaScript `instanceof` across a true HMR prototype
|
|
127
|
+
* swap. Subclasses inherit this static hook, so `value instanceof
|
|
128
|
+
* PlayerController` first performs the native prototype-chain check and,
|
|
129
|
+
* only when that fails, accepts an exact constructor lineage previously
|
|
130
|
+
* linked by ComponentManager.hotSwap(). Non-HMR values retain byte-for-byte
|
|
131
|
+
* native semantics.
|
|
132
|
+
*/
|
|
133
|
+
static [Symbol.hasInstance](value: unknown): boolean {
|
|
134
|
+
// biome-ignore lint/complexity/noThisInStatic: Symbol.hasInstance is inherited; `this` must be the queried subclass, not the GameComponent base.
|
|
135
|
+
const expected = this as HmrComponentConstructor;
|
|
136
|
+
const nativeMatch = Function.prototype[Symbol.hasInstance].call(expected, value) as boolean;
|
|
137
|
+
if (nativeMatch) return true;
|
|
138
|
+
if (value === null || (typeof value !== 'object' && typeof value !== 'function')) return false;
|
|
139
|
+
const actual = (value as { constructor?: unknown }).constructor;
|
|
140
|
+
return (
|
|
141
|
+
typeof actual === 'function' &&
|
|
142
|
+
classesShareHmrLineage(expected, actual as HmrComponentConstructor)
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
62
146
|
/**
|
|
63
|
-
* Runtime-checkable declaration of which {@link
|
|
147
|
+
* Runtime-checkable declaration of which {@link AdapterSurface} this component
|
|
64
148
|
* is written for (T7.2, D8 §3 — `docs/GAME-COMPONENT-GENERALIZATION.md`).
|
|
65
149
|
* TS's `K` type parameter is erased at runtime, so this static is what the
|
|
66
150
|
* ComponentManager checks at attach time: a node whose world's kind
|
|
@@ -71,7 +155,7 @@ export abstract class GameComponent<K extends WorldKind = 'threejs'> {
|
|
|
71
155
|
* any world components are legal in (every world except `'react'`, which
|
|
72
156
|
* always throws regardless of `declaredKind` — see the ComponentManager).
|
|
73
157
|
*/
|
|
74
|
-
static declaredKind:
|
|
158
|
+
static declaredKind: AdapterSurface | 'any' = 'threejs';
|
|
75
159
|
|
|
76
160
|
/**
|
|
77
161
|
* Optional Zod object schema for this component's authored fields. When set,
|
|
@@ -88,7 +172,7 @@ export abstract class GameComponent<K extends WorldKind = 'threejs'> {
|
|
|
88
172
|
world!: WorldInstance;
|
|
89
173
|
|
|
90
174
|
/**
|
|
91
|
-
* Typed accessor, threejs
|
|
175
|
+
* Typed accessor, threejs roots only — kept for compatibility. On a
|
|
92
176
|
* `GameComponent` (default `K`) this types as `THREE.Object3D`, so every
|
|
93
177
|
* existing component compiles unchanged. On a non-threejs instance it
|
|
94
178
|
* THROWS a descriptive error rather than ever returning a wrong-kind node —
|