Skip to content

Commit 9680de3

Browse files
committed
Add TransformBundle
1 parent 91c3b21 commit 9680de3

File tree

11 files changed

+129
-104
lines changed

11 files changed

+129
-104
lines changed

crates/bevy_gltf/src/loader.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use bevy_render::{
2020
use bevy_scene::Scene;
2121
use bevy_transform::{
2222
hierarchy::{BuildWorldChildren, WorldChildBuilder},
23-
prelude::{GlobalTransform, Transform},
23+
prelude::Transform,
24+
TransformBundle,
2425
};
2526
use gltf::{
2627
mesh::Mode,
@@ -280,7 +281,7 @@ async fn load_gltf<'a, 'b>(
280281
let mut world = World::default();
281282
world
282283
.spawn()
283-
.insert_bundle((Transform::identity(), GlobalTransform::identity()))
284+
.insert_bundle(TransformBundle::identity())
284285
.with_children(|parent| {
285286
for node in scene.nodes() {
286287
let result = load_node(&node, parent, load_context, &buffer_data);
@@ -450,9 +451,8 @@ fn load_node(
450451
) -> Result<(), GltfError> {
451452
let transform = gltf_node.transform();
452453
let mut gltf_error = None;
453-
let mut node = world_builder.spawn_bundle((
454+
let mut node = world_builder.spawn_bundle(TransformBundle::from_transform(
454455
Transform::from_matrix(Mat4::from_cols_array_2d(&transform.matrix())),
455-
GlobalTransform::identity(),
456456
));
457457

458458
if let Some(name) = gltf_node.name() {

crates/bevy_transform/src/components/global_transform.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use std::ops::Mul;
77
/// Describe the position of an entity relative to the reference frame.
88
///
99
/// * To place or move an entity, you should set its [`Transform`].
10-
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
1110
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
11+
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
12+
/// * You may use the [`TransformBundle`] to guarantee this.
1213
///
1314
/// ## [`Transform`] and [`GlobalTransform`]
1415
///
@@ -20,16 +21,6 @@ use std::ops::Mul;
2021
/// [`GlobalTransform`] is updated from [`Transform`] in the system
2122
/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system).
2223
///
23-
/// In pseudo code:
24-
/// ```ignore
25-
/// for entity in entities_without_parent:
26-
/// set entity.global_transform to entity.transform
27-
/// recursively:
28-
/// set parent to current entity
29-
/// for child in parent.children:
30-
/// set child.global_transform to parent.global_transform * child.transform
31-
/// ```
32-
///
3324
/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
3425
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
3526
/// before the [`GlobalTransform`] is updated.

crates/bevy_transform/src/components/transform.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use std::ops::Mul;
88
/// to its parent position.
99
///
1010
/// * To place or move an entity, you should set its [`Transform`].
11-
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
1211
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
12+
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
13+
/// * You may use the [`TransformBundle`] to guarantee this.
1314
///
1415
/// ## [`Transform`] and [`GlobalTransform`]
1516
///
@@ -21,16 +22,6 @@ use std::ops::Mul;
2122
/// [`GlobalTransform`] is updated from [`Transform`] in the system
2223
/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system).
2324
///
24-
/// In pseudo code:
25-
/// ```ignore
26-
/// for entity in entities_without_parent:
27-
/// set entity.global_transform to entity.transform
28-
/// recursively:
29-
/// set parent to current entity
30-
/// for child in parent.children:
31-
/// set child.global_transform to parent.global_transform * child.transform
32-
/// ```
33-
///
3425
/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
3526
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
3627
/// before the [`GlobalTransform`] is updated.

crates/bevy_transform/src/lib.rs

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,73 @@ pub mod transform_propagate_system;
44

55
pub mod prelude {
66
#[doc(hidden)]
7-
pub use crate::{components::*, hierarchy::*, TransformPlugin};
7+
pub use crate::{components::*, hierarchy::*, TransformBundle, TransformPlugin};
88
}
99

1010
use bevy_app::prelude::*;
11-
use bevy_ecs::schedule::{ParallelSystemDescriptorCoercion, SystemLabel};
11+
use bevy_ecs::{
12+
bundle::Bundle,
13+
schedule::{ParallelSystemDescriptorCoercion, SystemLabel},
14+
};
1215
use prelude::{parent_update_system, Children, GlobalTransform, Parent, PreviousParent, Transform};
1316

17+
/// A [`Bundle`] of the [`Transform`] and [`GlobalTransform`]
18+
/// [`Component`](bevy_ecs::component::Component)s, which describe the position of an entity.
19+
///
20+
/// * To place or move an entity, you should set its [`Transform`].
21+
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
22+
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
23+
/// * You may use the [`TransformBundle`] to guarantee this.
24+
///
25+
/// ## [`Transform`] and [`GlobalTransform`]
26+
///
27+
/// [`Transform`] is the position of an entity relative to its parent position, or the reference
28+
/// frame if it doesn't have a [`Parent`](Parent).
29+
///
30+
/// [`GlobalTransform`] is the position of an entity relative to the reference frame.
31+
///
32+
/// [`GlobalTransform`] is updated from [`Transform`] in the system
33+
/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system).
34+
///
35+
/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
36+
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
37+
/// before the [`GlobalTransform`] is updated.
38+
#[derive(Default, Bundle, Clone, Debug)]
39+
pub struct TransformBundle {
40+
pub local: Transform,
41+
pub global: GlobalTransform,
42+
}
43+
44+
impl TransformBundle {
45+
/// Creates a new [`TransformBundle`] from a [`Transform`] and leaving [`GlobalTransform`] with
46+
/// no translation, rotation, and a scale of 1 on all axes.
47+
#[inline]
48+
pub const fn from_transform(transform: Transform) -> Self {
49+
TransformBundle {
50+
local: transform,
51+
// Note: `..Default::default()` cannot be used here, because it isn't const
52+
..Self::identity()
53+
}
54+
}
55+
56+
/// Creates a new identity [`TransformBundle`], with no translation, rotation, and a scale of 1
57+
/// on all axes.
58+
#[inline]
59+
pub const fn identity() -> Self {
60+
TransformBundle {
61+
local: Transform::identity(),
62+
global: GlobalTransform::identity(),
63+
}
64+
}
65+
}
66+
67+
impl From<Transform> for TransformBundle {
68+
#[inline]
69+
fn from(transform: Transform) -> Self {
70+
Self::from_transform(transform)
71+
}
72+
}
73+
1474
#[derive(Default)]
1575
pub struct TransformPlugin;
1676

crates/bevy_transform/src/transform_propagate_system.rs

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ mod test {
8282
};
8383

8484
use super::*;
85-
use crate::hierarchy::{parent_update_system, BuildChildren, BuildWorldChildren};
85+
use crate::{
86+
hierarchy::{parent_update_system, BuildChildren, BuildWorldChildren},
87+
TransformBundle,
88+
};
8689

8790
#[test]
8891
fn did_propagate() {
@@ -96,33 +99,31 @@ mod test {
9699
schedule.add_stage("update", update_stage);
97100

98101
// Root entity
99-
world.spawn().insert_bundle((
100-
Transform::from_xyz(1.0, 0.0, 0.0),
101-
GlobalTransform::identity(),
102-
));
102+
world
103+
.spawn()
104+
.insert_bundle(TransformBundle::from_transform(Transform::from_xyz(
105+
1.0, 0.0, 0.0,
106+
)));
103107

104108
let mut children = Vec::new();
105109
world
106110
.spawn()
107-
.insert_bundle((
108-
Transform::from_xyz(1.0, 0.0, 0.0),
109-
GlobalTransform::identity(),
110-
))
111+
.insert_bundle(TransformBundle::from_transform(Transform::from_xyz(
112+
1.0, 0.0, 0.0,
113+
)))
111114
.with_children(|parent| {
112115
children.push(
113116
parent
114-
.spawn_bundle((
115-
Transform::from_xyz(0.0, 2.0, 0.),
116-
GlobalTransform::identity(),
117-
))
117+
.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz(
118+
0.0, 2.0, 0.,
119+
)))
118120
.id(),
119121
);
120122
children.push(
121123
parent
122-
.spawn_bundle((
123-
Transform::from_xyz(0.0, 0.0, 3.),
124-
GlobalTransform::identity(),
125-
))
124+
.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz(
125+
0.0, 0.0, 3.,
126+
)))
126127
.id(),
127128
);
128129
});
@@ -155,25 +156,22 @@ mod test {
155156
let mut commands = Commands::new(&mut queue, &world);
156157
let mut children = Vec::new();
157158
commands
158-
.spawn_bundle((
159-
Transform::from_xyz(1.0, 0.0, 0.0),
160-
GlobalTransform::identity(),
161-
))
159+
.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz(
160+
1.0, 0.0, 0.0,
161+
)))
162162
.with_children(|parent| {
163163
children.push(
164164
parent
165-
.spawn_bundle((
166-
Transform::from_xyz(0.0, 2.0, 0.0),
167-
GlobalTransform::identity(),
168-
))
165+
.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz(
166+
0.0, 2.0, 0.0,
167+
)))
169168
.id(),
170169
);
171170
children.push(
172171
parent
173-
.spawn_bundle((
174-
Transform::from_xyz(0.0, 0.0, 3.0),
175-
GlobalTransform::identity(),
176-
))
172+
.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz(
173+
0.0, 0.0, 3.0,
174+
)))
177175
.id(),
178176
);
179177
});

examples/3d/pbr.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ fn setup(
5555
});
5656
// light
5757
commands.spawn_bundle(PointLightBundle {
58-
transform: Transform::from_translation(Vec3::new(50.0, 50.0, 50.0)),
58+
transform: Transform::from_xyz(50.0, 50.0, 50.0),
5959
point_light: PointLight {
6060
intensity: 50000.,
6161
range: 100.,
@@ -65,8 +65,7 @@ fn setup(
6565
});
6666
// camera
6767
commands.spawn_bundle(OrthographicCameraBundle {
68-
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 8.0))
69-
.looking_at(Vec3::default(), Vec3::Y),
68+
transform: Transform::from_xyz(0.0, 0.0, 8.0).looking_at(Vec3::default(), Vec3::Y),
7069
orthographic_projection: bevy::render::camera::OrthographicProjection {
7170
scale: 0.01,
7271
..Default::default()

examples/3d/render_to_texture.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ fn setup(
154154
.spawn_bundle(PbrBundle {
155155
mesh: cube_handle,
156156
material: cube_material_handle,
157-
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
157+
transform: Transform::from_xyz(0.0, 0.0, 1.0),
158158
..Default::default()
159159
})
160160
.insert(FirstPassCube)
@@ -164,7 +164,7 @@ fn setup(
164164
// light
165165
// note: currently lights are shared between passes!
166166
commands.spawn_bundle(PointLightBundle {
167-
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)),
167+
transform: Transform::from_xyz(0.0, 0.0, 10.0),
168168
..Default::default()
169169
});
170170

@@ -176,8 +176,7 @@ fn setup(
176176
* calculation of projection matrix */
177177
..Default::default()
178178
},
179-
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 15.0))
180-
.looking_at(Vec3::default(), Vec3::Y),
179+
transform: Transform::from_xyz(0.0, 0.0, 15.0).looking_at(Vec3::default(), Vec3::Y),
181180
..Default::default()
182181
};
183182
active_cameras.add(FIRST_PASS_CAMERA);
@@ -220,8 +219,7 @@ fn setup(
220219
.insert(MainPassCube);
221220

222221
commands.spawn_bundle(PerspectiveCameraBundle {
223-
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 15.0))
224-
.looking_at(Vec3::default(), Vec3::Y),
222+
transform: Transform::from_xyz(0.0, 0.0, 15.0).looking_at(Vec3::default(), Vec3::Y),
225223
..Default::default()
226224
});
227225
}

examples/3d/update_gltf_scene.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ fn setup(
3838
// Spawn the scene as a child of another entity. This first scene will be translated backward
3939
// with its parent
4040
commands
41-
.spawn_bundle((
42-
Transform::from_xyz(0.0, 0.0, -1.0),
43-
GlobalTransform::identity(),
44-
))
41+
.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz(
42+
0.0, 0.0, -1.0,
43+
)))
4544
.with_children(|parent| {
4645
parent.spawn_scene(asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Scene0"));
4746
});

examples/async_tasks/async_compute.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fn spawn_tasks(mut commands: Commands, thread_pool: Res<AsyncComputeTaskPool>) {
6060
}
6161

6262
// Such hard work, all done!
63-
Transform::from_translation(Vec3::new(x as f32, y as f32, z as f32))
63+
Transform::from_xyz(x as f32, y as f32, z as f32)
6464
});
6565

6666
// Spawn new entity and add our new task as a component
@@ -107,13 +107,13 @@ fn setup_env(mut commands: Commands) {
107107

108108
// lights
109109
commands.spawn_bundle(PointLightBundle {
110-
transform: Transform::from_translation(Vec3::new(4.0, 12.0, 15.0)),
110+
transform: Transform::from_xyz(4.0, 12.0, 15.0),
111111
..Default::default()
112112
});
113113

114114
// camera
115115
commands.spawn_bundle(PerspectiveCameraBundle {
116-
transform: Transform::from_translation(Vec3::new(offset, offset, 15.0))
116+
transform: Transform::from_xyz(offset, offset, 15.0)
117117
.looking_at(Vec3::new(offset, offset, 0.0), Vec3::Y),
118118
..Default::default()
119119
});

examples/ecs/iter_combinations.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,7 @@ fn generate_bodies(
104104
commands
105105
.spawn_bundle(BodyBundle {
106106
pbr: PbrBundle {
107-
transform: Transform {
108-
scale: Vec3::splat(0.5),
109-
..Default::default()
110-
},
107+
transform: Transform::from_scale(Vec3::splat(0.5)),
111108
mesh: meshes.add(Mesh::from(shape::Icosphere {
112109
radius: 1.0,
113110
subdivisions: 5,

0 commit comments

Comments
 (0)