From 4c2f49daee435e610b0ad889b3e841c8e191b1eb Mon Sep 17 00:00:00 2001 From: Jerome Humbert <djeedai@gmail.com> Date: Sat, 1 Oct 2022 10:55:58 +0100 Subject: [PATCH] Fix animator speed feature (#63) Fix the animator speed applying, which got broken as part of the refactor of #44. Add a `speed()` getter to both `Animator<T>` and `AssetAnimator<T>`. Add some simple test for speed, but this is not enough to make sure the feature doesn't regress, so logged #62 to follow-up with a proper regression test. Fixes #61 --- CHANGELOG.md | 5 ++++ src/lib.rs | 81 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/plugin.rs | 20 +++++++++---- 3 files changed, 98 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52c2c3f..54bb6c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `RepeatCount` and `RepeatStrategy` for more granular control over animation looping. - Added `with_repeat_count()` and `with_repeat_strategy()` builder methods to `Tween<T>`. +- Added a `speed()` getter on `Animator<T>` and `AssetAnimator<T>`. ### Changed @@ -22,6 +23,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed `Tweenable::is_looping()`, which was not implemented for most tweenables. - Removed `TweeningType` in favor of `RepeatCount` and `RepeatStrategy`. +### Fixed + +- Fixed the animator speed feature, which got broken in #44. + ## [0.5.0] - 2022-08-04 ### Added diff --git a/src/lib.rs b/src/lib.rs index 013ae84..211050a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -361,6 +361,15 @@ macro_rules! animator_impl { self.speed = speed; } + /// Get the animation speed. + /// + /// See [`set_speed()`] for a definition of what the animation speed is. + /// + /// [`set_speed()`]: Animator::speed + pub fn speed(&self) -> f32 { + self.speed + } + /// Set the top-level tweenable item this animator controls. pub fn set_tweenable(&mut self, tween: impl Tweenable<T> + Send + Sync + 'static) { self.tweenable = Box::new(tween); @@ -468,18 +477,23 @@ mod tests { use super::{lens::*, *}; + /// Utility to compare floating-point values with a tolerance. + fn abs_diff_eq(a: f32, b: f32, tol: f32) -> bool { + (a - b).abs() < tol + } + struct DummyLens { start: f32, end: f32, } - #[derive(Component)] + #[derive(Debug, Component)] struct DummyComponent { value: f32, } #[cfg(feature = "bevy_asset")] - #[derive(Reflect, TypeUuid)] + #[derive(Debug, Reflect, TypeUuid)] #[uuid = "a33abc11-264e-4bbb-82e8-b87226bb4383"] struct DummyAsset { value: f32, @@ -574,6 +588,13 @@ mod tests { ); let animator = Animator::new(tween).with_state(state); assert_eq!(animator.state, state); + + // impl Debug + let debug_string = format!("{:?}", animator); + assert_eq!( + debug_string, + format!("Animator {{ state: {:?} }}", animator.state) + ); } } @@ -614,6 +635,30 @@ mod tests { assert!(animator.tweenable().progress().abs() <= 1e-5); } + #[test] + fn animator_speed() { + let tween = Tween::<DummyComponent>::new( + EaseFunction::QuadraticInOut, + Duration::from_secs(1), + DummyLens { start: 0., end: 1. }, + ); + + let mut animator = Animator::new(tween); + assert!(abs_diff_eq(animator.speed(), 1., 1e-5)); // default speed + + animator.set_speed(2.4); + assert!(abs_diff_eq(animator.speed(), 2.4, 1e-5)); + + let tween = Tween::<DummyComponent>::new( + EaseFunction::QuadraticInOut, + Duration::from_secs(1), + DummyLens { start: 0., end: 1. }, + ); + + let animator = Animator::new(tween).with_speed(3.5); + assert!(abs_diff_eq(animator.speed(), 3.5, 1e-5)); + } + #[cfg(feature = "bevy_asset")] #[test] fn asset_animator_new() { @@ -641,6 +686,13 @@ mod tests { let animator = AssetAnimator::new(Handle::<DummyAsset>::default(), tween).with_state(state); assert_eq!(animator.state, state); + + // impl Debug + let debug_string = format!("{:?}", animator); + assert_eq!( + debug_string, + format!("AssetAnimator {{ state: {:?} }}", animator.state) + ); } } @@ -681,4 +733,29 @@ mod tests { assert_eq!(animator.state, AnimatorState::Paused); assert!(animator.tweenable().progress().abs() <= 1e-5); } + + #[cfg(feature = "bevy_asset")] + #[test] + fn asset_animator_speed() { + let tween = Tween::new( + EaseFunction::QuadraticInOut, + Duration::from_secs(1), + DummyLens { start: 0., end: 1. }, + ); + + let mut animator = AssetAnimator::new(Handle::<DummyAsset>::default(), tween); + assert!(abs_diff_eq(animator.speed(), 1., 1e-5)); // default speed + + animator.set_speed(2.4); + assert!(abs_diff_eq(animator.speed(), 2.4, 1e-5)); + + let tween = Tween::new( + EaseFunction::QuadraticInOut, + Duration::from_secs(1), + DummyLens { start: 0., end: 1. }, + ); + + let animator = AssetAnimator::new(Handle::<DummyAsset>::default(), tween).with_speed(3.5); + assert!(abs_diff_eq(animator.speed(), 3.5, 1e-5)); + } } diff --git a/src/plugin.rs b/src/plugin.rs index feb22f3..bdbf3dc 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -75,9 +75,13 @@ pub fn component_animator_system<T: Component>( ) { for (entity, ref mut target, ref mut animator) in query.iter_mut() { if animator.state != AnimatorState::Paused { - animator - .tweenable_mut() - .tick(time.delta(), target, entity, &mut event_writer); + let speed = animator.speed(); + animator.tweenable_mut().tick( + time.delta().mul_f32(speed), + target, + entity, + &mut event_writer, + ); } } } @@ -97,10 +101,14 @@ pub fn asset_animator_system<T: Asset>( ) { for (entity, ref mut animator) in query.iter_mut() { if animator.state != AnimatorState::Paused { + let speed = animator.speed(); if let Some(target) = assets.get_mut(&animator.handle()) { - animator - .tweenable_mut() - .tick(time.delta(), target, entity, &mut event_writer); + animator.tweenable_mut().tick( + time.delta().mul_f32(speed), + target, + entity, + &mut event_writer, + ); } } } -- GitLab