Make adding children idempotent (#6763)
# 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.
This commit is contained in:
		
							parent
							
								
									416a33e613
								
							
						
					
					
						commit
						70d7f80564
					
				@ -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());
 | 
					    let mut moved: SmallVec<[HierarchyEvent; 8]> = SmallVec::with_capacity(children.len());
 | 
				
			||||||
    for child in children {
 | 
					    for child in children {
 | 
				
			||||||
        if let Some(previous) = update_parent(world, *child, parent) {
 | 
					        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);
 | 
					            remove_from_children(world, previous, *child);
 | 
				
			||||||
            moved.push(HierarchyEvent::ChildMoved {
 | 
					            moved.push(HierarchyEvent::ChildMoved {
 | 
				
			||||||
                child: *child,
 | 
					                child: *child,
 | 
				
			||||||
@ -287,7 +291,8 @@ pub trait BuildChildren {
 | 
				
			|||||||
    /// # }
 | 
					    /// # }
 | 
				
			||||||
    /// ```
 | 
					    /// ```
 | 
				
			||||||
    fn add_children<T>(&mut self, f: impl FnOnce(&mut ChildBuilder) -> T) -> T;
 | 
					    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
 | 
					    /// 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
 | 
					    /// will have those children removed from its list. Removing all children from a parent causes its
 | 
				
			||||||
@ -739,4 +744,19 @@ mod tests {
 | 
				
			|||||||
        let child = world.spawn_empty().id();
 | 
					        let child = world.spawn_empty().id();
 | 
				
			||||||
        world.spawn_empty().push_children(&[child]);
 | 
					        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]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user