Skip to content

Commit

Permalink
Make adding children idempotent (#6763)
Browse files Browse the repository at this point in the history
# Objective

* Fix #6668
* There is no need to panic when a parenting operation is redundant, as no invalid state is entered.

## Solution

Make `push_children` idempotent.
  • Loading branch information
JoJoJet committed Nov 28, 2022
1 parent 416a33e commit 70d7f80
Showing 1 changed file with 22 additions and 2 deletions.
24 changes: 22 additions & 2 deletions crates/bevy_hierarchy/src/child_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ fn update_old_parents(world: &mut World, parent: Entity, children: &[Entity]) {
let mut moved: SmallVec<[HierarchyEvent; 8]> = SmallVec::with_capacity(children.len());
for child in children {
if let Some(previous) = update_parent(world, *child, parent) {
debug_assert!(parent != previous);
// Do nothing if the entity already has the correct parent.
if parent == previous {
continue;
}

remove_from_children(world, previous, *child);
moved.push(HierarchyEvent::ChildMoved {
child: *child,
Expand Down Expand Up @@ -287,7 +291,8 @@ pub trait BuildChildren {
/// # }
/// ```
fn add_children<T>(&mut self, f: impl FnOnce(&mut ChildBuilder) -> T) -> T;
/// Pushes children to the back of the builder's children
/// Pushes children to the back of the builder's children. For any entities that are
/// already a child of this one, this method does nothing.
///
/// If the children were previously children of another parent, that parent's [`Children`] component
/// will have those children removed from its list. Removing all children from a parent causes its
Expand Down Expand Up @@ -739,4 +744,19 @@ mod tests {
let child = world.spawn_empty().id();
world.spawn_empty().push_children(&[child]);
}

#[test]
fn push_children_idempotent() {
let mut world = World::new();
let child = world.spawn_empty().id();
let parent = world
.spawn_empty()
.push_children(&[child])
.push_children(&[child])
.id();

let mut query = world.query::<&Children>();
let children = query.get(&world, parent).unwrap();
assert_eq!(**children, [child]);
}
}

0 comments on commit 70d7f80

Please sign in to comment.