summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ecs/src/component/storage.rs33
-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/query.rs22
-rw-r--r--ecs/src/relationship.rs8
6 files changed, 133 insertions, 78 deletions
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index c70e7e7..4a00510 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>
@@ -247,13 +244,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 +320,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/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..e5442c2 100644
--- a/ecs/src/relationship.rs
+++ b/ecs/src/relationship.rs
@@ -179,9 +179,9 @@ where
let component = ComponentRefMut::new(
entity
- .components
+ .components()
.get(component_index)?
- .component
+ .component()
.write_nonblock()
.unwrap_or_else(|_| {
panic!(
@@ -434,9 +434,9 @@ where
let component = ComponentRef::new(
entity
- .components
+ .components()
.get(component_index)?
- .component
+ .component()
.read_nonblock()
.unwrap_or_else(|_| {
panic!(