1#[cfg(feature = "bevy_reflect")]
2use bevy_reflect::Reflect;
3use bevy_utils::{Duration, Instant};
4
5use crate::time::Time;
6
7#[derive(Debug, Copy, Clone)]
43#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
44pub struct Real {
45 startup: Instant,
46 first_update: Option<Instant>,
47 last_update: Option<Instant>,
48}
49
50impl Default for Real {
51 fn default() -> Self {
52 Self {
53 startup: Instant::now(),
54 first_update: None,
55 last_update: None,
56 }
57 }
58}
59
60impl Time<Real> {
61 pub fn new(startup: Instant) -> Self {
64 Self::new_with(Real {
65 startup,
66 ..Default::default()
67 })
68 }
69
70 pub fn update(&mut self) {
76 let instant = Instant::now();
77 self.update_with_instant(instant);
78 }
79
80 pub fn update_with_duration(&mut self, duration: Duration) {
88 let last_update = self.context().last_update.unwrap_or(self.context().startup);
89 self.update_with_instant(last_update + duration);
90 }
91
92 pub fn update_with_instant(&mut self, instant: Instant) {
99 let Some(last_update) = self.context().last_update else {
100 let context = self.context_mut();
101 context.first_update = Some(instant);
102 context.last_update = Some(instant);
103 return;
104 };
105 let delta = instant - last_update;
106 self.advance_by(delta);
107 self.context_mut().last_update = Some(instant);
108 }
109
110 #[inline]
114 pub fn startup(&self) -> Instant {
115 self.context().startup
116 }
117
118 #[inline]
123 pub fn first_update(&self) -> Option<Instant> {
124 self.context().first_update
125 }
126
127 #[inline]
132 pub fn last_update(&self) -> Option<Instant> {
133 self.context().last_update
134 }
135}
136
137#[cfg(test)]
138mod test {
139 use super::*;
140
141 #[test]
142 fn test_update() {
143 let startup = Instant::now();
144 let mut time = Time::<Real>::new(startup);
145
146 assert_eq!(time.startup(), startup);
147 assert_eq!(time.first_update(), None);
148 assert_eq!(time.last_update(), None);
149 assert_eq!(time.delta(), Duration::ZERO);
150 assert_eq!(time.elapsed(), Duration::ZERO);
151
152 time.update();
153
154 assert_ne!(time.first_update(), None);
155 assert_ne!(time.last_update(), None);
156 assert_eq!(time.delta(), Duration::ZERO);
157 assert_eq!(time.elapsed(), Duration::ZERO);
158
159 time.update();
160
161 assert_ne!(time.first_update(), None);
162 assert_ne!(time.last_update(), None);
163 assert_ne!(time.last_update(), time.first_update());
164 assert_ne!(time.delta(), Duration::ZERO);
165 assert_eq!(time.elapsed(), time.delta());
166
167 let prev_elapsed = time.elapsed();
168 time.update();
169
170 assert_ne!(time.delta(), Duration::ZERO);
171 assert_eq!(time.elapsed(), prev_elapsed + time.delta());
172 }
173
174 #[test]
175 fn test_update_with_instant() {
176 let startup = Instant::now();
177 let mut time = Time::<Real>::new(startup);
178
179 let first_update = Instant::now();
180 time.update_with_instant(first_update);
181
182 assert_eq!(time.startup(), startup);
183 assert_eq!(time.first_update(), Some(first_update));
184 assert_eq!(time.last_update(), Some(first_update));
185 assert_eq!(time.delta(), Duration::ZERO);
186 assert_eq!(time.elapsed(), Duration::ZERO);
187
188 let second_update = Instant::now();
189 time.update_with_instant(second_update);
190
191 assert_eq!(time.first_update(), Some(first_update));
192 assert_eq!(time.last_update(), Some(second_update));
193 assert_eq!(time.delta(), second_update - first_update);
194 assert_eq!(time.elapsed(), second_update - first_update);
195
196 let third_update = Instant::now();
197 time.update_with_instant(third_update);
198
199 assert_eq!(time.first_update(), Some(first_update));
200 assert_eq!(time.last_update(), Some(third_update));
201 assert_eq!(time.delta(), third_update - second_update);
202 assert_eq!(time.elapsed(), third_update - first_update);
203 }
204
205 #[test]
206 fn test_update_with_duration() {
207 let startup = Instant::now();
208 let mut time = Time::<Real>::new(startup);
209
210 time.update_with_duration(Duration::from_secs(1));
211
212 assert_eq!(time.startup(), startup);
213 assert_eq!(time.first_update(), Some(startup + Duration::from_secs(1)));
214 assert_eq!(time.last_update(), Some(startup + Duration::from_secs(1)));
215 assert_eq!(time.delta(), Duration::ZERO);
216 assert_eq!(time.elapsed(), Duration::ZERO);
217
218 time.update_with_duration(Duration::from_secs(1));
219
220 assert_eq!(time.first_update(), Some(startup + Duration::from_secs(1)));
221 assert_eq!(time.last_update(), Some(startup + Duration::from_secs(2)));
222 assert_eq!(time.delta(), Duration::from_secs(1));
223 assert_eq!(time.elapsed(), Duration::from_secs(1));
224
225 time.update_with_duration(Duration::from_secs(1));
226
227 assert_eq!(time.first_update(), Some(startup + Duration::from_secs(1)));
228 assert_eq!(time.last_update(), Some(startup + Duration::from_secs(3)));
229 assert_eq!(time.delta(), Duration::from_secs(1));
230 assert_eq!(time.elapsed(), Duration::from_secs(2));
231 }
232}