From 2870b8ef83ae496cb74f3a0ff9651f3b2a4847e3 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Fri, 28 Aug 2020 22:48:38 -0600 Subject: [PATCH 1/4] Test whether child is removed from parent when it is despawned --- .../bevy_transform/src/hierarchy/hierarchy.rs | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/crates/bevy_transform/src/hierarchy/hierarchy.rs b/crates/bevy_transform/src/hierarchy/hierarchy.rs index 354c08d614312..ef4740cc97598 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy.rs +++ b/crates/bevy_transform/src/hierarchy/hierarchy.rs @@ -78,32 +78,42 @@ impl DespawnRecursiveExt for Commands { #[cfg(test)] mod tests { use super::DespawnRecursiveExt; + use crate::components::Children; use crate::hierarchy::BuildChildren; - use bevy_ecs::{Commands, Entity, Resources, World}; + use bevy_ecs::{Commands, Resources, World}; #[test] fn despawn_recursive() { let mut world = World::default(); let mut resources = Resources::default(); let mut command_buffer = Commands::default(); - let parent_entity = Entity::new(); command_buffer.spawn((0u32, 0u64)).with_children(|parent| { parent.spawn((0u32, 0u64)); }); - command_buffer - .spawn_as_entity(parent_entity, (1u32, 2u64)) - .with_children(|parent| { - parent.spawn((1u32, 2u64)).with_children(|parent| { - parent.spawn((1u32, 2u64)); + // Create a grandparent entity which will _not_ be deleted + command_buffer.spawn((1u32, 1u64)); + let grandparent_entity = command_buffer.current_entity().unwrap(); + + command_buffer.with_children(|parent| { + // Add a child to the grandparent (the "parent"), which will get deleted + parent.spawn((2u32, 2u64)); + // All descendents of the "parent" should also be deleted. + parent.with_children(|parent| { + parent.spawn((3u32, 3u64)).with_children(|parent| { + // child + parent.spawn((4u32, 4u64)); }); - parent.spawn((1u32, 2u64)); + parent.spawn((5u32, 5u64)); }); + }); command_buffer.spawn((0u32, 0u64)); command_buffer.apply(&mut world, &mut resources); + let parent_entity = world.get::(grandparent_entity).unwrap()[0]; + command_buffer.despawn_recursive(parent_entity); command_buffer.apply(&mut world, &mut resources); @@ -113,8 +123,20 @@ mod tests { .map(|(a, b)| (*a, *b)) .collect::>(); + { + let children = world.get::(grandparent_entity).unwrap(); + assert_eq!( + children.iter().any(|&i| i == parent_entity), + false, + "grandparent should no longer know about its child which has been removed" + ); + } + // parent_entity and its children should be deleted, - // the (0, 0) tuples remaining. - assert_eq!(results, vec![(0u32, 0u64), (0u32, 0u64), (0u32, 0u64)]); + // the grandparent tuple (1, 1) and (0, 0) tuples remaining. + assert_eq!( + results, + vec![(0u32, 0u64), (0u32, 0u64), (0u32, 0u64), (1u32, 1u64)] + ); } } From 9ef909d70ea9d55cfd44b65ee6714e482d0861fb Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Fri, 28 Aug 2020 22:49:12 -0600 Subject: [PATCH 2/4] Remove child from parent when it is despawned --- crates/bevy_transform/src/hierarchy/hierarchy.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/bevy_transform/src/hierarchy/hierarchy.rs b/crates/bevy_transform/src/hierarchy/hierarchy.rs index ef4740cc97598..33752c3d6912a 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy.rs +++ b/crates/bevy_transform/src/hierarchy/hierarchy.rs @@ -1,4 +1,4 @@ -use crate::components::Children; +use crate::components::{Children, Parent}; use bevy_ecs::{Commands, Entity, Query, World, WorldWriter}; pub fn run_on_hierarchy( @@ -44,6 +44,18 @@ pub struct DespawnRecursive { } fn despawn_with_children_recursive(world: &mut World, entity: Entity) { + // first, make the entity's own parent forget about it + if let Ok(parent) = world.get::(entity) { + if let Ok(mut children) = world.get_mut::(parent.0) { + children.0.retain(|c| *c != entity); + } + } + // then despawn the entity and all of its children + despawn_with_children_recursive_inner(world, entity); +} + +// Should only be called by `despawn_with_children_recursive`! +fn despawn_with_children_recursive_inner(world: &mut World, entity: Entity) { if let Some(children) = world .get::(entity) .ok() From 9e567bfff2685220a60632f943aa51754301138f Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Fri, 28 Aug 2020 22:58:59 -0600 Subject: [PATCH 3/4] Run 'cargo fmt' with nightly--different results --- crates/bevy_transform/src/hierarchy/hierarchy.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_transform/src/hierarchy/hierarchy.rs b/crates/bevy_transform/src/hierarchy/hierarchy.rs index 33752c3d6912a..3d3524b513ef3 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy.rs +++ b/crates/bevy_transform/src/hierarchy/hierarchy.rs @@ -90,8 +90,7 @@ impl DespawnRecursiveExt for Commands { #[cfg(test)] mod tests { use super::DespawnRecursiveExt; - use crate::components::Children; - use crate::hierarchy::BuildChildren; + use crate::{components::Children, hierarchy::BuildChildren}; use bevy_ecs::{Commands, Resources, World}; #[test] From eaa102b32eaebea427a0ea858d4c5b2d87eed222 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Tue, 1 Sep 2020 10:50:46 -0600 Subject: [PATCH 4/4] Update crates/bevy_transform/src/hierarchy/hierarchy.rs Co-authored-by: memoryruins --- crates/bevy_transform/src/hierarchy/hierarchy.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_transform/src/hierarchy/hierarchy.rs b/crates/bevy_transform/src/hierarchy/hierarchy.rs index 3d3524b513ef3..b13f665e963e0 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy.rs +++ b/crates/bevy_transform/src/hierarchy/hierarchy.rs @@ -47,7 +47,7 @@ fn despawn_with_children_recursive(world: &mut World, entity: Entity) { // first, make the entity's own parent forget about it if let Ok(parent) = world.get::(entity) { if let Ok(mut children) = world.get_mut::(parent.0) { - children.0.retain(|c| *c != entity); + children.retain(|c| *c != entity); } } // then despawn the entity and all of its children