use crate::prelude::*;
use bevy::{
ecs::schedule::{ExecutorKind, LogLevel, ScheduleBuildSettings, ScheduleLabel},
prelude::*,
};
use dynamics::integrator::IntegrationSystems;
#[derive(Debug, Default)]
pub struct SolverSchedulePlugin;
impl Plugin for SolverSchedulePlugin {
fn build(&self, app: &mut App) {
app.register_type::<Time<Substeps>>();
app.insert_resource(Time::new_with(Substeps))
.init_resource::<SubstepCount>();
let physics = app
.get_schedule_mut(PhysicsSchedule)
.expect("add PhysicsSchedule first");
physics.configure_sets(
(
SolverSystems::PrepareSolverBodies,
SolverSystems::PrepareJoints,
SolverSystems::PrepareContactConstraints,
SolverSystems::PreSubstep,
SolverSystems::Substep,
SolverSystems::PostSubstep,
SolverSystems::Restitution,
SolverSystems::Finalize,
SolverSystems::StoreContactImpulses,
)
.chain()
.in_set(PhysicsStepSystems::Solver),
);
physics.add_systems(run_substep_schedule.in_set(SolverSystems::Substep));
app.edit_schedule(SubstepSchedule, |schedule| {
schedule
.set_executor_kind(ExecutorKind::SingleThreaded)
.set_build_settings(ScheduleBuildSettings {
ambiguity_detection: LogLevel::Error,
..default()
})
.configure_sets(
(
IntegrationSystems::Velocity,
SubstepSolverSystems::WarmStart,
SubstepSolverSystems::SolveConstraints,
IntegrationSystems::Position,
SubstepSolverSystems::Relax,
SubstepSolverSystems::Damping,
)
.chain(),
);
});
}
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)]
pub struct SubstepSchedule;
#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum SolverSystems {
PrepareSolverBodies,
PrepareJoints,
PrepareContactConstraints,
PreSubstep,
Substep,
PostSubstep,
Restitution,
Finalize,
StoreContactImpulses,
}
#[deprecated(since = "0.4.0", note = "Renamed to `SolverSystems`")]
pub type SolverSet = SolverSystems;
#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum SubstepSolverSystems {
WarmStart,
SolveConstraints,
Relax,
Damping,
}
#[deprecated(since = "0.4.0", note = "Renamed to `SubstepSolverSystems`")]
pub type SubstepSolverSet = SubstepSolverSystems;
#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
#[derive(Debug, Reflect, Resource, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Resource, PartialEq)]
pub struct SubstepCount(pub u32);
impl Default for SubstepCount {
fn default() -> Self {
Self(6)
}
}
fn run_substep_schedule(world: &mut World) {
let delta = world.resource::<Time<Physics>>().delta();
let SubstepCount(substeps) = *world.resource::<SubstepCount>();
let sub_delta = delta.div_f64(substeps as f64);
let mut sub_delta_time = world.resource_mut::<Time<Substeps>>();
sub_delta_time.advance_by(sub_delta);
let _ = world.try_schedule_scope(SubstepSchedule, |world, schedule| {
for i in 0..substeps {
trace!("running SubstepSchedule: {i}");
*world.resource_mut::<Time>() = world.resource::<Time<Substeps>>().as_generic();
schedule.run(world);
}
});
*world.resource_mut::<Time>() = world.resource::<Time<Physics>>().as_generic();
}