diff options
author | HampusM <hampus@hampusmat.com> | 2024-02-25 23:25:03 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2024-02-26 19:54:00 +0100 |
commit | 1019924a29527eba2c8ec8bd976ece6ed76075b0 (patch) | |
tree | b26d8bd872684a0c87802e057d8952c42be31f7a /ecs/src/lib.rs | |
parent | 00055d6af92d59a86eb00f110c77c699a562d33e (diff) |
feat(ecs): add support for multiple system queries & local components
Diffstat (limited to 'ecs/src/lib.rs')
-rw-r--r-- | ecs/src/lib.rs | 73 |
1 files changed, 71 insertions, 2 deletions
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index df46a5a..84009e0 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -1,6 +1,6 @@ #![deny(clippy::all, clippy::pedantic)] -use std::any::TypeId; +use std::any::{Any, TypeId}; use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::hash::Hash; @@ -8,7 +8,12 @@ use std::marker::PhantomData; use std::slice::IterMut as SliceIterMut; use crate::component::{Component, Sequence as ComponentSequence}; -use crate::system::{System, TypeErased as TypeErasedSystem}; +use crate::system::{ + NoInitParamFlag as NoInitSystemParamFlag, + Param as SystemParam, + System, + TypeErased as TypeErasedSystem, +}; pub mod component; pub mod system; @@ -142,6 +147,70 @@ where } } +unsafe impl<'world, Comps> SystemParam<'world> for Query<'world, Comps> +where + Comps: ComponentSequence, +{ + type Flags = NoInitSystemParamFlag; + type Input = (); + + fn initialize<SystemImpl>(_system: &mut impl System<SystemImpl>, _input: Self::Input) + { + } + + fn new<SystemImpl>( + _system: &'world mut impl System<SystemImpl>, + component_storage: &'world mut ComponentStorage, + ) -> Self + { + Self::new(component_storage) + } + + fn is_compatible<Other: SystemParam<'world>>() -> bool + { + let other_comparable = Other::get_comparable(); + + let Some(other_query_component_ids) = + other_comparable.downcast_ref::<QueryComponentIds>() + else { + return true; + }; + + !other_query_component_ids.contains_component_in::<Comps>() + } + + fn get_comparable() -> Box<dyn Any> + { + Box::new(QueryComponentIds { + component_type_ids: Comps::type_ids(), + }) + } +} + +#[derive(Debug)] +struct QueryComponentIds +{ + component_type_ids: Vec<TypeId>, +} + +impl QueryComponentIds +{ + fn contains_component_in<OtherComps>(&self) -> bool + where + OtherComps: ComponentSequence, + { + let other_component_type_ids = OtherComps::type_ids() + .into_iter() + .collect::<HashSet<TypeId>>(); + + // TODO: Make this a bit smarter. Queries with a same component can be compatible + // if one of the queries have a component the other one does not have + self.component_type_ids + .iter() + .any(|component_type_id| other_component_type_ids.contains(component_type_id)) + } +} + pub struct QueryComponentIter<'world, Comps> { entity_iter: SliceIterMut<'world, Entity>, |