pax_runtime_api/
transform.rs1use super::*;
4
5#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Copy)]
7pub enum Rotation {
8 Radians(Numeric),
10 Degrees(Numeric),
12 Percent(Numeric),
14}
15
16impl Display for Rotation {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 Rotation::Radians(rad) => write!(f, "{}rad", rad),
20 Rotation::Degrees(deg) => write!(f, "{}deg", deg),
21 Rotation::Percent(per) => write!(f, "{}%", per),
22 }
23 }
24}
25
26impl Default for Rotation {
27 fn default() -> Self {
28 Self::Degrees(Numeric::F64(0.0))
29 }
30}
31
32impl Interpolatable for Rotation {
33 fn interpolate(&self, other: &Self, t: f64) -> Self {
34 Self::Degrees(Numeric::F64(
35 self.get_as_degrees() + (other.get_as_degrees() - self.get_as_degrees()) * t,
36 ))
37 }
38}
39
40impl Rotation {
41 #[allow(non_snake_case)]
42 pub fn ZERO() -> Self {
44 Self::Degrees(Numeric::F64(0.0))
45 }
46
47 pub fn to_float_0_1(&self) -> f64 {
52 match self {
53 Self::Radians(rad) => rad.to_float() / (std::f64::consts::PI * 2.0),
54 Self::Degrees(deg) => deg.to_float() / 360.0_f64,
55 Self::Percent(per) => per.to_float() / 100.0,
56 }
57 }
58
59 pub fn get_as_radians(&self) -> f64 {
61 if let Self::Radians(num) = self {
62 num.to_float()
63 } else if let Self::Degrees(num) = self {
64 num.to_float() * std::f64::consts::PI * 2.0 / 360.0
65 } else if let Self::Percent(num) = self {
66 num.to_float() * std::f64::consts::PI * 2.0 / 100.0
67 } else {
68 unreachable!()
69 }
70 }
71
72 pub fn get_as_degrees(&self) -> f64 {
74 if let Self::Radians(num) = self {
75 num.to_float() * 180.0 / std::f64::consts::PI
76 } else if let Self::Degrees(num) = self {
77 num.to_float()
78 } else if let Self::Percent(num) = self {
79 num.to_float() * 360.0 / 100.0
80 } else {
81 unreachable!()
82 }
83 }
84}
85impl Neg for Rotation {
86 type Output = Rotation;
87 fn neg(self) -> Self::Output {
88 match self {
89 Rotation::Degrees(deg) => Rotation::Degrees(-deg),
90 Rotation::Radians(rad) => Rotation::Radians(-rad),
91 Rotation::Percent(per) => Rotation::Percent(-per),
92 }
93 }
94}
95
96impl Add for Rotation {
97 type Output = Rotation;
98
99 fn add(self, rhs: Self) -> Self::Output {
100 let self_rad = self.get_as_radians();
101 let other_rad = rhs.get_as_radians();
102 Rotation::Radians(Numeric::F64(self_rad + other_rad))
103 }
104}
105
106#[derive(Debug, Default, Clone, Deserialize, Serialize)]
108pub struct Transform2D {
109 pub previous: Option<Box<Transform2D>>,
111 pub rotate: Option<Rotation>,
113 pub translate: Option<[Size; 2]>,
115 pub anchor: Option<[Size; 2]>,
117 pub scale: Option<[Size; 2]>,
119 pub skew: Option<[Rotation; 2]>,
121}
122
123impl Interpolatable for Transform2D {}
124
125impl Mul for Transform2D {
126 type Output = Transform2D;
127
128 fn mul(self, rhs: Self) -> Self::Output {
129 let mut ret = rhs.clone();
130 ret.previous = Some(Box::new(self));
131 ret
132 }
133}
134
135impl Transform2D {
136 pub fn scale(x: Size, y: Size) -> Self {
138 let mut ret = Transform2D::default();
139 ret.scale = Some([x, y]);
140 ret
141 }
142 pub fn rotate(z: Rotation) -> Self {
144 let mut ret = Transform2D::default();
145 ret.rotate = Some(z);
146 ret
147 }
148 pub fn translate(x: Size, y: Size) -> Self {
150 let mut ret = Transform2D::default();
151 ret.translate = Some([x, y]);
152 ret
153 }
154 pub fn anchor(x: Size, y: Size) -> Self {
156 let mut ret = Transform2D::default();
157 ret.anchor = Some([x, y]);
158 ret
159 }
160}