use bevy_ecs::system::ResMut;
use bevy_utils::{Duration, Instant};
#[derive(Debug)]
pub struct Time {
delta: Duration,
last_update: Option<Instant>,
delta_seconds_f64: f64,
delta_seconds: f32,
seconds_since_startup: f64,
startup: Instant,
}
impl Default for Time {
fn default() -> Time {
Time {
delta: Duration::from_secs(0),
last_update: None,
startup: Instant::now(),
delta_seconds_f64: 0.0,
seconds_since_startup: 0.0,
delta_seconds: 0.0,
}
}
}
impl Time {
pub fn update(&mut self) {
let now = Instant::now();
self.update_with_instant(now);
}
pub(crate) fn update_with_instant(&mut self, instant: Instant) {
if let Some(last_update) = self.last_update {
self.delta = instant - last_update;
self.delta_seconds_f64 = self.delta.as_secs_f64();
self.delta_seconds = self.delta.as_secs_f32();
}
let duration_since_startup = instant - self.startup;
self.seconds_since_startup = duration_since_startup.as_secs_f64();
self.last_update = Some(instant);
}
#[inline]
pub fn delta(&self) -> Duration {
self.delta
}
#[inline]
pub fn delta_seconds(&self) -> f32 {
self.delta_seconds
}
#[inline]
pub fn delta_seconds_f64(&self) -> f64 {
self.delta_seconds_f64
}
#[inline]
pub fn seconds_since_startup(&self) -> f64 {
self.seconds_since_startup
}
#[inline]
pub fn startup(&self) -> Instant {
self.startup
}
#[inline]
pub fn last_update(&self) -> Option<Instant> {
self.last_update
}
pub fn time_since_startup(&self) -> Duration {
Instant::now() - self.startup
}
}
pub(crate) fn time_system(mut time: ResMut<Time>) {
time.update();
}
#[cfg(test)]
#[allow(clippy::float_cmp)]
mod tests {
use super::Time;
use bevy_utils::{Duration, Instant};
#[test]
fn update_test() {
let start_instant = Instant::now();
let mut time = Time {
startup: start_instant,
..Default::default()
};
assert_eq!(time.delta(), Duration::from_secs(0));
assert_eq!(time.last_update(), None);
assert_eq!(time.startup(), start_instant);
assert_eq!(time.delta_seconds_f64(), 0.0);
assert_eq!(time.seconds_since_startup(), 0.0);
assert_eq!(time.delta_seconds(), 0.0);
let first_update_instant = Instant::now();
time.update_with_instant(first_update_instant);
assert_eq!(time.delta(), Duration::from_secs(0));
assert_eq!(time.last_update(), Some(first_update_instant));
assert_eq!(time.startup(), start_instant);
assert_eq!(time.delta_seconds_f64(), 0.0);
assert_eq!(
time.seconds_since_startup(),
(first_update_instant - start_instant).as_secs_f64()
);
assert_eq!(time.delta_seconds, 0.0);
let second_update_instant = Instant::now();
time.update_with_instant(second_update_instant);
assert_eq!(time.delta(), second_update_instant - first_update_instant);
assert_eq!(time.last_update(), Some(second_update_instant));
assert_eq!(time.startup(), start_instant);
assert_eq!(time.delta_seconds_f64(), time.delta().as_secs_f64());
assert_eq!(
time.seconds_since_startup(),
(second_update_instant - start_instant).as_secs_f64()
);
assert_eq!(time.delta_seconds(), time.delta().as_secs_f32());
}
}