nightshade 0.52.0

A cross-platform data-oriented game engine.
Documentation
use crate::ecs::world::World;

pub type SystemFn = fn(&mut World);

/// The frame schedule's coarse phases, in run order. Within a phase,
/// systems run in the order they were registered, so composition order is
/// run order: the core systems land first, then each plugin's systems in
/// the order the plugins were added.
#[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
}