use crate::{Resources, World}; use std::borrow::Cow; use fixedbitset::FixedBitSet; use hecs::{Query, Access}; #[derive(Copy, Clone)] pub enum ThreadLocalExecution { Immediate, NextFlush, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub struct SystemId(pub u32); impl SystemId { pub fn new() -> Self { SystemId(rand::random::()) } } pub trait System: Send + Sync { fn name(&self) -> Cow<'static, str>; fn id(&self) -> SystemId; fn update_archetype_access(&mut self, world: &World); fn get_archetype_access(&self) -> &ArchetypeAccess; fn thread_local_execution(&self) -> ThreadLocalExecution; fn run(&mut self, world: &World, resources: &Resources); fn run_thread_local(&mut self, world: &mut World, resources: &mut Resources); fn initialize(&mut self, _resources: &mut Resources) {} } // credit to Ratysz from the Yaks codebase #[derive(Default)] pub struct ArchetypeAccess { pub immutable: FixedBitSet, pub mutable: FixedBitSet, } impl ArchetypeAccess { pub fn is_compatible(&self, other: &ArchetypeAccess) -> bool { self.mutable.is_disjoint(&other.mutable) && self.mutable.is_disjoint(&other.immutable) && self.immutable.is_disjoint(&other.mutable) } pub fn union(&mut self, other: &ArchetypeAccess) { self.mutable.union_with(&other.mutable); self.immutable.union_with(&other.immutable); } pub fn set_access_for_query(&mut self, world: &World) where Q: Query, { self.immutable.clear(); self.mutable.clear(); let iterator = world.archetypes(); let bits = iterator.len(); self.immutable.grow(bits); self.mutable.grow(bits); iterator .enumerate() .filter_map(|(index, archetype)| archetype.access::().map(|access| (index, access))) .for_each(|(archetype, access)| match access { Access::Read => self.immutable.set(archetype, true), Access::Write => self.mutable.set(archetype, true), Access::Iterate => (), }); } }