Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_time/src/timer.rs
9297 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` 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
)]
495
pub enum TimerMode {
496
/// Run once and stop.
497
#[default]
498
Once,
499
/// Reset when finished.
500
Repeating,
501
}
502
503
#[cfg(test)]
504
mod 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
}
693
694