Skip to content

Commit

Permalink
Migrate bevy_transform to required components (bevyengine#14964)
Browse files Browse the repository at this point in the history
The first step in the migration to required components! This PR removes
`GlobalTransform` from all user-facing code, since it's now added
automatically wherever `Transform` is used.

## Testing

- None of the examples I tested were broken, and I assume breaking
transforms in any way would be visible *everywhere*

---

## Changelog

- Make `Transform` require `GlobalTransform`
~~- Remove `GlobalTransform` from all engine bundles~~
- Remove in-engine insertions of GlobalTransform and TransformBundle
- Deprecate `TransformBundle`
- update docs to reflect changes

## Migration Guide

Replace all insertions of `GlobalTransform` and/or `TransformBundle`
with `Transform` alone.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Tim <JustTheCoolDude@gmail.com>
  • Loading branch information
3 people authored and robtfm committed Oct 4, 2024
1 parent 92a204e commit 3727640
Show file tree
Hide file tree
Showing 10 changed files with 43 additions and 67 deletions.
5 changes: 5 additions & 0 deletions crates/bevy_transform/src/bundles.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![expect(deprecated)]
use bevy_ecs::bundle::Bundle;

use crate::prelude::{GlobalTransform, Transform};
Expand All @@ -24,6 +25,10 @@ use crate::prelude::{GlobalTransform, Transform};
/// update the [`Transform`] of an entity in this schedule or after, you will notice a 1 frame lag
/// before the [`GlobalTransform`] is updated.
#[derive(Clone, Copy, Debug, Default, Bundle)]
#[deprecated(
since = "0.15.0",
note = "Use the `Transform` component instead. Inserting `Transform` will now also insert a `GlobalTransform` automatically."
)]
pub struct TransformBundle {
/// The transform of the entity.
pub local: Transform,
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_transform/src/components/global_transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use {
///
/// * 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::bundles::TransformBundle) to guarantee this.
/// ~* You may use the [`TransformBundle`](crate::bundles::TransformBundle) to guarantee this.~
/// * [`TransformBundle`](crate::bundles::TransformBundle) is now deprecated.
/// [`GlobalTransform`] is automatically inserted whenever [`Transform`] is inserted.
///
/// ## [`Transform`] and [`GlobalTransform`]
///
Expand Down
5 changes: 4 additions & 1 deletion crates/bevy_transform/src/components/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use {
/// * To place or move an entity, you should set its [`Transform`].
/// * To get the global transform of an entity, you should get its [`GlobalTransform`].
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
/// * You may use the [`TransformBundle`](crate::bundles::TransformBundle) to guarantee this.
/// ~* You may use the [`TransformBundle`](crate::bundles::TransformBundle) to guarantee this.~
/// * [`TransformBundle`](crate::bundles::TransformBundle) is now deprecated.
/// [`GlobalTransform`] is inserted automatically whenever [`Transform`] is inserted.
///
/// ## [`Transform`] and [`GlobalTransform`]
///
Expand All @@ -39,6 +41,7 @@ use {
#[cfg_attr(
feature = "bevy-support",
derive(Component, Reflect),
require(GlobalTransform),
reflect(Component, Default, PartialEq, Debug)
)]
#[cfg_attr(
Expand Down
3 changes: 1 addition & 2 deletions crates/bevy_transform/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ mod tests {
use bevy_math::{Quat, Vec3};

use crate::{
bundles::TransformBundle,
components::{GlobalTransform, Transform},
helper::TransformHelper,
plugins::TransformPlugin,
Expand Down Expand Up @@ -122,7 +121,7 @@ mod tests {
let mut entity = None;

for transform in transforms {
let mut e = app.world_mut().spawn(TransformBundle::from(transform));
let mut e = app.world_mut().spawn(transform);

if let Some(entity) = entity {
e.set_parent(entity);
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub mod systems;
/// The transform prelude.
///
/// This includes the most common types in this crate, re-exported for your convenience.
#[doc(hidden)]
#[expect(deprecated)]
pub mod prelude {
#[doc(hidden)]
pub use crate::components::*;
Expand Down
61 changes: 18 additions & 43 deletions crates/bevy_transform/src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ mod test {
use bevy_math::{vec3, Vec3};
use bevy_tasks::{ComputeTaskPool, TaskPool};

use crate::{bundles::TransformBundle, systems::*};
use crate::systems::*;
use bevy_hierarchy::{BuildChildren, ChildBuild};

#[test]
Expand All @@ -199,8 +199,7 @@ mod test {
let mut world = World::default();
let offset_global_transform =
|offset| GlobalTransform::from(Transform::from_xyz(offset, offset, offset));
let offset_transform =
|offset| TransformBundle::from_transform(Transform::from_xyz(offset, offset, offset));
let offset_transform = |offset| Transform::from_xyz(offset, offset, offset);

let mut schedule = Schedule::default();
schedule.add_systems((sync_simple_transforms, propagate_transforms));
Expand Down Expand Up @@ -257,22 +256,14 @@ mod test {
schedule.add_systems((sync_simple_transforms, propagate_transforms));

// Root entity
world.spawn(TransformBundle::from(Transform::from_xyz(1.0, 0.0, 0.0)));
world.spawn(Transform::from_xyz(1.0, 0.0, 0.0));

let mut children = Vec::new();
world
.spawn(TransformBundle::from(Transform::from_xyz(1.0, 0.0, 0.0)))
.spawn(Transform::from_xyz(1.0, 0.0, 0.0))
.with_children(|parent| {
children.push(
parent
.spawn(TransformBundle::from(Transform::from_xyz(0.0, 2.0, 0.)))
.id(),
);
children.push(
parent
.spawn(TransformBundle::from(Transform::from_xyz(0.0, 0.0, 3.)))
.id(),
);
children.push(parent.spawn(Transform::from_xyz(0.0, 2.0, 0.)).id());
children.push(parent.spawn(Transform::from_xyz(0.0, 0.0, 3.)).id());
});
schedule.run(&mut world);

Expand All @@ -299,18 +290,10 @@ mod test {
let mut commands = Commands::new(&mut queue, &world);
let mut children = Vec::new();
commands
.spawn(TransformBundle::from(Transform::from_xyz(1.0, 0.0, 0.0)))
.spawn(Transform::from_xyz(1.0, 0.0, 0.0))
.with_children(|parent| {
children.push(
parent
.spawn(TransformBundle::from(Transform::from_xyz(0.0, 2.0, 0.0)))
.id(),
);
children.push(
parent
.spawn(TransformBundle::from(Transform::from_xyz(0.0, 0.0, 3.0)))
.id(),
);
children.push(parent.spawn(Transform::from_xyz(0.0, 2.0, 0.0)).id());
children.push(parent.spawn(Transform::from_xyz(0.0, 0.0, 3.0)).id());
});
queue.apply(&mut world);
schedule.run(&mut world);
Expand Down Expand Up @@ -417,15 +400,12 @@ mod test {
let mut grandchild = Entity::from_raw(1);
let parent = app
.world_mut()
.spawn((
Transform::from_translation(translation),
GlobalTransform::IDENTITY,
))
.spawn(Transform::from_translation(translation))
.with_children(|builder| {
child = builder
.spawn(TransformBundle::IDENTITY)
.spawn(Transform::IDENTITY)
.with_children(|builder| {
grandchild = builder.spawn(TransformBundle::IDENTITY).id();
grandchild = builder.spawn(Transform::IDENTITY).id();
})
.id();
})
Expand Down Expand Up @@ -462,9 +442,9 @@ mod test {
fn setup_world(world: &mut World) -> (Entity, Entity) {
let mut grandchild = Entity::from_raw(0);
let child = world
.spawn(TransformBundle::IDENTITY)
.spawn(Transform::IDENTITY)
.with_children(|builder| {
grandchild = builder.spawn(TransformBundle::IDENTITY).id();
grandchild = builder.spawn(Transform::IDENTITY).id();
})
.id();
(child, grandchild)
Expand All @@ -477,7 +457,7 @@ mod test {
assert_eq!(temp_grandchild, grandchild);

app.world_mut()
.spawn(TransformBundle::IDENTITY)
.spawn(Transform::IDENTITY)
.add_children(&[child]);
core::mem::swap(
&mut *app.world_mut().get_mut::<Parent>(child).unwrap(),
Expand All @@ -496,14 +476,9 @@ mod test {
let mut schedule = Schedule::default();
schedule.add_systems((sync_simple_transforms, propagate_transforms));

// Spawn a `TransformBundle` entity with a local translation of `Vec3::ONE`
let mut spawn_transform_bundle = || {
world
.spawn(TransformBundle::from_transform(
Transform::from_translation(translation),
))
.id()
};
// Spawn a `Transform` entity with a local translation of `Vec3::ONE`
let mut spawn_transform_bundle =
|| world.spawn(Transform::from_translation(translation)).id();

// Spawn parent and child with identical transform bundles
let parent = spawn_transform_bundle();
Expand Down
14 changes: 5 additions & 9 deletions errors/B0004.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn setup_cube(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands
.spawn(TransformBundle::default())
.spawn(Transform::default())
.with_children(|parent| {
// cube
parent.spawn(PbrBundle {
Expand Down Expand Up @@ -61,8 +61,7 @@ doesn't have a [`ViewVisibility`] or [`InheritedVisibility`] component.
Since the cube is spawned as a child of an entity without the
visibility components, it will not be visible at all.

To fix this, you must use [`SpatialBundle`] over [`TransformBundle`],
as follows:
To fix this, you must use [`SpatialBundle`], as follows:

```rust,no_run
use bevy::prelude::*;
Expand All @@ -73,7 +72,7 @@ fn setup_cube(
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands
// We use SpatialBundle instead of TransformBundle, it contains the
// We use SpatialBundle instead of Transform, it contains the
// visibility components needed to display the cube,
// In addition to the Transform and GlobalTransform components.
.spawn(SpatialBundle::default())
Expand Down Expand Up @@ -103,18 +102,15 @@ fn main() {
```

A similar problem occurs when the [`GlobalTransform`] component is missing.
However, when a parent [`GlobalTransform`] is missing,
it will simply prevent all transform propagation,
including when updating the [`Transform`] component of the child.
However, it will be automatically inserted whenever `Transform` is
inserted, as it's a required component.

You will most likely encounter this warning when loading a scene
as a child of a pre-existing [`Entity`] that does not have the proper components.

[`InheritedVisibility`]: https://docs.rs/bevy/*/bevy/render/view/struct.InheritedVisibility.html
[`ViewVisibility`]: https://docs.rs/bevy/*/bevy/render/view/struct.ViewVisibility.html
[`GlobalTransform`]: https://docs.rs/bevy/*/bevy/transform/components/struct.GlobalTransform.html
[`Transform`]: https://docs.rs/bevy/*/bevy/transform/components/struct.Transform.html
[`Parent`]: https://docs.rs/bevy/*/bevy/hierarchy/struct.Parent.html
[`Entity`]: https://docs.rs/bevy/*/bevy/ecs/entity/struct.Entity.html
[`SpatialBundle`]: https://docs.rs/bevy/*/bevy/render/prelude/struct.SpatialBundle.html
[`TransformBundle`]: https://docs.rs/bevy/*/bevy/transform/struct.TransformBundle.html
10 changes: 2 additions & 8 deletions examples/animation/custom_skinned_mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,9 @@ fn setup(
for i in -5..5 {
// Create joint entities
let joint_0 = commands
.spawn(TransformBundle::from(Transform::from_xyz(
i as f32 * 1.5,
0.0,
i as f32 * 0.1,
)))
.id();
let joint_1 = commands
.spawn((AnimatedJoint, TransformBundle::IDENTITY))
.spawn(Transform::from_xyz(i as f32 * 1.5, 0.0, i as f32 * 0.1))
.id();
let joint_1 = commands.spawn((AnimatedJoint, Transform::IDENTITY)).id();

// Set joint_1 as a child of joint_0.
commands.entity(joint_0).add_children(&[joint_1]);
Expand Down
2 changes: 1 addition & 1 deletion examples/asset/asset_decompression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
..default()
},
Sprite::default(),
TransformBundle::default(),
Transform::default(),
VisibilityBundle::default(),
));
}
Expand Down
4 changes: 2 additions & 2 deletions examples/stress_tests/transform_hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ fn spawn_tree(
}

// insert root
ents.push(commands.spawn(TransformBundle::from(root_transform)).id());
ents.push(commands.spawn(root_transform).id());

let mut result = InsertResult::default();
let mut rng = rand::thread_rng();
Expand Down Expand Up @@ -426,7 +426,7 @@ fn spawn_tree(
};

// only insert the components necessary for the transform propagation
cmd = cmd.insert(TransformBundle::from(transform));
cmd = cmd.insert(transform);

cmd.id()
};
Expand Down

0 comments on commit 3727640

Please sign in to comment.