Make paused timers update just_finished on tick (#4445)

# Objective
Make timers update `just_finished` on tick, even if paused.
Fixes #4436

## Solution
`just_finished()` returns `times_finished > 0`. So I:
 * Renamed `times_finished` to `times_finished_this_tick` to reduce confusion.
 * Set `times_finished_this_tick` to `0` on tick when paused.
 * Additionally set `finished` to `false` if the timer is repeating.

Notably this change broke none of the existing tests, so I added a couple for this.

Files changed shows a lot of noise because of the rename. Check the first commit for the relevant changes.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
This commit is contained in:
devil ira 2022-04-26 18:42:42 +00:00
parent 18b27269c0
commit 3f423074bf

View file

@ -15,7 +15,7 @@ pub struct Timer {
duration: Duration,
repeating: bool,
finished: bool,
times_finished: u32,
times_finished_this_tick: u32,
}
impl Timer {
@ -76,7 +76,7 @@ impl Timer {
/// ```
#[inline]
pub fn just_finished(&self) -> bool {
self.times_finished > 0
self.times_finished_this_tick > 0
}
/// Returns the time elapsed on the timer. Guaranteed to be between 0.0 and `duration`.
@ -202,11 +202,15 @@ impl Timer {
/// ```
pub fn tick(&mut self, delta: Duration) -> &Self {
if self.paused() {
self.times_finished_this_tick = 0;
if self.repeating() {
self.finished = false;
}
return self;
}
if !self.repeating() && self.finished() {
self.times_finished = 0;
self.times_finished_this_tick = 0;
return self;
}
@ -215,16 +219,16 @@ impl Timer {
if self.finished() {
if self.repeating() {
self.times_finished =
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);
self.set_elapsed(self.elapsed() - self.duration() * self.times_finished_this_tick);
} else {
self.times_finished = 1;
self.times_finished_this_tick = 1;
self.set_elapsed(self.duration());
}
} else {
self.times_finished = 0;
self.times_finished_this_tick = 0;
}
self
@ -305,7 +309,7 @@ impl Timer {
pub fn reset(&mut self) {
self.stopwatch.reset();
self.finished = false;
self.times_finished = 0;
self.times_finished_this_tick = 0;
}
/// Returns the percentage of the timer elapsed time (goes from 0.0 to 1.0).
@ -350,15 +354,15 @@ impl Timer {
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, true);
/// timer.tick(Duration::from_secs_f32(6.0));
/// assert_eq!(timer.times_finished(), 6);
/// assert_eq!(timer.times_finished_this_tick(), 6);
/// timer.tick(Duration::from_secs_f32(2.0));
/// assert_eq!(timer.times_finished(), 2);
/// assert_eq!(timer.times_finished_this_tick(), 2);
/// timer.tick(Duration::from_secs_f32(0.5));
/// assert_eq!(timer.times_finished(), 0);
/// assert_eq!(timer.times_finished_this_tick(), 0);
/// ```
#[inline]
pub fn times_finished(&self) -> u32 {
self.times_finished
pub fn times_finished_this_tick(&self) -> u32 {
self.times_finished_this_tick
}
}
@ -376,7 +380,7 @@ mod tests {
assert_eq!(t.duration(), Duration::from_secs_f32(10.0));
assert!(!t.finished());
assert!(!t.just_finished());
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
assert!(!t.repeating());
assert_eq!(t.percent(), 0.025);
assert_eq!(t.percent_left(), 0.975);
@ -387,7 +391,7 @@ mod tests {
assert_eq!(t.duration(), Duration::from_secs_f32(10.0));
assert!(!t.finished());
assert!(!t.just_finished());
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
assert!(!t.repeating());
assert_eq!(t.percent(), 0.025);
assert_eq!(t.percent_left(), 0.975);
@ -397,7 +401,7 @@ mod tests {
assert_eq!(t.elapsed_secs(), 10.0);
assert!(t.finished());
assert!(t.just_finished());
assert_eq!(t.times_finished(), 1);
assert_eq!(t.times_finished_this_tick(), 1);
assert_eq!(t.percent(), 1.0);
assert_eq!(t.percent_left(), 0.0);
// Continuing to tick when finished should only change just_finished
@ -405,7 +409,7 @@ mod tests {
assert_eq!(t.elapsed_secs(), 10.0);
assert!(t.finished());
assert!(!t.just_finished());
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
assert_eq!(t.percent(), 1.0);
assert_eq!(t.percent_left(), 0.0);
}
@ -419,7 +423,7 @@ mod tests {
assert_eq!(t.duration(), Duration::from_secs_f32(2.0));
assert!(!t.finished());
assert!(!t.just_finished());
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
assert!(t.repeating());
assert_eq!(t.percent(), 0.375);
assert_eq!(t.percent_left(), 0.625);
@ -428,7 +432,7 @@ mod tests {
assert_eq!(t.elapsed_secs(), 0.25);
assert!(t.finished());
assert!(t.just_finished());
assert_eq!(t.times_finished(), 1);
assert_eq!(t.times_finished_this_tick(), 1);
assert_eq!(t.percent(), 0.125);
assert_eq!(t.percent_left(), 0.875);
// Continuing to tick should turn off both finished & just_finished for repeating timers
@ -436,7 +440,7 @@ mod tests {
assert_eq!(t.elapsed_secs(), 1.25);
assert!(!t.finished());
assert!(!t.just_finished());
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
assert_eq!(t.percent(), 0.625);
assert_eq!(t.percent_left(), 0.375);
}
@ -444,42 +448,70 @@ mod tests {
#[test]
fn times_finished_repeating() {
let mut t = Timer::from_seconds(1.0, true);
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
t.tick(Duration::from_secs_f32(3.5));
assert_eq!(t.times_finished(), 3);
assert_eq!(t.times_finished_this_tick(), 3);
assert_eq!(t.elapsed_secs(), 0.5);
assert!(t.finished());
assert!(t.just_finished());
t.tick(Duration::from_secs_f32(0.2));
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
}
#[test]
fn times_finished() {
fn times_finished_this_tick() {
let mut t = Timer::from_seconds(1.0, false);
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
t.tick(Duration::from_secs_f32(1.5));
assert_eq!(t.times_finished(), 1);
assert_eq!(t.times_finished_this_tick(), 1);
t.tick(Duration::from_secs_f32(0.5));
assert_eq!(t.times_finished(), 0);
assert_eq!(t.times_finished_this_tick(), 0);
}
#[test]
fn times_finished_precise() {
fn times_finished_this_tick_precise() {
let mut t = Timer::from_seconds(0.01, true);
let duration = Duration::from_secs_f64(0.333);
// total duration: 0.333 => 33 times finished
t.tick(duration);
assert_eq!(t.times_finished(), 33);
assert_eq!(t.times_finished_this_tick(), 33);
// total duration: 0.666 => 33 times finished
t.tick(duration);
assert_eq!(t.times_finished(), 33);
assert_eq!(t.times_finished_this_tick(), 33);
// total duration: 0.999 => 33 times finished
t.tick(duration);
assert_eq!(t.times_finished(), 33);
assert_eq!(t.times_finished_this_tick(), 33);
// total duration: 1.332 => 34 times finished
t.tick(duration);
assert_eq!(t.times_finished(), 34);
assert_eq!(t.times_finished_this_tick(), 34);
}
#[test]
fn paused() {
let mut t = Timer::from_seconds(10.0, false);
t.tick(Duration::from_secs_f32(10.0));
assert!(t.just_finished());
assert!(t.finished());
// A paused timer should change just_finished to false after a tick
t.pause();
t.tick(Duration::from_secs_f32(5.0));
assert!(!t.just_finished());
assert!(t.finished());
}
#[test]
fn paused_repeating() {
let mut t = Timer::from_seconds(10.0, true);
t.tick(Duration::from_secs_f32(10.0));
assert!(t.just_finished());
assert!(t.finished());
// A paused repeating timer should change finished and just_finished to false after a tick
t.pause();
t.tick(Duration::from_secs_f32(5.0));
assert!(!t.just_finished());
assert!(!t.finished());
}
}