Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_transform/src/commands.rs
6596 views
1
//! Extension to [`EntityCommands`] to modify [`bevy_ecs::hierarchy`] hierarchies.
2
//! while preserving [`GlobalTransform`].
3
4
use crate::prelude::{GlobalTransform, Transform};
5
use bevy_ecs::{entity::Entity, hierarchy::ChildOf, system::EntityCommands, world::EntityWorldMut};
6
7
/// Collection of methods similar to the built-in parenting methods on [`EntityWorldMut`] and [`EntityCommands`], but preserving each
8
/// entity's [`GlobalTransform`].
9
pub trait BuildChildrenTransformExt {
10
/// Change this entity's parent while preserving this entity's [`GlobalTransform`]
11
/// by updating its [`Transform`].
12
///
13
/// Insert the [`ChildOf`] component directly if you don't want to also update the [`Transform`].
14
///
15
/// Note that both the hierarchy and transform updates will only execute
16
/// the next time commands are applied
17
/// (during [`ApplyDeferred`](bevy_ecs::schedule::ApplyDeferred)).
18
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self;
19
20
/// Make this entity parentless while preserving this entity's [`GlobalTransform`]
21
/// by updating its [`Transform`] to be equal to its current [`GlobalTransform`].
22
///
23
/// See [`EntityWorldMut::remove::<ChildOf>`] or [`EntityCommands::remove::<ChildOf>`] for a method that doesn't update the [`Transform`].
24
///
25
/// Note that both the hierarchy and transform updates will only execute
26
/// the next time commands are applied
27
/// (during [`ApplyDeferred`](bevy_ecs::schedule::ApplyDeferred)).
28
fn remove_parent_in_place(&mut self) -> &mut Self;
29
}
30
31
impl BuildChildrenTransformExt for EntityCommands<'_> {
32
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self {
33
self.queue(move |mut entity: EntityWorldMut| {
34
entity.set_parent_in_place(parent);
35
})
36
}
37
38
fn remove_parent_in_place(&mut self) -> &mut Self {
39
self.queue(move |mut entity: EntityWorldMut| {
40
entity.remove_parent_in_place();
41
})
42
}
43
}
44
45
impl BuildChildrenTransformExt for EntityWorldMut<'_> {
46
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self {
47
// FIXME: Replace this closure with a `try` block. See: https://github.com/rust-lang/rust/issues/31436.
48
let mut update_transform = || {
49
let child = self.id();
50
let parent_global = self.world_scope(|world| {
51
world
52
.get_entity_mut(parent)
53
.ok()?
54
.add_child(child)
55
.get::<GlobalTransform>()
56
.copied()
57
})?;
58
let child_global = self.get::<GlobalTransform>()?;
59
let new_child_local = child_global.reparented_to(&parent_global);
60
let mut child_local = self.get_mut::<Transform>()?;
61
*child_local = new_child_local;
62
Some(())
63
};
64
update_transform();
65
self
66
}
67
68
fn remove_parent_in_place(&mut self) -> &mut Self {
69
self.remove::<ChildOf>();
70
// FIXME: Replace this closure with a `try` block. See: https://github.com/rust-lang/rust/issues/31436.
71
let mut update_transform = || {
72
let global = self.get::<GlobalTransform>()?;
73
let new_local = global.compute_transform();
74
let mut local = self.get_mut::<Transform>()?;
75
*local = new_local;
76
Some(())
77
};
78
update_transform();
79
self
80
}
81
}
82
83