@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
|
@@ -1,32 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export interface AnimLayer {
|
|
14
|
-
name: string;
|
|
15
|
-
blendMode?: 'override' | 'additive';
|
|
16
|
-
weight?: number;
|
|
17
|
-
boneMask?: string[];
|
|
18
|
-
defaultState: string;
|
|
19
|
-
states: Record<string, AnimState>;
|
|
20
|
-
transitions: AnimTransition[];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface AnimState {
|
|
24
|
-
clip?: string;
|
|
25
|
-
loop?: boolean;
|
|
26
|
-
speed?: number;
|
|
27
|
-
blendTree?: BlendTreeDef;
|
|
28
|
-
}
|
|
29
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Blend-tree shapes shared by the (removed, E5) legacy `AnimGraph` runtime and
|
|
3
|
+
* the current XState -> AnimationMixer binding (`xstate-animation-binding.ts`,
|
|
4
|
+
* E2). Retained deliberately — see `packages/engine/test/removal-inventory.ts`'s
|
|
5
|
+
* `animgraph` family note: `BlendTreeDef`/`BlendChild` are imported directly by
|
|
6
|
+
* `xstate-animation-binding.ts`, so this file survived E5's removal as a
|
|
7
|
+
* partial edit rather than being deleted whole. Every other type this file
|
|
8
|
+
* used to declare (`AnimGraphFile`, `AnimParameter`, `AnimLayer`, `AnimState`,
|
|
9
|
+
* `AnimTransition`, `TransitionCondition` — the state-machine-shaped half of
|
|
10
|
+
* the old `.animgraph.json` format) was deleted with the runtime that read
|
|
11
|
+
* them (`anim-graph.ts`).
|
|
12
|
+
*/
|
|
30
13
|
export interface BlendTreeDef {
|
|
31
14
|
type: '1D' | '2D' | 'direct';
|
|
32
15
|
parameter: string;
|
|
@@ -40,17 +23,3 @@ export interface BlendChild {
|
|
|
40
23
|
thresholdY?: number; // for 2D
|
|
41
24
|
weight?: number; // for direct
|
|
42
25
|
}
|
|
43
|
-
|
|
44
|
-
export interface AnimTransition {
|
|
45
|
-
from: string; // '*' = any state (wildcard)
|
|
46
|
-
to: string;
|
|
47
|
-
conditions?: TransitionCondition[];
|
|
48
|
-
duration: number; // crossfade duration in seconds
|
|
49
|
-
exitTime?: number; // normalized time (0-1) — transition can happen after this point in the clip
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface TransitionCondition {
|
|
53
|
-
param: string;
|
|
54
|
-
op: '>' | '<' | '>=' | '<=' | '==' | '!=' | 'trigger';
|
|
55
|
-
value?: number | boolean;
|
|
56
|
-
}
|
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
import { PHASE_ORDER, type SystemPhaseName } from '../core/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* D1 — the canonical `AnimationClock` (spec §10 D1, §3.2, §4).
|
|
5
|
+
*
|
|
6
|
+
* VGAI owns exactly one clock per cinematic/scene context. It is the single
|
|
7
|
+
* source of truth for "what time is it" that Theatre sequences, registered
|
|
8
|
+
* GSAP timelines, and cinematic cue evaluators are seeked against (D2/D5/D7
|
|
9
|
+
* — NOT implemented here, this unit is the clock only). The render seam
|
|
10
|
+
* (I2) drives this clock's `seek(t)`/frame-index API directly, without ever
|
|
11
|
+
* advancing gameplay substeps.
|
|
12
|
+
*
|
|
13
|
+
* Design constraints (from the spec and the D1 review notes):
|
|
14
|
+
*
|
|
15
|
+
* - Time is in SECONDS with no hidden wall-clock read. This class never
|
|
16
|
+
* reads the system clock or a monotonic timer directly — the caller (the
|
|
17
|
+
* fixed-step game loop for live playback, or a render/export harness for
|
|
18
|
+
* offline scrubbing) is the only source of `dt`/target time. That is
|
|
19
|
+
* what makes `seek(t)` and frame-index seeking reproducible offline.
|
|
20
|
+
* - No parallel scheduler. Evaluator registration reuses the engine's own
|
|
21
|
+
* `SystemPhaseName`/`PHASE_ORDER` vocabulary (`core/types.ts`) — the same
|
|
22
|
+
* phase names every `GameComponent`/system in the engine already uses —
|
|
23
|
+
* so a Theatre binding (D2), a GSAP registration (D7), and a cue
|
|
24
|
+
* evaluator (D5) can each declare which phase they conceptually belong
|
|
25
|
+
* to and be invoked in one deterministic, engine-wide order instead of
|
|
26
|
+
* each subsystem inventing its own ordering rule. IMPORTANT: this only
|
|
27
|
+
* orders evaluators relative to each other WITHIN one `emit()` — i.e.
|
|
28
|
+
* within a single `seek()`/`advance()` call. Registering at `'preRender'`
|
|
29
|
+
* does NOT mean an evaluator runs during the live engine's own
|
|
30
|
+
* `system-runner` `preRender` phase inside a running RAF frame — the
|
|
31
|
+
* clock is independent of the live game loop's phase execution (and
|
|
32
|
+
* during offline export/scrub there is no RAF frame at all). The shared
|
|
33
|
+
* vocabulary buys a familiar, documented ordering convention between
|
|
34
|
+
* clock-side evaluators, not a promise of interleaving with unrelated
|
|
35
|
+
* engine systems that happen to run in a same-named phase during a live
|
|
36
|
+
* frame.
|
|
37
|
+
* - Frame-index seeking for export must be EXACT: frame `n` at fps `f`
|
|
38
|
+
* always evaluates `start + n / f`, computed directly from `n` and `f`
|
|
39
|
+
* on every call — never by accumulating `1/f` repeatedly, which would
|
|
40
|
+
* drift. See `seekFrame` below.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/** Sign of time evolution while the clock is actually playing. */
|
|
44
|
+
export type ClockDirection = 'forward' | 'reverse';
|
|
45
|
+
|
|
46
|
+
/** Coarse playback state. `advance()` is a no-op unless this is `'playing'`. */
|
|
47
|
+
export type ClockPlaybackState = 'playing' | 'paused' | 'stopped';
|
|
48
|
+
|
|
49
|
+
/** Loop/range metadata — the valid time domain `[start, end]`. */
|
|
50
|
+
export interface ClockRange {
|
|
51
|
+
readonly start: number;
|
|
52
|
+
readonly end: number;
|
|
53
|
+
readonly loop: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* One contiguous, monotonic sweep of time within a single `[start, end]`
|
|
58
|
+
* lap. A step that crosses a loop boundary produces MORE THAN ONE interval
|
|
59
|
+
* (one per lap segment) so a cue evaluator can test each segment
|
|
60
|
+
* independently and never conflate "crossed near the end of lap 1" with
|
|
61
|
+
* "crossed near the start of lap 2".
|
|
62
|
+
*
|
|
63
|
+
* ## Cue-crossing detection convention (half-open)
|
|
64
|
+
*
|
|
65
|
+
* A cue/marker at time `t` is considered CROSSED by an interval iff:
|
|
66
|
+
*
|
|
67
|
+
* - forward interval: `t > interval.from && t <= interval.to`
|
|
68
|
+
* - reverse interval: `t < interval.from && t >= interval.to`
|
|
69
|
+
*
|
|
70
|
+
* This is deliberately half-open on the "from" side and closed on the "to"
|
|
71
|
+
* side (i.e. the endpoint the sweep is *arriving at* counts, the endpoint it
|
|
72
|
+
* *departed from* does not). Consumers (D5 cinematic cues) MUST use exactly
|
|
73
|
+
* this convention, never an inclusive-both-ends test: `seek()` is
|
|
74
|
+
* idempotent and re-asserts a zero-length interval `{from: t, to: t}` on a
|
|
75
|
+
* repeated seek to the same `t` (see `AnimationClock.seek`), and an
|
|
76
|
+
* inclusive-both-ends detector would re-match that zero-length interval
|
|
77
|
+
* (`from === to === t`) and double-fire on every repeated seek. The
|
|
78
|
+
* half-open test above never matches a zero-length interval (`t > t` and
|
|
79
|
+
* `t < t` are both always false), so a fire-once cue evaluator built on it
|
|
80
|
+
* gets idempotent re-seeks "for free" with no extra bookkeeping.
|
|
81
|
+
*/
|
|
82
|
+
export interface ClockInterval {
|
|
83
|
+
readonly from: number;
|
|
84
|
+
readonly to: number;
|
|
85
|
+
readonly direction: ClockDirection;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* What a subscribed evaluator receives on every `seek`/`advance` call that
|
|
90
|
+
* changes (or idempotently re-asserts) the clock's position.
|
|
91
|
+
*/
|
|
92
|
+
export interface ClockCrossing {
|
|
93
|
+
readonly previousTime: number;
|
|
94
|
+
readonly currentTime: number;
|
|
95
|
+
/** Direction of this specific crossing (not necessarily `clock.direction`,
|
|
96
|
+
* which reflects live playback intent — a `seek()` while paused still
|
|
97
|
+
* reports the direction it moved, or the last known direction if it was
|
|
98
|
+
* a no-op re-seek to the same time). */
|
|
99
|
+
readonly direction: ClockDirection;
|
|
100
|
+
readonly timeScale: number;
|
|
101
|
+
/** True iff this crossing wrapped a loop boundary (produced 2+ intervals). */
|
|
102
|
+
readonly looped: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* The monotonic sweep segment(s) covered by this crossing, in
|
|
105
|
+
* chronological evaluation order. Normally exactly one interval
|
|
106
|
+
* `[previousTime, currentTime]`; a loop-wrapping step yields one interval
|
|
107
|
+
* per lap segment traversed. A subscriber determines exactly which cue
|
|
108
|
+
* times were crossed (and in which direction) by testing each interval,
|
|
109
|
+
* never by comparing `previousTime`/`currentTime` directly — that alone
|
|
110
|
+
* is ambiguous across a wrap.
|
|
111
|
+
*/
|
|
112
|
+
readonly intervals: readonly ClockInterval[];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type ClockEvaluator = (crossing: ClockCrossing) => void;
|
|
116
|
+
|
|
117
|
+
export interface ClockEvaluatorHandle {
|
|
118
|
+
dispose(): void;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface AnimationClockOptions {
|
|
122
|
+
/** Range start, in seconds. Default 0. */
|
|
123
|
+
start?: number;
|
|
124
|
+
/** Range end, in seconds. Default `Math.max(start, 1)`. */
|
|
125
|
+
end?: number;
|
|
126
|
+
/** Whether `advance()` wraps at the range boundary instead of clamping. Default false. */
|
|
127
|
+
loop?: boolean;
|
|
128
|
+
/** Playback rate multiplier, must be finite and >= 0. Default 1. */
|
|
129
|
+
timeScale?: number;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const EPSILON = 1e-9;
|
|
133
|
+
// Bails a pathological single `advance(dt)` call out of lap-by-lap interval
|
|
134
|
+
// enumeration (e.g. an absurd `dt` at max time scale over a tiny loop range)
|
|
135
|
+
// so a single call can never spin unboundedly. Real fixed-step `dt`s never
|
|
136
|
+
// approach this.
|
|
137
|
+
const MAX_LAPS_PER_ADVANCE = 100_000;
|
|
138
|
+
|
|
139
|
+
interface SweepResult {
|
|
140
|
+
pos: number;
|
|
141
|
+
intervals: ClockInterval[];
|
|
142
|
+
looped: boolean;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Advance `p0` forward by `distance` (>= 0) within `range`, honoring loop/clamp. */
|
|
146
|
+
function sweepForward(p0: number, distance: number, range: ClockRange): SweepResult {
|
|
147
|
+
const length = range.end - range.start;
|
|
148
|
+
const canLoop = range.loop && length > EPSILON;
|
|
149
|
+
const intervals: ClockInterval[] = [];
|
|
150
|
+
let pos = p0;
|
|
151
|
+
let remaining = distance;
|
|
152
|
+
let looped = false;
|
|
153
|
+
let laps = 0;
|
|
154
|
+
|
|
155
|
+
for (;;) {
|
|
156
|
+
const distToEnd = range.end - pos;
|
|
157
|
+
if (!canLoop || remaining <= distToEnd + EPSILON) {
|
|
158
|
+
// Always clamp to range.end here, even when canLoop is true: this
|
|
159
|
+
// terminal branch is reached whenever `remaining` is within EPSILON of
|
|
160
|
+
// `distToEnd` (not just when it's exactly equal), so `pos + remaining`
|
|
161
|
+
// can overshoot `range.end` by up to EPSILON on a loop range. Clamping
|
|
162
|
+
// unconditionally (D1 follow-up, spec §10 D5) keeps `clock.time` from
|
|
163
|
+
// ever exceeding `range.end`, which in turn keeps the NEXT advance()'s
|
|
164
|
+
// `distToEnd` non-negative and prevents a degenerate `from > to`
|
|
165
|
+
// interval on the following call.
|
|
166
|
+
const to = Math.min(pos + remaining, range.end);
|
|
167
|
+
intervals.push({ from: pos, to, direction: 'forward' });
|
|
168
|
+
pos = to;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
intervals.push({ from: pos, to: range.end, direction: 'forward' });
|
|
172
|
+
remaining -= distToEnd;
|
|
173
|
+
pos = range.start;
|
|
174
|
+
looped = true;
|
|
175
|
+
laps++;
|
|
176
|
+
if (laps > MAX_LAPS_PER_ADVANCE) {
|
|
177
|
+
const wrapped = range.start + (remaining % length);
|
|
178
|
+
intervals.push({ from: pos, to: wrapped, direction: 'forward' });
|
|
179
|
+
pos = wrapped;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return { pos, intervals, looped };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Advance `p0` backward by `distance` (>= 0) within `range`, honoring loop/clamp. */
|
|
188
|
+
function sweepReverse(p0: number, distance: number, range: ClockRange): SweepResult {
|
|
189
|
+
const length = range.end - range.start;
|
|
190
|
+
const canLoop = range.loop && length > EPSILON;
|
|
191
|
+
const intervals: ClockInterval[] = [];
|
|
192
|
+
let pos = p0;
|
|
193
|
+
let remaining = distance;
|
|
194
|
+
let looped = false;
|
|
195
|
+
let laps = 0;
|
|
196
|
+
|
|
197
|
+
for (;;) {
|
|
198
|
+
const distToStart = pos - range.start;
|
|
199
|
+
if (!canLoop || remaining <= distToStart + EPSILON) {
|
|
200
|
+
// Mirror of the forward-sweep clamp above: always clamp to
|
|
201
|
+
// range.start here so a reverse advance() cannot undershoot it by up
|
|
202
|
+
// to EPSILON on a loop range (D1 follow-up, spec §10 D5).
|
|
203
|
+
const to = Math.max(pos - remaining, range.start);
|
|
204
|
+
intervals.push({ from: pos, to, direction: 'reverse' });
|
|
205
|
+
pos = to;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
intervals.push({ from: pos, to: range.start, direction: 'reverse' });
|
|
209
|
+
remaining -= distToStart;
|
|
210
|
+
pos = range.end;
|
|
211
|
+
looped = true;
|
|
212
|
+
laps++;
|
|
213
|
+
if (laps > MAX_LAPS_PER_ADVANCE) {
|
|
214
|
+
const wrapped = range.end - (remaining % length);
|
|
215
|
+
intervals.push({ from: pos, to: wrapped, direction: 'reverse' });
|
|
216
|
+
pos = wrapped;
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return { pos, intervals, looped };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function clampToRange(t: number, range: ClockRange): number {
|
|
225
|
+
if (t < range.start) return range.start;
|
|
226
|
+
if (t > range.end) return range.end;
|
|
227
|
+
return t;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
interface EvaluatorEntry {
|
|
231
|
+
phase: SystemPhaseName;
|
|
232
|
+
order: number;
|
|
233
|
+
fn: ClockEvaluator;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* The engine-owned canonical clock. See the module doc comment above for
|
|
238
|
+
* the design constraints this implementation is bound by.
|
|
239
|
+
*/
|
|
240
|
+
export class AnimationClock {
|
|
241
|
+
private _previousTime: number;
|
|
242
|
+
private _currentTime: number;
|
|
243
|
+
private _range: ClockRange;
|
|
244
|
+
private _timeScale: number;
|
|
245
|
+
private _playDirection: ClockDirection = 'forward';
|
|
246
|
+
private _lastCrossingDirection: ClockDirection = 'forward';
|
|
247
|
+
private _playbackState: ClockPlaybackState = 'stopped';
|
|
248
|
+
private _evaluators: EvaluatorEntry[] = [];
|
|
249
|
+
private _registrationCounter = 0;
|
|
250
|
+
|
|
251
|
+
constructor(options: AnimationClockOptions = {}) {
|
|
252
|
+
const start = options.start ?? 0;
|
|
253
|
+
const end = options.end ?? Math.max(start, 1);
|
|
254
|
+
if (end < start) {
|
|
255
|
+
throw new Error(`[AnimationClock] range end (${end}) must be >= start (${start})`);
|
|
256
|
+
}
|
|
257
|
+
const timeScale = options.timeScale ?? 1;
|
|
258
|
+
if (!Number.isFinite(timeScale) || timeScale < 0) {
|
|
259
|
+
throw new Error(`[AnimationClock] timeScale must be a finite number >= 0, got ${timeScale}`);
|
|
260
|
+
}
|
|
261
|
+
this._range = { start, end, loop: options.loop ?? false };
|
|
262
|
+
this._timeScale = timeScale;
|
|
263
|
+
this._previousTime = start;
|
|
264
|
+
this._currentTime = start;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Current playhead time, in seconds. */
|
|
268
|
+
get time(): number {
|
|
269
|
+
return this._currentTime;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Playhead time immediately before the most recent seek/advance. */
|
|
273
|
+
get previousTime(): number {
|
|
274
|
+
return this._previousTime;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Playback direction. `'paused'` whenever `playbackState !== 'playing'`
|
|
279
|
+
* (covers both `pause()` and `stop()`) — matches the spec's literal
|
|
280
|
+
* `direction: forward | reverse | paused` acceptance criterion. The
|
|
281
|
+
* underlying intended direction is preserved across pause/resume; see
|
|
282
|
+
* `play()`.
|
|
283
|
+
*/
|
|
284
|
+
get direction(): ClockDirection | 'paused' {
|
|
285
|
+
return this._playbackState === 'playing' ? this._playDirection : 'paused';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
get playbackState(): ClockPlaybackState {
|
|
289
|
+
return this._playbackState;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
get timeScale(): number {
|
|
293
|
+
return this._timeScale;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
set timeScale(value: number) {
|
|
297
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
298
|
+
throw new Error(`[AnimationClock] timeScale must be a finite number >= 0, got ${value}`);
|
|
299
|
+
}
|
|
300
|
+
this._timeScale = value;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
get range(): ClockRange {
|
|
304
|
+
return this._range;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Update loop/range metadata. The current playhead is clamped into the
|
|
309
|
+
* new range if necessary (reported as an ordinary crossing — same
|
|
310
|
+
* evaluator path as `seek`/`advance` — so subscribers observe it).
|
|
311
|
+
*/
|
|
312
|
+
setRange(next: Partial<Pick<ClockRange, 'start' | 'end' | 'loop'>>): void {
|
|
313
|
+
const start = next.start ?? this._range.start;
|
|
314
|
+
const end = next.end ?? this._range.end;
|
|
315
|
+
const loop = next.loop ?? this._range.loop;
|
|
316
|
+
if (end < start) {
|
|
317
|
+
throw new Error(`[AnimationClock] range end (${end}) must be >= start (${start})`);
|
|
318
|
+
}
|
|
319
|
+
this._range = { start, end, loop };
|
|
320
|
+
const clamped = clampToRange(this._currentTime, this._range);
|
|
321
|
+
if (clamped !== this._currentTime) {
|
|
322
|
+
this.seek(clamped);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Begin/resume playback. `direction` sets (or re-asserts) the intended
|
|
328
|
+
* playback direction for subsequent `advance()` calls; omit it to resume
|
|
329
|
+
* in whatever direction was last set (default `'forward'` the first time).
|
|
330
|
+
*/
|
|
331
|
+
play(direction?: ClockDirection): void {
|
|
332
|
+
if (direction) this._playDirection = direction;
|
|
333
|
+
this._playbackState = 'playing';
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Halt playback at the current position. `advance()` becomes a no-op. */
|
|
337
|
+
pause(): void {
|
|
338
|
+
this._playbackState = 'paused';
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Halt playback at the current position (distinct from `pause()` only in
|
|
343
|
+
* reported `playbackState`; this unit does not prescribe a reset-to-start
|
|
344
|
+
* policy — that is a cinematic-controller/render-seam decision, D5/I2).
|
|
345
|
+
* `advance()` is a no-op in this state, same as `paused`.
|
|
346
|
+
*/
|
|
347
|
+
stop(): void {
|
|
348
|
+
this._playbackState = 'stopped';
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Jump directly to `t` (clamped into `range`). Idempotent: calling
|
|
353
|
+
* `seek(t)` twice in a row leaves `time`/`previousTime` identical to
|
|
354
|
+
* calling it once — the second call is a true no-op (no state mutation,
|
|
355
|
+
* though evaluators still fire so a subscriber can rely on `seek` always
|
|
356
|
+
* producing a crossing for e.g. re-asserting visual state).
|
|
357
|
+
*/
|
|
358
|
+
seek(t: number): ClockCrossing {
|
|
359
|
+
const target = clampToRange(t, this._range);
|
|
360
|
+
if (target === this._currentTime) {
|
|
361
|
+
return this.emit(
|
|
362
|
+
this._currentTime,
|
|
363
|
+
this._currentTime,
|
|
364
|
+
[{ from: target, to: target, direction: this._lastCrossingDirection }],
|
|
365
|
+
false,
|
|
366
|
+
this._lastCrossingDirection,
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
const direction: ClockDirection = target > this._currentTime ? 'forward' : 'reverse';
|
|
370
|
+
const prev = this._currentTime;
|
|
371
|
+
this._previousTime = prev;
|
|
372
|
+
this._currentTime = target;
|
|
373
|
+
this._lastCrossingDirection = direction;
|
|
374
|
+
return this.emit(prev, target, [{ from: prev, to: target, direction }], false, direction);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Frame-index seek for export (D1 AC): seeks to EXACTLY `range.start +
|
|
379
|
+
* n / fps`, computed fresh from `n`/`fps` on every call. This is what
|
|
380
|
+
* keeps a rendered frame sequence drift-free — unlike repeatedly calling
|
|
381
|
+
* `advance(1 / fps)` `n` times (which accumulates float error), this
|
|
382
|
+
* always derives the same exact double for a given `(n, fps)` pair no
|
|
383
|
+
* matter what the clock's prior state was.
|
|
384
|
+
*/
|
|
385
|
+
seekFrame(n: number, fps: number): ClockCrossing {
|
|
386
|
+
if (!Number.isFinite(fps) || fps <= 0) {
|
|
387
|
+
throw new Error(`[AnimationClock] seekFrame fps must be a finite number > 0, got ${fps}`);
|
|
388
|
+
}
|
|
389
|
+
return this.seek(this._range.start + n / fps);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Fixed-step advance by `dt` seconds (magnitude; sign of movement comes
|
|
394
|
+
* from `direction`/`play()`, not from `dt`'s sign). A no-op whenever
|
|
395
|
+
* `playbackState !== 'playing'` — this is what makes `advance()` do
|
|
396
|
+
* nothing while paused (D1 AC). Returns `null` for that no-op case;
|
|
397
|
+
* otherwise returns the resulting crossing (which may span multiple loop
|
|
398
|
+
* laps if `dt * timeScale` exceeds the range length).
|
|
399
|
+
*/
|
|
400
|
+
advance(dt: number): ClockCrossing | null {
|
|
401
|
+
if (this._playbackState !== 'playing') return null;
|
|
402
|
+
if (!Number.isFinite(dt)) {
|
|
403
|
+
throw new Error(`[AnimationClock] advance(dt) requires a finite dt, got ${dt}`);
|
|
404
|
+
}
|
|
405
|
+
const magnitude = Math.abs(dt) * this._timeScale;
|
|
406
|
+
const p0 = this._currentTime;
|
|
407
|
+
if (magnitude === 0) {
|
|
408
|
+
return this.emit(p0, p0, [], false, this._playDirection);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const result =
|
|
412
|
+
this._playDirection === 'forward'
|
|
413
|
+
? sweepForward(p0, magnitude, this._range)
|
|
414
|
+
: sweepReverse(p0, magnitude, this._range);
|
|
415
|
+
|
|
416
|
+
this._previousTime = p0;
|
|
417
|
+
this._currentTime = result.pos;
|
|
418
|
+
this._lastCrossingDirection = this._playDirection;
|
|
419
|
+
return this.emit(p0, result.pos, result.intervals, result.looped, this._playDirection);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Register an evaluator against a phase from the engine's own
|
|
424
|
+
* `SystemPhaseName` vocabulary (`core/types.ts`). Evaluators fire on
|
|
425
|
+
* every `seek()`/`advance()` (including idempotent no-op seeks and
|
|
426
|
+
* `setRange` clamps) in `PHASE_ORDER` order, then registration order
|
|
427
|
+
* within a phase — the same "deterministic phase order" every other
|
|
428
|
+
* engine system is invoked in, so a Theatre binding, a registered-GSAP
|
|
429
|
+
* seek, and a cue evaluator can each declare their phase and compose
|
|
430
|
+
* without inventing a second ordering rule.
|
|
431
|
+
*/
|
|
432
|
+
subscribe(phase: SystemPhaseName, evaluator: ClockEvaluator): ClockEvaluatorHandle {
|
|
433
|
+
if (!PHASE_ORDER.includes(phase)) {
|
|
434
|
+
throw new Error(
|
|
435
|
+
`[AnimationClock] unknown phase "${phase}". Valid: ${PHASE_ORDER.join(', ')}`,
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
const entry: EvaluatorEntry = { phase, order: this._registrationCounter++, fn: evaluator };
|
|
439
|
+
this._evaluators.push(entry);
|
|
440
|
+
return {
|
|
441
|
+
dispose: () => {
|
|
442
|
+
const idx = this._evaluators.indexOf(entry);
|
|
443
|
+
if (idx !== -1) this._evaluators.splice(idx, 1);
|
|
444
|
+
},
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private emit(
|
|
449
|
+
previousTime: number,
|
|
450
|
+
currentTime: number,
|
|
451
|
+
intervals: ClockInterval[],
|
|
452
|
+
looped: boolean,
|
|
453
|
+
direction: ClockDirection,
|
|
454
|
+
): ClockCrossing {
|
|
455
|
+
const crossing: ClockCrossing = {
|
|
456
|
+
previousTime,
|
|
457
|
+
currentTime,
|
|
458
|
+
direction,
|
|
459
|
+
timeScale: this._timeScale,
|
|
460
|
+
looped,
|
|
461
|
+
intervals,
|
|
462
|
+
};
|
|
463
|
+
if (this._evaluators.length > 0) {
|
|
464
|
+
const ordered = [...this._evaluators].sort((a, b) => {
|
|
465
|
+
const pa = PHASE_ORDER.indexOf(a.phase);
|
|
466
|
+
const pb = PHASE_ORDER.indexOf(b.phase);
|
|
467
|
+
return pa !== pb ? pa - pb : a.order - b.order;
|
|
468
|
+
});
|
|
469
|
+
for (const entry of ordered) {
|
|
470
|
+
try {
|
|
471
|
+
entry.fn(crossing);
|
|
472
|
+
} catch (err) {
|
|
473
|
+
console.error(`[AnimationClock] evaluator in phase "${entry.phase}" threw:`, err);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return crossing;
|
|
478
|
+
}
|
|
479
|
+
}
|