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}