Add associated constant IDENTITY to Transform and friends. (#5340)

# Objective
Since `identity` is a const fn that takes no arguments it seems logical to make it an associated constant.
This is also more in line with types from glam (eg. `Quat::IDENTITY`).

## Migration Guide

The method `identity()` on `Transform`, `GlobalTransform` and `TransformBundle` has been deprecated.
Use the associated constant `IDENTITY` instead.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
This commit is contained in:
ira 2022-08-30 22:10:24 +00:00
parent ed773dbe30
commit b42f426fc3
14 changed files with 65 additions and 79 deletions

View File

@ -466,7 +466,7 @@ async fn load_gltf<'a, 'b>(
world world
.spawn() .spawn()
.insert_bundle(SpatialBundle::visible_identity()) .insert_bundle(SpatialBundle::VISIBLE_IDENTITY)
.with_children(|parent| { .with_children(|parent| {
for node in scene.nodes() { for node in scene.nodes() {
let result = load_node( let result = load_node(
@ -1169,7 +1169,7 @@ mod test {
GltfNode { GltfNode {
children: vec![], children: vec![],
mesh: None, mesh: None,
transform: bevy_transform::prelude::Transform::identity(), transform: bevy_transform::prelude::Transform::IDENTITY,
} }
} }
} }

View File

@ -1450,7 +1450,7 @@ pub fn update_point_light_frusta(
Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, POINT_LIGHT_NEAR_Z); Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, POINT_LIGHT_NEAR_Z);
let view_rotations = CUBE_MAP_FACES let view_rotations = CUBE_MAP_FACES
.iter() .iter()
.map(|CubeMapFace { target, up }| Transform::identity().looking_at(*target, *up)) .map(|CubeMapFace { target, up }| Transform::IDENTITY.looking_at(*target, *up))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for (entity, transform, point_light, mut cubemap_frusta) in &mut views { for (entity, transform, point_light, mut cubemap_frusta) in &mut views {

View File

@ -781,7 +781,7 @@ pub fn prepare_lights(
Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, POINT_LIGHT_NEAR_Z); Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, POINT_LIGHT_NEAR_Z);
let cube_face_rotations = CUBE_MAP_FACES let cube_face_rotations = CUBE_MAP_FACES
.iter() .iter()
.map(|CubeMapFace { target, up }| Transform::identity().looking_at(*target, *up)) .map(|CubeMapFace { target, up }| Transform::IDENTITY.looking_at(*target, *up))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
global_light_meta.entity_to_index.clear(); global_light_meta.entity_to_index.clear();

View File

@ -33,22 +33,23 @@ impl SpatialBundle {
pub const fn from_transform(transform: Transform) -> Self { pub const fn from_transform(transform: Transform) -> Self {
SpatialBundle { SpatialBundle {
transform, transform,
// Note: `..Default::default()` cannot be used here, because it isn't const ..Self::VISIBLE_IDENTITY
..Self::visible_identity()
} }
} }
/// Creates a new identity [`SpatialBundle`], with no translation, rotation, and a scale of 1 /// A visible [`SpatialBundle`], with no translation, rotation, and a scale of 1 on all axes.
/// on all axes. pub const VISIBLE_IDENTITY: Self = SpatialBundle {
#[inline] visibility: Visibility::VISIBLE,
pub const fn visible_identity() -> Self { computed: ComputedVisibility::INVISIBLE,
SpatialBundle { transform: Transform::IDENTITY,
transform: Transform::identity(), global_transform: GlobalTransform::IDENTITY,
global_transform: GlobalTransform::identity(), };
visibility: Visibility::visible(),
computed: ComputedVisibility::not_visible(), /// An invisible [`SpatialBundle`], with no translation, rotation, and a scale of 1 on all axes.
} pub const INVISIBLE_IDENTITY: Self = SpatialBundle {
} visibility: Visibility::INVISIBLE,
..Self::VISIBLE_IDENTITY
};
} }
impl From<Transform> for SpatialBundle { impl From<Transform> for SpatialBundle {

View File

@ -37,15 +37,16 @@ pub struct Visibility {
impl Default for Visibility { impl Default for Visibility {
fn default() -> Self { fn default() -> Self {
Self::visible() Visibility::VISIBLE
} }
} }
impl Visibility { impl Visibility {
/// Creates a new [`Visibility`], set as visible /// A [`Visibility`], set as visible.
pub const fn visible() -> Self { pub const VISIBLE: Self = Visibility { is_visible: true };
Self { is_visible: true }
} /// A [`Visibility`], set as invisible.
pub const INVISIBLE: Self = Visibility { is_visible: false };
} }
/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
@ -58,18 +59,16 @@ pub struct ComputedVisibility {
impl Default for ComputedVisibility { impl Default for ComputedVisibility {
fn default() -> Self { fn default() -> Self {
Self::not_visible() Self::INVISIBLE
} }
} }
impl ComputedVisibility { impl ComputedVisibility {
/// Creates a new [`ComputedVisibility`], set as not visible /// A [`ComputedVisibility`], set as invisible.
pub const fn not_visible() -> Self { pub const INVISIBLE: Self = ComputedVisibility {
Self {
is_visible_in_hierarchy: false, is_visible_in_hierarchy: false,
is_visible_in_view: false, is_visible_in_view: false,
} };
}
/// Whether this entity is visible to something this frame. This is true if and only if [`Self::is_visible_in_hierarchy`] and [`Self::is_visible_in_view`] /// Whether this entity is visible to something this frame. This is true if and only if [`Self::is_visible_in_hierarchy`] and [`Self::is_visible_in_view`]
/// are true. This is the canonical method to call to determine if an entity should be drawn. /// are true. This is the canonical method to call to determine if an entity should be drawn.

View File

@ -46,6 +46,9 @@ macro_rules! impl_local_axis {
} }
impl GlobalTransform { impl GlobalTransform {
/// An identity [`GlobalTransform`] that maps all points in space to themselves.
pub const IDENTITY: Self = Self(Affine3A::IDENTITY);
#[doc(hidden)] #[doc(hidden)]
#[inline] #[inline]
pub fn from_xyz(x: f32, y: f32, z: f32) -> Self { pub fn from_xyz(x: f32, y: f32, z: f32) -> Self {
@ -105,12 +108,6 @@ impl GlobalTransform {
self.0.to_scale_rotation_translation() self.0.to_scale_rotation_translation()
} }
/// Creates a new identity [`GlobalTransform`], that maps all points in space to themselves.
#[inline]
pub const fn identity() -> Self {
Self(Affine3A::IDENTITY)
}
impl_local_axis!(right, left, X); impl_local_axis!(right, left, X);
impl_local_axis!(up, down, Y); impl_local_axis!(up, down, Y);
impl_local_axis!(back, forward, Z); impl_local_axis!(back, forward, Z);
@ -154,7 +151,7 @@ impl GlobalTransform {
impl Default for GlobalTransform { impl Default for GlobalTransform {
fn default() -> Self { fn default() -> Self {
Self::identity() Self::IDENTITY
} }
} }

View File

@ -38,6 +38,13 @@ pub struct Transform {
} }
impl Transform { impl Transform {
/// An identity [`Transform`] with no translation, rotation, and a scale of 1 on all axes.
pub const IDENTITY: Self = Transform {
translation: Vec3::ZERO,
rotation: Quat::IDENTITY,
scale: Vec3::ONE,
};
/// Creates a new [`Transform`] at the position `(x, y, z)`. In 2d, the `z` component /// Creates a new [`Transform`] at the position `(x, y, z)`. In 2d, the `z` component
/// is used for z-ordering elements: higher `z`-value will be in front of lower /// is used for z-ordering elements: higher `z`-value will be in front of lower
/// `z`-value. /// `z`-value.
@ -46,17 +53,6 @@ impl Transform {
Self::from_translation(Vec3::new(x, y, z)) Self::from_translation(Vec3::new(x, y, z))
} }
/// Creates a new identity [`Transform`], with no translation, rotation, and a scale of 1 on
/// all axes.
#[inline]
pub const fn identity() -> Self {
Transform {
translation: Vec3::ZERO,
rotation: Quat::IDENTITY,
scale: Vec3::ONE,
}
}
/// Extracts the translation, rotation, and scale from `matrix`. It must be a 3d affine /// Extracts the translation, rotation, and scale from `matrix`. It must be a 3d affine
/// transformation matrix. /// transformation matrix.
#[inline] #[inline]
@ -76,7 +72,7 @@ impl Transform {
pub const fn from_translation(translation: Vec3) -> Self { pub const fn from_translation(translation: Vec3) -> Self {
Transform { Transform {
translation, translation,
..Self::identity() ..Self::IDENTITY
} }
} }
@ -86,7 +82,7 @@ impl Transform {
pub const fn from_rotation(rotation: Quat) -> Self { pub const fn from_rotation(rotation: Quat) -> Self {
Transform { Transform {
rotation, rotation,
..Self::identity() ..Self::IDENTITY
} }
} }
@ -96,7 +92,7 @@ impl Transform {
pub const fn from_scale(scale: Vec3) -> Self { pub const fn from_scale(scale: Vec3) -> Self {
Transform { Transform {
scale, scale,
..Self::identity() ..Self::IDENTITY
} }
} }
@ -335,7 +331,7 @@ impl Transform {
impl Default for Transform { impl Default for Transform {
fn default() -> Self { fn default() -> Self {
Self::identity() Self::IDENTITY
} }
} }

View File

@ -46,6 +46,12 @@ pub struct TransformBundle {
} }
impl TransformBundle { impl TransformBundle {
/// An identity [`TransformBundle`] with no translation, rotation, and a scale of 1 on all axes.
pub const IDENTITY: Self = TransformBundle {
local: Transform::IDENTITY,
global: GlobalTransform::IDENTITY,
};
/// Creates a new [`TransformBundle`] from a [`Transform`]. /// Creates a new [`TransformBundle`] from a [`Transform`].
/// ///
/// This initializes [`GlobalTransform`] as identity, to be updated later by the /// This initializes [`GlobalTransform`] as identity, to be updated later by the
@ -54,18 +60,7 @@ impl TransformBundle {
pub const fn from_transform(transform: Transform) -> Self { pub const fn from_transform(transform: Transform) -> Self {
TransformBundle { TransformBundle {
local: transform, local: transform,
// Note: `..Default::default()` cannot be used here, because it isn't const ..Self::IDENTITY
..Self::identity()
}
}
/// Creates a new identity [`TransformBundle`], with no translation, rotation, and a scale of 1
/// on all axes.
#[inline]
pub const fn identity() -> Self {
TransformBundle {
local: Transform::identity(),
global: GlobalTransform::identity(),
} }
} }
} }

View File

@ -297,14 +297,12 @@ mod test {
.world .world
.spawn() .spawn()
.insert(Transform::from_translation(translation)) .insert(Transform::from_translation(translation))
.insert(GlobalTransform::default()) .insert(GlobalTransform::IDENTITY)
.with_children(|builder| { .with_children(|builder| {
child = builder child = builder
.spawn_bundle((Transform::identity(), GlobalTransform::default())) .spawn_bundle(TransformBundle::IDENTITY)
.with_children(|builder| { .with_children(|builder| {
grandchild = builder grandchild = builder.spawn_bundle(TransformBundle::IDENTITY).id();
.spawn_bundle((Transform::identity(), GlobalTransform::default()))
.id();
}) })
.id(); .id();
}) })
@ -338,11 +336,11 @@ mod test {
let mut grandchild = Entity::from_raw(0); let mut grandchild = Entity::from_raw(0);
let child = world let child = world
.spawn() .spawn()
.insert_bundle((Transform::identity(), GlobalTransform::default())) .insert_bundle(TransformBundle::IDENTITY)
.with_children(|builder| { .with_children(|builder| {
grandchild = builder grandchild = builder
.spawn() .spawn()
.insert_bundle((Transform::identity(), GlobalTransform::default())) .insert_bundle(TransformBundle::IDENTITY)
.id(); .id();
}) })
.id(); .id();
@ -357,7 +355,7 @@ mod test {
app.world app.world
.spawn() .spawn()
.insert_bundle((Transform::default(), GlobalTransform::default())) .insert_bundle(TransformBundle::IDENTITY)
.push_children(&[child]); .push_children(&[child]);
std::mem::swap( std::mem::swap(
&mut *app.world.get_mut::<Parent>(child).unwrap(), &mut *app.world.get_mut::<Parent>(child).unwrap(),

View File

@ -150,7 +150,7 @@ mod tests {
struct Label(&'static str); struct Label(&'static str);
fn node_with_transform(name: &'static str) -> (Label, Node, Transform) { fn node_with_transform(name: &'static str) -> (Label, Node, Transform) {
(Label(name), Node::default(), Transform::identity()) (Label(name), Node::default(), Transform::IDENTITY)
} }
fn node_without_transform(name: &'static str) -> (Label, Node) { fn node_without_transform(name: &'static str) -> (Label, Node) {

View File

@ -125,7 +125,7 @@ fn setup(
.insert_bundle((planet, player)) .insert_bundle((planet, player))
.with_children(|p| { .with_children(|p| {
// This entity is just used for animation, but doesn't display anything // This entity is just used for animation, but doesn't display anything
p.spawn_bundle(SpatialBundle::default()) p.spawn_bundle(SpatialBundle::VISIBLE_IDENTITY)
// Add the Name component // Add the Name component
.insert(orbit_controller) .insert(orbit_controller)
.with_children(|p| { .with_children(|p| {

View File

@ -123,14 +123,14 @@ fn setup(
let joint_0 = commands let joint_0 = commands
.spawn_bundle(( .spawn_bundle((
Transform::from_xyz(i as f32 * 1.5, 0.0, 0.0), Transform::from_xyz(i as f32 * 1.5, 0.0, 0.0),
GlobalTransform::identity(), GlobalTransform::IDENTITY,
)) ))
.id(); .id();
let joint_1 = commands let joint_1 = commands
.spawn_bundle(( .spawn_bundle((
AnimatedJoint, AnimatedJoint,
Transform::identity(), Transform::IDENTITY,
GlobalTransform::identity(), GlobalTransform::IDENTITY,
)) ))
.id(); .id();

View File

@ -18,7 +18,7 @@ struct MyComponent(f64);
fn setup(mut commands: Commands) { fn setup(mut commands: Commands) {
commands.spawn().insert(MyComponent(0.)); commands.spawn().insert(MyComponent(0.));
commands.spawn().insert(Transform::identity()); commands.spawn().insert(Transform::IDENTITY);
} }
fn change_component(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) { fn change_component(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) {

View File

@ -84,7 +84,7 @@ fn save_scene_system(world: &mut World) {
scene_world.spawn().insert_bundle(( scene_world.spawn().insert_bundle((
component_b, component_b,
ComponentA { x: 1.0, y: 2.0 }, ComponentA { x: 1.0, y: 2.0 },
Transform::identity(), Transform::IDENTITY,
)); ));
scene_world scene_world
.spawn() .spawn()