use std::time::Duration; use crate::{Easing, Mapping, StartTime, Tween, Value, clock::ClockTime, info::MockInfoBuilder}; use super::Parameter; /// Tests that the basic tweening behavior of a `Parameter` /// works properly. #[test] #[allow(clippy::float_cmp)] fn tweening() { let mut parameter = Parameter::new(Value::Fixed(0.0), 0.0); let info = MockInfoBuilder::new().build(); // value should not be changing yet for _ in 0..3 { assert_eq!(parameter.value(), 0.0); assert!(!parameter.update(1.0, &info)); } parameter.set( Value::Fixed(1.0), Tween { duration: Duration::from_secs(2), ..Default::default() }, ); assert!(!parameter.update(1.0, &info)); assert_eq!(parameter.value(), 0.5); assert!(parameter.update(1.0, &info)); assert_eq!(parameter.value(), 1.0); assert!(!parameter.update(1.0, &info)); assert_eq!(parameter.value(), 1.0); } /// Tests that a `Parameter` with a delayed start time waits for /// that time before it begins tweening. #[test] #[allow(clippy::float_cmp)] fn waits_for_delay() { let info = MockInfoBuilder::new().build(); let mut parameter = Parameter::new(Value::Fixed(0.0), 0.0); parameter.set( Value::Fixed(1.0), Tween { start_time: StartTime::Delayed(Duration::from_secs(2)), duration: Duration::from_secs(1), ..Default::default() }, ); // value should not be changing yet for _ in 0..2 { assert_eq!(parameter.value(), 0.0); assert!(!parameter.update(1.0, &info)); } // the tween should start now assert!(parameter.update(1.0, &info)); assert_eq!(parameter.value(), 1.0); } /// Tests that a `Parameter` with a clock time set as /// the start time waits for that time before it /// begins tweening. #[test] #[allow(clippy::float_cmp)] fn waits_for_start_time() { let mut info_builder = MockInfoBuilder::new(); let clock_id_1 = info_builder.add_clock(true, 0, 0.0); let info = info_builder.build(); let mut parameter = Parameter::new(Value::Fixed(0.0), 0.0); parameter.set( Value::Fixed(1.0), Tween { start_time: StartTime::ClockTime(ClockTime { clock: clock_id_1, ticks: 2, fraction: 0.0, }), duration: Duration::from_secs(1), ..Default::default() }, ); // value should not be changing yet for _ in 0..3 { assert_eq!(parameter.value(), 0.0); assert!(!parameter.update(1.0, &info)); } let info = { let mut builder = MockInfoBuilder::new(); builder.add_clock(true, 1, 0.0); builder.add_clock(true, 0, 0.0); builder.build() }; // the tween is set to start at tick 2, so it should not // start yet for _ in 0..3 { assert_eq!(parameter.value(), 0.0); assert!(!parameter.update(1.0, &info)); } let info = { let mut builder = MockInfoBuilder::new(); builder.add_clock(true, 1, 0.0); builder.add_clock(true, 2, 0.0); builder.build() }; // a different clock reached tick 2, so the tween should not // start yet for _ in 0..3 { assert_eq!(parameter.value(), 0.0); assert!(!parameter.update(1.0, &info)); } let info = { let mut builder = MockInfoBuilder::new(); builder.add_clock(true, 2, 0.0); builder.add_clock(true, 2, 0.0); builder.build() }; // the tween should start now assert!(parameter.update(1.0, &info)); assert_eq!(parameter.value(), 1.0); } /// Tests that a parameter can smoothly tween from a fixed value /// to the value of a modulator (while the modulator value is changing). #[test] #[allow(clippy::float_cmp)] fn tweens_to_modulator_values() { let mut info_builder = MockInfoBuilder::new(); let modulator_id = info_builder.add_modulator(0.0); let mut parameter = Parameter::new(Value::Fixed(0.0), 0.0); parameter.set( Value::FromModulator { id: modulator_id, mapping: Mapping { input_range: (0.0, 1.0), output_range: (0.0, 1.0), easing: Easing::Linear, }, }, Tween { duration: Duration::from_secs(1), ..Default::default() }, ); for i in 1..=4 { let time = i as f64 / 4.0; let info = { let mut builder = MockInfoBuilder::new(); builder.add_modulator(time); builder.build() }; parameter.update(0.25, &info); assert_eq!(parameter.value(), time * time); } }