diff options
author | HampusM <hampus@hampusmat.com> | 2024-03-12 20:54:42 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2024-03-12 20:54:42 +0100 |
commit | 01066718b0f13846587d26b1869f03e3713082c6 (patch) | |
tree | 0ef39b49b26330ab1ed2526105a15c7a0cba7c85 /ecs/src/lib.rs | |
parent | 251beb34720d2e7d60ceaddc811a65f52f15bdbd (diff) |
feat(ecs): make components internally mutable
Diffstat (limited to 'ecs/src/lib.rs')
-rw-r--r-- | ecs/src/lib.rs | 160 |
1 files changed, 46 insertions, 114 deletions
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 6b9373c..d781b3e 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -1,10 +1,11 @@ #![deny(clippy::all, clippy::pedantic)] use std::any::{Any, TypeId}; +use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::marker::PhantomData; -use std::slice::{Iter as SliceIter, IterMut as SliceIterMut}; +use std::slice::Iter as SliceIter; use crate::actions::Action; use crate::component::{Component, Sequence as ComponentSequence}; @@ -28,7 +29,7 @@ pub use ecs_macros::Component; #[derive(Debug, Default)] struct Entity { - components: Vec<Box<dyn Component>>, + components: Vec<RefCell<Box<dyn Component>>>, } #[derive(Debug, Default)] @@ -50,18 +51,20 @@ impl World where Comps: ComponentSequence, { - self.data - .component_storage - .entities - .push(Entity { components: components.into_vec() }); + self.data.component_storage.entities.push(Entity { + components: components + .into_vec() + .into_iter() + .map(RefCell::new) + .collect(), + }); } - pub fn register_system<TSystem, SystemImpl>( - &mut self, + pub fn register_system<'this, SystemImpl>( + &'this mut self, event: &impl Event, - system: TSystem, - ) where - TSystem: System<SystemImpl>, + system: impl System<'this, SystemImpl>, + ) { self.systems.push(system.into_type_erased()); @@ -77,36 +80,38 @@ impl World /// /// # Panics /// Will panic if a system has dissapeared. - pub fn emit(&mut self, event: &impl Event) + pub fn emit(&self, event: &impl Event) { let Some(system_indices) = self.data.events.get(&event.id()).cloned() else { return; }; for system_index in system_indices { - let system = self.systems.get_mut(system_index).unwrap(); + let system = self.systems.get(system_index).unwrap(); - system.run(&mut self.data); + // SAFETY: The world data lives long enough + unsafe { + system.run(&self.data); + } } } - pub fn query<Comps>(&mut self) -> Query<Comps> + pub fn query<Comps>(&self) -> Query<Comps> where Comps: ComponentSequence, { - Query::new(&mut self.data) + Query::new(&self.data) } /// Peforms the actions that have been queued up using [`Actions`]. pub fn perform_queued_actions(&mut self) { - for action in self.data.action_queue.drain(..) { + for action in self.data.action_queue.borrow_mut().drain(..) { match action { Action::Spawn(components) => { - self.data - .component_storage - .entities - .push(Entity { components }); + self.data.component_storage.entities.push(Entity { + components: components.into_iter().map(RefCell::new).collect(), + }); } } } @@ -118,7 +123,7 @@ pub struct WorldData { events: HashMap<EventId, Vec<usize>>, component_storage: ComponentStorage, - action_queue: Vec<Action>, + action_queue: RefCell<Vec<Action>>, } #[derive(Debug)] @@ -126,7 +131,7 @@ pub struct Query<'world, Comps> where Comps: ComponentSequence, { - world_data: &'world mut WorldData, + world_data: &'world WorldData, comps_pd: PhantomData<Comps>, } @@ -134,17 +139,7 @@ impl<'world, Comps> Query<'world, Comps> where Comps: ComponentSequence, { - fn new(world_data: &'world mut WorldData) -> Self - { - Self { world_data, comps_pd: PhantomData } - } -} - -impl<'world, Comps> Query<'world, Comps> -where - Comps: ComponentSequence, -{ - pub fn iter(&self) -> QueryComponentIter<Comps> + pub fn iter(&self) -> QueryComponentIter<'world, Comps> { QueryComponentIter { entity_iter: self.world_data.component_storage.entities.iter(), @@ -153,13 +148,9 @@ where } } - pub fn iter_mut(&mut self) -> QueryComponentMutIter<Comps> + fn new(world_data: &'world WorldData) -> Self { - QueryComponentMutIter { - entity_iter: self.world_data.component_storage.entities.iter_mut(), - component_type_ids: Comps::type_ids(), - comps_pd: PhantomData, - } + Self { world_data, comps_pd: PhantomData } } } @@ -176,19 +167,6 @@ where } } -impl<'world, Comps> IntoIterator for &'world mut Query<'world, Comps> -where - Comps: ComponentSequence, -{ - type IntoIter = QueryComponentMutIter<'world, Comps>; - type Item = Comps::MutRefs<'world>; - - fn into_iter(self) -> Self::IntoIter - { - self.iter_mut() - } -} - unsafe impl<'world, Comps> SystemParam<'world> for Query<'world, Comps> where Comps: ComponentSequence, @@ -196,13 +174,16 @@ where type Flags = NoInitSystemParamFlag; type Input = TupleFilterExclude; - fn initialize<SystemImpl>(_system: &mut impl System<SystemImpl>, _input: Self::Input) + fn initialize<SystemImpl>( + _system: &mut impl System<'world, SystemImpl>, + _input: Self::Input, + ) { } fn new<SystemImpl>( - _system: &'world mut impl System<SystemImpl>, - world_data: &'world mut WorldData, + _system: &'world impl System<'world, SystemImpl>, + world_data: &'world WorldData, ) -> Self { Self::new(world_data) @@ -268,75 +249,26 @@ where fn next(&mut self) -> Option<Self::Item> { - let matching_entity = find_entity_with_components::<&Entity>( - &mut self.entity_iter, - &self.component_type_ids, - )?; + let matching_entity = + find_entity_with_components(&mut self.entity_iter, &self.component_type_ids)?; Some(Comps::from_components(&matching_entity.components)) } } -pub struct QueryComponentMutIter<'world, Comps> -{ - entity_iter: SliceIterMut<'world, Entity>, - component_type_ids: Vec<TypeId>, - comps_pd: PhantomData<Comps>, -} - -impl<'world, Comps> Iterator for QueryComponentMutIter<'world, Comps> -where - Comps: ComponentSequence + 'world, -{ - type Item = Comps::MutRefs<'world>; - - fn next(&mut self) -> Option<Self::Item> - { - let matching_entity = find_entity_with_components::<&mut Entity>( - &mut self.entity_iter, - &self.component_type_ids, - )?; - - Some(Comps::from_components_mut(&mut matching_entity.components)) - } -} - -trait EntityRef -{ - fn components(&self) -> &[Box<dyn Component>]; -} - -impl EntityRef for &Entity -{ - fn components(&self) -> &[Box<dyn Component>] - { - &self.components - } -} - -impl EntityRef for &mut Entity -{ - fn components(&self) -> &[Box<dyn Component>] - { - &self.components - } -} - -fn find_entity_with_components<EntityRefT>( - entity_iter: &mut impl Iterator<Item = EntityRefT>, +fn find_entity_with_components<'world>( + entity_iter: &mut impl Iterator<Item = &'world Entity>, component_type_ids: &[TypeId], -) -> Option<EntityRefT> -where - EntityRefT: EntityRef, +) -> Option<&'world Entity> { // TODO: This is a really dumb and slow way to do this. Refactor the world // to store components in archetypes entity_iter.find(|entity| { - let entity_components: HashSet<_> = entity - .components() + let entity_components = entity + .components .iter() - .map(|component| component.as_ref().type_id()) - .collect(); + .filter_map(|component| Some(component.try_borrow().ok()?.as_ref().type_id())) + .collect::<HashSet<_>>(); if component_type_ids .iter() |