pierro/widget/
animation.rs1
2use crate::{Color, Id, Vec2, UI};
3
4pub trait Animatable: Copy + Clone + Default {
5
6 fn similar(&self, other: Self) -> bool;
7 fn lerp(&self, other: Self, t: f32) -> Self;
8
9}
10
11#[derive(Default)]
12struct AnimationState<T: Animatable>(T);
13
14pub fn animate<T: Animatable + 'static>(ui: &mut UI, node: Id, target: T, rate: f32) -> T {
15 if !ui.memory().has::<AnimationState<T>>(node) {
16 ui.memory().get::<AnimationState<T>>(node).0 = target;
17 return target;
18 }
19
20 let state = ui.memory().get::<AnimationState<T>>(node);
21 state.0 = state.0.lerp(target, rate);
22 let value = state.0;
23 if !state.0.similar(target) {
24 ui.request_redraw();
25 value
26 } else {
27 state.0 = target;
28 target
29 }
30}
31
32impl Animatable for f32 {
33
34 fn similar(&self, other: Self) -> bool {
35 (*self - other).abs() < 0.005
36 }
37
38 fn lerp(&self, other: Self, t: f32) -> Self {
39 *self + (other - *self) * t
40 }
41
42}
43
44impl Animatable for Vec2 {
45
46 fn similar(&self, other: Self) -> bool {
47 self.distance(other) < 0.05
48 }
49
50 fn lerp(&self, other: Self, t: f32) -> Self {
51 *self + (other - *self) * t
52 }
53
54}
55
56impl Animatable for Color {
57
58 fn similar(&self, other: Self) -> bool {
59 self.r.similar(other.r) && self.g.similar(other.g) && self.b.similar(other.b) && self.a.similar(other.a)
60 }
61
62 fn lerp(&self, other: Self, t: f32) -> Self {
63 Self::rgba(
64 self.r.lerp(other.r, t),
65 self.g.lerp(other.g, t),
66 self.b.lerp(other.b, t),
67 self.a.lerp(other.a, t)
68 )
69 }
70
71}