use crate::animation::types::Rect;
#[inline]
#[allow(clippy::cast_possible_truncation)] pub fn lerp_i32(from: i32, to: i32, t: f64) -> i32 {
f64::from(to - from).mul_add(t, f64::from(from)).round() as i32
}
#[inline]
#[allow(dead_code)] pub fn lerp_f64(from: f64, to: f64, t: f64) -> f64 {
(to - from).mul_add(t, from)
}
#[inline]
pub fn lerp_rect(from: Rect, to: Rect, tp: f64, ts: f64) -> Rect {
Rect {
x: lerp_i32(from.x, to.x, tp),
y: lerp_i32(from.y, to.y, tp),
w: lerp_i32(from.w, to.w, ts),
h: lerp_i32(from.h, to.h, ts),
}
}
#[inline]
#[allow(dead_code)] pub fn is_noop(from: &Rect, to: &Rect) -> bool {
from == to
}
#[inline]
#[allow(dead_code)] pub fn is_translation_only(from: &Rect, to: &Rect) -> bool {
from.w == to.w && from.h == to.h
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lerp_i32_midpoint() {
assert_eq!(lerp_i32(0, 100, 0.5), 50);
}
#[test]
fn lerp_i32_boundaries() {
assert_eq!(lerp_i32(0, 100, 0.0), 0);
assert_eq!(lerp_i32(0, 100, 1.0), 100);
}
#[test]
fn lerp_i32_rounding() {
assert_eq!(lerp_i32(0, 1, 0.4), 0);
assert_eq!(lerp_i32(0, 1, 0.6), 1);
}
#[test]
fn lerp_i32_negative_range() {
assert_eq!(lerp_i32(-100, 100, 0.5), 0);
}
#[test]
fn lerp_f64_midpoint() {
assert!((lerp_f64(0.0, 1.0, 0.5) - 0.5).abs() < 1e-15);
}
#[test]
fn lerp_rect_separate_position_and_size() {
let from = Rect::new(0, 0, 100, 100);
let to = Rect::new(200, 400, 300, 500);
let result = lerp_rect(from, to, 0.5, 1.0);
assert_eq!(result.x, 100);
assert_eq!(result.y, 200);
assert_eq!(result.w, 300);
assert_eq!(result.h, 500);
}
#[test]
fn lerp_rect_at_zero_returns_from() {
let from = Rect::new(10, 20, 300, 200);
let to = Rect::new(50, 80, 600, 400);
let result = lerp_rect(from, to, 0.0, 0.0);
assert_eq!(result, from);
}
#[test]
fn lerp_rect_at_one_returns_to() {
let from = Rect::new(10, 20, 300, 200);
let to = Rect::new(50, 80, 600, 400);
let result = lerp_rect(from, to, 1.0, 1.0);
assert_eq!(result, to);
}
#[test]
fn is_noop_identical_rects() {
let r = Rect::new(0, 0, 100, 100);
assert!(is_noop(&r, &r));
}
#[test]
fn is_noop_different_position() {
let from = Rect::new(0, 0, 100, 100);
let to = Rect::new(10, 0, 100, 100);
assert!(!is_noop(&from, &to));
}
#[test]
fn is_translation_only_same_size() {
let from = Rect::new(0, 0, 100, 200);
let to = Rect::new(50, 50, 100, 200);
assert!(is_translation_only(&from, &to));
}
#[test]
fn is_translation_only_different_size() {
let from = Rect::new(0, 0, 100, 200);
let to = Rect::new(0, 0, 150, 200);
assert!(!is_translation_only(&from, &to));
}
#[test]
fn is_translation_only_noop_is_also_translation_only() {
let r = Rect::new(10, 10, 80, 80);
assert!(is_translation_only(&r, &r));
}
}