From d2095e0ee129d273f97fbd33db07e66fc8e9ed83 Mon Sep 17 00:00:00 2001 From: CrazyRoka Date: Sat, 22 Apr 2023 22:46:21 +0100 Subject: [PATCH] Fix timer with zero duration --- crates/bevy_time/src/timer.rs | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/crates/bevy_time/src/timer.rs b/crates/bevy_time/src/timer.rs index 369036eeed6df..9d586f7d59172 100644 --- a/crates/bevy_time/src/timer.rs +++ b/crates/bevy_time/src/timer.rs @@ -224,10 +224,17 @@ impl Timer { if self.finished() { if self.mode == TimerMode::Repeating { - self.times_finished_this_tick = - (self.elapsed().as_nanos() / self.duration().as_nanos()) as u32; - // Duration does not have a modulo - self.set_elapsed(self.elapsed() - self.duration() * self.times_finished_this_tick); + self.times_finished_this_tick = self + .elapsed() + .as_nanos() + .checked_div(self.duration().as_nanos()) + .map_or(u32::MAX, |x| x as u32); + self.set_elapsed( + self.elapsed() + .as_nanos() + .checked_rem(self.duration().as_nanos()) + .map_or(Duration::ZERO, |x| Duration::from_nanos(x as u64)), + ); } else { self.times_finished_this_tick = 1; self.set_elapsed(self.duration()); @@ -329,7 +336,11 @@ impl Timer { /// ``` #[inline] pub fn percent(&self) -> f32 { - self.elapsed().as_secs_f32() / self.duration().as_secs_f32() + if self.duration == Duration::ZERO { + 1.0 + } else { + self.elapsed().as_secs_f32() / self.duration().as_secs_f32() + } } /// Returns the percentage of the timer remaining time (goes from 1.0 to 0.0). @@ -517,6 +528,26 @@ mod tests { assert_eq!(t.times_finished_this_tick(), 0); } + #[test] + fn times_finished_this_tick_repeating_zero_duration() { + let mut t = Timer::from_seconds(0.0, TimerMode::Repeating); + assert_eq!(t.times_finished_this_tick(), 0); + assert_eq!(t.elapsed(), Duration::ZERO); + assert_eq!(t.percent(), 1.0); + t.tick(Duration::from_secs(1)); + assert_eq!(t.times_finished_this_tick(), u32::MAX); + assert_eq!(t.elapsed(), Duration::ZERO); + assert_eq!(t.percent(), 1.0); + t.tick(Duration::from_secs(2)); + assert_eq!(t.times_finished_this_tick(), u32::MAX); + assert_eq!(t.elapsed(), Duration::ZERO); + assert_eq!(t.percent(), 1.0); + t.reset(); + assert_eq!(t.times_finished_this_tick(), 0); + assert_eq!(t.elapsed(), Duration::ZERO); + assert_eq!(t.percent(), 1.0); + } + #[test] fn times_finished_this_tick_precise() { let mut t = Timer::from_seconds(0.01, TimerMode::Repeating);