bevy_time/stopwatch.rs
1#[cfg(feature = "bevy_reflect")]
2use bevy_reflect::{prelude::*, Reflect};
3use core::time::Duration;
4
5/// A Stopwatch is a struct that tracks elapsed time when started.
6///
7/// Note that in order to advance the stopwatch [`tick`](Stopwatch::tick) **MUST** be called.
8/// # Examples
9///
10/// ```
11/// # use bevy_time::*;
12/// use std::time::Duration;
13/// let mut stopwatch = Stopwatch::new();
14/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
15///
16/// stopwatch.tick(Duration::from_secs_f32(1.0)); // tick one second
17/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
18///
19/// stopwatch.pause();
20/// stopwatch.tick(Duration::from_secs_f32(1.0)); // paused stopwatches don't tick
21/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
22///
23/// stopwatch.reset(); // reset the stopwatch
24/// assert!(stopwatch.is_paused());
25/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
26/// ```
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 Stopwatch {
35 elapsed: Duration,
36 is_paused: bool,
37}
38
39impl Stopwatch {
40 /// Create a new unpaused `Stopwatch` with no elapsed time.
41 ///
42 /// # Examples
43 /// ```
44 /// # use bevy_time::*;
45 /// let stopwatch = Stopwatch::new();
46 /// assert_eq!(stopwatch.elapsed_secs(), 0.0);
47 /// assert_eq!(stopwatch.is_paused(), false);
48 /// ```
49 pub fn new() -> Self {
50 Default::default()
51 }
52
53 /// Returns the elapsed time since the last [`reset`](Stopwatch::reset)
54 /// of the stopwatch.
55 ///
56 /// # Examples
57 /// ```
58 /// # use bevy_time::*;
59 /// use std::time::Duration;
60 /// let mut stopwatch = Stopwatch::new();
61 /// stopwatch.tick(Duration::from_secs(1));
62 /// assert_eq!(stopwatch.elapsed(), Duration::from_secs(1));
63 /// ```
64 ///
65 /// # See Also
66 ///
67 /// [`elapsed_secs`](Stopwatch::elapsed_secs) - if an `f32` value is desirable instead.
68 /// [`elapsed_secs_f64`](Stopwatch::elapsed_secs_f64) - if an `f64` is desirable instead.
69 #[inline]
70 pub fn elapsed(&self) -> Duration {
71 self.elapsed
72 }
73
74 /// Returns the elapsed time since the last [`reset`](Stopwatch::reset)
75 /// of the stopwatch, in seconds.
76 ///
77 /// # Examples
78 /// ```
79 /// # use bevy_time::*;
80 /// use std::time::Duration;
81 /// let mut stopwatch = Stopwatch::new();
82 /// stopwatch.tick(Duration::from_secs(1));
83 /// assert_eq!(stopwatch.elapsed_secs(), 1.0);
84 /// ```
85 ///
86 /// # See Also
87 ///
88 /// [`elapsed`](Stopwatch::elapsed) - if a `Duration` is desirable instead.
89 /// [`elapsed_secs_f64`](Stopwatch::elapsed_secs_f64) - if an `f64` is desirable instead.
90 #[inline]
91 pub fn elapsed_secs(&self) -> f32 {
92 self.elapsed().as_secs_f32()
93 }
94
95 /// Returns the elapsed time since the last [`reset`](Stopwatch::reset)
96 /// of the stopwatch, in seconds, as f64.
97 ///
98 /// # See Also
99 ///
100 /// [`elapsed`](Stopwatch::elapsed) - if a `Duration` is desirable instead.
101 /// [`elapsed_secs`](Stopwatch::elapsed_secs) - if an `f32` is desirable instead.
102 #[inline]
103 pub fn elapsed_secs_f64(&self) -> f64 {
104 self.elapsed().as_secs_f64()
105 }
106
107 /// Sets the elapsed time of the stopwatch.
108 ///
109 /// # Examples
110 /// ```
111 /// # use bevy_time::*;
112 /// use std::time::Duration;
113 /// let mut stopwatch = Stopwatch::new();
114 /// stopwatch.set_elapsed(Duration::from_secs_f32(1.0));
115 /// assert_eq!(stopwatch.elapsed_secs(), 1.0);
116 /// ```
117 #[inline]
118 pub fn set_elapsed(&mut self, time: Duration) {
119 self.elapsed = time;
120 }
121
122 /// Advance the stopwatch by `delta` seconds.
123 /// If the stopwatch is paused, ticking will not have any effect
124 /// on elapsed time.
125 ///
126 /// # Examples
127 /// ```
128 /// # use bevy_time::*;
129 /// use std::time::Duration;
130 /// let mut stopwatch = Stopwatch::new();
131 /// stopwatch.tick(Duration::from_secs_f32(1.5));
132 /// assert_eq!(stopwatch.elapsed_secs(), 1.5);
133 /// ```
134 pub fn tick(&mut self, delta: Duration) -> &Self {
135 if !self.is_paused() {
136 self.elapsed = self.elapsed.saturating_add(delta);
137 }
138 self
139 }
140
141 /// Pauses the stopwatch. Any call to [`tick`](Stopwatch::tick) while
142 /// paused will not have any effect on the elapsed time.
143 ///
144 /// # Examples
145 /// ```
146 /// # use bevy_time::*;
147 /// use std::time::Duration;
148 /// let mut stopwatch = Stopwatch::new();
149 /// stopwatch.pause();
150 /// stopwatch.tick(Duration::from_secs_f32(1.5));
151 /// assert!(stopwatch.is_paused());
152 /// assert_eq!(stopwatch.elapsed_secs(), 0.0);
153 /// ```
154 #[inline]
155 pub fn pause(&mut self) {
156 self.is_paused = true;
157 }
158
159 /// Unpauses the stopwatch. Resume the effect of ticking on elapsed time.
160 ///
161 /// # Examples
162 /// ```
163 /// # use bevy_time::*;
164 /// use std::time::Duration;
165 /// let mut stopwatch = Stopwatch::new();
166 /// stopwatch.pause();
167 /// stopwatch.tick(Duration::from_secs_f32(1.0));
168 /// stopwatch.unpause();
169 /// stopwatch.tick(Duration::from_secs_f32(1.0));
170 /// assert!(!stopwatch.is_paused());
171 /// assert_eq!(stopwatch.elapsed_secs(), 1.0);
172 /// ```
173 #[inline]
174 pub fn unpause(&mut self) {
175 self.is_paused = false;
176 }
177
178 /// Returns `true` if the stopwatch is paused.
179 ///
180 /// # Examples
181 /// ```
182 /// # use bevy_time::*;
183 /// let mut stopwatch = Stopwatch::new();
184 /// assert!(!stopwatch.is_paused());
185 /// stopwatch.pause();
186 /// assert!(stopwatch.is_paused());
187 /// stopwatch.unpause();
188 /// assert!(!stopwatch.is_paused());
189 /// ```
190 #[inline]
191 pub fn is_paused(&self) -> bool {
192 self.is_paused
193 }
194
195 /// Resets the stopwatch. The reset doesn't affect the paused state of the stopwatch.
196 ///
197 /// # Examples
198 /// ```
199 /// # use bevy_time::*;
200 /// use std::time::Duration;
201 /// let mut stopwatch = Stopwatch::new();
202 /// stopwatch.tick(Duration::from_secs_f32(1.5));
203 /// stopwatch.reset();
204 /// assert_eq!(stopwatch.elapsed_secs(), 0.0);
205 /// ```
206 #[inline]
207 pub fn reset(&mut self) {
208 self.elapsed = Default::default();
209 }
210}