#![warn(missing_copy_implementations)]
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Vector {
pub x: f32,
pub y: f32,
}
pub type Point = Vector;
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Rect {
pub position: Point,
pub size: Vector,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
impl Vector {
pub fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
pub fn length_sq(self) -> f32 {
self.x * self.x + self.y * self.y
}
pub fn length(self) -> f32 {
self.length_sq().sqrt()
}
pub fn distance(self, other: Vector) -> f32 {
(other - self).length()
}
}
pub fn vector(x: f32, y: f32) -> Vector {
Vector::new(x, y)
}
pub fn point(x: f32, y: f32) -> Point {
Point::new(x, y)
}
impl Color {
pub const BLACK: Self = rgb(0, 0, 0);
pub const WHITE: Self = rgb(255, 255, 255);
pub const TRANSPARENT: Self = rgba(0, 0, 0, 0);
pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
Self { r, g, b, a }
}
pub const fn argb(hex: u32) -> Self {
let a = (hex >> 24) & 0xFF;
let r = (hex >> 16) & 0xFF;
let g = (hex >> 8) & 0xFF;
let b = hex & 0xFF;
Self {
r: r as u8,
g: g as u8,
b: b as u8,
a: a as u8,
}
}
pub const fn to_argb(&self) -> u32 {
((self.a as u32) << 24) | ((self.r as u32) << 16) | ((self.g as u32) << 8) | (self.b as u32)
}
pub const fn rgb(hex: u32) -> Self {
Self::argb(hex | 0xFF000000)
}
pub const fn with_alpha(self, a: u8) -> Self {
Self::new(self.r, self.g, self.b, a)
}
}
pub const fn rgb(r: u8, g: u8, b: u8) -> Color {
Color::new(r, g, b, 255)
}
pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Color {
Color::new(r, g, b, a)
}
impl Rect {
pub fn new(position: impl Into<Point>, size: impl Into<Vector>) -> Self {
Self {
position: position.into(),
size: size.into(),
}
}
pub fn x(&self) -> f32 {
self.position.x
}
pub fn y(&self) -> f32 {
self.position.y
}
pub fn width(&self) -> f32 {
self.size.x
}
pub fn height(&self) -> f32 {
self.size.y
}
pub fn left(&self) -> f32 {
self.position.x
}
pub fn top(&self) -> f32 {
self.position.y
}
pub fn right(&self) -> f32 {
self.position.x + self.size.x
}
pub fn bottom(&self) -> f32 {
self.position.y + self.size.y
}
pub fn top_left(&self) -> Point {
self.position
}
pub fn top_right(&self) -> Point {
self.position + vector(self.size.x, 0.0)
}
pub fn bottom_left(&self) -> Point {
self.position + vector(0.0, self.size.y)
}
pub fn bottom_right(&self) -> Point {
self.position + self.size
}
pub fn center(&self) -> Point {
self.position + self.size / 2.0
}
pub fn center_x(&self) -> f32 {
self.position.x + self.size.x / 2.0
}
pub fn center_y(&self) -> f32 {
self.position.y + self.size.y / 2.0
}
pub fn sort(self) -> Self {
let left = f32::min(self.left(), self.right());
let right = f32::max(self.left(), self.right());
let top = f32::min(self.top(), self.bottom());
let bottom = f32::max(self.top(), self.bottom());
Self::new(point(left, top), vector(right - left, bottom - top))
}
}
impl Default for Vector {
fn default() -> Self {
vector(0.0, 0.0)
}
}
impl From<(f32, f32)> for Vector {
fn from(tuple: (f32, f32)) -> Self {
vector(tuple.0, tuple.1)
}
}
impl From<[f32; 2]> for Vector {
fn from(array: [f32; 2]) -> Self {
vector(array[0], array[1])
}
}
impl Neg for Vector {
type Output = Self;
fn neg(self) -> Self::Output {
vector(-self.x, -self.y)
}
}
impl<T: Into<Self>> Add<T> for Vector {
type Output = Self;
fn add(self, v: T) -> Self {
let v = v.into();
vector(self.x + v.x, self.y + v.y)
}
}
impl<T: Into<Self>> AddAssign<T> for Vector {
fn add_assign(&mut self, v: T) {
let v = v.into();
self.x += v.x;
self.y += v.y;
}
}
impl<T: Into<Self>> Sub<T> for Vector {
type Output = Self;
fn sub(self, v: T) -> Self {
let v = v.into();
vector(self.x - v.x, self.y - v.y)
}
}
impl<T: Into<Self>> SubAssign<T> for Vector {
fn sub_assign(&mut self, v: T) {
let v = v.into();
self.x -= v.x;
self.y -= v.y;
}
}
impl<T: Into<Self>> Mul<T> for Vector {
type Output = Self;
fn mul(self, v: T) -> Self {
let v = v.into();
vector(self.x * v.x, self.y * v.y)
}
}
impl<T: Into<Self>> MulAssign<T> for Vector {
fn mul_assign(&mut self, v: T) {
let v = v.into();
self.x *= v.x;
self.y *= v.y;
}
}
impl<T: Into<Self>> Div<T> for Vector {
type Output = Self;
fn div(self, v: T) -> Self {
let v = v.into();
vector(self.x / v.x, self.y / v.y)
}
}
impl<T: Into<Self>> DivAssign<T> for Vector {
fn div_assign(&mut self, v: T) {
let v = v.into();
self.x /= v.x;
self.y /= v.y;
}
}
impl Mul<f32> for Vector {
type Output = Self;
fn mul(self, s: f32) -> Self {
vector(self.x * s, self.y * s)
}
}
impl MulAssign<f32> for Vector {
fn mul_assign(&mut self, s: f32) {
self.x *= s;
self.y *= s;
}
}
impl Div<f32> for Vector {
type Output = Self;
fn div(self, s: f32) -> Self {
vector(self.x / s, self.y / s)
}
}
impl DivAssign<f32> for Vector {
fn div_assign(&mut self, s: f32) {
self.x /= s;
self.y /= s;
}
}