From 1019924a29527eba2c8ec8bd976ece6ed76075b0 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 25 Feb 2024 23:25:03 +0100 Subject: feat(ecs): add support for multiple system queries & local components --- ecs/src/lib.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) (limited to 'ecs/src/lib.rs') 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(_system: &mut impl System, _input: Self::Input) + { + } + + fn new( + _system: &'world mut impl System, + component_storage: &'world mut ComponentStorage, + ) -> Self + { + Self::new(component_storage) + } + + fn is_compatible>() -> bool + { + let other_comparable = Other::get_comparable(); + + let Some(other_query_component_ids) = + other_comparable.downcast_ref::() + else { + return true; + }; + + !other_query_component_ids.contains_component_in::() + } + + fn get_comparable() -> Box + { + Box::new(QueryComponentIds { + component_type_ids: Comps::type_ids(), + }) + } +} + +#[derive(Debug)] +struct QueryComponentIds +{ + component_type_ids: Vec, +} + +impl QueryComponentIds +{ + fn contains_component_in(&self) -> bool + where + OtherComps: ComponentSequence, + { + let other_component_type_ids = OtherComps::type_ids() + .into_iter() + .collect::>(); + + // 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>, -- cgit v1.2.3-18-g5258