#![allow(clippy::unnecessary_cast)]
use crate::{physics_transform::PhysicsTransformConfig, prelude::*};
use bevy::{
ecs::{lifecycle::HookContext, world::DeferredWorld},
math::DQuat,
prelude::*,
};
use derive_more::From;
#[cfg(feature = "2d")]
use crate::math::Matrix;
#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
#[cfg_attr(feature = "2d", doc = " Position::from_xy(0.0, 20.0),")]
#[cfg_attr(feature = "3d", doc = " Position::from_xyz(0.0, 2.0, 0.0),")]
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct Position(pub Vector);
impl Position {
pub const PLACEHOLDER: Self = Self(Vector::MAX);
pub fn new(position: Vector) -> Self {
Self(position)
}
#[cfg(feature = "2d")]
pub fn from_xy(x: Scalar, y: Scalar) -> Self {
Self(Vector::new(x, y))
}
#[cfg(feature = "3d")]
pub fn from_xyz(x: Scalar, y: Scalar, z: Scalar) -> Self {
Self(Vector::new(x, y, z))
}
}
impl From<GlobalTransform> for Position {
#[cfg(feature = "2d")]
fn from(value: GlobalTransform) -> Self {
Self::from_xy(
value.translation().adjust_precision().x,
value.translation().adjust_precision().y,
)
}
#[cfg(feature = "3d")]
fn from(value: GlobalTransform) -> Self {
Self::from_xyz(
value.translation().adjust_precision().x,
value.translation().adjust_precision().y,
value.translation().adjust_precision().z,
)
}
}
impl From<&GlobalTransform> for Position {
#[cfg(feature = "2d")]
fn from(value: &GlobalTransform) -> Self {
Self::from_xy(
value.translation().adjust_precision().x,
value.translation().adjust_precision().y,
)
}
#[cfg(feature = "3d")]
fn from(value: &GlobalTransform) -> Self {
Self::from_xyz(
value.translation().adjust_precision().x,
value.translation().adjust_precision().y,
value.translation().adjust_precision().z,
)
}
}
impl Ease for Position {
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
FunctionCurve::new(Interval::UNIT, move |t| {
Position(Vector::lerp(start.0, end.0, t as Scalar))
})
}
}
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct PreSolveDeltaPosition(pub Vector);
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct PreSolveDeltaRotation(pub Rotation);
#[cfg(feature = "2d")]
#[allow(dead_code)]
pub(crate) type RotationValue = Scalar;
#[cfg(feature = "3d")]
#[allow(dead_code)]
pub(crate) type RotationValue = Quaternion;
#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, PartialEq)]
#[cfg(feature = "2d")]
pub struct Rotation {
pub cos: Scalar,
pub sin: Scalar,
}
#[cfg(feature = "2d")]
impl Default for Rotation {
fn default() -> Self {
Self::IDENTITY
}
}
#[cfg(feature = "2d")]
impl Rotation {
pub const PLACEHOLDER: Self = Self {
cos: Scalar::MAX,
sin: Scalar::MAX,
};
pub const IDENTITY: Self = Self { cos: 1.0, sin: 0.0 };
pub const PI: Self = Self {
cos: -1.0,
sin: 0.0,
};
pub const FRAC_PI_2: Self = Self { cos: 0.0, sin: 1.0 };
pub const FRAC_PI_3: Self = Self {
cos: 0.5,
sin: 0.866_025_4,
};
pub const FRAC_PI_4: Self = Self {
cos: FRAC_1_SQRT_2,
sin: FRAC_1_SQRT_2,
};
pub const FRAC_PI_6: Self = Self {
cos: 0.866_025_4,
sin: 0.5,
};
pub const FRAC_PI_8: Self = Self {
cos: 0.923_879_5,
sin: 0.382_683_43,
};
#[inline]
pub fn radians(radians: Scalar) -> Self {
#[cfg(feature = "enhanced-determinism")]
let (sin, cos) = (
libm::sin(radians as f64) as Scalar,
libm::cos(radians as f64) as Scalar,
);
#[cfg(not(feature = "enhanced-determinism"))]
let (sin, cos) = radians.sin_cos();
Self::from_sin_cos(sin, cos)
}
#[inline]
pub fn degrees(degrees: Scalar) -> Self {
Self::radians(degrees.to_radians())
}
#[deprecated(note = "renamed to just `radians` to match Bevy")]
pub fn from_radians(radians: Scalar) -> Self {
Self::radians(radians)
}
#[deprecated(note = "renamed to just `degrees` to match Bevy")]
pub fn from_degrees(degrees: Scalar) -> Self {
Self::degrees(degrees)
}
#[inline]
pub fn from_sin_cos(sin: Scalar, cos: Scalar) -> Self {
let rotation = Self { sin, cos };
debug_assert!(
rotation.is_normalized(),
"the given sine and cosine produce an invalid rotation"
);
rotation
}
#[inline]
pub fn as_radians(self) -> Scalar {
#[cfg(feature = "enhanced-determinism")]
{
libm::atan2(self.sin as f64, self.cos as f64) as Scalar
}
#[cfg(not(feature = "enhanced-determinism"))]
{
Scalar::atan2(self.sin, self.cos)
}
}
#[inline]
pub fn as_degrees(self) -> Scalar {
self.as_radians().to_degrees()
}
#[inline]
pub const fn sin_cos(self) -> (Scalar, Scalar) {
(self.sin, self.cos)
}
#[deprecated(note = "use the `Mul` impl instead, like `rot * vec`")]
pub fn rotate(&self, vec: Vector) -> Vector {
self * vec
}
#[inline]
#[doc(alias = "norm")]
pub fn length(self) -> Scalar {
Vector::new(self.sin, self.cos).length()
}
#[inline]
#[doc(alias = "norm2")]
pub fn length_squared(self) -> Scalar {
Vector::new(self.sin, self.cos).length_squared()
}
#[inline]
pub fn length_recip(self) -> Scalar {
Vector::new(self.sin, self.cos).length_recip()
}
#[inline]
#[must_use]
pub fn try_normalize(self) -> Option<Self> {
let recip = self.length_recip();
if recip.is_finite() && recip > 0.0 {
Some(Self::from_sin_cos(self.sin * recip, self.cos * recip))
} else {
None
}
}
#[inline]
#[must_use]
pub fn normalize(self) -> Self {
let length_recip = self.length_recip();
Self::from_sin_cos(self.sin * length_recip, self.cos * length_recip)
}
#[inline]
#[must_use]
pub fn fast_renormalize(self) -> Self {
let length_squared = self.length_squared();
let approx_inv_length = 0.5 * (3.0 - length_squared);
Self::from_sin_cos(self.sin * approx_inv_length, self.cos * approx_inv_length)
}
#[inline]
pub fn is_finite(self) -> bool {
self.sin.is_finite() && self.cos.is_finite()
}
#[inline]
pub fn is_nan(self) -> bool {
self.sin.is_nan() || self.cos.is_nan()
}
#[inline]
pub fn is_normalized(self) -> bool {
(self.length_squared() - 1.0).abs() <= 2e-4
}
#[inline]
pub fn is_near_identity(self) -> bool {
let threshold_angle_sin = 0.000_049_692_047; self.cos > 0.0 && self.sin.abs() < threshold_angle_sin
}
#[inline]
pub fn angle_between(self, other: Self) -> Scalar {
(other * self.inverse()).as_radians()
}
#[inline]
#[must_use]
#[doc(alias = "conjugate")]
pub fn inverse(self) -> Self {
Self {
cos: self.cos,
sin: -self.sin,
}
}
#[inline]
#[must_use]
pub fn add_angle_fast(&self, radians: Scalar) -> Self {
let (sin, cos) = (self.sin + radians * self.cos, self.cos - radians * self.sin);
let magnitude_squared = sin * sin + cos * cos;
let magnitude_recip = if magnitude_squared > 0.0 {
magnitude_squared.sqrt().recip()
} else {
0.0
};
Rotation::from_sin_cos(sin * magnitude_recip, cos * magnitude_recip)
}
#[inline]
pub fn nlerp(self, end: Self, s: Scalar) -> Self {
Self {
sin: self.sin.lerp(end.sin, s),
cos: self.cos.lerp(end.cos, s),
}
.try_normalize()
.unwrap_or(self)
}
#[inline]
pub fn slerp(self, end: Self, s: Scalar) -> Self {
self * Self::radians(self.angle_between(end) * s)
}
}
#[cfg(feature = "2d")]
impl From<Scalar> for Rotation {
fn from(rotation: Scalar) -> Self {
Self::radians(rotation)
}
}
#[cfg(feature = "2d")]
impl From<Rotation> for Matrix {
fn from(rot: Rotation) -> Self {
Matrix::from_cols_array(&[rot.cos, rot.sin, -rot.sin, rot.cos])
}
}
#[cfg(feature = "2d")]
impl From<Matrix> for Rotation {
fn from(mat: Matrix) -> Self {
let cos = mat.x_axis.x;
let sin = mat.x_axis.y;
Self::from_sin_cos(sin, cos)
}
}
#[cfg(feature = "2d")]
impl From<Rot2> for Rotation {
fn from(rot: Rot2) -> Self {
Self::from_sin_cos(rot.sin as Scalar, rot.cos as Scalar)
}
}
#[cfg(feature = "2d")]
impl From<Rotation> for Rot2 {
fn from(rot: Rotation) -> Self {
Self::from_sin_cos(rot.sin as f32, rot.cos as f32)
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul for Rotation {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Self {
cos: self.cos * rhs.cos - self.sin * rhs.sin,
sin: self.sin * rhs.cos + self.cos * rhs.sin,
}
}
}
#[cfg(feature = "2d")]
impl core::ops::MulAssign for Rotation {
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<Vector> for Rotation {
type Output = Vector;
fn mul(self, rhs: Vector) -> Self::Output {
Vector::new(
rhs.x * self.cos - rhs.y * self.sin,
rhs.x * self.sin + rhs.y * self.cos,
)
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<Vector3> for Rotation {
type Output = Vector3;
fn mul(self, rhs: Vector3) -> Self::Output {
Vector3::new(
rhs.x * self.cos - rhs.y * self.sin,
rhs.x * self.sin + rhs.y * self.cos,
rhs.z,
)
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<&Vector3> for Rotation {
type Output = Vector3;
fn mul(self, rhs: &Vector3) -> Self::Output {
self * *rhs
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<&mut Vector3> for Rotation {
type Output = Vector3;
fn mul(self, rhs: &mut Vector3) -> Self::Output {
self * *rhs
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<Vector3> for &Rotation {
type Output = Vector3;
fn mul(self, rhs: Vector3) -> Self::Output {
*self * rhs
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<&Vector3> for &Rotation {
type Output = Vector3;
fn mul(self, rhs: &Vector3) -> Self::Output {
*self * *rhs
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<&mut Vector3> for &Rotation {
type Output = Vector3;
fn mul(self, rhs: &mut Vector3) -> Self::Output {
*self * *rhs
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<Vector3> for &mut Rotation {
type Output = Vector3;
fn mul(self, rhs: Vector3) -> Self::Output {
*self * rhs
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<&Vector3> for &mut Rotation {
type Output = Vector3;
fn mul(self, rhs: &Vector3) -> Self::Output {
*self * *rhs
}
}
#[cfg(feature = "2d")]
impl core::ops::Mul<&mut Vector3> for &mut Rotation {
type Output = Vector3;
fn mul(self, rhs: &mut Vector3) -> Self::Output {
*self * *rhs
}
}
impl Ease for Rotation {
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
FunctionCurve::new(Interval::UNIT, move |t| {
Rotation::slerp(start, end, t as Scalar)
})
}
}
#[cfg(feature = "3d")]
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct Rotation(pub Quaternion);
#[cfg(feature = "3d")]
impl Rotation {
pub const PLACEHOLDER: Self = Self(Quaternion::from_xyzw(
Scalar::MAX,
Scalar::MAX,
Scalar::MAX,
Scalar::MAX,
));
pub const IDENTITY: Self = Self(Quaternion::IDENTITY);
#[inline]
pub fn angle_between(self, other: Self) -> Scalar {
self.0.angle_between(other.0)
}
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
Self(self.0.inverse())
}
#[inline]
pub fn nlerp(self, end: Self, t: Scalar) -> Self {
Self(self.0.lerp(end.0, t))
}
#[inline]
pub fn slerp(self, end: Self, t: Scalar) -> Self {
Self(self.0.slerp(end.0, t))
}
#[inline]
#[must_use]
pub fn fast_renormalize(self) -> Self {
let length_squared = self.length_squared();
let approx_inv_length = 0.5 * (3.0 - length_squared);
Self(self.0 * approx_inv_length)
}
}
#[cfg(feature = "3d")]
impl core::ops::Mul<Vector> for Rotation {
type Output = Vector;
fn mul(self, vector: Vector) -> Self::Output {
self.0 * vector
}
}
#[cfg(feature = "3d")]
impl core::ops::Mul for Rotation {
type Output = Rotation;
fn mul(self, rhs: Self) -> Self::Output {
Self(self.0 * rhs.0)
}
}
#[cfg(feature = "3d")]
impl core::ops::MulAssign for Rotation {
fn mul_assign(&mut self, rhs: Self) {
self.0 *= rhs.0;
}
}
#[cfg(feature = "3d")]
impl core::ops::Mul<Quaternion> for Rotation {
type Output = Quaternion;
fn mul(self, quaternion: Quaternion) -> Self::Output {
self.0 * quaternion
}
}
#[cfg(feature = "3d")]
impl core::ops::Mul<Quaternion> for &Rotation {
type Output = Quaternion;
fn mul(self, quaternion: Quaternion) -> Self::Output {
self.0 * quaternion
}
}
#[cfg(feature = "3d")]
impl core::ops::Mul<Quaternion> for &mut Rotation {
type Output = Quaternion;
fn mul(self, quaternion: Quaternion) -> Self::Output {
self.0 * quaternion
}
}
#[cfg(feature = "3d")]
impl core::ops::Mul<Rotation> for Quaternion {
type Output = Rotation;
fn mul(self, rotation: Rotation) -> Self::Output {
Rotation(self * rotation.0)
}
}
#[cfg(feature = "3d")]
impl core::ops::Mul<Rotation> for &Quaternion {
type Output = Rotation;
fn mul(self, rotation: Rotation) -> Self::Output {
Rotation(*self * rotation.0)
}
}
#[cfg(feature = "3d")]
impl core::ops::Mul<Rotation> for &mut Quaternion {
type Output = Rotation;
fn mul(self, rotation: Rotation) -> Self::Output {
Rotation(*self * rotation.0)
}
}
impl core::ops::Mul<Dir> for Rotation {
type Output = Dir;
fn mul(self, direction: Dir) -> Self::Output {
Dir::new_unchecked((self * direction.adjust_precision()).f32())
}
}
impl core::ops::Mul<Vector> for &Rotation {
type Output = Vector;
fn mul(self, vector: Vector) -> Self::Output {
*self * vector
}
}
impl core::ops::Mul<Dir> for &Rotation {
type Output = Dir;
fn mul(self, direction: Dir) -> Self::Output {
Dir::new_unchecked((*self * direction.adjust_precision()).f32())
}
}
impl core::ops::Mul<Vector> for &mut Rotation {
type Output = Vector;
fn mul(self, vector: Vector) -> Self::Output {
*self * vector
}
}
impl core::ops::Mul<Dir> for &mut Rotation {
type Output = Dir;
fn mul(self, direction: Dir) -> Self::Output {
Dir::new_unchecked((*self * direction.adjust_precision()).f32())
}
}
impl core::ops::Mul<&Vector> for Rotation {
type Output = Vector;
fn mul(self, vector: &Vector) -> Self::Output {
self * *vector
}
}
impl core::ops::Mul<&Dir> for Rotation {
type Output = Dir;
fn mul(self, direction: &Dir) -> Self::Output {
Dir::new_unchecked((self * direction.adjust_precision()).f32())
}
}
impl core::ops::Mul<&mut Vector> for Rotation {
type Output = Vector;
fn mul(self, vector: &mut Vector) -> Self::Output {
self * *vector
}
}
impl core::ops::Mul<&mut Dir> for Rotation {
type Output = Dir;
fn mul(self, direction: &mut Dir) -> Self::Output {
Dir::new_unchecked((self * direction.adjust_precision()).f32())
}
}
impl core::ops::Mul<&Vector> for &Rotation {
type Output = Vector;
fn mul(self, vector: &Vector) -> Self::Output {
*self * *vector
}
}
impl core::ops::Mul<&Dir> for &Rotation {
type Output = Dir;
fn mul(self, direction: &Dir) -> Self::Output {
Dir::new_unchecked((*self * direction.adjust_precision()).f32())
}
}
impl core::ops::Mul<&Vector> for &mut Rotation {
type Output = Vector;
fn mul(self, vector: &Vector) -> Self::Output {
*self * *vector
}
}
impl core::ops::Mul<&Dir> for &mut Rotation {
type Output = Dir;
fn mul(self, direction: &Dir) -> Self::Output {
Dir::new_unchecked((*self * direction.adjust_precision()).f32())
}
}
impl core::ops::Mul<&mut Vector> for &Rotation {
type Output = Vector;
fn mul(self, vector: &mut Vector) -> Self::Output {
*self * *vector
}
}
impl core::ops::Mul<&mut Dir> for &Rotation {
type Output = Dir;
fn mul(self, direction: &mut Dir) -> Self::Output {
Dir::new_unchecked((*self * direction.adjust_precision()).f32())
}
}
impl core::ops::Mul<&mut Vector> for &mut Rotation {
type Output = Vector;
fn mul(self, vector: &mut Vector) -> Self::Output {
*self * *vector
}
}
impl core::ops::Mul<&mut Dir> for &mut Rotation {
type Output = Dir;
fn mul(self, direction: &mut Dir) -> Self::Output {
Dir::new_unchecked((*self * direction.adjust_precision()).f32())
}
}
#[cfg(feature = "2d")]
impl From<Rotation> for Scalar {
fn from(rot: Rotation) -> Self {
rot.as_radians()
}
}
#[cfg(feature = "2d")]
impl From<Rotation> for Quaternion {
fn from(rot: Rotation) -> Self {
let z = rot.sin.signum() * ((1.0 - rot.cos) / 2.0).abs().sqrt();
let w = ((1.0 + rot.cos) / 2.0).abs().sqrt();
Quaternion::from_xyzw(0.0, 0.0, z, w)
}
}
#[cfg(feature = "3d")]
impl From<Rotation> for Quaternion {
fn from(rot: Rotation) -> Self {
rot.0
}
}
impl From<Transform> for Rotation {
fn from(value: Transform) -> Self {
Self::from(value.rotation)
}
}
impl From<GlobalTransform> for Rotation {
fn from(value: GlobalTransform) -> Self {
Self::from(value.compute_transform().rotation)
}
}
impl From<&GlobalTransform> for Rotation {
fn from(value: &GlobalTransform) -> Self {
Self::from(value.compute_transform().rotation)
}
}
#[cfg(feature = "2d")]
impl From<Quat> for Rotation {
fn from(quat: Quat) -> Self {
let angle = quat.to_euler(EulerRot::XYZ).2;
Self::radians(angle as Scalar)
}
}
#[cfg(feature = "2d")]
impl From<DQuat> for Rotation {
fn from(quat: DQuat) -> Self {
let angle = quat.to_euler(EulerRot::XYZ).2;
Self::radians(angle as Scalar)
}
}
#[cfg(feature = "3d")]
impl From<Quat> for Rotation {
fn from(quat: Quat) -> Self {
Self(Quaternion::from_xyzw(
quat.x as Scalar,
quat.y as Scalar,
quat.z as Scalar,
quat.w as Scalar,
))
}
}
#[cfg(feature = "3d")]
impl From<DQuat> for Rotation {
fn from(quat: DQuat) -> Self {
Self(Quaternion::from_xyzw(
quat.x as Scalar,
quat.y as Scalar,
quat.z as Scalar,
quat.w as Scalar,
))
}
}
pub(crate) fn init_physics_transform(world: &mut DeferredWorld, ctx: &HookContext) {
let entity_ref = world.entity(ctx.entity);
let (mut position, is_pos_placeholder) = entity_ref
.get::<Position>()
.map_or((default(), true), |p| (*p, *p == Position::PLACEHOLDER));
let (mut rotation, is_rot_placeholder) = entity_ref
.get::<Rotation>()
.map_or((default(), true), |r| (*r, *r == Rotation::PLACEHOLDER));
if is_pos_placeholder {
position.0 = Vector::ZERO;
}
if is_rot_placeholder {
rotation = Rotation::IDENTITY;
}
let is_not_placeholder = !is_pos_placeholder || !is_rot_placeholder;
let config = world
.get_resource::<PhysicsTransformConfig>()
.cloned()
.unwrap_or_default();
let mut parent_global_transform = GlobalTransform::default();
let mut curr_parent = world.get::<ChildOf>(ctx.entity);
while let Some(parent) = curr_parent {
if let Some(parent_transform) = world.get::<Transform>(parent.0) {
parent_global_transform = *parent_transform * parent_global_transform;
}
curr_parent = world.get::<ChildOf>(parent.0);
}
let transform = world.get::<Transform>(ctx.entity).copied();
let global_transform = transform.map(|transform| {
let global_transform = parent_global_transform * GlobalTransform::from(transform);
*world.get_mut::<GlobalTransform>(ctx.entity).unwrap() = global_transform;
global_transform
});
if is_not_placeholder && config.position_to_transform {
if parent_global_transform != GlobalTransform::default() {
#[cfg(feature = "2d")]
let Some(transform) = transform else {
return;
};
#[cfg(feature = "2d")]
let new_transform =
{
let (parent_translation, parent_scale) = (
parent_global_transform.translation(),
parent_global_transform.scale(),
);
GlobalTransform::from(
Transform::from_translation(position.f32().extend(
parent_translation.z + transform.translation.z * parent_scale.z,
))
.with_rotation(Quaternion::from(rotation).f32()),
)
.reparented_to(&parent_global_transform)
};
#[cfg(feature = "3d")]
let new_transform = GlobalTransform::from(
Transform::from_translation(position.f32()).with_rotation(rotation.f32()),
)
.reparented_to(&parent_global_transform);
if let Some(mut transform) = world.get_mut::<Transform>(ctx.entity) {
transform.translation = new_transform.translation;
transform.rotation = new_transform.rotation;
}
} else if let Some(mut transform) = world.get_mut::<Transform>(ctx.entity) {
#[cfg(feature = "2d")]
{
if !is_pos_placeholder {
transform.translation = position.f32().extend(transform.translation.z);
}
if !is_rot_placeholder {
transform.rotation = Quaternion::from(rotation).f32();
}
}
#[cfg(feature = "3d")]
{
if !is_pos_placeholder {
transform.translation = position.f32();
}
if !is_rot_placeholder {
transform.rotation = rotation.f32();
}
}
}
}
if !config.transform_to_position {
if is_pos_placeholder && let Some(mut position) = world.get_mut::<Position>(ctx.entity) {
position.0 = Vector::ZERO;
}
if is_rot_placeholder && let Some(mut rotation) = world.get_mut::<Rotation>(ctx.entity) {
*rotation = Rotation::IDENTITY;
}
} else if is_pos_placeholder || is_rot_placeholder {
if let Some(global_transform) = global_transform {
let (_, global_rotation, global_translation) =
global_transform.to_scale_rotation_translation();
#[cfg(feature = "2d")]
{
position.0 = global_translation.truncate().adjust_precision();
rotation = Rotation::from(global_rotation.adjust_precision());
}
#[cfg(feature = "3d")]
{
position.0 = global_translation.adjust_precision();
rotation.0 = global_rotation.adjust_precision();
}
} else {
if is_pos_placeholder {
position.0 = Vector::ZERO;
}
if is_rot_placeholder {
rotation = Rotation::IDENTITY;
}
}
let mut entity_mut = world.entity_mut(ctx.entity);
if let Some(mut pos) = entity_mut
.get_mut::<Position>()
.filter(|pos| **pos == Position::PLACEHOLDER)
{
*pos = position;
}
if let Some(mut rot) = entity_mut
.get_mut::<Rotation>()
.filter(|rot| **rot == Rotation::PLACEHOLDER)
{
*rot = rotation;
}
}
}