summaryrefslogtreecommitdiff
path: root/ecs/src/component
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/component')
-rw-r--r--ecs/src/component/local.rs75
-rw-r--r--ecs/src/component/storage.rs86
-rw-r--r--ecs/src/component/storage/archetype.rs85
-rw-r--r--ecs/src/component/storage/graph.rs2
4 files changed, 129 insertions, 119 deletions
diff --git a/ecs/src/component/local.rs b/ecs/src/component/local.rs
index 0f6f641..b19a30b 100644
--- a/ecs/src/component/local.rs
+++ b/ecs/src/component/local.rs
@@ -1,7 +1,17 @@
+use std::any::type_name;
use std::ops::{Deref, DerefMut};
-use crate::component::{Component, HandleMut as ComponentHandleMut};
-use crate::system::{Param as SystemParam, System};
+use ecs_macros::Component;
+
+use crate::component::{
+ Component,
+ HandleMut as ComponentHandleMut,
+ IntoParts as _,
+ Parts as ComponentParts,
+};
+use crate::pair::Pair;
+use crate::system::initializable::Param as InitializableParam;
+use crate::system::{Metadata as SystemMetadata, Param as SystemParam};
use crate::World;
/// Holds a component which is local to a single system.
@@ -17,27 +27,52 @@ where
{
type Input = LocalComponent;
- fn initialize<SystemImpl>(
- system: &mut impl System<'world, SystemImpl>,
- input: Self::Input,
- )
+ fn new(world: &'world World, system_metadata: &SystemMetadata) -> Self
{
- system.set_local_component(input);
- }
+ let Some(system_ent) = world.get_entity(system_metadata.ent_id) else {
+ panic!(
+ "System entity with ID {} does not exist",
+ system_metadata.ent_id
+ );
+ };
- fn new<SystemImpl>(
- system: &'world impl System<'world, SystemImpl>,
- _world: &'world World,
- ) -> Self
- {
- let local_component = system
- .get_local_component_mut::<LocalComponent>()
- .expect("Local component is uninitialized");
+ let Some(local_component) = system_ent.get_with_id_mut::<LocalComponent>(
+ Pair::builder()
+ .relation::<IsLocalComponent>()
+ .target::<LocalComponent>()
+ .build()
+ .id(),
+ ) else {
+ panic!(
+ "Local component {} of system with ID {} is uninitialized",
+ type_name::<LocalComponent>(),
+ system_metadata.ent_id
+ );
+ };
Self { local_component }
}
}
+impl<'world, LocalComponent, SystemT> InitializableParam<'world, SystemT>
+ for Local<'world, LocalComponent>
+where
+ LocalComponent: Component,
+ SystemT: SystemWithLocalComponents,
+ Self: SystemParam<'world, Input = LocalComponent>,
+{
+ fn initialize(system: &mut SystemT, input: Self::Input)
+ {
+ system.add_local_component(
+ Pair::builder()
+ .relation::<IsLocalComponent>()
+ .target_as_data(input)
+ .build()
+ .into_parts(),
+ );
+ }
+}
+
impl<LocalComponent> Deref for Local<'_, LocalComponent>
where
LocalComponent: Component,
@@ -59,3 +94,11 @@ where
&mut self.local_component
}
}
+
+pub trait SystemWithLocalComponents
+{
+ fn add_local_component(&mut self, component_parts: ComponentParts);
+}
+
+#[derive(Component)]
+struct IsLocalComponent;
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index 14f3ea4..a8711c5 100644
--- a/ecs/src/component/storage.rs
+++ b/ecs/src/component/storage.rs
@@ -88,7 +88,7 @@ impl Storage
search_terms: ArchetypeSearchTerms<'search_terms>,
) -> ArchetypeRefIter<'_, 'search_terms>
{
- let archetype_id = ArchetypeId::new(&search_terms.required_components);
+ let archetype_id = ArchetypeId::new(search_terms.required_components);
if search_terms.contains_conflicting() {
return ArchetypeRefIter {
@@ -105,7 +105,12 @@ impl Storage
self.imaginary_archetypes
.borrow_mut()
.push(ImaginaryArchetype {
- id: archetype_id,
+ id: ArchetypeId::new(search_terms.required_components.iter().filter(
+ |required_comp_id| {
+ required_comp_id.kind() != UidKind::Pair
+ || required_comp_id.target_component() != Uid::wildcard()
+ },
+ )),
component_ids: search_terms
.required_components
.iter()
@@ -148,7 +153,7 @@ impl Storage
return Err(Error::EntityAlreadyExists(uid));
}
- let empty_archetype_id = ArchetypeId::from_components_metadata(&[]);
+ let empty_archetype_id = ArchetypeId::new_empty();
let archetype_node = self.graph.get_or_create_node(empty_archetype_id, &[]);
@@ -216,38 +221,35 @@ impl Storage
});
}
- let add_edge_archetype_id = match archetype_node
+ let add_edge_archetype_id = if let Some(add_edge_id) = archetype_node
.get_or_insert_edges(component_id, ArchetypeEdges::default)
.add
{
- 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
+ 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");
+ .expect("Archetype should exist")
+ .make_add_edge(component_id);
- let (add_edge_id, add_edge_comp_ids) =
- archetype_node.make_add_edge(component_id);
+ self.graph.create_node(add_edge_id, &add_edge_comp_ids);
+ }
- if !self.graph.contains_archetype(add_edge_id) {
- self.graph.create_node(add_edge_id, &add_edge_comp_ids);
- }
+ add_edge_id
+ } else {
+ let archetype_node = self
+ .graph
+ .get_node_by_id(archetype_id)
+ .expect("Archetype should exist");
- add_edge_id
+ let (add_edge_id, add_edge_comp_ids) =
+ archetype_node.make_add_edge(component_id);
+
+ if !self.graph.contains_archetype(add_edge_id) {
+ self.graph.create_node(add_edge_id, &add_edge_comp_ids);
}
+
+ add_edge_id
};
let archetype_node = self
@@ -268,7 +270,7 @@ impl Storage
entity.insert_component(
component_id,
- ArchetypeEntityComponent::new(component, component_id, component_name),
+ ArchetypeEntityComponent::new(component, component_name),
add_edge_archetype,
);
@@ -369,9 +371,12 @@ impl Storage
) -> Vec<ArchetypeId>
{
let Some(mut search_iter) =
- self.graph.dfs_archetype_add_edges(ArchetypeId::new(&[]))
+ self.graph.dfs_archetype_add_edges(ArchetypeId::new_empty())
else {
// If the root archetype doesn't exist, no other archetype can exist either
+ //
+ // TODO: The above comment is not true. Cases where imaginary archetypes have
+ // been created should be handled as well
return Vec::new();
};
@@ -592,8 +597,7 @@ pub struct ArchetypeRefIter<'storage, 'search_terms>
search_terms: ArchetypeSearchTerms<'search_terms>,
}
-impl<'component_storage, 'search_terms> Iterator
- for ArchetypeRefIter<'component_storage, 'search_terms>
+impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage, '_>
{
type Item = &'component_storage Archetype;
@@ -638,18 +642,15 @@ impl<'component_storage, 'search_terms> Iterator
let mut add_edge_archetype_comps =
archetype.component_ids_sorted().collect::<Vec<_>>();
- add_edge_archetype_comps.insert_at_partition_point_by_key(
- add_edge_component_id,
- |comp_id| *comp_id,
- );
+ add_edge_archetype_comps
+ .insert_at_part_pt_by_key(add_edge_component_id, |comp_id| {
+ comp_id
+ });
self.storage.imaginary_archetypes.borrow_mut().push(
ImaginaryArchetype {
id: add_edge_archetype_id,
- component_ids: add_edge_archetype_comps
- .iter()
- .map(|comp_id| *comp_id)
- .collect::<Vec<_>>(),
+ component_ids: add_edge_archetype_comps.clone(),
},
);
@@ -663,8 +664,6 @@ impl<'component_storage, 'search_terms> Iterator
)),
found.into_iter(),
));
-
- continue;
}
_ => {
unreachable!();
@@ -713,8 +712,7 @@ impl ArchetypeRefIter<'_, '_>
let mut add_edge_comp_ids = imaginary_archetype_comps.to_vec();
- add_edge_comp_ids
- .insert_at_partition_point_by_key(unique_comp_id, |id| *id);
+ add_edge_comp_ids.insert_at_part_pt_by_key(unique_comp_id, |id| id);
let add_edge = ArchetypeId::new(&add_edge_comp_ids);
@@ -774,7 +772,7 @@ mod tests
let archetype_node = new_storage
.graph
- .get_node_by_id(ArchetypeId::from_components_metadata(&[]))
+ .get_node_by_id(ArchetypeId::new_empty())
.expect("Archetype for entities with no component doesn't exist");
assert_eq!(archetype_node.archetype().component_cnt(), 0);
@@ -782,7 +780,7 @@ mod tests
assert_eq!(
new_storage.entity_archetype_lookup.get(&uid).copied(),
- Some(ArchetypeId::from_components_metadata(&[]))
+ Some(ArchetypeId::new_empty())
);
}
}
diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs
index f8c204b..d96632e 100644
--- a/ecs/src/component/storage/archetype.rs
+++ b/ecs/src/component/storage/archetype.rs
@@ -7,7 +7,6 @@ use std::slice::Iter as SliceIter;
use hashbrown::HashMap;
-use crate::component::Metadata as ComponentMetadata;
use crate::lock::Lock;
use crate::uid::{Kind as UidKind, Uid};
use crate::util::{Either, HashMapExt};
@@ -123,7 +122,7 @@ impl Archetype
pub fn get_matching_component_indices(
&self,
component_id: Uid,
- ) -> MatchingComponentIter
+ ) -> MatchingComponentIter<'_>
{
assert!(
component_id.kind() == UidKind::Component
@@ -155,7 +154,7 @@ impl Archetype
inner: Either::B(
[component_id]
.into_iter()
- .zip(self.get_index_for_component(component_id).into_iter()),
+ .zip(self.get_index_for_component(component_id)),
),
}
}
@@ -219,19 +218,20 @@ type MatchingComponentIterFilterFn = fn(&((usize, &Uid), Uid)) -> bool;
type MatchingComponentIterMapFn = fn(((usize, &Uid), Uid)) -> (Uid, usize);
+type InnerMatchingComponentIterA<'archetype> = Map<
+ Filter<
+ Zip<Enumerate<SliceIter<'archetype, Uid>>, RepeatN<Uid>>,
+ MatchingComponentIterFilterFn,
+ >,
+ MatchingComponentIterMapFn,
+>;
+
+type InnerMatchingComponentIterB = Zip<ArrayIntoIter<Uid, 1>, OptionIntoIter<usize>>;
+
#[derive(Debug)]
pub struct MatchingComponentIter<'archetype>
{
- inner: Either<
- Map<
- Filter<
- Zip<Enumerate<SliceIter<'archetype, Uid>>, RepeatN<Uid>>,
- MatchingComponentIterFilterFn,
- >,
- MatchingComponentIterMapFn,
- >,
- Zip<ArrayIntoIter<Uid, 1>, OptionIntoIter<usize>>,
- >,
+ inner: Either<InnerMatchingComponentIterA<'archetype>, InnerMatchingComponentIterB>,
}
impl Iterator for MatchingComponentIter<'_>
@@ -314,29 +314,18 @@ impl Entity
#[derive(Debug)]
pub struct EntityComponent
{
- id: Uid,
component: Lock<Box<dyn Any>>,
}
impl EntityComponent
{
- pub fn new(
- component: Box<dyn Any>,
- component_id: Uid,
- component_name: &'static str,
- ) -> Self
+ pub fn new(component: Box<dyn Any>, component_name: &'static str) -> Self
{
Self {
- id: component_id,
component: Lock::new(component, component_name),
}
}
- pub fn id(&self) -> Uid
- {
- self.id
- }
-
pub fn component(&self) -> &Lock<Box<dyn Any>>
{
&self.component
@@ -352,52 +341,32 @@ pub struct Id
impl Id
{
- pub fn new(component_ids: &impl AsRef<[Uid]>) -> Self
+ pub fn new_empty() -> Self
{
- if component_ids.as_ref().is_empty() {
- return Self { hash: 0 };
- }
-
- debug_assert!(
- component_ids.as_ref().is_sorted(),
- "Cannot create archetype ID from unsorted component IDs"
- );
-
- let mut hasher = DefaultHasher::new();
-
- for component_id in component_ids.as_ref() {
- component_id.hash(&mut hasher);
- }
-
- Self { hash: hasher.finish() }
+ Self { hash: 0 }
}
- pub fn from_components_metadata<'a>(
- components_metadata: impl IntoIterator<Item = &'a ComponentMetadata>,
- ) -> Self
+ pub fn new<'a>(component_ids: impl IntoIterator<Item = &'a Uid>) -> Self
{
let mut hasher = DefaultHasher::new();
let mut prev_component_id: Option<Uid> = None;
- let mut comp_metadata_iter = components_metadata.into_iter().peekable();
+ let mut component_id_iter = component_ids.into_iter().peekable();
- if comp_metadata_iter.peek().is_none() {
- return Self { hash: 0 };
+ if component_id_iter.peek().is_none() {
+ return Self::new_empty();
}
- for comp_metadata in comp_metadata_iter {
- if prev_component_id
- .is_some_and(|prev_comp_id| comp_metadata.id < prev_comp_id)
- {
- panic!(
- "Cannot create archetype ID from a unsorted component metadata list"
- );
- }
+ for comp_id in component_id_iter {
+ assert!(
+ prev_component_id.is_none_or(|prev_comp_id| *comp_id >= prev_comp_id),
+ "Cannot create archetype ID from a unsorted component metadata list"
+ );
- prev_component_id = Some(comp_metadata.id);
+ prev_component_id = Some(*comp_id);
- comp_metadata.id.hash(&mut hasher);
+ comp_id.hash(&mut hasher);
}
Self { hash: hasher.finish() }
diff --git a/ecs/src/component/storage/graph.rs b/ecs/src/component/storage/graph.rs
index 29fa937..76200f9 100644
--- a/ecs/src/component/storage/graph.rs
+++ b/ecs/src/component/storage/graph.rs
@@ -80,7 +80,7 @@ impl Graph
pub fn dfs_archetype_add_edges(
&self,
archetype_id: ArchetypeId,
- ) -> Option<ArchetypeAddEdgeDfsIter>
+ ) -> Option<ArchetypeAddEdgeDfsIter<'_>>
{
let node = self.get_node_by_id(archetype_id)?;