use std::cmp::PartialOrd;
const I8_MAX: i16 = i8::MAX as i16;
const I8_MIN: i16 = i8::MIN as i16;
const I16_MAX: i32 = i16::MAX as i32;
const I16_MIN: i32 = i16::MIN as i32;
const I32_MAX: i64 = i32::MAX as i64;
const I32_MIN: i64 = i32::MIN as i64;
const I64_MAX: i128 = i64::MAX as i128;
const I64_MIN: i128 = i64::MIN as i128;
pub fn overlay<T, U>(src: &[T], dst: &mut Vec<T>, time: f64, framerate: u32, add: bool)
where
T: Copy + PartialOrd + Overlayable<T, U> + From<u8>,
U: Copy + PartialOrd + ValueBounds<U>,
{
let mut index: usize = (time * framerate as f64) as usize;
let len: usize = dst.len();
let zero: T = T::from(0);
if index >= len {
if add {
dst.extend(vec![zero; index - len]);
dst.extend(src.iter().cloned());
}
return;
}
let min: U = U::min();
let max: U = U::max();
for (i, &v) in src.iter().enumerate() {
if index >= len {
if add {
dst.extend(src[i..].iter().cloned());
}
return;
}
if dst[index] == zero {
dst[index] = v;
}
else {
dst[index] = T::overlay(dst[index], v, min, max);
}
index += 1;
}
}
fn clamp<T>(value: T, min: T, max: T) -> T
where
T: PartialOrd,
{
if value > max {
max
} else if value < min {
min
} else {
value
}
}
pub trait Overlayable<T, U>
where
T: Copy + PartialOrd,
U: Copy + PartialOrd,
{
fn overlay(a: T, b: T, min: U, max: U) -> T;
}
impl Overlayable<i8, i16> for i8 {
fn overlay(a: i8, b: i8, min: i16, max: i16) -> i8 {
clamp((a + b) as i16, min, max) as i8
}
}
impl Overlayable<i16, i32> for i16 {
fn overlay(a: i16, b: i16, min: i32, max: i32) -> i16 {
clamp((a + b) as i32, min, max) as i16
}
}
impl Overlayable<i32, i64> for i32 {
fn overlay(a: i32, b: i32, min: i64, max: i64) -> i32 {
clamp((a + b) as i64, min, max) as i32
}
}
impl Overlayable<i64, i128> for i64 {
fn overlay(a: i64, b: i64, min: i128, max: i128) -> i64 {
clamp((a + b) as i128, min, max) as i64
}
}
impl Overlayable<f32, f32> for f32 {
fn overlay(a: f32, b: f32, min: f32, max: f32) -> f32 {
clamp(a + b, min, max)
}
}
impl Overlayable<f64, f64> for f64 {
fn overlay(a: f64, b: f64, min: f64, max: f64) -> f64 {
clamp(a + b, min, max)
}
}
pub trait ValueBounds<T>
where
T: Copy + PartialOrd,
{
fn min() -> T;
fn max() -> T;
}
impl ValueBounds<i16> for i16 {
fn min() -> i16 {
I8_MIN
}
fn max() -> i16 {
I8_MAX
}
}
impl ValueBounds<i32> for i32 {
fn min() -> i32 {
I16_MIN
}
fn max() -> i32 {
I16_MAX
}
}
impl ValueBounds<i64> for i64 {
fn min() -> i64 {
I32_MIN
}
fn max() -> i64 {
I32_MAX
}
}
impl ValueBounds<i128> for i128 {
fn min() -> i128 {
I64_MIN
}
fn max() -> i128 {
I64_MAX
}
}
impl ValueBounds<f32> for f32 {
fn min() -> f32 {
-1.0
}
fn max() -> f32 {
1.0
}
}
impl ValueBounds<f64> for f64 {
fn min() -> f64 {
-1.0
}
fn max() -> f64 {
1.0
}
}