Reviewed-on: iris/iris#16 Reviewed-by: iris <2+iris@noreply.localhost> Co-authored-by: iris-ai <4+iris-ai@noreply.localhost>
77 lines
2.4 KiB
Rust
77 lines
2.4 KiB
Rust
pub const trait LerpUtil: Sized {
|
|
fn lerp(self, from: Self, to: Self) -> Self;
|
|
fn lerp_inv(self, from: Self, to: Self) -> Option<Self>;
|
|
}
|
|
|
|
const impl LerpUtil for f32 {
|
|
/// linear interpolation
|
|
/// from * (1.0 - self) + to * self
|
|
fn lerp(self, from: Self, to: Self) -> Self {
|
|
from + (to - from) * self
|
|
}
|
|
/// inverse of lerp, and `None` where `from` and `to` are the same point:
|
|
/// every input lerps to it, so there is no one answer to come back to.
|
|
fn lerp_inv(self, from: Self, to: Self) -> Option<Self> {
|
|
match to == from {
|
|
true => None,
|
|
false => Some((self - from) / (to - from)),
|
|
}
|
|
}
|
|
}
|
|
|
|
macro_rules! impl_op {
|
|
($T:ident $op:ident $fn:ident $opa:ident $fna:ident; $($field:ident)*) => {
|
|
#[allow(non_snake_case)]
|
|
mod ${concat($T, _op_, $fn, _impl)} {
|
|
use super::*;
|
|
#[allow(unused_imports)]
|
|
use std::ops::*;
|
|
const impl $op for $T {
|
|
type Output = Self;
|
|
|
|
fn $fn(self, rhs: Self) -> Self::Output {
|
|
Self {
|
|
$($field: self.$field.$fn(rhs.$field),)*
|
|
}
|
|
}
|
|
}
|
|
const impl $opa for $T {
|
|
fn $fna(&mut self, rhs: Self) {
|
|
*self = self.$fn(rhs);
|
|
}
|
|
}
|
|
const impl $op<f32> for $T {
|
|
type Output = Self;
|
|
|
|
fn $fn(self, rhs: f32) -> Self::Output {
|
|
Self {
|
|
$($field: self.$field.$fn(rhs),)*
|
|
}
|
|
}
|
|
}
|
|
const impl $op<$T> for f32 {
|
|
type Output = $T;
|
|
|
|
fn $fn(self, rhs: $T) -> Self::Output {
|
|
$T {
|
|
$($field: self.$fn(rhs.$field),)*
|
|
}
|
|
}
|
|
}
|
|
const impl $opa<f32> for $T {
|
|
fn $fna(&mut self, rhs: f32) {
|
|
*self = self.$fn(rhs);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
($T:ident $op:ident $fn:ident; $($field:ident)*) => {
|
|
impl_op!($T $op $fn ${concat($op,Assign)} ${concat($fn,_assign)}; $($field)*);
|
|
};
|
|
(impl $op:ident for $T:ident: $fn:ident $($field:ident)*) => {
|
|
impl_op!($T $op $fn ${concat($op,Assign)} ${concat($fn,_assign)}; $($field)*);
|
|
};
|
|
}
|
|
|
|
pub(crate) use impl_op;
|