diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 9f22588c6711c..7015195757d79 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -4,10 +4,11 @@ use bevy_asset::{AssetEvent, Assets, Handle}; use bevy_ecs::{ entity::{Entity, EntityMap}, reflect::{ReflectComponent, ReflectMapEntities}, + system::Command, world::{Mut, World}, }; use bevy_reflect::TypeRegistryArc; -use bevy_transform::{components::Children, prelude::Parent}; +use bevy_transform::{hierarchy::AddChild, prelude::Parent}; use bevy_utils::{tracing::error, HashMap}; use thiserror::Error; use uuid::Uuid; @@ -268,23 +269,22 @@ impl SceneSpawner { for (instance_id, parent) in scenes_with_parent { if let Some(instance) = self.spawned_instances.get(&instance_id) { for entity in instance.entity_map.values() { - // Add the `Parent` component to the scene root - if let Some(mut entity_mut) = world.get_entity_mut(entity) { + // Add the `Parent` component to the scene root, and update the `Children` component of + // the scene parent + if !world + .get_entity(entity) // This will filter only the scene root entity, as all other from the // scene have a parent - if !entity_mut.contains::() { - entity_mut.insert(Parent(parent)); - if let Some(mut parent_entity) = world.get_entity_mut(parent) { - if let Some(children) = parent_entity.get_mut::() { - let children = &**children; - let mut children = children.to_vec(); - children.push(entity); - parent_entity.insert(Children::with(&children)); - } else { - parent_entity.insert(Children::with(&[entity])); - } - } + .map(|entity| entity.contains::()) + // Default is true so that it won't run on an entity that wouldn't exist anymore + // this case shouldn't happen anyway + .unwrap_or(true) + { + AddChild { + parent, + child: entity, } + .write(world); } } } else { diff --git a/crates/bevy_transform/src/hierarchy/child_builder.rs b/crates/bevy_transform/src/hierarchy/child_builder.rs index 094a2af1314bd..7868d64926bb2 100644 --- a/crates/bevy_transform/src/hierarchy/child_builder.rs +++ b/crates/bevy_transform/src/hierarchy/child_builder.rs @@ -7,6 +7,28 @@ use bevy_ecs::{ }; use smallvec::SmallVec; +#[derive(Debug)] +pub struct AddChild { + pub parent: Entity, + pub child: Entity, +} + +impl Command for AddChild { + fn write(self, world: &mut World) { + world + .entity_mut(self.child) + // FIXME: don't erase the previous parent (see #1545) + .insert_bundle((Parent(self.parent), PreviousParent(self.parent))); + if let Some(mut children) = world.get_mut::(self.parent) { + children.0.push(self.child); + } else { + world + .entity_mut(self.parent) + .insert(Children(smallvec::smallvec![self.child])); + } + } +} + #[derive(Debug)] pub struct InsertChildren { parent: Entity,