From 87c0971c4f6135b491d2b7948852404e213eff67 Mon Sep 17 00:00:00 2001 From: lassade Date: Thu, 19 Nov 2020 01:57:59 -0300 Subject: [PATCH 1/4] fixed dup children --- .../bevy_transform/src/components/children.rs | 20 ++++--------------- .../src/hierarchy/child_builder.rs | 12 ++--------- .../bevy_transform/src/hierarchy/hierarchy.rs | 2 +- .../hierarchy/hierarchy_maintenance_system.rs | 8 ++++++-- .../src/hierarchy/world_child_builder.rs | 6 +----- crates/bevy_transform/src/lib.rs | 2 +- examples/ecs/hierarchy.rs | 6 +++--- 7 files changed, 18 insertions(+), 38 deletions(-) diff --git a/crates/bevy_transform/src/components/children.rs b/crates/bevy_transform/src/components/children.rs index 5b08a41b48f6d..c8c274a18d66f 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(#[property(ignore)] pub(crate) SmallVec<[Entity; 8]>); impl MapEntities for Children { fn map_entities( @@ -19,22 +19,10 @@ impl MapEntities for Children { } } -impl Children { - pub fn with(entity: &[Entity]) -> Self { - Self(SmallVec::from_slice(entity)) - } -} - 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/hierarchy/child_builder.rs b/crates/bevy_transform/src/hierarchy/child_builder.rs index b42772cfb8bc7..abb0d8e78c711 100644 --- a/crates/bevy_transform/src/hierarchy/child_builder.rs +++ b/crates/bevy_transform/src/hierarchy/child_builder.rs @@ -17,11 +17,7 @@ impl Command for InsertChildren { .unwrap(); } { - let mut added = false; - if let Ok(mut children) = world.get_mut::(self.parent) { - children.insert_from_slice(self.index, &self.children); - added = true; - } + let added = world.get_mut::(self.parent).is_ok(); // NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails borrow-checking if !added { @@ -52,11 +48,7 @@ impl Command for PushChildren { .unwrap(); } { - let mut added = false; - if let Ok(mut children) = world.get_mut::(self.parent) { - children.extend(self.children.iter().cloned()); - added = true; - } + let added = world.get_mut::(self.parent).is_ok(); // NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails borrow-checking if !added { 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..f8f4d2a642827 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs +++ b/crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs @@ -46,8 +46,12 @@ pub fn parent_update_system( // Add to the parent's `Children` (either the real component, or // `children_additions`). if let Ok(mut new_parent_children) = children_query.get_mut(parent.0) { + let children_vec = &mut (*new_parent_children).0; + // Duplicate entities inside the Children component will lead to a state explosion + // that will kill the game frame rate + debug_assert!(!children_vec.contains(&entity), "duplicate children"); // This is the parent - (*new_parent_children).0.push(entity); + children_vec.push(entity); } else { // The parent doesn't have a children entity, lets add it children_additions @@ -61,7 +65,7 @@ pub fn parent_update_system( // collect multiple new children that point to the same parent into the same // SmallVec, and to prevent redundant add+remove operations. children_additions.iter().for_each(|(k, v)| { - commands.insert_one(*k, Children::with(v)); + commands.insert_one(*k, Children(SmallVec::from_slice(v))); }); } #[cfg(test)] diff --git a/crates/bevy_transform/src/hierarchy/world_child_builder.rs b/crates/bevy_transform/src/hierarchy/world_child_builder.rs index a658956c06e69..e36734f3b4e63 100644 --- a/crates/bevy_transform/src/hierarchy/world_child_builder.rs +++ b/crates/bevy_transform/src/hierarchy/world_child_builder.rs @@ -20,11 +20,7 @@ impl<'a, 'b> WorldChildBuilder<'a, 'b> { let entity = self.world_builder.current_entity.unwrap(); { let world = &mut self.world_builder.world; - let mut added = false; - if let Ok(mut children) = world.get_mut::(parent_entity) { - children.push(entity); - added = true; - } + let added = world.get_mut::(parent_entity).is_ok(); // NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails borrow-checking if !added { diff --git a/crates/bevy_transform/src/lib.rs b/crates/bevy_transform/src/lib.rs index fe8dc696c996e..b44114a5eb386 100644 --- a/crates/bevy_transform/src/lib.rs +++ b/crates/bevy_transform/src/lib.rs @@ -15,7 +15,7 @@ pub struct TransformPlugin; impl Plugin for TransformPlugin { fn build(&self, app: &mut AppBuilder) { - app.register_component_with::(|reg| reg.map_entities()) + app.register_component::() .register_component_with::(|reg| reg.map_entities()) .register_component::() .register_component::() diff --git a/examples/ecs/hierarchy.rs b/examples/ecs/hierarchy.rs index 9dbbccf19c07c..82e56760486b6 100644 --- a/examples/ecs/hierarchy.rs +++ b/examples/ecs/hierarchy.rs @@ -91,11 +91,11 @@ fn setup( fn rotate( commands: &mut Commands, time: Res