Skip to content

Commit 0941d20

Browse files
committed
Rename 'keep_global_transform' to 'in_place'
1 parent 5e6311e commit 0941d20

File tree

2 files changed

+245
-10
lines changed

2 files changed

+245
-10
lines changed

crates/bevy_transform/src/commands.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ use crate::{GlobalTransform, Transform};
1313
///
1414
/// You most likely want to use [`BuildChildrenTransformExt::set_parent_keep_global_transform`]
1515
/// method on [`EntityCommands`] instead.
16-
pub struct AddChildKeep {
16+
pub struct AddChildInPlace {
1717
/// Parent entity to add the child to.
1818
pub parent: Entity,
1919
/// Child entity to add.
2020
pub child: Entity,
2121
}
22-
impl Command for AddChildKeep {
22+
impl Command for AddChildInPlace {
2323
fn write(self, world: &mut World) {
2424
let hierarchy_command = AddChild {
2525
child: self.child,
@@ -42,11 +42,11 @@ impl Command for AddChildKeep {
4242
///
4343
/// You most likely want to use [`BuildChildrenTransformExt::remove_parent_keep_global_transform`]
4444
/// method on [`EntityCommands`] instead.
45-
struct RemoveParentKeep {
45+
struct RemoveParentInPlace {
4646
/// `Entity` which parent must be removed.
4747
child: Entity,
4848
}
49-
impl Command for RemoveParentKeep {
49+
impl Command for RemoveParentInPlace {
5050
fn write(self, world: &mut World) {
5151
let hierarchy_command = RemoveParent { child: self.child };
5252
hierarchy_command.write(world);
@@ -71,7 +71,7 @@ pub trait BuildChildrenTransformExt {
7171
///
7272
/// Note that both the hierarchy and transform updates will only execute
7373
/// at the end of the current stage.
74-
fn set_parent_keep_global_transform(&mut self, parent: Entity) -> &mut Self;
74+
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self;
7575

7676
/// Make this entity parentless while preserving this entity's [`GlobalTransform`]
7777
/// by updating its [`Transform`] to be equal to its current [`GlobalTransform`].
@@ -81,18 +81,18 @@ pub trait BuildChildrenTransformExt {
8181
///
8282
/// Note that both the hierarchy and transform updates will only execute
8383
/// at the end of the current stage.
84-
fn remove_parent_keep_global_transform(&mut self) -> &mut Self;
84+
fn remove_parent_in_place(&mut self) -> &mut Self;
8585
}
8686
impl<'w, 's, 'a> BuildChildrenTransformExt for EntityCommands<'w, 's, 'a> {
87-
fn remove_parent_keep_global_transform(&mut self) -> &mut Self {
87+
fn remove_parent_in_place(&mut self) -> &mut Self {
8888
let child = self.id();
89-
self.commands().add(RemoveParentKeep { child });
89+
self.commands().add(RemoveParentInPlace { child });
9090
self
9191
}
9292

93-
fn set_parent_keep_global_transform(&mut self, parent: Entity) -> &mut Self {
93+
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self {
9494
let child = self.id();
95-
self.commands().add(AddChildKeep { child, parent });
95+
self.commands().add(AddChildInPlace { child, parent });
9696
self
9797
}
9898
}
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
//! Illustrates the difference between direction of a translation in respect to local object or
2+
//! global object Transform.
3+
4+
use bevy::{math::Vec3A, prelude::*};
5+
6+
// Define a marker for entities that should be changed via their global transform.
7+
#[derive(Component)]
8+
struct ChangeGlobal;
9+
10+
// Define a marker for entities that should be changed via their local transform.
11+
#[derive(Component)]
12+
struct ChangeLocal;
13+
14+
// Define a marker for entities that should move.
15+
#[derive(Component)]
16+
struct Move;
17+
18+
// Define a resource for the current movement direction;
19+
#[derive(Resource, Default)]
20+
struct Direction(Vec3);
21+
22+
// Define component to decide when an entity should be ignored by the movement systems.
23+
#[derive(Component)]
24+
struct ToggledBy(KeyCode);
25+
26+
#[derive(Resource)]
27+
struct DynamicParent {
28+
green: Entity,
29+
yellow: Entity,
30+
has_hierarchy: bool,
31+
}
32+
33+
fn main() {
34+
App::new()
35+
.add_plugins(DefaultPlugins)
36+
.add_startup_system(setup)
37+
.init_resource::<Direction>()
38+
.add_system(move_cubes_according_to_global_transform)
39+
.add_system(move_cubes_according_to_local_transform)
40+
.add_system(update_directional_input)
41+
.add_system(toggle_movement)
42+
.run();
43+
}
44+
45+
// Startup system to setup the scene and spawn all relevant entities.
46+
fn setup(
47+
mut commands: Commands,
48+
mut meshes: ResMut<Assets<Mesh>>,
49+
mut materials: ResMut<Assets<StandardMaterial>>,
50+
asset_server: Res<AssetServer>,
51+
) {
52+
let mut green = None;
53+
// To show the difference between a local transform (rotation, scale and
54+
// position in respect to a given entity) and global transform (rotation,
55+
// scale and position in respect to the base coordinate system of the visible scene)
56+
// it's helpful to add multiple entities that are attached to each other.
57+
// This way we'll see that the transform in respect to an entity's parent is different to the
58+
// global transform within the visible scene.
59+
// This example focuses on translation only to clearly demonstrate the differences.
60+
61+
// Spawn a basic cube to have an entity as reference.
62+
let yellow = commands
63+
.spawn((
64+
PbrBundle {
65+
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
66+
material: materials.add(StandardMaterial {
67+
base_color: Color::YELLOW,
68+
alpha_mode: AlphaMode::Blend,
69+
..Default::default()
70+
}),
71+
..default()
72+
},
73+
ChangeGlobal,
74+
Move,
75+
ToggledBy(KeyCode::Key1),
76+
))
77+
// Spawn two entities as children above the original main entity.
78+
// The red entity spawned here will be changed via its global transform
79+
// where the green one will be changed via its local transform.
80+
.with_children(|child_builder| {
81+
// also see parenting example
82+
child_builder.spawn((
83+
PbrBundle {
84+
mesh: meshes.add(Mesh::from(shape::Cube { size: 0.5 })),
85+
material: materials.add(StandardMaterial {
86+
base_color: Color::RED,
87+
alpha_mode: AlphaMode::Blend,
88+
..Default::default()
89+
}),
90+
transform: Transform::from_translation(Vec3::Y - Vec3::Z),
91+
..default()
92+
},
93+
ChangeGlobal,
94+
Move,
95+
ToggledBy(KeyCode::Key2),
96+
));
97+
let green_content = child_builder
98+
.spawn((
99+
PbrBundle {
100+
mesh: meshes.add(Mesh::from(shape::Cube { size: 0.5 })),
101+
material: materials.add(StandardMaterial {
102+
base_color: Color::GREEN,
103+
alpha_mode: AlphaMode::Blend,
104+
..Default::default()
105+
}),
106+
transform: Transform::from_translation(Vec3::Y + Vec3::Z),
107+
..default()
108+
},
109+
ChangeLocal,
110+
Move,
111+
ToggledBy(KeyCode::Key3),
112+
))
113+
.id();
114+
green = Some(green_content);
115+
})
116+
.id();
117+
commands.insert_resource(DynamicParent {
118+
green: green.unwrap(),
119+
yellow,
120+
has_hierarchy: true,
121+
});
122+
123+
// Spawn a camera looking at the entities to show what's happening in this example.
124+
commands.spawn(Camera3dBundle {
125+
transform: Transform::from_xyz(0.0, 10.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
126+
..default()
127+
});
128+
129+
// Add a light source for better 3d visibility.
130+
commands.spawn(PointLightBundle {
131+
transform: Transform::from_translation(Vec3::splat(3.0)),
132+
..default()
133+
});
134+
135+
// Add text to explain inputs and what is happening.
136+
commands.spawn(TextBundle::from_section(
137+
"Press the arrow keys to move the cubes. \
138+
Toggle movement for yellow (1), red (2) and green (3) cubes via number keys.\n\n\
139+
Notice how the green cube will translate further in respect to the \
140+
yellow in contrast to the red cube.\n\
141+
This is due to the use of its LocalTransform that is relative to the \
142+
yellow cubes transform instead of the GlobalTransform as in the case of the red cube.\n\
143+
The red cube is moved through its GlobalTransform and thus is \
144+
unaffected by the yellows transform.\n\
145+
You can toggle the parent relationship between the green and yellow cubes using (4)",
146+
TextStyle {
147+
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
148+
font_size: 22.0,
149+
color: Color::WHITE,
150+
},
151+
));
152+
}
153+
154+
// This system will move all cubes that are marked as ChangeGlobal according to their global transform.
155+
fn move_cubes_according_to_global_transform(
156+
mut cubes: Query<&mut GlobalTransform, (With<ChangeGlobal>, With<Move>)>,
157+
direction: Res<Direction>,
158+
time: Res<Time>,
159+
) {
160+
for mut global_transform in &mut cubes {
161+
*global_transform.translation_mut() += Vec3A::from(direction.0) * time.delta_seconds();
162+
}
163+
}
164+
165+
// This system will move all cubes that are marked as ChangeLocal according to their local transform.
166+
fn move_cubes_according_to_local_transform(
167+
mut cubes: Query<&mut Transform, (With<ChangeLocal>, With<Move>)>,
168+
direction: Res<Direction>,
169+
time: Res<Time>,
170+
) {
171+
for mut transform in &mut cubes {
172+
transform.translation += direction.0 * time.delta_seconds();
173+
}
174+
}
175+
176+
// This system updates a resource that defines in which direction the cubes should move.
177+
// The direction is defined by the input of arrow keys and is only in left/right and up/down direction.
178+
fn update_directional_input(mut direction: ResMut<Direction>, keyboard_input: Res<Input<KeyCode>>) {
179+
let horizontal_movement = Vec3::X
180+
* (keyboard_input.pressed(KeyCode::Right) as i32
181+
- keyboard_input.pressed(KeyCode::Left) as i32) as f32;
182+
let vertical_movement = Vec3::Y
183+
* (keyboard_input.pressed(KeyCode::Up) as i32
184+
- keyboard_input.pressed(KeyCode::Down) as i32) as f32;
185+
direction.0 = horizontal_movement + vertical_movement;
186+
}
187+
188+
// This system enables and disables the movement for each entity if their assigned key is pressed.
189+
fn toggle_movement(
190+
mut commands: Commands,
191+
movable_entities: Query<(Entity, &Handle<StandardMaterial>, &ToggledBy), With<Move>>,
192+
static_entities: Query<(Entity, &Handle<StandardMaterial>, &ToggledBy), Without<Move>>,
193+
mut materials: ResMut<Assets<StandardMaterial>>,
194+
keyboard_input: Res<Input<KeyCode>>,
195+
mut dynamic_parent: ResMut<DynamicParent>,
196+
) {
197+
if keyboard_input.just_pressed(KeyCode::Key4) {
198+
if dynamic_parent.has_hierarchy {
199+
commands
200+
.entity(dynamic_parent.green)
201+
.remove_parent_in_place();
202+
} else {
203+
commands
204+
.entity(dynamic_parent.green)
205+
.set_parent_in_place(dynamic_parent.yellow);
206+
}
207+
dynamic_parent.has_hierarchy = !dynamic_parent.has_hierarchy;
208+
}
209+
// Update the currently movable entities and remove their Move component if
210+
// the assigned key was pressed to disable their movement. This will also
211+
// make them transparent so they can be identified as 'disabled' in the scene.
212+
for (entity, material_handle, toggled_by) in &movable_entities {
213+
if keyboard_input.just_pressed(toggled_by.0) {
214+
materials
215+
.get_mut(material_handle)
216+
.unwrap()
217+
.base_color
218+
.set_a(0.5);
219+
commands.entity(entity).remove::<Move>();
220+
}
221+
}
222+
// Update the currently non-movable entities and add a Move component if
223+
// the assigned key was pressed to enable their movement. This will also
224+
// make them opaque so they can be identified as 'enabled' in the scene.
225+
for (entity, material_handle, toggled_by) in &static_entities {
226+
if keyboard_input.just_pressed(toggled_by.0) {
227+
materials
228+
.get_mut(material_handle)
229+
.unwrap()
230+
.base_color
231+
.set_a(1.0);
232+
commands.entity(entity).insert(Move);
233+
}
234+
}
235+
}

0 commit comments

Comments
 (0)