From ff6f7840d7a0b686731f2e2c77c71829ae1bbb6d Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 6 Oct 2022 18:38:30 +0200 Subject: [PATCH 01/10] bop --- crates/bevy_hierarchy/src/lib.rs | 5 +- crates/bevy_hierarchy/src/query_extension.rs | 125 +++++++++++++++++++ examples/3d/update_gltf_scene.rs | 11 +- 3 files changed, 130 insertions(+), 11 deletions(-) create mode 100644 crates/bevy_hierarchy/src/query_extension.rs diff --git a/crates/bevy_hierarchy/src/lib.rs b/crates/bevy_hierarchy/src/lib.rs index 1f8c08d9c76c4..0740df0259b11 100644 --- a/crates/bevy_hierarchy/src/lib.rs +++ b/crates/bevy_hierarchy/src/lib.rs @@ -19,11 +19,14 @@ pub use events::*; mod valid_parent_check_plugin; pub use valid_parent_check_plugin::*; +mod query_extension; + #[doc(hidden)] pub mod prelude { #[doc(hidden)] pub use crate::{ - child_builder::*, components::*, hierarchy::*, HierarchyPlugin, ValidParentCheckPlugin, + child_builder::*, components::*, hierarchy::*, query_extension::*, HierarchyPlugin, + ValidParentCheckPlugin, }; } diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs new file mode 100644 index 0000000000000..682e45119c3d5 --- /dev/null +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -0,0 +1,125 @@ +use std::collections::VecDeque; + +use bevy_ecs::{ + entity::Entity, + query::{ReadOnlyWorldQuery, WorldQuery, WorldQueryGats}, + system::Query, +}; + +use crate::{Children, Parent}; + +/// Extension trait for [`Query`] +pub trait HierarchyQueryExt<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> { + /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s descendants. + /// + /// Traverses the hierarchy breadth-first. + fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, Q, F> + where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Children>; + + /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s ancestors. + fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, Q, F> + where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Parent>; +} + +impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> HierarchyQueryExt<'w, 's, Q, F> + for Query<'w, 's, Q, F> +{ + fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, Q, F> + where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Children>, + { + DescendantIter::new(self, entity) + } + + fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, Q, F> + where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Parent>, + { + AncestorIter::new(self, entity) + } +} + +/// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. +/// +/// Traverses the hierarchy breadth-first. +pub struct DescendantIter<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> +where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Children>, +{ + children_query: &'w Query<'w, 's, Q, F>, + vecdeque: VecDeque, +} + +impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> DescendantIter<'w, 's, Q, F> +where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Children>, +{ + /// Returns a new [`DescendantIter`]. + pub fn new(children_query: &'w Query<'w, 's, Q, F>, entity: Entity) -> Self { + DescendantIter { + children_query, + vecdeque: children_query + .get(entity) + .into_iter() + .flatten() + .copied() + .collect(), + } + } +} + +impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Iterator for DescendantIter<'w, 's, Q, F> +where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Children>, +{ + type Item = Entity; + + fn next(&mut self) -> Option { + let entity = self.vecdeque.pop_front()?; + + if let Ok(children) = self.children_query.get(entity) { + self.vecdeque.extend(children); + } + + Some(entity) + } +} + +/// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`]. +pub struct AncestorIter<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> +where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Parent>, +{ + parent_query: &'w Query<'w, 's, Q, F>, + next: Option, +} + +impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> AncestorIter<'w, 's, Q, F> +where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Parent>, +{ + /// Returns a new [`AncestorIter`]. + pub fn new(parent_query: &'w Query<'w, 's, Q, F>, entity: Entity) -> Self { + AncestorIter { + parent_query, + next: parent_query.get(entity).ok().map(|p| p.get()), + } + } +} + +impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Iterator for AncestorIter<'w, 's, Q, F> +where + Q::ReadOnly: WorldQueryGats<'w, Item = &'w Parent>, +{ + type Item = Entity; + + fn next(&mut self) -> Option { + let next = self.next?; + + self.next = self.parent_query.get(next).ok().map(|p| p.get()); + + Some(next) + } +} diff --git a/examples/3d/update_gltf_scene.rs b/examples/3d/update_gltf_scene.rs index 265cf09f375b9..07f312c793995 100644 --- a/examples/3d/update_gltf_scene.rs +++ b/examples/3d/update_gltf_scene.rs @@ -51,7 +51,7 @@ fn move_scene_entities( ) { for moved_scene_entity in &moved_scene { let mut offset = 0.; - iter_hierarchy(moved_scene_entity, &children, &mut |entity| { + for entity in children.iter_descendants(moved_scene_entity) { if let Ok(mut transform) = transforms.get_mut(entity) { transform.translation = Vec3::new( offset * time.seconds_since_startup().sin() as f32 / 20., @@ -60,15 +60,6 @@ fn move_scene_entities( ); offset += 1.0; } - }); - } -} - -fn iter_hierarchy(entity: Entity, children_query: &Query<&Children>, f: &mut impl FnMut(Entity)) { - (f)(entity); - if let Ok(children) = children_query.get(entity) { - for child in children.iter().copied() { - iter_hierarchy(child, children_query, f); } } } From a381808fd25fdf8ce528311885e1953f32ee1ae0 Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 6 Oct 2022 18:58:02 +0200 Subject: [PATCH 02/10] docs --- crates/bevy_hierarchy/src/query_extension.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index 682e45119c3d5..89de010d73e46 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -8,7 +8,7 @@ use bevy_ecs::{ use crate::{Children, Parent}; -/// Extension trait for [`Query`] +/// An extension trait for [`Query`] that adds hierarchy related methods. pub trait HierarchyQueryExt<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> { /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s descendants. /// From 1b48b84807d24b395c22888c418f8ebb22ac4f02 Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 13 Oct 2022 12:22:05 +0200 Subject: [PATCH 03/10] Add tests --- crates/bevy_hierarchy/src/query_extension.rs | 67 ++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index 89de010d73e46..10e230c020813 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -123,3 +123,70 @@ where Some(next) } } + +#[cfg(test)] +mod tests { + use bevy_ecs::{ + prelude::Component, + system::{Query, SystemState, Command}, + world::World, + }; + + use crate::{Children, AddChild, query_extension::HierarchyQueryExt, Parent}; + + #[derive(Component, PartialEq, Debug)] + struct A(usize); + + #[test] + fn descendant_iter() { + let world = &mut World::new(); + + let [a, b, c, d] = std::array::from_fn(|i| world.spawn(A(i)).id()); + + AddChild { + parent: a, + child: b, + }.write(world); + + AddChild { + parent: a, + child: c, + }.write(world); + + AddChild { + parent: c, + child: d, + }.write(world); + + let mut system_param = SystemState::<(Query<&Children>, Query<&A>)>::new(world); + let (children_query, a_query) = system_param.get(world); + + let result: Vec<_> = a_query.iter_many(children_query.iter_descendants(a)).collect(); + + assert_eq!([&A(1), &A(2), &A(3)], result.as_slice()); + } + + #[test] + fn ancestor_iter() { + let world = &mut World::new(); + + let [a, b, c] = std::array::from_fn(|i| world.spawn(A(i)).id()); + + AddChild { + parent: a, + child: b, + }.write(world); + + AddChild { + parent: b, + child: c, + }.write(world); + + let mut system_param = SystemState::<(Query<&Parent>, Query<&A>)>::new(world); + let (parent_query, a_query) = system_param.get(world); + + let result: Vec<_> = a_query.iter_many(parent_query.iter_ancestors(c)).collect(); + + assert_eq!([&A(1), &A(0)], result.as_slice()); + } +} From 33bc1ead95870214e42fb9cff5ecba26f44fe274 Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 13 Oct 2022 12:22:39 +0200 Subject: [PATCH 04/10] fmt --- crates/bevy_hierarchy/src/query_extension.rs | 23 +++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index 10e230c020813..967f7568e5191 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -128,11 +128,11 @@ where mod tests { use bevy_ecs::{ prelude::Component, - system::{Query, SystemState, Command}, + system::{Command, Query, SystemState}, world::World, }; - use crate::{Children, AddChild, query_extension::HierarchyQueryExt, Parent}; + use crate::{query_extension::HierarchyQueryExt, AddChild, Children, Parent}; #[derive(Component, PartialEq, Debug)] struct A(usize); @@ -146,22 +146,27 @@ mod tests { AddChild { parent: a, child: b, - }.write(world); + } + .write(world); AddChild { parent: a, child: c, - }.write(world); + } + .write(world); AddChild { parent: c, child: d, - }.write(world); + } + .write(world); let mut system_param = SystemState::<(Query<&Children>, Query<&A>)>::new(world); let (children_query, a_query) = system_param.get(world); - let result: Vec<_> = a_query.iter_many(children_query.iter_descendants(a)).collect(); + let result: Vec<_> = a_query + .iter_many(children_query.iter_descendants(a)) + .collect(); assert_eq!([&A(1), &A(2), &A(3)], result.as_slice()); } @@ -175,12 +180,14 @@ mod tests { AddChild { parent: a, child: b, - }.write(world); + } + .write(world); AddChild { parent: b, child: c, - }.write(world); + } + .write(world); let mut system_param = SystemState::<(Query<&Parent>, Query<&A>)>::new(world); let (parent_query, a_query) = system_param.get(world); From 6d4afbf6c8a5b382203f74a44073e5bfd92cfa3b Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 13 Oct 2022 12:44:11 +0200 Subject: [PATCH 05/10] moar docs --- crates/bevy_hierarchy/src/query_extension.rs | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index 967f7568e5191..3019805b43acc 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -12,12 +12,46 @@ use crate::{Children, Parent}; pub trait HierarchyQueryExt<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> { /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s descendants. /// + /// Can only be called on a [`Query`] of [`Children`] (i.e. `Query<&Children>`). + /// /// Traverses the hierarchy breadth-first. + /// + /// # Examples + /// ``` + /// # use bevy_ecs::prelude::*; + /// # use bevy_hierarchy::prelude::*; + /// # #[derive(Component)] + /// # struct Marker; + /// fn system(query: Query>, children_query: Query<&Children>) { + /// let entity = query.single(); + /// for descendant in children_query.iter_descendants(entity) { + /// // Do something! + /// } + /// } + /// # bevy_ecs::system::assert_is_system(system); + /// ``` fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, Q, F> where Q::ReadOnly: WorldQueryGats<'w, Item = &'w Children>; /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s ancestors. + /// + /// Can only be called on a [`Query`] of [`Parent`] (i.e. `Query<&Parent>`). + /// + /// # Examples + /// ``` + /// # use bevy_ecs::prelude::*; + /// # use bevy_hierarchy::prelude::*; + /// # #[derive(Component)] + /// # struct Marker; + /// fn system(query: Query>, parent_query: Query<&Parent>) { + /// let entity = query.single(); + /// for ancestor in parent_query.iter_ancestors(entity) { + /// // Do something! + /// } + /// } + /// # bevy_ecs::system::assert_is_system(system); + /// ``` fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, Q, F> where Q::ReadOnly: WorldQueryGats<'w, Item = &'w Parent>; From 04d9e96610ed01b41cae92e8597ff0e390ac636e Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 13 Oct 2022 12:48:47 +0200 Subject: [PATCH 06/10] simplify --- crates/bevy_hierarchy/src/query_extension.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index 3019805b43acc..4257d83272d86 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -138,7 +138,7 @@ where pub fn new(parent_query: &'w Query<'w, 's, Q, F>, entity: Entity) -> Self { AncestorIter { parent_query, - next: parent_query.get(entity).ok().map(|p| p.get()), + next: Some(entity), } } } @@ -150,11 +150,8 @@ where type Item = Entity; fn next(&mut self) -> Option { - let next = self.next?; - - self.next = self.parent_query.get(next).ok().map(|p| p.get()); - - Some(next) + self.next = self.parent_query.get(self.next?).ok().map(|p| p.get()); + self.next } } From 5fd1e5781e66b62eae82f117f11f84c98640f979 Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 13 Oct 2022 13:58:13 +0200 Subject: [PATCH 07/10] use `Commands` in test --- crates/bevy_hierarchy/src/query_extension.rs | 49 +++++++------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index 4257d83272d86..7ac85d2b9a476 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -159,11 +159,11 @@ where mod tests { use bevy_ecs::{ prelude::Component, - system::{Command, Query, SystemState}, + system::{Commands, Query, SystemState}, world::World, }; - use crate::{query_extension::HierarchyQueryExt, AddChild, Children, Parent}; + use crate::{query_extension::HierarchyQueryExt, BuildChildren, Children, Parent}; #[derive(Component, PartialEq, Debug)] struct A(usize); @@ -174,26 +174,17 @@ mod tests { let [a, b, c, d] = std::array::from_fn(|i| world.spawn(A(i)).id()); - AddChild { - parent: a, - child: b, - } - .write(world); + let mut system_state = SystemState::::new(world); + let mut commands = system_state.get_mut(world); - AddChild { - parent: a, - child: c, - } - .write(world); + commands.entity(a).add_child(b); + commands.entity(a).add_child(c); + commands.entity(c).add_child(d); - AddChild { - parent: c, - child: d, - } - .write(world); + system_state.apply(world); - let mut system_param = SystemState::<(Query<&Children>, Query<&A>)>::new(world); - let (children_query, a_query) = system_param.get(world); + 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(a)) @@ -208,20 +199,16 @@ mod tests { let [a, b, c] = std::array::from_fn(|i| world.spawn(A(i)).id()); - AddChild { - parent: a, - child: b, - } - .write(world); + let mut system_state = SystemState::::new(world); + let mut commands = system_state.get_mut(world); - AddChild { - parent: b, - child: c, - } - .write(world); + commands.entity(a).add_child(b); + commands.entity(b).add_child(c); + + system_state.apply(world); - let mut system_param = SystemState::<(Query<&Parent>, Query<&A>)>::new(world); - let (parent_query, a_query) = system_param.get(world); + 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(c)).collect(); From 56939ab13e8f704586d6f65cbe6f603815dfecad Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 13 Oct 2022 14:21:49 +0200 Subject: [PATCH 08/10] doc --- crates/bevy_hierarchy/src/components/children.rs | 7 ++++++- crates/bevy_hierarchy/src/components/parent.rs | 5 +++++ crates/bevy_hierarchy/src/lib.rs | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/bevy_hierarchy/src/components/children.rs b/crates/bevy_hierarchy/src/components/children.rs index e9e3b72654709..cfb234dd8bb9a 100644 --- a/crates/bevy_hierarchy/src/components/children.rs +++ b/crates/bevy_hierarchy/src/components/children.rs @@ -10,7 +10,12 @@ use core::slice; use smallvec::SmallVec; use std::ops::Deref; -/// Contains references to the child entities of this entity +/// Contains references to the child entities of this entity. +/// +/// See [`HierarchyQueryExt`] for hierarchy related methods on [`Query`]. +/// +/// [`HierarchyQueryExt`]: crate::query_extension::HierarchyQueryExt +/// [`Query`]: bevy_ecs::system::Query #[derive(Component, Debug, Reflect)] #[reflect(Component, MapEntities)] pub struct Children(pub(crate) SmallVec<[Entity; 8]>); diff --git a/crates/bevy_hierarchy/src/components/parent.rs b/crates/bevy_hierarchy/src/components/parent.rs index d4a5e2f3bec70..c30962b0497bc 100644 --- a/crates/bevy_hierarchy/src/components/parent.rs +++ b/crates/bevy_hierarchy/src/components/parent.rs @@ -9,6 +9,11 @@ use std::ops::Deref; /// Holds a reference to the parent entity of this entity. /// This component should only be present on entities that actually have a parent entity. +/// +/// See [`HierarchyQueryExt`] for hierarchy related methods on [`Query`]. +/// +/// [`HierarchyQueryExt`]: crate::query_extension::HierarchyQueryExt +/// [`Query`]: bevy_ecs::system::Query #[derive(Component, Debug, Eq, PartialEq, Reflect)] #[reflect(Component, MapEntities, PartialEq)] pub struct Parent(pub(crate) Entity); diff --git a/crates/bevy_hierarchy/src/lib.rs b/crates/bevy_hierarchy/src/lib.rs index 0740df0259b11..0959fa8130a7b 100644 --- a/crates/bevy_hierarchy/src/lib.rs +++ b/crates/bevy_hierarchy/src/lib.rs @@ -20,6 +20,7 @@ mod valid_parent_check_plugin; pub use valid_parent_check_plugin::*; mod query_extension; +pub use query_extension::*; #[doc(hidden)] pub mod prelude { From 4fad515add70a65702dce8e21ab6176360b7ea63 Mon Sep 17 00:00:00 2001 From: devil-ira Date: Thu, 13 Oct 2022 14:22:04 +0200 Subject: [PATCH 09/10] fmt --- crates/bevy_hierarchy/src/components/children.rs | 2 +- crates/bevy_hierarchy/src/components/parent.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_hierarchy/src/components/children.rs b/crates/bevy_hierarchy/src/components/children.rs index cfb234dd8bb9a..541b48d68a07f 100644 --- a/crates/bevy_hierarchy/src/components/children.rs +++ b/crates/bevy_hierarchy/src/components/children.rs @@ -13,7 +13,7 @@ use std::ops::Deref; /// Contains references to the child entities of this entity. /// /// See [`HierarchyQueryExt`] for hierarchy related methods on [`Query`]. -/// +/// /// [`HierarchyQueryExt`]: crate::query_extension::HierarchyQueryExt /// [`Query`]: bevy_ecs::system::Query #[derive(Component, Debug, Reflect)] diff --git a/crates/bevy_hierarchy/src/components/parent.rs b/crates/bevy_hierarchy/src/components/parent.rs index c30962b0497bc..d22fa67d3fce7 100644 --- a/crates/bevy_hierarchy/src/components/parent.rs +++ b/crates/bevy_hierarchy/src/components/parent.rs @@ -11,7 +11,7 @@ use std::ops::Deref; /// This component should only be present on entities that actually have a parent entity. /// /// See [`HierarchyQueryExt`] for hierarchy related methods on [`Query`]. -/// +/// /// [`HierarchyQueryExt`]: crate::query_extension::HierarchyQueryExt /// [`Query`]: bevy_ecs::system::Query #[derive(Component, Debug, Eq, PartialEq, Reflect)] From cdc3d69d0ff47c9b8ad2fe6d220c0ca0fc350645 Mon Sep 17 00:00:00 2001 From: devil-ira Date: Sun, 30 Oct 2022 14:16:02 +0100 Subject: [PATCH 10/10] yuck --- crates/bevy_hierarchy/src/query_extension.rs | 23 +++++--------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index 7ac85d2b9a476..6282c81992514 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -159,11 +159,11 @@ where mod tests { use bevy_ecs::{ prelude::Component, - system::{Commands, Query, SystemState}, + system::{Query, SystemState}, world::World, }; - use crate::{query_extension::HierarchyQueryExt, BuildChildren, Children, Parent}; + use crate::{query_extension::HierarchyQueryExt, BuildWorldChildren, Children, Parent}; #[derive(Component, PartialEq, Debug)] struct A(usize); @@ -174,14 +174,8 @@ mod tests { let [a, b, c, d] = std::array::from_fn(|i| world.spawn(A(i)).id()); - let mut system_state = SystemState::::new(world); - let mut commands = system_state.get_mut(world); - - commands.entity(a).add_child(b); - commands.entity(a).add_child(c); - commands.entity(c).add_child(d); - - system_state.apply(world); + world.entity_mut(a).push_children(&[b, c]); + world.entity_mut(c).push_children(&[d]); let mut system_state = SystemState::<(Query<&Children>, Query<&A>)>::new(world); let (children_query, a_query) = system_state.get(world); @@ -199,13 +193,8 @@ mod tests { let [a, b, c] = std::array::from_fn(|i| world.spawn(A(i)).id()); - let mut system_state = SystemState::::new(world); - let mut commands = system_state.get_mut(world); - - commands.entity(a).add_child(b); - commands.entity(b).add_child(c); - - system_state.apply(world); + world.entity_mut(a).push_children(&[b]); + world.entity_mut(b).push_children(&[c]); let mut system_state = SystemState::<(Query<&Parent>, Query<&A>)>::new(world); let (parent_query, a_query) = system_state.get(world);