|
1 | 1 | use crate::{
|
2 | 2 | archetype::{Archetype, ArchetypeEntity, Archetypes},
|
3 | 3 | component::Tick,
|
4 |
| - entity::{Entities, Entity}, |
| 4 | + entity::{Entities, Entity, EntityHashSet}, |
5 | 5 | query::{ArchetypeFilter, DebugCheckedUnwrap, QueryState, StorageId},
|
6 | 6 | storage::{Table, TableRow, Tables},
|
7 | 7 | world::unsafe_world_cell::UnsafeWorldCell,
|
8 | 8 | };
|
9 |
| -use std::{borrow::Borrow, cmp::Ordering, iter::FusedIterator, mem::MaybeUninit, ops::Range}; |
| 9 | +use std::{ |
| 10 | + borrow::Borrow, |
| 11 | + cmp::Ordering, |
| 12 | + fmt::{self, Debug, Formatter}, |
| 13 | + iter::FusedIterator, |
| 14 | + mem::MaybeUninit, |
| 15 | + ops::Range, |
| 16 | + vec::IntoIter, |
| 17 | +}; |
10 | 18 |
|
11 | 19 | use super::{QueryData, QueryFilter, ReadOnlyQueryData};
|
12 | 20 |
|
@@ -1102,6 +1110,83 @@ where
|
1102 | 1110 | // of any previously returned unique references first, thus preventing aliasing.
|
1103 | 1111 | unsafe { self.fetch_next_aliased_unchecked().map(D::shrink) }
|
1104 | 1112 | }
|
| 1113 | + |
| 1114 | + /// Checks for uniqueness in the `Entity` iterator `I`, returning a new Iterator on success. |
| 1115 | + /// Return `self` on failure. |
| 1116 | + /// This new iterator allows for mutable iteration without `fetch_next`. |
| 1117 | + /// # Example |
| 1118 | + /// ``` |
| 1119 | + /// # use bevy_ecs::prelude::*; |
| 1120 | + /// # use std::ops::{Deref, DerefMut}; |
| 1121 | + /// # |
| 1122 | + /// # #[derive(Component, Clone, Copy)] |
| 1123 | + /// # struct PartValue(usize); |
| 1124 | + /// # |
| 1125 | + /// # impl Deref for PartValue { |
| 1126 | + /// # type Target = usize; |
| 1127 | + /// # |
| 1128 | + /// # fn deref(&self) -> &Self::Target { |
| 1129 | + /// # &self.0 |
| 1130 | + /// # } |
| 1131 | + /// # } |
| 1132 | + /// # |
| 1133 | + /// # impl DerefMut for PartValue { |
| 1134 | + /// # fn deref_mut(&mut self) -> &mut Self::Target { |
| 1135 | + /// # &mut self.0 |
| 1136 | + /// # } |
| 1137 | + /// # } |
| 1138 | + /// # |
| 1139 | + /// # let mut world = World::new(); |
| 1140 | + /// # |
| 1141 | + /// // Mutable `Iterator` trait iteration. |
| 1142 | + /// fn system(mut query: Query<&mut PartValue>) { |
| 1143 | + /// # let entity_list: Vec<Entity> = Vec::new(); |
| 1144 | + /// # |
| 1145 | + /// let mut unique_iter = query.iter_many_mut(entity_list) |
| 1146 | + /// .entities_all_unique() |
| 1147 | + /// .expect("the entity_list only contains unique entities"); |
| 1148 | + /// |
| 1149 | + /// for mut part_value in unique_iter { |
| 1150 | + /// **part_value += 1; |
| 1151 | + /// } |
| 1152 | + /// } |
| 1153 | + /// # |
| 1154 | + /// # let mut schedule = Schedule::default(); |
| 1155 | + /// # schedule.add_systems((system)); |
| 1156 | + /// # schedule.run(&mut world); |
| 1157 | + /// ``` |
| 1158 | + #[inline(always)] |
| 1159 | + pub fn entities_all_unique( |
| 1160 | + self, |
| 1161 | + ) -> Result< |
| 1162 | + QueryManyUniqueIter<'w, 's, D, F, IntoIter<I::Item>>, |
| 1163 | + QueryManyIter<'w, 's, D, F, IntoIter<I::Item>>, |
| 1164 | + > { |
| 1165 | + let mut used = EntityHashSet::default(); |
| 1166 | + let entities: Vec<_> = self.entity_iter.collect(); |
| 1167 | + |
| 1168 | + if entities.iter().all(move |e| used.insert(*e.borrow())) { |
| 1169 | + return Ok(QueryManyUniqueIter { |
| 1170 | + entity_iter: entities.into_iter(), |
| 1171 | + entities: self.entities, |
| 1172 | + tables: self.tables, |
| 1173 | + archetypes: self.archetypes, |
| 1174 | + fetch: self.fetch, |
| 1175 | + filter: self.filter, |
| 1176 | + query_state: self.query_state, |
| 1177 | + }); |
| 1178 | + } |
| 1179 | + |
| 1180 | + Err(QueryManyIter { |
| 1181 | + entity_iter: entities.into_iter(), |
| 1182 | + entities: self.entities, |
| 1183 | + tables: self.tables, |
| 1184 | + archetypes: self.archetypes, |
| 1185 | + fetch: self.fetch, |
| 1186 | + filter: self.filter, |
| 1187 | + query_state: self.query_state, |
| 1188 | + }) |
| 1189 | + } |
1105 | 1190 | }
|
1106 | 1191 |
|
1107 | 1192 | impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator> Iterator
|
@@ -1131,6 +1216,127 @@ where
|
1131 | 1216 | {
|
1132 | 1217 | }
|
1133 | 1218 |
|
| 1219 | +impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Debug for QueryManyIter<'w, 's, D, F, I> |
| 1220 | +where |
| 1221 | + I::Item: Borrow<Entity>, |
| 1222 | +{ |
| 1223 | + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 1224 | + f.debug_struct("QueryManyIter").finish() |
| 1225 | + } |
| 1226 | +} |
| 1227 | + |
| 1228 | +/// An [`Iterator`] over the query items generated from an iterator of unique [`Entity`]s. |
| 1229 | +/// |
| 1230 | +/// Items are returned in the order of the provided iterator. |
| 1231 | +/// Entities that don't match the query are skipped. |
| 1232 | +/// |
| 1233 | +/// In contrast with `QueryManyIter`, this allows for mutable iteration without a `fetch_next` method. |
| 1234 | +/// |
| 1235 | +/// This struct is created by the [`QueryManyIter::entities_all_unique`] method. |
| 1236 | +pub struct QueryManyUniqueIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> |
| 1237 | +where |
| 1238 | + I::Item: Borrow<Entity>, |
| 1239 | +{ |
| 1240 | + entity_iter: I, |
| 1241 | + entities: &'w Entities, |
| 1242 | + tables: &'w Tables, |
| 1243 | + archetypes: &'w Archetypes, |
| 1244 | + fetch: D::Fetch<'w>, |
| 1245 | + filter: F::Fetch<'w>, |
| 1246 | + query_state: &'s QueryState<D, F>, |
| 1247 | +} |
| 1248 | + |
| 1249 | +impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> QueryManyUniqueIter<'w, 's, D, F, I> |
| 1250 | +where |
| 1251 | + I::Item: Borrow<Entity>, |
| 1252 | +{ |
| 1253 | + // Entities are guaranteed to be unique, so no lifetime shrinking needed for mutable iteration. |
| 1254 | + #[inline(always)] |
| 1255 | + fn fetch_next(&mut self) -> Option<D::Item<'w>> { |
| 1256 | + for entity in self.entity_iter.by_ref() { |
| 1257 | + let entity = *entity.borrow(); |
| 1258 | + let Some(location) = self.entities.get(entity) else { |
| 1259 | + continue; |
| 1260 | + }; |
| 1261 | + |
| 1262 | + if !self |
| 1263 | + .query_state |
| 1264 | + .matched_archetypes |
| 1265 | + .contains(location.archetype_id.index()) |
| 1266 | + { |
| 1267 | + continue; |
| 1268 | + } |
| 1269 | + let (archetype, table); |
| 1270 | + // SAFETY: |
| 1271 | + // `tables` and `archetypes` belong to the same world that the [`QueryIter`] |
| 1272 | + // was initialized for. |
| 1273 | + unsafe { |
| 1274 | + archetype = self |
| 1275 | + .archetypes |
| 1276 | + .get(location.archetype_id) |
| 1277 | + .debug_checked_unwrap(); |
| 1278 | + table = self.tables.get(location.table_id).debug_checked_unwrap(); |
| 1279 | + } |
| 1280 | + // SAFETY: `archetype` is from the world that `fetch/filter` were created for, |
| 1281 | + // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with |
| 1282 | + unsafe { |
| 1283 | + D::set_archetype( |
| 1284 | + &mut self.fetch, |
| 1285 | + &self.query_state.fetch_state, |
| 1286 | + archetype, |
| 1287 | + table, |
| 1288 | + ); |
| 1289 | + } |
| 1290 | + // SAFETY: `table` is from the world that `fetch/filter` were created for, |
| 1291 | + // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with |
| 1292 | + unsafe { |
| 1293 | + F::set_archetype( |
| 1294 | + &mut self.filter, |
| 1295 | + &self.query_state.filter_state, |
| 1296 | + archetype, |
| 1297 | + table, |
| 1298 | + ); |
| 1299 | + } |
| 1300 | + |
| 1301 | + // SAFETY: set_archetype was called prior. |
| 1302 | + // `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 |
| 1303 | + if unsafe { F::filter_fetch(&mut self.filter, entity, location.table_row) } { |
| 1304 | + // SAFETY: |
| 1305 | + // - set_archetype was called prior, `location.archetype_row` is an archetype index in range of the current archetype |
| 1306 | + // - fetch is only called once for each entity. |
| 1307 | + return Some(unsafe { D::fetch(&mut self.fetch, entity, location.table_row) }); |
| 1308 | + } |
| 1309 | + } |
| 1310 | + None |
| 1311 | + } |
| 1312 | +} |
| 1313 | + |
| 1314 | +impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Iterator |
| 1315 | + for QueryManyUniqueIter<'w, 's, D, F, I> |
| 1316 | +where |
| 1317 | + I::Item: Borrow<Entity>, |
| 1318 | +{ |
| 1319 | + type Item = D::Item<'w>; |
| 1320 | + |
| 1321 | + #[inline(always)] |
| 1322 | + fn next(&mut self) -> Option<Self::Item> { |
| 1323 | + self.fetch_next() |
| 1324 | + } |
| 1325 | + |
| 1326 | + fn size_hint(&self) -> (usize, Option<usize>) { |
| 1327 | + let (_, max_size) = self.entity_iter.size_hint(); |
| 1328 | + (0, max_size) |
| 1329 | + } |
| 1330 | +} |
| 1331 | + |
| 1332 | +// This is correct as [`QueryManyIter`] always returns `None` once exhausted. |
| 1333 | +impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> FusedIterator |
| 1334 | + for QueryManyUniqueIter<'w, 's, D, F, I> |
| 1335 | +where |
| 1336 | + I::Item: Borrow<Entity>, |
| 1337 | +{ |
| 1338 | +} |
| 1339 | + |
1134 | 1340 | /// An iterator over `K`-sized combinations of query items without repetition.
|
1135 | 1341 | ///
|
1136 | 1342 | /// A combination is an arrangement of a collection of items where order does not matter.
|
|
0 commit comments