diff --git a/crates/bevy_ecs/src/event/mod.rs b/crates/bevy_ecs/src/event/mod.rs index f7f46af258..46b04c8a18 100644 --- a/crates/bevy_ecs/src/event/mod.rs +++ b/crates/bevy_ecs/src/event/mod.rs @@ -7,7 +7,6 @@ mod mut_iterators; mod mutator; mod reader; mod registry; -mod send_event; mod update; mod writer; @@ -25,7 +24,6 @@ pub use mut_iterators::{EventMutIterator, EventMutIteratorWithId}; pub use mutator::EventMutator; pub use reader::EventReader; pub use registry::{EventRegistry, ShouldUpdateEvents}; -pub use send_event::SendEvent; pub use update::{ event_update_condition, event_update_system, signal_event_update_system, EventUpdates, }; diff --git a/crates/bevy_ecs/src/event/send_event.rs b/crates/bevy_ecs/src/event/send_event.rs deleted file mode 100644 index 0d5f61cadc..0000000000 --- a/crates/bevy_ecs/src/event/send_event.rs +++ /dev/null @@ -1,37 +0,0 @@ -#[cfg(feature = "track_change_detection")] -use core::panic::Location; - -use super::{Event, Events}; -use crate::world::{Command, World}; - -/// A command to send an arbitrary [`Event`], used by [`Commands::send_event`](crate::system::Commands::send_event). -pub struct SendEvent { - /// The event to send. - pub event: E, - /// The source code location that triggered this command. - #[cfg(feature = "track_change_detection")] - pub caller: &'static Location<'static>, -} - -// This does not use `From`, as the resulting `Into` is not track_caller -impl SendEvent { - /// Constructs a new `SendEvent` tracking the caller. - pub fn new(event: E) -> Self { - Self { - event, - #[cfg(feature = "track_change_detection")] - caller: Location::caller(), - } - } -} - -impl Command for SendEvent { - fn apply(self, world: &mut World) { - let mut events = world.resource_mut::>(); - events.send_with_caller( - self.event, - #[cfg(feature = "track_change_detection")] - self.caller, - ); - } -} diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index b96d2baba9..74e776e5aa 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -11,7 +11,7 @@ use crate::{ change_detection::Mut, component::{Component, ComponentId, ComponentInfo, Mutable}, entity::{Entities, Entity, EntityCloneBuilder}, - event::{Event, SendEvent}, + event::{Event, Events}, observer::{Observer, TriggerTargets}, schedule::ScheduleLabel, system::{input::SystemInput, SystemId}, @@ -1060,10 +1060,15 @@ impl<'w, 's> Commands<'w, 's> { /// [`EventWriter`]: crate::event::EventWriter #[track_caller] pub fn send_event(&mut self, event: E) -> &mut Self { - self.queue(SendEvent { - event, - #[cfg(feature = "track_change_detection")] - caller: Location::caller(), + #[cfg(feature = "track_change_detection")] + let caller = Location::caller(); + self.queue(move |world: &mut World| { + let mut events = world.resource_mut::>(); + events.send_with_caller( + event, + #[cfg(feature = "track_change_detection")] + caller, + ); }); self } diff --git a/crates/bevy_hierarchy/src/child_builder.rs b/crates/bevy_hierarchy/src/child_builder.rs index 769da2b83b..0da5c1c68a 100644 --- a/crates/bevy_hierarchy/src/child_builder.rs +++ b/crates/bevy_hierarchy/src/child_builder.rs @@ -2,7 +2,7 @@ use crate::{Children, HierarchyEvent, Parent}; use bevy_ecs::{ bundle::Bundle, entity::Entity, - prelude::Events, + event::Events, system::{Commands, EntityCommands}, world::{Command, EntityWorldMut, World}, }; @@ -149,109 +149,6 @@ fn remove_children(parent: Entity, children: &[Entity], world: &mut World) { } } -/// Removes all children from `parent` by removing its [`Children`] component, as well as removing -/// [`Parent`] component from its children. -fn clear_children(parent: Entity, world: &mut World) { - if let Some(children) = world.entity_mut(parent).take::() { - for &child in &children.0 { - world.entity_mut(child).remove::(); - } - } -} - -/// Command that adds a child to an entity. -#[derive(Debug)] -pub struct AddChild { - /// Parent entity to add the child to. - pub parent: Entity, - /// Child entity to add. - pub child: Entity, -} - -impl Command for AddChild { - fn apply(self, world: &mut World) { - world.entity_mut(self.parent).add_child(self.child); - } -} - -/// Command that inserts a child at a given index of a parent's children, shifting following children back. -#[derive(Debug)] -pub struct InsertChildren { - parent: Entity, - children: SmallVec<[Entity; 8]>, - index: usize, -} - -impl Command for InsertChildren { - fn apply(self, world: &mut World) { - world - .entity_mut(self.parent) - .insert_children(self.index, &self.children); - } -} - -/// Command that pushes children to the end of the entity's [`Children`]. -#[derive(Debug)] -pub struct AddChildren { - parent: Entity, - children: SmallVec<[Entity; 8]>, -} - -impl Command for AddChildren { - fn apply(self, world: &mut World) { - world.entity_mut(self.parent).add_children(&self.children); - } -} - -/// Command that removes children from an entity, and removes these children's parent. -pub struct RemoveChildren { - parent: Entity, - children: SmallVec<[Entity; 8]>, -} - -impl Command for RemoveChildren { - fn apply(self, world: &mut World) { - remove_children(self.parent, &self.children, world); - } -} - -/// Command that clears all children from an entity and removes [`Parent`] component from those -/// children. -pub struct ClearChildren { - parent: Entity, -} - -impl Command for ClearChildren { - fn apply(self, world: &mut World) { - clear_children(self.parent, world); - } -} - -/// Command that clear all children from an entity, replacing them with the given children. -pub struct ReplaceChildren { - parent: Entity, - children: SmallVec<[Entity; 8]>, -} - -impl Command for ReplaceChildren { - fn apply(self, world: &mut World) { - clear_children(self.parent, world); - world.entity_mut(self.parent).add_children(&self.children); - } -} - -/// Command that removes the parent of an entity, and removes that entity from the parent's [`Children`]. -pub struct RemoveParent { - /// `Entity` whose parent must be removed. - pub child: Entity, -} - -impl Command for RemoveParent { - fn apply(self, world: &mut World) { - world.entity_mut(self.child).remove_parent(); - } -} - /// Struct for building children entities and adding them to a parent entity. /// /// # Example @@ -276,7 +173,8 @@ impl Command for RemoveParent { /// ``` pub struct ChildBuilder<'a> { commands: Commands<'a, 'a>, - add_children: AddChildren, + children: SmallVec<[Entity; 8]>, + parent: Entity, } /// Trait for building children entities and adding them to a parent entity. This is used in @@ -316,18 +214,18 @@ impl ChildBuild for ChildBuilder<'_> { fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands { let e = self.commands.spawn(bundle); - self.add_children.children.push(e.id()); + self.children.push(e.id()); e } fn spawn_empty(&mut self) -> EntityCommands { let e = self.commands.spawn_empty(); - self.add_children.children.push(e.id()); + self.children.push(e.id()); e } fn parent_entity(&self) -> Entity { - self.add_children.parent + self.parent } fn queue_command(&mut self, command: C) -> &mut Self { @@ -431,38 +329,37 @@ impl BuildChildren for EntityCommands<'_> { let parent = self.id(); let mut builder = ChildBuilder { commands: self.commands(), - add_children: AddChildren { - children: SmallVec::default(), - parent, - }, + children: SmallVec::default(), + parent, }; spawn_children(&mut builder); - let children = builder.add_children; - if children.children.contains(&parent) { + + let children = builder.children; + if children.contains(&parent) { panic!("Entity cannot be a child of itself."); } - self.commands().queue(children); - self + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).add_children(&children); + }) } fn with_child(&mut self, bundle: B) -> &mut Self { - let parent = self.id(); let child = self.commands().spawn(bundle).id(); - self.commands().queue(AddChild { parent, child }); - self + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).add_child(child); + }) } fn add_children(&mut self, children: &[Entity]) -> &mut Self { let parent = self.id(); if children.contains(&parent) { - panic!("Cannot push entity as a child of itself."); + panic!("Cannot add entity as a child of itself."); } - self.commands().queue(AddChildren { - children: SmallVec::from(children), - parent, - }); - self + let children = SmallVec::<[Entity; 8]>::from_slice(children); + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).add_children(&children); + }) } fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self { @@ -470,21 +367,17 @@ impl BuildChildren for EntityCommands<'_> { if children.contains(&parent) { panic!("Cannot insert entity as a child of itself."); } - self.commands().queue(InsertChildren { - children: SmallVec::from(children), - index, - parent, - }); - self + let children = SmallVec::<[Entity; 8]>::from_slice(children); + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).insert_children(index, &children); + }) } fn remove_children(&mut self, children: &[Entity]) -> &mut Self { - let parent = self.id(); - self.commands().queue(RemoveChildren { - children: SmallVec::from(children), - parent, - }); - self + let children = SmallVec::<[Entity; 8]>::from_slice(children); + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).remove_children(&children); + }) } fn add_child(&mut self, child: Entity) -> &mut Self { @@ -492,14 +385,15 @@ impl BuildChildren for EntityCommands<'_> { if child == parent { panic!("Cannot add entity as a child of itself."); } - self.commands().queue(AddChild { child, parent }); - self + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).add_child(child); + }) } fn clear_children(&mut self) -> &mut Self { - let parent = self.id(); - self.commands().queue(ClearChildren { parent }); - self + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).clear_children(); + }) } fn replace_children(&mut self, children: &[Entity]) -> &mut Self { @@ -507,11 +401,10 @@ impl BuildChildren for EntityCommands<'_> { if children.contains(&parent) { panic!("Cannot replace entity as a child of itself."); } - self.commands().queue(ReplaceChildren { - children: SmallVec::from(children), - parent, - }); - self + let children = SmallVec::<[Entity; 8]>::from_slice(children); + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).replace_children(&children); + }) } fn set_parent(&mut self, parent: Entity) -> &mut Self { @@ -519,14 +412,15 @@ impl BuildChildren for EntityCommands<'_> { if child == parent { panic!("Cannot set parent to itself"); } - self.commands().queue(AddChild { child, parent }); - self + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(parent).add_child(entity); + }) } fn remove_parent(&mut self) -> &mut Self { - let child = self.id(); - self.commands().queue(RemoveParent { child }); - self + self.queue(move |entity: Entity, world: &mut World| { + world.entity_mut(entity).remove_parent(); + }) } } @@ -557,16 +451,7 @@ impl ChildBuild for WorldChildBuilder<'_> { } fn spawn_empty(&mut self) -> EntityWorldMut { - let entity = self.world.spawn(Parent(self.parent)).id(); - add_child_unchecked(self.world, self.parent, entity); - push_events( - self.world, - [HierarchyEvent::ChildAdded { - child: entity, - parent: self.parent, - }], - ); - self.world.entity_mut(entity) + self.spawn(()) } fn parent_entity(&self) -> Entity { @@ -691,7 +576,11 @@ impl BuildChildren for EntityWorldMut<'_> { fn clear_children(&mut self) -> &mut Self { let parent = self.id(); self.world_scope(|world| { - clear_children(parent, world); + if let Some(children) = world.entity_mut(parent).take::() { + for &child in &children.0 { + world.entity_mut(child).remove::(); + } + } }); self } diff --git a/crates/bevy_hierarchy/src/hierarchy.rs b/crates/bevy_hierarchy/src/hierarchy.rs index 7b384d25e6..43d6cdd1fb 100644 --- a/crates/bevy_hierarchy/src/hierarchy.rs +++ b/crates/bevy_hierarchy/src/hierarchy.rs @@ -6,28 +6,10 @@ use bevy_ecs::{ component::ComponentCloneHandler, entity::{ComponentCloneCtx, Entity, EntityCloneBuilder}, system::EntityCommands, - world::{Command, DeferredWorld, EntityWorldMut, World}, + world::{DeferredWorld, EntityWorldMut, World}, }; use log::debug; -/// Despawns the given entity and all its children recursively -#[derive(Debug)] -pub struct DespawnRecursive { - /// Target entity - pub entity: Entity, - /// Whether or not this command should output a warning if the entity does not exist - pub warn: bool, -} - -/// Despawns the given entity's children recursively -#[derive(Debug)] -pub struct DespawnChildrenRecursive { - /// Target entity - pub entity: Entity, - /// Whether or not this command should output a warning if the entity does not exist - pub warn: bool, -} - /// Function for despawning an entity and all its children pub fn despawn_with_children_recursive(world: &mut World, entity: Entity, warn: bool) { // first, make the entity's own parent forget about it @@ -41,7 +23,7 @@ pub fn despawn_with_children_recursive(world: &mut World, entity: Entity, warn: despawn_with_children_recursive_inner(world, entity, warn); } -// Should only be called by `despawn_with_children_recursive` and `try_despawn_with_children_recursive`! +// Should only be called by `despawn_with_children_recursive` and `despawn_children_recursive`! fn despawn_with_children_recursive_inner(world: &mut World, entity: Entity, warn: bool) { if let Some(mut children) = world.get_mut::(entity) { for e in core::mem::take(&mut children.0) { @@ -66,35 +48,6 @@ fn despawn_children_recursive(world: &mut World, entity: Entity, warn: bool) { } } -impl Command for DespawnRecursive { - fn apply(self, world: &mut World) { - #[cfg(feature = "trace")] - let _span = tracing::info_span!( - "command", - name = "DespawnRecursive", - entity = tracing::field::debug(self.entity), - warn = tracing::field::debug(self.warn) - ) - .entered(); - despawn_with_children_recursive(world, self.entity, self.warn); - } -} - -impl Command for DespawnChildrenRecursive { - fn apply(self, world: &mut World) { - #[cfg(feature = "trace")] - let _span = tracing::info_span!( - "command", - name = "DespawnChildrenRecursive", - entity = tracing::field::debug(self.entity), - warn = tracing::field::debug(self.warn) - ) - .entered(); - - despawn_children_recursive(world, self.entity, self.warn); - } -} - /// Trait that holds functions for despawning recursively down the transform hierarchy pub trait DespawnRecursiveExt { /// Despawns the provided entity alongside all descendants. @@ -114,33 +67,65 @@ impl DespawnRecursiveExt for EntityCommands<'_> { /// Despawns the provided entity and its children. /// This will emit warnings for any entity that does not exist. fn despawn_recursive(mut self) { - let entity = self.id(); - self.commands() - .queue(DespawnRecursive { entity, warn: true }); + let warn = true; + self.queue(move |entity: Entity, world: &mut World| { + #[cfg(feature = "trace")] + let _span = tracing::info_span!( + "command", + name = "DespawnRecursive", + entity = tracing::field::debug(entity), + warn = tracing::field::debug(warn) + ) + .entered(); + despawn_with_children_recursive(world, entity, warn); + }); } fn despawn_descendants(&mut self) -> &mut Self { - let entity = self.id(); - self.commands() - .queue(DespawnChildrenRecursive { entity, warn: true }); + let warn = true; + self.queue(move |entity: Entity, world: &mut World| { + #[cfg(feature = "trace")] + let _span = tracing::info_span!( + "command", + name = "DespawnChildrenRecursive", + entity = tracing::field::debug(entity), + warn = tracing::field::debug(warn) + ) + .entered(); + despawn_children_recursive(world, entity, warn); + }); self } /// Despawns the provided entity and its children. /// This will never emit warnings. fn try_despawn_recursive(mut self) { - let entity = self.id(); - self.commands().queue(DespawnRecursive { - entity, - warn: false, + let warn = false; + self.queue(move |entity: Entity, world: &mut World| { + #[cfg(feature = "trace")] + let _span = tracing::info_span!( + "command", + name = "TryDespawnRecursive", + entity = tracing::field::debug(entity), + warn = tracing::field::debug(warn) + ) + .entered(); + despawn_with_children_recursive(world, entity, warn); }); } fn try_despawn_descendants(&mut self) -> &mut Self { - let entity = self.id(); - self.commands().queue(DespawnChildrenRecursive { - entity, - warn: false, + let warn = false; + self.queue(move |entity: Entity, world: &mut World| { + #[cfg(feature = "trace")] + let _span = tracing::info_span!( + "command", + name = "TryDespawnChildrenRecursive", + entity = tracing::field::debug(entity), + warn = tracing::field::debug(warn) + ) + .entered(); + despawn_children_recursive(world, entity, warn); }); self } diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index babc45f7f1..f29c925f7e 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -204,9 +204,9 @@ mod tests { }, reflect::{AppTypeRegistry, ReflectComponent, ReflectMapEntities, ReflectResource}, system::Resource, - world::{Command, World}, + world::World, }; - use bevy_hierarchy::{AddChild, Parent}; + use bevy_hierarchy::{BuildChildren, Parent}; use bevy_reflect::Reflect; use crate::dynamic_scene::DynamicScene; @@ -271,11 +271,9 @@ mod tests { .register::(); let original_parent_entity = world.spawn_empty().id(); let original_child_entity = world.spawn_empty().id(); - AddChild { - parent: original_parent_entity, - child: original_child_entity, - } - .apply(&mut world); + world + .entity_mut(original_parent_entity) + .add_child(original_child_entity); // We then write this relationship to a new scene, and then write that scene back to the // world to create another parent and child relationship @@ -292,11 +290,9 @@ mod tests { // We then add the parent from the scene as a child of the original child // Hierarchy should look like: // Original Parent <- Original Child <- Scene Parent <- Scene Child - AddChild { - parent: original_child_entity, - child: from_scene_parent_entity, - } - .apply(&mut world); + world + .entity_mut(original_child_entity) + .add_child(from_scene_parent_entity); // We then reload the scene to make sure that from_scene_parent_entity's parent component // isn't updated with the entity map, since this component isn't defined in the scene. diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 32d829b8c7..edba01b40c 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -5,9 +5,9 @@ use bevy_ecs::{ event::{Event, EventCursor, Events}, reflect::AppTypeRegistry, system::Resource, - world::{Command, Mut, World}, + world::{Mut, World}, }; -use bevy_hierarchy::{AddChild, BuildChildren, DespawnRecursiveExt, Parent}; +use bevy_hierarchy::{BuildChildren, DespawnRecursiveExt, Parent}; use bevy_reflect::Reflect; use bevy_utils::{HashMap, HashSet}; use thiserror::Error; @@ -382,11 +382,7 @@ impl SceneSpawner { // this case shouldn't happen anyway .unwrap_or(true) { - AddChild { - parent, - child: entity, - } - .apply(world); + world.entity_mut(parent).add_child(entity); } } diff --git a/crates/bevy_transform/src/commands.rs b/crates/bevy_transform/src/commands.rs index ff30917407..4ea8f0d1f7 100644 --- a/crates/bevy_transform/src/commands.rs +++ b/crates/bevy_transform/src/commands.rs @@ -3,83 +3,19 @@ use crate::prelude::{GlobalTransform, Transform}; use bevy_ecs::{ - prelude::Entity, + entity::Entity, system::EntityCommands, - world::{Command, EntityWorldMut, World}, + world::{EntityWorldMut, World}, }; -use bevy_hierarchy::{AddChild, RemoveParent}; +use bevy_hierarchy::BuildChildren; -/// Command similar to [`AddChild`], but updating the child transform to keep -/// it at the same [`GlobalTransform`]. -/// -/// You most likely want to use [`BuildChildrenTransformExt::set_parent_in_place`] -/// method on [`EntityCommands`] instead. -pub struct AddChildInPlace { - /// Parent entity to add the child to. - pub parent: Entity, - /// Child entity to add. - pub child: Entity, -} -impl Command for AddChildInPlace { - fn apply(self, world: &mut World) { - let hierarchy_command = AddChild { - child: self.child, - parent: self.parent, - }; - hierarchy_command.apply(world); - // FIXME: Replace this closure with a `try` block. See: https://github.com/rust-lang/rust/issues/31436. - let mut update_transform = || { - let parent = *world - .get_entity(self.parent) - .ok()? - .get::()?; - let child_global = *world - .get_entity(self.child) - .ok()? - .get::()?; - let mut child_entity = world.get_entity_mut(self.child).ok()?; - let mut child = child_entity.get_mut::()?; - *child = child_global.reparented_to(&parent); - Some(()) - }; - update_transform(); - } -} -/// Command similar to [`RemoveParent`], but updating the child transform to keep -/// it at the same [`GlobalTransform`]. -/// -/// You most likely want to use [`BuildChildrenTransformExt::remove_parent_in_place`] -/// method on [`EntityCommands`] instead. -pub struct RemoveParentInPlace { - /// [`Entity`] whose parent must be removed. - pub child: Entity, -} -impl Command for RemoveParentInPlace { - fn apply(self, world: &mut World) { - let hierarchy_command = RemoveParent { child: self.child }; - hierarchy_command.apply(world); - // FIXME: Replace this closure with a `try` block. See: https://github.com/rust-lang/rust/issues/31436. - let mut update_transform = || { - let child_global = *world - .get_entity(self.child) - .ok()? - .get::()?; - let mut child_entity = world.get_entity_mut(self.child).ok()?; - let mut child = child_entity.get_mut::()?; - *child = child_global.compute_transform(); - Some(()) - }; - update_transform(); - } -} -/// Collection of methods similar to [`BuildChildren`](bevy_hierarchy::BuildChildren), but preserving each +/// Collection of methods similar to [`BuildChildren`], but preserving each /// entity's [`GlobalTransform`]. pub trait BuildChildrenTransformExt { /// Change this entity's parent while preserving this entity's [`GlobalTransform`] /// by updating its [`Transform`]. /// - /// See [`BuildChildren::set_parent`](bevy_hierarchy::BuildChildren::set_parent) for a method that doesn't update the - /// [`Transform`]. + /// See [`BuildChildren::set_parent`] for a method that doesn't update the [`Transform`]. /// /// Note that both the hierarchy and transform updates will only execute /// the next time commands are applied @@ -89,38 +25,65 @@ pub trait BuildChildrenTransformExt { /// Make this entity parentless while preserving this entity's [`GlobalTransform`] /// by updating its [`Transform`] to be equal to its current [`GlobalTransform`]. /// - /// See [`BuildChildren::remove_parent`](bevy_hierarchy::BuildChildren::remove_parent) for a method that doesn't update the - /// [`Transform`]. + /// See [`BuildChildren::remove_parent`] for a method that doesn't update the [`Transform`]. /// /// Note that both the hierarchy and transform updates will only execute /// the next time commands are applied /// (during [`ApplyDeferred`](bevy_ecs::schedule::ApplyDeferred)). fn remove_parent_in_place(&mut self) -> &mut Self; } + impl BuildChildrenTransformExt for EntityCommands<'_> { fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self { - let child = self.id(); - self.commands().queue(AddChildInPlace { child, parent }); - self + self.queue(move |entity: Entity, world: &mut World| { + if let Ok(mut entity) = world.get_entity_mut(entity) { + entity.set_parent_in_place(parent); + } + }) } fn remove_parent_in_place(&mut self) -> &mut Self { - let child = self.id(); - self.commands().queue(RemoveParentInPlace { child }); - self + self.queue(move |entity: Entity, world: &mut World| { + if let Ok(mut entity) = world.get_entity_mut(entity) { + entity.remove_parent_in_place(); + } + }) } } impl BuildChildrenTransformExt for EntityWorldMut<'_> { fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self { let child = self.id(); - self.world_scope(|world| AddChildInPlace { child, parent }.apply(world)); + self.world_scope(|world| { + world.entity_mut(parent).add_child(child); + // FIXME: Replace this closure with a `try` block. See: https://github.com/rust-lang/rust/issues/31436. + let mut update_transform = || { + let parent = *world.get_entity(parent).ok()?.get::()?; + let child_global = *world.get_entity(child).ok()?.get::()?; + let mut child_entity = world.get_entity_mut(child).ok()?; + let mut child = child_entity.get_mut::()?; + *child = child_global.reparented_to(&parent); + Some(()) + }; + update_transform(); + }); self } fn remove_parent_in_place(&mut self) -> &mut Self { let child = self.id(); - self.world_scope(|world| RemoveParentInPlace { child }.apply(world)); + self.world_scope(|world| { + world.entity_mut(child).remove_parent(); + // FIXME: Replace this closure with a `try` block. See: https://github.com/rust-lang/rust/issues/31436. + let mut update_transform = || { + let child_global = *world.get_entity(child).ok()?.get::()?; + let mut child_entity = world.get_entity_mut(child).ok()?; + let mut child = child_entity.get_mut::()?; + *child = child_global.compute_transform(); + Some(()) + }; + update_transform(); + }); self } }