Skip to content

Commit 0a150b0

Browse files
alice-i-cecilevilloratornityItsDoot
authored
Add more tools for traversing hierarchies (#15627)
# Objective - Working with hierarchies in Bevy is far too tedious due to a lack of helper functions. - This is the first half of #15609. ## Solution Extend [`HierarchyQueryExt`](https://docs.rs/bevy/latest/bevy/hierarchy/trait.HierarchyQueryExt) with the following methods: - `parent` - `children` - `root_parent` - `iter_leaves` - `iter_siblings` - `iter_descendants_depth_first` I've opted to make both `iter_leaves` and `iter_siblings` collect the list of matching Entities for now, rather that operate by reference like the existing `iter_descendants`. This was simpler, and in the case of `iter_siblings` especially, the number of matching entities is likely to be much smaller. I've kept the generics in the type signature however, so we can go back and optimize that freely without a breaking change whenever we want. ## Testing I've added some basic testing, but they're currently failing. If you'd like to help, I'd welcome suggestions or a PR to my PR over the weekend <3 --------- Co-authored-by: Viktor Gustavsson <[email protected]> Co-authored-by: poopy <[email protected]> Co-authored-by: Christian Hughes <[email protected]>
1 parent 584d148 commit 0a150b0

File tree

1 file changed

+241
-9
lines changed

1 file changed

+241
-9
lines changed

crates/bevy_hierarchy/src/query_extension.rs

Lines changed: 241 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,54 @@ use bevy_ecs::{
55
query::{QueryData, QueryFilter, WorldQuery},
66
system::Query,
77
};
8+
use smallvec::SmallVec;
89

910
use crate::{Children, Parent};
1011

1112
/// An extension trait for [`Query`] that adds hierarchy related methods.
1213
pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
14+
/// Returns the parent [`Entity`] of the given `entity`, if any.
15+
fn parent(&'w self, entity: Entity) -> Option<Entity>
16+
where
17+
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>;
18+
19+
/// Returns a slice over the [`Children`] of the given `entity`.
20+
///
21+
/// This may be empty if the `entity` has no children.
22+
fn children(&'w self, entity: Entity) -> &'w [Entity]
23+
where
24+
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
25+
26+
/// Returns the topmost ancestor of the given `entity`.
27+
///
28+
/// This may be the entity itself if it has no parent.
29+
fn root_ancestor(&'w self, entity: Entity) -> Entity
30+
where
31+
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>;
32+
33+
/// Returns an [`Iterator`] of [`Entity`]s over the leaves of the hierarchy that are underneath this `entity`.
34+
///
35+
/// Only entities which have no children are considered leaves.
36+
/// This will not include the entity itself, and will not include any entities which are not descendants of the entity,
37+
/// even if they are leaves in the same hierarchical tree.
38+
///
39+
/// Traverses the hierarchy depth-first.
40+
fn iter_leaves(&'w self, entity: Entity) -> impl Iterator<Item = Entity> + 'w
41+
where
42+
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
43+
44+
/// Returns an [`Iterator`] of [`Entity`]s over the `entity`s immediate siblings, who share the same parent.
45+
///
46+
/// The entity itself is not included in the iterator.
47+
fn iter_siblings(&'w self, entity: Entity) -> impl Iterator<Item = Entity>
48+
where
49+
D::ReadOnly: WorldQuery<Item<'w> = (Option<&'w Parent>, Option<&'w Children>)>;
50+
1351
/// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s descendants.
1452
///
1553
/// Can only be called on a [`Query`] of [`Children`] (i.e. `Query<&Children>`).
1654
///
17-
/// Traverses the hierarchy breadth-first.
55+
/// Traverses the hierarchy breadth-first and does not include the entity itself.
1856
///
1957
/// # Examples
2058
/// ```
@@ -34,8 +72,21 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
3472
where
3573
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
3674

75+
/// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s descendants.
76+
///
77+
/// Can only be called on a [`Query`] of [`Children`] (i.e. `Query<&Children>`).
78+
///
79+
/// This is a depth-first alternative to [`HierarchyQueryExt::iter_descendants`].
80+
fn iter_descendants_depth_first(
81+
&'w self,
82+
entity: Entity,
83+
) -> DescendantDepthFirstIter<'w, 's, D, F>
84+
where
85+
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>;
86+
3787
/// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s ancestors.
3888
///
89+
/// Does not include the entity itself.
3990
/// Can only be called on a [`Query`] of [`Parent`] (i.e. `Query<&Parent>`).
4091
///
4192
/// # Examples
@@ -58,13 +109,76 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
58109
}
59110

60111
impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Query<'w, 's, D, F> {
112+
fn parent(&'w self, entity: Entity) -> Option<Entity>
113+
where
114+
<D as QueryData>::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
115+
{
116+
self.get(entity).map(Parent::get).ok()
117+
}
118+
119+
fn children(&'w self, entity: Entity) -> &'w [Entity]
120+
where
121+
<D as QueryData>::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
122+
{
123+
self.get(entity)
124+
.map_or(&[] as &[Entity], |children| children)
125+
}
126+
127+
fn root_ancestor(&'w self, entity: Entity) -> Entity
128+
where
129+
<D as QueryData>::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
130+
{
131+
// Recursively search up the tree until we're out of parents
132+
match self.get(entity) {
133+
Ok(parent) => self.root_ancestor(parent.get()),
134+
Err(_) => entity,
135+
}
136+
}
137+
138+
fn iter_leaves(&'w self, entity: Entity) -> impl Iterator<Item = Entity>
139+
where
140+
<D as QueryData>::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
141+
{
142+
self.iter_descendants_depth_first(entity).filter(|entity| {
143+
self.get(*entity)
144+
// These are leaf nodes if they have the `Children` component but it's empty
145+
.map(|children| children.is_empty())
146+
// Or if they don't have the `Children` component at all
147+
.unwrap_or(true)
148+
})
149+
}
150+
151+
fn iter_siblings(&'w self, entity: Entity) -> impl Iterator<Item = Entity>
152+
where
153+
D::ReadOnly: WorldQuery<Item<'w> = (Option<&'w Parent>, Option<&'w Children>)>,
154+
{
155+
self.get(entity)
156+
.ok()
157+
.and_then(|(maybe_parent, _)| maybe_parent.map(Parent::get))
158+
.and_then(|parent| self.get(parent).ok())
159+
.and_then(|(_, maybe_children)| maybe_children)
160+
.into_iter()
161+
.flat_map(move |children| children.iter().filter(move |child| **child != entity))
162+
.copied()
163+
}
164+
61165
fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, D, F>
62166
where
63167
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
64168
{
65169
DescendantIter::new(self, entity)
66170
}
67171

172+
fn iter_descendants_depth_first(
173+
&'w self,
174+
entity: Entity,
175+
) -> DescendantDepthFirstIter<'w, 's, D, F>
176+
where
177+
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
178+
{
179+
DescendantDepthFirstIter::new(self, entity)
180+
}
181+
68182
fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F>
69183
where
70184
D::ReadOnly: WorldQuery<Item<'w> = &'w Parent>,
@@ -119,6 +233,51 @@ where
119233
}
120234
}
121235

236+
/// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`].
237+
///
238+
/// Traverses the hierarchy depth-first.
239+
pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter>
240+
where
241+
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
242+
{
243+
children_query: &'w Query<'w, 's, D, F>,
244+
stack: SmallVec<[Entity; 8]>,
245+
}
246+
247+
impl<'w, 's, D: QueryData, F: QueryFilter> DescendantDepthFirstIter<'w, 's, D, F>
248+
where
249+
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
250+
{
251+
/// Returns a new [`DescendantDepthFirstIter`].
252+
pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self {
253+
DescendantDepthFirstIter {
254+
children_query,
255+
stack: children_query
256+
.get(entity)
257+
.map_or(SmallVec::new(), |children| {
258+
children.iter().rev().copied().collect()
259+
}),
260+
}
261+
}
262+
}
263+
264+
impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for DescendantDepthFirstIter<'w, 's, D, F>
265+
where
266+
D::ReadOnly: WorldQuery<Item<'w> = &'w Children>,
267+
{
268+
type Item = Entity;
269+
270+
fn next(&mut self) -> Option<Self::Item> {
271+
let entity = self.stack.pop()?;
272+
273+
if let Ok(children) = self.children_query.get(entity) {
274+
self.stack.extend(children.iter().rev().copied());
275+
}
276+
277+
Some(entity)
278+
}
279+
}
280+
122281
/// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`].
123282
pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter>
124283
where
@@ -170,35 +329,108 @@ mod tests {
170329
fn descendant_iter() {
171330
let world = &mut World::new();
172331

173-
let [a, b, c, d] = core::array::from_fn(|i| world.spawn(A(i)).id());
332+
let [a0, a1, a2, a3] = core::array::from_fn(|i| world.spawn(A(i)).id());
174333

175-
world.entity_mut(a).add_children(&[b, c]);
176-
world.entity_mut(c).add_children(&[d]);
334+
world.entity_mut(a0).add_children(&[a1, a2]);
335+
world.entity_mut(a1).add_children(&[a3]);
177336

178337
let mut system_state = SystemState::<(Query<&Children>, Query<&A>)>::new(world);
179338
let (children_query, a_query) = system_state.get(world);
180339

181340
let result: Vec<_> = a_query
182-
.iter_many(children_query.iter_descendants(a))
341+
.iter_many(children_query.iter_descendants(a0))
183342
.collect();
184343

185344
assert_eq!([&A(1), &A(2), &A(3)], result.as_slice());
186345
}
187346

347+
#[test]
348+
fn descendant_depth_first_iter() {
349+
let world = &mut World::new();
350+
351+
let [a0, a1, a2, a3] = core::array::from_fn(|i| world.spawn(A(i)).id());
352+
353+
world.entity_mut(a0).add_children(&[a1, a2]);
354+
world.entity_mut(a1).add_children(&[a3]);
355+
356+
let mut system_state = SystemState::<(Query<&Children>, Query<&A>)>::new(world);
357+
let (children_query, a_query) = system_state.get(world);
358+
359+
let result: Vec<_> = a_query
360+
.iter_many(children_query.iter_descendants_depth_first(a0))
361+
.collect();
362+
363+
assert_eq!([&A(1), &A(3), &A(2)], result.as_slice());
364+
}
365+
188366
#[test]
189367
fn ancestor_iter() {
190368
let world = &mut World::new();
191369

192-
let [a, b, c] = core::array::from_fn(|i| world.spawn(A(i)).id());
370+
let [a0, a1, a2] = core::array::from_fn(|i| world.spawn(A(i)).id());
193371

194-
world.entity_mut(a).add_children(&[b]);
195-
world.entity_mut(b).add_children(&[c]);
372+
world.entity_mut(a0).add_children(&[a1]);
373+
world.entity_mut(a1).add_children(&[a2]);
196374

197375
let mut system_state = SystemState::<(Query<&Parent>, Query<&A>)>::new(world);
198376
let (parent_query, a_query) = system_state.get(world);
199377

200-
let result: Vec<_> = a_query.iter_many(parent_query.iter_ancestors(c)).collect();
378+
let result: Vec<_> = a_query.iter_many(parent_query.iter_ancestors(a2)).collect();
201379

202380
assert_eq!([&A(1), &A(0)], result.as_slice());
203381
}
382+
383+
#[test]
384+
fn root_ancestor() {
385+
let world = &mut World::new();
386+
387+
let [a0, a1, a2] = core::array::from_fn(|i| world.spawn(A(i)).id());
388+
389+
world.entity_mut(a0).add_children(&[a1]);
390+
world.entity_mut(a1).add_children(&[a2]);
391+
392+
let mut system_state = SystemState::<Query<&Parent>>::new(world);
393+
let parent_query = system_state.get(world);
394+
395+
assert_eq!(a0, parent_query.root_ancestor(a2));
396+
assert_eq!(a0, parent_query.root_ancestor(a1));
397+
assert_eq!(a0, parent_query.root_ancestor(a0));
398+
}
399+
400+
#[test]
401+
fn leaf_iter() {
402+
let world = &mut World::new();
403+
404+
let [a0, a1, a2, a3] = core::array::from_fn(|i| world.spawn(A(i)).id());
405+
406+
world.entity_mut(a0).add_children(&[a1, a2]);
407+
world.entity_mut(a1).add_children(&[a3]);
408+
409+
let mut system_state = SystemState::<(Query<&Children>, Query<&A>)>::new(world);
410+
let (children_query, a_query) = system_state.get(world);
411+
412+
let result: Vec<_> = a_query.iter_many(children_query.iter_leaves(a0)).collect();
413+
414+
assert_eq!([&A(3), &A(2)], result.as_slice());
415+
}
416+
417+
#[test]
418+
fn siblings() {
419+
let world = &mut World::new();
420+
421+
let [a0, a1, a2, a3, a4] = core::array::from_fn(|i| world.spawn(A(i)).id());
422+
423+
world.entity_mut(a0).add_children(&[a1, a2, a3]);
424+
world.entity_mut(a2).add_children(&[a4]);
425+
426+
let mut system_state =
427+
SystemState::<(Query<(Option<&Parent>, Option<&Children>)>, Query<&A>)>::new(world);
428+
let (hierarchy_query, a_query) = system_state.get(world);
429+
430+
let result: Vec<_> = a_query
431+
.iter_many(hierarchy_query.iter_siblings(a1))
432+
.collect();
433+
434+
assert_eq!([&A(2), &A(3)], result.as_slice());
435+
}
204436
}

0 commit comments

Comments
 (0)