diff options
author | HampusM <hampus@hampusmat.com> | 2025-03-21 20:05:53 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-03-22 15:16:01 +0100 |
commit | fe62665b1d62d36ee0839e6bf24e3841ea667da9 (patch) | |
tree | 0533941d2cbbe5bf0a1995a33f05bca37da949fd /ecs/src/component | |
parent | 76e7e612e7b516bf52b508ae5bb367b1ddc3babc (diff) |
refactor(ecs): replace query options with fieldless terms
Diffstat (limited to 'ecs/src/component')
-rw-r--r-- | ecs/src/component/storage.rs | 96 | ||||
-rw-r--r-- | ecs/src/component/storage/graph.rs | 11 |
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, |