use std::ops::*; #[repr(C)] #[derive(Clone, Copy, PartialEq, Default, bytemuck::Pod, bytemuck::Zeroable)] pub struct Point { pub x: f32, pub y: f32, } pub const fn point(x: f32, y: f32) -> Point { Point::new(x, y) } impl Point { pub const fn new(x: f32, y: f32) -> Self { Self { x, y } } pub const fn lerp(self, to: Self, amt: impl const Into) -> Self { let amt = amt.into(); Self { x: lerp(self.x, to.x, amt.x), y: lerp(self.y, to.y, amt.y), } } } const fn lerp(x: f32, y: f32, amt: f32) -> f32 { (1.0 - amt) * x + y * amt } impl const From for Point { fn from(v: f32) -> Self { Self { x: v, y: v } } } macro_rules! impl_op_inner { ($op:ident $fn:ident $opa:ident $fna:ident) => { impl const $op for Point { type Output = Self; fn $fn(self, rhs: Self) -> Self::Output { Self { x: self.x.$fn(rhs.x), y: self.y.$fn(rhs.y), } } } impl $opa for Point { fn $fna(&mut self, rhs: Self) { self.x.$fna(rhs.x); self.y.$fna(rhs.y); } } impl const $op for Point { type Output = Self; fn $fn(self, rhs: f32) -> Self::Output { Self { x: self.x.$fn(rhs), y: self.y.$fn(rhs), } } } impl $opa for Point { fn $fna(&mut self, rhs: f32) { self.x.$fna(rhs); self.y.$fna(rhs); } } }; } macro_rules! impl_op { ($op:ident $fn:ident) => { impl_op_inner!($op $fn ${concat($op,Assign)} ${concat($fn,_assign)}); }; } impl_op!(Add add); impl_op!(Sub sub); impl_op!(Mul mul); impl_op!(Div div);