mod rect;
mod transform;
mod lerp;
mod angle;
pub use glam::{Vec2, Vec3, Vec4, Mat4, Quat};
pub use rect::Rect;
pub use transform::Transform;
pub use lerp::Lerp;
pub use angle::Angle;
#[inline(always)]
pub const fn vec2(x: f32, y: f32) -> Vec2 {
Vec2::new(x, y)
}
#[inline(always)]
pub const fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
Vec3::new(x, y, z)
}
#[inline(always)]
pub const fn ivec2(x: i32, y: i32) -> glam::IVec2 {
glam::IVec2::new(x, y)
}
pub mod consts {
use super::*;
pub const ZERO: Vec2 = Vec2::new(0.0, 0.0);
pub const RIGHT: Vec2 = Vec2::new(1.0, 0.0);
pub const LEFT: Vec2 = Vec2::new(-1.0, 0.0);
pub const UP: Vec2 = Vec2::new(0.0, -1.0);
pub const DOWN: Vec2 = Vec2::new(0.0, 1.0);
pub const ONE: Vec2 = Vec2::new(1.0, 1.0);
pub const PI: f32 = std::f32::consts::PI;
pub const HALF_PI: f32 = PI / 2.0;
pub const TAU: f32 = PI * 2.0;
}
pub trait Vec2Ext {
fn distance_to(self, other: Vec2) -> f32;
fn distance_squared_to(self, other: Vec2) -> f32;
fn angle_to(self, other: Vec2) -> f32;
fn rotated(self, angle: f32) -> Vec2;
fn move_toward(self, target: Vec2, max_delta: f32) -> Vec2;
fn reflect(self, normal: Vec2) -> Vec2;
fn projected_onto(self, onto: Vec2) -> Vec2;
fn perp(self) -> Vec2;
fn to_ivec(self) -> glam::IVec2;
}
impl Vec2Ext for Vec2 {
#[inline]
fn distance_to(self, other: Vec2) -> f32 {
(self - other).length()
}
#[inline]
fn distance_squared_to(self, other: Vec2) -> f32 {
(self - other).length_squared()
}
#[inline]
fn angle_to(self, other: Vec2) -> f32 {
let diff = other - self;
diff.y.atan2(diff.x)
}
#[inline]
fn rotated(self, angle: f32) -> Vec2 {
let (sin, cos) = angle.sin_cos();
Vec2::new(
self.x * cos - self.y * sin,
self.x * sin + self.y * cos,
)
}
#[inline]
fn move_toward(self, target: Vec2, max_delta: f32) -> Vec2 {
let diff = target - self;
let dist = diff.length();
if dist <= max_delta || dist < 1e-6 {
target
} else {
self + diff * (max_delta / dist)
}
}
#[inline]
fn reflect(self, normal: Vec2) -> Vec2 {
self - 2.0 * self.dot(normal) * normal
}
#[inline]
fn projected_onto(self, onto: Vec2) -> Vec2 {
onto * (self.dot(onto) / onto.length_squared())
}
#[inline]
fn perp(self) -> Vec2 {
Vec2::new(self.y, -self.x)
}
#[inline]
fn to_ivec(self) -> glam::IVec2 {
glam::IVec2::new(self.x as i32, self.y as i32)
}
}
pub trait FloatExt {
fn lerp(self, other: f32, t: f32) -> f32;
fn clamp(self, min: f32, max: f32) -> f32;
fn map_range(self, in_min: f32, in_max: f32, out_min: f32, out_max: f32) -> f32;
fn deadzone(self, deadzone: f32) -> f32;
fn snap(self, step: f32) -> f32;
}
impl FloatExt for f32 {
#[inline]
fn lerp(self, other: f32, t: f32) -> f32 {
self + (other - self) * t.clamp(0.0, 1.0)
}
#[inline]
fn clamp(self, min: f32, max: f32) -> f32 {
Self::clamp(self, min, max)
}
#[inline]
fn map_range(self, in_min: f32, in_max: f32, out_min: f32, out_max: f32) -> f32 {
(self - in_min) / (in_max - in_min) * (out_max - out_min) + out_min
}
#[inline]
fn deadzone(self, deadzone: f32) -> f32 {
if self.abs() < deadzone { 0.0 } else { self }
}
#[inline]
fn snap(self, step: f32) -> f32 {
(self / step).round() * step
}
}