flake-engine 0.1.0

Immediate-mode game framework built on wgpu + winit
#![allow(unused)]
pub use cgmath::num_traits::*;
pub use cgmath::prelude::*;
pub use std::ops::Neg;

pub type Vector2 = cgmath::Vector2<f32>;
pub type Vector3 = cgmath::Vector3<f32>;
pub type Vector4 = cgmath::Vector4<f32>;
pub type Quaternion = cgmath::Quaternion<f32>;

pub trait FlakeMath: Sized {
    fn normalize_or_zero(&self) -> Self;
    fn one() -> Self;
    fn neg_one() -> Self;
}

impl<T> FlakeMath for T
where
    T: InnerSpace + Array<Element = <T as VectorSpace>::Scalar> + Copy,
    T::Scalar: cgmath::BaseFloat,
{
    fn normalize_or_zero(&self) -> Self {
        if self.magnitude2().is_zero() {
            Self::zero()
        } else {
            self.normalize()
        }
    }

    fn one() -> Self {
        Self::from_value(T::Scalar::one())
    }

    fn neg_one() -> Self {
        Self::from_value(T::Scalar::neg(T::Scalar::one()))
    }
}

pub trait FlakeVector2Ext {
    /// Returns the radian angle [-π, π] of this vector relative to (1, 0)
    fn angle_rad(&self) -> f32;

    /// Returns the radian direction looking from this point toward a target point
    fn angle_towards(&self, target: Vector2) -> f32;
}

impl FlakeVector2Ext for Vector2 {
    fn angle_rad(&self) -> f32 {
        self.y.atan2(self.x)
    }

    fn angle_towards(&self, target: Vector2) -> f32 {
        (target - *self).angle_rad()
    }
}

use std::ops::{Add, Div, Mul, Sub};

pub trait Number:
    Copy
    + PartialOrd
    + Add<Output = Self>
    + Sub<Output = Self>
    + Mul<Output = Self>
    + Div<Output = Self>
{
    fn to_f32(self) -> f32;
    fn zero() -> Self;
    fn one() -> Self;
}

pub fn lerp<T: Copy + Sub + Add<<<T as Sub>::Output as Mul<f32>>::Output, Output = T>>(
    a: T,
    b: T,
    t: f32,
) -> T
where
    <T as Sub>::Output: Mul<f32>,
{
    a + (b - a) * t
}

macro_rules! impl_number {
    ($($t:ty),*) => {
        $(impl Number for $t {
            fn to_f32(self) -> f32 { self as f32 }
            fn zero() -> Self { 0 as $t }
            fn one() -> Self { 1 as $t }
        })*
    };
}

impl_number!(f32, f64, i8, i16, i32, i64, u8, u16, u32, u64, usize, isize);