mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Remove the GlobalTransform::translation_mut
method (#7134)
# Objective It is possible to manually update `GlobalTransform`. The engine actually assumes this is not possible. For example, `propagate_transform` does not update children of an `Entity` which **`GlobalTransform`** changed, leading to unexpected behaviors. A `GlobalTransform` set by the user may also be blindly overwritten by the propagation system. ## Solution - Remove `translation_mut` - Explain to users that they shouldn't manually update the `GlobalTransform` - Remove `global_vs_local.rs` example, since it misleads users in believing that it is a valid use-case to manually update the `GlobalTransform` --- ## Changelog - Remove `GlobalTransform::translation_mut` ## Migration Guide `GlobalTransform::translation_mut` has been removed without alternative, if you were relying on this, update the `Transform` instead. If the given entity had children or parent, you may need to remove its parent to make its transform independent (in which case the new `Commands::set_parent_in_place` and `Commands::remove_parent_in_place` may be of interest) Bevy may add in the future a way to toggle transform propagation on an entity basis.
This commit is contained in:
parent
fa40e2badb
commit
3600c5a340
4 changed files with 4 additions and 218 deletions
11
Cargo.toml
11
Cargo.toml
|
@ -1384,17 +1384,6 @@ description = "Shows a visualization of gamepad buttons, sticks, and triggers"
|
|||
category = "Tools"
|
||||
wasm = false
|
||||
|
||||
# Transforms
|
||||
[[example]]
|
||||
name = "global_vs_local_translation"
|
||||
path = "examples/transforms/global_vs_local_translation.rs"
|
||||
|
||||
[package.metadata.example.global_vs_local_translation]
|
||||
name = "Global / Local Translation"
|
||||
description = "Illustrates the difference between direction of a translation in respect to local object or global object Transform"
|
||||
category = "Transforms"
|
||||
wasm = true
|
||||
|
||||
[[example]]
|
||||
name = "3d_rotation"
|
||||
path = "examples/transforms/3d_rotation.rs"
|
||||
|
|
|
@ -8,6 +8,8 @@ use bevy_reflect::{std_traits::ReflectDefault, FromReflect, Reflect};
|
|||
/// Describe the position of an entity relative to the reference frame.
|
||||
///
|
||||
/// * To place or move an entity, you should set its [`Transform`].
|
||||
/// * [`GlobalTransform`] is fully managed by bevy, you cannot mutate it, use
|
||||
/// [`Transform`] instead.
|
||||
/// * To get the global transform of an entity, you should get its [`GlobalTransform`].
|
||||
/// * For transform hierarchies to work correctly, you must have both a [`Transform`] and a [`GlobalTransform`].
|
||||
/// * You may use the [`TransformBundle`](crate::TransformBundle) to guarantee this.
|
||||
|
@ -28,9 +30,9 @@ use bevy_reflect::{std_traits::ReflectDefault, FromReflect, Reflect};
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// - [`global_vs_local_translation`]
|
||||
/// - [`transform`]
|
||||
///
|
||||
/// [`global_vs_local_translation`]: https://github.com/bevyengine/bevy/blob/latest/examples/transforms/global_vs_local_translation.rs
|
||||
/// [`transform`]: https://github.com/bevyengine/bevy/blob/latest/examples/transforms/transform.rs
|
||||
#[derive(Component, Debug, PartialEq, Clone, Copy, Reflect, FromReflect)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[reflect(Component, Default, PartialEq)]
|
||||
|
@ -169,12 +171,6 @@ impl GlobalTransform {
|
|||
self.0.translation.into()
|
||||
}
|
||||
|
||||
/// Mutably access the internal translation.
|
||||
#[inline]
|
||||
pub fn translation_mut(&mut self) -> &mut Vec3A {
|
||||
&mut self.0.translation
|
||||
}
|
||||
|
||||
/// Get the translation as a [`Vec3A`].
|
||||
#[inline]
|
||||
pub fn translation_vec3a(&self) -> Vec3A {
|
||||
|
|
|
@ -302,7 +302,6 @@ Example | Description
|
|||
Example | Description
|
||||
--- | ---
|
||||
[3D Rotation](../examples/transforms/3d_rotation.rs) | Illustrates how to (constantly) rotate an object around an axis
|
||||
[Global / Local Translation](../examples/transforms/global_vs_local_translation.rs) | Illustrates the difference between direction of a translation in respect to local object or global object Transform
|
||||
[Scale](../examples/transforms/scale.rs) | Illustrates how to scale an object in each direction
|
||||
[Transform](../examples/transforms/transform.rs) | Shows multiple transformations of objects
|
||||
[Translation](../examples/transforms/translation.rs) | Illustrates how to move an object along an axis
|
||||
|
|
|
@ -1,198 +0,0 @@
|
|||
//! Illustrates the difference between direction of a translation in respect to local object or
|
||||
//! global object Transform.
|
||||
|
||||
use bevy::{math::Vec3A, prelude::*};
|
||||
|
||||
// Define a marker for entities that should be changed via their global transform.
|
||||
#[derive(Component)]
|
||||
struct ChangeGlobal;
|
||||
|
||||
// Define a marker for entities that should be changed via their local transform.
|
||||
#[derive(Component)]
|
||||
struct ChangeLocal;
|
||||
|
||||
// Define a marker for entities that should move.
|
||||
#[derive(Component)]
|
||||
struct Move;
|
||||
|
||||
// Define a resource for the current movement direction;
|
||||
#[derive(Resource, Default)]
|
||||
struct Direction(Vec3);
|
||||
|
||||
// Define component to decide when an entity should be ignored by the movement systems.
|
||||
#[derive(Component)]
|
||||
struct ToggledBy(KeyCode);
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_startup_system(setup)
|
||||
.init_resource::<Direction>()
|
||||
.add_system(move_cubes_according_to_global_transform)
|
||||
.add_system(move_cubes_according_to_local_transform)
|
||||
.add_system(update_directional_input)
|
||||
.add_system(toggle_movement)
|
||||
.run();
|
||||
}
|
||||
|
||||
// Startup system to setup the scene and spawn all relevant entities.
|
||||
fn setup(
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
// To show the difference between a local transform (rotation, scale and position in respect to a given entity)
|
||||
// and global transform (rotation, scale and position in respect to the base coordinate system of the visible scene)
|
||||
// it's helpful to add multiple entities that are attached to each other.
|
||||
// This way we'll see that the transform in respect to an entity's parent is different to the
|
||||
// global transform within the visible scene.
|
||||
// This example focuses on translation only to clearly demonstrate the differences.
|
||||
|
||||
// Spawn a basic cube to have an entity as reference.
|
||||
commands
|
||||
.spawn((
|
||||
PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||
material: materials.add(StandardMaterial {
|
||||
base_color: Color::YELLOW,
|
||||
alpha_mode: AlphaMode::Blend,
|
||||
..Default::default()
|
||||
}),
|
||||
..default()
|
||||
},
|
||||
ChangeGlobal,
|
||||
Move,
|
||||
ToggledBy(KeyCode::Key1),
|
||||
))
|
||||
// Spawn two entities as children above the original main entity.
|
||||
// The red entity spawned here will be changed via its global transform
|
||||
// where the green one will be changed via its local transform.
|
||||
.with_children(|child_builder| {
|
||||
// also see parenting example
|
||||
child_builder.spawn((
|
||||
PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 0.5 })),
|
||||
material: materials.add(StandardMaterial {
|
||||
base_color: Color::RED,
|
||||
alpha_mode: AlphaMode::Blend,
|
||||
..Default::default()
|
||||
}),
|
||||
transform: Transform::from_translation(Vec3::Y - Vec3::Z),
|
||||
..default()
|
||||
},
|
||||
ChangeGlobal,
|
||||
Move,
|
||||
ToggledBy(KeyCode::Key2),
|
||||
));
|
||||
child_builder.spawn((
|
||||
PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 0.5 })),
|
||||
material: materials.add(StandardMaterial {
|
||||
base_color: Color::GREEN,
|
||||
alpha_mode: AlphaMode::Blend,
|
||||
..Default::default()
|
||||
}),
|
||||
transform: Transform::from_translation(Vec3::Y + Vec3::Z),
|
||||
..default()
|
||||
},
|
||||
ChangeLocal,
|
||||
Move,
|
||||
ToggledBy(KeyCode::Key3),
|
||||
));
|
||||
});
|
||||
|
||||
// Spawn a camera looking at the entities to show what's happening in this example.
|
||||
commands.spawn(Camera3dBundle {
|
||||
transform: Transform::from_xyz(0.0, 10.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
..default()
|
||||
});
|
||||
|
||||
// Add a light source for better 3d visibility.
|
||||
commands.spawn(PointLightBundle {
|
||||
transform: Transform::from_translation(Vec3::splat(3.0)),
|
||||
..default()
|
||||
});
|
||||
|
||||
// Add text to explain inputs and what is happening.
|
||||
commands.spawn(TextBundle::from_section(
|
||||
"Press the arrow keys to move the cubes. Toggle movement for yellow (1), red (2) and green (3) cubes via number keys.
|
||||
|
||||
Notice how the green cube will translate further in respect to the yellow in contrast to the red cube.
|
||||
This is due to the use of its LocalTransform that is relative to the yellow cubes transform instead of the GlobalTransform as in the case of the red cube.
|
||||
The red cube is moved through its GlobalTransform and thus is unaffected by the yellows transform.",
|
||||
TextStyle {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 22.0,
|
||||
color: Color::WHITE,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
// This system will move all cubes that are marked as ChangeGlobal according to their global transform.
|
||||
fn move_cubes_according_to_global_transform(
|
||||
mut cubes: Query<&mut GlobalTransform, (With<ChangeGlobal>, With<Move>)>,
|
||||
direction: Res<Direction>,
|
||||
timer: Res<Time>,
|
||||
) {
|
||||
for mut global_transform in &mut cubes {
|
||||
*global_transform.translation_mut() += Vec3A::from(direction.0) * timer.delta_seconds();
|
||||
}
|
||||
}
|
||||
|
||||
// This system will move all cubes that are marked as ChangeLocal according to their local transform.
|
||||
fn move_cubes_according_to_local_transform(
|
||||
mut cubes: Query<&mut Transform, (With<ChangeLocal>, With<Move>)>,
|
||||
direction: Res<Direction>,
|
||||
timer: Res<Time>,
|
||||
) {
|
||||
for mut transform in &mut cubes {
|
||||
transform.translation += direction.0 * timer.delta_seconds();
|
||||
}
|
||||
}
|
||||
|
||||
// This system updates a resource that defines in which direction the cubes should move.
|
||||
// The direction is defined by the input of arrow keys and is only in left/right and up/down direction.
|
||||
fn update_directional_input(mut direction: ResMut<Direction>, keyboard_input: Res<Input<KeyCode>>) {
|
||||
let horizontal_movement = Vec3::X
|
||||
* (keyboard_input.pressed(KeyCode::Right) as i32
|
||||
- keyboard_input.pressed(KeyCode::Left) as i32) as f32;
|
||||
let vertical_movement = Vec3::Y
|
||||
* (keyboard_input.pressed(KeyCode::Up) as i32
|
||||
- keyboard_input.pressed(KeyCode::Down) as i32) as f32;
|
||||
direction.0 = horizontal_movement + vertical_movement;
|
||||
}
|
||||
|
||||
// This system enables and disables the movement for each entity if their assigned key is pressed.
|
||||
fn toggle_movement(
|
||||
mut commands: Commands,
|
||||
movable_entities: Query<(Entity, &Handle<StandardMaterial>, &ToggledBy), With<Move>>,
|
||||
static_entities: Query<(Entity, &Handle<StandardMaterial>, &ToggledBy), Without<Move>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
keyboard_input: Res<Input<KeyCode>>,
|
||||
) {
|
||||
// Update the currently movable entities and remove their Move component if the assigned key was pressed to disable their movement.
|
||||
// This will also make them transparent so they can be identified as 'disabled' in the scene.
|
||||
for (entity, material_handle, toggled_by) in &movable_entities {
|
||||
if keyboard_input.just_pressed(toggled_by.0) {
|
||||
materials
|
||||
.get_mut(material_handle)
|
||||
.unwrap()
|
||||
.base_color
|
||||
.set_a(0.5);
|
||||
commands.entity(entity).remove::<Move>();
|
||||
}
|
||||
}
|
||||
// Update the currently non-movable entities and add a Move component if the assigned key was pressed to enable their movement.
|
||||
// This will also make them opaque so they can be identified as 'enabled' in the scene.
|
||||
for (entity, material_handle, toggled_by) in &static_entities {
|
||||
if keyboard_input.just_pressed(toggled_by.0) {
|
||||
materials
|
||||
.get_mut(material_handle)
|
||||
.unwrap()
|
||||
.base_color
|
||||
.set_a(1.0);
|
||||
commands.entity(entity).insert(Move);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue