use alloc::collections::VecDeque;
use bevy_ecs::{
entity::Entity,
query::{QueryData, QueryFilter, WorldQuery},
system::Query,
};
use smallvec::SmallVec;
use crate::{Children, Parent};
pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
fn parent(&'w self, entity: Entity) -> Option<Entity>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>;
fn children(&'w self, entity: Entity) -> &'w [Entity]
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
fn root_ancestor(&'w self, entity: Entity) -> Entity
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>;
fn iter_leaves(&'w self, entity: Entity) -> impl Iterator<Item = Entity> + 'w
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
fn iter_siblings(&'w self, entity: Entity) -> impl Iterator<Item = Entity>
where
D::ReadOnly: WorldQuery<Item<'w> = (Option<&'w Parent>, Option<&'w Children>)>;
fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
fn iter_descendants_depth_first(
&'w self,
entity: Entity,
) -> DescendantDepthFirstIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>;
}
impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Query<'w, 's, D, F> {
fn parent(&'w self, entity: Entity) -> Option<Entity>
where
<D as QueryData>::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
self.get(entity).map(Parent::get).ok()
}
fn children(&'w self, entity: Entity) -> &'w [Entity]
where
<D as QueryData>::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
self.get(entity)
.map_or(&[] as &[Entity], |children| children)
}
fn root_ancestor(&'w self, entity: Entity) -> Entity
where
<D as QueryData>::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
match self.get(entity) {
Ok(parent) => self.root_ancestor(parent.get()),
Err(_) => entity,
}
}
fn iter_leaves(&'w self, entity: Entity) -> impl Iterator<Item = Entity>
where
<D as QueryData>::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
self.iter_descendants_depth_first(entity).filter(|entity| {
self.get(*entity)
.map(|children| children.is_empty())
.unwrap_or(true)
})
}
fn iter_siblings(&'w self, entity: Entity) -> impl Iterator<Item = Entity>
where
D::ReadOnly: WorldQuery<Item<'w> = (Option<&'w Parent>, Option<&'w Children>)>,
{
self.get(entity)
.ok()
.and_then(|(maybe_parent, _)| maybe_parent.map(Parent::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))
.copied()
}
fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
DescendantIter::new(self, entity)
}
fn iter_descendants_depth_first(
&'w self,
entity: Entity,
) -> DescendantDepthFirstIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
DescendantDepthFirstIter::new(self, entity)
}
fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
AncestorIter::new(self, entity)
}
}
pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
children_query: &'w Query<'w, 's, D, F>,
vecdeque: VecDeque<Entity>,
}
impl<'w, 's, D: QueryData, F: QueryFilter> DescendantIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
DescendantIter {
children_query,
vecdeque: children_query
.get(entity)
.into_iter()
.flatten()
.copied()
.collect(),
}
}
}
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for DescendantIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
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);
}
Some(entity)
}
}
pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
children_query: &'w Query<'w, 's, D, F>,
stack: SmallVec<[Entity; 8]>,
}
impl<'w, 's, D: QueryData, F: QueryFilter> DescendantDepthFirstIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
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().copied().collect()
}),
}
}
}
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for DescendantDepthFirstIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
{
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().copied());
}
Some(entity)
}
}
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
parent_query: &'w Query<'w, 's, D, F>,
next: Option<Entity>,
}
impl<'w, 's, D: QueryData, F: QueryFilter> AncestorIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
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> Iterator for AncestorIter<'w, 's, D, F>
where
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
{
type Item = Entity;
fn next(&mut self) -> Option<Self::Item> {
self.next = self.parent_query.get(self.next?).ok().map(Parent::get);
self.next
}
}
#[cfg(test)]
mod tests {
use bevy_ecs::{
prelude::Component,
system::{Query, SystemState},
world::World,
};
use crate::{query_extension::HierarchyQueryExt, BuildChildren, Children, Parent};
#[derive(Component, PartialEq, Debug)]
struct A(usize);
#[test]
fn descendant_iter() {
let world = &mut World::new();
let [a0, a1, a2, a3] = core::array::from_fn(|i| world.spawn(A(i)).id());
world.entity_mut(a0).add_children(&[a1, a2]);
world.entity_mut(a1).add_children(&[a3]);
let mut system_state = SystemState::<(Query<&Children>, Query<&A>)>::new(world);
let (children_query, a_query) = system_state.get(world);
let result: Vec<_> = a_query
.iter_many(children_query.iter_descendants(a0))
.collect();
assert_eq!([&A(1), &A(2), &A(3)], result.as_slice());
}
#[test]
fn descendant_depth_first_iter() {
let world = &mut World::new();
let [a0, a1, a2, a3] = core::array::from_fn(|i| world.spawn(A(i)).id());
world.entity_mut(a0).add_children(&[a1, a2]);
world.entity_mut(a1).add_children(&[a3]);
let mut system_state = SystemState::<(Query<&Children>, Query<&A>)>::new(world);
let (children_query, a_query) = system_state.get(world);
let result: Vec<_> = a_query
.iter_many(children_query.iter_descendants_depth_first(a0))
.collect();
assert_eq!([&A(1), &A(3), &A(2)], result.as_slice());
}
#[test]
fn ancestor_iter() {
let world = &mut World::new();
let [a0, a1, a2] = core::array::from_fn(|i| world.spawn(A(i)).id());
world.entity_mut(a0).add_children(&[a1]);
world.entity_mut(a1).add_children(&[a2]);
let mut system_state = SystemState::<(Query<&Parent>, Query<&A>)>::new(world);
let (parent_query, a_query) = system_state.get(world);
let result: Vec<_> = a_query.iter_many(parent_query.iter_ancestors(a2)).collect();
assert_eq!([&A(1), &A(0)], result.as_slice());
}
#[test]
fn root_ancestor() {
let world = &mut World::new();
let [a0, a1, a2] = core::array::from_fn(|i| world.spawn(A(i)).id());
world.entity_mut(a0).add_children(&[a1]);
world.entity_mut(a1).add_children(&[a2]);
let mut system_state = SystemState::<Query<&Parent>>::new(world);
let parent_query = system_state.get(world);
assert_eq!(a0, parent_query.root_ancestor(a2));
assert_eq!(a0, parent_query.root_ancestor(a1));
assert_eq!(a0, parent_query.root_ancestor(a0));
}
#[test]
fn leaf_iter() {
let world = &mut World::new();
let [a0, a1, a2, a3] = core::array::from_fn(|i| world.spawn(A(i)).id());
world.entity_mut(a0).add_children(&[a1, a2]);
world.entity_mut(a1).add_children(&[a3]);
let mut system_state = SystemState::<(Query<&Children>, Query<&A>)>::new(world);
let (children_query, a_query) = system_state.get(world);
let result: Vec<_> = a_query.iter_many(children_query.iter_leaves(a0)).collect();
assert_eq!([&A(3), &A(2)], result.as_slice());
}
#[test]
fn siblings() {
let world = &mut World::new();
let [a0, a1, a2, a3, a4] = core::array::from_fn(|i| world.spawn(A(i)).id());
world.entity_mut(a0).add_children(&[a1, a2, a3]);
world.entity_mut(a2).add_children(&[a4]);
let mut system_state =
SystemState::<(Query<(Option<&Parent>, Option<&Children>)>, Query<&A>)>::new(world);
let (hierarchy_query, a_query) = system_state.get(world);
let result: Vec<_> = a_query
.iter_many(hierarchy_query.iter_siblings(a1))
.collect();
assert_eq!([&A(2), &A(3)], result.as_slice());
}
}