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}