rn-gamekit 0.1.0 → 0.2.1
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/CHANGELOG.md +75 -0
- package/README.md +97 -16
- package/lib/module/assets/defineAssets.js +28 -3
- package/lib/module/assets/defineAssets.js.map +1 -1
- package/lib/module/assets.js +11 -0
- package/lib/module/assets.js.map +1 -0
- package/lib/module/audio/createGameAudio.js +784 -0
- package/lib/module/audio/createGameAudio.js.map +1 -0
- package/lib/module/audio/errors.js +12 -0
- package/lib/module/audio/errors.js.map +1 -0
- package/lib/module/audio/index.js +5 -0
- package/lib/module/audio/index.js.map +1 -0
- package/lib/module/audio/resolver.js +37 -0
- package/lib/module/audio/resolver.js.map +1 -0
- package/lib/module/audio/types.js +4 -0
- package/lib/module/audio/types.js.map +1 -0
- package/lib/module/audio.js +9 -0
- package/lib/module/audio.js.map +1 -0
- package/lib/module/camera2d/bounds.js +59 -0
- package/lib/module/camera2d/bounds.js.map +1 -0
- package/lib/module/camera2d/extents.js +25 -0
- package/lib/module/camera2d/extents.js.map +1 -0
- package/lib/module/camera2d/follow.js +138 -0
- package/lib/module/camera2d/follow.js.map +1 -0
- package/lib/module/camera2d/index.js +20 -0
- package/lib/module/camera2d/index.js.map +1 -0
- package/lib/module/camera2d/interpolation.js +98 -0
- package/lib/module/camera2d/interpolation.js.map +1 -0
- package/lib/module/camera2d/shake.js +85 -0
- package/lib/module/camera2d/shake.js.map +1 -0
- package/lib/module/camera2d/transform.js +151 -0
- package/lib/module/camera2d/transform.js.map +1 -0
- package/lib/module/camera2d/types.js +4 -0
- package/lib/module/camera2d/types.js.map +1 -0
- package/lib/module/camera2d/validation.js +98 -0
- package/lib/module/camera2d/validation.js.map +1 -0
- package/lib/module/camera2d/visibility.js +138 -0
- package/lib/module/camera2d/visibility.js.map +1 -0
- package/lib/module/camera2d.js +9 -0
- package/lib/module/camera2d.js.map +1 -0
- package/lib/module/collision2d/colliders.js +266 -0
- package/lib/module/collision2d/colliders.js.map +1 -0
- package/lib/module/collision2d/debug.js +105 -0
- package/lib/module/collision2d/debug.js.map +1 -0
- package/lib/module/collision2d/filters.js +40 -0
- package/lib/module/collision2d/filters.js.map +1 -0
- package/lib/module/collision2d/index.js +12 -0
- package/lib/module/collision2d/index.js.map +1 -0
- package/lib/module/collision2d/intersections.js +67 -0
- package/lib/module/collision2d/intersections.js.map +1 -0
- package/lib/module/collision2d/manifolds.js +218 -0
- package/lib/module/collision2d/manifolds.js.map +1 -0
- package/lib/module/collision2d/segments.js +187 -0
- package/lib/module/collision2d/segments.js.map +1 -0
- package/lib/module/collision2d/spatialHash.js +167 -0
- package/lib/module/collision2d/spatialHash.js.map +1 -0
- package/lib/module/collision2d/sweeps.js +255 -0
- package/lib/module/collision2d/sweeps.js.map +1 -0
- package/lib/module/collision2d.js +9 -0
- package/lib/module/collision2d.js.map +1 -0
- package/lib/module/core/input/buttonPad.js +214 -0
- package/lib/module/core/input/buttonPad.js.map +1 -0
- package/lib/module/core/input/createInputBuffer.js +66 -14
- package/lib/module/core/input/createInputBuffer.js.map +1 -1
- package/lib/module/core/session/createGameSession.js +454 -50
- package/lib/module/core/session/createGameSession.js.map +1 -1
- package/lib/module/core/session/deepFreeze.js +92 -2
- package/lib/module/core/session/deepFreeze.js.map +1 -1
- package/lib/module/core/session/types.js +12 -0
- package/lib/module/core/session/types.js.map +1 -1
- package/lib/module/definition/defineGame.js +23 -0
- package/lib/module/definition/defineGame.js.map +1 -1
- package/lib/module/events/defineGameEvents.js +46 -0
- package/lib/module/events/defineGameEvents.js.map +1 -0
- package/lib/module/events/errors.js +16 -0
- package/lib/module/events/errors.js.map +1 -0
- package/lib/module/events/index.js +7 -0
- package/lib/module/events/index.js.map +1 -0
- package/lib/module/events/payload.js +219 -0
- package/lib/module/events/payload.js.map +1 -0
- package/lib/module/events/seed.js +33 -0
- package/lib/module/events/seed.js.map +1 -0
- package/lib/module/events/types.js +4 -0
- package/lib/module/events/types.js.map +1 -0
- package/lib/module/events.js +13 -0
- package/lib/module/events.js.map +1 -0
- package/lib/module/geometry/helpers.js +140 -0
- package/lib/module/geometry/helpers.js.map +1 -0
- package/lib/module/geometry/index.js +5 -0
- package/lib/module/geometry/index.js.map +1 -0
- package/lib/module/geometry/validation.js +104 -0
- package/lib/module/geometry/validation.js.map +1 -0
- package/lib/module/geometry.js +9 -0
- package/lib/module/geometry.js.map +1 -0
- package/lib/module/haptics/createGameHaptics.js +214 -0
- package/lib/module/haptics/createGameHaptics.js.map +1 -0
- package/lib/module/haptics/errors.js +12 -0
- package/lib/module/haptics/errors.js.map +1 -0
- package/lib/module/haptics/index.js +5 -0
- package/lib/module/haptics/index.js.map +1 -0
- package/lib/module/haptics/resolver.js +37 -0
- package/lib/module/haptics/resolver.js.map +1 -0
- package/lib/module/haptics/types.js +4 -0
- package/lib/module/haptics/types.js.map +1 -0
- package/lib/module/haptics.js +9 -0
- package/lib/module/haptics.js.map +1 -0
- package/lib/module/index.js +8 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/particles/createParticleSystem.js +481 -0
- package/lib/module/particles/createParticleSystem.js.map +1 -0
- package/lib/module/particles/defineParticleEffect.js +178 -0
- package/lib/module/particles/defineParticleEffect.js.map +1 -0
- package/lib/module/particles/errors.js +9 -0
- package/lib/module/particles/errors.js.map +1 -0
- package/lib/module/particles/index.js +8 -0
- package/lib/module/particles/index.js.map +1 -0
- package/lib/module/particles/sampling.js +121 -0
- package/lib/module/particles/sampling.js.map +1 -0
- package/lib/module/particles/types.js +4 -0
- package/lib/module/particles/types.js.map +1 -0
- package/lib/module/particles.js +4 -0
- package/lib/module/particles.js.map +1 -0
- package/lib/module/react/GameButtonPad.js +344 -0
- package/lib/module/react/GameButtonPad.js.map +1 -0
- package/lib/module/react/GamePointerInput.js +74 -16
- package/lib/module/react/GamePointerInput.js.map +1 -1
- package/lib/module/react/GameView.js +139 -60
- package/lib/module/react/GameView.js.map +1 -1
- package/lib/module/react/assets/createGameAssetStore.js +145 -95
- package/lib/module/react/assets/createGameAssetStore.js.map +1 -1
- package/lib/module/react/assets/useGameAssets.js +60 -35
- package/lib/module/react/assets/useGameAssets.js.map +1 -1
- package/lib/module/react/bindAppLifecycle.js +46 -17
- package/lib/module/react/bindAppLifecycle.js.map +1 -1
- package/lib/module/react/bindGameSession.js +13 -2
- package/lib/module/react/bindGameSession.js.map +1 -1
- package/lib/module/react/camera2d/GameLayer2D.js +50 -0
- package/lib/module/react/camera2d/GameLayer2D.js.map +1 -0
- package/lib/module/react/camera2d/defineGameCamera2D.js +30 -0
- package/lib/module/react/camera2d/defineGameCamera2D.js.map +1 -0
- package/lib/module/react/camera2d/usePresentedCameraBinding.js +177 -0
- package/lib/module/react/camera2d/usePresentedCameraBinding.js.map +1 -0
- package/lib/module/react/cleanupList.js +38 -0
- package/lib/module/react/cleanupList.js.map +1 -0
- package/lib/module/react/lifecycleSource.js +49 -0
- package/lib/module/react/lifecycleSource.js.map +1 -0
- package/lib/module/react/particles/ParticleView.js +308 -0
- package/lib/module/react/particles/ParticleView.js.map +1 -0
- package/lib/module/react/particles/culling.js +115 -0
- package/lib/module/react/particles/culling.js.map +1 -0
- package/lib/module/react/particles/index.js +7 -0
- package/lib/module/react/particles/index.js.map +1 -0
- package/lib/module/react/particles/spriteXForm.js +45 -0
- package/lib/module/react/particles/spriteXForm.js.map +1 -0
- package/lib/module/react/particles/useParticlePresentation.js +204 -0
- package/lib/module/react/particles/useParticlePresentation.js.map +1 -0
- package/lib/module/react/pointerBinding.js +55 -17
- package/lib/module/react/pointerBinding.js.map +1 -1
- package/lib/module/react/pointerCamera.js +28 -0
- package/lib/module/react/pointerCamera.js.map +1 -0
- package/lib/module/react/pointerCoalescer.js +16 -9
- package/lib/module/react/pointerCoalescer.js.map +1 -1
- package/lib/module/react/sprites/GameSprite.js +5 -17
- package/lib/module/react/sprites/GameSprite.js.map +1 -1
- package/lib/module/react/sprites/GameWorld2D.js +112 -9
- package/lib/module/react/sprites/GameWorld2D.js.map +1 -1
- package/lib/module/react/sprites/Sprite.js +48 -63
- package/lib/module/react/sprites/Sprite.js.map +1 -1
- package/lib/module/react/sprites/SpriteBatch.js +53 -28
- package/lib/module/react/sprites/SpriteBatch.js.map +1 -1
- package/lib/module/react/sprites/batchVisibility.js +58 -0
- package/lib/module/react/sprites/batchVisibility.js.map +1 -0
- package/lib/module/react/sprites/spriteSelection.js +103 -0
- package/lib/module/react/sprites/spriteSelection.js.map +1 -0
- package/lib/module/react/sprites/spriteTransform.js +46 -25
- package/lib/module/react/sprites/spriteTransform.js.map +1 -1
- package/lib/module/react/tilemap/TileMapLayer2D.js +217 -0
- package/lib/module/react/tilemap/TileMapLayer2D.js.map +1 -0
- package/lib/module/react/tilemap/tilePresentation.js +374 -0
- package/lib/module/react/tilemap/tilePresentation.js.map +1 -0
- package/lib/module/react/useGameSession.js +70 -0
- package/lib/module/react/useGameSession.js.map +1 -0
- package/lib/module/react/useGameSessionStatus.js +46 -0
- package/lib/module/react/useGameSessionStatus.js.map +1 -0
- package/lib/module/react/viewportBinding.js +5 -1
- package/lib/module/react/viewportBinding.js.map +1 -1
- package/lib/module/react.js +12 -1
- package/lib/module/react.js.map +1 -1
- package/lib/module/scene/defineScene.js +17 -0
- package/lib/module/scene/defineScene.js.map +1 -1
- package/lib/module/sprites/sampleSpriteClip.js +66 -6
- package/lib/module/sprites/sampleSpriteClip.js.map +1 -1
- package/lib/module/sprites/spriteAnimationState.js +10 -20
- package/lib/module/sprites/spriteAnimationState.js.map +1 -1
- package/lib/module/sprites.js +11 -0
- package/lib/module/sprites.js.map +1 -0
- package/lib/module/storage/adapters/asyncStorage.js +57 -0
- package/lib/module/storage/adapters/asyncStorage.js.map +1 -0
- package/lib/module/storage/adapters/memory.js +50 -0
- package/lib/module/storage/adapters/memory.js.map +1 -0
- package/lib/module/storage/errors.js +34 -0
- package/lib/module/storage/errors.js.map +1 -0
- package/lib/module/storage/index.js +11 -0
- package/lib/module/storage/index.js.map +1 -0
- package/lib/module/storage/schema.js +151 -0
- package/lib/module/storage/schema.js.map +1 -0
- package/lib/module/storage/serialization.js +249 -0
- package/lib/module/storage/serialization.js.map +1 -0
- package/lib/module/storage/store.js +387 -0
- package/lib/module/storage/store.js.map +1 -0
- package/lib/module/storage/types.js +16 -0
- package/lib/module/storage/types.js.map +1 -0
- package/lib/module/storage/validation.js +111 -0
- package/lib/module/storage/validation.js.map +1 -0
- package/lib/module/storage.js +4 -0
- package/lib/module/storage.js.map +1 -0
- package/lib/module/testing.js +4 -0
- package/lib/module/testing.js.map +1 -1
- package/lib/module/tilemap/chunkStats.js +27 -0
- package/lib/module/tilemap/chunkStats.js.map +1 -0
- package/lib/module/tilemap/definitions.js +308 -0
- package/lib/module/tilemap/definitions.js.map +1 -0
- package/lib/module/tilemap/errors.js +13 -0
- package/lib/module/tilemap/errors.js.map +1 -0
- package/lib/module/tilemap/index.js +10 -0
- package/lib/module/tilemap/index.js.map +1 -0
- package/lib/module/tilemap/movement.js +379 -0
- package/lib/module/tilemap/movement.js.map +1 -0
- package/lib/module/tilemap/queries.js +114 -0
- package/lib/module/tilemap/queries.js.map +1 -0
- package/lib/module/tilemap/tiledAdapter.js +141 -0
- package/lib/module/tilemap/tiledAdapter.js.map +1 -0
- package/lib/module/tilemap/types.js +4 -0
- package/lib/module/tilemap/types.js.map +1 -0
- package/lib/module/tilemap.js +4 -0
- package/lib/module/tilemap.js.map +1 -0
- package/lib/typescript/src/assets/defineAssets.d.ts +1 -1
- package/lib/typescript/src/assets/defineAssets.d.ts.map +1 -1
- package/lib/typescript/src/assets.d.ts +11 -0
- package/lib/typescript/src/assets.d.ts.map +1 -0
- package/lib/typescript/src/audio/createGameAudio.d.ts +5 -0
- package/lib/typescript/src/audio/createGameAudio.d.ts.map +1 -0
- package/lib/typescript/src/audio/errors.d.ts +6 -0
- package/lib/typescript/src/audio/errors.d.ts.map +1 -0
- package/lib/typescript/src/audio/index.d.ts +4 -0
- package/lib/typescript/src/audio/index.d.ts.map +1 -0
- package/lib/typescript/src/audio/resolver.d.ts +44 -0
- package/lib/typescript/src/audio/resolver.d.ts.map +1 -0
- package/lib/typescript/src/audio/types.d.ts +42 -0
- package/lib/typescript/src/audio/types.d.ts.map +1 -0
- package/lib/typescript/src/audio.d.ts +8 -0
- package/lib/typescript/src/audio.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/bounds.d.ts +25 -0
- package/lib/typescript/src/camera2d/bounds.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/extents.d.ts +17 -0
- package/lib/typescript/src/camera2d/extents.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/follow.d.ts +24 -0
- package/lib/typescript/src/camera2d/follow.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/index.d.ts +19 -0
- package/lib/typescript/src/camera2d/index.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/interpolation.d.ts +17 -0
- package/lib/typescript/src/camera2d/interpolation.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/shake.d.ts +20 -0
- package/lib/typescript/src/camera2d/shake.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/transform.d.ts +44 -0
- package/lib/typescript/src/camera2d/transform.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/types.d.ts +74 -0
- package/lib/typescript/src/camera2d/types.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/validation.d.ts +30 -0
- package/lib/typescript/src/camera2d/validation.d.ts.map +1 -0
- package/lib/typescript/src/camera2d/visibility.d.ts +47 -0
- package/lib/typescript/src/camera2d/visibility.d.ts.map +1 -0
- package/lib/typescript/src/camera2d.d.ts +7 -0
- package/lib/typescript/src/camera2d.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/colliders.d.ts +120 -0
- package/lib/typescript/src/collision2d/colliders.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/debug.d.ts +67 -0
- package/lib/typescript/src/collision2d/debug.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/filters.d.ts +28 -0
- package/lib/typescript/src/collision2d/filters.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/index.d.ts +17 -0
- package/lib/typescript/src/collision2d/index.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/intersections.d.ts +24 -0
- package/lib/typescript/src/collision2d/intersections.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/manifolds.d.ts +39 -0
- package/lib/typescript/src/collision2d/manifolds.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/segments.d.ts +24 -0
- package/lib/typescript/src/collision2d/segments.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/spatialHash.d.ts +50 -0
- package/lib/typescript/src/collision2d/spatialHash.d.ts.map +1 -0
- package/lib/typescript/src/collision2d/sweeps.d.ts +60 -0
- package/lib/typescript/src/collision2d/sweeps.d.ts.map +1 -0
- package/lib/typescript/src/collision2d.d.ts +7 -0
- package/lib/typescript/src/collision2d.d.ts.map +1 -0
- package/lib/typescript/src/core/input/buttonPad.d.ts +59 -0
- package/lib/typescript/src/core/input/buttonPad.d.ts.map +1 -0
- package/lib/typescript/src/core/input/createInputBuffer.d.ts +1 -1
- package/lib/typescript/src/core/input/createInputBuffer.d.ts.map +1 -1
- package/lib/typescript/src/core/input/types.d.ts +7 -0
- package/lib/typescript/src/core/input/types.d.ts.map +1 -1
- package/lib/typescript/src/core/session/createGameSession.d.ts +4 -2
- package/lib/typescript/src/core/session/createGameSession.d.ts.map +1 -1
- package/lib/typescript/src/core/session/deepFreeze.d.ts +21 -1
- package/lib/typescript/src/core/session/deepFreeze.d.ts.map +1 -1
- package/lib/typescript/src/core/session/diagnostics.d.ts +2 -0
- package/lib/typescript/src/core/session/diagnostics.d.ts.map +1 -1
- package/lib/typescript/src/core/session/types.d.ts +69 -4
- package/lib/typescript/src/core/session/types.d.ts.map +1 -1
- package/lib/typescript/src/definition/defineGame.d.ts +12 -1
- package/lib/typescript/src/definition/defineGame.d.ts.map +1 -1
- package/lib/typescript/src/definition/types.d.ts +10 -1
- package/lib/typescript/src/definition/types.d.ts.map +1 -1
- package/lib/typescript/src/events/defineGameEvents.d.ts +26 -0
- package/lib/typescript/src/events/defineGameEvents.d.ts.map +1 -0
- package/lib/typescript/src/events/errors.d.ts +12 -0
- package/lib/typescript/src/events/errors.d.ts.map +1 -0
- package/lib/typescript/src/events/index.d.ts +6 -0
- package/lib/typescript/src/events/index.d.ts.map +1 -0
- package/lib/typescript/src/events/payload.d.ts +21 -0
- package/lib/typescript/src/events/payload.d.ts.map +1 -0
- package/lib/typescript/src/events/seed.d.ts +3 -0
- package/lib/typescript/src/events/seed.d.ts.map +1 -0
- package/lib/typescript/src/events/types.d.ts +42 -0
- package/lib/typescript/src/events/types.d.ts.map +1 -0
- package/lib/typescript/src/events.d.ts +12 -0
- package/lib/typescript/src/events.d.ts.map +1 -0
- package/lib/typescript/src/geometry/helpers.d.ts +35 -0
- package/lib/typescript/src/geometry/helpers.d.ts.map +1 -0
- package/lib/typescript/src/geometry/index.d.ts +4 -0
- package/lib/typescript/src/geometry/index.d.ts.map +1 -0
- package/lib/typescript/src/geometry/types.d.ts +49 -0
- package/lib/typescript/src/geometry/types.d.ts.map +1 -1
- package/lib/typescript/src/geometry/validation.d.ts +44 -0
- package/lib/typescript/src/geometry/validation.d.ts.map +1 -0
- package/lib/typescript/src/geometry.d.ts +7 -0
- package/lib/typescript/src/geometry.d.ts.map +1 -0
- package/lib/typescript/src/haptics/createGameHaptics.d.ts +3 -0
- package/lib/typescript/src/haptics/createGameHaptics.d.ts.map +1 -0
- package/lib/typescript/src/haptics/errors.d.ts +6 -0
- package/lib/typescript/src/haptics/errors.d.ts.map +1 -0
- package/lib/typescript/src/haptics/index.d.ts +4 -0
- package/lib/typescript/src/haptics/index.d.ts.map +1 -0
- package/lib/typescript/src/haptics/resolver.d.ts +22 -0
- package/lib/typescript/src/haptics/resolver.d.ts.map +1 -0
- package/lib/typescript/src/haptics/types.d.ts +37 -0
- package/lib/typescript/src/haptics/types.d.ts.map +1 -0
- package/lib/typescript/src/haptics.d.ts +8 -0
- package/lib/typescript/src/haptics.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/particles/createParticleSystem.d.ts +5 -0
- package/lib/typescript/src/particles/createParticleSystem.d.ts.map +1 -0
- package/lib/typescript/src/particles/defineParticleEffect.d.ts +3 -0
- package/lib/typescript/src/particles/defineParticleEffect.d.ts.map +1 -0
- package/lib/typescript/src/particles/errors.d.ts +5 -0
- package/lib/typescript/src/particles/errors.d.ts.map +1 -0
- package/lib/typescript/src/particles/index.d.ts +6 -0
- package/lib/typescript/src/particles/index.d.ts.map +1 -0
- package/lib/typescript/src/particles/sampling.d.ts +54 -0
- package/lib/typescript/src/particles/sampling.d.ts.map +1 -0
- package/lib/typescript/src/particles/types.d.ts +292 -0
- package/lib/typescript/src/particles/types.d.ts.map +1 -0
- package/lib/typescript/src/particles.d.ts +2 -0
- package/lib/typescript/src/particles.d.ts.map +1 -0
- package/lib/typescript/src/react/GameButtonPad.d.ts +84 -0
- package/lib/typescript/src/react/GameButtonPad.d.ts.map +1 -0
- package/lib/typescript/src/react/GamePointerInput.d.ts.map +1 -1
- package/lib/typescript/src/react/GameView.d.ts +27 -1
- package/lib/typescript/src/react/GameView.d.ts.map +1 -1
- package/lib/typescript/src/react/assets/createGameAssetStore.d.ts.map +1 -1
- package/lib/typescript/src/react/assets/useGameAssets.d.ts.map +1 -1
- package/lib/typescript/src/react/bindAppLifecycle.d.ts +7 -1
- package/lib/typescript/src/react/bindAppLifecycle.d.ts.map +1 -1
- package/lib/typescript/src/react/bindGameSession.d.ts.map +1 -1
- package/lib/typescript/src/react/camera2d/GameLayer2D.d.ts +24 -0
- package/lib/typescript/src/react/camera2d/GameLayer2D.d.ts.map +1 -0
- package/lib/typescript/src/react/camera2d/defineGameCamera2D.d.ts +44 -0
- package/lib/typescript/src/react/camera2d/defineGameCamera2D.d.ts.map +1 -0
- package/lib/typescript/src/react/camera2d/usePresentedCameraBinding.d.ts +22 -0
- package/lib/typescript/src/react/camera2d/usePresentedCameraBinding.d.ts.map +1 -0
- package/lib/typescript/src/react/cleanupList.d.ts +21 -0
- package/lib/typescript/src/react/cleanupList.d.ts.map +1 -0
- package/lib/typescript/src/react/instrumentation.d.ts +33 -3
- package/lib/typescript/src/react/instrumentation.d.ts.map +1 -1
- package/lib/typescript/src/react/lifecycleSource.d.ts +21 -0
- package/lib/typescript/src/react/lifecycleSource.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/ParticleView.d.ts +65 -0
- package/lib/typescript/src/react/particles/ParticleView.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/culling.d.ts +70 -0
- package/lib/typescript/src/react/particles/culling.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/index.d.ts +7 -0
- package/lib/typescript/src/react/particles/index.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/spriteXForm.d.ts +28 -0
- package/lib/typescript/src/react/particles/spriteXForm.d.ts.map +1 -0
- package/lib/typescript/src/react/particles/useParticlePresentation.d.ts +48 -0
- package/lib/typescript/src/react/particles/useParticlePresentation.d.ts.map +1 -0
- package/lib/typescript/src/react/pointerBinding.d.ts +38 -8
- package/lib/typescript/src/react/pointerBinding.d.ts.map +1 -1
- package/lib/typescript/src/react/pointerCamera.d.ts +20 -0
- package/lib/typescript/src/react/pointerCamera.d.ts.map +1 -0
- package/lib/typescript/src/react/pointerCoalescer.d.ts +17 -1
- package/lib/typescript/src/react/pointerCoalescer.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/GameSprite.d.ts +3 -10
- package/lib/typescript/src/react/sprites/GameSprite.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/GameWorld2D.d.ts +51 -6
- package/lib/typescript/src/react/sprites/GameWorld2D.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/Sprite.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/SpriteBatch.d.ts +22 -1
- package/lib/typescript/src/react/sprites/SpriteBatch.d.ts.map +1 -1
- package/lib/typescript/src/react/sprites/batchVisibility.d.ts +28 -0
- package/lib/typescript/src/react/sprites/batchVisibility.d.ts.map +1 -0
- package/lib/typescript/src/react/sprites/spriteSelection.d.ts +58 -0
- package/lib/typescript/src/react/sprites/spriteSelection.d.ts.map +1 -0
- package/lib/typescript/src/react/sprites/spriteTransform.d.ts +27 -12
- package/lib/typescript/src/react/sprites/spriteTransform.d.ts.map +1 -1
- package/lib/typescript/src/react/tilemap/TileMapLayer2D.d.ts +69 -0
- package/lib/typescript/src/react/tilemap/TileMapLayer2D.d.ts.map +1 -0
- package/lib/typescript/src/react/tilemap/tilePresentation.d.ts +217 -0
- package/lib/typescript/src/react/tilemap/tilePresentation.d.ts.map +1 -0
- package/lib/typescript/src/react/useGameSession.d.ts +48 -0
- package/lib/typescript/src/react/useGameSession.d.ts.map +1 -0
- package/lib/typescript/src/react/useGameSessionStatus.d.ts +23 -0
- package/lib/typescript/src/react/useGameSessionStatus.d.ts.map +1 -0
- package/lib/typescript/src/react/viewportBinding.d.ts +5 -1
- package/lib/typescript/src/react/viewportBinding.d.ts.map +1 -1
- package/lib/typescript/src/react.d.ts +18 -1
- package/lib/typescript/src/react.d.ts.map +1 -1
- package/lib/typescript/src/scene/defineScene.d.ts +22 -2
- package/lib/typescript/src/scene/defineScene.d.ts.map +1 -1
- package/lib/typescript/src/scene/types.d.ts +24 -4
- package/lib/typescript/src/scene/types.d.ts.map +1 -1
- package/lib/typescript/src/sprites/sampleSpriteClip.d.ts +26 -2
- package/lib/typescript/src/sprites/sampleSpriteClip.d.ts.map +1 -1
- package/lib/typescript/src/sprites/spriteAnimationState.d.ts +6 -7
- package/lib/typescript/src/sprites/spriteAnimationState.d.ts.map +1 -1
- package/lib/typescript/src/sprites.d.ts +10 -0
- package/lib/typescript/src/sprites.d.ts.map +1 -0
- package/lib/typescript/src/storage/adapters/asyncStorage.d.ts +18 -0
- package/lib/typescript/src/storage/adapters/asyncStorage.d.ts.map +1 -0
- package/lib/typescript/src/storage/adapters/memory.d.ts +16 -0
- package/lib/typescript/src/storage/adapters/memory.d.ts.map +1 -0
- package/lib/typescript/src/storage/errors.d.ts +37 -0
- package/lib/typescript/src/storage/errors.d.ts.map +1 -0
- package/lib/typescript/src/storage/index.d.ts +11 -0
- package/lib/typescript/src/storage/index.d.ts.map +1 -0
- package/lib/typescript/src/storage/schema.d.ts +22 -0
- package/lib/typescript/src/storage/schema.d.ts.map +1 -0
- package/lib/typescript/src/storage/serialization.d.ts +23 -0
- package/lib/typescript/src/storage/serialization.d.ts.map +1 -0
- package/lib/typescript/src/storage/store.d.ts +3 -0
- package/lib/typescript/src/storage/store.d.ts.map +1 -0
- package/lib/typescript/src/storage/types.d.ts +69 -0
- package/lib/typescript/src/storage/types.d.ts.map +1 -0
- package/lib/typescript/src/storage/validation.d.ts +24 -0
- package/lib/typescript/src/storage/validation.d.ts.map +1 -0
- package/lib/typescript/src/storage.d.ts +2 -0
- package/lib/typescript/src/storage.d.ts.map +1 -0
- package/lib/typescript/src/testing.d.ts +1 -0
- package/lib/typescript/src/testing.d.ts.map +1 -1
- package/lib/typescript/src/tilemap/chunkStats.d.ts +14 -0
- package/lib/typescript/src/tilemap/chunkStats.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/definitions.d.ts +38 -0
- package/lib/typescript/src/tilemap/definitions.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/errors.d.ts +7 -0
- package/lib/typescript/src/tilemap/errors.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/index.d.ts +8 -0
- package/lib/typescript/src/tilemap/index.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/movement.d.ts +52 -0
- package/lib/typescript/src/tilemap/movement.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/queries.d.ts +21 -0
- package/lib/typescript/src/tilemap/queries.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/tiledAdapter.d.ts +32 -0
- package/lib/typescript/src/tilemap/tiledAdapter.d.ts.map +1 -0
- package/lib/typescript/src/tilemap/types.d.ts +127 -0
- package/lib/typescript/src/tilemap/types.d.ts.map +1 -0
- package/lib/typescript/src/tilemap.d.ts +2 -0
- package/lib/typescript/src/tilemap.d.ts.map +1 -0
- package/package.json +100 -10
- package/src/assets/defineAssets.ts +31 -5
- package/src/assets.ts +27 -0
- package/src/audio/createGameAudio.ts +749 -0
- package/src/audio/errors.ts +12 -0
- package/src/audio/index.ts +9 -0
- package/src/audio/resolver.ts +74 -0
- package/src/audio/types.ts +47 -0
- package/src/audio.ts +13 -0
- package/src/camera2d/bounds.ts +69 -0
- package/src/camera2d/extents.ts +25 -0
- package/src/camera2d/follow.ts +165 -0
- package/src/camera2d/index.ts +29 -0
- package/src/camera2d/interpolation.ts +113 -0
- package/src/camera2d/shake.ts +90 -0
- package/src/camera2d/transform.ts +148 -0
- package/src/camera2d/types.ts +73 -0
- package/src/camera2d/validation.ts +126 -0
- package/src/camera2d/visibility.ts +181 -0
- package/src/camera2d.ts +6 -0
- package/src/collision2d/colliders.ts +292 -0
- package/src/collision2d/debug.ts +133 -0
- package/src/collision2d/filters.ts +48 -0
- package/src/collision2d/index.ts +74 -0
- package/src/collision2d/intersections.ts +82 -0
- package/src/collision2d/manifolds.ts +191 -0
- package/src/collision2d/segments.ts +176 -0
- package/src/collision2d/spatialHash.ts +211 -0
- package/src/collision2d/sweeps.ts +269 -0
- package/src/collision2d.ts +6 -0
- package/src/core/input/buttonPad.ts +235 -0
- package/src/core/input/createInputBuffer.ts +95 -14
- package/src/core/input/types.ts +7 -0
- package/src/core/session/createGameSession.ts +480 -53
- package/src/core/session/deepFreeze.ts +104 -3
- package/src/core/session/diagnostics.ts +2 -0
- package/src/core/session/types.ts +77 -4
- package/src/definition/defineGame.ts +61 -3
- package/src/definition/types.ts +10 -0
- package/src/events/defineGameEvents.ts +46 -0
- package/src/events/errors.ts +14 -0
- package/src/events/index.ts +14 -0
- package/src/events/payload.ts +234 -0
- package/src/events/seed.ts +33 -0
- package/src/events/types.ts +53 -0
- package/src/events.ts +20 -0
- package/src/geometry/helpers.ts +136 -0
- package/src/geometry/index.ts +14 -0
- package/src/geometry/types.ts +54 -0
- package/src/geometry/validation.ts +131 -0
- package/src/geometry.ts +6 -0
- package/src/haptics/createGameHaptics.ts +214 -0
- package/src/haptics/errors.ts +12 -0
- package/src/haptics/index.ts +3 -0
- package/src/haptics/resolver.ts +58 -0
- package/src/haptics/types.ts +48 -0
- package/src/haptics.ts +7 -0
- package/src/index.ts +37 -1
- package/src/particles/createParticleSystem.ts +505 -0
- package/src/particles/defineParticleEffect.ts +164 -0
- package/src/particles/errors.ts +6 -0
- package/src/particles/index.ts +5 -0
- package/src/particles/sampling.ts +141 -0
- package/src/particles/types.ts +327 -0
- package/src/particles.ts +1 -0
- package/src/react/GameButtonPad.tsx +436 -0
- package/src/react/GamePointerInput.tsx +73 -8
- package/src/react/GameView.tsx +160 -61
- package/src/react/assets/createGameAssetStore.ts +140 -107
- package/src/react/assets/useGameAssets.ts +63 -31
- package/src/react/bindAppLifecycle.ts +55 -19
- package/src/react/bindGameSession.ts +12 -2
- package/src/react/camera2d/GameLayer2D.tsx +43 -0
- package/src/react/camera2d/defineGameCamera2D.ts +59 -0
- package/src/react/camera2d/usePresentedCameraBinding.ts +185 -0
- package/src/react/cleanupList.ts +48 -0
- package/src/react/instrumentation.ts +31 -3
- package/src/react/lifecycleSource.ts +58 -0
- package/src/react/particles/ParticleView.tsx +358 -0
- package/src/react/particles/culling.ts +145 -0
- package/src/react/particles/index.ts +6 -0
- package/src/react/particles/spriteXForm.ts +72 -0
- package/src/react/particles/useParticlePresentation.ts +261 -0
- package/src/react/pointerBinding.ts +74 -16
- package/src/react/pointerCamera.ts +33 -0
- package/src/react/pointerCoalescer.ts +36 -10
- package/src/react/sprites/GameSprite.tsx +4 -33
- package/src/react/sprites/GameWorld2D.tsx +113 -7
- package/src/react/sprites/Sprite.tsx +51 -72
- package/src/react/sprites/SpriteBatch.tsx +74 -22
- package/src/react/sprites/batchVisibility.ts +76 -0
- package/src/react/sprites/spriteSelection.ts +133 -0
- package/src/react/sprites/spriteTransform.ts +46 -26
- package/src/react/tilemap/TileMapLayer2D.tsx +274 -0
- package/src/react/tilemap/tilePresentation.ts +491 -0
- package/src/react/useGameSession.ts +90 -0
- package/src/react/useGameSessionStatus.ts +53 -0
- package/src/react/viewportBinding.ts +5 -1
- package/src/react.ts +18 -1
- package/src/scene/defineScene.ts +47 -5
- package/src/scene/types.ts +37 -3
- package/src/sprites/sampleSpriteClip.ts +82 -14
- package/src/sprites/spriteAnimationState.ts +29 -25
- package/src/sprites.ts +22 -0
- package/src/storage/adapters/asyncStorage.ts +77 -0
- package/src/storage/adapters/memory.ts +58 -0
- package/src/storage/errors.ts +88 -0
- package/src/storage/index.ts +18 -0
- package/src/storage/schema.ts +147 -0
- package/src/storage/serialization.ts +248 -0
- package/src/storage/store.ts +380 -0
- package/src/storage/types.ts +76 -0
- package/src/storage/validation.ts +102 -0
- package/src/storage.ts +1 -0
- package/src/testing.ts +4 -0
- package/src/tilemap/chunkStats.ts +24 -0
- package/src/tilemap/definitions.ts +327 -0
- package/src/tilemap/errors.ts +11 -0
- package/src/tilemap/index.ts +10 -0
- package/src/tilemap/movement.ts +368 -0
- package/src/tilemap/queries.ts +136 -0
- package/src/tilemap/tiledAdapter.ts +165 -0
- package/src/tilemap/types.ts +119 -0
- package/src/tilemap.ts +1 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { useSharedValue, type SharedValue } from 'react-native-reanimated';
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
GameLifecycleSource,
|
|
6
|
+
GameSessionStatus,
|
|
7
|
+
} from '../../core/session/types';
|
|
8
|
+
import type {
|
|
9
|
+
ParticleSystem,
|
|
10
|
+
ParticleUiRegistry,
|
|
11
|
+
} from '../../particles/types';
|
|
12
|
+
|
|
13
|
+
export type SessionStatus = GameSessionStatus;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* What the presentation hook hands to views (T15-SF1): a SCALAR active-time
|
|
17
|
+
* clock written every running frame, plus the bounded emission registry
|
|
18
|
+
* transferred only when membership changes. No per-frame bulk arrays cross
|
|
19
|
+
* the runtime boundary.
|
|
20
|
+
*/
|
|
21
|
+
export interface ParticlePresentation {
|
|
22
|
+
readonly clock: SharedValue<number>;
|
|
23
|
+
readonly registry: SharedValue<ParticleUiRegistry>;
|
|
24
|
+
/** Imperative manual-pause control, independent of the session source. */
|
|
25
|
+
setManualPaused(paused: boolean): void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const EMPTY_REGISTRY: ParticleUiRegistry = Object.freeze({
|
|
29
|
+
registryRevision: -1,
|
|
30
|
+
activeClock: 0,
|
|
31
|
+
effects: Object.freeze({}),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
function defaultSchedule(tick: () => void): () => void {
|
|
35
|
+
const id = requestAnimationFrame(tick);
|
|
36
|
+
return () => cancelAnimationFrame(id);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Own THE exclusive presentation clock for one system (T15-F1/T15-RF3).
|
|
41
|
+
*
|
|
42
|
+
* Per-frame runtime work is ONE scalar write (`clock.value`); the bounded
|
|
43
|
+
* emission registry is transferred only when membership changes (T15-SF1).
|
|
44
|
+
*
|
|
45
|
+
* Pause sources are applied through ONE effect-owned control so transitions
|
|
46
|
+
* stop/start the scheduler immediately — including while the driver is idle
|
|
47
|
+
* or asleep (T15-SF3). Scheduling runs only when the system is running AND
|
|
48
|
+
* at least one particle is active; it fully stops otherwise and restarts
|
|
49
|
+
* from resume/wake transitions.
|
|
50
|
+
*/
|
|
51
|
+
export function useParticlePresentation(
|
|
52
|
+
system: ParticleSystem,
|
|
53
|
+
options?: {
|
|
54
|
+
/**
|
|
55
|
+
* The owning session's lifecycle source (T20.3) — the preferred way to
|
|
56
|
+
* follow a session. Supplied by `GameView` through
|
|
57
|
+
* `useGameLifecycleSource()`. When set, it takes precedence over the
|
|
58
|
+
* legacy `sessionStatus`/`sessionSubscribe` options.
|
|
59
|
+
*/
|
|
60
|
+
readonly lifecycle?: GameLifecycleSource;
|
|
61
|
+
/** Legacy reader: read the owning session's status each frame / on change. */
|
|
62
|
+
readonly sessionStatus?: () => SessionStatus;
|
|
63
|
+
/** Legacy reactive subscription for session status changes. */
|
|
64
|
+
readonly sessionSubscribe?: (
|
|
65
|
+
listener: (status: SessionStatus) => void,
|
|
66
|
+
) => () => void;
|
|
67
|
+
/** Independent user/lab pause reader; a running session cannot cancel it. */
|
|
68
|
+
readonly manualPaused?: () => boolean;
|
|
69
|
+
/** Injectable scheduler for deterministic headless/mounted tests. */
|
|
70
|
+
readonly schedule?: (tick: () => void) => () => void;
|
|
71
|
+
/** Injectable clock for deterministic deltas in tests. */
|
|
72
|
+
readonly now?: () => number;
|
|
73
|
+
},
|
|
74
|
+
): ParticlePresentation {
|
|
75
|
+
const binding = useMemo(() => system.bindPresentation(), [system]);
|
|
76
|
+
const clock = useSharedValue(binding.activeClock);
|
|
77
|
+
const registry = useSharedValue<ParticleUiRegistry>(EMPTY_REGISTRY);
|
|
78
|
+
// T20F-R2: the driver effect must key ONLY on ownership inputs. Shared
|
|
79
|
+
// values are stable in Reanimated; the refs keep the effect closures
|
|
80
|
+
// pointing at the latest instance even where mocks hand back fresh objects.
|
|
81
|
+
const clockRef = useRef(clock);
|
|
82
|
+
const registryRef = useRef(registry);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
clockRef.current = clock;
|
|
85
|
+
registryRef.current = registry;
|
|
86
|
+
}, [clock, registry]);
|
|
87
|
+
|
|
88
|
+
// Latest-source refs (frame loop + reactive callbacks read these).
|
|
89
|
+
const lifecycleRef = useRef(options?.lifecycle);
|
|
90
|
+
lifecycleRef.current = options?.lifecycle;
|
|
91
|
+
const sessionRef = useRef(options?.sessionStatus);
|
|
92
|
+
sessionRef.current = options?.sessionStatus;
|
|
93
|
+
const manualReaderRef = useRef(options?.manualPaused);
|
|
94
|
+
manualReaderRef.current = options?.manualPaused;
|
|
95
|
+
const scheduleRef = useRef(options?.schedule ?? defaultSchedule);
|
|
96
|
+
const nowRef = useRef(options?.now ?? (() => Date.now()));
|
|
97
|
+
// Manual pause lives OUTSIDE render so the imperative setter is stable and
|
|
98
|
+
// reactive without depending on animation frames.
|
|
99
|
+
const manualPausedRef = useRef(false);
|
|
100
|
+
|
|
101
|
+
// Stable control ref owned by the effect (T15-TF2): the public setter and
|
|
102
|
+
// every pause transition route through this without capturing stale state.
|
|
103
|
+
const controlRef = useRef<{
|
|
104
|
+
applyPause(): void;
|
|
105
|
+
syncRegistry(): void;
|
|
106
|
+
updateScheduling(): void;
|
|
107
|
+
}>({ applyPause: () => {}, syncRegistry: () => {}, updateScheduling: () => {} });
|
|
108
|
+
|
|
109
|
+
// T20F-R2: STABLE across re-renders — it reads only refs plus `system`, so
|
|
110
|
+
// the driver effect below keeps a single acquire/subscription for the
|
|
111
|
+
// lifetime of one system instead of rebinding on every parent render.
|
|
112
|
+
const applyCombinedPause = useCallback((): void => {
|
|
113
|
+
if (system.status === 'disposed') return;
|
|
114
|
+
const session = lifecycleRef.current
|
|
115
|
+
? lifecycleRef.current.getStatus()
|
|
116
|
+
: (sessionRef.current?.() ?? 'running');
|
|
117
|
+
const effectivePaused =
|
|
118
|
+
manualPausedRef.current ||
|
|
119
|
+
(manualReaderRef.current?.() ?? false) ||
|
|
120
|
+
session === 'paused' ||
|
|
121
|
+
session === 'disposed';
|
|
122
|
+
if (effectivePaused) system.pauseIfRunning();
|
|
123
|
+
else system.resumeIfPaused();
|
|
124
|
+
}, [system]);
|
|
125
|
+
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
const driver = binding.acquireDriver();
|
|
128
|
+
let cancelled = false;
|
|
129
|
+
let cancelSchedule: (() => void) | null = null;
|
|
130
|
+
let last = nowRef.current();
|
|
131
|
+
|
|
132
|
+
const stopScheduling = (): void => {
|
|
133
|
+
if (cancelSchedule) {
|
|
134
|
+
cancelSchedule();
|
|
135
|
+
cancelSchedule = null;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const startScheduling = (): void => {
|
|
140
|
+
if (cancelled || cancelSchedule !== null) return;
|
|
141
|
+
last = nowRef.current();
|
|
142
|
+
let canceller: (() => void) | null = null;
|
|
143
|
+
// The executed tick clears its own handle so the next frame may be
|
|
144
|
+
// scheduled from inside stepFrame (self-perpetuating loop).
|
|
145
|
+
canceller = scheduleRef.current(() => {
|
|
146
|
+
if (cancelSchedule === canceller) cancelSchedule = null;
|
|
147
|
+
stepFrame();
|
|
148
|
+
});
|
|
149
|
+
cancelSchedule = canceller ?? null;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const syncRegistry = (): void => {
|
|
153
|
+
if (binding.registryRevision !== registryRef.current.value.registryRevision) {
|
|
154
|
+
// Bounded transfer: only on membership changes (T15-SF1). Expiration
|
|
155
|
+
// bumps the revision too, so the terminal prune ships (T15-TF1).
|
|
156
|
+
registryRef.current.value = binding.buildUiRegistry();
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const stepFrame = (): void => {
|
|
161
|
+
if (cancelled) return;
|
|
162
|
+
const now = nowRef.current();
|
|
163
|
+
const dt = Math.max(0, Math.min((now - last) / 1000, 0.1));
|
|
164
|
+
last = now;
|
|
165
|
+
|
|
166
|
+
applyCombinedPause();
|
|
167
|
+
driver.step(dt);
|
|
168
|
+
syncRegistry();
|
|
169
|
+
|
|
170
|
+
// ALWAYS publish the terminal scalar — including the step that
|
|
171
|
+
// transitions to zero actives, so renderers hide the expired record
|
|
172
|
+
// before we sleep (T15-TF1).
|
|
173
|
+
clockRef.current.value = binding.activeClock;
|
|
174
|
+
|
|
175
|
+
// T20L-R2: the frame path enforces the same running guard as the
|
|
176
|
+
// reactive path — a paused step cannot expire particles, so scheduling
|
|
177
|
+
// another frame while paused would spin the driver forever.
|
|
178
|
+
if (system.status === 'running' && !driver.isIdle()) {
|
|
179
|
+
startScheduling();
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// Paused or idle: fully stop; resume transitions and emissions restart us.
|
|
183
|
+
stopScheduling();
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// Effect-owned scheduling control (T15-TF2): pause transitions call this
|
|
187
|
+
// synchronously via the stable ref.
|
|
188
|
+
controlRef.current = {
|
|
189
|
+
applyPause: applyCombinedPause,
|
|
190
|
+
syncRegistry,
|
|
191
|
+
updateScheduling(): void {
|
|
192
|
+
applyCombinedPause();
|
|
193
|
+
syncRegistry();
|
|
194
|
+
if (cancelled || system.status === 'disposed') {
|
|
195
|
+
stopScheduling();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
// Schedule only when running AND something is active.
|
|
199
|
+
if (system.status === 'running' && !driver.isIdle()) {
|
|
200
|
+
startScheduling();
|
|
201
|
+
} else {
|
|
202
|
+
stopScheduling();
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// Reactive pause application + registry sync + reschedule.
|
|
208
|
+
driver.setWakeListener(() => controlRef.current.updateScheduling());
|
|
209
|
+
|
|
210
|
+
// Initial synchronous application at bind time.
|
|
211
|
+
applyCombinedPause();
|
|
212
|
+
|
|
213
|
+
stepFrame();
|
|
214
|
+
|
|
215
|
+
return () => {
|
|
216
|
+
cancelled = true;
|
|
217
|
+
driver.setWakeListener(null);
|
|
218
|
+
stopScheduling();
|
|
219
|
+
driver.release();
|
|
220
|
+
};
|
|
221
|
+
}, [system, binding, applyCombinedPause]);
|
|
222
|
+
|
|
223
|
+
// T20F-R2: the lifecycle subscription is keyed by the SOURCE identity, not
|
|
224
|
+
// by render — one subscribe/detach per system generation. Status changes
|
|
225
|
+
// route through the effect-owned control so pause transitions stay
|
|
226
|
+
// synchronous without rebinding the driver.
|
|
227
|
+
const lifecycleSource = options?.lifecycle ?? null;
|
|
228
|
+
const legacySubscribe = options?.sessionSubscribe ?? null;
|
|
229
|
+
useEffect(() => {
|
|
230
|
+
const onSessionStatus = (status: SessionStatus): void => {
|
|
231
|
+
sessionRef.current = () => status;
|
|
232
|
+
controlRef.current.updateScheduling();
|
|
233
|
+
};
|
|
234
|
+
const detach =
|
|
235
|
+
lifecycleSource !== null
|
|
236
|
+
? lifecycleSource.subscribe(onSessionStatus)
|
|
237
|
+
: legacySubscribe?.(onSessionStatus);
|
|
238
|
+
// T20F-R2 re-review: a REPLACED source may already be paused (or running)
|
|
239
|
+
// — apply its current status immediately instead of waiting for its next
|
|
240
|
+
// transition, so paused emissions are never accepted in between.
|
|
241
|
+
controlRef.current.updateScheduling();
|
|
242
|
+
return detach;
|
|
243
|
+
}, [lifecycleSource, legacySubscribe]);
|
|
244
|
+
|
|
245
|
+
// Initial registry transfer at bind time.
|
|
246
|
+
useEffect(() => {
|
|
247
|
+
registryRef.current.value = binding.buildUiRegistry();
|
|
248
|
+
}, [binding]);
|
|
249
|
+
|
|
250
|
+
const setManualPaused = useCallback(
|
|
251
|
+
(paused: boolean): void => {
|
|
252
|
+
manualPausedRef.current = paused;
|
|
253
|
+
// Route through the effect-owned control: applies combined sources AND
|
|
254
|
+
// stops/starts the scheduler immediately (T15-TF2).
|
|
255
|
+
controlRef.current.updateScheduling();
|
|
256
|
+
},
|
|
257
|
+
[],
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
return { clock, registry, setManualPaused };
|
|
261
|
+
}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
import type { CameraCut2D } from '../camera2d';
|
|
2
|
+
import { logicalToWorld2D } from '../camera2d';
|
|
1
3
|
import type { InputController } from '../core/input/types';
|
|
2
4
|
import type { Point2D } from '../geometry/types';
|
|
3
5
|
import { containsSurfacePoint, surfaceToWorld, type ResolvedViewport2D } from '../viewport2d';
|
|
6
|
+
/** One accepted surface -> world conversion with its exact inputs (T12-TF3). */
|
|
7
|
+
export interface PointerSample2D {
|
|
8
|
+
readonly surface: { readonly x: number; readonly y: number };
|
|
9
|
+
readonly viewport: ResolvedViewport2D;
|
|
10
|
+
readonly camera: CameraCut2D | undefined;
|
|
11
|
+
readonly world: { readonly x: number; readonly y: number };
|
|
12
|
+
}
|
|
13
|
+
|
|
4
14
|
import type { CoalescedPointerEvent } from './pointerCoalescer';
|
|
5
15
|
|
|
6
16
|
/**
|
|
@@ -9,6 +19,12 @@ import type { CoalescedPointerEvent } from './pointerCoalescer';
|
|
|
9
19
|
* replacement carry the old epoch and are rejected on the RN runtime, so a
|
|
10
20
|
* stale begin cannot reacquire input with old coordinates and a stale
|
|
11
21
|
* terminal edge cannot release a newer capture that reused the pointer id.
|
|
22
|
+
*
|
|
23
|
+
* T12-F4: the packet also carries the presented camera cut sampled AT
|
|
24
|
+
* EVENT TIME on the UI runtime. JS inverts through that stamp — never a
|
|
25
|
+
* later lazy read — so the world coordinate matches the camera under the
|
|
26
|
+
* finger when the touch happened, even while the camera follows, zooms,
|
|
27
|
+
* rotates, or shakes.
|
|
12
28
|
*/
|
|
13
29
|
export type PointerPacket = CoalescedPointerEvent & {
|
|
14
30
|
/** Monotonic adapter-owned binding generation (F3 follow-up). */
|
|
@@ -19,6 +35,8 @@ export type PointerPacket = CoalescedPointerEvent & {
|
|
|
19
35
|
readonly seq: number;
|
|
20
36
|
/** UI-runtime timestamp of the forward (F1 latency causality). */
|
|
21
37
|
readonly atMs: number;
|
|
38
|
+
/** The presented camera cut at event time; absent for no-camera games. */
|
|
39
|
+
readonly camera?: CameraCut2D | undefined;
|
|
22
40
|
};
|
|
23
41
|
|
|
24
42
|
/** Monotonic generation source for factory-created bindings (F3). */
|
|
@@ -32,6 +50,12 @@ export interface PointerBindingIdentity<TName extends string> {
|
|
|
32
50
|
readonly action: TName;
|
|
33
51
|
/** Identity token for the viewport provider (changes on layout owner swaps). */
|
|
34
52
|
readonly viewport: unknown;
|
|
53
|
+
/**
|
|
54
|
+
* Identity token for the presented camera provider (T12.4). Changes when
|
|
55
|
+
* the camera surface is replaced, so a fresh binding generation stamps
|
|
56
|
+
* packets under the new camera owner.
|
|
57
|
+
*/
|
|
58
|
+
readonly camera: unknown;
|
|
35
59
|
}
|
|
36
60
|
|
|
37
61
|
/** A binding plus the identity it was created for. */
|
|
@@ -53,7 +77,8 @@ export function createPointerBinding<TName extends string>(
|
|
|
53
77
|
previous !== undefined &&
|
|
54
78
|
previous.identity.input === identity.input &&
|
|
55
79
|
previous.identity.action === identity.action &&
|
|
56
|
-
previous.identity.viewport === identity.viewport
|
|
80
|
+
previous.identity.viewport === identity.viewport &&
|
|
81
|
+
previous.identity.camera === identity.camera
|
|
57
82
|
) {
|
|
58
83
|
return { entry: previous, created: false };
|
|
59
84
|
}
|
|
@@ -78,9 +103,11 @@ export function createPointerBinding<TName extends string>(
|
|
|
78
103
|
* Platform-neutral pointer binding seam.
|
|
79
104
|
*
|
|
80
105
|
* It converts gesture positions from surface coordinates into logical world
|
|
81
|
-
* coordinates through the current resolved viewport
|
|
106
|
+
* coordinates through the current resolved viewport (T12.4: and through the
|
|
107
|
+
* currently presented camera when the game has one), rejects begins that
|
|
82
108
|
* start in `fit` letterbox space, and forwards semantic events into the
|
|
83
|
-
* session input buffer.
|
|
109
|
+
* session input buffer. Containment always happens BEFORE camera inversion:
|
|
110
|
+
* letterbox space is rejected regardless of the camera. The high-level `handleTouches*` methods mirror the
|
|
84
111
|
* adapter's touch dispatch (including forwarding the final up position) so
|
|
85
112
|
* the full adapter behavior is testable without mounting native gesture
|
|
86
113
|
* views. Ownership and neutralization live in the input buffer.
|
|
@@ -89,6 +116,7 @@ export class PointerBinding<TActionName extends string> {
|
|
|
89
116
|
readonly #action: TActionName;
|
|
90
117
|
readonly #input: InputController<TActionName>;
|
|
91
118
|
readonly #getViewport: () => ResolvedViewport2D | undefined;
|
|
119
|
+
readonly #onSample: ((sample: PointerSample2D) => void) | undefined;
|
|
92
120
|
readonly #generation: number;
|
|
93
121
|
#disposed = false;
|
|
94
122
|
|
|
@@ -97,13 +125,39 @@ export class PointerBinding<TActionName extends string> {
|
|
|
97
125
|
input: InputController<TActionName>,
|
|
98
126
|
getViewport: () => ResolvedViewport2D | undefined,
|
|
99
127
|
generation: number,
|
|
128
|
+
onSample?: (sample: PointerSample2D) => void,
|
|
100
129
|
) {
|
|
101
130
|
this.#action = action;
|
|
102
131
|
this.#input = input;
|
|
103
132
|
this.#getViewport = getViewport;
|
|
133
|
+
this.#onSample = onSample;
|
|
104
134
|
this.#generation = generation;
|
|
105
135
|
}
|
|
106
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Surface -> world through the viewport and the EVENT-TIME camera cut
|
|
139
|
+
* (T12.4, T12-F4).
|
|
140
|
+
*
|
|
141
|
+
* The frozen order: inverse viewport first, then inverse camera, using
|
|
142
|
+
* the camera stamp sampled by the UI worklet when the touch happened —
|
|
143
|
+
* the same camera the renderer drew at that moment. Without a camera
|
|
144
|
+
* stamp this is exactly `surfaceToWorld`.
|
|
145
|
+
*/
|
|
146
|
+
#toWorld(viewport: ResolvedViewport2D, point: Point2D, camera: CameraCut2D | undefined): Point2D {
|
|
147
|
+
const logical = surfaceToWorld(viewport, point);
|
|
148
|
+
const world =
|
|
149
|
+
camera === undefined ? logical : logicalToWorld2D(logical, camera.camera, viewport.visibleLogicalBounds);
|
|
150
|
+
// T12-TF3: report one accepted conversion with its exact inputs and
|
|
151
|
+
// output — the lab measures the round trip from the real pipeline.
|
|
152
|
+
this.#onSample?.({
|
|
153
|
+
surface: { x: point.x, y: point.y },
|
|
154
|
+
viewport,
|
|
155
|
+
camera,
|
|
156
|
+
world,
|
|
157
|
+
});
|
|
158
|
+
return world;
|
|
159
|
+
}
|
|
160
|
+
|
|
107
161
|
/**
|
|
108
162
|
* The monotonic adapter-owned generation this binding belongs to (F3).
|
|
109
163
|
* Generations never reset to zero, so a replacement binding and the
|
|
@@ -129,13 +183,13 @@ export class PointerBinding<TActionName extends string> {
|
|
|
129
183
|
}
|
|
130
184
|
switch (packet.kind) {
|
|
131
185
|
case 'begin':
|
|
132
|
-
this.handleTouchesDown(packet.pointerId, packet.x, packet.y);
|
|
186
|
+
this.handleTouchesDown(packet.pointerId, packet.x, packet.y, packet.camera);
|
|
133
187
|
break;
|
|
134
188
|
case 'move':
|
|
135
|
-
this.handleTouchesMove(packet.pointerId, packet.x, packet.y);
|
|
189
|
+
this.handleTouchesMove(packet.pointerId, packet.x, packet.y, packet.camera);
|
|
136
190
|
break;
|
|
137
191
|
case 'end':
|
|
138
|
-
this.handleTouchesUp(packet.pointerId, packet.x, packet.y);
|
|
192
|
+
this.handleTouchesUp(packet.pointerId, packet.x, packet.y, packet.camera);
|
|
139
193
|
break;
|
|
140
194
|
case 'cancel':
|
|
141
195
|
this.handleTouchesCancelled();
|
|
@@ -150,7 +204,11 @@ export class PointerBinding<TActionName extends string> {
|
|
|
150
204
|
* Returns `false` when the layout is invalid or the point starts in
|
|
151
205
|
* letterbox space; the gesture must be rejected and never becomes the owner.
|
|
152
206
|
*/
|
|
153
|
-
begin(
|
|
207
|
+
begin(
|
|
208
|
+
pointerId: number,
|
|
209
|
+
surfacePoint: Point2D,
|
|
210
|
+
camera?: CameraCut2D,
|
|
211
|
+
): boolean {
|
|
154
212
|
if (this.#disposed) {
|
|
155
213
|
return false;
|
|
156
214
|
}
|
|
@@ -161,12 +219,12 @@ export class PointerBinding<TActionName extends string> {
|
|
|
161
219
|
if (!containsSurfacePoint(viewport, surfacePoint)) {
|
|
162
220
|
return false;
|
|
163
221
|
}
|
|
164
|
-
this.#input.begin(this.#action, pointerId,
|
|
222
|
+
this.#input.begin(this.#action, pointerId, this.#toWorld(viewport, surfacePoint, camera));
|
|
165
223
|
return true;
|
|
166
224
|
}
|
|
167
225
|
|
|
168
226
|
/** Move a pointer. Conversion remains unbounded outside content bounds. */
|
|
169
|
-
move(pointerId: number, surfacePoint: Point2D): void {
|
|
227
|
+
move(pointerId: number, surfacePoint: Point2D, camera?: CameraCut2D): void {
|
|
170
228
|
if (this.#disposed) {
|
|
171
229
|
return;
|
|
172
230
|
}
|
|
@@ -174,7 +232,7 @@ export class PointerBinding<TActionName extends string> {
|
|
|
174
232
|
if (viewport === undefined) {
|
|
175
233
|
return;
|
|
176
234
|
}
|
|
177
|
-
this.#input.move(this.#action, pointerId,
|
|
235
|
+
this.#input.move(this.#action, pointerId, this.#toWorld(viewport, surfacePoint, camera));
|
|
178
236
|
}
|
|
179
237
|
|
|
180
238
|
/** End a pointer. The owning pointer is released by the input buffer. */
|
|
@@ -194,13 +252,13 @@ export class PointerBinding<TActionName extends string> {
|
|
|
194
252
|
}
|
|
195
253
|
|
|
196
254
|
/** Handle a touch-down gesture event with a surface position. */
|
|
197
|
-
handleTouchesDown(pointerId: number, x: number, y: number): boolean {
|
|
198
|
-
return this.begin(pointerId, { x, y });
|
|
255
|
+
handleTouchesDown(pointerId: number, x: number, y: number, camera?: CameraCut2D): boolean {
|
|
256
|
+
return this.begin(pointerId, { x, y }, camera);
|
|
199
257
|
}
|
|
200
258
|
|
|
201
259
|
/** Handle a touch-move gesture event with a surface position. */
|
|
202
|
-
handleTouchesMove(pointerId: number, x: number, y: number): void {
|
|
203
|
-
this.move(pointerId, { x, y });
|
|
260
|
+
handleTouchesMove(pointerId: number, x: number, y: number, camera?: CameraCut2D): void {
|
|
261
|
+
this.move(pointerId, { x, y }, camera);
|
|
204
262
|
}
|
|
205
263
|
|
|
206
264
|
/**
|
|
@@ -209,8 +267,8 @@ export class PointerBinding<TActionName extends string> {
|
|
|
209
267
|
* The final position is forwarded before ownership ends so the documented
|
|
210
268
|
* release frame contains the actual point where the pointer lifted.
|
|
211
269
|
*/
|
|
212
|
-
handleTouchesUp(pointerId: number, x: number, y: number): void {
|
|
213
|
-
this.move(pointerId, { x, y });
|
|
270
|
+
handleTouchesUp(pointerId: number, x: number, y: number, camera?: CameraCut2D): void {
|
|
271
|
+
this.move(pointerId, { x, y }, camera);
|
|
214
272
|
this.end(pointerId);
|
|
215
273
|
}
|
|
216
274
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-time camera selection for pointer packets (T12-SF1, T12-TF1).
|
|
3
|
+
*
|
|
4
|
+
* Internal module (not part of the public barrel): the ONE rule that pairs
|
|
5
|
+
* a forwarded pointer event with the presented camera at the event's own
|
|
6
|
+
* native sample. `GamePointerInput` and the focused tests import the same
|
|
7
|
+
* function, so the test can never drift from production.
|
|
8
|
+
*/
|
|
9
|
+
import type { CameraCut2D } from '../camera2d';
|
|
10
|
+
import type { CoalescedPointerEvent } from './pointerCoalescer';
|
|
11
|
+
|
|
12
|
+
/** A move's explicit capture: `captured: true` even when the value is
|
|
13
|
+
* undefined, so a captured-undefined camera is distinguishable from "no
|
|
14
|
+
* stamp" and never falls back to a later presentation (T12-SF1). */
|
|
15
|
+
export interface PointerCameraCapture2D {
|
|
16
|
+
readonly captured: true;
|
|
17
|
+
readonly value: CameraCut2D | undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** The event-time camera for one forwarded event (worklet-safe). */
|
|
21
|
+
export function packetCameraFor(
|
|
22
|
+
forwarded: CoalescedPointerEvent,
|
|
23
|
+
presented: CameraCut2D | undefined,
|
|
24
|
+
): CameraCut2D | undefined {
|
|
25
|
+
'worklet';
|
|
26
|
+
if (forwarded.kind === 'move') {
|
|
27
|
+
const stamp = forwarded.stamp as PointerCameraCapture2D | undefined;
|
|
28
|
+
// A move ALWAYS carries its capture (possibly undefined): a captured
|
|
29
|
+
// undefined stays undefined — never fall back to a later camera.
|
|
30
|
+
return stamp !== undefined ? stamp.value : presented;
|
|
31
|
+
}
|
|
32
|
+
return presented;
|
|
33
|
+
}
|
|
@@ -24,7 +24,19 @@
|
|
|
24
24
|
|
|
25
25
|
export type CoalescedPointerEvent =
|
|
26
26
|
| { readonly kind: 'begin'; readonly pointerId: number; readonly x: number; readonly y: number }
|
|
27
|
-
| {
|
|
27
|
+
| {
|
|
28
|
+
readonly kind: 'move';
|
|
29
|
+
readonly pointerId: number;
|
|
30
|
+
readonly x: number;
|
|
31
|
+
readonly y: number;
|
|
32
|
+
/**
|
|
33
|
+
* Opaque event-time stamp (T12-RF3): captured with the native sample
|
|
34
|
+
* that produced this move and carried through deferral, so the
|
|
35
|
+
* presenter pairs coordinates and presentation state from the SAME
|
|
36
|
+
* native sample, never from a later flush frame.
|
|
37
|
+
*/
|
|
38
|
+
readonly stamp?: unknown;
|
|
39
|
+
}
|
|
28
40
|
| { readonly kind: 'end'; readonly pointerId: number; readonly x: number; readonly y: number }
|
|
29
41
|
| { readonly kind: 'cancel' };
|
|
30
42
|
|
|
@@ -47,7 +59,7 @@ interface ActivePointer {
|
|
|
47
59
|
readonly pointerId: number;
|
|
48
60
|
readonly lastForwardMs: number;
|
|
49
61
|
readonly pendingMove:
|
|
50
|
-
| { readonly x: number; readonly y: number }
|
|
62
|
+
| { readonly x: number; readonly y: number; readonly stamp?: unknown }
|
|
51
63
|
| undefined;
|
|
52
64
|
}
|
|
53
65
|
|
|
@@ -60,11 +72,20 @@ export interface PointerCoalescerState {
|
|
|
60
72
|
/** One native touch input consumed by the pure coalescer reducer. */
|
|
61
73
|
export type PointerCoalescerInput =
|
|
62
74
|
| {
|
|
63
|
-
readonly kind: 'down' | '
|
|
75
|
+
readonly kind: 'down' | 'up';
|
|
76
|
+
readonly pointerId: number;
|
|
77
|
+
readonly x: number;
|
|
78
|
+
readonly y: number;
|
|
79
|
+
readonly nowMs: number;
|
|
80
|
+
}
|
|
81
|
+
| {
|
|
82
|
+
readonly kind: 'move';
|
|
64
83
|
readonly pointerId: number;
|
|
65
84
|
readonly x: number;
|
|
66
85
|
readonly y: number;
|
|
67
86
|
readonly nowMs: number;
|
|
87
|
+
/** Event-time stamp paired with this native sample (T12-RF3). */
|
|
88
|
+
readonly stamp?: unknown;
|
|
68
89
|
}
|
|
69
90
|
| { readonly kind: 'cancel'; readonly nowMs: number }
|
|
70
91
|
| { readonly kind: 'flush'; readonly nowMs: number }
|
|
@@ -158,6 +179,7 @@ export function reducePointerCoalescer(
|
|
|
158
179
|
pointerId: active.pointerId,
|
|
159
180
|
x: active.pendingMove.x,
|
|
160
181
|
y: active.pendingMove.y,
|
|
182
|
+
stamp: active.pendingMove.stamp,
|
|
161
183
|
},
|
|
162
184
|
],
|
|
163
185
|
};
|
|
@@ -182,12 +204,15 @@ export function reducePointerCoalescer(
|
|
|
182
204
|
};
|
|
183
205
|
}
|
|
184
206
|
|
|
207
|
+
// The remaining branch is the move input (down/up/cancel/flush/reset
|
|
208
|
+
// returned above); its optional stamp rides with the sample.
|
|
209
|
+
const moveInput = input as Extract<PointerCoalescerInput, { kind: 'move' }>;
|
|
185
210
|
const shouldForward =
|
|
186
|
-
|
|
211
|
+
moveInput.nowMs - active.lastForwardMs >= state.maxMoveIntervalMs;
|
|
187
212
|
const nextActive: ActivePointer = {
|
|
188
|
-
pointerId:
|
|
189
|
-
lastForwardMs: shouldForward ?
|
|
190
|
-
pendingMove: shouldForward ? undefined : { x:
|
|
213
|
+
pointerId: moveInput.pointerId,
|
|
214
|
+
lastForwardMs: shouldForward ? moveInput.nowMs : active.lastForwardMs,
|
|
215
|
+
pendingMove: shouldForward ? undefined : { x: moveInput.x, y: moveInput.y, stamp: moveInput.stamp },
|
|
191
216
|
};
|
|
192
217
|
return {
|
|
193
218
|
state: { ...state, active: nextActive },
|
|
@@ -195,9 +220,10 @@ export function reducePointerCoalescer(
|
|
|
195
220
|
? [
|
|
196
221
|
{
|
|
197
222
|
kind: 'move',
|
|
198
|
-
pointerId:
|
|
199
|
-
x:
|
|
200
|
-
y:
|
|
223
|
+
pointerId: moveInput.pointerId,
|
|
224
|
+
x: moveInput.x,
|
|
225
|
+
y: moveInput.y,
|
|
226
|
+
stamp: moveInput.stamp,
|
|
201
227
|
},
|
|
202
228
|
]
|
|
203
229
|
: [],
|
|
@@ -13,8 +13,12 @@ import type { CommitFrame } from '../../core/session/types';
|
|
|
13
13
|
import type { SceneSnapshot } from '../../scene/types';
|
|
14
14
|
import type { SceneMap } from '../../definition/types';
|
|
15
15
|
import type { LoadedImage, LoadedSpriteSheet } from '../../assets/types';
|
|
16
|
+
import { spriteFrameNameForClip } from '../../sprites/sampleSpriteClip';
|
|
16
17
|
import { Sprite, type SpriteAnimatable, type SpriteAnimatableBoolean, type SpriteProps } from './Sprite';
|
|
17
18
|
|
|
19
|
+
/** Re-exported from the single sampler contract (GS-ANIMATION-01). */
|
|
20
|
+
export { spriteFrameNameForClip };
|
|
21
|
+
|
|
18
22
|
/** Interpolation context for the select mapper. */
|
|
19
23
|
export interface GameSpriteSelectContext<
|
|
20
24
|
TScenes extends SceneMap,
|
|
@@ -70,39 +74,6 @@ export interface GameSpriteProps<
|
|
|
70
74
|
readonly select: (context: GameSpriteSelectContext<TScenes, TSceneName>) => GameSpriteSelection;
|
|
71
75
|
}
|
|
72
76
|
|
|
73
|
-
/**
|
|
74
|
-
* Select the frame name for a clip + elapsed time (loop/once semantics).
|
|
75
|
-
* Reads the descriptor's animation table; the result is resolved against
|
|
76
|
-
* the frame rectangles by the caller. Reuses the pure sampler's semantics.
|
|
77
|
-
*/
|
|
78
|
-
export function spriteFrameNameForClip(
|
|
79
|
-
animations: Readonly<
|
|
80
|
-
Record<
|
|
81
|
-
string,
|
|
82
|
-
{
|
|
83
|
-
readonly frames: readonly string[];
|
|
84
|
-
readonly frameDurationMs: number;
|
|
85
|
-
readonly mode: 'loop' | 'once';
|
|
86
|
-
}
|
|
87
|
-
>
|
|
88
|
-
>,
|
|
89
|
-
clip: string,
|
|
90
|
-
elapsedMs: number,
|
|
91
|
-
): string {
|
|
92
|
-
'worklet';
|
|
93
|
-
const animation = animations[clip];
|
|
94
|
-
if (animation === undefined || animation.frames.length === 0) {
|
|
95
|
-
return clip;
|
|
96
|
-
}
|
|
97
|
-
const duration = animation.frameDurationMs;
|
|
98
|
-
const count = animation.frames.length;
|
|
99
|
-
const index =
|
|
100
|
-
animation.mode === 'once'
|
|
101
|
-
? Math.min(Math.floor(elapsedMs / duration), count - 1)
|
|
102
|
-
: Math.floor(elapsedMs / duration) % count;
|
|
103
|
-
return animation.frames[index] ?? animation.frames[0] ?? clip;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
77
|
export function GameSprite<
|
|
107
78
|
TScenes extends SceneMap,
|
|
108
79
|
TSceneName extends Extract<keyof TScenes, string>,
|