#[derive(Debug, Copy, Clone)]
pub struct PhysicsTime {
scale: f32,
previous_scale: Option<f32>,
}
impl PhysicsTime {
#[must_use]
pub fn new(scale: f32) -> Self {
assert!(scale >= 0.0, "Negative scale: {}", scale);
Self {
scale,
previous_scale: None,
}
}
pub fn pause(&mut self) {
self.previous_scale = Some(self.scale);
self.scale = 0.0;
}
pub fn resume(&mut self) {
if let Some(prev) = self.previous_scale {
self.scale = prev;
self.previous_scale = None;
}
}
pub fn set_scale(&mut self, scale: f32) {
assert!(scale >= 0.0);
self.scale = scale;
}
#[must_use]
pub fn scale(&self) -> f32 {
self.scale
}
#[must_use]
#[deprecated(note = "Please use 'scale()' instead")]
#[doc(hidden)]
pub fn get_scale(&self) -> f32 {
self.scale
}
}
impl Default for PhysicsTime {
fn default() -> Self {
Self {
scale: 1.0,
previous_scale: None,
}
}
}
#[cfg(test)]
#[allow(clippy::float_cmp)]
mod tests {
use rstest::rstest;
use super::*;
#[rstest]
#[case(0.0)]
#[case(1.0)]
#[case(0.5)]
fn pause_sets_scale_to_zero(#[case] initial_scale: f32) {
let mut time = PhysicsTime::new(initial_scale);
time.pause();
assert_eq!(time.scale(), 0.0);
}
#[rstest]
#[case(0.0)]
#[case(1.0)]
#[case(0.5)]
fn pause_restore_time_scale_before_pause(#[case] initial_scale: f32) {
let mut time = PhysicsTime::new(initial_scale);
time.pause();
time.resume();
assert_eq!(time.scale(), initial_scale);
}
#[rstest]
#[case(1.0, 2.0)]
#[case(1.0, 0.0)]
#[case(1.0, 1.0)]
#[case(0.0, 0.0)]
fn scale_can_be_set(#[case] initial_scale: f32, #[case] new_scale: f32) {
let mut time = PhysicsTime::new(initial_scale);
time.set_scale(new_scale);
assert_eq!(new_scale, time.scale());
}
#[rstest]
#[case(PhysicsTime::new(1.0), -1.0)]
#[case(PhysicsTime::new(0.0), -0.1)]
#[should_panic]
fn set_negative_scale_panics(#[case] mut time: PhysicsTime, #[case] new_scale: f32) {
time.set_scale(new_scale);
}
#[rstest]
#[case(-1.0)]
#[case(-0.1)]
#[should_panic]
fn new_with_negative_scale_panics(#[case] scale: f32) {
let _ = PhysicsTime::new(scale);
}
}