1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
use super::*;
use crate::Conformal3;
/// Transform component.
///
/// Use to move and rotate entities (without physics).
pub struct Transform {
id: Entity,
}
impl std::fmt::Debug for Transform {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Transform")
.field("entity", &self.id.name())
.field("scale", &self.scale().get())
.field("rotation", &self.rotation().get())
.field("position", &self.position().get())
.finish_non_exhaustive()
}
}
impl Transform {
impl_world_accessor!(
/// Returns a `ValueAccessor` for the local position of the entity.
///
/// Used to set/get/animate the position.
/// Moves the entity to this position.
/// If physics (non-kinematic) are enabled, it's recommended to use forces instead of
/// explicitly moving the entity.
Transform,
Position,
Vec3,
position,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the local rotation of the entity.
///
/// Used to set/get/animate the rotation (in quaternion format).
///
/// If physics (non-kinematic) are enabled, it's recommended to use forces/torques instead of
/// explicitly rotating the entity.
Transform,
Rotation,
Quat,
rotation,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the local scale of the entity.
///
/// Used to set/get/animate the scale. Scale animation is not recommended for entities
/// with physics enabled.
///
/// NOTE: scale values must be greater than 0.0
Transform,
ScaleUniform,
f32,
scale,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Sets/gets the parent of the entity in the transform hierarchy.
///
/// Does not work for dynamic physics. If you change an object to use dynamic physics,
/// the parent will be removed. Works for kinematic physics objects though.
Transform,
ParentId,
Entity,
parent,
ValueAccessorReadWrite
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the world position of the entity.
///
/// Used to get the current world position.
Transform,
WorldPosition,
Vec3,
world_position,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the world rotation of the entity.
///
/// Used to get the current rotation (in quaternion format).
Transform,
WorldRotation,
Quat,
world_rotation,
ValueAccessorReadWriteAnimate
);
impl_world_accessor!(
/// Returns a `ValueAccessor` for the world scale of the entity.
///
/// Used to get the scale.
/// Will be the scale of the last frame.
Transform,
WorldScaleUniform,
f32,
world_scale,
ValueAccessorReadWriteAnimate
);
/// Returns the entity-to-parent transform as a [`Conformal3`].
pub fn entity_to_parent(&self) -> Conformal3 {
let scale = self.scale().get();
let rotation = self.rotation().get();
let translation = self.position().get();
Conformal3::from_scale_rotation_translation(scale, rotation, translation)
}
/// Set the entity-to-parent transform.
pub fn set_entity_to_parent(&self, entity_to_parent: &Conformal3) {
let (scale, rotation, translation) = entity_to_parent.to_scale_rotation_translation();
self.scale().set(scale);
self.rotation().set(rotation);
self.position().set(translation);
}
/// Returns the parent-to-entity transform as a [`Conformal3`].
pub fn parent_to_entity(&self) -> Conformal3 {
self.entity_to_parent().inverse()
}
/// Set the parent-to-entity transform from a [`Conformal3`].
pub fn set_parent_to_entity(&self, parent_to_entity: &Conformal3) {
self.set_entity_to_parent(&parent_to_entity.inverse());
}
/// Returns the entity-to-world transform as a decomposed [`Conformal3`] (translation, rotation, uniform scale).
pub fn entity_to_world(&self) -> Conformal3 {
let mut t = vec![];
World::get_entity_world_transforms(&[self.id], &mut t);
Conformal3::from_scale_rotation_translation(
t[0].translation_and_scale[3],
Quat::from_array(t[0].rotation),
Vec3::from_slice(&t[0].translation_and_scale[0..3]),
)
}
/// Sets the entity-to-world transform from a [`Conformal3`] (translation, rotation, uniform scale).
pub fn set_entity_to_world(&self, entity_to_world: &Conformal3) {
let t = EntityTransformConformal3 {
translation_and_scale: entity_to_world.translation_and_scale().to_array(),
rotation: entity_to_world.rotation().into(),
};
World::set_entity_world_transforms(&[self.id], &[t]);
}
/// Returns the world-to-entity transform as an [`Conformal3`].
pub fn world_to_entity(&self) -> Conformal3 {
self.entity_to_world().inverse()
}
/// Set the world-to-entity transform.
pub fn set_world_to_entity(&self, world_to_entity: &Conformal3) {
self.set_entity_to_world(&world_to_entity.inverse());
}
}
impl_world_component!(Transform);