use crate::ecs::world::World;
pub type SystemFn = fn(&mut World);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FramePhase {
Start,
Update,
PostUpdate,
Render,
Last,
}
#[derive(Clone, Default)]
pub struct FrameSchedule {
pub start: Vec<SystemFn>,
pub update: Vec<SystemFn>,
pub post_update: Vec<SystemFn>,
pub render: Vec<SystemFn>,
pub last: Vec<SystemFn>,
}
impl FrameSchedule {
fn phase_mut(&mut self, phase: FramePhase) -> &mut Vec<SystemFn> {
match phase {
FramePhase::Start => &mut self.start,
FramePhase::Update => &mut self.update,
FramePhase::PostUpdate => &mut self.post_update,
FramePhase::Render => &mut self.render,
FramePhase::Last => &mut self.last,
}
}
fn phases(&self) -> [&[SystemFn]; 5] {
[
&self.start,
&self.update,
&self.post_update,
&self.render,
&self.last,
]
}
fn phases_mut(&mut self) -> [&mut Vec<SystemFn>; 5] {
[
&mut self.start,
&mut self.update,
&mut self.post_update,
&mut self.render,
&mut self.last,
]
}
}
#[derive(Clone, Default)]
pub struct Schedules {
pub frame: FrameSchedule,
pub retained_ui: Vec<SystemFn>,
}
pub fn schedule_push(schedule: &mut FrameSchedule, phase: FramePhase, system: SystemFn) {
schedule.phase_mut(phase).push(system);
}
pub fn schedule_remove(schedule: &mut FrameSchedule, system: SystemFn) {
for phase in schedule.phases_mut() {
phase.retain(|entry| !std::ptr::fn_addr_eq(*entry, system));
}
}
pub fn schedule_run(schedule: &FrameSchedule, world: &mut World) {
let _span = tracing::info_span!("systems").entered();
for phase in schedule.phases() {
for system in phase {
system(world);
}
}
}
pub fn build_default_frame_schedule() -> FrameSchedule {
let mut schedule = FrameSchedule::default();
schedule_push(
&mut schedule,
FramePhase::Start,
crate::ecs::event::swap_events_system,
);
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::graphics::systems::day_night_cycle_system,
);
#[cfg(target_arch = "wasm32")]
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::camera::systems::sync_wasm_canvas_size,
);
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::bounding_volume::systems::ensure_bounding_volumes,
);
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::animation::systems::update_animation_players,
);
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::animation::systems::apply_animations,
);
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::tween::update_tweens_system,
);
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::particles::systems::update_particle_emitters,
);
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::cloth::systems::sync_cloth_meshes_system,
);
schedule_push(
&mut schedule,
FramePhase::Update,
crate::ecs::vfx::systems::update_vfx_system,
);
schedule_push(
&mut schedule,
FramePhase::PostUpdate,
crate::ecs::transform::systems::run_systems,
);
schedule_push(
&mut schedule,
FramePhase::PostUpdate,
crate::ecs::mesh::systems::update_instanced_mesh_caches_system,
);
schedule_push(
&mut schedule,
FramePhase::Last,
crate::ecs::input::systems::apply_ime_allowed_system,
);
schedule_push(
&mut schedule,
FramePhase::Last,
crate::ecs::input::systems::reset_mouse_system,
);
schedule_push(
&mut schedule,
FramePhase::Last,
crate::ecs::input::systems::reset_keyboard_system,
);
schedule_push(
&mut schedule,
FramePhase::Last,
crate::ecs::input::systems::reset_touch_system,
);
schedule_push(
&mut schedule,
FramePhase::Last,
crate::ecs::world::process_commands_system,
);
schedule_push(
&mut schedule,
FramePhase::Last,
crate::ecs::world::cleanup_unused_resources_system,
);
schedule
}