use super::*;
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Copy)]
pub enum Rotation {
Radians(Numeric),
Degrees(Numeric),
Percent(Numeric),
}
impl Display for Rotation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Rotation::Radians(rad) => write!(f, "{}rad", rad),
Rotation::Degrees(deg) => write!(f, "{}deg", deg),
Rotation::Percent(per) => write!(f, "{}%", per),
}
}
}
impl Default for Rotation {
fn default() -> Self {
Self::Degrees(Numeric::F64(0.0))
}
}
impl Interpolatable for Rotation {
fn interpolate(&self, other: &Self, t: f64) -> Self {
Self::Degrees(Numeric::F64(
self.get_as_degrees() + (other.get_as_degrees() - self.get_as_degrees()) * t,
))
}
}
impl Rotation {
#[allow(non_snake_case)]
pub fn ZERO() -> Self {
Self::Degrees(Numeric::F64(0.0))
}
pub fn to_float_0_1(&self) -> f64 {
match self {
Self::Radians(rad) => rad.to_float() / (std::f64::consts::PI * 2.0),
Self::Degrees(deg) => deg.to_float() / 360.0_f64,
Self::Percent(per) => per.to_float() / 100.0,
}
}
pub fn get_as_radians(&self) -> f64 {
if let Self::Radians(num) = self {
num.to_float()
} else if let Self::Degrees(num) = self {
num.to_float() * std::f64::consts::PI * 2.0 / 360.0
} else if let Self::Percent(num) = self {
num.to_float() * std::f64::consts::PI * 2.0 / 100.0
} else {
unreachable!()
}
}
pub fn get_as_degrees(&self) -> f64 {
if let Self::Radians(num) = self {
num.to_float() * 180.0 / std::f64::consts::PI
} else if let Self::Degrees(num) = self {
num.to_float()
} else if let Self::Percent(num) = self {
num.to_float() * 360.0 / 100.0
} else {
unreachable!()
}
}
}
impl Neg for Rotation {
type Output = Rotation;
fn neg(self) -> Self::Output {
match self {
Rotation::Degrees(deg) => Rotation::Degrees(-deg),
Rotation::Radians(rad) => Rotation::Radians(-rad),
Rotation::Percent(per) => Rotation::Percent(-per),
}
}
}
impl Add for Rotation {
type Output = Rotation;
fn add(self, rhs: Self) -> Self::Output {
let self_rad = self.get_as_radians();
let other_rad = rhs.get_as_radians();
Rotation::Radians(Numeric::F64(self_rad + other_rad))
}
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct Transform2D {
pub previous: Option<Box<Transform2D>>,
pub rotate: Option<Rotation>,
pub translate: Option<[Size; 2]>,
pub anchor: Option<[Size; 2]>,
pub scale: Option<[Size; 2]>,
pub skew: Option<[Rotation; 2]>,
}
impl Interpolatable for Transform2D {}
impl Mul for Transform2D {
type Output = Transform2D;
fn mul(self, rhs: Self) -> Self::Output {
let mut ret = rhs.clone();
ret.previous = Some(Box::new(self));
ret
}
}
impl Transform2D {
pub fn scale(x: Size, y: Size) -> Self {
let mut ret = Transform2D::default();
ret.scale = Some([x, y]);
ret
}
pub fn rotate(z: Rotation) -> Self {
let mut ret = Transform2D::default();
ret.rotate = Some(z);
ret
}
pub fn translate(x: Size, y: Size) -> Self {
let mut ret = Transform2D::default();
ret.translate = Some([x, y]);
ret
}
pub fn anchor(x: Size, y: Size) -> Self {
let mut ret = Transform2D::default();
ret.anchor = Some([x, y]);
ret
}
}