use std::time::Duration;
use bevy::prelude::*;
use crate::prelude::*;
#[derive(Reflect, Clone, Copy, Debug, PartialEq)]
pub enum TimestepMode {
Fixed {
delta: Duration,
overstep: Duration,
max_delta_overstep: Duration,
},
FixedOnce {
delta: Duration,
},
Variable {
max_delta: Duration,
},
}
impl Default for TimestepMode {
fn default() -> Self {
Self::Fixed {
delta: Duration::default(),
overstep: Duration::default(),
max_delta_overstep: Duration::from_secs_f64(1.0 / 60.0),
}
}
}
#[cfg_attr(feature = "2d", doc = "use bevy_xpbd_2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use bevy_xpbd_3d::prelude::*;")]
#[cfg_attr(
feature = "2d",
doc = "use bevy_xpbd_2d::{prelude::*, PhysicsSchedule, PhysicsStepSet};"
)]
#[cfg_attr(
feature = "3d",
doc = "use bevy_xpbd_3d::{prelude::*, PhysicsSchedule, PhysicsStepSet};"
)]
#[cfg_attr(feature = "2d", doc = "use bevy_xpbd_2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use bevy_xpbd_3d::prelude::*;")]
#[cfg_attr(
feature = "2d",
doc = "use bevy_xpbd_2d::{prelude::*, PhysicsSchedule};"
)]
#[cfg_attr(
feature = "3d",
doc = "use bevy_xpbd_3d::{prelude::*, PhysicsSchedule};"
)]
#[derive(Reflect, Clone, Copy, Debug, PartialEq)]
pub struct Physics {
timestep_mode: TimestepMode,
paused: bool,
relative_speed: f64,
}
impl Default for Physics {
fn default() -> Self {
Self::fixed_hz(60.0)
}
}
impl Physics {
pub const fn from_timestep(timestep_mode: TimestepMode) -> Self {
Self {
timestep_mode,
paused: false,
relative_speed: 1.0,
}
}
pub fn fixed_hz(hz: f64) -> Self {
assert!(hz > 0.0, "Hz less than or equal to zero");
assert!(hz.is_finite(), "Hz is infinite");
Self::from_timestep(TimestepMode::Fixed {
delta: Duration::from_secs_f64(1.0 / hz),
overstep: Duration::ZERO,
max_delta_overstep: Duration::from_secs_f64(1.0 / 60.0),
})
}
pub fn fixed_once_hz(hz: f64) -> Self {
assert!(hz > 0.0, "Hz less than or equal to zero");
assert!(hz.is_finite(), "Hz is infinite");
Self::from_timestep(TimestepMode::FixedOnce {
delta: Duration::from_secs_f64(1.0 / hz),
})
}
pub fn variable(max_delta_seconds: f64) -> Self {
assert!(
max_delta_seconds > 0.0,
"max delta less than or equal to zero"
);
Self::from_timestep(TimestepMode::Variable {
max_delta: Duration::from_secs_f64(max_delta_seconds),
})
}
}
pub trait PhysicsTime {
fn from_timestep(timestep_mode: TimestepMode) -> Self;
fn timestep_mode(&self) -> TimestepMode;
fn timestep_mode_mut(&mut self) -> &mut TimestepMode;
fn set_timestep_mode(&mut self, timestep_mode: TimestepMode);
fn relative_speed(&self) -> f32;
fn relative_speed_f64(&self) -> f64;
fn with_relative_speed(self, ratio: f32) -> Self;
fn with_relative_speed_f64(self, ratio: f64) -> Self;
fn set_relative_speed(&mut self, ratio: f32);
fn set_relative_speed_f64(&mut self, ratio: f64);
fn is_paused(&self) -> bool;
fn pause(&mut self);
#[doc(alias = "resume")]
fn unpause(&mut self);
}
impl PhysicsTime for Time<Physics> {
fn from_timestep(timestep_mode: TimestepMode) -> Self {
Self::new_with(Physics::from_timestep(timestep_mode))
}
fn timestep_mode(&self) -> TimestepMode {
self.context().timestep_mode
}
fn timestep_mode_mut(&mut self) -> &mut TimestepMode {
&mut self.context_mut().timestep_mode
}
fn set_timestep_mode(&mut self, timestep_mode: TimestepMode) {
self.context_mut().timestep_mode = timestep_mode;
}
fn with_relative_speed(self, ratio: f32) -> Self {
self.with_relative_speed_f64(ratio as f64)
}
fn with_relative_speed_f64(mut self, ratio: f64) -> Self {
assert!(ratio.is_finite(), "tried to go infinitely fast");
assert!(ratio >= 0.0, "tried to go back in time");
self.context_mut().relative_speed = ratio;
self
}
fn relative_speed(&self) -> f32 {
self.relative_speed_f64() as f32
}
fn relative_speed_f64(&self) -> f64 {
self.context().relative_speed
}
fn set_relative_speed(&mut self, ratio: f32) {
self.set_relative_speed_f64(ratio as f64);
}
fn set_relative_speed_f64(&mut self, ratio: f64) {
assert!(ratio.is_finite(), "tried to go infinitely fast");
assert!(ratio >= 0.0, "tried to go back in time");
self.context_mut().relative_speed = ratio;
}
fn pause(&mut self) {
self.context_mut().paused = true;
}
fn unpause(&mut self) {
self.context_mut().paused = false;
}
fn is_paused(&self) -> bool {
self.context().paused
}
}
#[derive(Reflect, Clone, Copy, Debug, Default, PartialEq)]
pub struct Substeps;
pub(crate) trait TimePrecisionAdjusted {
fn delta_seconds_adjusted(&self) -> Scalar;
}
pub(crate) trait DurationPrecisionAdjusted {
fn as_secs_adjusted(&self) -> Scalar;
fn from_secs_adjusted(secs: Scalar) -> Self;
}
impl TimePrecisionAdjusted for Time {
fn delta_seconds_adjusted(&self) -> Scalar {
#[cfg(feature = "f32")]
{
self.delta_seconds()
}
#[cfg(feature = "f64")]
{
self.delta_seconds_f64()
}
}
}
impl DurationPrecisionAdjusted for Duration {
fn as_secs_adjusted(&self) -> Scalar {
#[cfg(feature = "f32")]
{
self.as_secs_f32()
}
#[cfg(feature = "f64")]
{
self.as_secs_f64()
}
}
fn from_secs_adjusted(secs: Scalar) -> Self {
#[cfg(feature = "f32")]
{
Self::from_secs_f32(secs)
}
#[cfg(feature = "f64")]
{
Self::from_secs_f64(secs)
}
}
}