summaryrefslogtreecommitdiff
path: root/ecs/src/component
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-03-21 20:05:53 +0100
committerHampusM <hampus@hampusmat.com>2025-03-22 15:16:01 +0100
commitfe62665b1d62d36ee0839e6bf24e3841ea667da9 (patch)
tree0533941d2cbbe5bf0a1995a33f05bca37da949fd /ecs/src/component
parent76e7e612e7b516bf52b508ae5bb367b1ddc3babc (diff)
refactor(ecs): replace query options with fieldless terms
Diffstat (limited to 'ecs/src/component')
-rw-r--r--ecs/src/component/storage.rs96
-rw-r--r--ecs/src/component/storage/graph.rs11
2 files changed, 91 insertions, 16 deletions
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index 21f9a37..4b2b6d8 100644
--- a/ecs/src/component/storage.rs
+++ b/ecs/src/component/storage.rs
@@ -26,6 +26,26 @@ pub mod archetype;
mod graph;
+#[derive(Debug)]
+pub struct ArchetypeSearchTerms<'a>
+{
+ pub required_components: &'a [Uid],
+ pub excluded_components: &'a [Uid],
+}
+
+impl ArchetypeSearchTerms<'_>
+{
+ fn excluded_contains(&self, uid: Uid) -> bool
+ {
+ self.excluded_components.binary_search(&uid).is_ok()
+ }
+
+ fn required_contains(&self, uid: Uid) -> bool
+ {
+ self.required_components.binary_search(&uid).is_ok()
+ }
+}
+
#[derive(Debug, Default)]
pub struct Storage
{
@@ -36,9 +56,25 @@ pub struct Storage
impl Storage
{
- pub fn search_archetypes(&self, component_ids: &[Uid]) -> ArchetypeRefIter<'_>
+ pub fn search_archetypes<'search_terms>(
+ &self,
+ search_terms: ArchetypeSearchTerms<'search_terms>,
+ ) -> ArchetypeRefIter<'_, 'search_terms>
{
- let archetype_id = ArchetypeId::new(&component_ids);
+ let archetype_id = ArchetypeId::new(&search_terms.required_components);
+
+ if search_terms
+ .excluded_components
+ .iter()
+ .any(|excluded_comp_id| search_terms.required_contains(*excluded_comp_id))
+ {
+ return ArchetypeRefIter {
+ storage: self,
+ pre_iter: Either::B(Vec::new().into_iter()),
+ dfs_iter: ArchetypeAddEdgeDfsIter::new(&self.graph, &[]),
+ search_terms,
+ };
+ }
let Some(add_edge_recursive_iter) =
self.graph.dfs_archetype_add_edges(archetype_id)
@@ -47,15 +83,16 @@ impl Storage
.borrow_mut()
.push(ImaginaryArchetype {
id: archetype_id,
- component_ids: component_ids.to_vec(),
+ component_ids: search_terms.required_components.to_vec(),
});
- let found_archetypes = self.find_all_archetype_with_comps(component_ids);
+ let found_archetypes = self.find_all_archetype_with_comps(&search_terms);
return ArchetypeRefIter {
storage: self,
pre_iter: Either::B(found_archetypes.clone().into_iter()),
dfs_iter: ArchetypeAddEdgeDfsIter::new(&self.graph, &found_archetypes),
+ search_terms,
};
};
@@ -63,6 +100,7 @@ impl Storage
storage: self,
pre_iter: Either::A([archetype_id].into_iter()),
dfs_iter: add_edge_recursive_iter,
+ search_terms,
}
}
@@ -321,7 +359,10 @@ impl Storage
}
}
- fn find_all_archetype_with_comps(&self, component_ids: &[Uid]) -> Vec<ArchetypeId>
+ fn find_all_archetype_with_comps(
+ &self,
+ search_terms: &ArchetypeSearchTerms<'_>,
+ ) -> Vec<ArchetypeId>
{
let Some(mut search_iter) =
self.graph.dfs_archetype_add_edges(ArchetypeId::new(&[]))
@@ -333,20 +374,30 @@ impl Storage
let mut found = Vec::<ArchetypeId>::new();
while let Some(node_id) = search_iter.streaming_next() {
- let ArchetypeAddEdgeDfsIterResult::AddEdge(node_id) = node_id else {
+ let ArchetypeAddEdgeDfsIterResult::AddEdge {
+ add_edge_archetype_id: node_id,
+ add_edge_component_id,
+ } = node_id
+ else {
continue;
};
+ if search_terms.excluded_contains(add_edge_component_id) {
+ search_iter.pop();
+ continue;
+ }
+
let node = self
.graph
.get_node_by_id(node_id)
.expect("Graph node found through DFS doesn't exist");
- if node.archetype().component_cnt() < component_ids.len() {
+ if node.archetype().component_cnt() < search_terms.required_components.len() {
continue;
}
- if !component_ids
+ if !search_terms
+ .required_components
.iter()
.all(|comp_id| node.archetype().has_component_with_id(*comp_id))
{
@@ -371,14 +422,16 @@ impl TypeName for Storage
}
#[derive(Debug)]
-pub struct ArchetypeRefIter<'storage>
+pub struct ArchetypeRefIter<'storage, 'search_terms>
{
storage: &'storage Storage,
pre_iter: Either<ArrayIter<ArchetypeId, 1>, VecIntoIter<ArchetypeId>>,
dfs_iter: ArchetypeAddEdgeDfsIter<'storage>,
+ search_terms: ArchetypeSearchTerms<'search_terms>,
}
-impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage>
+impl<'component_storage, 'search_terms> Iterator
+ for ArchetypeRefIter<'component_storage, 'search_terms>
{
type Item = &'component_storage Archetype;
@@ -400,14 +453,26 @@ impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage>
| ArchetypeAddEdgeDfsIterResult::AddEdgeArchetypeNotFound { .. }
)
})? {
- ArchetypeAddEdgeDfsIterResult::AddEdge(add_edge_archetype_id) => {
- break add_edge_archetype_id
+ ArchetypeAddEdgeDfsIterResult::AddEdge {
+ add_edge_archetype_id,
+ add_edge_component_id,
+ } => {
+ if self.search_terms.excluded_contains(add_edge_component_id) {
+ self.dfs_iter.pop();
+ continue;
+ }
+
+ break add_edge_archetype_id;
}
ArchetypeAddEdgeDfsIterResult::AddEdgeArchetypeNotFound {
archetype,
add_edge_archetype_id,
add_edge_component_id,
} => {
+ if self.search_terms.excluded_contains(add_edge_component_id) {
+ continue;
+ }
+
let mut add_edge_archetype_comps =
archetype.component_ids_sorted().collect::<Vec<_>>();
@@ -453,7 +518,7 @@ impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage>
}
}
-impl ArchetypeRefIter<'_>
+impl ArchetypeRefIter<'_, '_>
{
fn find_edges_of_imaginary_archetype(
&self,
@@ -461,7 +526,10 @@ impl ArchetypeRefIter<'_>
) -> Vec<(Uid, ArchetypeEdges)>
{
self.storage
- .find_all_archetype_with_comps(imaginary_archetype_comps)
+ .find_all_archetype_with_comps(&ArchetypeSearchTerms {
+ required_components: imaginary_archetype_comps,
+ excluded_components: &[],
+ })
.into_iter()
.filter_map(|found_id| {
let found_archetype = self.storage.get_archetype_by_id(found_id).unwrap();
diff --git a/ecs/src/component/storage/graph.rs b/ecs/src/component/storage/graph.rs
index feac16c..e1f48f7 100644
--- a/ecs/src/component/storage/graph.rs
+++ b/ecs/src/component/storage/graph.rs
@@ -381,14 +381,21 @@ impl<'graph> StreamingIterator for ArchetypeAddEdgeDfsIter<'graph>
.into_iter(),
));
- Some(ArchetypeAddEdgeDfsIterResult::AddEdge(add_edge))
+ Some(ArchetypeAddEdgeDfsIterResult::AddEdge {
+ add_edge_archetype_id: add_edge,
+ add_edge_component_id: component_id,
+ })
}
}
#[derive(Debug)]
pub enum ArchetypeAddEdgeDfsIterResult<'graph, 'iter>
{
- AddEdge(ArchetypeId),
+ AddEdge
+ {
+ add_edge_archetype_id: ArchetypeId,
+ add_edge_component_id: Uid,
+ },
NoEdgesLeftForArchetype,
NoAddEdge,
AddEdgeAlreadyVisited,