argui-animation 0.2.1

Animation timing and interpolation for Argui interfaces
Documentation
use argui_animation::{Decay, DecayConfig, Duration, PhysicsError};

#[test]
fn exponential_decay_is_frame_partition_independent() {
    let config = DecayConfig {
        rest_speed: 0.0,
        ..DecayConfig::default()
    };
    let mut single = Decay::new(0.0_f64, 100.0, config).unwrap();
    let mut partitioned = single;
    single.advance(Duration::from_secs(1));
    for _ in 0..100 {
        partitioned.advance(Duration::from_millis(10));
    }
    assert!((single.value() - partitioned.value()).abs() < 1.0e-10);
    assert!((single.velocity() - partitioned.velocity()).abs() < 1.0e-10);
}

#[test]
fn decay_kicks_and_stops_at_its_rest_threshold() {
    let mut decay = Decay::new(4.0_f32, 0.0, DecayConfig::default()).unwrap();
    assert!(!decay.is_active());
    assert!(!decay.advance(Duration::ZERO));
    decay.kick(10.0);
    assert!(decay.is_active());
    assert!(!decay.advance(Duration::ZERO));
    assert_eq!(decay.value(), 4.0);
    assert_eq!(decay.velocity(), 10.0);
    for _ in 0..1_000 {
        decay.advance(Duration::from_millis(16));
        if !decay.is_active() {
            break;
        }
    }
    assert!(!decay.is_active());
    assert_eq!(decay.velocity(), 0.0);
    assert!(decay.value() > 4.0);
}

#[test]
fn decay_configuration_is_validated() {
    assert_eq!(
        Decay::new(
            0.0_f32,
            1.0,
            DecayConfig {
                rate: f64::NAN,
                ..DecayConfig::default()
            }
        ),
        Err(PhysicsError::InvalidDecay)
    );
    assert_eq!(
        Decay::new(
            0.0_f32,
            1.0,
            DecayConfig {
                rate: 0.0,
                ..DecayConfig::default()
            }
        ),
        Err(PhysicsError::InvalidDecay)
    );
    assert_eq!(
        Decay::new(
            0.0_f32,
            1.0,
            DecayConfig {
                rest_speed: f64::NAN,
                ..DecayConfig::default()
            }
        ),
        Err(PhysicsError::InvalidRestThreshold)
    );
    assert_eq!(
        Decay::new(
            0.0_f32,
            1.0,
            DecayConfig {
                rest_speed: -1.0,
                ..DecayConfig::default()
            }
        ),
        Err(PhysicsError::InvalidRestThreshold)
    );
}