#[cfg(feature = "bevy_reflect")]1use bevy_reflect::{prelude::*, Reflect};2use core::time::Duration;34/// A Stopwatch is a struct that tracks elapsed time when started.5///6/// Note that in order to advance the stopwatch [`tick`](Stopwatch::tick) **MUST** be called.7/// # Examples8///9/// ```10/// # use bevy_time::*;11/// use std::time::Duration;12/// let mut stopwatch = Stopwatch::new();13/// assert_eq!(stopwatch.elapsed_secs(), 0.0);14///15/// stopwatch.tick(Duration::from_secs_f32(1.0)); // tick one second16/// assert_eq!(stopwatch.elapsed_secs(), 1.0);17///18/// stopwatch.pause();19/// stopwatch.tick(Duration::from_secs_f32(1.0)); // paused stopwatches don't tick20/// assert_eq!(stopwatch.elapsed_secs(), 1.0);21///22/// stopwatch.reset(); // reset the stopwatch23/// assert!(stopwatch.is_paused());24/// assert_eq!(stopwatch.elapsed_secs(), 0.0);25/// ```26#[derive(Clone, Debug, Default, PartialEq, Eq)]27#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]28#[cfg_attr(29feature = "bevy_reflect",30derive(Reflect),31reflect(Default, Clone, PartialEq)32)]33pub struct Stopwatch {34elapsed: Duration,35is_paused: bool,36}3738impl Stopwatch {39/// Create a new unpaused `Stopwatch` with no elapsed time.40///41/// # Examples42/// ```43/// # use bevy_time::*;44/// let stopwatch = Stopwatch::new();45/// assert_eq!(stopwatch.elapsed_secs(), 0.0);46/// assert_eq!(stopwatch.is_paused(), false);47/// ```48pub fn new() -> Self {49Default::default()50}5152/// Returns the elapsed time since the last [`reset`](Stopwatch::reset)53/// of the stopwatch.54///55/// # Examples56/// ```57/// # use bevy_time::*;58/// use std::time::Duration;59/// let mut stopwatch = Stopwatch::new();60/// stopwatch.tick(Duration::from_secs(1));61/// assert_eq!(stopwatch.elapsed(), Duration::from_secs(1));62/// ```63///64/// # See Also65///66/// [`elapsed_secs`](Stopwatch::elapsed_secs) - if an `f32` value is desirable instead.67/// [`elapsed_secs_f64`](Stopwatch::elapsed_secs_f64) - if an `f64` is desirable instead.68#[inline]69pub fn elapsed(&self) -> Duration {70self.elapsed71}7273/// Returns the elapsed time since the last [`reset`](Stopwatch::reset)74/// of the stopwatch, in seconds.75///76/// # Examples77/// ```78/// # use bevy_time::*;79/// use std::time::Duration;80/// let mut stopwatch = Stopwatch::new();81/// stopwatch.tick(Duration::from_secs(1));82/// assert_eq!(stopwatch.elapsed_secs(), 1.0);83/// ```84///85/// # See Also86///87/// [`elapsed`](Stopwatch::elapsed) - if a `Duration` is desirable instead.88/// [`elapsed_secs_f64`](Stopwatch::elapsed_secs_f64) - if an `f64` is desirable instead.89#[inline]90pub fn elapsed_secs(&self) -> f32 {91self.elapsed().as_secs_f32()92}9394/// Returns the elapsed time since the last [`reset`](Stopwatch::reset)95/// of the stopwatch, in seconds, as f64.96///97/// # See Also98///99/// [`elapsed`](Stopwatch::elapsed) - if a `Duration` is desirable instead.100/// [`elapsed_secs`](Stopwatch::elapsed_secs) - if an `f32` is desirable instead.101#[inline]102pub fn elapsed_secs_f64(&self) -> f64 {103self.elapsed().as_secs_f64()104}105106/// Sets the elapsed time of the stopwatch.107///108/// # Examples109/// ```110/// # use bevy_time::*;111/// use std::time::Duration;112/// let mut stopwatch = Stopwatch::new();113/// stopwatch.set_elapsed(Duration::from_secs_f32(1.0));114/// assert_eq!(stopwatch.elapsed_secs(), 1.0);115/// ```116#[inline]117pub fn set_elapsed(&mut self, time: Duration) {118self.elapsed = time;119}120121/// Advance the stopwatch by `delta` seconds.122/// If the stopwatch is paused, ticking will not have any effect123/// on elapsed time.124///125/// # Examples126/// ```127/// # use bevy_time::*;128/// use std::time::Duration;129/// let mut stopwatch = Stopwatch::new();130/// stopwatch.tick(Duration::from_secs_f32(1.5));131/// assert_eq!(stopwatch.elapsed_secs(), 1.5);132/// ```133pub fn tick(&mut self, delta: Duration) -> &Self {134if !self.is_paused() {135self.elapsed = self.elapsed.saturating_add(delta);136}137self138}139140/// Pauses the stopwatch. Any call to [`tick`](Stopwatch::tick) while141/// paused will not have any effect on the elapsed time.142///143/// # Examples144/// ```145/// # use bevy_time::*;146/// use std::time::Duration;147/// let mut stopwatch = Stopwatch::new();148/// stopwatch.pause();149/// stopwatch.tick(Duration::from_secs_f32(1.5));150/// assert!(stopwatch.is_paused());151/// assert_eq!(stopwatch.elapsed_secs(), 0.0);152/// ```153#[inline]154pub fn pause(&mut self) {155self.is_paused = true;156}157158/// Unpauses the stopwatch. Resume the effect of ticking on elapsed time.159///160/// # Examples161/// ```162/// # use bevy_time::*;163/// use std::time::Duration;164/// let mut stopwatch = Stopwatch::new();165/// stopwatch.pause();166/// stopwatch.tick(Duration::from_secs_f32(1.0));167/// stopwatch.unpause();168/// stopwatch.tick(Duration::from_secs_f32(1.0));169/// assert!(!stopwatch.is_paused());170/// assert_eq!(stopwatch.elapsed_secs(), 1.0);171/// ```172#[inline]173pub fn unpause(&mut self) {174self.is_paused = false;175}176177/// Returns `true` if the stopwatch is paused.178///179/// # Examples180/// ```181/// # use bevy_time::*;182/// let mut stopwatch = Stopwatch::new();183/// assert!(!stopwatch.is_paused());184/// stopwatch.pause();185/// assert!(stopwatch.is_paused());186/// stopwatch.unpause();187/// assert!(!stopwatch.is_paused());188/// ```189#[inline]190pub fn is_paused(&self) -> bool {191self.is_paused192}193194/// Resets the stopwatch. The reset doesn't affect the paused state of the stopwatch.195///196/// # Examples197/// ```198/// # use bevy_time::*;199/// use std::time::Duration;200/// let mut stopwatch = Stopwatch::new();201/// stopwatch.tick(Duration::from_secs_f32(1.5));202/// stopwatch.reset();203/// assert_eq!(stopwatch.elapsed_secs(), 0.0);204/// ```205#[inline]206pub fn reset(&mut self) {207self.elapsed = Default::default();208}209}210211212