use crate::world::World;
use std::cell::{Cell, RefCell};
#[derive(Copy, Clone)]
pub struct SysId(u64);
pub type System<'a, RES> = (SysId, Option<Box<dyn FnMut(&World, &mut RES) + 'a>>);
pub struct Scheduler<'a, RES> {
next_id: Cell<u64>,
systems: RefCell<Vec<System<'a, RES>>>,
}
impl<RES> Default for Scheduler<'_, RES> {
fn default() -> Self {
Self {
next_id: Default::default(),
systems: Default::default(),
}
}
}
impl<'a, RES> Scheduler<'a, RES> {
pub fn register(&self, system: impl FnMut(&World, &mut RES) + 'a) -> SysId {
let id = SysId(self.next_id.get());
self.next_id.set(id.0 + 1);
self.systems.borrow_mut().push((id, Some(Box::new(system))));
id
}
pub fn deregister(&self, system: SysId) {
let position = self
.systems
.borrow()
.iter()
.position(|(id, _)| id.0 == system.0);
if let Some(pos) = position {
let _ = self.systems.borrow_mut().remove(pos);
}
}
pub fn run(&self, world: &World, res: &mut RES) {
let len = self.systems.borrow().len();
for i in 0..len {
let mut guard = self.systems.borrow_mut();
let Some((_, sys)) = guard.get_mut(i) else {
break;
};
let mut sys = sys.take().unwrap();
drop(guard);
sys(world, res);
world.flush_despawned();
let mut guard = self.systems.borrow_mut();
let Some((_, entry)) = guard.get_mut(i) else {
break;
};
*entry = Some(sys);
}
}
}