ranim_core/traits/transform/
shift.rs

1use glam::DVec3;
2
3use crate::anchor::{Aabb, AabbPoint, Locate};
4
5/// Shifting operations.
6///
7/// This trait is automatically implemented for [`DVec3`] and `[T]` where `T: ShiftTransform`.
8pub trait ShiftTransform {
9    /// Shift the item by a given vector.
10    fn shift(&mut self, offset: DVec3) -> &mut Self;
11}
12
13impl ShiftTransform for DVec3 {
14    fn shift(&mut self, shift: DVec3) -> &mut Self {
15        *self += shift;
16        self
17    }
18}
19
20impl<T: ShiftTransformExt> ShiftTransform for [T] {
21    fn shift(&mut self, shift: DVec3) -> &mut Self {
22        self.iter_mut().for_each(|x| {
23            x.shift(shift);
24        });
25        self
26    }
27}
28
29impl<T: ShiftTransformExt> ShiftTransform for Vec<T> {
30    fn shift(&mut self, shift: DVec3) -> &mut Self {
31        self.as_mut_slice().shift(shift);
32        self
33    }
34}
35
36/// Useful extensions for shifting operations.
37///
38/// This trait is implemented automatically for types that implement [`ShiftTransform`], you should not implement it yourself.
39pub trait ShiftTransformExt: ShiftTransform {
40    /// Do something with the origin of the item.
41    ///
42    /// See [`crate::anchor`]'s [`Locate`] for more details.
43    fn with_origin(&mut self, p: impl Locate<Self>, f: impl FnOnce(&mut Self)) -> &mut Self {
44        let p = p.locate(self);
45        self.shift(-p);
46        f(self);
47        self.shift(p)
48    }
49    /// Put anchor at a given point.
50    ///
51    /// See [`crate::anchor`]'s [`Locate`] for more details.
52    fn move_anchor_to<A>(&mut self, anchor: A, point: DVec3) -> &mut Self
53    where
54        A: Locate<Self>,
55    {
56        self.shift(point - anchor.locate(self));
57        self
58    }
59    /// Put pivot at a given point.
60    fn move_to(&mut self, point: DVec3) -> &mut Self
61    where
62        AabbPoint: Locate<Self>,
63    {
64        self.move_anchor_to(AabbPoint::CENTER, point)
65    }
66    /// Put negative anchor of self on anchor of target
67    fn move_next_to<T: Aabb + ?Sized>(&mut self, target: &T, anchor: AabbPoint) -> &mut Self
68    where
69        AabbPoint: Locate<Self>,
70    {
71        self.move_next_to_padded(target, anchor, 0.0)
72    }
73    /// Put negative anchor of self on anchor of target, with a distance of `padding`
74    fn move_next_to_padded<T: Aabb + ?Sized>(
75        &mut self,
76        target: &T,
77        anchor: AabbPoint,
78        padding: f64,
79    ) -> &mut Self
80    where
81        AabbPoint: Locate<Self>,
82    {
83        let neg_anchor = AabbPoint(-anchor.0);
84        self.move_anchor_to(
85            neg_anchor,
86            Locate::<T>::locate(&anchor, target) + anchor.0.normalize() * padding,
87        )
88    }
89}
90
91impl<T: ShiftTransform + ?Sized> ShiftTransformExt for T {}