summaryrefslogtreecommitdiff
path: root/ecs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs')
-rw-r--r--ecs/Cargo.toml4
-rw-r--r--ecs/src/component/storage.rs203
-rw-r--r--ecs/src/component/storage/archetype.rs94
-rw-r--r--ecs/src/component/storage/graph.rs12
-rw-r--r--ecs/src/entity.rs38
-rw-r--r--ecs/src/lib.rs95
-rw-r--r--ecs/src/query.rs29
-rw-r--r--ecs/src/query/flexible.rs34
-rw-r--r--ecs/src/relationship.rs8
9 files changed, 408 insertions, 109 deletions
diff --git a/ecs/Cargo.toml b/ecs/Cargo.toml
index 4945171..cf35a74 100644
--- a/ecs/Cargo.toml
+++ b/ecs/Cargo.toml
@@ -3,6 +3,9 @@ name = "ecs"
version = "0.1.0"
edition = "2021"
+[features]
+vizoxide = ["dep:vizoxide"]
+
[dependencies]
seq-macro = "0.3.5"
paste = "1.0.14"
@@ -13,6 +16,7 @@ hashbrown = "0.15.2"
parking_lot = "0.12.3"
ecs-macros = { path = "../ecs-macros" }
util-macros = { path = "../util-macros" }
+vizoxide = { version = "1.0.5", optional = true }
[dev-dependencies.criterion]
version = "0.5.1"
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index 4b2b6d8..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)
@@ -421,6 +408,176 @@ impl TypeName for Storage
}
}
+#[cfg(feature = "vizoxide")]
+impl Storage
+{
+ pub fn create_vizoxide_archetype_graph(
+ &self,
+ graph_name: impl AsRef<str>,
+ params: VizoxideArchetypeGraphParams,
+ ) -> Result<vizoxide::Graph, vizoxide::GraphvizError>
+ {
+ let viz_graph = vizoxide::Graph::builder(graph_name.as_ref())
+ .strict(true)
+ .directed(true)
+ .build()?;
+
+ let mut viz_node_lookup = HashMap::new();
+
+ for node in self.graph.iter_nodes() {
+ let id = node.archetype().id();
+
+ if !viz_node_lookup.contains_key(&id) {
+ let node = self.graph.get_node_by_id(id).unwrap();
+
+ let viz_node = (params.create_node_cb)(
+ node.archetype(),
+ ArchetypeMetadata { is_imaginary: false },
+ viz_graph.create_node(&(params.create_node_name)(
+ node.archetype(),
+ ArchetypeMetadata { is_imaginary: false },
+ )),
+ )
+ .build()?;
+
+ viz_node_lookup.insert(id, viz_node);
+ }
+
+ for (edge_comp_id, edges) in node.iter_edges() {
+ if let Some(add_edge) = edges.add {
+ if !viz_node_lookup.contains_key(&add_edge) {
+ let viz_node = self.create_vizoxide_archetype_graph_edge_node(
+ &viz_graph,
+ node,
+ add_edge,
+ *edge_comp_id,
+ &params,
+ )?;
+
+ viz_node_lookup.insert(add_edge, viz_node);
+ }
+
+ (params.create_edge_cb)(
+ node.archetype(),
+ *edge_comp_id,
+ VizoxideArchetypeGraphEdgeKind::Add,
+ viz_graph.create_edge(
+ viz_node_lookup.get(&id).unwrap(),
+ viz_node_lookup.get(&add_edge).unwrap(),
+ Some(&format!("Add {}", edge_comp_id.id())),
+ ),
+ )
+ .build()?;
+ }
+
+ if let Some(remove_edge) = edges.remove {
+ if !viz_node_lookup.contains_key(&remove_edge) {
+ let viz_node = self.create_vizoxide_archetype_graph_edge_node(
+ &viz_graph,
+ node,
+ remove_edge,
+ *edge_comp_id,
+ &params,
+ )?;
+
+ viz_node_lookup.insert(remove_edge, viz_node);
+ }
+
+ (params.create_edge_cb)(
+ node.archetype(),
+ *edge_comp_id,
+ VizoxideArchetypeGraphEdgeKind::Remove,
+ viz_graph.create_edge(
+ viz_node_lookup.get(&id).unwrap(),
+ viz_node_lookup.get(&remove_edge).unwrap(),
+ Some(&format!("Remove {}", edge_comp_id.id())),
+ ),
+ )
+ .build()?;
+ }
+ }
+ }
+
+ drop(viz_node_lookup);
+
+ Ok(viz_graph)
+ }
+
+ fn create_vizoxide_archetype_graph_edge_node<'vizoxide_graph>(
+ &self,
+ viz_graph: &'vizoxide_graph vizoxide::Graph,
+ node: &graph::ArchetypeNode,
+ edge_id: ArchetypeId,
+ edge_comp_id: Uid,
+ params: &VizoxideArchetypeGraphParams,
+ ) -> Result<vizoxide::Node<'vizoxide_graph>, vizoxide::GraphvizError>
+ {
+ match self.graph.get_node_by_id(edge_id) {
+ Some(edge_node) => (params.create_node_cb)(
+ edge_node.archetype(),
+ ArchetypeMetadata { is_imaginary: false },
+ viz_graph.create_node(&(params.create_node_name)(
+ edge_node.archetype(),
+ ArchetypeMetadata { is_imaginary: false },
+ )),
+ )
+ .build(),
+ None => {
+ let mut comp_ids =
+ node.archetype().component_ids_sorted().collect::<Vec<_>>();
+
+ let insert_index = comp_ids.partition_point(|cid| *cid <= edge_comp_id);
+
+ comp_ids.insert(insert_index, edge_comp_id);
+
+ let imaginary_edge_archetype = Archetype::new(edge_id, comp_ids);
+
+ (params.create_node_cb)(
+ &imaginary_edge_archetype,
+ ArchetypeMetadata { is_imaginary: true },
+ viz_graph.create_node(&(params.create_node_name)(
+ &imaginary_edge_archetype,
+ ArchetypeMetadata { is_imaginary: true },
+ )),
+ )
+ .build()
+ }
+ }
+ }
+}
+
+#[cfg(feature = "vizoxide")]
+pub struct VizoxideArchetypeGraphParams
+{
+ pub create_node_name: fn(&Archetype, ArchetypeMetadata) -> std::borrow::Cow<'_, str>,
+ pub create_node_cb: for<'storage, 'graph> fn(
+ &'storage Archetype,
+ ArchetypeMetadata,
+ vizoxide::NodeBuilder<'graph>,
+ ) -> vizoxide::NodeBuilder<'graph>,
+ pub create_edge_cb: for<'storage, 'graph> fn(
+ &'storage Archetype,
+ Uid,
+ VizoxideArchetypeGraphEdgeKind,
+ vizoxide::EdgeBuilder<'graph>,
+ ) -> vizoxide::EdgeBuilder<'graph>,
+}
+
+#[cfg(feature = "vizoxide")]
+#[derive(Debug, Clone)]
+pub struct ArchetypeMetadata
+{
+ pub is_imaginary: bool,
+}
+
+#[cfg(feature = "vizoxide")]
+#[derive(Debug, Clone, Copy)]
+pub enum VizoxideArchetypeGraphEdgeKind
+{
+ Add,
+ Remove,
+}
+
#[derive(Debug)]
pub struct ArchetypeRefIter<'storage, 'search_terms>
{
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/component/storage/graph.rs b/ecs/src/component/storage/graph.rs
index a221877..11160e7 100644
--- a/ecs/src/component/storage/graph.rs
+++ b/ecs/src/component/storage/graph.rs
@@ -71,6 +71,12 @@ impl Graph
}))
}
+ #[cfg(feature = "vizoxide")]
+ pub fn iter_nodes(&self) -> impl Iterator<Item = &ArchetypeNode>
+ {
+ self.nodes.iter()
+ }
+
pub fn dfs_archetype_add_edges(
&self,
archetype_id: ArchetypeId,
@@ -233,6 +239,12 @@ impl ArchetypeNode
self.edges.entry(component_id).or_insert_with(insert_fn)
}
+ #[cfg(feature = "vizoxide")]
+ pub fn iter_edges(&self) -> impl Iterator<Item = (&Uid, &ArchetypeEdges)>
+ {
+ self.edges.iter()
+ }
+
pub fn get_edges_mut(&mut self, component_id: Uid) -> Option<&mut ArchetypeEdges>
{
debug_assert_eq!(component_id.kind(), UidKind::Component);
diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs
index 3de9cd5..a43f9ce 100644
--- a/ecs/src/entity.rs
+++ b/ecs/src/entity.rs
@@ -1,6 +1,42 @@
use linkme::distributed_slice;
-use crate::World;
+use crate::component::storage::archetype::{Archetype, Entity as ArchetypeEntity};
+use crate::uid::Uid;
+use crate::{EntityComponentRef, World};
+
+/// A handle to a entity.
+pub struct Handle<'a>
+{
+ archetype: &'a Archetype,
+ entity: &'a ArchetypeEntity,
+}
+
+impl<'a> Handle<'a>
+{
+ /// Returns the [`Uid`] of this entity.
+ #[inline]
+ #[must_use]
+ pub fn uid(&self) -> Uid
+ {
+ self.entity.uid()
+ }
+
+ #[inline]
+ #[must_use]
+ pub fn get_component(&self, component_uid: Uid) -> Option<EntityComponentRef<'a>>
+ {
+ let index = self.archetype.get_index_for_component(component_uid)?;
+
+ Some(EntityComponentRef::new(
+ self.entity.components().get(index).unwrap(),
+ ))
+ }
+
+ pub(crate) fn new(archetype: &'a Archetype, entity: &'a ArchetypeEntity) -> Self
+ {
+ Self { archetype, entity }
+ }
+}
#[allow(clippy::module_name_repetitions)]
#[macro_export]
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index 9b787a2..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,
@@ -246,6 +247,59 @@ impl World
while let StepResult::Continue = self.step() {}
}
+ #[cfg(feature = "vizoxide")]
+ pub fn create_vizoxide_archetype_graph(
+ &self,
+ name: impl AsRef<str>,
+ ) -> Result<vizoxide::Graph, vizoxide::GraphvizError>
+ {
+ use std::borrow::Cow;
+
+ use crate::component::storage::{
+ VizoxideArchetypeGraphEdgeKind,
+ VizoxideArchetypeGraphParams,
+ };
+
+ let component_storage_lock = self
+ .data
+ .component_storage
+ .read_nonblock()
+ .expect("Failed to acquire read-only component storage lock");
+
+ component_storage_lock.create_vizoxide_archetype_graph(
+ name,
+ VizoxideArchetypeGraphParams {
+ create_node_name: |archetype, _| {
+ Cow::Owned(format!(
+ "[{}]",
+ archetype
+ .component_ids_sorted()
+ .into_iter()
+ .map(|comp_id| comp_id.id().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ ))
+ },
+ create_node_cb: |_archetype, archetype_metadata, node_builder| {
+ if archetype_metadata.is_imaginary {
+ return node_builder.attribute("shape", "ellipse");
+ }
+
+ node_builder.attribute("shape", "box")
+ },
+ create_edge_cb: |_, _, edge_kind, edge_builder| {
+ edge_builder.attribute(
+ "color",
+ match edge_kind {
+ VizoxideArchetypeGraphEdgeKind::Add => "green",
+ VizoxideArchetypeGraphEdgeKind::Remove => "red",
+ },
+ )
+ },
+ },
+ )
+ }
+
fn query_and_run_systems(&self, phase_euid: Uid)
{
let system_comps_query =
@@ -414,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}");
@@ -422,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)
@@ -481,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(
@@ -494,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);
}
@@ -550,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 1889e00..d7d2d1c 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -5,11 +5,8 @@ use std::marker::PhantomData;
use seq_macro::seq;
use crate::component::{Component, FromLockedOptional, Ref as ComponentRef};
-use crate::query::flexible::{
- EntityHandle,
- Iter as FlexibleQueryIter,
- Query as FlexibleQuery,
-};
+use crate::entity::Handle as EntityHandle;
+use crate::query::flexible::{Iter as FlexibleQueryIter, Query as FlexibleQuery};
use crate::system::{Param as SystemParam, System};
use crate::uid::Uid;
use crate::util::VecExt;
@@ -39,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,
@@ -51,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,
@@ -70,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,
@@ -116,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
@@ -304,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| {
@@ -333,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>>,
@@ -344,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>>,
@@ -363,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/query/flexible.rs b/ecs/src/query/flexible.rs
index 7d24dc9..652b96f 100644
--- a/ecs/src/query/flexible.rs
+++ b/ecs/src/query/flexible.rs
@@ -1,16 +1,16 @@
//! Low-level querying.
use std::iter::{repeat_n, FlatMap, RepeatN, Zip};
-use crate::component::storage::archetype::{Archetype, ArchetypeEntity, EntityIter};
+use crate::component::storage::archetype::{Archetype, EntityIter};
use crate::component::storage::{
ArchetypeRefIter,
ArchetypeSearchTerms,
Storage as ComponentStorage,
};
+use crate::entity::Handle as EntityHandle;
use crate::lock::ReadGuard;
use crate::query::Terms;
-use crate::uid::Uid;
-use crate::{EntityComponent, World};
+use crate::World;
/// Low-level entity query structure.
#[derive(Debug)]
@@ -68,33 +68,7 @@ impl<'query> Iterator for Iter<'query>
{
let (archetype, entity) = self.iter.next()?;
- Some(EntityHandle { archetype, entity })
- }
-}
-
-pub struct EntityHandle<'query>
-{
- archetype: &'query Archetype,
- entity: &'query ArchetypeEntity,
-}
-
-impl<'query> EntityHandle<'query>
-{
- /// Returns the [`Uid`] of this entity.
- #[inline]
- #[must_use]
- pub fn uid(&self) -> Uid
- {
- self.entity.uid
- }
-
- #[inline]
- #[must_use]
- pub fn get_component(&self, component_uid: Uid) -> Option<&'query EntityComponent>
- {
- let index = self.archetype.get_index_for_component(component_uid)?;
-
- Some(self.entity.components.get(index).unwrap())
+ Some(EntityHandle::new(archetype, entity))
}
}
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!(