Fix duplicated chilren in Scene spawn (#904)
Fix duplicated chilren in Scene spawn
This commit is contained in:
parent
46fac78774
commit
c1e499d5fe
@ -1,10 +1,10 @@
|
|||||||
use bevy_ecs::{Entity, MapEntities};
|
use bevy_ecs::{Entity, MapEntities};
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[derive(Default, Clone, Properties, Debug)]
|
#[derive(Default, Clone, Properties, Debug)]
|
||||||
pub struct Children(pub SmallVec<[Entity; 8]>);
|
pub struct Children(pub(crate) SmallVec<[Entity; 8]>);
|
||||||
|
|
||||||
impl MapEntities for Children {
|
impl MapEntities for Children {
|
||||||
fn map_entities(
|
fn map_entities(
|
||||||
@ -23,18 +23,17 @@ impl Children {
|
|||||||
pub fn with(entity: &[Entity]) -> Self {
|
pub fn with(entity: &[Entity]) -> Self {
|
||||||
Self(SmallVec::from_slice(entity))
|
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 {
|
impl Deref for Children {
|
||||||
type Target = SmallVec<[Entity; 8]>;
|
type Target = [Entity];
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0[..]
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for Children {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,6 @@ impl MapEntities for Parent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
|
||||||
pub struct PreviousParent(pub Entity);
|
|
||||||
|
|
||||||
impl Deref for Parent {
|
impl Deref for Parent {
|
||||||
type Target = Entity;
|
type Target = Entity;
|
||||||
|
|
||||||
@ -41,3 +38,23 @@ impl DerefMut for Parent {
|
|||||||
&mut self.0
|
&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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,7 +19,7 @@ impl Command for InsertChildren {
|
|||||||
{
|
{
|
||||||
let mut added = false;
|
let mut added = false;
|
||||||
if let Ok(mut children) = world.get_mut::<Children>(self.parent) {
|
if let Ok(mut children) = world.get_mut::<Children>(self.parent) {
|
||||||
children.insert_from_slice(self.index, &self.children);
|
children.0.insert_from_slice(self.index, &self.children);
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ impl Command for PushChildren {
|
|||||||
{
|
{
|
||||||
let mut added = false;
|
let mut added = false;
|
||||||
if let Ok(mut children) = world.get_mut::<Children>(self.parent) {
|
if let Ok(mut children) = world.get_mut::<Children>(self.parent) {
|
||||||
children.extend(self.children.iter().cloned());
|
children.0.extend(self.children.iter().cloned());
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ fn despawn_with_children_recursive(world: &mut World, entity: Entity) {
|
|||||||
// first, make the entity's own parent forget about it
|
// first, make the entity's own parent forget about it
|
||||||
if let Ok(parent) = world.get::<Parent>(entity).map(|parent| parent.0) {
|
if let Ok(parent) = world.get::<Parent>(entity).map(|parent| parent.0) {
|
||||||
if let Ok(mut children) = world.get_mut::<Children>(parent) {
|
if let Ok(mut children) = world.get_mut::<Children>(parent) {
|
||||||
children.retain(|c| *c != entity);
|
children.0.retain(|c| *c != entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,10 @@ pub fn parent_update_system(
|
|||||||
// `children_additions`).
|
// `children_additions`).
|
||||||
if let Ok(mut new_parent_children) = children_query.get_mut(parent.0) {
|
if let Ok(mut new_parent_children) = children_query.get_mut(parent.0) {
|
||||||
// This is the parent
|
// This is the parent
|
||||||
|
debug_assert!(
|
||||||
|
!(*new_parent_children).0.contains(&entity),
|
||||||
|
"children already added"
|
||||||
|
);
|
||||||
(*new_parent_children).0.push(entity);
|
(*new_parent_children).0.push(entity);
|
||||||
} else {
|
} else {
|
||||||
// The parent doesn't have a children entity, lets add it
|
// The parent doesn't have a children entity, lets add it
|
||||||
|
@ -22,7 +22,7 @@ impl<'a, 'b> WorldChildBuilder<'a, 'b> {
|
|||||||
let world = &mut self.world_builder.world;
|
let world = &mut self.world_builder.world;
|
||||||
let mut added = false;
|
let mut added = false;
|
||||||
if let Ok(mut children) = world.get_mut::<Children>(parent_entity) {
|
if let Ok(mut children) = world.get_mut::<Children>(parent_entity) {
|
||||||
children.push(entity);
|
children.0.push(entity);
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ pub mod prelude {
|
|||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_type_registry::RegisterType;
|
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)]
|
#[derive(Default)]
|
||||||
pub struct TransformPlugin;
|
pub struct TransformPlugin;
|
||||||
@ -17,6 +17,7 @@ impl Plugin for TransformPlugin {
|
|||||||
fn build(&self, app: &mut AppBuilder) {
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
app.register_component_with::<Children>(|reg| reg.map_entities())
|
app.register_component_with::<Children>(|reg| reg.map_entities())
|
||||||
.register_component_with::<Parent>(|reg| reg.map_entities())
|
.register_component_with::<Parent>(|reg| reg.map_entities())
|
||||||
|
.register_component_with::<PreviousParent>(|reg| reg.map_entities())
|
||||||
.register_component::<Transform>()
|
.register_component::<Transform>()
|
||||||
.register_component::<GlobalTransform>()
|
.register_component::<GlobalTransform>()
|
||||||
// add transform systems to startup so the first update is "correct"
|
// add transform systems to startup so the first update is "correct"
|
||||||
|
@ -91,11 +91,11 @@ fn setup(
|
|||||||
fn rotate(
|
fn rotate(
|
||||||
commands: &mut Commands,
|
commands: &mut Commands,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut parents_query: Query<(Entity, &mut Children), With<Sprite>>,
|
mut parents_query: Query<(Entity, &Children), With<Sprite>>,
|
||||||
mut transform_query: Query<&mut Transform, With<Sprite>>,
|
mut transform_query: Query<&mut Transform, With<Sprite>>,
|
||||||
) {
|
) {
|
||||||
let angle = std::f32::consts::PI / 2.0;
|
let angle = std::f32::consts::PI / 2.0;
|
||||||
for (parent, mut children) in parents_query.iter_mut() {
|
for (parent, children) in parents_query.iter_mut() {
|
||||||
if let Ok(mut transform) = transform_query.get_mut(parent) {
|
if let Ok(mut transform) = transform_query.get_mut(parent) {
|
||||||
transform.rotate(Quat::from_rotation_z(-angle * time.delta_seconds));
|
transform.rotate(Quat::from_rotation_z(-angle * time.delta_seconds));
|
||||||
}
|
}
|
||||||
@ -110,10 +110,7 @@ fn rotate(
|
|||||||
|
|
||||||
// To demonstrate removing children, we'll start to remove the children after a couple of seconds
|
// To demonstrate removing children, we'll start to remove the children after a couple of seconds
|
||||||
if time.seconds_since_startup >= 2.0 && children.len() == 3 {
|
if time.seconds_since_startup >= 2.0 && children.len() == 3 {
|
||||||
// Using .despawn() on an entity does not remove it from its parent's list of children!
|
let child = children.last().copied().unwrap();
|
||||||
// It must be done manually if using .despawn()
|
|
||||||
// NOTE: This is a bug. Eventually Bevy will update the children list automatically
|
|
||||||
let child = children.pop().unwrap();
|
|
||||||
commands.despawn(child);
|
commands.despawn(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user