use enum_dispatch::enum_dispatch;
use nalgebra::RealField;
use crate::base::Pose;
#[enum_dispatch]
pub trait Transform<T: RealField> {
fn pose(&self) -> &Pose<T>;
fn pose_mut(&mut self) -> &mut Pose<T>;
#[inline]
fn set_pose(&mut self, pose: Pose<T>) {
*self.pose_mut() = pose;
}
}
macro_rules! impl_transform {
($name:ident < $( $args:ty ),* > where $( $bounds:tt )* ) => {
impl< $( $bounds )* > crate::base::transform::Transform<T> for $name< $( $args ),* > {
#[inline]
fn pose(&self) -> &crate::base::Pose<T> {
&self.pose
}
#[inline]
fn pose_mut(&mut self) -> &mut crate::base::Pose<T> {
&mut self.pose
}
}
};
}
pub(crate) use impl_transform;
#[cfg(feature = "std")]
macro_rules! impl_group_transform {
($name:ident < $( $args:ty ),* > where $( $bounds:tt )* ) => {
impl< $( $bounds )* > $name< $( $args ),*> {
#[inline]
pub fn set_pose(&mut self, new_pose: impl Into<Pose<T>>) {
self.pose = new_pose.into();
for node in self.nodes.iter_mut() {
let global_isometry = self.pose.as_isometry() * node.local_offset.as_isometry();
node.component.set_pose(global_isometry.into());
}
}
delegate::delegate! {
to self.pose {
#[inline]
pub fn position(&self) -> Point3<T>;
#[inline]
pub fn orientation(&self) -> UnitQuaternion<T>;
}
}
#[inline]
pub fn set_position(&mut self, position: impl Into<Translation3<T>>) {
let mut new_pose = *self.pose();
new_pose.set_position(position);
self.set_pose(new_pose);
}
#[inline]
pub fn set_orientation(&mut self, orientation: UnitQuaternion<T>) {
let mut new_pose = *self.pose();
new_pose.set_orientation(orientation);
self.set_pose(new_pose);
}
#[inline]
pub fn translate(&mut self, translation: impl Into<Translation3<T>>) {
let mut new_pose = *self.pose();
new_pose.translate(translation);
self.set_pose(new_pose);
}
#[inline]
pub fn rotate(&mut self, rotation: UnitQuaternion<T>) {
let mut new_pose = *self.pose();
new_pose.rotate(rotation);
self.set_pose(new_pose);
}
#[inline]
pub fn rotate_anchor(&mut self, rotation: UnitQuaternion<T>, anchor: impl Into<Point3<T>>) {
let mut new_pose = *self.pose();
new_pose.rotate_anchor(rotation, anchor);
self.set_pose(new_pose);
}
}
};
}
#[cfg(feature = "std")]
pub(crate) use impl_group_transform;