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}