Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_time/src/timer.rs
6598 views
1
use crate::Stopwatch;
2
#[cfg(feature = "bevy_reflect")]
3
use bevy_reflect::prelude::*;
4
use 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
)]
34
pub struct Timer {
35
stopwatch: Stopwatch,
36
duration: Duration,
37
mode: TimerMode,
38
finished: bool,
39
times_finished_this_tick: u32,
40
}
41
42
impl 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
)]
525
pub enum TimerMode {
526
/// Run once and stop.
527
#[default]
528
Once,
529
/// Reset when finished.
530
Repeating,
531
}
532
533
#[cfg(test)]
534
mod 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
}
708
709