From c1e499d5fe26ff5ad518720bd7ab6d9e685ed16f Mon Sep 17 00:00:00 2001 From: Felipe Jorge Date: Sun, 22 Nov 2020 17:05:58 -0300 Subject: [PATCH] Fix duplicated chilren in Scene spawn (#904) Fix duplicated chilren in Scene spawn --- .../bevy_transform/src/components/children.rs | 19 ++++++++------- .../bevy_transform/src/components/parent.rs | 23 ++++++++++++++++--- .../src/hierarchy/child_builder.rs | 4 ++-- .../bevy_transform/src/hierarchy/hierarchy.rs | 2 +- .../hierarchy/hierarchy_maintenance_system.rs | 4 ++++ .../src/hierarchy/world_child_builder.rs | 2 +- crates/bevy_transform/src/lib.rs | 3 ++- examples/ecs/hierarchy.rs | 9 +++----- 8 files changed, 42 insertions(+), 24 deletions(-) diff --git a/crates/bevy_transform/src/components/children.rs b/crates/bevy_transform/src/components/children.rs index 5b08a41b48f6d..e4205c9ebeaae 100644 --- a/crates/bevy_transform/src/components/children.rs +++ b/crates/bevy_transform/src/components/children.rs @@ -1,10 +1,10 @@ use bevy_ecs::{Entity, MapEntities}; use bevy_property::Properties; use smallvec::SmallVec; -use std::ops::{Deref, DerefMut}; +use std::ops::Deref; #[derive(Default, Clone, Properties, Debug)] -pub struct Children(pub SmallVec<[Entity; 8]>); +pub struct Children(pub(crate) SmallVec<[Entity; 8]>); impl MapEntities for Children { fn map_entities( @@ -23,18 +23,17 @@ impl Children { pub fn with(entity: &[Entity]) -> Self { Self(SmallVec::from_slice(entity)) } + + /// Swaps the child at `a_index` with the child at `b_index` + pub fn swap(&mut self, a_index: usize, b_index: usize) { + self.0.swap(a_index, b_index); + } } impl Deref for Children { - type Target = SmallVec<[Entity; 8]>; + type Target = [Entity]; fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Children { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 + &self.0[..] } } diff --git a/crates/bevy_transform/src/components/parent.rs b/crates/bevy_transform/src/components/parent.rs index bf9bdab9a67b2..9eddcdaff94f5 100644 --- a/crates/bevy_transform/src/components/parent.rs +++ b/crates/bevy_transform/src/components/parent.rs @@ -25,9 +25,6 @@ impl MapEntities for Parent { } } -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct PreviousParent(pub Entity); - impl Deref for Parent { type Target = Entity; @@ -41,3 +38,23 @@ impl DerefMut for Parent { &mut self.0 } } + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Properties)] +pub struct PreviousParent(pub(crate) Entity); + +impl MapEntities for PreviousParent { + fn map_entities( + &mut self, + entity_map: &bevy_ecs::EntityMap, + ) -> Result<(), bevy_ecs::MapEntitiesError> { + self.0 = entity_map.get(self.0)?; + Ok(()) + } +} + +// TODO: Better handle this case see `impl FromResources for Parent` +impl FromResources for PreviousParent { + fn from_resources(_resources: &bevy_ecs::Resources) -> Self { + PreviousParent(Entity::new(u32::MAX)) + } +} diff --git a/crates/bevy_transform/src/hierarchy/child_builder.rs b/crates/bevy_transform/src/hierarchy/child_builder.rs index b42772cfb8bc7..572f2a100c9b4 100644 --- a/crates/bevy_transform/src/hierarchy/child_builder.rs +++ b/crates/bevy_transform/src/hierarchy/child_builder.rs @@ -19,7 +19,7 @@ impl Command for InsertChildren { { let mut added = false; if let Ok(mut children) = world.get_mut::(self.parent) { - children.insert_from_slice(self.index, &self.children); + children.0.insert_from_slice(self.index, &self.children); added = true; } @@ -54,7 +54,7 @@ impl Command for PushChildren { { let mut added = false; if let Ok(mut children) = world.get_mut::(self.parent) { - children.extend(self.children.iter().cloned()); + children.0.extend(self.children.iter().cloned()); added = true; } diff --git a/crates/bevy_transform/src/hierarchy/hierarchy.rs b/crates/bevy_transform/src/hierarchy/hierarchy.rs index 6509fa0ff7a0d..e9ec1070bc80b 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy.rs +++ b/crates/bevy_transform/src/hierarchy/hierarchy.rs @@ -42,7 +42,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).map(|parent| parent.0) { if let Ok(mut children) = world.get_mut::(parent) { - children.retain(|c| *c != entity); + children.0.retain(|c| *c != entity); } } diff --git a/crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs b/crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs index 09f67b68e8b05..6073300001af7 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs +++ b/crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs @@ -47,6 +47,10 @@ pub fn parent_update_system( // `children_additions`). if let Ok(mut new_parent_children) = children_query.get_mut(parent.0) { // This is the parent + debug_assert!( + !(*new_parent_children).0.contains(&entity), + "children already added" + ); (*new_parent_children).0.push(entity); } else { // The parent doesn't have a children entity, lets add it diff --git a/crates/bevy_transform/src/hierarchy/world_child_builder.rs b/crates/bevy_transform/src/hierarchy/world_child_builder.rs index a658956c06e69..8f1dc84528fe6 100644 --- a/crates/bevy_transform/src/hierarchy/world_child_builder.rs +++ b/crates/bevy_transform/src/hierarchy/world_child_builder.rs @@ -22,7 +22,7 @@ impl<'a, 'b> WorldChildBuilder<'a, 'b> { let world = &mut self.world_builder.world; let mut added = false; if let Ok(mut children) = world.get_mut::(parent_entity) { - children.push(entity); + children.0.push(entity); added = true; } diff --git a/crates/bevy_transform/src/lib.rs b/crates/bevy_transform/src/lib.rs index fe8dc696c996e..eece2199a1e4a 100644 --- a/crates/bevy_transform/src/lib.rs +++ b/crates/bevy_transform/src/lib.rs @@ -8,7 +8,7 @@ pub mod prelude { use bevy_app::prelude::*; use bevy_type_registry::RegisterType; -use prelude::{parent_update_system, Children, GlobalTransform, Parent, Transform}; +use prelude::{parent_update_system, Children, GlobalTransform, Parent, PreviousParent, Transform}; #[derive(Default)] pub struct TransformPlugin; @@ -17,6 +17,7 @@ impl Plugin for TransformPlugin { fn build(&self, app: &mut AppBuilder) { app.register_component_with::(|reg| reg.map_entities()) .register_component_with::(|reg| reg.map_entities()) + .register_component_with::(|reg| reg.map_entities()) .register_component::() .register_component::() // add transform systems to startup so the first update is "correct" diff --git a/examples/ecs/hierarchy.rs b/examples/ecs/hierarchy.rs index 9dbbccf19c07c..03fe54830f170 100644 --- a/examples/ecs/hierarchy.rs +++ b/examples/ecs/hierarchy.rs @@ -91,11 +91,11 @@ fn setup( fn rotate( commands: &mut Commands, time: Res