@vgai/engine 0.2.0 → 0.3.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/README.md +3 -1
- package/dist/adapter/authoring.d.ts +404 -0
- package/dist/adapter/authoring.d.ts.map +1 -0
- package/dist/adapter/authoring.js +22 -0
- package/dist/adapter/colyseus-networking-adapter.d.ts +43 -0
- package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -0
- package/dist/adapter/colyseus-networking-adapter.js +38 -0
- package/dist/adapter/first-party-systems.d.ts +38 -0
- package/dist/adapter/first-party-systems.d.ts.map +1 -0
- package/dist/adapter/first-party-systems.js +77 -0
- package/dist/adapter/game-adapter.d.ts +133 -0
- package/dist/adapter/game-adapter.d.ts.map +1 -0
- package/dist/adapter/game-adapter.js +10 -0
- package/dist/adapter/host-context.d.ts +73 -0
- package/dist/adapter/host-context.d.ts.map +1 -0
- package/dist/adapter/host-context.js +16 -0
- package/dist/adapter/index.d.ts +22 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +15 -0
- package/dist/adapter/ingest/game-contract.d.ts +53 -0
- package/dist/adapter/ingest/game-contract.d.ts.map +1 -0
- package/dist/adapter/ingest/game-contract.js +30 -0
- package/dist/adapter/ingest/overlay-applier.d.ts +118 -0
- package/dist/adapter/ingest/overlay-applier.d.ts.map +1 -0
- package/dist/adapter/ingest/overlay-applier.js +132 -0
- package/dist/adapter/ingest/overlay-apply.d.ts +60 -0
- package/dist/adapter/ingest/overlay-apply.d.ts.map +1 -0
- package/dist/adapter/ingest/overlay-apply.js +101 -0
- package/dist/adapter/ingest/overlay-file.d.ts +79 -0
- package/dist/adapter/ingest/overlay-file.d.ts.map +1 -0
- package/dist/adapter/ingest/overlay-file.js +66 -0
- package/dist/adapter/ingest/overlay-report.d.ts +113 -0
- package/dist/adapter/ingest/overlay-report.d.ts.map +1 -0
- package/dist/adapter/ingest/overlay-report.js +103 -0
- package/dist/adapter/ingest/scene-capture.d.ts +97 -0
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -0
- package/dist/adapter/ingest/scene-capture.js +248 -0
- package/dist/adapter/ingest/upstream-pin.d.ts +47 -0
- package/dist/adapter/ingest/upstream-pin.d.ts.map +1 -0
- package/dist/adapter/ingest/upstream-pin.js +50 -0
- package/dist/adapter/loop-gate-report.d.ts +34 -0
- package/dist/adapter/loop-gate-report.d.ts.map +1 -0
- package/dist/adapter/loop-gate-report.js +37 -0
- package/dist/adapter/rapier-physics-adapter.d.ts +12 -0
- package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -0
- package/dist/adapter/rapier-physics-adapter.js +46 -0
- package/dist/adapter/system-adapter.d.ts +133 -0
- package/dist/adapter/system-adapter.d.ts.map +1 -0
- package/dist/adapter/system-adapter.js +13 -0
- package/dist/adapter/transform.d.ts +18 -0
- package/dist/adapter/transform.d.ts.map +1 -0
- package/dist/adapter/transform.js +1 -0
- package/dist/adapter/vgai-scene-game-adapter.d.ts +116 -0
- package/dist/adapter/vgai-scene-game-adapter.d.ts.map +1 -0
- package/dist/adapter/vgai-scene-game-adapter.js +714 -0
- package/dist/adapter/world-kind.d.ts +30 -0
- package/dist/adapter/world-kind.d.ts.map +1 -0
- package/dist/adapter/world-kind.js +18 -0
- package/dist/ai/navigation.d.ts +64 -0
- package/dist/ai/navigation.d.ts.map +1 -0
- package/dist/ai/navigation.js +133 -0
- package/dist/animation/anim-graph-types.d.ts +25 -0
- package/dist/animation/anim-graph-types.d.ts.map +1 -0
- package/dist/animation/anim-graph-types.js +1 -0
- package/dist/animation/animation-clock.d.ts +213 -0
- package/dist/animation/animation-clock.d.ts.map +1 -0
- package/dist/animation/animation-clock.js +301 -0
- package/dist/animation/blend-node.d.ts +22 -0
- package/dist/animation/blend-node.d.ts.map +1 -0
- package/dist/animation/blend-node.js +97 -0
- package/dist/animation/camera-ownership.d.ts +250 -0
- package/dist/animation/camera-ownership.d.ts.map +1 -0
- package/dist/animation/camera-ownership.js +169 -0
- package/dist/animation/cinematic-cues.d.ts +200 -0
- package/dist/animation/cinematic-cues.d.ts.map +1 -0
- package/dist/animation/cinematic-cues.js +213 -0
- package/dist/animation/clip-map.d.ts +12 -0
- package/dist/animation/clip-map.d.ts.map +1 -0
- package/dist/animation/clip-map.js +37 -0
- package/dist/animation/gsap-registration.d.ts +119 -0
- package/dist/animation/gsap-registration.d.ts.map +1 -0
- package/dist/animation/gsap-registration.js +92 -0
- package/dist/animation/theatre-clock-binding.d.ts +89 -0
- package/dist/animation/theatre-clock-binding.d.ts.map +1 -0
- package/dist/animation/theatre-clock-binding.js +29 -0
- package/dist/animation/theatre-director.d.ts +242 -0
- package/dist/animation/theatre-director.d.ts.map +1 -0
- package/dist/animation/theatre-director.js +235 -0
- package/dist/animation/theatre-object-binding.d.ts +305 -0
- package/dist/animation/theatre-object-binding.d.ts.map +1 -0
- package/dist/animation/theatre-object-binding.js +351 -0
- package/dist/animation/xstate-animation-binding.d.ts +111 -0
- package/dist/animation/xstate-animation-binding.d.ts.map +1 -0
- package/dist/animation/xstate-animation-binding.js +307 -0
- package/dist/animation/xstate-animation-meta.d.ts +228 -0
- package/dist/animation/xstate-animation-meta.d.ts.map +1 -0
- package/dist/animation/xstate-animation-meta.js +221 -0
- package/dist/assets.d.ts +26 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +55 -0
- package/dist/audio/index.d.ts +4 -0
- package/dist/audio/index.d.ts.map +1 -0
- package/dist/audio/index.js +24 -0
- package/dist/audio/tone-clock-binding.d.ts +75 -0
- package/dist/audio/tone-clock-binding.d.ts.map +1 -0
- package/dist/audio/tone-clock-binding.js +29 -0
- package/dist/audio/tone-context.d.ts +114 -0
- package/dist/audio/tone-context.d.ts.map +1 -0
- package/dist/audio/tone-context.js +39 -0
- package/dist/audio/tone-offline-render.d.ts +90 -0
- package/dist/audio/tone-offline-render.d.ts.map +1 -0
- package/dist/audio/tone-offline-render.js +56 -0
- package/dist/audio/wav-encode.d.ts +38 -0
- package/dist/audio/wav-encode.d.ts.map +1 -0
- package/dist/audio/wav-encode.js +97 -0
- package/dist/core/game-loop.d.ts +21 -0
- package/dist/core/game-loop.d.ts.map +1 -0
- package/dist/core/game-loop.js +130 -0
- package/dist/core/system-runner.d.ts +120 -0
- package/dist/core/system-runner.d.ts.map +1 -0
- package/dist/core/system-runner.js +286 -0
- package/dist/core/types.d.ts +58 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +25 -0
- package/dist/data/data-asset.d.ts +101 -0
- package/dist/data/data-asset.d.ts.map +1 -0
- package/dist/data/data-asset.js +122 -0
- package/dist/data/data-check-core.d.ts +110 -0
- package/dist/data/data-check-core.d.ts.map +1 -0
- package/dist/data/data-check-core.js +178 -0
- package/dist/data/data-ref.d.ts +79 -0
- package/dist/data/data-ref.d.ts.map +1 -0
- package/dist/data/data-ref.js +130 -0
- package/dist/data/vite-plugin-data.d.ts +79 -0
- package/dist/data/vite-plugin-data.d.ts.map +1 -0
- package/dist/data/vite-plugin-data.js +217 -0
- package/dist/dev/console-bridge.d.ts +22 -0
- package/dist/dev/console-bridge.d.ts.map +1 -0
- package/dist/dev/console-bridge.js +71 -0
- package/dist/dev/debug-draw.d.ts +24 -0
- package/dist/dev/debug-draw.d.ts.map +1 -0
- package/dist/dev/debug-draw.js +73 -0
- package/dist/dev/logger.d.ts +30 -0
- package/dist/dev/logger.d.ts.map +1 -0
- package/dist/dev/logger.js +90 -0
- package/dist/ecs/component-manager.d.ts +189 -0
- package/dist/ecs/component-manager.d.ts.map +1 -0
- package/dist/ecs/component-manager.js +676 -0
- package/dist/ecs/game-component.d.ts +97 -0
- package/dist/ecs/game-component.d.ts.map +1 -0
- package/dist/ecs/game-component.js +80 -0
- package/dist/ecs/hmr-swap-report.d.ts +53 -0
- package/dist/ecs/hmr-swap-report.d.ts.map +1 -0
- package/dist/ecs/hmr-swap-report.js +55 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/input/input-manager.d.ts +596 -0
- package/dist/input/input-manager.d.ts.map +1 -0
- package/dist/input/input-manager.js +1564 -0
- package/dist/input/input-types.d.ts +171 -0
- package/dist/input/input-types.d.ts.map +1 -0
- package/dist/input/input-types.js +1 -0
- package/dist/input/prompt-labels.d.ts +21 -0
- package/dist/input/prompt-labels.d.ts.map +1 -0
- package/dist/input/prompt-labels.js +121 -0
- package/dist/input/rebind-controller.d.ts +59 -0
- package/dist/input/rebind-controller.d.ts.map +1 -0
- package/dist/input/rebind-controller.js +85 -0
- package/dist/input/schema.d.ts +16 -0
- package/dist/input/schema.d.ts.map +1 -0
- package/dist/input/schema.js +228 -0
- package/dist/loader.d.ts +43 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +59 -0
- package/dist/manifest/index.d.ts +5 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +8 -0
- package/dist/manifest/load-file.d.ts +4 -0
- package/dist/manifest/load-file.d.ts.map +1 -0
- package/dist/manifest/load-file.js +14 -0
- package/dist/manifest/load.d.ts +117 -0
- package/dist/manifest/load.d.ts.map +1 -0
- package/dist/manifest/load.js +255 -0
- package/dist/manifest/schema.d.ts +173 -0
- package/dist/manifest/schema.d.ts.map +1 -0
- package/dist/manifest/schema.js +302 -0
- package/dist/physics/collision-system.d.ts +41 -0
- package/dist/physics/collision-system.d.ts.map +1 -0
- package/dist/physics/collision-system.js +64 -0
- package/dist/physics/physics-registry.d.ts +45 -0
- package/dist/physics/physics-registry.d.ts.map +1 -0
- package/dist/physics/physics-registry.js +65 -0
- package/dist/physics/transform-writer.d.ts +16 -0
- package/dist/physics/transform-writer.d.ts.map +1 -0
- package/dist/physics/transform-writer.js +38 -0
- package/dist/physics/trigger-dispatch.d.ts +24 -0
- package/dist/physics/trigger-dispatch.d.ts.map +1 -0
- package/dist/physics/trigger-dispatch.js +80 -0
- package/dist/react/game-state.d.ts +105 -0
- package/dist/react/game-state.d.ts.map +1 -0
- package/dist/react/game-state.js +144 -0
- package/dist/react/use-data.d.ts +60 -0
- package/dist/react/use-data.d.ts.map +1 -0
- package/dist/react/use-data.js +96 -0
- package/dist/react/use-selection.d.ts +75 -0
- package/dist/react/use-selection.d.ts.map +1 -0
- package/dist/react/use-selection.js +90 -0
- package/dist/render/auto-batcher.d.ts +34 -0
- package/dist/render/auto-batcher.d.ts.map +1 -0
- package/dist/render/auto-batcher.js +140 -0
- package/dist/render/render-batch-system.d.ts +33 -0
- package/dist/render/render-batch-system.d.ts.map +1 -0
- package/dist/render/render-batch-system.js +230 -0
- package/dist/render/render-features.d.ts +47 -0
- package/dist/render/render-features.d.ts.map +1 -0
- package/dist/render/render-features.js +105 -0
- package/dist/render/render-settings.d.ts +36 -0
- package/dist/render/render-settings.d.ts.map +1 -0
- package/dist/render/render-settings.js +51 -0
- package/dist/runtime/create-runtime.d.ts +280 -0
- package/dist/runtime/create-runtime.d.ts.map +1 -0
- package/dist/runtime/create-runtime.js +795 -0
- package/dist/runtime/frame-selector-cache.d.ts +41 -0
- package/dist/runtime/frame-selector-cache.d.ts.map +1 -0
- package/dist/runtime/frame-selector-cache.js +65 -0
- package/dist/runtime/game.d.ts +433 -0
- package/dist/runtime/game.d.ts.map +1 -0
- package/dist/runtime/game.js +569 -0
- package/dist/runtime/input-router.d.ts +78 -0
- package/dist/runtime/input-router.d.ts.map +1 -0
- package/dist/runtime/input-router.js +171 -0
- package/dist/runtime/mount-game.d.ts +129 -0
- package/dist/runtime/mount-game.d.ts.map +1 -0
- package/dist/runtime/mount-game.js +152 -0
- package/dist/runtime/mount-manifest.d.ts +119 -0
- package/dist/runtime/mount-manifest.d.ts.map +1 -0
- package/dist/runtime/mount-manifest.js +204 -0
- package/dist/runtime/render-audio-control.d.ts +110 -0
- package/dist/runtime/render-audio-control.d.ts.map +1 -0
- package/dist/runtime/render-audio-control.js +111 -0
- package/dist/runtime/render-control.d.ts +291 -0
- package/dist/runtime/render-control.d.ts.map +1 -0
- package/dist/runtime/render-control.js +264 -0
- package/dist/runtime/render-seed.d.ts +57 -0
- package/dist/runtime/render-seed.d.ts.map +1 -0
- package/dist/runtime/render-seed.js +74 -0
- package/dist/runtime/scene-ui-bridge.d.ts +69 -0
- package/dist/runtime/scene-ui-bridge.d.ts.map +1 -0
- package/dist/runtime/scene-ui-bridge.js +23 -0
- package/dist/runtime/scene-ui-data.d.ts +13 -0
- package/dist/runtime/scene-ui-data.d.ts.map +1 -0
- package/dist/runtime/scene-ui-data.js +92 -0
- package/dist/runtime/state-bridge.d.ts +47 -0
- package/dist/runtime/state-bridge.d.ts.map +1 -0
- package/dist/runtime/state-bridge.js +53 -0
- package/dist/runtime/types.d.ts +179 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +1 -0
- package/dist/scene/asset-loaders.d.ts +79 -0
- package/dist/scene/asset-loaders.d.ts.map +1 -0
- package/dist/scene/asset-loaders.js +141 -0
- package/dist/scene/asset-paths.d.ts +11 -0
- package/dist/scene/asset-paths.d.ts.map +1 -0
- package/dist/scene/asset-paths.js +108 -0
- package/dist/scene/asset-ref-check.d.ts +88 -0
- package/dist/scene/asset-ref-check.d.ts.map +1 -0
- package/dist/scene/asset-ref-check.js +214 -0
- package/dist/scene/asset-registry.d.ts +30 -0
- package/dist/scene/asset-registry.d.ts.map +1 -0
- package/dist/scene/asset-registry.js +50 -0
- package/dist/scene/collider-dimensions.d.ts +63 -0
- package/dist/scene/collider-dimensions.d.ts.map +1 -0
- package/dist/scene/collider-dimensions.js +98 -0
- package/dist/scene/component-registry.d.ts +17 -0
- package/dist/scene/component-registry.d.ts.map +1 -0
- package/dist/scene/component-registry.js +28 -0
- package/dist/scene/defaults.d.ts +252 -0
- package/dist/scene/defaults.d.ts.map +1 -0
- package/dist/scene/defaults.js +151 -0
- package/dist/scene/geometries/index.d.ts +8 -0
- package/dist/scene/geometries/index.d.ts.map +1 -0
- package/dist/scene/geometries/index.js +7 -0
- package/dist/scene/geometries/terrain.d.ts +2 -0
- package/dist/scene/geometries/terrain.d.ts.map +1 -0
- package/dist/scene/geometries/terrain.js +37 -0
- package/dist/scene/geometry-registry.d.ts +24 -0
- package/dist/scene/geometry-registry.d.ts.map +1 -0
- package/dist/scene/geometry-registry.js +20 -0
- package/dist/scene/instance-registry.d.ts +36 -0
- package/dist/scene/instance-registry.d.ts.map +1 -0
- package/dist/scene/instance-registry.js +55 -0
- package/dist/scene/instancers/grid.d.ts +2 -0
- package/dist/scene/instancers/grid.d.ts.map +1 -0
- package/dist/scene/instancers/grid.js +36 -0
- package/dist/scene/instancers/index.d.ts +8 -0
- package/dist/scene/instancers/index.d.ts.map +1 -0
- package/dist/scene/instancers/index.js +7 -0
- package/dist/scene/light-camera-factory.d.ts +23 -0
- package/dist/scene/light-camera-factory.d.ts.map +1 -0
- package/dist/scene/light-camera-factory.js +68 -0
- package/dist/scene/material-factory.d.ts +17 -0
- package/dist/scene/material-factory.d.ts.map +1 -0
- package/dist/scene/material-factory.js +197 -0
- package/dist/scene/material-registry.d.ts +40 -0
- package/dist/scene/material-registry.d.ts.map +1 -0
- package/dist/scene/material-registry.js +44 -0
- package/dist/scene/materials/index.d.ts +8 -0
- package/dist/scene/materials/index.d.ts.map +1 -0
- package/dist/scene/materials/index.js +7 -0
- package/dist/scene/materials/water.d.ts +2 -0
- package/dist/scene/materials/water.d.ts.map +1 -0
- package/dist/scene/materials/water.js +54 -0
- package/dist/scene/parse.d.ts +23 -0
- package/dist/scene/parse.d.ts.map +1 -0
- package/dist/scene/parse.js +179 -0
- package/dist/scene/particles-factory.d.ts +33 -0
- package/dist/scene/particles-factory.d.ts.map +1 -0
- package/dist/scene/particles-factory.js +282 -0
- package/dist/scene/scene-apply.d.ts +109 -0
- package/dist/scene/scene-apply.d.ts.map +1 -0
- package/dist/scene/scene-apply.js +326 -0
- package/dist/scene/scene-diff-schema.d.ts +285 -0
- package/dist/scene/scene-diff-schema.d.ts.map +1 -0
- package/dist/scene/scene-diff-schema.js +92 -0
- package/dist/scene/scene-diff-types.d.ts +40 -0
- package/dist/scene/scene-diff-types.d.ts.map +1 -0
- package/dist/scene/scene-diff-types.js +14 -0
- package/dist/scene/scene-loader.d.ts +177 -0
- package/dist/scene/scene-loader.d.ts.map +1 -0
- package/dist/scene/scene-loader.js +1213 -0
- package/dist/scene/scene-query.d.ts +11 -0
- package/dist/scene/scene-query.d.ts.map +1 -0
- package/dist/scene/scene-query.js +63 -0
- package/dist/scene/scene-types.d.ts +10 -0
- package/dist/scene/scene-types.d.ts.map +1 -0
- package/dist/scene/scene-types.js +8 -0
- package/dist/scene/scene-version.d.ts +26 -0
- package/dist/scene/scene-version.d.ts.map +1 -0
- package/dist/scene/scene-version.js +34 -0
- package/dist/scene/schema/animation.d.ts +8 -0
- package/dist/scene/schema/animation.d.ts.map +1 -0
- package/dist/scene/schema/animation.js +42 -0
- package/dist/scene/schema/audio.d.ts +13 -0
- package/dist/scene/schema/audio.d.ts.map +1 -0
- package/dist/scene/schema/audio.js +22 -0
- package/dist/scene/schema/camera.d.ts +28 -0
- package/dist/scene/schema/camera.d.ts.map +1 -0
- package/dist/scene/schema/camera.js +17 -0
- package/dist/scene/schema/collider.d.ts +40 -0
- package/dist/scene/schema/collider.d.ts.map +1 -0
- package/dist/scene/schema/collider.js +55 -0
- package/dist/scene/schema/entity-ref.d.ts +31 -0
- package/dist/scene/schema/entity-ref.d.ts.map +1 -0
- package/dist/scene/schema/entity-ref.js +61 -0
- package/dist/scene/schema/entity.d.ts +1036 -0
- package/dist/scene/schema/entity.d.ts.map +1 -0
- package/dist/scene/schema/entity.js +153 -0
- package/dist/scene/schema/environment.d.ts +425 -0
- package/dist/scene/schema/environment.d.ts.map +1 -0
- package/dist/scene/schema/environment.js +357 -0
- package/dist/scene/schema/index.d.ts +39 -0
- package/dist/scene/schema/index.d.ts.map +1 -0
- package/dist/scene/schema/index.js +20 -0
- package/dist/scene/schema/instances.d.ts +14 -0
- package/dist/scene/schema/instances.d.ts.map +1 -0
- package/dist/scene/schema/instances.js +28 -0
- package/dist/scene/schema/joint.d.ts +23 -0
- package/dist/scene/schema/joint.d.ts.map +1 -0
- package/dist/scene/schema/joint.js +23 -0
- package/dist/scene/schema/light.d.ts +38 -0
- package/dist/scene/schema/light.d.ts.map +1 -0
- package/dist/scene/schema/light.js +26 -0
- package/dist/scene/schema/material.d.ts +199 -0
- package/dist/scene/schema/material.d.ts.map +1 -0
- package/dist/scene/schema/material.js +99 -0
- package/dist/scene/schema/mesh.d.ts +48 -0
- package/dist/scene/schema/mesh.d.ts.map +1 -0
- package/dist/scene/schema/mesh.js +82 -0
- package/dist/scene/schema/particles.d.ts +2178 -0
- package/dist/scene/schema/particles.d.ts.map +1 -0
- package/dist/scene/schema/particles.js +321 -0
- package/dist/scene/schema/physics.d.ts +56 -0
- package/dist/scene/schema/physics.d.ts.map +1 -0
- package/dist/scene/schema/physics.js +37 -0
- package/dist/scene/schema/scene-file.d.ts +304 -0
- package/dist/scene/schema/scene-file.d.ts.map +1 -0
- package/dist/scene/schema/scene-file.js +262 -0
- package/dist/scene/schema/shadow.d.ts +28 -0
- package/dist/scene/schema/shadow.d.ts.map +1 -0
- package/dist/scene/schema/shadow.js +20 -0
- package/dist/scene/schema/spline.d.ts +25 -0
- package/dist/scene/schema/spline.d.ts.map +1 -0
- package/dist/scene/schema/spline.js +15 -0
- package/dist/scene/schema/tuples.d.ts +12 -0
- package/dist/scene/schema/tuples.d.ts.map +1 -0
- package/dist/scene/schema/tuples.js +14 -0
- package/dist/scene/schema/ui.d.ts +880 -0
- package/dist/scene/schema/ui.d.ts.map +1 -0
- package/dist/scene/schema/ui.js +506 -0
- package/dist/scene/user-data.d.ts +171 -0
- package/dist/scene/user-data.d.ts.map +1 -0
- package/dist/scene/user-data.js +137 -0
- package/dist/setup/setup-audio.d.ts +20 -0
- package/dist/setup/setup-audio.d.ts.map +1 -0
- package/dist/setup/setup-audio.js +41 -0
- package/dist/setup/setup-particles.d.ts +17 -0
- package/dist/setup/setup-particles.d.ts.map +1 -0
- package/dist/setup/setup-particles.js +16 -0
- package/dist/setup/setup-physics.d.ts +25 -0
- package/dist/setup/setup-physics.d.ts.map +1 -0
- package/dist/setup/setup-physics.js +51 -0
- package/dist/setup/setup-renderer.d.ts +69 -0
- package/dist/setup/setup-renderer.d.ts.map +1 -0
- package/dist/setup/setup-renderer.js +363 -0
- package/dist/tools/define-tool.d.ts +105 -0
- package/dist/tools/define-tool.d.ts.map +1 -0
- package/dist/tools/define-tool.js +82 -0
- package/dist/world2d/authoring-2d.d.ts +76 -0
- package/dist/world2d/authoring-2d.d.ts.map +1 -0
- package/dist/world2d/authoring-2d.js +176 -0
- package/dist/world2d/capture-to-scene2d.d.ts +5 -0
- package/dist/world2d/capture-to-scene2d.d.ts.map +1 -0
- package/dist/world2d/capture-to-scene2d.js +49 -0
- package/dist/world2d/collision-2d.d.ts +52 -0
- package/dist/world2d/collision-2d.d.ts.map +1 -0
- package/dist/world2d/collision-2d.js +70 -0
- package/dist/world2d/components-2d.d.ts +47 -0
- package/dist/world2d/components-2d.d.ts.map +1 -0
- package/dist/world2d/components-2d.js +77 -0
- package/dist/world2d/index.d.ts +34 -0
- package/dist/world2d/index.d.ts.map +1 -0
- package/dist/world2d/index.js +32 -0
- package/dist/world2d/ingest-iframe-2d.d.ts +82 -0
- package/dist/world2d/ingest-iframe-2d.d.ts.map +1 -0
- package/dist/world2d/ingest-iframe-2d.js +166 -0
- package/dist/world2d/ingest2d.d.ts +97 -0
- package/dist/world2d/ingest2d.d.ts.map +1 -0
- package/dist/world2d/ingest2d.js +40 -0
- package/dist/world2d/physics2d-registry.d.ts +24 -0
- package/dist/world2d/physics2d-registry.d.ts.map +1 -0
- package/dist/world2d/physics2d-registry.js +38 -0
- package/dist/world2d/pixi-game-adapter.d.ts +107 -0
- package/dist/world2d/pixi-game-adapter.d.ts.map +1 -0
- package/dist/world2d/pixi-game-adapter.js +211 -0
- package/dist/world2d/pixi-surface.d.ts +39 -0
- package/dist/world2d/pixi-surface.d.ts.map +1 -0
- package/dist/world2d/pixi-surface.js +47 -0
- package/dist/world2d/scene-capture-2d.d.ts +43 -0
- package/dist/world2d/scene-capture-2d.d.ts.map +1 -0
- package/dist/world2d/scene-capture-2d.js +92 -0
- package/dist/world2d/scene2d-loader.d.ts +27 -0
- package/dist/world2d/scene2d-loader.d.ts.map +1 -0
- package/dist/world2d/scene2d-loader.js +274 -0
- package/dist/world2d/schema/entity2d.d.ts +102 -0
- package/dist/world2d/schema/entity2d.d.ts.map +1 -0
- package/dist/world2d/schema/entity2d.js +119 -0
- package/dist/world2d/schema/physics2d.d.ts +46 -0
- package/dist/world2d/schema/physics2d.d.ts.map +1 -0
- package/dist/world2d/schema/physics2d.js +45 -0
- package/dist/world2d/schema/sprite.d.ts +42 -0
- package/dist/world2d/schema/sprite.d.ts.map +1 -0
- package/dist/world2d/schema/sprite.js +63 -0
- package/dist/world2d/schema/tilemap.d.ts +15 -0
- package/dist/world2d/schema/tilemap.d.ts.map +1 -0
- package/dist/world2d/schema/tilemap.js +19 -0
- package/dist/world2d/schema/tuples2d.d.ts +20 -0
- package/dist/world2d/schema/tuples2d.d.ts.map +1 -0
- package/dist/world2d/schema/tuples2d.js +19 -0
- package/dist/world2d/system-adapters-2d.d.ts +16 -0
- package/dist/world2d/system-adapters-2d.d.ts.map +1 -0
- package/dist/world2d/system-adapters-2d.js +37 -0
- package/dist/world2d/transform-writer-2d.d.ts +16 -0
- package/dist/world2d/transform-writer-2d.d.ts.map +1 -0
- package/dist/world2d/transform-writer-2d.js +22 -0
- package/dist/world2d/types.d.ts +53 -0
- package/dist/world2d/types.d.ts.map +1 -0
- package/dist/world2d/types.js +1 -0
- package/package.json +18 -4
- package/src/adapter/authoring.ts +10 -0
- package/src/adapter/first-party-systems.ts +23 -34
- package/src/adapter/index.ts +1 -3
- package/src/adapter/system-adapter.ts +15 -22
- package/src/adapter/vgai-scene-game-adapter.ts +5 -14
- package/src/animation/anim-graph-types.ts +12 -43
- package/src/animation/animation-clock.ts +479 -0
- package/src/animation/camera-ownership.ts +467 -0
- package/src/animation/cinematic-cues.ts +451 -0
- package/src/animation/clip-map.ts +41 -0
- package/src/animation/gsap-registration.ts +184 -0
- package/src/animation/theatre-clock-binding.ts +111 -0
- package/src/animation/theatre-director.ts +347 -0
- package/src/animation/theatre-object-binding.ts +661 -0
- package/src/animation/xstate-animation-binding.ts +398 -0
- package/src/animation/xstate-animation-meta.ts +282 -0
- package/src/audio/index.ts +39 -7
- package/src/audio/tone-clock-binding.ts +98 -0
- package/src/audio/tone-context.ts +129 -0
- package/src/audio/tone-offline-render.ts +167 -0
- package/src/audio/wav-encode.ts +119 -0
- package/src/core/game-loop.ts +17 -0
- package/src/core/types.ts +13 -0
- package/src/data/data-asset.ts +167 -0
- package/src/data/data-check-core.ts +242 -0
- package/src/data/data-ref.ts +145 -0
- package/src/data/vite-plugin-data.ts +290 -0
- package/src/index.ts +48 -0
- package/src/input/input-manager.ts +1206 -32
- package/src/input/input-types.ts +155 -3
- package/src/input/prompt-labels.ts +122 -0
- package/src/input/rebind-controller.ts +105 -0
- package/src/input/schema.ts +206 -52
- package/src/react/use-data.ts +114 -0
- package/src/react/use-selection.tsx +135 -0
- package/src/runtime/create-runtime.ts +30 -9
- package/src/runtime/render-audio-control.ts +168 -0
- package/src/runtime/render-control.ts +522 -0
- package/src/runtime/render-seed.ts +79 -0
- package/src/runtime/types.ts +0 -5
- package/src/scene/asset-loaders.ts +10 -36
- package/src/scene/asset-paths.ts +0 -2
- package/src/scene/asset-ref-check.ts +248 -0
- package/src/scene/parse.ts +133 -0
- package/src/scene/scene-loader.ts +81 -96
- package/src/scene/schema/animation.ts +30 -79
- package/src/scene/schema/entity.ts +20 -0
- package/src/scene/schema/index.ts +2 -12
- package/src/scene/user-data.ts +8 -9
- package/src/setup/setup-renderer.ts +9 -2
- package/src/tools/define-tool.ts +152 -0
- package/src/animation/anim-graph.ts +0 -406
- package/src/animation/anim-system.ts +0 -28
- package/src/animation/property-track.ts +0 -178
- package/src/animation/schema.ts +0 -204
- package/src/audio/ambient.ts +0 -300
- package/src/audio/impacts.ts +0 -212
- package/src/audio/movement.ts +0 -140
- package/src/audio/musical.ts +0 -200
- package/src/audio/ui-sounds.ts +0 -171
- package/src/audio/vehicle.ts +0 -235
- package/src/audio/weapons.ts +0 -152
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { PHASE_ORDER } from '../core/types';
|
|
2
|
+
const EPSILON = 1e-9;
|
|
3
|
+
// Bails a pathological single `advance(dt)` call out of lap-by-lap interval
|
|
4
|
+
// enumeration (e.g. an absurd `dt` at max time scale over a tiny loop range)
|
|
5
|
+
// so a single call can never spin unboundedly. Real fixed-step `dt`s never
|
|
6
|
+
// approach this.
|
|
7
|
+
const MAX_LAPS_PER_ADVANCE = 100_000;
|
|
8
|
+
/** Advance `p0` forward by `distance` (>= 0) within `range`, honoring loop/clamp. */
|
|
9
|
+
function sweepForward(p0, distance, range) {
|
|
10
|
+
const length = range.end - range.start;
|
|
11
|
+
const canLoop = range.loop && length > EPSILON;
|
|
12
|
+
const intervals = [];
|
|
13
|
+
let pos = p0;
|
|
14
|
+
let remaining = distance;
|
|
15
|
+
let looped = false;
|
|
16
|
+
let laps = 0;
|
|
17
|
+
for (;;) {
|
|
18
|
+
const distToEnd = range.end - pos;
|
|
19
|
+
if (!canLoop || remaining <= distToEnd + EPSILON) {
|
|
20
|
+
// Always clamp to range.end here, even when canLoop is true: this
|
|
21
|
+
// terminal branch is reached whenever `remaining` is within EPSILON of
|
|
22
|
+
// `distToEnd` (not just when it's exactly equal), so `pos + remaining`
|
|
23
|
+
// can overshoot `range.end` by up to EPSILON on a loop range. Clamping
|
|
24
|
+
// unconditionally (D1 follow-up, spec §10 D5) keeps `clock.time` from
|
|
25
|
+
// ever exceeding `range.end`, which in turn keeps the NEXT advance()'s
|
|
26
|
+
// `distToEnd` non-negative and prevents a degenerate `from > to`
|
|
27
|
+
// interval on the following call.
|
|
28
|
+
const to = Math.min(pos + remaining, range.end);
|
|
29
|
+
intervals.push({ from: pos, to, direction: 'forward' });
|
|
30
|
+
pos = to;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
intervals.push({ from: pos, to: range.end, direction: 'forward' });
|
|
34
|
+
remaining -= distToEnd;
|
|
35
|
+
pos = range.start;
|
|
36
|
+
looped = true;
|
|
37
|
+
laps++;
|
|
38
|
+
if (laps > MAX_LAPS_PER_ADVANCE) {
|
|
39
|
+
const wrapped = range.start + (remaining % length);
|
|
40
|
+
intervals.push({ from: pos, to: wrapped, direction: 'forward' });
|
|
41
|
+
pos = wrapped;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { pos, intervals, looped };
|
|
46
|
+
}
|
|
47
|
+
/** Advance `p0` backward by `distance` (>= 0) within `range`, honoring loop/clamp. */
|
|
48
|
+
function sweepReverse(p0, distance, range) {
|
|
49
|
+
const length = range.end - range.start;
|
|
50
|
+
const canLoop = range.loop && length > EPSILON;
|
|
51
|
+
const intervals = [];
|
|
52
|
+
let pos = p0;
|
|
53
|
+
let remaining = distance;
|
|
54
|
+
let looped = false;
|
|
55
|
+
let laps = 0;
|
|
56
|
+
for (;;) {
|
|
57
|
+
const distToStart = pos - range.start;
|
|
58
|
+
if (!canLoop || remaining <= distToStart + EPSILON) {
|
|
59
|
+
// Mirror of the forward-sweep clamp above: always clamp to
|
|
60
|
+
// range.start here so a reverse advance() cannot undershoot it by up
|
|
61
|
+
// to EPSILON on a loop range (D1 follow-up, spec §10 D5).
|
|
62
|
+
const to = Math.max(pos - remaining, range.start);
|
|
63
|
+
intervals.push({ from: pos, to, direction: 'reverse' });
|
|
64
|
+
pos = to;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
intervals.push({ from: pos, to: range.start, direction: 'reverse' });
|
|
68
|
+
remaining -= distToStart;
|
|
69
|
+
pos = range.end;
|
|
70
|
+
looped = true;
|
|
71
|
+
laps++;
|
|
72
|
+
if (laps > MAX_LAPS_PER_ADVANCE) {
|
|
73
|
+
const wrapped = range.end - (remaining % length);
|
|
74
|
+
intervals.push({ from: pos, to: wrapped, direction: 'reverse' });
|
|
75
|
+
pos = wrapped;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { pos, intervals, looped };
|
|
80
|
+
}
|
|
81
|
+
function clampToRange(t, range) {
|
|
82
|
+
if (t < range.start)
|
|
83
|
+
return range.start;
|
|
84
|
+
if (t > range.end)
|
|
85
|
+
return range.end;
|
|
86
|
+
return t;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The engine-owned canonical clock. See the module doc comment above for
|
|
90
|
+
* the design constraints this implementation is bound by.
|
|
91
|
+
*/
|
|
92
|
+
export class AnimationClock {
|
|
93
|
+
_previousTime;
|
|
94
|
+
_currentTime;
|
|
95
|
+
_range;
|
|
96
|
+
_timeScale;
|
|
97
|
+
_playDirection = 'forward';
|
|
98
|
+
_lastCrossingDirection = 'forward';
|
|
99
|
+
_playbackState = 'stopped';
|
|
100
|
+
_evaluators = [];
|
|
101
|
+
_registrationCounter = 0;
|
|
102
|
+
constructor(options = {}) {
|
|
103
|
+
const start = options.start ?? 0;
|
|
104
|
+
const end = options.end ?? Math.max(start, 1);
|
|
105
|
+
if (end < start) {
|
|
106
|
+
throw new Error(`[AnimationClock] range end (${end}) must be >= start (${start})`);
|
|
107
|
+
}
|
|
108
|
+
const timeScale = options.timeScale ?? 1;
|
|
109
|
+
if (!Number.isFinite(timeScale) || timeScale < 0) {
|
|
110
|
+
throw new Error(`[AnimationClock] timeScale must be a finite number >= 0, got ${timeScale}`);
|
|
111
|
+
}
|
|
112
|
+
this._range = { start, end, loop: options.loop ?? false };
|
|
113
|
+
this._timeScale = timeScale;
|
|
114
|
+
this._previousTime = start;
|
|
115
|
+
this._currentTime = start;
|
|
116
|
+
}
|
|
117
|
+
/** Current playhead time, in seconds. */
|
|
118
|
+
get time() {
|
|
119
|
+
return this._currentTime;
|
|
120
|
+
}
|
|
121
|
+
/** Playhead time immediately before the most recent seek/advance. */
|
|
122
|
+
get previousTime() {
|
|
123
|
+
return this._previousTime;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Playback direction. `'paused'` whenever `playbackState !== 'playing'`
|
|
127
|
+
* (covers both `pause()` and `stop()`) — matches the spec's literal
|
|
128
|
+
* `direction: forward | reverse | paused` acceptance criterion. The
|
|
129
|
+
* underlying intended direction is preserved across pause/resume; see
|
|
130
|
+
* `play()`.
|
|
131
|
+
*/
|
|
132
|
+
get direction() {
|
|
133
|
+
return this._playbackState === 'playing' ? this._playDirection : 'paused';
|
|
134
|
+
}
|
|
135
|
+
get playbackState() {
|
|
136
|
+
return this._playbackState;
|
|
137
|
+
}
|
|
138
|
+
get timeScale() {
|
|
139
|
+
return this._timeScale;
|
|
140
|
+
}
|
|
141
|
+
set timeScale(value) {
|
|
142
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
143
|
+
throw new Error(`[AnimationClock] timeScale must be a finite number >= 0, got ${value}`);
|
|
144
|
+
}
|
|
145
|
+
this._timeScale = value;
|
|
146
|
+
}
|
|
147
|
+
get range() {
|
|
148
|
+
return this._range;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Update loop/range metadata. The current playhead is clamped into the
|
|
152
|
+
* new range if necessary (reported as an ordinary crossing — same
|
|
153
|
+
* evaluator path as `seek`/`advance` — so subscribers observe it).
|
|
154
|
+
*/
|
|
155
|
+
setRange(next) {
|
|
156
|
+
const start = next.start ?? this._range.start;
|
|
157
|
+
const end = next.end ?? this._range.end;
|
|
158
|
+
const loop = next.loop ?? this._range.loop;
|
|
159
|
+
if (end < start) {
|
|
160
|
+
throw new Error(`[AnimationClock] range end (${end}) must be >= start (${start})`);
|
|
161
|
+
}
|
|
162
|
+
this._range = { start, end, loop };
|
|
163
|
+
const clamped = clampToRange(this._currentTime, this._range);
|
|
164
|
+
if (clamped !== this._currentTime) {
|
|
165
|
+
this.seek(clamped);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Begin/resume playback. `direction` sets (or re-asserts) the intended
|
|
170
|
+
* playback direction for subsequent `advance()` calls; omit it to resume
|
|
171
|
+
* in whatever direction was last set (default `'forward'` the first time).
|
|
172
|
+
*/
|
|
173
|
+
play(direction) {
|
|
174
|
+
if (direction)
|
|
175
|
+
this._playDirection = direction;
|
|
176
|
+
this._playbackState = 'playing';
|
|
177
|
+
}
|
|
178
|
+
/** Halt playback at the current position. `advance()` becomes a no-op. */
|
|
179
|
+
pause() {
|
|
180
|
+
this._playbackState = 'paused';
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Halt playback at the current position (distinct from `pause()` only in
|
|
184
|
+
* reported `playbackState`; this unit does not prescribe a reset-to-start
|
|
185
|
+
* policy — that is a cinematic-controller/render-seam decision, D5/I2).
|
|
186
|
+
* `advance()` is a no-op in this state, same as `paused`.
|
|
187
|
+
*/
|
|
188
|
+
stop() {
|
|
189
|
+
this._playbackState = 'stopped';
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Jump directly to `t` (clamped into `range`). Idempotent: calling
|
|
193
|
+
* `seek(t)` twice in a row leaves `time`/`previousTime` identical to
|
|
194
|
+
* calling it once — the second call is a true no-op (no state mutation,
|
|
195
|
+
* though evaluators still fire so a subscriber can rely on `seek` always
|
|
196
|
+
* producing a crossing for e.g. re-asserting visual state).
|
|
197
|
+
*/
|
|
198
|
+
seek(t) {
|
|
199
|
+
const target = clampToRange(t, this._range);
|
|
200
|
+
if (target === this._currentTime) {
|
|
201
|
+
return this.emit(this._currentTime, this._currentTime, [{ from: target, to: target, direction: this._lastCrossingDirection }], false, this._lastCrossingDirection);
|
|
202
|
+
}
|
|
203
|
+
const direction = target > this._currentTime ? 'forward' : 'reverse';
|
|
204
|
+
const prev = this._currentTime;
|
|
205
|
+
this._previousTime = prev;
|
|
206
|
+
this._currentTime = target;
|
|
207
|
+
this._lastCrossingDirection = direction;
|
|
208
|
+
return this.emit(prev, target, [{ from: prev, to: target, direction }], false, direction);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Frame-index seek for export (D1 AC): seeks to EXACTLY `range.start +
|
|
212
|
+
* n / fps`, computed fresh from `n`/`fps` on every call. This is what
|
|
213
|
+
* keeps a rendered frame sequence drift-free — unlike repeatedly calling
|
|
214
|
+
* `advance(1 / fps)` `n` times (which accumulates float error), this
|
|
215
|
+
* always derives the same exact double for a given `(n, fps)` pair no
|
|
216
|
+
* matter what the clock's prior state was.
|
|
217
|
+
*/
|
|
218
|
+
seekFrame(n, fps) {
|
|
219
|
+
if (!Number.isFinite(fps) || fps <= 0) {
|
|
220
|
+
throw new Error(`[AnimationClock] seekFrame fps must be a finite number > 0, got ${fps}`);
|
|
221
|
+
}
|
|
222
|
+
return this.seek(this._range.start + n / fps);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Fixed-step advance by `dt` seconds (magnitude; sign of movement comes
|
|
226
|
+
* from `direction`/`play()`, not from `dt`'s sign). A no-op whenever
|
|
227
|
+
* `playbackState !== 'playing'` — this is what makes `advance()` do
|
|
228
|
+
* nothing while paused (D1 AC). Returns `null` for that no-op case;
|
|
229
|
+
* otherwise returns the resulting crossing (which may span multiple loop
|
|
230
|
+
* laps if `dt * timeScale` exceeds the range length).
|
|
231
|
+
*/
|
|
232
|
+
advance(dt) {
|
|
233
|
+
if (this._playbackState !== 'playing')
|
|
234
|
+
return null;
|
|
235
|
+
if (!Number.isFinite(dt)) {
|
|
236
|
+
throw new Error(`[AnimationClock] advance(dt) requires a finite dt, got ${dt}`);
|
|
237
|
+
}
|
|
238
|
+
const magnitude = Math.abs(dt) * this._timeScale;
|
|
239
|
+
const p0 = this._currentTime;
|
|
240
|
+
if (magnitude === 0) {
|
|
241
|
+
return this.emit(p0, p0, [], false, this._playDirection);
|
|
242
|
+
}
|
|
243
|
+
const result = this._playDirection === 'forward'
|
|
244
|
+
? sweepForward(p0, magnitude, this._range)
|
|
245
|
+
: sweepReverse(p0, magnitude, this._range);
|
|
246
|
+
this._previousTime = p0;
|
|
247
|
+
this._currentTime = result.pos;
|
|
248
|
+
this._lastCrossingDirection = this._playDirection;
|
|
249
|
+
return this.emit(p0, result.pos, result.intervals, result.looped, this._playDirection);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Register an evaluator against a phase from the engine's own
|
|
253
|
+
* `SystemPhaseName` vocabulary (`core/types.ts`). Evaluators fire on
|
|
254
|
+
* every `seek()`/`advance()` (including idempotent no-op seeks and
|
|
255
|
+
* `setRange` clamps) in `PHASE_ORDER` order, then registration order
|
|
256
|
+
* within a phase — the same "deterministic phase order" every other
|
|
257
|
+
* engine system is invoked in, so a Theatre binding, a registered-GSAP
|
|
258
|
+
* seek, and a cue evaluator can each declare their phase and compose
|
|
259
|
+
* without inventing a second ordering rule.
|
|
260
|
+
*/
|
|
261
|
+
subscribe(phase, evaluator) {
|
|
262
|
+
if (!PHASE_ORDER.includes(phase)) {
|
|
263
|
+
throw new Error(`[AnimationClock] unknown phase "${phase}". Valid: ${PHASE_ORDER.join(', ')}`);
|
|
264
|
+
}
|
|
265
|
+
const entry = { phase, order: this._registrationCounter++, fn: evaluator };
|
|
266
|
+
this._evaluators.push(entry);
|
|
267
|
+
return {
|
|
268
|
+
dispose: () => {
|
|
269
|
+
const idx = this._evaluators.indexOf(entry);
|
|
270
|
+
if (idx !== -1)
|
|
271
|
+
this._evaluators.splice(idx, 1);
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
emit(previousTime, currentTime, intervals, looped, direction) {
|
|
276
|
+
const crossing = {
|
|
277
|
+
previousTime,
|
|
278
|
+
currentTime,
|
|
279
|
+
direction,
|
|
280
|
+
timeScale: this._timeScale,
|
|
281
|
+
looped,
|
|
282
|
+
intervals,
|
|
283
|
+
};
|
|
284
|
+
if (this._evaluators.length > 0) {
|
|
285
|
+
const ordered = [...this._evaluators].sort((a, b) => {
|
|
286
|
+
const pa = PHASE_ORDER.indexOf(a.phase);
|
|
287
|
+
const pb = PHASE_ORDER.indexOf(b.phase);
|
|
288
|
+
return pa !== pb ? pa - pb : a.order - b.order;
|
|
289
|
+
});
|
|
290
|
+
for (const entry of ordered) {
|
|
291
|
+
try {
|
|
292
|
+
entry.fn(crossing);
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
console.error(`[AnimationClock] evaluator in phase "${entry.phase}" threw:`, err);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return crossing;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BlendTreeDef } from './anim-graph-types';
|
|
2
|
+
/**
|
|
3
|
+
* Evaluates a blend tree and returns weights for each child clip.
|
|
4
|
+
*
|
|
5
|
+
* 1D blend: interpolates between sorted blend points based on a single parameter.
|
|
6
|
+
* Example: speed=3 with children at [walk:1, run:5] → weights [0.5, 0.5]
|
|
7
|
+
*
|
|
8
|
+
* 2D blend: uses two parameters (e.g., strafe locomotion). Weights are computed by
|
|
9
|
+
* inverse-distance weighting (IDW): each child's weight is proportional to
|
|
10
|
+
* 1/distance from the (parameter, parameterY) sample point to that child's
|
|
11
|
+
* (threshold, thresholdY) position, then normalized so all weights sum to 1.
|
|
12
|
+
* A sample landing exactly on a child gives that child ~full weight. This is a
|
|
13
|
+
* smooth approximation, not a Delaunay/barycentric blend (so non-adjacent
|
|
14
|
+
* children still receive a small share); it is intentionally kept simple.
|
|
15
|
+
*
|
|
16
|
+
* Direct: each child has an explicit weight.
|
|
17
|
+
*/
|
|
18
|
+
export declare function evaluateBlendTree(def: BlendTreeDef, parameters: Map<string, number | boolean>): {
|
|
19
|
+
clip: string;
|
|
20
|
+
weight: number;
|
|
21
|
+
}[];
|
|
22
|
+
//# sourceMappingURL=blend-node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blend-node.d.ts","sourceRoot":"","sources":["../../src/animation/blend-node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,YAAY,EACjB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GACxC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAWpC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluates a blend tree and returns weights for each child clip.
|
|
3
|
+
*
|
|
4
|
+
* 1D blend: interpolates between sorted blend points based on a single parameter.
|
|
5
|
+
* Example: speed=3 with children at [walk:1, run:5] → weights [0.5, 0.5]
|
|
6
|
+
*
|
|
7
|
+
* 2D blend: uses two parameters (e.g., strafe locomotion). Weights are computed by
|
|
8
|
+
* inverse-distance weighting (IDW): each child's weight is proportional to
|
|
9
|
+
* 1/distance from the (parameter, parameterY) sample point to that child's
|
|
10
|
+
* (threshold, thresholdY) position, then normalized so all weights sum to 1.
|
|
11
|
+
* A sample landing exactly on a child gives that child ~full weight. This is a
|
|
12
|
+
* smooth approximation, not a Delaunay/barycentric blend (so non-adjacent
|
|
13
|
+
* children still receive a small share); it is intentionally kept simple.
|
|
14
|
+
*
|
|
15
|
+
* Direct: each child has an explicit weight.
|
|
16
|
+
*/
|
|
17
|
+
export function evaluateBlendTree(def, parameters) {
|
|
18
|
+
switch (def.type) {
|
|
19
|
+
case '1D':
|
|
20
|
+
return evaluate1D(def, parameters);
|
|
21
|
+
case '2D':
|
|
22
|
+
return evaluate2D(def, parameters);
|
|
23
|
+
case 'direct':
|
|
24
|
+
return evaluateDirect(def);
|
|
25
|
+
default:
|
|
26
|
+
return def.children.map((c) => ({ clip: c.clip, weight: 1 / def.children.length }));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function evaluate1D(def, parameters) {
|
|
30
|
+
const paramValue = Number(parameters.get(def.parameter) ?? 0);
|
|
31
|
+
const children = [...def.children].sort((a, b) => a.threshold - b.threshold);
|
|
32
|
+
const results = children.map((c) => ({ clip: c.clip, weight: 0 }));
|
|
33
|
+
if (children.length === 0)
|
|
34
|
+
return results;
|
|
35
|
+
if (children.length === 1) {
|
|
36
|
+
results[0].weight = 1;
|
|
37
|
+
return results;
|
|
38
|
+
}
|
|
39
|
+
// Below first threshold
|
|
40
|
+
if (paramValue <= children[0].threshold) {
|
|
41
|
+
results[0].weight = 1;
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
// Above last threshold
|
|
45
|
+
if (paramValue >= children[children.length - 1].threshold) {
|
|
46
|
+
results[results.length - 1].weight = 1;
|
|
47
|
+
return results;
|
|
48
|
+
}
|
|
49
|
+
// Between two thresholds — linear interpolation
|
|
50
|
+
for (let i = 0; i < children.length - 1; i++) {
|
|
51
|
+
const lo = children[i];
|
|
52
|
+
const hi = children[i + 1];
|
|
53
|
+
if (paramValue >= lo.threshold && paramValue <= hi.threshold) {
|
|
54
|
+
const range = hi.threshold - lo.threshold;
|
|
55
|
+
const t = range > 0 ? (paramValue - lo.threshold) / range : 0;
|
|
56
|
+
results[i].weight = 1 - t;
|
|
57
|
+
results[i + 1].weight = t;
|
|
58
|
+
return results;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return results;
|
|
62
|
+
}
|
|
63
|
+
function evaluate2D(def, parameters) {
|
|
64
|
+
const px = Number(parameters.get(def.parameter) ?? 0);
|
|
65
|
+
const py = Number(parameters.get(def.parameterY ?? '') ?? 0);
|
|
66
|
+
// Inverse-distance weighting: weight each child by 1/distance to its 2D point,
|
|
67
|
+
// then normalize below so the returned weights sum to 1.
|
|
68
|
+
const children = def.children;
|
|
69
|
+
const results = children.map((c) => ({ clip: c.clip, weight: 0 }));
|
|
70
|
+
let totalInvDist = 0;
|
|
71
|
+
const invDists = [];
|
|
72
|
+
for (const child of children) {
|
|
73
|
+
const dx = px - child.threshold;
|
|
74
|
+
const dy = py - (child.thresholdY ?? 0);
|
|
75
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
76
|
+
const invDist = dist < 0.001 ? 1000 : 1 / dist;
|
|
77
|
+
invDists.push(invDist);
|
|
78
|
+
totalInvDist += invDist;
|
|
79
|
+
}
|
|
80
|
+
if (totalInvDist > 0) {
|
|
81
|
+
for (let i = 0; i < results.length; i++) {
|
|
82
|
+
results[i].weight = invDists[i] / totalInvDist;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return results;
|
|
86
|
+
}
|
|
87
|
+
function evaluateDirect(def) {
|
|
88
|
+
const results = def.children.map((c) => ({ clip: c.clip, weight: c.weight ?? 0 }));
|
|
89
|
+
// Normalize so weights sum to exactly 1.0 — otherwise the leftover weight
|
|
90
|
+
// bleeds in the bind pose / T-pose (the actions add up to <1 or >1).
|
|
91
|
+
const total = results.reduce((sum, r) => sum + r.weight, 0);
|
|
92
|
+
if (total > 0) {
|
|
93
|
+
for (const r of results)
|
|
94
|
+
r.weight /= total;
|
|
95
|
+
}
|
|
96
|
+
return results;
|
|
97
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import type { SystemPhaseName } from '../core/types';
|
|
3
|
+
import type { AnimationClock } from './animation-clock';
|
|
4
|
+
import type { CameraOwnershipChangeEvent } from './theatre-director';
|
|
5
|
+
/**
|
|
6
|
+
* D6 — Camera Ownership and Restoration (spec §10 D6, §3.2, §4).
|
|
7
|
+
*
|
|
8
|
+
* VGAI owns exactly one thing here: WHO is allowed to move the live,
|
|
9
|
+
* actually-rendered camera at any given moment, and what happens to it when
|
|
10
|
+
* that control is released. The actual camera math (cuts, blends, lens
|
|
11
|
+
* changes, orbit/follow/look-at/dolly behavior) is expressed entirely with
|
|
12
|
+
* native `THREE.PerspectiveCamera` objects — Object3D-as-truth, no camera
|
|
13
|
+
* wrapper (spec §4, `ARCHITECTURE.md`'s "the world node IS the entity"
|
|
14
|
+
* rule). This module reads and writes real Three.js camera properties
|
|
15
|
+
* (`position`, `quaternion`, `fov`, `near`, `far`) and nothing else.
|
|
16
|
+
*
|
|
17
|
+
* ## Two cooperating pieces
|
|
18
|
+
*
|
|
19
|
+
* - `cameras`: a fixed registry of named SOURCE cameras (`cameraKey ->
|
|
20
|
+
* THREE.PerspectiveCamera`), each an ordinary Object3D that ANY other
|
|
21
|
+
* system may drive however it likes — a Theatre binding
|
|
22
|
+
* (`bindObject3DTransform`/`bindCameraLens`, D3), a hand-written orbit/
|
|
23
|
+
* follow/spline-dolly update, or a one-shot `camera.lookAt(target)` call.
|
|
24
|
+
* This module never mutates a source camera; it only READS its current
|
|
25
|
+
* pose at evaluation time.
|
|
26
|
+
* - `liveCamera`: the ONE camera actually rendered. This module is the only
|
|
27
|
+
* thing that writes to it while a cinematic owns it. Whatever ordinary
|
|
28
|
+
* game code drives `liveCamera` the rest of the time (gameplay's own
|
|
29
|
+
* orbit/follow controller, typically) is untouched and resumes writing to
|
|
30
|
+
* it the moment ownership returns to "nobody" (the stack is empty).
|
|
31
|
+
*
|
|
32
|
+
* ## Ownership stack (LIFO) — the D6 nested/interrupted-cinematics rule
|
|
33
|
+
*
|
|
34
|
+
* `take(ownerId)` pushes a new ownership FRAME, capturing `liveCamera`'s
|
|
35
|
+
* CURRENT pose as that frame's `restorePose` — i.e. "whatever the camera
|
|
36
|
+
* looked like the instant this owner took over" (gameplay's pose for the
|
|
37
|
+
* first/outermost `take`, or the parent cinematic's current pose for a
|
|
38
|
+
* NESTED `take` while a parent is still on the stack). Only the TOP frame
|
|
39
|
+
* may drive the camera (`cut`/`blend`/`applyDirectorEvent`/`release` all
|
|
40
|
+
* throw `CameraOwnershipError` if `ownerId` is not the current top) — this
|
|
41
|
+
* is what makes nested ownership resolve deterministically: a second
|
|
42
|
+
* cinematic taking the camera while a first one owns it must explicitly
|
|
43
|
+
* `take()` (pushing on top) before it can drive anything, and must
|
|
44
|
+
* `release()` (popping) before the frame beneath it can drive anything
|
|
45
|
+
* again. There is no "steal without taking" path.
|
|
46
|
+
*
|
|
47
|
+
* `release(ownerId, { completed })` pops the top frame (throws if `ownerId`
|
|
48
|
+
* is not on top — the LIFO rule) and applies that frame's declared
|
|
49
|
+
* `CameraRestorePolicy` to `liveCamera` IMMEDIATELY:
|
|
50
|
+
*
|
|
51
|
+
* - `'restore'` (default): `liveCamera` is set back to the frame's captured
|
|
52
|
+
* `restorePose` — bit-exact, no interpolation.
|
|
53
|
+
* - `'retain'`: `liveCamera` is left exactly as the cinematic last set it
|
|
54
|
+
* (the cinematic's end pose).
|
|
55
|
+
* - `'retain-if-completed'`: `'retain'` if `completed: true` was passed,
|
|
56
|
+
* `'restore'` otherwise. This is the policy a cinematic controller (not
|
|
57
|
+
* built in this unit — spec §3.2 names it as a future seam) would use to
|
|
58
|
+
* express "keep the final shot if the cinematic played to its natural
|
|
59
|
+
* end, but snap back to gameplay if it was skipped/cancelled".
|
|
60
|
+
*
|
|
61
|
+
* If a PARENT frame remains after the pop, it is NOT forcibly re-applied —
|
|
62
|
+
* the parent's own tracking/blending state (whatever it last was) simply
|
|
63
|
+
* resumes driving `liveCamera` on the next clock crossing, same as it always
|
|
64
|
+
* would. Concretely: "B stops → ownership returns to A's state" means
|
|
65
|
+
* `liveCamera` is snapped to A's captured pose the instant B releases, and
|
|
66
|
+
* then continues to be driven by A's own last `cut`/`blend` target (if any)
|
|
67
|
+
* on subsequent crossings — exactly as if B had never interrupted A. If A's
|
|
68
|
+
* target camera is static (not itself being animated), the snapped pose and
|
|
69
|
+
* the resumed-tracking pose are identical, which is what the test suite
|
|
70
|
+
* exercises for determinism.
|
|
71
|
+
*
|
|
72
|
+
* `dispose()` is the "render cleanup" path (D6 AC: "render cleanup restore
|
|
73
|
+
* or retain state according to the declared policy"): every still-open
|
|
74
|
+
* frame is released LIFO, per ITS OWN declared policy, with `completed:
|
|
75
|
+
* false` (a teardown is never a natural completion — `retain-if-completed`
|
|
76
|
+
* frames restore on cleanup, exactly like a cancel).
|
|
77
|
+
*
|
|
78
|
+
* ## Cut vs. blend — consuming the D4 `CameraOwnershipHook` seam
|
|
79
|
+
*
|
|
80
|
+
* `theatre-director.ts` (D4) detects discrete `activeCamera` transitions and
|
|
81
|
+
* reports them through `CameraOwnershipHook` — a `CameraOwnershipChangeEvent`
|
|
82
|
+
* carrying `cameraKey`/`mode`/`blendSeconds`, nothing else. This module's
|
|
83
|
+
* `applyDirectorEvent(ownerId, event)` is the entire consumption of that
|
|
84
|
+
* seam: it forwards `event.cameraKey`/`event.blendSeconds` into the same
|
|
85
|
+
* `cut`/`blend` logic a caller could invoke directly. The wiring is ordinary
|
|
86
|
+
* caller-side composition (same pattern D4/D5 already use to compose on one
|
|
87
|
+
* shared clock — see `theatre-director.test.ts`'s "composes with D5" suite):
|
|
88
|
+
*
|
|
89
|
+
* ```ts
|
|
90
|
+
* const ownership = createCameraOwnershipSystem({ liveCamera, cameras, clock });
|
|
91
|
+
* ownership.take('intro-cinematic');
|
|
92
|
+
* const directorBinding = bindDirectorToClock(clock, director, {
|
|
93
|
+
* onActiveCameraChange: (event) => ownership.applyDirectorEvent('intro-cinematic', event),
|
|
94
|
+
* });
|
|
95
|
+
* // ...cinematic plays...
|
|
96
|
+
* ownership.release('intro-cinematic', { completed: true });
|
|
97
|
+
* directorBinding.dispose();
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* The Director's FIRST event per bind is always `mode: 'cut'`
|
|
101
|
+
* (`previousCameraKey: null` — an "assignment", per the D4 module doc) —
|
|
102
|
+
* consumed exactly like any other cut, which is what performs the
|
|
103
|
+
* cinematic's INITIAL camera capture/placement onto its opening shot. A
|
|
104
|
+
* `take()` before binding the Director is required so the pre-cinematic
|
|
105
|
+
* gameplay pose is captured before that first cut lands.
|
|
106
|
+
*
|
|
107
|
+
* ## One unified transition model — cut is just a zero-duration blend
|
|
108
|
+
*
|
|
109
|
+
* Internally, `cut`/`blend`/`applyDirectorEvent` all record exactly one
|
|
110
|
+
* `FrameState` shape: `{ targetKey, fromPose, startTime, durationSeconds }`
|
|
111
|
+
* (`durationSeconds` is `0` for a cut). On EVERY clock crossing, the applied
|
|
112
|
+
* pose is a PURE function of `clock.time` and this fixed record — nothing is
|
|
113
|
+
* mutated as time passes:
|
|
114
|
+
*
|
|
115
|
+
* ```
|
|
116
|
+
* t = durationSeconds <= 0 ? 1 : clamp((clock.time - startTime) / durationSeconds, 0, 1)
|
|
117
|
+
* appliedPose = t >= 1 ? currentPoseOf(targetKey) : lerp(fromPose, currentPoseOf(targetKey), t)
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* `currentPoseOf(targetKey)` is re-sampled LIVE every crossing (never a
|
|
121
|
+
* frozen snapshot), so blending onto — or having already cut to — a moving/
|
|
122
|
+
* Theatre-animated source camera tracks it correctly both mid-blend and
|
|
123
|
+
* after the blend window has fully elapsed. `fromPose` IS a fixed snapshot,
|
|
124
|
+
* taken once at the moment the transition begins (`capturePose(liveCamera)`
|
|
125
|
+
* — "wherever the camera currently is"); `t` clamps to `0` for any
|
|
126
|
+
* `clock.time` before `startTime` (holds `fromPose`) and to `1` at/after
|
|
127
|
+
* `startTime + durationSeconds` (holds the target's live current pose) —
|
|
128
|
+
* the same clamp-to-domain-boundary convention `AnimationClock` itself uses.
|
|
129
|
+
*
|
|
130
|
+
* Because nothing here depends on evaluation HISTORY (no state flips from
|
|
131
|
+
* "blending" to "tracking" as time passes — a cut IS just `durationSeconds:
|
|
132
|
+
* 0`, permanently, until the next `cut`/`blend` call replaces the record),
|
|
133
|
+
* a blend is fully deterministic under arbitrary re-seek: seeking forward
|
|
134
|
+
* past the blend end and then BACK into the blend window reproduces the
|
|
135
|
+
* exact same interpolated pose, not whatever the live target happened to be
|
|
136
|
+
* doing after the blend completed. See `camera-ownership.test.ts`'s
|
|
137
|
+
* "deterministic under re-seek" case.
|
|
138
|
+
*
|
|
139
|
+
* ## Phase choice: 'render', deliberately later than D3's 'preRender'
|
|
140
|
+
*
|
|
141
|
+
* `bindObject3DTransform`/`bindCameraLens` (D3) and `bindDirectorToClock`
|
|
142
|
+
* (D4) both default to the `'preRender'` phase. This module's own clock
|
|
143
|
+
* evaluator defaults to `'render'` — the LAST phase in `PHASE_ORDER` —
|
|
144
|
+
* specifically so `PHASE_ORDER` itself (not registration order) guarantees
|
|
145
|
+
* every registered source camera has already received its per-crossing
|
|
146
|
+
* pose update, and the Director has already fired any `applyDirectorEvent`
|
|
147
|
+
* for this crossing, before this module samples `cameras[key]` or resolves
|
|
148
|
+
* a pending transition. This is the same reasoning `theatre-director.ts`'s
|
|
149
|
+
* module doc gives for its own phase default relative to
|
|
150
|
+
* `bindClockToTheatreSequence`'s `'animation'` phase.
|
|
151
|
+
*
|
|
152
|
+
* ## Camera behaviors — what's tested vs. merely expressible
|
|
153
|
+
*
|
|
154
|
+
* Because a "source camera" is an ordinary `THREE.PerspectiveCamera` sampled
|
|
155
|
+
* fresh every crossing, ANY procedural code that mutates one earlier in
|
|
156
|
+
* `PHASE_ORDER` (or synchronously before a direct `cut`/`blend` call) is
|
|
157
|
+
* picked up automatically — this module does not special-case which
|
|
158
|
+
* mechanism produced the pose:
|
|
159
|
+
*
|
|
160
|
+
* - **cuts, blends, FOV, near/far** — implemented and tested directly in
|
|
161
|
+
* this module (`camera-ownership.test.ts`).
|
|
162
|
+
* - **look-at** — tested: a source camera's orientation is set with
|
|
163
|
+
* ordinary `camera.lookAt(target)` before a crossing; this module reads
|
|
164
|
+
* the resulting `quaternion` like any other pose.
|
|
165
|
+
* - **follow** — tested: a source camera's `position` is updated by
|
|
166
|
+
* ordinary per-crossing application code (simulating a follow
|
|
167
|
+
* controller); `currentPoseOf` re-samples it live every crossing, so the
|
|
168
|
+
* live camera visibly follows.
|
|
169
|
+
* - **orbit, spline-dolly** — EXPRESSIBLE via the identical mechanism
|
|
170
|
+
* (ordinary code moves a registered source camera's `position`/
|
|
171
|
+
* `quaternion` every crossing/frame — an orbit controller stepping an
|
|
172
|
+
* angle, a spline sampler stepping arc-length) but not independently
|
|
173
|
+
* tested in this unit; the follow test proves the general "procedurally
|
|
174
|
+
* driven source camera, resampled live" path they would use.
|
|
175
|
+
*/
|
|
176
|
+
/** Restore-vs-retain policy applied when an ownership frame is released. */
|
|
177
|
+
export type CameraRestorePolicy = 'restore' | 'retain' | 'retain-if-completed';
|
|
178
|
+
/** A fully-captured camera pose: position, orientation, and lens. */
|
|
179
|
+
export interface CameraPose {
|
|
180
|
+
readonly position: THREE.Vector3;
|
|
181
|
+
readonly quaternion: THREE.Quaternion;
|
|
182
|
+
readonly fov: number;
|
|
183
|
+
readonly near: number;
|
|
184
|
+
readonly far: number;
|
|
185
|
+
}
|
|
186
|
+
/** Thrown on an ownership-stack rule violation (not-current-owner, unknown camera key, duplicate take). */
|
|
187
|
+
export declare class CameraOwnershipError extends Error {
|
|
188
|
+
readonly ownerId: string;
|
|
189
|
+
constructor(message: string, ownerId: string);
|
|
190
|
+
}
|
|
191
|
+
/** Snapshot a camera's full pose (position/quaternion cloned — never aliases the live object). */
|
|
192
|
+
export declare function capturePose(camera: THREE.PerspectiveCamera): CameraPose;
|
|
193
|
+
/** Write a captured pose onto a camera, updating its projection matrix. */
|
|
194
|
+
export declare function applyPose(camera: THREE.PerspectiveCamera, pose: CameraPose): void;
|
|
195
|
+
/** Position LERP + quaternion SLERP + fov/near/far LERP, `t` in `[0, 1]`. */
|
|
196
|
+
export declare function lerpPose(from: CameraPose, to: CameraPose, t: number): CameraPose;
|
|
197
|
+
export interface CameraOwnershipTakeOptions {
|
|
198
|
+
/** Restore policy for this frame. Defaults to the system's `defaultPolicy` (itself default `'restore'`). */
|
|
199
|
+
policy?: CameraRestorePolicy;
|
|
200
|
+
}
|
|
201
|
+
export interface CameraOwnershipReleaseOptions {
|
|
202
|
+
/**
|
|
203
|
+
* Whether the cinematic reached its natural end (vs. stop/skip/cancel).
|
|
204
|
+
* Only meaningful for a frame taken with `policy: 'retain-if-completed'`.
|
|
205
|
+
* Default `false`.
|
|
206
|
+
*/
|
|
207
|
+
completed?: boolean;
|
|
208
|
+
}
|
|
209
|
+
export interface CameraOwnershipSystemOptions {
|
|
210
|
+
/** The camera actually rendered. Mutated in place by this system; untouched by it while the ownership stack is empty. */
|
|
211
|
+
liveCamera: THREE.PerspectiveCamera;
|
|
212
|
+
/**
|
|
213
|
+
* `cameraKey -> source camera` registry. Each value is an ordinary
|
|
214
|
+
* `THREE.PerspectiveCamera` that other code (Theatre bindings, orbit/
|
|
215
|
+
* follow/dolly controllers, `lookAt`) is free to drive; this module only
|
|
216
|
+
* reads its pose.
|
|
217
|
+
*/
|
|
218
|
+
cameras: Readonly<Record<string, THREE.PerspectiveCamera>>;
|
|
219
|
+
/** The canonical clock driving deterministic, time-based blends. */
|
|
220
|
+
clock: AnimationClock;
|
|
221
|
+
/** Default `CameraRestorePolicy` for `take()` calls that don't specify one. Default `'restore'`. */
|
|
222
|
+
defaultPolicy?: CameraRestorePolicy;
|
|
223
|
+
/** `AnimationClock` phase to evaluate tracking/blending in. Default `'render'` — see module doc. */
|
|
224
|
+
phase?: SystemPhaseName;
|
|
225
|
+
}
|
|
226
|
+
export interface CameraOwnershipSystem {
|
|
227
|
+
/** Push a new ownership frame for `ownerId`, capturing `liveCamera`'s current pose as its restore point. Throws if `ownerId` is already on the stack. */
|
|
228
|
+
take(ownerId: string, options?: CameraOwnershipTakeOptions): void;
|
|
229
|
+
/** Hard-cut the live camera to `cameraKey`'s current pose. `ownerId` must be the current (top-of-stack) owner. */
|
|
230
|
+
cut(ownerId: string, cameraKey: string): void;
|
|
231
|
+
/** Begin a deterministic, clock-driven blend to `cameraKey` over `blendSeconds`. `ownerId` must be the current owner. */
|
|
232
|
+
blend(ownerId: string, cameraKey: string, blendSeconds: number): void;
|
|
233
|
+
/** Consume a D4 `CameraOwnershipChangeEvent` directly — cuts or blends per `event.mode`/`event.blendSeconds`. */
|
|
234
|
+
applyDirectorEvent(ownerId: string, event: CameraOwnershipChangeEvent): void;
|
|
235
|
+
/** Pop the top frame for `ownerId` (must be the current owner) and apply its declared restore policy. */
|
|
236
|
+
release(ownerId: string, options?: CameraOwnershipReleaseOptions): void;
|
|
237
|
+
/** Whether `ownerId` currently owns the camera (is top of stack). */
|
|
238
|
+
isOwner(ownerId: string): boolean;
|
|
239
|
+
/** Current ownership-stack depth. `0` means gameplay (nobody) owns the camera. */
|
|
240
|
+
readonly depth: number;
|
|
241
|
+
/** Render-cleanup path: releases every open frame LIFO per its own policy (`completed: false`), then unsubscribes. */
|
|
242
|
+
dispose(): void;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Build a camera-ownership system bound to `clock`. See the module doc
|
|
246
|
+
* comment for the full ownership-stack, cut/blend, and restore-policy
|
|
247
|
+
* contract.
|
|
248
|
+
*/
|
|
249
|
+
export declare function createCameraOwnershipSystem(options: CameraOwnershipSystemOptions): CameraOwnershipSystem;
|
|
250
|
+
//# sourceMappingURL=camera-ownership.d.ts.map
|