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