Skip to content

Instantly share code, notes, and snippets.

@Staninna
Created July 5, 2025 12:29
Show Gist options
  • Save Staninna/9f13b1c503fe7edc3de3dfc360475884 to your computer and use it in GitHub Desktop.
Save Staninna/9f13b1c503fe7edc3de3dfc360475884 to your computer and use it in GitHub Desktop.

Revisions

  1. Staninna created this gist Jul 5, 2025.
    246 changes: 246 additions & 0 deletions Feedback.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,246 @@
    ==== main.rs ====
    ```rs
    mod functions;
    mod interpolated;
    mod vec2;

    use crate::{functions::TransitionFunction, interpolated::Interpolated, vec2::Vec2};
    use std::time::Duration;

    fn main() {
    let init = Vec2::new(-35.0, 10.0);
    let end = Vec2::new(100.0, 50.0);
    let dur = 1.5;
    let trans = TransitionFunction::EaseInOutExponential;

    let mut pos = Interpolated::new(init);
    pos.set_duration(Duration::from_secs_f32(dur));
    pos.transition = trans;
    pos.set(end);

    while !pos.is_finished() {
    let v = pos.value();
    println!("position = {:+.1?}", v);
    std::thread::sleep(Duration::from_millis(100));
    }
    }
    ```

    ==== interpolated.rs ====
    ```rs
    use crate::functions::TransitionFunction;
    use std::ops::{Add, Mul, Sub};
    use std::time::{Duration, Instant};

    pub struct Interpolated<T> {
    start: T,
    end: T,
    start_time: Instant,
    pub speed: f32,
    pub transition: TransitionFunction,
    }

    impl<T> Interpolated<T>
    where
    T: Copy + Add<Output = T> + Sub<Output = T> + Mul<f32, Output = T>,
    {
    pub fn new(initial: T) -> Self {
    let now = Instant::now();
    Interpolated {
    start: initial,
    end: initial,
    start_time: now,
    speed: 1.0,
    transition: TransitionFunction::Linear,
    }
    }

    pub fn set_duration(&mut self, dur: Duration) {
    self.speed = 1.0 / dur.as_secs_f32();
    }

    pub fn set(&mut self, value: T) {
    self.start = self.value();
    self.end = value;
    self.start_time = Instant::now();
    }

    pub fn value(&self) -> T {
    let elapsed_secs = (Instant::now() - self.start_time).as_secs_f32() * self.speed;
    if elapsed_secs >= 1.0 {
    return self.end;
    }
    let r = self.transition.ratio(elapsed_secs);
    self.start + (self.end - self.start) * r
    }

    pub fn is_finished(&self) -> bool {
    let elapsed = (Instant::now() - self.start_time).as_secs_f32() * self.speed;
    elapsed >= 1.0
    }
    }
    ```

    ==== vec2.rs ====
    ```rs
    use std::ops::{Add, Mul, Sub};

    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    pub struct Vec2<T> {
    pub x: T,
    pub y: T,
    }

    impl<T> Vec2<T> {
    pub fn new(x: T, y: T) -> Self {
    Self { x, y }
    }

    pub fn zero() -> Self
    where
    T: Default + Copy,
    {
    Self::new(T::default(), T::default())
    }
    }

    impl<T> Add for Vec2<T>
    where
    T: Add<Output = T>,
    {
    type Output = Vec2<T>;

    fn add(self, rhs: Vec2<T>) -> Vec2<T> {
    Vec2 {
    x: self.x + rhs.x,
    y: self.y + rhs.y,
    }
    }
    }

    impl<T> Sub for Vec2<T>
    where
    T: Sub<Output = T>,
    {
    type Output = Vec2<T>;

    fn sub(self, rhs: Vec2<T>) -> Vec2<T> {
    Vec2 {
    x: self.x - rhs.x,
    y: self.y - rhs.y,
    }
    }
    }

    impl<T> Mul<T> for Vec2<T>
    where
    T: Mul<Output = T> + Copy,
    {
    type Output = Vec2<T>;

    fn mul(self, scalar: T) -> Vec2<T> {
    Vec2 {
    x: self.x * scalar,
    y: self.y * scalar,
    }
    }
    }
    ```

    ==== functions.rs ====
    ```rs
    use std::f32::consts::PI;

    fn ease_none(_: f32) -> f32 {
    1.0
    }

    fn linear(t: f32) -> f32 {
    t
    }

    fn expo_in_out(t: f32) -> f32 {
    if t < 0.5 {
    0.5 * (20.0 * t - 10.0).exp2()
    } else {
    1.0 - 0.5 * (10.0 - 20.0 * t).exp2()
    }
    }

    fn ease_out_back(t: f32) -> f32 {
    const C1: f32 = 1.70158;
    const C3: f32 = C1 + 1.0;
    1.0 + C3 * (t - 1.0).powi(3) + C1 * (t - 1.0).powi(2)
    }

    fn ease_in_back(t: f32) -> f32 {
    const C1: f32 = 1.70158;
    const C3: f32 = C1 + 1.0;
    C3 * t * t * t - C1 * t * t
    }

    fn ease_out_elastic(t: f32) -> f32 {
    const TWO_PI: f32 = 2.0 * PI;
    const C4: f32 = TWO_PI / 3.0;
    if t == 0.0 {
    return 0.0;
    }
    if t == 1.0 {
    return 1.0;
    }
    (-10.0 * t).exp2() * ((t * 10.0 - 0.75) * C4).sin() + 1.0
    }

    const EASINGS: [fn(f32) -> f32; 6] = [
    ease_none,
    linear,
    expo_in_out,
    ease_out_back,
    ease_in_back,
    ease_out_elastic,
    ];

    #[repr(u8)]
    #[derive(Copy, Clone, Debug)]
    pub enum TransitionFunction {
    None = 0,
    Linear = 1,
    EaseInOutExponential = 2,
    EaseOutBack = 3,
    EaseInBack = 4,
    EaseOutElastic = 5,
    }

    impl TransitionFunction {
    #[inline]
    pub fn ratio(self, t: f32) -> f32 {
    let t = if t < 0.0 {
    0.0
    } else if t > 1.0 {
    1.0
    } else {
    t
    };
    EASINGS[self as u8 as usize](t)
    }
    }
    ```

    Output:
    ```txt
    position = Vec2 { x: -34.9, y: +10.0 }
    position = Vec2 { x: -34.8, y: +10.0 }
    position = Vec2 { x: -34.6, y: +10.1 }
    position = Vec2 { x: -33.9, y: +10.3 }
    position = Vec2 { x: -32.3, y: +10.8 }
    position = Vec2 { x: -28.2, y: +12.0 }
    position = Vec2 { x: -17.8, y: +15.1 }
    position = Vec2 { x: +8.4, y: +22.9 }
    position = Vec2 { x: +58.5, y: +37.7 }
    position = Vec2 { x: +83.6, y: +45.1 }
    position = Vec2 { x: +93.5, y: +48.1 }
    position = Vec2 { x: +97.4, y: +49.2 }
    position = Vec2 { x: +99.0, y: +49.7 }
    position = Vec2 { x: +99.6, y: +49.9 }
    position = Vec2 { x: +99.8, y: +50.0 }
    ```