bevy/crates/bevy_time/src/stopwatch.rs
Zachary Harrold 3c829d7f68
Remove everything except Instant from bevy_utils::time (#17158)
# Objective

- Contributes to #11478
- Contributes to #16877

## Solution

- Removed everything except `Instant` from `bevy_utils::time`

## Testing

- CI

---

## Migration Guide

If you relied on any of the following from `bevy_utils::time`:

- `Duration`
- `TryFromFloatSecsError`

Import these directly from `core::time` regardless of platform target
(WASM, mobile, etc.)

If you relied on any of the following from `bevy_utils::time`:

- `SystemTime`
- `SystemTimeError`

Instead import these directly from either `std::time` or `web_time` as
appropriate for your target platform.

## Notes

`Duration` and `TryFromFloatSecsError` are both re-exports from
`core::time` regardless of whether they are used from `web_time` or
`std::time`, so there is no value gained from re-exporting them from
`bevy_utils::time` as well. As for `SystemTime` and `SystemTimeError`,
no Bevy internal crates or examples rely on these types. Since Bevy
doesn't have a `Time<Wall>` resource for interacting with wall-time (and
likely shouldn't need one), I think removing these from `bevy_utils`
entirely and waiting for a use-case to justify inclusion is a reasonable
path forward.
2025-01-05 20:36:08 +00:00

207 lines
6.2 KiB
Rust

#[cfg(feature = "bevy_reflect")]
use bevy_reflect::{prelude::*, Reflect};
use core::time::Duration;
/// A Stopwatch is a struct that tracks elapsed time when started.
///
/// Note that in order to advance the stopwatch [`tick`](Stopwatch::tick) **MUST** be called.
/// # Examples
///
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
///
/// stopwatch.tick(Duration::from_secs_f32(1.0)); // tick one second
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
///
/// stopwatch.pause();
/// stopwatch.tick(Duration::from_secs_f32(1.0)); // paused stopwatches don't tick
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
///
/// stopwatch.reset(); // reset the stopwatch
/// assert!(stopwatch.is_paused());
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
/// ```
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Default))]
pub struct Stopwatch {
elapsed: Duration,
is_paused: bool,
}
impl Stopwatch {
/// Create a new unpaused `Stopwatch` with no elapsed time.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// let stopwatch = Stopwatch::new();
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
/// assert_eq!(stopwatch.is_paused(), false);
/// ```
pub fn new() -> Self {
Default::default()
}
/// Returns the elapsed time since the last [`reset`](Stopwatch::reset)
/// of the stopwatch.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.tick(Duration::from_secs(1));
/// assert_eq!(stopwatch.elapsed(), Duration::from_secs(1));
/// ```
///
/// # See Also
///
/// [`elapsed_secs`](Stopwatch::elapsed_secs) - if an `f32` value is desirable instead.
/// [`elapsed_secs_f64`](Stopwatch::elapsed_secs_f64) - if an `f64` is desirable instead.
#[inline]
pub fn elapsed(&self) -> Duration {
self.elapsed
}
/// Returns the elapsed time since the last [`reset`](Stopwatch::reset)
/// of the stopwatch, in seconds.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.tick(Duration::from_secs(1));
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
/// ```
///
/// # See Also
///
/// [`elapsed`](Stopwatch::elapsed) - if a `Duration` is desirable instead.
/// [`elapsed_secs_f64`](Stopwatch::elapsed_secs_f64) - if an `f64` is desirable instead.
#[inline]
pub fn elapsed_secs(&self) -> f32 {
self.elapsed().as_secs_f32()
}
/// Returns the elapsed time since the last [`reset`](Stopwatch::reset)
/// of the stopwatch, in seconds, as f64.
///
/// # See Also
///
/// [`elapsed`](Stopwatch::elapsed) - if a `Duration` is desirable instead.
/// [`elapsed_secs`](Stopwatch::elapsed_secs) - if an `f32` is desirable instead.
#[inline]
pub fn elapsed_secs_f64(&self) -> f64 {
self.elapsed().as_secs_f64()
}
/// Sets the elapsed time of the stopwatch.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.set_elapsed(Duration::from_secs_f32(1.0));
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
/// ```
#[inline]
pub fn set_elapsed(&mut self, time: Duration) {
self.elapsed = time;
}
/// Advance the stopwatch by `delta` seconds.
/// If the stopwatch is paused, ticking will not have any effect
/// on elapsed time.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.tick(Duration::from_secs_f32(1.5));
/// assert_eq!(stopwatch.elapsed_secs(), 1.5);
/// ```
pub fn tick(&mut self, delta: Duration) -> &Self {
if !self.is_paused() {
self.elapsed = self.elapsed.saturating_add(delta);
}
self
}
/// Pauses the stopwatch. Any call to [`tick`](Stopwatch::tick) while
/// paused will not have any effect on the elapsed time.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.pause();
/// stopwatch.tick(Duration::from_secs_f32(1.5));
/// assert!(stopwatch.is_paused());
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
/// ```
#[inline]
pub fn pause(&mut self) {
self.is_paused = true;
}
/// Unpauses the stopwatch. Resume the effect of ticking on elapsed time.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.pause();
/// stopwatch.tick(Duration::from_secs_f32(1.0));
/// stopwatch.unpause();
/// stopwatch.tick(Duration::from_secs_f32(1.0));
/// assert!(!stopwatch.is_paused());
/// assert_eq!(stopwatch.elapsed_secs(), 1.0);
/// ```
#[inline]
pub fn unpause(&mut self) {
self.is_paused = false;
}
/// Returns `true` if the stopwatch is paused.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// let mut stopwatch = Stopwatch::new();
/// assert!(!stopwatch.is_paused());
/// stopwatch.pause();
/// assert!(stopwatch.is_paused());
/// stopwatch.unpause();
/// assert!(!stopwatch.is_paused());
/// ```
#[inline]
pub fn is_paused(&self) -> bool {
self.is_paused
}
/// Resets the stopwatch. The reset doesn't affect the paused state of the stopwatch.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut stopwatch = Stopwatch::new();
/// stopwatch.tick(Duration::from_secs_f32(1.5));
/// stopwatch.reset();
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
/// ```
#[inline]
pub fn reset(&mut self) {
self.elapsed = Default::default();
}
}