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