From 77b56f44d18e87f3a09c088b438bf8ac6dfa9d77 Mon Sep 17 00:00:00 2001 From: Gyrobifastigium <109982825+Gyrobifastigium@users.noreply.github.com> Date: Wed, 3 Aug 2022 23:36:42 +0300 Subject: [PATCH] Carry time delta between tweens in a Sequence (#39) --- src/tweenable.rs | 67 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/src/tweenable.rs b/src/tweenable.rs index 9b13dd1..04ea8f2 100644 --- a/src/tweenable.rs +++ b/src/tweenable.rs @@ -650,28 +650,26 @@ impl Tweenable for Sequence { fn tick( &mut self, - delta: Duration, + mut delta: Duration, target: &mut T, entity: Entity, event_writer: &mut EventWriter, ) -> TweenState { - if self.index < self.tweens.len() { - let mut state = TweenState::Active; - self.time = (self.time + delta).min(self.duration); + self.time = (self.time + delta).min(self.duration); + while self.index < self.tweens.len() { let tween = &mut self.tweens[self.index]; - let tween_state = tween.tick(delta, target, entity, event_writer); - if tween_state == TweenState::Completed { - tween.rewind(); - self.index += 1; - if self.index >= self.tweens.len() { - state = TweenState::Completed; - self.times_completed = 1; - } + let tween_remaining = tween.duration().mul_f32(1.0 - tween.progress()); + if let TweenState::Active = tween.tick(delta, target, entity, event_writer) { + return TweenState::Active; } - state - } else { - TweenState::Completed + + tween.rewind(); + delta -= tween_remaining; + self.index += 1; } + + self.times_completed = 1; + TweenState::Completed } fn times_completed(&self) -> u32 { @@ -1265,6 +1263,45 @@ mod tests { } } + /// Test crossing tween boundaries in one tick. + #[test] + fn seq_tick_boundaries() { + let mut seq = Sequence::new((0..3).map(|i| { + Tween::new( + EaseMethod::Linear, + TweeningType::Once, + Duration::from_secs(1), + TransformPositionLens { + start: Vec3::splat(i as f32), + end: Vec3::splat((i + 1) as f32), + }, + ) + })); + let mut transform = Transform::default(); + + // Dummy world and event writer + let mut world = World::new(); + world.insert_resource(Events::::default()); + let mut system_state: SystemState> = + SystemState::new(&mut world); + let mut event_writer = system_state.get_mut(&mut world); + + // Tick halfway through the first tween, then in one tick: + // - Finish the first tween + // - Start and finish the second tween + // - Start the third tween + for delta in [0.5, 2.0] { + seq.tick( + Duration::from_secs_f32(delta), + &mut transform, + Entity::from_raw(0), + &mut event_writer, + ); + } + assert_eq!(seq.index(), 2); + assert!(transform.translation.abs_diff_eq(Vec3::splat(2.5), 1e-5)); + } + /// Sequence::new() and various Sequence-specific methods #[test] fn seq_iter() {