summaryrefslogtreecommitdiff
path: root/ecs/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/lib.rs')
-rw-r--r--ecs/src/lib.rs73
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>,