Skip to content

Commit 3c502c4

Browse files
committed
add entities_all_unique to QueryManyIter
1 parent c4cedb1 commit 3c502c4

File tree

1 file changed

+191
-1
lines changed

1 file changed

+191
-1
lines changed

crates/bevy_ecs/src/query/iter.rs

Lines changed: 191 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use 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

1819
use 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

11281206
impl<'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

Comments
 (0)