This commit is contained in:
Chris Russell 2025-07-16 17:24:38 -04:00 committed by GitHub
commit 97b28f91b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 622 additions and 531 deletions

View File

@ -2020,7 +2020,7 @@ mod tests {
.run_system_once(|query: Query<&mut A>| { .run_system_once(|query: Query<&mut A>| {
let mut readonly = query.as_readonly(); let mut readonly = query.as_readonly();
let mut lens: QueryLens<&mut A> = readonly.transmute_lens(); let mut lens: QueryLens<&mut A> = readonly.transmute_lens();
bad(lens.query(), query.as_readonly()); bad(lens.reborrow(), query.as_readonly());
}) })
.unwrap(); .unwrap();
} }
@ -2146,7 +2146,7 @@ mod tests {
.run_system_once(|query_a: Query<&mut A>, mut query_b: Query<&mut B>| { .run_system_once(|query_a: Query<&mut A>, mut query_b: Query<&mut B>| {
let mut readonly = query_a.as_readonly(); let mut readonly = query_a.as_readonly();
let mut lens: QueryLens<(&mut A, &mut B)> = readonly.join(&mut query_b); let mut lens: QueryLens<(&mut A, &mut B)> = readonly.join(&mut query_b);
bad(lens.query(), query_a.as_readonly()); bad(lens.reborrow(), query_a.as_readonly());
}) })
.unwrap(); .unwrap();
} }

View File

@ -1,6 +1,8 @@
use core::ops::Deref;
use crate::{ use crate::{
entity::Entity, entity::Entity,
query::{QueryData, QueryFilter}, query::{QueryData, QueryFilter, QueryState},
relationship::{Relationship, RelationshipTarget}, relationship::{Relationship, RelationshipTarget},
system::Query, system::Query,
}; };
@ -9,24 +11,26 @@ use smallvec::SmallVec;
use super::SourceIter; use super::SourceIter;
impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref<Target = QueryState<D, F>>>
Query<'w, 's, D, F, S>
{
/// If the given `entity` contains the `R` [`Relationship`] component, returns the /// If the given `entity` contains the `R` [`Relationship`] component, returns the
/// target entity of that relationship. /// target entity of that relationship.
pub fn related<R: Relationship>(&'w self, entity: Entity) -> Option<Entity> pub fn related<R: Relationship>(&'w self, entity: Entity) -> Option<Entity>
where where
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w R>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
self.get(entity).map(R::get).ok() self.get(entity).map(R::get).ok()
} }
/// If the given `entity` contains the `S` [`RelationshipTarget`] component, returns the /// If the given `entity` contains the `S` [`RelationshipTarget`] component, returns the
/// source entities stored on that component. /// source entities stored on that component.
pub fn relationship_sources<S: RelationshipTarget>( pub fn relationship_sources<R: RelationshipTarget>(
&'w self, &'w self,
entity: Entity, entity: Entity,
) -> impl Iterator<Item = Entity> + 'w ) -> impl Iterator<Item = Entity> + 'w
where where
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
self.get(entity) self.get(entity)
.into_iter() .into_iter()
@ -42,7 +46,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.
pub fn root_ancestor<R: Relationship>(&'w self, entity: Entity) -> Entity pub fn root_ancestor<R: Relationship>(&'w self, entity: Entity) -> Entity
where where
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w R>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
// Recursively search up the tree until we're out of parents // Recursively search up the tree until we're out of parents
match self.get(entity) { match self.get(entity) {
@ -57,13 +61,13 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// For relationship graphs that contain loops, this could loop infinitely. /// For relationship graphs that contain loops, this could loop infinitely.
/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.
pub fn iter_leaves<S: RelationshipTarget>( pub fn iter_leaves<R: RelationshipTarget>(
&'w self, &'w self,
entity: Entity, entity: Entity,
) -> impl Iterator<Item = Entity> + use<'w, 's, S, D, F> ) -> impl Iterator<Item = Entity> + use<'w, 's, D, F, S, R>
where where
<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
SourceIter<'w, S>: DoubleEndedIterator, SourceIter<'w, R>: DoubleEndedIterator,
{ {
self.iter_descendants_depth_first(entity).filter(|entity| { self.iter_descendants_depth_first(entity).filter(|entity| {
self.get(*entity) self.get(*entity)
@ -80,7 +84,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
entity: Entity, entity: Entity,
) -> impl Iterator<Item = Entity> + 'w ) -> impl Iterator<Item = Entity> + 'w
where where
D::ReadOnly: QueryData<Item<'w, 's> = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>, D::ReadOnly: QueryData<Item<'w, 'w> = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>,
{ {
self.get(entity) self.get(entity)
.ok() .ok()
@ -98,12 +102,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// For relationship graphs that contain loops, this could loop infinitely. /// For relationship graphs that contain loops, this could loop infinitely.
/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.
pub fn iter_descendants<S: RelationshipTarget>( pub fn iter_descendants<R: RelationshipTarget>(
&'w self, &'w self,
entity: Entity, entity: Entity,
) -> DescendantIter<'w, 's, D, F, S> ) -> DescendantIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
DescendantIter::new(self, entity) DescendantIter::new(self, entity)
} }
@ -115,13 +119,13 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// ///
/// For relationship graphs that contain loops, this could loop infinitely. /// For relationship graphs that contain loops, this could loop infinitely.
/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.
pub fn iter_descendants_depth_first<S: RelationshipTarget>( pub fn iter_descendants_depth_first<R: RelationshipTarget>(
&'w self, &'w self,
entity: Entity, entity: Entity,
) -> DescendantDepthFirstIter<'w, 's, D, F, S> ) -> DescendantDepthFirstIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
SourceIter<'w, S>: DoubleEndedIterator, SourceIter<'w, R>: DoubleEndedIterator,
{ {
DescendantDepthFirstIter::new(self, entity) DescendantDepthFirstIter::new(self, entity)
} }
@ -135,9 +139,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn iter_ancestors<R: Relationship>( pub fn iter_ancestors<R: Relationship>(
&'w self, &'w self,
entity: Entity, entity: Entity,
) -> AncestorIter<'w, 's, D, F, R> ) -> AncestorIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
AncestorIter::new(self, entity) AncestorIter::new(self, entity)
} }
@ -146,20 +150,33 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`].
/// ///
/// Traverses the hierarchy breadth-first. /// Traverses the hierarchy breadth-first.
pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> pub struct DescendantIter<
where 'w,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>, 's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: RelationshipTarget,
> where
D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
children_query: &'w Query<'w, 's, D, F>, children_query: &'w Query<'w, 's, D, F, S>,
vecdeque: VecDeque<Entity>, vecdeque: VecDeque<Entity>,
} }
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S> impl<
'w,
's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: RelationshipTarget,
> DescendantIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
/// Returns a new [`DescendantIter`]. /// Returns a new [`DescendantIter`].
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { pub fn new(children_query: &'w Query<'w, 's, D, F, S>, entity: Entity) -> Self {
DescendantIter { DescendantIter {
children_query, children_query,
vecdeque: children_query vecdeque: children_query
@ -171,10 +188,16 @@ where
} }
} }
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator impl<
for DescendantIter<'w, 's, D, F, S> 'w,
's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: RelationshipTarget,
> Iterator for DescendantIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
type Item = Entity; type Item = Entity;
@ -192,22 +215,34 @@ where
/// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`].
/// ///
/// Traverses the hierarchy depth-first. /// Traverses the hierarchy depth-first.
pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> pub struct DescendantDepthFirstIter<
where 'w,
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>, 's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: RelationshipTarget,
> where
D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
children_query: &'w Query<'w, 's, D, F>, children_query: &'w Query<'w, 's, D, F, S>,
stack: SmallVec<[Entity; 8]>, stack: SmallVec<[Entity; 8]>,
} }
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> impl<
DescendantDepthFirstIter<'w, 's, D, F, S> 'w,
's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: RelationshipTarget,
> DescendantDepthFirstIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
SourceIter<'w, S>: DoubleEndedIterator, SourceIter<'w, R>: DoubleEndedIterator,
{ {
/// Returns a new [`DescendantDepthFirstIter`]. /// Returns a new [`DescendantDepthFirstIter`].
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { pub fn new(children_query: &'w Query<'w, 's, D, F, S>, entity: Entity) -> Self {
DescendantDepthFirstIter { DescendantDepthFirstIter {
children_query, children_query,
stack: children_query stack: children_query
@ -217,11 +252,17 @@ where
} }
} }
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator impl<
for DescendantDepthFirstIter<'w, 's, D, F, S> 'w,
's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: RelationshipTarget,
> Iterator for DescendantDepthFirstIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w S>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
SourceIter<'w, S>: DoubleEndedIterator, SourceIter<'w, R>: DoubleEndedIterator,
{ {
type Item = Entity; type Item = Entity;
@ -237,20 +278,33 @@ where
} }
/// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`]. /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> pub struct AncestorIter<
where 'w,
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>, 's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: Relationship,
> where
D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
parent_query: &'w Query<'w, 's, D, F>, parent_query: &'w Query<'w, 's, D, F, S>,
next: Option<Entity>, next: Option<Entity>,
} }
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R> impl<
'w,
's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: Relationship,
> AncestorIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
/// Returns a new [`AncestorIter`]. /// Returns a new [`AncestorIter`].
pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { pub fn new(parent_query: &'w Query<'w, 's, D, F, S>, entity: Entity) -> Self {
AncestorIter { AncestorIter {
parent_query, parent_query,
next: Some(entity), next: Some(entity),
@ -258,10 +312,16 @@ where
} }
} }
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> Iterator impl<
for AncestorIter<'w, 's, D, F, R> 'w,
's,
D: QueryData,
F: QueryFilter,
S: Deref<Target = QueryState<D, F>>,
R: Relationship,
> Iterator for AncestorIter<'w, 's, D, F, S, R>
where where
D::ReadOnly: QueryData<Item<'w, 's> = &'w R>, D::ReadOnly: QueryData<Item<'w, 'w> = &'w R>,
{ {
type Item = Entity; type Item = Entity;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
---
title: Combine `Query` and `QueryLens`
pull_requests: [18162]
---
The `QueryLens::query()` method has been deprecated.
The `QueryLens` type has now been combined with `Query`, so most methods can be called directly on the `QueryLens` and the call can simply be removed.
If that doesn't work and you do need a fresh `Query`, the call to `.query()` can be replaced with `.reborrow()`.
```rust
fn with_query(query: Query<&T>) {}
fn with_lens(lens: QueryLens<&T>) -> Result {
// 0.16
for item in lens.query().iter() {}
with_query(lens.query());
// 0.17
for item in lens.iter() {}
with_query(lens.reborrow());
}
```