use crate::{
entity::Entity,
query::{QueryData, QueryFilter},
relationship::{Relationship, RelationshipTarget},
system::Query,
};
use alloc::collections::VecDeque;
use smallvec::SmallVec;
use super::SourceIter;
impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
pub fn related<R: Relationship>(&'w self, entity: Entity) -> Option<Entity>
where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w R>,
{
self.get(entity).map(R::get).ok()
}
pub fn relationship_sources<S: RelationshipTarget>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'w
where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
{
self.get(entity)
.into_iter()
.flat_map(RelationshipTarget::iter)
}
pub fn root_ancestor<R: Relationship>(&'w self, entity: Entity) -> Entity
where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w R>,
{
match self.get(entity) {
Ok(parent) => self.root_ancestor(parent.get()),
Err(_) => entity,
}
}
pub fn iter_leaves<S: RelationshipTarget>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'w
where
<D as QueryData>::ReadOnly: QueryData<Item<'w> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator,
{
self.iter_descendants_depth_first(entity).filter(|entity| {
self.get(*entity)
.map(|children| children.len() == 0)
.unwrap_or(true)
})
}
pub fn iter_siblings<R: Relationship>(
&'w self,
entity: Entity,
) -> impl Iterator<Item = Entity> + 'w
where
D::ReadOnly: QueryData<Item<'w> = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>,
{
self.get(entity)
.ok()
.and_then(|(maybe_parent, _)| maybe_parent.map(R::get))
.and_then(|parent| self.get(parent).ok())
.and_then(|(_, maybe_children)| maybe_children)
.into_iter()
.flat_map(move |children| children.iter().filter(move |child| *child != entity))
}
pub fn iter_descendants<S: RelationshipTarget>(
&'w self,
entity: Entity,
) -> DescendantIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
{
DescendantIter::new(self, entity)
}
pub fn iter_descendants_depth_first<S: RelationshipTarget>(
&'w self,
entity: Entity,
) -> DescendantDepthFirstIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator,
{
DescendantDepthFirstIter::new(self, entity)
}
pub fn iter_ancestors<R: Relationship>(
&'w self,
entity: Entity,
) -> AncestorIter<'w, 's, D, F, R>
where
D::ReadOnly: QueryData<Item<'w> = &'w R>,
{
AncestorIter::new(self, entity)
}
}
pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
{
children_query: &'w Query<'w, 's, D, F>,
vecdeque: VecDeque<Entity>,
}
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
{
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
DescendantIter {
children_query,
vecdeque: children_query
.get(entity)
.into_iter()
.flat_map(RelationshipTarget::iter)
.collect(),
}
}
}
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator
for DescendantIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
{
type Item = Entity;
fn next(&mut self) -> Option<Self::Item> {
let entity = self.vecdeque.pop_front()?;
if let Ok(children) = self.children_query.get(entity) {
self.vecdeque.extend(children.iter());
}
Some(entity)
}
}
pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
{
children_query: &'w Query<'w, 's, D, F>,
stack: SmallVec<[Entity; 8]>,
}
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget>
DescendantDepthFirstIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator,
{
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
DescendantDepthFirstIter {
children_query,
stack: children_query
.get(entity)
.map_or(SmallVec::new(), |children| children.iter().rev().collect()),
}
}
}
impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator
for DescendantDepthFirstIter<'w, 's, D, F, S>
where
D::ReadOnly: QueryData<Item<'w> = &'w S>,
SourceIter<'w, S>: DoubleEndedIterator,
{
type Item = Entity;
fn next(&mut self) -> Option<Self::Item> {
let entity = self.stack.pop()?;
if let Ok(children) = self.children_query.get(entity) {
self.stack.extend(children.iter().rev());
}
Some(entity)
}
}
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship>
where
D::ReadOnly: QueryData<Item<'w> = &'w R>,
{
parent_query: &'w Query<'w, 's, D, F>,
next: Option<Entity>,
}
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R>
where
D::ReadOnly: QueryData<Item<'w> = &'w R>,
{
pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
AncestorIter {
parent_query,
next: Some(entity),
}
}
}
impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> Iterator
for AncestorIter<'w, 's, D, F, R>
where
D::ReadOnly: QueryData<Item<'w> = &'w R>,
{
type Item = Entity;
fn next(&mut self) -> Option<Self::Item> {
self.next = self.parent_query.get(self.next?).ok().map(R::get);
self.next
}
}