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}