diff --git a/src/animation.rs b/src/animation.rs index d0fafb1f..8d804588 100644 --- a/src/animation.rs +++ b/src/animation.rs @@ -391,6 +391,7 @@ impl AnimationState { retained: Option>, now_nsec: u64, duration_ms: u32, + curve: AnimationCurve, ) -> bool { let start = spawn_in_start_rect(target); self.set_target( @@ -400,7 +401,7 @@ impl AnimationState { retained, now_nsec, duration_ms, - AnimationCurve::Linear, + curve, ) } @@ -413,6 +414,7 @@ impl AnimationState { layer: RetainedExitLayer, now_nsec: u64, duration_ms: u32, + curve: AnimationCurve, ) -> bool { if from.is_empty() || duration_ms == 0 { return false; @@ -430,6 +432,7 @@ impl AnimationState { to, start_nsec: now_nsec, duration_nsec: duration_ms as u64 * 1_000_000, + curve, last_damage: from, retained, frame_inset, @@ -681,6 +684,7 @@ struct ExitAnimation { to: Rect, start_nsec: u64, duration_nsec: u64, + curve: AnimationCurve, last_damage: Rect, retained: Rc, frame_inset: i32, @@ -700,6 +704,7 @@ impl ExitAnimation { } let elapsed = now_nsec.saturating_sub(self.start_nsec); let t = (elapsed as f64 / self.duration_nsec as f64).clamp(0.0, 1.0); + let t = self.curve.sample(t); lerp_rect(self.from, self.to, t) } } @@ -872,11 +877,12 @@ mod tests { } #[test] - fn spawn_out_frames_shrink_linearly_and_expire() { + fn spawn_out_frames_use_configured_curve_and_expire() { let state = AnimationState::default(); let retained = retained_for_tests(); let from = Rect::new_sized_saturating(10, 20, 100, 80); let to = spawn_in_start_rect(from); + let curve = AnimationCurve::from_config(3); assert!(state.set_spawn_out( from, 2, @@ -884,7 +890,8 @@ mod tests { true, RetainedExitLayer::Floating, 0, - 160 + 160, + curve )); let start = state.exit_frames(0); @@ -897,7 +904,8 @@ mod tests { let middle = state.exit_frames(80_000_000); assert_eq!(middle.len(), 1); - assert_eq!(middle[0].rect, lerp_rect(from, to, 0.5)); + assert_eq!(middle[0].rect, lerp_rect(from, to, curve.sample(0.5))); + assert_ne!(middle[0].rect, lerp_rect(from, to, 0.5)); assert!(state.exit_frames(160_000_000).is_empty()); } @@ -1034,12 +1042,17 @@ mod tests { } #[test] - fn spawn_in_uses_linear_curve() { + fn spawn_in_uses_configured_curve() { let state = AnimationState::default(); let id = NodeId(1); let target = Rect::new_sized_saturating(10, 20, 100, 50); - assert!(state.set_spawn_in(id, target, None, 0, 160)); + let curve = AnimationCurve::from_config(3); + assert!(state.set_spawn_in(id, target, None, 0, 160, curve)); assert_eq!( + state.visual_rect(id, target, 80_000_000), + lerp_rect(spawn_in_start_rect(target), target, curve.sample(0.5)) + ); + assert_ne!( state.visual_rect(id, target, 80_000_000), Rect::new_sized_saturating(35, 33, 50, 25) ); diff --git a/src/state.rs b/src/state.rs index e0cc4469..685af984 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1812,6 +1812,7 @@ impl State { retained, now, self.animations.duration_ms.get(), + self.animations.curve.get(), ); if started { self.damage(expand_damage_rect( @@ -1842,6 +1843,7 @@ impl State { layer, now, self.animations.duration_ms.get(), + self.animations.curve.get(), ); if started { self.damage(expand_damage_rect(