use std::ops::{Add, Div, Mul, Neg, Sub};
#[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd)]
pub struct MotionPx(f32);
impl MotionPx {
pub const ZERO: Self = Self(0.0);
pub const ONE: Self = Self(1.0);
pub const fn new(value: f32) -> Self {
Self(value)
}
pub const fn as_f32(self) -> f32 {
self.0
}
pub const fn half(self) -> Self {
Self(self.0 * 0.5)
}
pub const fn min(self, other: Self) -> Self {
if self.0 <= other.0 { self } else { other }
}
pub const fn max(self, other: Self) -> Self {
if self.0 >= other.0 { self } else { other }
}
}
impl Add for MotionPx {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0)
}
}
impl Sub for MotionPx {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 - rhs.0)
}
}
impl Neg for MotionPx {
type Output = Self;
fn neg(self) -> Self::Output {
Self(-self.0)
}
}
impl Mul<f32> for MotionPx {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
Self(self.0 * rhs)
}
}
impl Div<f32> for MotionPx {
type Output = Self;
fn div(self, rhs: f32) -> Self::Output {
Self(self.0 / rhs)
}
}
pub const fn motion_px(value: f32) -> MotionPx {
MotionPx::new(value)
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct MotionPoint {
pub x: MotionPx,
pub y: MotionPx,
}
impl MotionPoint {
pub const fn new(x: MotionPx, y: MotionPx) -> Self {
Self { x, y }
}
}
pub const fn motion_point(x: MotionPx, y: MotionPx) -> MotionPoint {
MotionPoint::new(x, y)
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct MotionSize {
pub width: MotionPx,
pub height: MotionPx,
}
impl MotionSize {
pub const fn new(width: MotionPx, height: MotionPx) -> Self {
Self { width, height }
}
}
pub const fn motion_size(width: MotionPx, height: MotionPx) -> MotionSize {
MotionSize::new(width, height)
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct MotionRect {
pub origin: MotionPoint,
pub size: MotionSize,
}
impl MotionRect {
pub const fn new(origin: MotionPoint, size: MotionSize) -> Self {
Self { origin, size }
}
pub const fn top_left(self) -> MotionPoint {
self.origin
}
pub fn top_center(self) -> MotionPoint {
MotionPoint::new(self.origin.x + self.size.width.half(), self.origin.y)
}
pub fn top_right(self) -> MotionPoint {
MotionPoint::new(self.origin.x + self.size.width, self.origin.y)
}
pub fn right_center(self) -> MotionPoint {
MotionPoint::new(
self.origin.x + self.size.width,
self.origin.y + self.size.height.half(),
)
}
pub fn bottom_left(self) -> MotionPoint {
MotionPoint::new(self.origin.x, self.origin.y + self.size.height)
}
pub fn bottom_center(self) -> MotionPoint {
MotionPoint::new(
self.origin.x + self.size.width.half(),
self.origin.y + self.size.height,
)
}
pub fn bottom_right(self) -> MotionPoint {
MotionPoint::new(
self.origin.x + self.size.width,
self.origin.y + self.size.height,
)
}
pub fn left_center(self) -> MotionPoint {
MotionPoint::new(self.origin.x, self.origin.y + self.size.height.half())
}
pub fn inset(self, amount: MotionPx) -> Self {
let double = MotionPx::new(amount.as_f32() * 2.0);
Self {
origin: MotionPoint::new(self.origin.x + amount, self.origin.y + amount),
size: MotionSize::new(self.size.width - double, self.size.height - double),
}
}
}
pub const fn motion_rect(origin: MotionPoint, size: MotionSize) -> MotionRect {
MotionRect::new(origin, size)
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct MotionEdges {
pub top: MotionPx,
pub right: MotionPx,
pub bottom: MotionPx,
pub left: MotionPx,
}
impl MotionEdges {
pub const fn new(top: MotionPx, right: MotionPx, bottom: MotionPx, left: MotionPx) -> Self {
Self {
top,
right,
bottom,
left,
}
}
pub const fn uniform(value: MotionPx) -> Self {
Self {
top: value,
right: value,
bottom: value,
left: value,
}
}
}
pub const fn motion_edges(
top: MotionPx,
right: MotionPx,
bottom: MotionPx,
left: MotionPx,
) -> MotionEdges {
MotionEdges::new(top, right, bottom, left)
}