egui/
animation_manager.rs
1use crate::{
2 emath::{remap_clamp, NumExt as _},
3 Id, IdMap, InputState,
4};
5
6#[derive(Clone, Default)]
7pub(crate) struct AnimationManager {
8 bools: IdMap<BoolAnim>,
9 values: IdMap<ValueAnim>,
10}
11
12#[derive(Clone, Debug)]
13struct BoolAnim {
14 last_value: f32,
15 last_tick: f64,
16}
17
18#[derive(Clone, Debug)]
19struct ValueAnim {
20 from_value: f32,
21
22 to_value: f32,
23
24 toggle_time: f64,
26}
27
28impl AnimationManager {
29 pub fn animate_bool(
31 &mut self,
32 input: &InputState,
33 animation_time: f32,
34 id: Id,
35 value: bool,
36 ) -> f32 {
37 let (start, end) = if value { (0.0, 1.0) } else { (1.0, 0.0) };
38 match self.bools.get_mut(&id) {
39 None => {
40 self.bools.insert(
41 id,
42 BoolAnim {
43 last_value: end,
44 last_tick: input.time - input.stable_dt as f64,
45 },
46 );
47 end
48 }
49 Some(anim) => {
50 let BoolAnim {
51 last_value,
52 last_tick,
53 } = anim;
54 let current_time = input.time;
55 let elapsed = ((current_time - *last_tick) as f32).at_most(input.stable_dt);
56 let new_value = *last_value + (end - start) * elapsed / animation_time;
57 *last_value = if new_value.is_finite() {
58 new_value.clamp(0.0, 1.0)
59 } else {
60 end
61 };
62 *last_tick = current_time;
63 *last_value
64 }
65 }
66 }
67
68 pub fn animate_value(
69 &mut self,
70 input: &InputState,
71 animation_time: f32,
72 id: Id,
73 value: f32,
74 ) -> f32 {
75 match self.values.get_mut(&id) {
76 None => {
77 self.values.insert(
78 id,
79 ValueAnim {
80 from_value: value,
81 to_value: value,
82 toggle_time: -f64::INFINITY, },
84 );
85 value
86 }
87 Some(anim) => {
88 let time_since_toggle = (input.time - anim.toggle_time) as f32;
89 let time_since_toggle = time_since_toggle + input.predicted_dt / 2.0;
92 let current_value = remap_clamp(
93 time_since_toggle,
94 0.0..=animation_time,
95 anim.from_value..=anim.to_value,
96 );
97 if anim.to_value != value {
98 anim.from_value = current_value; anim.to_value = value;
100 anim.toggle_time = input.time;
101 }
102 if animation_time == 0.0 {
103 anim.from_value = value;
104 anim.to_value = value;
105 }
106 current_value
107 }
108 }
109 }
110}