bevy_time/
stopwatch.rs

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