summaryrefslogtreecommitdiff
path: root/ecs/src/lib.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-03-12 20:54:42 +0100
committerHampusM <hampus@hampusmat.com>2024-03-12 20:54:42 +0100
commit01066718b0f13846587d26b1869f03e3713082c6 (patch)
tree0ef39b49b26330ab1ed2526105a15c7a0cba7c85 /ecs/src/lib.rs
parent251beb34720d2e7d60ceaddc811a65f52f15bdbd (diff)
feat(ecs): make components internally mutable
Diffstat (limited to 'ecs/src/lib.rs')
-rw-r--r--ecs/src/lib.rs160
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()