diff --git a/crates/egui/src/animation_manager.rs b/crates/egui/src/animation_manager.rs index b7b7d18beff..fee5ad5ea8c 100644 --- a/crates/egui/src/animation_manager.rs +++ b/crates/egui/src/animation_manager.rs @@ -1,4 +1,7 @@ -use crate::{emath::remap_clamp, Id, IdMap, InputState}; +use crate::{ + emath::{remap_clamp, NumExt as _}, + Id, IdMap, InputState, +}; #[derive(Clone, Default)] pub(crate) struct AnimationManager { @@ -8,10 +11,8 @@ pub(crate) struct AnimationManager { #[derive(Clone, Debug)] struct BoolAnim { - value: bool, - - /// when did `value` last toggle? - toggle_time: f64, + last_value: f32, + last_tick: f64, } #[derive(Clone, Debug)] @@ -33,38 +34,33 @@ impl AnimationManager { id: Id, value: bool, ) -> f32 { + let (start, end) = if value { (0.0, 1.0) } else { (1.0, 0.0) }; match self.bools.get_mut(&id) { None => { self.bools.insert( id, BoolAnim { - value, - toggle_time: -f64::INFINITY, // long time ago + last_value: end, + last_tick: input.time - input.stable_dt as f64, }, ); - if value { - 1.0 - } else { - 0.0 - } + end } Some(anim) => { - if anim.value != value { - anim.value = value; - anim.toggle_time = input.time; - } - - let time_since_toggle = (input.time - anim.toggle_time) as f32; - - // On the frame we toggle we don't want to return the old value, - // so we extrapolate forwards: - let time_since_toggle = time_since_toggle + input.predicted_dt; - - if value { - remap_clamp(time_since_toggle, 0.0..=animation_time, 0.0..=1.0) + let BoolAnim { + last_value, + last_tick, + } = anim; + let current_time = input.time; + let elapsed = ((current_time - *last_tick) as f32).at_most(input.stable_dt); + let new_value = *last_value + (end - start) * elapsed / animation_time; + *last_value = if new_value.is_finite() { + new_value.clamp(0.0, 1.0) } else { - remap_clamp(time_since_toggle, 0.0..=animation_time, 1.0..=0.0) - } + end + }; + *last_tick = current_time; + *last_value } } }