From 527d3a5885daa4b43df7054f7787dad47f06135d Mon Sep 17 00:00:00 2001 From: Nicola Papale Date: Sun, 11 Jun 2023 01:24:09 +0200 Subject: [PATCH] Add iter_many_manual QueryState method (#8772) # Objective `QueryState` exposes a `get_manual` and `iter_manual` method. However, there is now `iter_many_manual`. `iter_many_manual` is useful when you have a `&World` (eg: the `world` in a `Scene`) and want to run a query several times on it (eg: iteratively navigate a hierarchy by calling `iter_many` on `Children` component). `iter_many`'s need for a `&mut World` makes the API much less flexible. The exclusive access pattern requires doing some very funky dance and excludes a category of algorithms for hierarchy traversal. ## Solution - Add a `iter_many_manual` method to `QueryState` ### Alternative My current workaround is to use `get_manual`. However, this doesn't benefit from the optimizations on `QueryManyIter`. --- ## Changelog - Add a `iter_many_manual` method to `QueryState` --- crates/bevy_ecs/src/query/state.rs | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 87ea0854df..16a0ea6c9d 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -652,6 +652,41 @@ impl QueryState { } } + /// Returns an [`Iterator`] over the read-only query items generated from an [`Entity`] list. + /// + /// Items are returned in the order of the list of entities. + /// Entities that don't match the query are skipped. + /// + /// If `world` archetypes changed since [`Self::update_archetypes`] was last called, + /// this will skip entities contained in new archetypes. + /// + /// This can only be called for read-only queries. + /// + /// # See also + /// + /// - [`iter_many`](Self::iter_many) to update archetypes. + /// - [`iter_manual`](Self::iter_manual) to iterate over all query items. + #[inline] + pub fn iter_many_manual<'w, 's, EntityList: IntoIterator>( + &'s self, + world: &'w World, + entities: EntityList, + ) -> QueryManyIter<'w, 's, Q::ReadOnly, F::ReadOnly, EntityList::IntoIter> + where + EntityList::Item: Borrow, + { + self.validate_world(world); + // SAFETY: query is read only, world id is validated + unsafe { + self.as_readonly().iter_many_unchecked_manual( + entities, + world, + world.last_change_tick(), + world.read_change_tick(), + ) + } + } + /// Returns an iterator over the query items generated from an [`Entity`] list. /// /// Items are returned in the order of the list of entities.