Skip to content

Commit ab407aa

Browse files
kokounetcart
andcommitted
♻️ Timer refactor to duration.✨ Add Stopwatch struct. (#1151)
This pull request is following the discussion on the issue #1127. Additionally, it integrates the change proposed by #1112. The list of change of this pull request: * ✨ Add `Timer::times_finished` method that counts the number of wraps for repeating timers. * ♻️ Refactored `Timer` * 🐛 Fix a bug where 2 successive calls to `Timer::tick` which makes a repeating timer to finish makes `Timer::just_finished` to return `false` where it should return `true`. Minimal failing example: ```rust use bevy::prelude::*; let mut timer: Timer<()> = Timer::from_seconds(1.0, true); timer.tick(1.5); assert!(timer.finished()); assert!(timer.just_finished()); timer.tick(1.5); assert!(timer.finished()); assert!(timer.just_finished()); // <- This fails where it should not ``` * 📚 Add extensive documentation for Timer with doc examples. * ✨ Add a `Stopwatch` struct similar to `Timer` with extensive doc and tests. Even if the type specialization is not retained for bevy, the doc, bugfix and added method are worth salvaging 😅. This is my first PR for bevy, please be kind to me ❤️ . Co-authored-by: Carter Anderson <[email protected]>
1 parent 4686437 commit ab407aa

File tree

11 files changed

+508
-113
lines changed

11 files changed

+508
-113
lines changed

crates/bevy_core/src/time/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
mod fixed_timestep;
2+
mod stopwatch;
23
#[allow(clippy::module_inception)]
34
mod time;
45
mod timer;
56

67
pub use fixed_timestep::*;
8+
pub use stopwatch::*;
79
pub use time::*;
810
pub use timer::*;
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
use bevy_ecs::reflect::ReflectComponent;
2+
use bevy_reflect::Reflect;
3+
use bevy_utils::Duration;
4+
5+
/// A Stopwatch is a struct that track elapsed time when started.
6+
///
7+
/// # Examples
8+
///
9+
/// ```
10+
/// # use bevy_core::*;
11+
/// use std::time::Duration;
12+
/// let mut stopwatch = Stopwatch::new();
13+
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
14+
/// stopwatch.tick(Duration::from_secs_f32(1.0)); // tick one second
15+
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
16+
/// stopwatch.pause();
17+
/// stopwatch.tick(Duration::from_secs_f32(1.0)); // paused stopwatches don't tick
18+
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
19+
/// stopwatch.reset(); // reset the stopwatch
20+
/// assert!(stopwatch.paused());
21+
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
22+
/// ```
23+
#[derive(Clone, Debug, Default, Reflect)]
24+
#[reflect(Component)]
25+
pub struct Stopwatch {
26+
elapsed: Duration,
27+
paused: bool,
28+
}
29+
30+
impl Stopwatch {
31+
/// Create a new unpaused `Stopwatch` with no elapsed time.
32+
///
33+
/// # Examples
34+
/// ```
35+
/// # use bevy_core::*;
36+
/// let stopwatch = Stopwatch::new();
37+
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
38+
/// assert_eq!(stopwatch.paused(), false);
39+
/// ```
40+
pub fn new() -> Self {
41+
Default::default()
42+
}
43+
44+
/// Returns the elapsed time since the last [`reset`](Stopwatch::reset)
45+
/// of the stopwatch.
46+
///
47+
/// # Examples
48+
/// ```
49+
/// # use bevy_core::*;
50+
/// use std::time::Duration;
51+
/// let mut stopwatch = Stopwatch::new();
52+
/// stopwatch.tick(Duration::from_secs(1));
53+
/// assert_eq!(stopwatch.elapsed(), Duration::from_secs(1));
54+
/// ```
55+
#[inline]
56+
pub fn elapsed(&self) -> Duration {
57+
self.elapsed
58+
}
59+
60+
#[inline]
61+
pub fn elapsed_secs(&self) -> f32 {
62+
self.elapsed().as_secs_f32()
63+
}
64+
65+
/// Sets the elapsed time of the stopwatch.
66+
///
67+
/// # Examples
68+
/// ```
69+
/// # use bevy_core::*;
70+
/// use std::time::Duration;
71+
/// let mut stopwatch = Stopwatch::new();
72+
/// stopwatch.set_elapsed(Duration::from_secs_f32(1.0));
73+
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
74+
/// ```
75+
#[inline]
76+
pub fn set_elapsed(&mut self, time: Duration) {
77+
self.elapsed = time;
78+
}
79+
80+
/// Advance the stopwatch by `delta` seconds.
81+
/// If the stopwatch is paused, ticking will not have any effect
82+
/// on elapsed time.
83+
///
84+
/// # Examples
85+
/// ```
86+
/// # use bevy_core::*;
87+
/// use std::time::Duration;
88+
/// let mut stopwatch = Stopwatch::new();
89+
/// stopwatch.tick(Duration::from_secs_f32(1.5));
90+
/// assert_eq!(stopwatch.elapsed_secs(), 1.5);
91+
/// ```
92+
pub fn tick(&mut self, delta: Duration) -> &Self {
93+
if !self.paused() {
94+
self.elapsed += delta;
95+
}
96+
self
97+
}
98+
99+
/// Pauses the stopwatch. Any call to [`tick`](Stopwatch::tick) while
100+
/// paused will not have any effect on the elapsed time.
101+
///
102+
/// # Examples
103+
/// ```
104+
/// # use bevy_core::*;
105+
/// use std::time::Duration;
106+
/// let mut stopwatch = Stopwatch::new();
107+
/// stopwatch.pause();
108+
/// stopwatch.tick(Duration::from_secs_f32(1.5));
109+
/// assert!(stopwatch.paused());
110+
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
111+
/// ```
112+
#[inline]
113+
pub fn pause(&mut self) {
114+
self.paused = true;
115+
}
116+
117+
/// Unpauses the stopwatch. Resume the effect of ticking on elapsed time.
118+
///
119+
/// # Examples
120+
/// ```
121+
/// # use bevy_core::*;
122+
/// use std::time::Duration;
123+
/// let mut stopwatch = Stopwatch::new();
124+
/// stopwatch.pause();
125+
/// stopwatch.tick(Duration::from_secs_f32(1.0));
126+
/// stopwatch.unpause();
127+
/// stopwatch.tick(Duration::from_secs_f32(1.0));
128+
/// assert!(!stopwatch.paused());
129+
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
130+
/// ```
131+
#[inline]
132+
pub fn unpause(&mut self) {
133+
self.paused = false;
134+
}
135+
136+
/// Returns `true` if the stopwatch is paused.
137+
///
138+
/// # Examples
139+
/// ```
140+
/// # use bevy_core::*;
141+
/// let mut stopwatch = Stopwatch::new();
142+
/// assert!(!stopwatch.paused());
143+
/// stopwatch.pause();
144+
/// assert!(stopwatch.paused());
145+
/// stopwatch.unpause();
146+
/// assert!(!stopwatch.paused());
147+
/// ```
148+
#[inline]
149+
pub fn paused(&self) -> bool {
150+
self.paused
151+
}
152+
153+
/// Resets the stopwatch.
154+
///
155+
/// # Examples
156+
/// ```
157+
/// # use bevy_core::*;
158+
/// use std::time::Duration;
159+
/// let mut stopwatch = Stopwatch::new();
160+
/// stopwatch.tick(Duration::from_secs_f32(1.5));
161+
/// stopwatch.reset();
162+
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
163+
/// ```
164+
#[inline]
165+
pub fn reset(&mut self) {
166+
self.elapsed = Default::default();
167+
}
168+
}

0 commit comments

Comments
 (0)