Path: blob/main/crates/bevy_ecs/src/relationship/relationship_query.rs
6600 views
use crate::{1entity::Entity,2query::{QueryData, QueryFilter},3relationship::{Relationship, RelationshipTarget},4system::Query,5};6use alloc::collections::VecDeque;7use smallvec::SmallVec;89use super::SourceIter;1011impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {12/// If the given `entity` contains the `R` [`Relationship`] component, returns the13/// target entity of that relationship.14pub fn related<R: Relationship>(&'w self, entity: Entity) -> Option<Entity>15where16<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w R>,17{18self.get(entity).map(R::get).ok()19}2021/// If the given `entity` contains the `S` [`RelationshipTarget`] component, returns the22/// source entities stored on that component.23pub fn relationship_sources<S: RelationshipTarget>(24&'w self,25entity: Entity,26) -> impl Iterator<Item = Entity> + 'w27where28<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>,29{30self.get(entity)31.into_iter()32.flat_map(RelationshipTarget::iter)33}3435/// Recursively walks up the tree defined by the given `R` [`Relationship`] until36/// there are no more related entities, returning the "root entity" of the relationship hierarchy.37///38/// # Warning39///40/// For relationship graphs that contain loops, this could loop infinitely.41/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.42pub fn root_ancestor<R: Relationship>(&'w self, entity: Entity) -> Entity43where44<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w R>,45{46// Recursively search up the tree until we're out of parents47match self.get(entity) {48Ok(parent) => self.root_ancestor(parent.get()),49Err(_) => entity,50}51}5253/// Iterates all "leaf entities" as defined by the [`RelationshipTarget`] hierarchy.54///55/// # Warning56///57/// For relationship graphs that contain loops, this could loop infinitely.58/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.59pub fn iter_leaves<S: RelationshipTarget>(60&'w self,61entity: Entity,62) -> impl Iterator<Item = Entity> + use<'w, 's, S, D, F>63where64<D as QueryData>::ReadOnly: QueryData<Item<'w, 's> = &'w S>,65SourceIter<'w, S>: DoubleEndedIterator,66{67self.iter_descendants_depth_first(entity).filter(|entity| {68self.get(*entity)69// These are leaf nodes if they have the `Children` component but it's empty70.map(|children| children.len() == 0)71// Or if they don't have the `Children` component at all72.unwrap_or(true)73})74}7576/// Iterates all sibling entities that also have the `R` [`Relationship`] with the same target entity.77pub fn iter_siblings<R: Relationship>(78&'w self,79entity: Entity,80) -> impl Iterator<Item = Entity> + 'w81where82D::ReadOnly: QueryData<Item<'w, 's> = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>,83{84self.get(entity)85.ok()86.and_then(|(maybe_parent, _)| maybe_parent.map(R::get))87.and_then(|parent| self.get(parent).ok())88.and_then(|(_, maybe_children)| maybe_children)89.into_iter()90.flat_map(move |children| children.iter().filter(move |child| *child != entity))91}9293/// Iterates all descendant entities as defined by the given `entity`'s [`RelationshipTarget`] and their recursive94/// [`RelationshipTarget`].95///96/// # Warning97///98/// For relationship graphs that contain loops, this could loop infinitely.99/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.100pub fn iter_descendants<S: RelationshipTarget>(101&'w self,102entity: Entity,103) -> DescendantIter<'w, 's, D, F, S>104where105D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,106{107DescendantIter::new(self, entity)108}109110/// Iterates all descendant entities as defined by the given `entity`'s [`RelationshipTarget`] and their recursive111/// [`RelationshipTarget`] in depth-first order.112///113/// # Warning114///115/// For relationship graphs that contain loops, this could loop infinitely.116/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.117pub fn iter_descendants_depth_first<S: RelationshipTarget>(118&'w self,119entity: Entity,120) -> DescendantDepthFirstIter<'w, 's, D, F, S>121where122D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,123SourceIter<'w, S>: DoubleEndedIterator,124{125DescendantDepthFirstIter::new(self, entity)126}127128/// Iterates all ancestors of the given `entity` as defined by the `R` [`Relationship`].129///130/// # Warning131///132/// For relationship graphs that contain loops, this could loop infinitely.133/// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity.134pub fn iter_ancestors<R: Relationship>(135&'w self,136entity: Entity,137) -> AncestorIter<'w, 's, D, F, R>138where139D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,140{141AncestorIter::new(self, entity)142}143}144145/// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`].146///147/// Traverses the hierarchy breadth-first.148pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>149where150D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,151{152children_query: &'w Query<'w, 's, D, F>,153vecdeque: VecDeque<Entity>,154}155156impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S>157where158D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,159{160/// Returns a new [`DescendantIter`].161pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {162DescendantIter {163children_query,164vecdeque: children_query165.get(entity)166.into_iter()167.flat_map(RelationshipTarget::iter)168.collect(),169}170}171}172173impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator174for DescendantIter<'w, 's, D, F, S>175where176D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,177{178type Item = Entity;179180fn next(&mut self) -> Option<Self::Item> {181let entity = self.vecdeque.pop_front()?;182183if let Ok(children) = self.children_query.get(entity) {184self.vecdeque.extend(children.iter());185}186187Some(entity)188}189}190191/// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`].192///193/// Traverses the hierarchy depth-first.194pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>195where196D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,197{198children_query: &'w Query<'w, 's, D, F>,199stack: SmallVec<[Entity; 8]>,200}201202impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>203DescendantDepthFirstIter<'w, 's, D, F, S>204where205D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,206SourceIter<'w, S>: DoubleEndedIterator,207{208/// Returns a new [`DescendantDepthFirstIter`].209pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {210DescendantDepthFirstIter {211children_query,212stack: children_query213.get(entity)214.map_or(SmallVec::new(), |children| children.iter().rev().collect()),215}216}217}218219impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator220for DescendantDepthFirstIter<'w, 's, D, F, S>221where222D::ReadOnly: QueryData<Item<'w, 's> = &'w S>,223SourceIter<'w, S>: DoubleEndedIterator,224{225type Item = Entity;226227fn next(&mut self) -> Option<Self::Item> {228let entity = self.stack.pop()?;229230if let Ok(children) = self.children_query.get(entity) {231self.stack.extend(children.iter().rev());232}233234Some(entity)235}236}237238/// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].239pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship>240where241D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,242{243parent_query: &'w Query<'w, 's, D, F>,244next: Option<Entity>,245}246247impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R>248where249D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,250{251/// Returns a new [`AncestorIter`].252pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {253AncestorIter {254parent_query,255next: Some(entity),256}257}258}259260impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> Iterator261for AncestorIter<'w, 's, D, F, R>262where263D::ReadOnly: QueryData<Item<'w, 's> = &'w R>,264{265type Item = Entity;266267fn next(&mut self) -> Option<Self::Item> {268self.next = self.parent_query.get(self.next?).ok().map(R::get);269self.next270}271}272273274