11use crate :: {
22 archetype:: { Archetype , ArchetypeEntity , Archetypes } ,
33 component:: Tick ,
4- entity:: { Entities , Entity } ,
4+ entity:: { Entities , Entity , EntityHashSet } ,
55 query:: { ArchetypeFilter , DebugCheckedUnwrap , QueryState , StorageId } ,
66 storage:: { Table , TableRow , Tables } ,
77 world:: unsafe_world_cell:: UnsafeWorldCell ,
@@ -13,6 +13,7 @@ use std::{
1313 iter:: FusedIterator ,
1414 mem:: MaybeUninit ,
1515 ops:: Range ,
16+ vec:: IntoIter ,
1617} ;
1718
1819use super :: { QueryData , QueryFilter , ReadOnlyQueryData } ;
@@ -1123,6 +1124,83 @@ where
11231124 // of any previously returned unique references first, thus preventing aliasing.
11241125 unsafe { self . fetch_next_aliased_unchecked ( ) . map ( D :: shrink) }
11251126 }
1127+
1128+ /// Checks for uniqueness in the `Entity` iterator `I`, returning a new Iterator on success.
1129+ /// Return `self` on failure.
1130+ /// This new iterator allows for mutable iteration without `fetch_next`.
1131+ /// # Example
1132+ /// ```
1133+ /// # use bevy_ecs::prelude::*;
1134+ /// # use std::ops::{Deref, DerefMut};
1135+ /// #
1136+ /// # #[derive(Component, Clone, Copy)]
1137+ /// # struct PartValue(usize);
1138+ /// #
1139+ /// # impl Deref for PartValue {
1140+ /// # type Target = usize;
1141+ /// #
1142+ /// # fn deref(&self) -> &Self::Target {
1143+ /// # &self.0
1144+ /// # }
1145+ /// # }
1146+ /// #
1147+ /// # impl DerefMut for PartValue {
1148+ /// # fn deref_mut(&mut self) -> &mut Self::Target {
1149+ /// # &mut self.0
1150+ /// # }
1151+ /// # }
1152+ /// #
1153+ /// # let mut world = World::new();
1154+ /// #
1155+ /// // Mutable `Iterator` trait iteration.
1156+ /// fn system(mut query: Query<&mut PartValue>) {
1157+ /// # let entity_list: Vec<Entity> = Vec::new();
1158+ /// #
1159+ /// let mut unique_iter = query.iter_many_mut(entity_list)
1160+ /// .entities_all_unique()
1161+ /// .expect("the entity_list only contains unique entities");
1162+ ///
1163+ /// for mut part_value in unique_iter {
1164+ /// **part_value += 1;
1165+ /// }
1166+ /// }
1167+ /// #
1168+ /// # let mut schedule = Schedule::default();
1169+ /// # schedule.add_systems((system));
1170+ /// # schedule.run(&mut world);
1171+ /// ```
1172+ #[ inline( always) ]
1173+ pub fn entities_all_unique (
1174+ self ,
1175+ ) -> Result <
1176+ QueryManyUniqueIter < ' w , ' s , D , F , IntoIter < I :: Item > > ,
1177+ QueryManyIter < ' w , ' s , D , F , IntoIter < I :: Item > > ,
1178+ > {
1179+ let mut used = EntityHashSet :: default ( ) ;
1180+ let entities: Vec < _ > = self . entity_iter . collect ( ) ;
1181+
1182+ if entities. iter ( ) . all ( move |e| used. insert ( * e. borrow ( ) ) ) {
1183+ return Ok ( QueryManyUniqueIter {
1184+ entity_iter : entities. into_iter ( ) ,
1185+ entities : self . entities ,
1186+ tables : self . tables ,
1187+ archetypes : self . archetypes ,
1188+ fetch : self . fetch ,
1189+ filter : self . filter ,
1190+ query_state : self . query_state ,
1191+ } ) ;
1192+ }
1193+
1194+ Err ( QueryManyIter {
1195+ entity_iter : entities. into_iter ( ) ,
1196+ entities : self . entities ,
1197+ tables : self . tables ,
1198+ archetypes : self . archetypes ,
1199+ fetch : self . fetch ,
1200+ filter : self . filter ,
1201+ query_state : self . query_state ,
1202+ } )
1203+ }
11261204}
11271205
11281206impl < ' w , ' s , D : ReadOnlyQueryData , F : QueryFilter , I : Iterator > Iterator
@@ -1161,6 +1239,118 @@ where
11611239 }
11621240}
11631241
1242+ /// An [`Iterator`] over the query items generated from an iterator of unique [`Entity`]s.
1243+ ///
1244+ /// Items are returned in the order of the provided iterator.
1245+ /// Entities that don't match the query are skipped.
1246+ ///
1247+ /// In contrast with `QueryManyIter`, this allows for mutable iteration without a `fetch_next` method.
1248+ ///
1249+ /// This struct is created by the [`QueryManyIter::entities_all_unique`] method.
1250+ pub struct QueryManyUniqueIter < ' w , ' s , D : QueryData , F : QueryFilter , I : Iterator >
1251+ where
1252+ I :: Item : Borrow < Entity > ,
1253+ {
1254+ entity_iter : I ,
1255+ entities : & ' w Entities ,
1256+ tables : & ' w Tables ,
1257+ archetypes : & ' w Archetypes ,
1258+ fetch : D :: Fetch < ' w > ,
1259+ filter : F :: Fetch < ' w > ,
1260+ query_state : & ' s QueryState < D , F > ,
1261+ }
1262+
1263+ impl < ' w , ' s , D : QueryData , F : QueryFilter , I : Iterator > QueryManyUniqueIter < ' w , ' s , D , F , I >
1264+ where
1265+ I :: Item : Borrow < Entity > ,
1266+ {
1267+ // Entities are guaranteed to be unique, so no lifetime shrinking needed for mutable iteration.
1268+ #[ inline( always) ]
1269+ fn fetch_next ( & mut self ) -> Option < D :: Item < ' w > > {
1270+ for entity in self . entity_iter . by_ref ( ) {
1271+ let entity = * entity. borrow ( ) ;
1272+ let Some ( location) = self . entities . get ( entity) else {
1273+ continue ;
1274+ } ;
1275+
1276+ if !self
1277+ . query_state
1278+ . matched_archetypes
1279+ . contains ( location. archetype_id . index ( ) )
1280+ {
1281+ continue ;
1282+ }
1283+ let ( archetype, table) ;
1284+ // SAFETY:
1285+ // `tables` and `archetypes` belong to the same world that the [`QueryIter`]
1286+ // was initialized for.
1287+ unsafe {
1288+ archetype = self
1289+ . archetypes
1290+ . get ( location. archetype_id )
1291+ . debug_checked_unwrap ( ) ;
1292+ table = self . tables . get ( location. table_id ) . debug_checked_unwrap ( ) ;
1293+ }
1294+ // SAFETY: `archetype` is from the world that `fetch/filter` were created for,
1295+ // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
1296+ unsafe {
1297+ D :: set_archetype (
1298+ & mut self . fetch ,
1299+ & self . query_state . fetch_state ,
1300+ archetype,
1301+ table,
1302+ ) ;
1303+ }
1304+ // SAFETY: `table` is from the world that `fetch/filter` were created for,
1305+ // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
1306+ unsafe {
1307+ F :: set_archetype (
1308+ & mut self . filter ,
1309+ & self . query_state . filter_state ,
1310+ archetype,
1311+ table,
1312+ ) ;
1313+ }
1314+
1315+ // SAFETY: set_archetype was called prior.
1316+ // `location.archetype_row` is an archetype index row in range of the current archetype, because if it was not, the match above would have `continue`d
1317+ if unsafe { F :: filter_fetch ( & mut self . filter , entity, location. table_row ) } {
1318+ // SAFETY:
1319+ // - set_archetype was called prior, `location.archetype_row` is an archetype index in range of the current archetype
1320+ // - fetch is only called once for each entity.
1321+ return Some ( unsafe { D :: fetch ( & mut self . fetch , entity, location. table_row ) } ) ;
1322+ }
1323+ }
1324+ None
1325+ }
1326+ }
1327+
1328+ impl < ' w , ' s , D : QueryData , F : QueryFilter , I : Iterator > Iterator
1329+ for QueryManyUniqueIter < ' w , ' s , D , F , I >
1330+ where
1331+ I :: Item : Borrow < Entity > ,
1332+ {
1333+ type Item = D :: Item < ' w > ;
1334+
1335+ #[ inline( always) ]
1336+ fn next ( & mut self ) -> Option < Self :: Item > {
1337+ self . fetch_next ( )
1338+ }
1339+
1340+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1341+ let ( _, max_size) = self . entity_iter . size_hint ( ) ;
1342+ ( 0 , max_size)
1343+ }
1344+ }
1345+
1346+ // This is correct as [`QueryManyIter`] always returns `None` once exhausted.
1347+ impl < ' w , ' s , D : QueryData , F : QueryFilter , I : Iterator > FusedIterator
1348+ for QueryManyUniqueIter < ' w , ' s , D , F , I >
1349+ where
1350+ I :: Item : Borrow < Entity > ,
1351+ {
1352+ }
1353+
11641354/// An iterator over `K`-sized combinations of query items without repetition.
11651355///
11661356/// A combination is an arrangement of a collection of items where order does not matter.
0 commit comments