summaryrefslogtreecommitdiff
path: root/ecs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs')
-rw-r--r--ecs/src/component.rs194
-rw-r--r--ecs/src/component/local.rs6
-rw-r--r--ecs/src/component/storage.rs54
-rw-r--r--ecs/src/component/storage/archetype.rs94
-rw-r--r--ecs/src/entity.rs12
-rw-r--r--ecs/src/lib.rs42
-rw-r--r--ecs/src/lock.rs13
-rw-r--r--ecs/src/query.rs22
-rw-r--r--ecs/src/relationship.rs158
-rw-r--r--ecs/src/system.rs228
-rw-r--r--ecs/src/system/stateful.rs7
11 files changed, 365 insertions, 465 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index 265eb9e..46fbf8a 100644
--- a/ecs/src/component.rs
+++ b/ecs/src/component.rs
@@ -1,5 +1,6 @@
use std::any::{type_name, Any};
use std::fmt::Debug;
+use std::ops::{Deref, DerefMut};
use seq_macro::seq;
@@ -8,7 +9,14 @@ use crate::event::component::{
Kind as ComponentEventKind,
Removed as ComponentRemovedEvent,
};
-use crate::lock::{Error as LockError, Lock, ReadGuard, WriteGuard};
+use crate::lock::{
+ Error as LockError,
+ Lock,
+ MappedReadGuard,
+ MappedWriteGuard,
+ ReadGuard,
+ WriteGuard,
+};
use crate::system::Input as SystemInput;
use crate::type_name::TypeName;
use crate::uid::Uid;
@@ -26,11 +34,11 @@ pub trait Component: SystemInput + Any + TypeName
where
Self: Sized;
- type RefMut<'component>: FromOptionalMut<'component> + FromLockedOptional<'component>
+ type HandleMut<'component>: FromLockedOptional<'component>
where
Self: Sized;
- type Ref<'component>: FromOptional<'component> + FromLockedOptional<'component>
+ type Handle<'component>: FromLockedOptional<'component>
where
Self: Sized;
@@ -101,12 +109,12 @@ impl TypeName for Box<dyn Component>
impl<ComponentT> Component for Option<ComponentT>
where
ComponentT: Component,
- for<'a> Option<ComponentT::Ref<'a>>: FromOptional<'a> + FromLockedOptional<'a>,
- for<'a> Option<ComponentT::RefMut<'a>>: FromOptionalMut<'a> + FromLockedOptional<'a>,
+ for<'a> Option<ComponentT::Handle<'a>>: FromLockedOptional<'a>,
+ for<'a> Option<ComponentT::HandleMut<'a>>: FromLockedOptional<'a>,
{
type Component = ComponentT;
- type Ref<'component> = Option<ComponentT::Ref<'component>>;
- type RefMut<'component> = Option<ComponentT::RefMut<'component>>;
+ type Handle<'component> = Option<ComponentT::Handle<'component>>;
+ type HandleMut<'component> = Option<ComponentT::HandleMut<'component>>;
fn id() -> Uid
{
@@ -182,7 +190,7 @@ where
ComponentT: Component,
{
type Component = ComponentT;
- type Handle<'component> = ComponentT::Ref<'component>;
+ type Handle<'component> = ComponentT::Handle<'component>;
}
impl<ComponentT> Ref for &mut ComponentT
@@ -190,7 +198,7 @@ where
ComponentT: Component,
{
type Component = ComponentT;
- type Handle<'component> = ComponentT::RefMut<'component>;
+ type Handle<'component> = ComponentT::HandleMut<'component>;
}
/// [`Component`] metadata.
@@ -220,22 +228,6 @@ impl Metadata
}
}
-pub trait FromOptionalMut<'comp>
-{
- fn from_optional_mut_component(
- optional_component: Option<WriteGuard<'comp, Box<dyn Component>>>,
- world: &'comp World,
- ) -> Self;
-}
-
-pub trait FromOptional<'comp>
-{
- fn from_optional_component(
- optional_component: Option<ReadGuard<'comp, Box<dyn Component>>>,
- world: &'comp World,
- ) -> Self;
-}
-
pub trait FromLockedOptional<'comp>: Sized
{
/// Converts a reference to a optional locked boxed component to a instance of `Self`.
@@ -248,18 +240,158 @@ pub trait FromLockedOptional<'comp>: Sized
) -> Result<Self, LockError>;
}
+#[derive(Debug)]
+pub struct Handle<'a, ComponentT: Component>
+{
+ inner: MappedReadGuard<'a, ComponentT>,
+}
+
+impl<'a, ComponentT: Component> Handle<'a, ComponentT>
+{
+ pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self
+ {
+ Self {
+ inner: inner.map(|component| {
+ component.downcast_ref::<ComponentT>().unwrap_or_else(|| {
+ panic!(
+ "Cannot downcast component {} to type {}",
+ component.type_name(),
+ type_name::<ComponentT>()
+ );
+ })
+ }),
+ }
+ }
+}
+
+impl<'component, ComponentT: Component> FromLockedOptional<'component>
+ for Handle<'component, ComponentT>
+{
+ fn from_locked_optional_component(
+ optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>,
+ _world: &'component World,
+ ) -> Result<Self, LockError>
+ {
+ let component = optional_component.unwrap_or_else(|| {
+ panic!(
+ "Component {} was not found in entity",
+ type_name::<ComponentT>()
+ );
+ });
+
+ Ok(Self::new(component.read_nonblock()?))
+ }
+}
+
+impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<Handle<'comp, ComponentT>>
+where
+ ComponentT: Component,
+{
+ fn from_locked_optional_component(
+ optional_component: Option<&'comp Lock<Box<dyn Component>>>,
+ _world: &'comp World,
+ ) -> Result<Self, LockError>
+ {
+ optional_component
+ .map(|lock| Ok(Handle::new(lock.read_nonblock()?)))
+ .transpose()
+ }
+}
+
+impl<ComponentT: Component> Deref for Handle<'_, ComponentT>
+{
+ type Target = ComponentT;
+
+ fn deref(&self) -> &Self::Target
+ {
+ &self.inner
+ }
+}
+
+#[derive(Debug)]
+pub struct HandleMut<'a, ComponentT: Component>
+{
+ inner: MappedWriteGuard<'a, ComponentT>,
+}
+
+impl<'a, ComponentT: Component> HandleMut<'a, ComponentT>
+{
+ pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self
+ {
+ Self {
+ inner: inner.map(|component| {
+ let component_type_name = component.type_name();
+
+ component.downcast_mut::<ComponentT>().unwrap_or_else(|| {
+ panic!(
+ "Cannot downcast component {component_type_name} to type {}",
+ type_name::<ComponentT>()
+ );
+ })
+ }),
+ }
+ }
+}
+
+impl<'component, ComponentT: Component> FromLockedOptional<'component>
+ for HandleMut<'component, ComponentT>
+{
+ fn from_locked_optional_component(
+ optional_component: Option<&'component Lock<Box<dyn Component>>>,
+ _world: &'component World,
+ ) -> Result<Self, LockError>
+ {
+ let component = optional_component.unwrap_or_else(|| {
+ panic!(
+ "Component {} was not found in entity",
+ type_name::<ComponentT>()
+ );
+ });
+
+ Ok(Self::new(component.write_nonblock()?))
+ }
+}
+
+impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<HandleMut<'comp, ComponentT>>
+where
+ ComponentT: Component,
+{
+ fn from_locked_optional_component(
+ optional_component: Option<&'comp Lock<Box<dyn Component>>>,
+ _world: &'comp World,
+ ) -> Result<Self, LockError>
+ {
+ optional_component
+ .map(|lock| Ok(HandleMut::new(lock.write_nonblock()?)))
+ .transpose()
+ }
+}
+
+impl<ComponentT: Component> Deref for HandleMut<'_, ComponentT>
+{
+ type Target = ComponentT;
+
+ fn deref(&self) -> &Self::Target
+ {
+ &self.inner
+ }
+}
+
+impl<ComponentT: Component> DerefMut for HandleMut<'_, ComponentT>
+{
+ fn deref_mut(&mut self) -> &mut Self::Target
+ {
+ &mut self.inner
+ }
+}
+
macro_rules! inner {
($c: tt) => {
seq!(I in 0..=$c {
impl<#(IntoComp~I,)*> Sequence for (#(IntoComp~I,)*)
where
#(
- for<'comp> IntoComp~I: Into<
- Component: Component<
- RefMut<'comp>: FromOptionalMut<'comp>,
- Ref<'comp>: FromOptional<'comp>
- >
- >,
+ for<'comp> IntoComp~I: Into<Component: Component>,
)*
{
const COUNT: usize = $c + 1;
diff --git a/ecs/src/component/local.rs b/ecs/src/component/local.rs
index d4e414e..0f6f641 100644
--- a/ecs/src/component/local.rs
+++ b/ecs/src/component/local.rs
@@ -1,14 +1,14 @@
use std::ops::{Deref, DerefMut};
-use crate::component::Component;
-use crate::system::{ComponentRefMut, Param as SystemParam, System};
+use crate::component::{Component, HandleMut as ComponentHandleMut};
+use crate::system::{Param as SystemParam, System};
use crate::World;
/// Holds a component which is local to a single system.
#[derive(Debug)]
pub struct Local<'world, LocalComponent: Component>
{
- local_component: ComponentRefMut<'world, LocalComponent>,
+ local_component: ComponentHandleMut<'world, LocalComponent>,
}
impl<'world, LocalComponent> SystemParam<'world> for Local<'world, LocalComponent>
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index c70e7e7..40909fb 100644
--- a/ecs/src/component/storage.rs
+++ b/ecs/src/component/storage.rs
@@ -7,7 +7,8 @@ use hashbrown::HashMap;
use crate::component::storage::archetype::{
Archetype,
- ArchetypeEntity,
+ Entity as ArchetypeEntity,
+ EntityComponent as ArchetypeEntityComponent,
Id as ArchetypeId,
};
use crate::component::storage::graph::{
@@ -20,7 +21,6 @@ use crate::component::Component;
use crate::type_name::TypeName;
use crate::uid::{Kind as UidKind, Uid};
use crate::util::{BorrowedOrOwned, Either, StreamingIterator, VecExt};
-use crate::EntityComponent;
pub mod archetype;
@@ -123,17 +123,14 @@ impl Storage
archetype_node
.archetype_mut()
- .push_entity(ArchetypeEntity { uid, components: vec![] });
+ .push_entity(ArchetypeEntity::new(uid, []));
self.entity_archetype_lookup.insert(uid, empty_archetype_id);
Ok(())
}
- pub fn remove_entity(
- &mut self,
- entity_uid: Uid,
- ) -> Result<Vec<EntityComponent>, Error>
+ pub fn remove_entity(&mut self, entity_uid: Uid) -> Result<ArchetypeEntity, Error>
{
let Some(archetype_id) = self.entity_archetype_lookup.get(&entity_uid) else {
return Err(Error::EntityDoesNotExist(entity_uid));
@@ -151,7 +148,7 @@ impl Storage
self.entity_archetype_lookup.remove(&entity_uid);
- Ok(entity.components)
+ Ok(entity)
}
pub fn get_entity_archetype(&self, entity_uid: Uid) -> Option<&Archetype>
@@ -195,10 +192,24 @@ impl Storage
});
}
- let add_edge_archetype_id = archetype_node
+ let add_edge_archetype_id = match archetype_node
.get_or_insert_edges(component_id, ArchetypeEdges::default)
.add
- .unwrap_or_else(|| {
+ {
+ Some(add_edge_id) => {
+ if !self.graph.contains_archetype(add_edge_id) {
+ let (_, add_edge_comp_ids) = self
+ .graph
+ .get_node_by_id(archetype_id)
+ .expect("Archetype should exist")
+ .make_add_edge(component_id);
+
+ self.graph.create_node(add_edge_id, &add_edge_comp_ids);
+ }
+
+ add_edge_id
+ }
+ None => {
let archetype_node = self
.graph
.get_node_by_id_mut(archetype_id)
@@ -217,7 +228,8 @@ impl Storage
}
add_edge_id
- });
+ }
+ };
{
let add_edge_archetype_node = self
@@ -247,13 +259,10 @@ impl Storage
.expect("Add edge archetype should exist")
.archetype_mut();
- let component_index = add_edge_archetype
- .get_index_for_component(component_id)
- .expect("Archetype should have index for component");
-
- entity.components.insert(
- component_index,
- EntityComponent::new(component_id, component),
+ entity.insert_component(
+ component_id,
+ ArchetypeEntityComponent::new(component),
+ add_edge_archetype,
);
add_edge_archetype.push_entity(entity);
@@ -326,14 +335,7 @@ impl Storage
.remove_entity(entity_uid)
.expect("Entity should exist in archetype");
- let (comp_to_remove_index, _) = entity
- .components
- .iter()
- .enumerate()
- .find(|(_, comp)| comp.id == component_id)
- .expect("Entity should contain component");
-
- entity.components.remove(comp_to_remove_index);
+ entity.remove_component(component_id, archetype_node.archetype());
self.graph
.get_node_by_id_mut(remove_edge_id)
diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs
index f6f8132..5306cf9 100644
--- a/ecs/src/component/storage/archetype.rs
+++ b/ecs/src/component/storage/archetype.rs
@@ -3,16 +3,16 @@ use std::slice::Iter as SliceIter;
use hashbrown::HashMap;
-use crate::component::Metadata as ComponentMetadata;
+use crate::component::{Component, Metadata as ComponentMetadata};
+use crate::lock::Lock;
use crate::uid::{Kind as UidKind, Uid};
use crate::util::HashMapExt;
-use crate::EntityComponent;
#[derive(Debug)]
pub struct Archetype
{
id: Id,
- entities: Vec<ArchetypeEntity>,
+ entities: Vec<Entity>,
entity_index_lookup: HashMap<Uid, usize>,
component_index_lookup: HashMap<Uid, usize>,
component_ids: Vec<Uid>,
@@ -53,7 +53,7 @@ impl Archetype
.keys_is_subset(&other.component_index_lookup)
}
- pub fn get_entity_by_id(&self, entity_uid: Uid) -> Option<&ArchetypeEntity>
+ pub fn get_entity_by_id(&self, entity_uid: Uid) -> Option<&Entity>
{
let index = *self.entity_index_lookup.get(&entity_uid)?;
@@ -64,7 +64,7 @@ impl Archetype
}))
}
- pub fn push_entity(&mut self, entity: ArchetypeEntity)
+ pub fn push_entity(&mut self, entity: Entity)
{
self.entity_index_lookup
.insert(entity.uid, self.entities.len());
@@ -72,7 +72,7 @@ impl Archetype
self.entities.push(entity);
}
- pub fn remove_entity(&mut self, entity_uid: Uid) -> Option<ArchetypeEntity>
+ pub fn remove_entity(&mut self, entity_uid: Uid) -> Option<Entity>
{
//debug_assert_eq!(entity_uid.kind(), UidKind::Entity);
@@ -142,12 +142,12 @@ impl Archetype
#[derive(Debug)]
pub struct EntityIter<'archetype>
{
- iter: SliceIter<'archetype, ArchetypeEntity>,
+ iter: SliceIter<'archetype, Entity>,
}
impl<'archetype> Iterator for EntityIter<'archetype>
{
- type Item = &'archetype ArchetypeEntity;
+ type Item = &'archetype Entity;
fn next(&mut self) -> Option<Self::Item>
{
@@ -156,10 +156,82 @@ impl<'archetype> Iterator for EntityIter<'archetype>
}
#[derive(Debug)]
-pub struct ArchetypeEntity
+pub struct Entity
{
- pub uid: Uid,
- pub components: Vec<EntityComponent>,
+ uid: Uid,
+ components: Vec<EntityComponent>,
+}
+
+impl Entity
+{
+ pub fn new(uid: Uid, components: impl IntoIterator<Item = EntityComponent>) -> Self
+ {
+ Self {
+ uid,
+ components: components.into_iter().collect(),
+ }
+ }
+
+ pub fn uid(&self) -> Uid
+ {
+ self.uid
+ }
+
+ pub fn components(&self) -> &[EntityComponent]
+ {
+ &self.components
+ }
+
+ pub fn remove_component(&mut self, component_id: Uid, archetype: &Archetype)
+ {
+ let index = archetype
+ .get_index_for_component(component_id)
+ .expect("Archetype should contain component");
+
+ self.components.remove(index);
+ }
+
+ pub fn insert_component(
+ &mut self,
+ component_id: Uid,
+ component: EntityComponent,
+ archetype: &Archetype,
+ )
+ {
+ let index = archetype
+ .get_index_for_component(component_id)
+ .expect("Archetype should contain component");
+
+ self.components.insert(index, component);
+ }
+}
+
+#[derive(Debug)]
+pub struct EntityComponent
+{
+ name: &'static str,
+ component: Lock<Box<dyn Component>>,
+}
+
+impl EntityComponent
+{
+ pub fn new(component: Box<dyn Component>) -> Self
+ {
+ Self {
+ name: component.type_name(),
+ component: Lock::new(component),
+ }
+ }
+
+ pub fn name(&self) -> &str
+ {
+ self.name
+ }
+
+ pub fn component(&self) -> &Lock<Box<dyn Component>>
+ {
+ &self.component
+ }
}
/// Archetype ID.
diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs
index 85e7461..a43f9ce 100644
--- a/ecs/src/entity.rs
+++ b/ecs/src/entity.rs
@@ -1,8 +1,8 @@
use linkme::distributed_slice;
-use crate::component::storage::archetype::{Archetype, ArchetypeEntity};
+use crate::component::storage::archetype::{Archetype, Entity as ArchetypeEntity};
use crate::uid::Uid;
-use crate::{EntityComponent, World};
+use crate::{EntityComponentRef, World};
/// A handle to a entity.
pub struct Handle<'a>
@@ -18,16 +18,18 @@ impl<'a> Handle<'a>
#[must_use]
pub fn uid(&self) -> Uid
{
- self.entity.uid
+ self.entity.uid()
}
#[inline]
#[must_use]
- pub fn get_component(&self, component_uid: Uid) -> Option<&'a EntityComponent>
+ pub fn get_component(&self, component_uid: Uid) -> Option<EntityComponentRef<'a>>
{
let index = self.archetype.get_index_for_component(component_uid)?;
- Some(self.entity.components.get(index).unwrap())
+ Some(EntityComponentRef::new(
+ self.entity.components().get(index).unwrap(),
+ ))
}
pub(crate) fn new(archetype: &'a Archetype, entity: &'a ArchetypeEntity) -> Self
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index 3adc415..3caaa6b 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -10,6 +10,7 @@ use std::sync::Arc;
use hashbrown::HashMap;
use crate::actions::Action;
+use crate::component::storage::archetype::EntityComponent as ArchetypeEntityComponent;
use crate::component::storage::Storage as ComponentStorage;
use crate::component::{Component, Sequence as ComponentSequence};
use crate::entity::CREATE_STATIC_ENTITIES;
@@ -20,7 +21,7 @@ use crate::phase::{Phase, START as START_PHASE};
use crate::query::flexible::Query as FlexibleQuery;
use crate::query::term::Without;
use crate::query::{
- ComponentIter,
+ Iter as QueryIter,
TermWithFieldTuple as QueryTermWithFieldTuple,
TermWithoutFieldTuple as QueryTermWithoutFieldTuple,
Terms as QueryTerms,
@@ -467,7 +468,7 @@ impl World
{
let mut component_storage_lock = self.lock_component_storage_rw();
- let components = match component_storage_lock.remove_entity(entity_uid) {
+ let removed_entity = match component_storage_lock.remove_entity(entity_uid) {
Ok(components) => components,
Err(err) => {
tracing::error!("Failed to despawn entity: {err}");
@@ -475,16 +476,17 @@ impl World
}
};
- let component_removed_event_uids = components
+ let component_removed_event_uids = removed_entity
+ .components()
.iter()
.map(|component| {
component
- .component
+ .component()
.read_nonblock()
.unwrap_or_else(|_| {
panic!(
"Failed to acquire read-only {} component lock",
- component.name
+ component.name()
)
})
.get_event_uid(ComponentEventKind::Removed)
@@ -534,11 +536,6 @@ impl World
fn emit_event_by_id(&self, event_id: Uid)
{
- //let query = self.flexible_query([
- // ComponentMetadata::of::<SystemComponent>(),
- // ComponentMetadata { id: event_id, is_optional: false },
- //]);
-
let mut query_required_ids = [SystemComponent::id(), event_id];
let query = self.flexible_query(
@@ -547,8 +544,7 @@ impl World
.build(),
);
- for (system,) in ComponentIter::<(&SystemComponent,), _>::new(self, query.iter())
- {
+ for (system,) in QueryIter::<(&SystemComponent,), _>::new(self, query.iter()) {
unsafe {
system.system.run(self);
}
@@ -603,23 +599,21 @@ pub struct WorldData
}
#[derive(Debug)]
-#[non_exhaustive]
-pub struct EntityComponent
+pub struct EntityComponentRef<'a>
{
- pub id: Uid,
- pub name: &'static str,
- pub component: Lock<Box<dyn Component>>,
+ comp: &'a ArchetypeEntityComponent,
}
-impl EntityComponent
+impl<'a> EntityComponentRef<'a>
{
- pub fn new(id: Uid, component: Box<dyn Component>) -> Self
+ pub fn component(&self) -> &'a Lock<Box<dyn Component>>
{
- Self {
- id,
- name: component.type_name(),
- component: Lock::new(component),
- }
+ self.comp.component()
+ }
+
+ fn new(comp: &'a ArchetypeEntityComponent) -> Self
+ {
+ Self { comp }
}
}
diff --git a/ecs/src/lock.rs b/ecs/src/lock.rs
index 1ce13fc..d6ed40e 100644
--- a/ecs/src/lock.rs
+++ b/ecs/src/lock.rs
@@ -1,4 +1,4 @@
-use std::mem::{forget, transmute};
+use std::mem::forget;
use std::ops::{Deref, DerefMut};
use parking_lot::{
@@ -101,17 +101,6 @@ where
inner: RwLockReadGuard::map(inner, func),
}
}
-
- /// Converts the `ReadGuard` to a `ReadGuard` with a possibly longer lifetime.
- ///
- /// # Safety
- /// The returned `ReadGuard` must **NOT** be used for longer than the original
- /// lifetime.
- #[must_use]
- pub unsafe fn upgrade_lifetime<'new>(self) -> ReadGuard<'new, Value>
- {
- unsafe { transmute(self) }
- }
}
impl<Value> Deref for ReadGuard<'_, Value>
diff --git a/ecs/src/query.rs b/ecs/src/query.rs
index 668c573..d7d2d1c 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -36,11 +36,11 @@ where
#[must_use]
pub fn iter<'query>(
&'query self,
- ) -> ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>
+ ) -> Iter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>
{
tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>());
- ComponentIter {
+ Iter {
world: self.world,
iter: self.inner.iter(),
comps_pd: PhantomData,
@@ -48,7 +48,7 @@ where
}
/// Iterates over the entities matching this query, the iterator item being the entity
- /// [`Uid`] and the entity components.
+ /// [`Uid`] and the matching entity components.
#[must_use]
pub fn iter_with_euids<'query>(
&'query self,
@@ -67,18 +67,18 @@ where
/// `func`.
///
/// This function exists so that a custom [`EntityHandle`] iterator can be given to
- /// [`ComponentIter`] without giving the user access to a reference to the [`World`].
+ /// [`Iter`] without giving the user access to a reference to the [`World`].
#[must_use]
pub fn iter_with<'query, OutIter>(
&'query self,
func: impl FnOnce(FlexibleQueryIter<'query>) -> OutIter,
- ) -> ComponentIter<'query, 'world, FieldTerms, OutIter>
+ ) -> Iter<'query, 'world, FieldTerms, OutIter>
where
OutIter: Iterator<Item = EntityHandle<'query>>,
{
tracing::trace!("Searching for {}", std::any::type_name::<FieldTerms>());
- ComponentIter {
+ Iter {
world: self.world,
iter: func(self.inner.iter()),
comps_pd: PhantomData,
@@ -113,7 +113,7 @@ where
FieldTerms: TermWithFieldTuple + 'world,
FieldlessTerms: TermWithoutFieldTuple,
{
- type IntoIter = ComponentIter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>;
+ type IntoIter = Iter<'query, 'world, FieldTerms, FlexibleQueryIter<'query>>;
type Item = FieldTerms::Fields<'query>;
fn into_iter(self) -> Self::IntoIter
@@ -301,7 +301,7 @@ impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT
Self::Field::from_locked_optional_component(
entity_handle
.get_component(ComponentRefT::Component::id())
- .map(|component| &component.component),
+ .map(|component| component.component()),
world,
)
.unwrap_or_else(|err| {
@@ -330,7 +330,7 @@ pub trait TermWithFieldTuple
) -> Self::Fields<'component>;
}
-pub struct ComponentIter<'query, 'world, FieldTerms, EntityHandleIter>
+pub struct Iter<'query, 'world, FieldTerms, EntityHandleIter>
where
FieldTerms: TermWithFieldTuple + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
@@ -341,7 +341,7 @@ where
}
impl<'query, 'world, FieldTerms, EntityHandleIter>
- ComponentIter<'query, 'world, FieldTerms, EntityHandleIter>
+ Iter<'query, 'world, FieldTerms, EntityHandleIter>
where
FieldTerms: TermWithFieldTuple + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
@@ -360,7 +360,7 @@ where
}
impl<'query, 'world, FieldTerms, EntityHandleIter> Iterator
- for ComponentIter<'query, 'world, FieldTerms, EntityHandleIter>
+ for Iter<'query, 'world, FieldTerms, EntityHandleIter>
where
FieldTerms: TermWithFieldTuple + 'world,
EntityHandleIter: Iterator<Item = EntityHandle<'query>>,
diff --git a/ecs/src/relationship.rs b/ecs/src/relationship.rs
index a0ccf4d..45fa265 100644
--- a/ecs/src/relationship.rs
+++ b/ecs/src/relationship.rs
@@ -7,19 +7,18 @@ use crate::component::storage::Storage as ComponentStorage;
use crate::component::{
Component,
FromLockedOptional as FromLockedOptionalComponent,
- FromOptional as FromOptionalComponent,
- FromOptionalMut as FromOptionalMutComponent,
+ Handle as ComponentHandle,
+ HandleMut as ComponentHandleMut,
};
-use crate::lock::{Error as LockError, Lock, ReadGuard, WriteGuard};
-use crate::system::{ComponentRef, ComponentRefMut};
+use crate::lock::{Error as LockError, Lock, ReadGuard};
use crate::uid::{Kind as UidKind, Uid};
use crate::World;
/// A relationship to one or more targets.
#[derive(Debug, Component)]
#[component(
- ref_type = Relation<'component, Kind, ComponentT>,
- ref_mut_type = RelationMut<'component, Kind, ComponentT>,
+ handle_type = Relation<'component, Kind, ComponentT>,
+ handle_mut_type = RelationMut<'component, Kind, ComponentT>,
)]
pub struct Relationship<Kind, ComponentT: Component>
where
@@ -67,27 +66,26 @@ where
Kind: 'static,
ComponentT: Component,
{
- component_storage_lock: ReadGuard<'static, ComponentStorage>,
- relationship_comp: ComponentRefMut<'rel_comp, Relationship<Kind, ComponentT>>,
+ component_storage_lock: ReadGuard<'rel_comp, ComponentStorage>,
+ relationship_comp: ComponentHandleMut<'rel_comp, Relationship<Kind, ComponentT>>,
}
-impl<'rel_comp, Kind, ComponentT> FromOptionalMutComponent<'rel_comp>
+impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
for RelationMut<'rel_comp, Kind, ComponentT>
where
ComponentT: Component,
{
- fn from_optional_mut_component(
- optional_component: Option<
- crate::lock::WriteGuard<'rel_comp, Box<dyn Component>>,
- >,
+ fn from_locked_optional_component(
+ optional_component: Option<&'rel_comp crate::lock::Lock<Box<dyn Component>>>,
world: &'rel_comp World,
- ) -> Self
+ ) -> Result<Self, LockError>
{
+ let relationship_comp_handle_from_locked_opt_comp = ComponentHandleMut::<
+ Relationship<Kind, ComponentT>,
+ >::from_locked_optional_component;
+
let relationship_comp =
- ComponentRefMut::<Relationship<Kind, ComponentT>>::from_optional_mut_component(
- optional_component,
- world,
- );
+ relationship_comp_handle_from_locked_opt_comp(optional_component, world)?;
let component_storage_lock = world
.data
@@ -95,49 +93,14 @@ where
.read_nonblock()
.expect("Failed to aquire read-only component storage lock");
- Self {
+ Ok(Self {
relationship_comp,
- // SAFETY: The component lock is not used for longer than the original
- // lifetime
- component_storage_lock: unsafe { component_storage_lock.upgrade_lifetime() },
- }
- }
-}
-
-impl<'rel_comp, Kind, ComponentT> FromOptionalMutComponent<'rel_comp>
- for Option<RelationMut<'rel_comp, Kind, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_optional_mut_component(
- optional_component: Option<WriteGuard<'rel_comp, Box<dyn Component>>>,
- world: &'rel_comp World,
- ) -> Self
- {
- optional_component.map(|component| {
- RelationMut::from_optional_mut_component(Some(component), world)
+ component_storage_lock,
})
}
}
impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
- for RelationMut<'rel_comp, Kind, ComponentT>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'rel_comp crate::lock::Lock<Box<dyn Component>>>,
- world: &'rel_comp World,
- ) -> Result<Self, LockError>
- {
- Ok(Self::from_optional_mut_component(
- optional_component.map(Lock::write_nonblock).transpose()?,
- world,
- ))
- }
-}
-
-impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
for Option<RelationMut<'rel_comp, Kind, ComponentT>>
where
ComponentT: Component,
@@ -165,7 +128,7 @@ where
/// Will panic if the entity does not exist in the archetype it belongs to. This
/// should hopefully never happend.
#[must_use]
- pub fn get(&self, index: usize) -> Option<ComponentRefMut<'_, ComponentT>>
+ pub fn get(&self, index: usize) -> Option<ComponentHandleMut<'_, ComponentT>>
{
let target = self.get_target(index)?;
@@ -177,11 +140,11 @@ where
let component_index = archetype.get_index_for_component(ComponentT::id())?;
- let component = ComponentRefMut::new(
+ let component = ComponentHandleMut::new(
entity
- .components
+ .components()
.get(component_index)?
- .component
+ .component()
.write_nonblock()
.unwrap_or_else(|_| {
panic!(
@@ -276,7 +239,7 @@ where
ComponentT: Component,
{
type IntoIter = TargetComponentIterMut<'relationship, 'rel_comp, Kind, ComponentT>;
- type Item = ComponentRefMut<'rel_comp, ComponentT>;
+ type Item = ComponentHandleMut<'rel_comp, ComponentT>;
fn into_iter(self) -> Self::IntoIter
{
@@ -301,7 +264,7 @@ where
Kind: 'static,
ComponentT: Component,
{
- type Item = ComponentRefMut<'rel_comp, ComponentT>;
+ type Item = ComponentHandleMut<'rel_comp, ComponentT>;
fn next(&mut self) -> Option<Self::Item>
{
@@ -325,25 +288,26 @@ where
Kind: 'static,
ComponentT: Component,
{
- component_storage_lock: ReadGuard<'static, ComponentStorage>,
- relationship_comp: ComponentRef<'rel_comp, Relationship<Kind, ComponentT>>,
+ component_storage_lock: ReadGuard<'rel_comp, ComponentStorage>,
+ relationship_comp: ComponentHandle<'rel_comp, Relationship<Kind, ComponentT>>,
}
-impl<'rel_comp, Kind, ComponentT> FromOptionalComponent<'rel_comp>
+impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
for Relation<'rel_comp, Kind, ComponentT>
where
ComponentT: Component,
{
- fn from_optional_component(
- optional_component: Option<ReadGuard<'rel_comp, Box<dyn Component>>>,
+ fn from_locked_optional_component(
+ optional_component: Option<&'rel_comp Lock<Box<dyn Component>>>,
world: &'rel_comp World,
- ) -> Self
+ ) -> Result<Self, LockError>
{
+ let relationship_comp_handle_from_locked_opt_comp = ComponentHandle::<
+ Relationship<Kind, ComponentT>,
+ >::from_locked_optional_component;
+
let relationship_comp =
- ComponentRef::<Relationship<Kind, ComponentT>>::from_optional_component(
- optional_component,
- world,
- );
+ relationship_comp_handle_from_locked_opt_comp(optional_component, world)?;
let component_storage_lock = world
.data
@@ -351,44 +315,10 @@ where
.read_nonblock()
.expect("Failed to aquire read-only component storage lock");
- Self {
+ Ok(Self {
relationship_comp,
- // SAFETY: The component lock is not used for longer than the original
- // lifetime
- component_storage_lock: unsafe { component_storage_lock.upgrade_lifetime() },
- }
- }
-}
-
-impl<'rel_comp, Kind, ComponentT> FromOptionalComponent<'rel_comp>
- for Option<Relation<'rel_comp, Kind, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_optional_component(
- optional_component: Option<ReadGuard<'rel_comp, Box<dyn Component>>>,
- world: &'rel_comp World,
- ) -> Self
- {
- optional_component
- .map(|component| Relation::from_optional_component(Some(component), world))
- }
-}
-
-impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
- for Relation<'rel_comp, Kind, ComponentT>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'rel_comp Lock<Box<dyn Component>>>,
- world: &'rel_comp World,
- ) -> Result<Self, LockError>
- {
- Ok(Self::from_optional_component(
- optional_component.map(Lock::read_nonblock).transpose()?,
- world,
- ))
+ component_storage_lock,
+ })
}
}
@@ -420,7 +350,7 @@ where
/// Will panic if the entity does not exist in the archetype it belongs to. This
/// should hopefully never happend.
#[must_use]
- pub fn get(&self, index: usize) -> Option<ComponentRef<'_, ComponentT>>
+ pub fn get(&self, index: usize) -> Option<ComponentHandle<'_, ComponentT>>
{
let target = self.get_target(index)?;
@@ -432,11 +362,11 @@ where
let component_index = archetype.get_index_for_component(ComponentT::id())?;
- let component = ComponentRef::new(
+ let component = ComponentHandle::new(
entity
- .components
+ .components()
.get(component_index)?
- .component
+ .component()
.read_nonblock()
.unwrap_or_else(|_| {
panic!(
@@ -490,7 +420,7 @@ where
ComponentT: Component,
{
type IntoIter = TargetComponentIter<'relationship, 'rel_comp, Kind, ComponentT>;
- type Item = ComponentRef<'rel_comp, ComponentT>;
+ type Item = ComponentHandle<'rel_comp, ComponentT>;
fn into_iter(self) -> Self::IntoIter
{
@@ -515,7 +445,7 @@ where
Kind: 'static,
ComponentT: Component,
{
- type Item = ComponentRef<'rel_comp, ComponentT>;
+ type Item = ComponentHandle<'rel_comp, ComponentT>;
fn next(&mut self) -> Option<Self::Item>
{
diff --git a/ecs/src/system.rs b/ecs/src/system.rs
index 40eba8d..603c015 100644
--- a/ecs/src/system.rs
+++ b/ecs/src/system.rs
@@ -1,26 +1,11 @@
-use std::any::{type_name, Any};
+use std::any::Any;
use std::convert::Infallible;
use std::fmt::Debug;
-use std::marker::PhantomData;
-use std::ops::{Deref, DerefMut};
use ecs_macros::Component;
use seq_macro::seq;
-use crate::component::{
- Component,
- FromLockedOptional as FromLockedOptionalComponent,
- FromOptional as FromOptionalComponent,
- FromOptionalMut as FromOptionalMutComponent,
-};
-use crate::lock::{
- Error as LockError,
- Lock,
- MappedReadGuard,
- MappedWriteGuard,
- ReadGuard,
- WriteGuard,
-};
+use crate::component::{Component, HandleMut as ComponentHandleMut};
use crate::tuple::{ReduceElement as TupleReduceElement, Tuple};
use crate::World;
@@ -41,7 +26,7 @@ pub trait System<'world, Impl>: 'static
fn get_local_component_mut<LocalComponent: Component>(
&self,
- ) -> Option<ComponentRefMut<LocalComponent>>;
+ ) -> Option<ComponentHandleMut<LocalComponent>>;
fn set_local_component<LocalComponent: Component>(
&mut self,
@@ -100,7 +85,7 @@ macro_rules! impl_system {
fn get_local_component_mut<LocalComponent: Component>(
&self,
- ) -> Option<ComponentRefMut<LocalComponent>>
+ ) -> Option<ComponentHandleMut<LocalComponent>>
{
panic!("System does not have any local components");
}
@@ -194,211 +179,6 @@ impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for ()
type Return = Accumulator;
}
-#[derive(Debug)]
-pub struct ComponentRefMut<'a, ComponentT: Component>
-{
- inner: MappedWriteGuard<'a, ComponentT>,
- _ph: PhantomData<ComponentT>,
-}
-
-impl<'a, ComponentT: Component> ComponentRefMut<'a, ComponentT>
-{
- pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self
- {
- Self {
- inner: inner.map(|component| {
- let component_type_name = component.type_name();
-
- component.downcast_mut::<ComponentT>().unwrap_or_else(|| {
- panic!(
- "Cannot downcast component {component_type_name} to type {}",
- type_name::<ComponentT>()
- );
- })
- }),
- _ph: PhantomData,
- }
- }
-}
-
-impl<'component, ComponentT: Component> FromOptionalMutComponent<'component>
- for ComponentRefMut<'component, ComponentT>
-{
- fn from_optional_mut_component(
- inner: Option<WriteGuard<'component, Box<dyn Component>>>,
- _world: &'component World,
- ) -> Self
- {
- Self::new(inner.unwrap_or_else(|| {
- panic!(
- "Component {} was not found in entity",
- type_name::<ComponentT>()
- );
- }))
- }
-}
-
-impl<'component, ComponentT: Component> FromLockedOptionalComponent<'component>
- for ComponentRefMut<'component, ComponentT>
-{
- fn from_locked_optional_component(
- optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>,
- world: &'component World,
- ) -> Result<Self, LockError>
- {
- Ok(Self::from_optional_mut_component(
- optional_component.map(Lock::write_nonblock).transpose()?,
- world,
- ))
- }
-}
-
-impl<'comp, ComponentT> FromOptionalMutComponent<'comp>
- for Option<ComponentRefMut<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_optional_mut_component(
- optional_component: Option<WriteGuard<'comp, Box<dyn Component>>>,
- _world: &'comp World,
- ) -> Self
- {
- optional_component.map(|component| ComponentRefMut::new(component))
- }
-}
-
-impl<'comp, ComponentT> FromLockedOptionalComponent<'comp>
- for Option<ComponentRefMut<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
- _world: &'comp World,
- ) -> Result<Self, LockError>
- {
- optional_component
- .map(|lock| Ok(ComponentRefMut::new(lock.write_nonblock()?)))
- .transpose()
- }
-}
-
-impl<ComponentT: Component> Deref for ComponentRefMut<'_, ComponentT>
-{
- type Target = ComponentT;
-
- fn deref(&self) -> &Self::Target
- {
- &self.inner
- }
-}
-
-impl<ComponentT: Component> DerefMut for ComponentRefMut<'_, ComponentT>
-{
- fn deref_mut(&mut self) -> &mut Self::Target
- {
- &mut self.inner
- }
-}
-
-#[derive(Debug)]
-pub struct ComponentRef<'a, ComponentT: Component>
-{
- inner: MappedReadGuard<'a, ComponentT>,
- _ph: PhantomData<ComponentT>,
-}
-
-impl<'a, ComponentT: Component> ComponentRef<'a, ComponentT>
-{
- pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self
- {
- Self {
- inner: inner.map(|component| {
- component.downcast_ref::<ComponentT>().unwrap_or_else(|| {
- panic!(
- "Cannot downcast component {} to type {}",
- component.type_name(),
- type_name::<ComponentT>()
- );
- })
- }),
- _ph: PhantomData,
- }
- }
-}
-
-impl<'component, ComponentT: Component> FromOptionalComponent<'component>
- for ComponentRef<'component, ComponentT>
-{
- fn from_optional_component(
- inner: Option<ReadGuard<'component, Box<dyn Component>>>,
- _world: &'component World,
- ) -> Self
- {
- Self::new(inner.unwrap_or_else(|| {
- panic!(
- "Component {} was not found in entity",
- type_name::<ComponentT>()
- );
- }))
- }
-}
-
-impl<'component, ComponentT: Component> FromLockedOptionalComponent<'component>
- for ComponentRef<'component, ComponentT>
-{
- fn from_locked_optional_component(
- optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>,
- world: &'component World,
- ) -> Result<Self, LockError>
- {
- Ok(Self::from_optional_component(
- optional_component.map(Lock::read_nonblock).transpose()?,
- world,
- ))
- }
-}
-
-impl<'comp, ComponentT> FromOptionalComponent<'comp>
- for Option<ComponentRef<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_optional_component(
- optional_component: Option<ReadGuard<'comp, Box<dyn Component>>>,
- _world: &'comp World,
- ) -> Self
- {
- optional_component.map(|component| ComponentRef::new(component))
- }
-}
-
-impl<'comp, ComponentT> FromLockedOptionalComponent<'comp>
- for Option<ComponentRef<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
- _world: &'comp World,
- ) -> Result<Self, LockError>
- {
- optional_component
- .map(|lock| Ok(ComponentRef::new(lock.read_nonblock()?)))
- .transpose()
- }
-}
-
-impl<ComponentT: Component> Deref for ComponentRef<'_, ComponentT>
-{
- type Target = ComponentT;
-
- fn deref(&self) -> &Self::Target
- {
- &self.inner
- }
-}
-
#[derive(Debug, Component)]
pub(crate) struct SystemComponent
{
diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs
index 80ac346..9d911ee 100644
--- a/ecs/src/system/stateful.rs
+++ b/ecs/src/system/stateful.rs
@@ -4,10 +4,9 @@ use std::panic::{RefUnwindSafe, UnwindSafe};
use hashbrown::HashMap;
use seq_macro::seq;
-use crate::component::Component;
+use crate::component::{Component, HandleMut as ComponentHandleMut};
use crate::lock::Lock;
use crate::system::{
- ComponentRefMut,
Into as IntoSystem,
Param,
ParamWithInputFilter,
@@ -110,14 +109,14 @@ macro_rules! impl_system {
fn get_local_component_mut<LocalComponent: Component>(
&self,
- ) -> Option<ComponentRefMut<LocalComponent>>
+ ) -> Option<ComponentHandleMut<LocalComponent>>
{
let local_component = self.local_components
.get(&LocalComponent::id())?
.write_nonblock()
.expect("Failed to aquire read-write local component lock");
- Some(ComponentRefMut::new(local_component))
+ Some(ComponentHandleMut::new(local_component))
}
fn set_local_component<LocalComponent: Component>(