bevy/crates/bevy_transform/src/components/transform.rs
Michael Dorst 593f64cfcb Fix doc_markdown lints in bevy_transform (#3483)
#3457 adds the `doc_markdown` clippy lint, which checks doc comments to make sure code identifiers are escaped with backticks. This causes a lot of lint errors, so this is one of a number of PR's that will fix those lint errors one crate at a time.

This PR fixes lints in the `bevy_transform` crate.
2021-12-30 09:23:17 +00:00

280 lines
8.2 KiB
Rust

use super::GlobalTransform;
use bevy_ecs::{component::Component, reflect::ReflectComponent};
use bevy_math::{Mat3, Mat4, Quat, Vec3};
use bevy_reflect::Reflect;
use std::ops::Mul;
/// Describe the position of an entity. If the entity has a parent, the position is relative
/// to its parent position.
///
/// * To place or move an entity, you should set its [`Transform`].
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
///
/// ## [`Transform`] and [`GlobalTransform`]
///
/// [`Transform`] is the position of an entity relative to its parent position, or the reference
/// frame if it doesn't have a [`Parent`](super::Parent).
///
/// [`GlobalTransform`] is the position of an entity relative to the reference frame.
///
/// [`GlobalTransform`] is updated from [`Transform`] in the system
/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system).
///
/// In pseudo code:
/// ```ignore
/// for entity in entities_without_parent:
/// set entity.global_transform to entity.transform
/// recursively:
/// set parent to current entity
/// for child in parent.children:
/// set child.global_transform to parent.global_transform * child.transform
/// ```
///
/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
/// before the [`GlobalTransform`] is updated.
#[derive(Component, Debug, PartialEq, Clone, Copy, Reflect)]
#[reflect(Component, PartialEq)]
pub struct Transform {
/// Position of the entity. In 2d, the last value of the `Vec3` is used for z-ordering.
pub translation: Vec3,
/// Rotation of the entity.
pub rotation: Quat,
/// Scale of the entity.
pub scale: Vec3,
}
impl Transform {
/// 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
/// `z`-value.
#[inline]
pub fn from_xyz(x: f32, y: f32, z: f32) -> Self {
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
/// transformation matrix.
#[inline]
pub fn from_matrix(matrix: Mat4) -> Self {
let (scale, rotation, translation) = matrix.to_scale_rotation_translation();
Transform {
translation,
rotation,
scale,
}
}
/// Creates a new [`Transform`], with `translation`. Rotation will be 0 and scale 1 on
/// all axes.
#[inline]
pub fn from_translation(translation: Vec3) -> Self {
Transform {
translation,
..Default::default()
}
}
/// Creates a new [`Transform`], with `rotation`. Translation will be 0 and scale 1 on
/// all axes.
#[inline]
pub fn from_rotation(rotation: Quat) -> Self {
Transform {
rotation,
..Default::default()
}
}
/// Creates a new [`Transform`], with `scale`. Translation will be 0 and rotation 0 on
/// all axes.
#[inline]
pub fn from_scale(scale: Vec3) -> Self {
Transform {
scale,
..Default::default()
}
}
/// Updates and returns this [`Transform`] by rotating it so that its unit vector in the
/// local z direction is toward `target` and its unit vector in the local y direction
/// is toward `up`.
#[inline]
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
self.look_at(target, up);
self
}
/// Returns this [`Transform`] with a new translation.
#[inline]
pub fn with_translation(mut self, translation: Vec3) -> Self {
self.translation = translation;
self
}
/// Returns this [`Transform`] with a new rotation.
#[inline]
pub fn with_rotation(mut self, rotation: Quat) -> Self {
self.rotation = rotation;
self
}
/// Returns this [`Transform`] with a new scale.
#[inline]
pub fn with_scale(mut self, scale: Vec3) -> Self {
self.scale = scale;
self
}
/// Returns the 3d affine transformation matrix from this transforms translation,
/// rotation, and scale.
#[inline]
pub fn compute_matrix(&self) -> Mat4 {
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
}
/// Get the unit vector in the local x direction.
#[inline]
pub fn local_x(&self) -> Vec3 {
self.rotation * Vec3::X
}
/// Equivalent to [`-local_x()`][Transform::local_x()]
#[inline]
pub fn left(&self) -> Vec3 {
-self.local_x()
}
/// Equivalent to [`local_x()`][Transform::local_x()]
#[inline]
pub fn right(&self) -> Vec3 {
self.local_x()
}
/// Get the unit vector in the local y direction.
#[inline]
pub fn local_y(&self) -> Vec3 {
self.rotation * Vec3::Y
}
/// Equivalent to [`local_y()`][Transform::local_y]
#[inline]
pub fn up(&self) -> Vec3 {
self.local_y()
}
/// Equivalent to [`-local_y()`][Transform::local_y]
#[inline]
pub fn down(&self) -> Vec3 {
-self.local_y()
}
/// Get the unit vector in the local z direction.
#[inline]
pub fn local_z(&self) -> Vec3 {
self.rotation * Vec3::Z
}
/// Equivalent to [`-local_z()`][Transform::local_z]
#[inline]
pub fn forward(&self) -> Vec3 {
-self.local_z()
}
/// Equivalent to [`local_z()`][Transform::local_z]
#[inline]
pub fn back(&self) -> Vec3 {
self.local_z()
}
/// Rotates the transform by the given rotation.
#[inline]
pub fn rotate(&mut self, rotation: Quat) {
self.rotation = rotation * self.rotation;
}
/// Multiplies `self` with `transform` component by component, returning the
/// resulting [`Transform`]
#[inline]
pub fn mul_transform(&self, transform: Transform) -> Self {
let translation = self.mul_vec3(transform.translation);
let rotation = self.rotation * transform.rotation;
let scale = self.scale * transform.scale;
Transform {
translation,
rotation,
scale,
}
}
/// Returns a [`Vec3`] of this [`Transform`] applied to `value`.
#[inline]
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 {
value = self.rotation * value;
value = self.scale * value;
value += self.translation;
value
}
/// Changes the `scale` of this [`Transform`], multiplying the current `scale` by
/// `scale_factor`.
#[inline]
pub fn apply_non_uniform_scale(&mut self, scale_factor: Vec3) {
self.scale *= scale_factor;
}
/// Rotates this [`Transform`] so that its unit vector in the local z direction is toward
/// `target` and its unit vector in the local y direction is toward `up`.
#[inline]
pub fn look_at(&mut self, target: Vec3, up: Vec3) {
let forward = Vec3::normalize(self.translation - target);
let right = up.cross(forward).normalize();
let up = forward.cross(right);
self.rotation = Quat::from_mat3(&Mat3::from_cols(right, up, forward));
}
}
impl Default for Transform {
fn default() -> Self {
Self::identity()
}
}
impl From<GlobalTransform> for Transform {
fn from(transform: GlobalTransform) -> Self {
Self {
translation: transform.translation,
rotation: transform.rotation,
scale: transform.scale,
}
}
}
impl Mul<Transform> for Transform {
type Output = Transform;
fn mul(self, transform: Transform) -> Self::Output {
self.mul_transform(transform)
}
}
impl Mul<Vec3> for Transform {
type Output = Vec3;
fn mul(self, value: Vec3) -> Self::Output {
self.mul_vec3(value)
}
}