Skip to main content

bevy_time/
timer.rs

1use crate::Stopwatch;
2#[cfg(feature = "bevy_reflect")]
3use bevy_reflect::prelude::*;
4use core::time::Duration;
5
6/// Tracks elapsed time. Enters the finished state once `duration` is reached.
7///
8/// Note that in order to advance the timer [`tick`](Timer::tick) **MUST** be called.
9///
10/// # Timer modes
11///
12/// There are two timer modes ([`TimerMode`]):
13///
14/// - Non repeating timers will stop tracking and stay in the finished state until reset.
15/// - Repeating timers will only be in the finished state on each tick `duration` is reached or
16///   exceeded, and can still be reset at any given point.
17///
18/// # Pausing timers
19///
20/// You can pause a timer using [`Timer::pause`]. Paused timers will not have elapsed time increased.
21///
22/// # Elapsing multiple times a frame
23///
24/// Repeating timers might elapse multiple times per frame if the time is advanced by more than the timer duration.
25/// You can check how many times a timer elapsed each tick with [`Timer::times_finished_this_tick`].
26/// For non-repeating timers, this will always be 0 or 1.
27#[derive(Clone, Debug, Default, PartialEq, Eq)]
28#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
29#[cfg_attr(
30    feature = "bevy_reflect",
31    derive(Reflect),
32    reflect(Default, Clone, PartialEq)
33)]
34pub struct Timer {
35    stopwatch: Stopwatch,
36    duration: Duration,
37    mode: TimerMode,
38    finished: bool,
39    times_finished_this_tick: u32,
40}
41
42impl Timer {
43    /// Creates a new timer with a given duration.
44    ///
45    /// See also [`Timer::from_seconds`](Timer::from_seconds).
46    pub fn new(duration: Duration, mode: TimerMode) -> Self {
47        Self {
48            duration,
49            mode,
50            ..Default::default()
51        }
52    }
53
54    /// Creates a new timer with a given duration in seconds.
55    ///
56    /// # Example
57    /// ```
58    /// # use bevy_time::*;
59    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
60    /// ```
61    pub fn from_seconds(duration: f32, mode: TimerMode) -> Self {
62        Self {
63            duration: Duration::from_secs_f32(duration),
64            mode,
65            ..Default::default()
66        }
67    }
68
69    /// Returns `true` if the timer has reached its duration.
70    ///
71    /// For repeating timers, this method behaves identically to [`Timer::just_finished`].
72    ///
73    /// # Examples
74    /// ```
75    /// # use bevy_time::*;
76    /// use std::time::Duration;
77    ///
78    /// let mut timer_once = Timer::from_seconds(1.0, TimerMode::Once);
79    /// timer_once.tick(Duration::from_secs_f32(1.5));
80    /// assert!(timer_once.is_finished());
81    /// timer_once.tick(Duration::from_secs_f32(0.5));
82    /// assert!(timer_once.is_finished());
83    ///
84    /// let mut timer_repeating = Timer::from_seconds(1.0, TimerMode::Repeating);
85    /// timer_repeating.tick(Duration::from_secs_f32(1.1));
86    /// assert!(timer_repeating.is_finished());
87    /// timer_repeating.tick(Duration::from_secs_f32(0.8));
88    /// assert!(!timer_repeating.is_finished());
89    /// timer_repeating.tick(Duration::from_secs_f32(0.6));
90    /// assert!(timer_repeating.is_finished());
91    /// ```
92    #[inline]
93    pub fn is_finished(&self) -> bool {
94        self.finished
95    }
96
97    /// Returns `true` only on the tick the timer reached its duration.
98    ///
99    /// # Examples
100    /// ```
101    /// # use bevy_time::*;
102    /// use std::time::Duration;
103    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
104    /// timer.tick(Duration::from_secs_f32(1.5));
105    /// assert!(timer.just_finished());
106    /// timer.tick(Duration::from_secs_f32(0.5));
107    /// assert!(!timer.just_finished());
108    /// ```
109    #[inline]
110    pub fn just_finished(&self) -> bool {
111        self.times_finished_this_tick > 0
112    }
113
114    /// Returns the time elapsed on the timer. Guaranteed to be between 0.0 and `duration`.
115    /// Will only equal `duration` when the timer is finished and non repeating.
116    ///
117    /// See also [`Stopwatch::elapsed`](Stopwatch::elapsed).
118    ///
119    /// # Examples
120    /// ```
121    /// # use bevy_time::*;
122    /// use std::time::Duration;
123    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
124    /// timer.tick(Duration::from_secs_f32(0.5));
125    /// assert_eq!(timer.elapsed(), Duration::from_secs_f32(0.5));
126    /// ```
127    #[inline]
128    pub fn elapsed(&self) -> Duration {
129        self.stopwatch.elapsed()
130    }
131
132    /// Returns the time elapsed on the timer as an `f32`.
133    /// See also [`Timer::elapsed`](Timer::elapsed).
134    #[inline]
135    pub fn elapsed_secs(&self) -> f32 {
136        self.stopwatch.elapsed_secs()
137    }
138
139    /// Returns the time elapsed on the timer as an `f64`.
140    /// See also [`Timer::elapsed`](Timer::elapsed).
141    #[inline]
142    pub fn elapsed_secs_f64(&self) -> f64 {
143        self.stopwatch.elapsed_secs_f64()
144    }
145
146    /// Sets the elapsed time of the timer without any other considerations.
147    ///
148    /// See also [`Stopwatch::set`](Stopwatch::set).
149    ///
150    /// #
151    /// ```
152    /// # use bevy_time::*;
153    /// use std::time::Duration;
154    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
155    /// timer.set_elapsed(Duration::from_secs(2));
156    /// assert_eq!(timer.elapsed(), Duration::from_secs(2));
157    /// // the timer is not finished even if the elapsed time is greater than the duration.
158    /// assert!(!timer.is_finished());
159    /// ```
160    #[inline]
161    pub fn set_elapsed(&mut self, time: Duration) {
162        self.stopwatch.set_elapsed(time);
163    }
164
165    /// Returns the duration of the timer.
166    ///
167    /// # Examples
168    /// ```
169    /// # use bevy_time::*;
170    /// use std::time::Duration;
171    /// let timer = Timer::new(Duration::from_secs(1), TimerMode::Once);
172    /// assert_eq!(timer.duration(), Duration::from_secs(1));
173    /// ```
174    #[inline]
175    pub fn duration(&self) -> Duration {
176        self.duration
177    }
178
179    /// Sets the duration of the timer.
180    ///
181    /// # Examples
182    /// ```
183    /// # use bevy_time::*;
184    /// use std::time::Duration;
185    /// let mut timer = Timer::from_seconds(1.5, TimerMode::Once);
186    /// timer.set_duration(Duration::from_secs(1));
187    /// assert_eq!(timer.duration(), Duration::from_secs(1));
188    /// ```
189    #[inline]
190    pub fn set_duration(&mut self, duration: Duration) {
191        self.duration = duration;
192    }
193
194    /// Finishes the timer.
195    ///
196    /// # Examples
197    /// ```
198    /// # use bevy_time::*;
199    /// let mut timer = Timer::from_seconds(1.5, TimerMode::Once);
200    /// timer.finish();
201    /// assert!(timer.is_finished());
202    /// ```
203    #[inline]
204    pub fn finish(&mut self) {
205        let remaining = self.remaining();
206        self.tick(remaining);
207    }
208
209    /// Almost finishes the timer leaving 1 ns of remaining time.
210    /// This can be useful when needing an immediate action without having
211    /// to wait for the set duration of the timer in the first tick.
212    ///
213    /// If the timer is already finished, this does nothing.
214    ///
215    /// # Examples
216    /// ```
217    /// # use bevy_time::*;
218    /// use std::time::Duration;
219    /// let mut timer = Timer::from_seconds(1.5, TimerMode::Once);
220    /// timer.almost_finish();
221    /// assert!(!timer.is_finished());
222    /// assert_eq!(timer.remaining(), Duration::from_nanos(1));
223    /// ```
224    #[inline]
225    pub fn almost_finish(&mut self) {
226        let remaining = self.remaining().saturating_sub(Duration::from_nanos(1));
227        self.tick(remaining);
228    }
229
230    /// Returns the mode of the timer.
231    ///
232    /// # Examples
233    /// ```
234    /// # use bevy_time::*;
235    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Repeating);
236    /// assert_eq!(timer.mode(), TimerMode::Repeating);
237    /// ```
238    #[inline]
239    pub fn mode(&self) -> TimerMode {
240        self.mode
241    }
242
243    /// Sets the mode of the timer.
244    ///
245    /// # Examples
246    /// ```
247    /// # use bevy_time::*;
248    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Repeating);
249    /// timer.set_mode(TimerMode::Once);
250    /// assert_eq!(timer.mode(), TimerMode::Once);
251    /// ```
252    #[doc(alias = "repeating")]
253    #[inline]
254    pub fn set_mode(&mut self, mode: TimerMode) {
255        if self.mode != TimerMode::Repeating && mode == TimerMode::Repeating && self.finished {
256            self.stopwatch.reset();
257            self.finished = self.just_finished();
258        }
259        self.mode = mode;
260    }
261
262    /// Advance the timer by `delta` seconds.
263    /// Non repeating timer will clamp at duration.
264    /// Repeating timer will wrap around.
265    /// Will not affect paused timers.
266    ///
267    /// See also [`Stopwatch::tick`](Stopwatch::tick).
268    ///
269    /// # Examples
270    /// ```
271    /// # use bevy_time::*;
272    /// use std::time::Duration;
273    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
274    /// let mut repeating = Timer::from_seconds(1.0, TimerMode::Repeating);
275    /// timer.tick(Duration::from_secs_f32(1.5));
276    /// repeating.tick(Duration::from_secs_f32(1.5));
277    /// assert_eq!(timer.elapsed_secs(), 1.0);
278    /// assert_eq!(repeating.elapsed_secs(), 0.5);
279    /// ```
280    pub fn tick(&mut self, delta: Duration) -> &Self {
281        if self.is_paused() {
282            self.times_finished_this_tick = 0;
283            if self.mode == TimerMode::Repeating {
284                self.finished = false;
285            }
286            return self;
287        }
288
289        if self.mode != TimerMode::Repeating && self.is_finished() {
290            self.times_finished_this_tick = 0;
291            return self;
292        }
293
294        self.stopwatch.tick(delta);
295        self.finished = self.elapsed() >= self.duration();
296
297        if self.is_finished() {
298            if self.mode == TimerMode::Repeating {
299                self.times_finished_this_tick = self
300                    .elapsed()
301                    .as_nanos()
302                    .checked_div(self.duration().as_nanos())
303                    .map_or(u32::MAX, |x| x as u32);
304                self.set_elapsed(
305                    self.elapsed()
306                        .as_nanos()
307                        .checked_rem(self.duration().as_nanos())
308                        .map_or(Duration::ZERO, |x| Duration::from_nanos(x as u64)),
309                );
310            } else {
311                self.times_finished_this_tick = 1;
312                self.set_elapsed(self.duration());
313            }
314        } else {
315            self.times_finished_this_tick = 0;
316        }
317
318        self
319    }
320
321    /// Pauses the Timer. Disables the ticking of the timer.
322    ///
323    /// See also [`Stopwatch::pause`](Stopwatch::pause).
324    ///
325    /// # Examples
326    /// ```
327    /// # use bevy_time::*;
328    /// use std::time::Duration;
329    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
330    /// timer.pause();
331    /// timer.tick(Duration::from_secs_f32(0.5));
332    /// assert_eq!(timer.elapsed_secs(), 0.0);
333    /// ```
334    #[inline]
335    pub fn pause(&mut self) {
336        self.stopwatch.pause();
337    }
338
339    /// Unpauses the Timer. Resumes the ticking of the timer.
340    ///
341    /// See also [`Stopwatch::unpause()`](Stopwatch::unpause).
342    ///
343    /// # Examples
344    /// ```
345    /// # use bevy_time::*;
346    /// use std::time::Duration;
347    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
348    /// timer.pause();
349    /// timer.tick(Duration::from_secs_f32(0.5));
350    /// timer.unpause();
351    /// timer.tick(Duration::from_secs_f32(0.5));
352    /// assert_eq!(timer.elapsed_secs(), 0.5);
353    /// ```
354    #[inline]
355    pub fn unpause(&mut self) {
356        self.stopwatch.unpause();
357    }
358
359    /// Returns `true` if the timer is paused.
360    ///
361    /// See also [`Stopwatch::is_paused`](Stopwatch::is_paused).
362    ///
363    /// # Examples
364    /// ```
365    /// # use bevy_time::*;
366    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
367    /// assert!(!timer.is_paused());
368    /// timer.pause();
369    /// assert!(timer.is_paused());
370    /// timer.unpause();
371    /// assert!(!timer.is_paused());
372    /// ```
373    #[inline]
374    pub fn is_paused(&self) -> bool {
375        self.stopwatch.is_paused()
376    }
377
378    /// Resets the timer. The reset doesn't affect the `paused` state of the timer.
379    ///
380    /// See also [`Stopwatch::reset`](Stopwatch::reset).
381    ///
382    /// Examples
383    /// ```
384    /// # use bevy_time::*;
385    /// use std::time::Duration;
386    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
387    /// timer.tick(Duration::from_secs_f32(1.5));
388    /// timer.reset();
389    /// assert!(!timer.is_finished());
390    /// assert!(!timer.just_finished());
391    /// assert_eq!(timer.elapsed_secs(), 0.0);
392    /// ```
393    pub fn reset(&mut self) {
394        self.stopwatch.reset();
395        self.finished = false;
396        self.times_finished_this_tick = 0;
397    }
398
399    /// Returns the fraction of the timer elapsed time (goes from 0.0 to 1.0).
400    ///
401    /// # Examples
402    /// ```
403    /// # use bevy_time::*;
404    /// use std::time::Duration;
405    /// let mut timer = Timer::from_seconds(2.0, TimerMode::Once);
406    /// timer.tick(Duration::from_secs_f32(0.5));
407    /// assert_eq!(timer.fraction(), 0.25);
408    /// ```
409    #[inline]
410    pub fn fraction(&self) -> f32 {
411        if self.duration == Duration::ZERO {
412            1.0
413        } else {
414            self.elapsed().as_secs_f32() / self.duration().as_secs_f32()
415        }
416    }
417
418    /// Returns the fraction of the timer remaining time (goes from 1.0 to 0.0).
419    ///
420    /// # Examples
421    /// ```
422    /// # use bevy_time::*;
423    /// use std::time::Duration;
424    /// let mut timer = Timer::from_seconds(2.0, TimerMode::Once);
425    /// timer.tick(Duration::from_secs_f32(0.5));
426    /// assert_eq!(timer.fraction_remaining(), 0.75);
427    /// ```
428    #[inline]
429    pub fn fraction_remaining(&self) -> f32 {
430        1.0 - self.fraction()
431    }
432
433    /// Returns the remaining time in seconds
434    ///
435    /// # Examples
436    /// ```
437    /// # use bevy_time::*;
438    /// use std::cmp::Ordering;
439    /// use std::time::Duration;
440    /// let mut timer = Timer::from_seconds(2.0, TimerMode::Once);
441    /// timer.tick(Duration::from_secs_f32(0.5));
442    /// let result = timer.remaining_secs().total_cmp(&1.5);
443    /// assert_eq!(Ordering::Equal, result);
444    /// ```
445    #[inline]
446    pub fn remaining_secs(&self) -> f32 {
447        self.remaining().as_secs_f32()
448    }
449
450    /// Returns the remaining time using Duration
451    ///
452    /// # Examples
453    /// ```
454    /// # use bevy_time::*;
455    /// use std::time::Duration;
456    /// let mut timer = Timer::from_seconds(2.0, TimerMode::Once);
457    /// timer.tick(Duration::from_secs_f32(0.5));
458    /// assert_eq!(timer.remaining(), Duration::from_secs_f32(1.5));
459    /// ```
460    #[inline]
461    pub fn remaining(&self) -> Duration {
462        self.duration() - self.elapsed()
463    }
464
465    /// Returns the number of times a repeating timer
466    /// finished during the last [`tick`](Timer<T>::tick) call.
467    ///
468    /// For non repeating-timers, this method will only ever
469    /// return 0 or 1.
470    ///
471    /// # Examples
472    /// ```
473    /// # use bevy_time::*;
474    /// use std::time::Duration;
475    /// let mut timer = Timer::from_seconds(1.0, TimerMode::Repeating);
476    /// timer.tick(Duration::from_secs_f32(6.0));
477    /// assert_eq!(timer.times_finished_this_tick(), 6);
478    /// timer.tick(Duration::from_secs_f32(2.0));
479    /// assert_eq!(timer.times_finished_this_tick(), 2);
480    /// timer.tick(Duration::from_secs_f32(0.5));
481    /// assert_eq!(timer.times_finished_this_tick(), 0);
482    /// ```
483    #[inline]
484    pub fn times_finished_this_tick(&self) -> u32 {
485        self.times_finished_this_tick
486    }
487}
488
489/// Specifies [`Timer`] behavior.
490#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default)]
491#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
492#[cfg_attr(
493    feature = "bevy_reflect",
494    derive(Reflect),
495    reflect(Default, Clone, PartialEq, Hash)
496)]
497pub enum TimerMode {
498    /// Run once and stop.
499    #[default]
500    Once,
501    /// Reset when finished.
502    Repeating,
503}
504
505#[cfg(test)]
506mod tests {
507    use super::*;
508
509    #[test]
510    fn non_repeating_timer() {
511        let mut t = Timer::from_seconds(10.0, TimerMode::Once);
512        // Tick once, check all attributes
513        t.tick(Duration::from_secs_f32(0.25));
514        assert_eq!(t.elapsed_secs(), 0.25);
515        assert_eq!(t.elapsed_secs_f64(), 0.25);
516        assert_eq!(t.duration(), Duration::from_secs_f32(10.0));
517        assert!(!t.is_finished());
518        assert!(!t.just_finished());
519        assert_eq!(t.times_finished_this_tick(), 0);
520        assert_eq!(t.mode(), TimerMode::Once);
521        assert_eq!(t.fraction(), 0.025);
522        assert_eq!(t.fraction_remaining(), 0.975);
523        // Ticking while paused changes nothing
524        t.pause();
525        t.tick(Duration::from_secs_f32(500.0));
526        assert_eq!(t.elapsed_secs(), 0.25);
527        assert_eq!(t.duration(), Duration::from_secs_f32(10.0));
528        assert!(!t.is_finished());
529        assert!(!t.just_finished());
530        assert_eq!(t.times_finished_this_tick(), 0);
531        assert_eq!(t.mode(), TimerMode::Once);
532        assert_eq!(t.fraction(), 0.025);
533        assert_eq!(t.fraction_remaining(), 0.975);
534        // Tick past the end and make sure elapsed doesn't go past 0.0 and other things update
535        t.unpause();
536        t.tick(Duration::from_secs_f32(500.0));
537        assert_eq!(t.elapsed_secs(), 10.0);
538        assert_eq!(t.elapsed_secs_f64(), 10.0);
539        assert!(t.is_finished());
540        assert!(t.just_finished());
541        assert_eq!(t.times_finished_this_tick(), 1);
542        assert_eq!(t.fraction(), 1.0);
543        assert_eq!(t.fraction_remaining(), 0.0);
544        // Continuing to tick when finished should only change just_finished
545        t.tick(Duration::from_secs_f32(1.0));
546        assert_eq!(t.elapsed_secs(), 10.0);
547        assert_eq!(t.elapsed_secs_f64(), 10.0);
548        assert!(t.is_finished());
549        assert!(!t.just_finished());
550        assert_eq!(t.times_finished_this_tick(), 0);
551        assert_eq!(t.fraction(), 1.0);
552        assert_eq!(t.fraction_remaining(), 0.0);
553    }
554
555    #[test]
556    fn repeating_timer() {
557        let mut t = Timer::from_seconds(2.0, TimerMode::Repeating);
558        // Tick once, check all attributes
559        t.tick(Duration::from_secs_f32(0.75));
560        assert_eq!(t.elapsed_secs(), 0.75);
561        assert_eq!(t.elapsed_secs_f64(), 0.75);
562        assert_eq!(t.duration(), Duration::from_secs_f32(2.0));
563        assert!(!t.is_finished());
564        assert!(!t.just_finished());
565        assert_eq!(t.times_finished_this_tick(), 0);
566        assert_eq!(t.mode(), TimerMode::Repeating);
567        assert_eq!(t.fraction(), 0.375);
568        assert_eq!(t.fraction_remaining(), 0.625);
569        // Tick past the end and make sure elapsed wraps
570        t.tick(Duration::from_secs_f32(1.5));
571        assert_eq!(t.elapsed_secs(), 0.25);
572        assert_eq!(t.elapsed_secs_f64(), 0.25);
573        assert!(t.is_finished());
574        assert!(t.just_finished());
575        assert_eq!(t.times_finished_this_tick(), 1);
576        assert_eq!(t.fraction(), 0.125);
577        assert_eq!(t.fraction_remaining(), 0.875);
578        // Continuing to tick should turn off both finished & just_finished for repeating timers
579        t.tick(Duration::from_secs_f32(1.0));
580        assert_eq!(t.elapsed_secs(), 1.25);
581        assert_eq!(t.elapsed_secs_f64(), 1.25);
582        assert!(!t.is_finished());
583        assert!(!t.just_finished());
584        assert_eq!(t.times_finished_this_tick(), 0);
585        assert_eq!(t.fraction(), 0.625);
586        assert_eq!(t.fraction_remaining(), 0.375);
587    }
588
589    #[test]
590    fn times_finished_repeating() {
591        let mut t = Timer::from_seconds(1.0, TimerMode::Repeating);
592        assert_eq!(t.times_finished_this_tick(), 0);
593        t.tick(Duration::from_secs_f32(3.5));
594        assert_eq!(t.times_finished_this_tick(), 3);
595        assert_eq!(t.elapsed_secs(), 0.5);
596        assert_eq!(t.elapsed_secs_f64(), 0.5);
597        assert!(t.is_finished());
598        assert!(t.just_finished());
599        t.tick(Duration::from_secs_f32(0.2));
600        assert_eq!(t.times_finished_this_tick(), 0);
601    }
602
603    #[test]
604    fn times_finished_this_tick() {
605        let mut t = Timer::from_seconds(1.0, TimerMode::Once);
606        assert_eq!(t.times_finished_this_tick(), 0);
607        t.tick(Duration::from_secs_f32(1.5));
608        assert_eq!(t.times_finished_this_tick(), 1);
609        t.tick(Duration::from_secs_f32(0.5));
610        assert_eq!(t.times_finished_this_tick(), 0);
611    }
612
613    #[test]
614    fn times_finished_this_tick_repeating_zero_duration() {
615        let mut t = Timer::from_seconds(0.0, TimerMode::Repeating);
616        assert_eq!(t.times_finished_this_tick(), 0);
617        assert_eq!(t.elapsed(), Duration::ZERO);
618        assert_eq!(t.fraction(), 1.0);
619        t.tick(Duration::from_secs(1));
620        assert_eq!(t.times_finished_this_tick(), u32::MAX);
621        assert_eq!(t.elapsed(), Duration::ZERO);
622        assert_eq!(t.fraction(), 1.0);
623        t.tick(Duration::from_secs(2));
624        assert_eq!(t.times_finished_this_tick(), u32::MAX);
625        assert_eq!(t.elapsed(), Duration::ZERO);
626        assert_eq!(t.fraction(), 1.0);
627        t.reset();
628        assert_eq!(t.times_finished_this_tick(), 0);
629        assert_eq!(t.elapsed(), Duration::ZERO);
630        assert_eq!(t.fraction(), 1.0);
631    }
632
633    #[test]
634    fn times_finished_this_tick_precise() {
635        let mut t = Timer::from_seconds(0.01, TimerMode::Repeating);
636        let duration = Duration::from_secs_f64(0.333);
637
638        // total duration: 0.333 => 33 times finished
639        t.tick(duration);
640        assert_eq!(t.times_finished_this_tick(), 33);
641        // total duration: 0.666 => 33 times finished
642        t.tick(duration);
643        assert_eq!(t.times_finished_this_tick(), 33);
644        // total duration: 0.999 => 33 times finished
645        t.tick(duration);
646        assert_eq!(t.times_finished_this_tick(), 33);
647        // total duration: 1.332 => 34 times finished
648        t.tick(duration);
649        assert_eq!(t.times_finished_this_tick(), 34);
650    }
651
652    #[test]
653    fn almost_finished_repeating() {
654        let mut t = Timer::from_seconds(10.0, TimerMode::Repeating);
655        let duration = Duration::from_nanos(1);
656
657        t.almost_finish();
658        assert!(!t.is_finished());
659        assert_eq!(t.times_finished_this_tick(), 0);
660        assert_eq!(t.remaining(), Duration::from_nanos(1));
661
662        t.tick(duration);
663        assert!(t.is_finished());
664        assert_eq!(t.times_finished_this_tick(), 1);
665    }
666
667    #[test]
668    fn paused() {
669        let mut t = Timer::from_seconds(10.0, TimerMode::Once);
670
671        t.tick(Duration::from_secs_f32(10.0));
672        assert!(t.just_finished());
673        assert!(t.is_finished());
674        // A paused timer should change just_finished to false after a tick
675        t.pause();
676        t.tick(Duration::from_secs_f32(5.0));
677        assert!(!t.just_finished());
678        assert!(t.is_finished());
679    }
680
681    #[test]
682    fn paused_repeating() {
683        let mut t = Timer::from_seconds(10.0, TimerMode::Repeating);
684
685        t.tick(Duration::from_secs_f32(10.0));
686        assert!(t.just_finished());
687        assert!(t.is_finished());
688        // A paused repeating timer should change finished and just_finished to false after a tick
689        t.pause();
690        t.tick(Duration::from_secs_f32(5.0));
691        assert!(!t.just_finished());
692        assert!(!t.is_finished());
693    }
694}