From c47067d4c1eb2e6f2ea0ac7d3daba01d4f46e5e1 Mon Sep 17 00:00:00 2001 From: HampusM Date: Tue, 9 Apr 2024 21:09:00 +0200 Subject: refactor: move query structs to new query module --- ecs/src/lib.rs | 243 ++------------------------------------------------------- 1 file changed, 7 insertions(+), 236 deletions(-) (limited to 'ecs/src/lib.rs') diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 9d79b91..33d981b 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -1,38 +1,34 @@ #![deny(clippy::all, clippy::pedantic)] -use std::any::{type_name, Any, TypeId}; +use std::any::{type_name, TypeId}; use std::collections::{HashMap, HashSet}; use std::fmt::Debug; -use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::ops::RangeBounds; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use std::vec::Drain; use crate::actions::Action; use crate::component::{Component, Sequence as ComponentSequence}; use crate::event::{Event, Id as EventId, Ids, Sequence as EventSequence}; -use crate::lock::{Lock, ReadGuard}; -use crate::system::{ - NoInitParamFlag as NoInitSystemParamFlag, - Param as SystemParam, - System, - TypeErased as TypeErasedSystem, -}; -use crate::tuple::FilterExclude as TupleFilterExclude; +use crate::lock::Lock; +use crate::system::{System, TypeErased as TypeErasedSystem}; use crate::type_name::TypeName; pub mod actions; pub mod component; pub mod event; pub mod lock; +pub mod query; pub mod system; pub mod tuple; pub mod type_name; pub use ecs_macros::Component; +pub use crate::query::Query; + #[derive(Debug, Default)] struct Entity { @@ -240,231 +236,6 @@ impl TypeName for ActionQueue } } -/// A entity query. -#[derive(Debug)] -pub struct Query<'world, Comps> -where - Comps: ComponentSequence, -{ - component_storage: ReadGuard<'world, ComponentStorage>, - component_storage_lock: Weak>, - comps_pd: PhantomData, -} - -impl<'world, Comps> Query<'world, Comps> -where - Comps: ComponentSequence, -{ - #[must_use] - pub fn iter<'this>(&'this self) -> QueryComponentIter<'world, Comps> - where - 'this: 'world, - { - QueryComponentIter { - component_storage: &self.component_storage, - current_entity_index: 0, - component_type_ids: Comps::type_ids(), - comps_pd: PhantomData, - } - } - - /// Returns a weak reference query to the same components. - #[must_use] - pub fn to_weak_ref(&self) -> WeakRefQuery - { - WeakRefQuery { - component_storage: self.component_storage_lock.clone(), - comps_pd: PhantomData, - } - } - - fn new(component_storage: &'world Arc>) -> Self - { - Self { - component_storage: component_storage - .read_nonblock() - .expect("Failed to acquire read-only component storage lock"), - component_storage_lock: Arc::downgrade(component_storage), - comps_pd: PhantomData, - } - } -} - -impl<'world, Comps> IntoIterator for &'world Query<'world, Comps> -where - Comps: ComponentSequence, -{ - type IntoIter = QueryComponentIter<'world, Comps>; - type Item = Comps::Refs<'world>; - - fn into_iter(self) -> Self::IntoIter - { - self.iter() - } -} - -unsafe impl<'world, Comps> SystemParam<'world> for Query<'world, Comps> -where - Comps: ComponentSequence, -{ - type Flags = NoInitSystemParamFlag; - type Input = TupleFilterExclude; - - fn initialize( - _system: &mut impl System<'world, SystemImpl>, - _input: Self::Input, - ) - { - } - - fn new( - _system: &'world impl System<'world, SystemImpl>, - world_data: &'world WorldData, - ) -> Self - { - Self::new(&world_data.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(), - }) - } -} - -/// A entity query containing a weak reference to the world. -#[derive(Debug)] -pub struct WeakRefQuery -where - Comps: ComponentSequence, -{ - component_storage: Weak>, - comps_pd: PhantomData, -} - -impl WeakRefQuery -where - Comps: ComponentSequence, -{ - /// Returns a struct which can be used to retrieve a [`Query`]. - /// - /// Returns [`None`] if the [`World`] has been dropped. - #[must_use] - pub fn access(&self) -> Option> - { - Some(RefQuery { - component_storage: self.component_storage.upgrade()?, - _pd: PhantomData, - }) - } -} - -impl Clone for WeakRefQuery -where - Comps: ComponentSequence, -{ - fn clone(&self) -> Self - { - Self { - component_storage: self.component_storage.clone(), - comps_pd: PhantomData, - } - } -} - -/// Intermediate between [`Query`] and [`WeakRefQuery`]. Contains a strong reference to -/// the world which is not allowed direct access to. -#[derive(Debug, Clone)] -pub struct RefQuery<'weak_ref, Comps> -where - Comps: ComponentSequence, -{ - component_storage: Arc>, - _pd: PhantomData<&'weak_ref Comps>, -} - -impl<'weak_ref, Comps> RefQuery<'weak_ref, Comps> -where - Comps: ComponentSequence, -{ - #[must_use] - pub fn to_query(&self) -> Query<'_, Comps> - { - Query::new(&self.component_storage) - } -} - -#[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> -{ - component_storage: &'world ComponentStorage, - current_entity_index: usize, - component_type_ids: Vec, - comps_pd: PhantomData, -} - -impl<'world, Comps> Iterator for QueryComponentIter<'world, Comps> -where - Comps: ComponentSequence + 'world, -{ - type Item = Comps::Refs<'world>; - - fn next(&mut self) -> Option - { - let (matching_entity_index, matching_entity) = - self.component_storage.find_entity_with_components( - self.current_entity_index, - &self.component_type_ids, - )?; - - self.current_entity_index = matching_entity_index + 1; - - Some(Comps::from_components( - matching_entity - .components - .iter() - .map(|component| &component.component), - )) - } -} - #[derive(Debug, Default)] pub struct ComponentStorage { -- cgit v1.2.3-18-g5258