tuigui/widgets/
animation_container.rs1use crate::preludes::widget_creation::*;
2
3#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
4pub enum AnimationContainerSequence<A: crate::Animation> {
5 Single(A),
6 Many(Vec<A>),
7}
8
9#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
10pub struct AnimationContainer<W: Widget, A: crate::Animation> {
12 pub widget: W,
13 pub sequence: AnimationContainerSequence<A>,
14 index: usize,
15 prev_transform: Option<Transform>,
16 new_start_transform: Option<Transform>,
17 is_playing: bool,
18 paused_time: Option<std::time::Instant>,
19 paused_duration: std::time::Duration,
20 is_done: bool,
21 widget_data: WidgetData,
22}
23
24impl<W: Widget, A: crate::Animation> AnimationContainer<W, A> {
25 pub fn new(sequence: AnimationContainerSequence<A>, autoplay: bool, widget: W) -> Self {
27 Self {
28 widget,
29 sequence,
30 index: 0,
31 prev_transform: None,
32 new_start_transform: None,
33 is_playing: autoplay,
34 paused_time: None,
35 paused_duration: std::time::Duration::ZERO,
36 is_done: false,
37 widget_data: WidgetData::new(),
38 }
39 }
40
41 pub fn play(&mut self) {
43 if self.is_playing == false {
44 self.is_playing = true;
45
46 if let Some(paused_time) = self.paused_time {
47 let duration = std::time::Instant::now() - paused_time;
48
49 self.paused_duration += duration;
50 }
51
52 else {
53 self.soft_reset();
54 }
55 }
56 }
57
58 pub fn pause(&mut self) {
60 if self.is_playing {
61 self.is_playing = false;
62 self.paused_time = Some(std::time::Instant::now());
63 }
64 }
65
66 pub fn is_playing(&self) -> bool {
68 return self.is_playing;
69 }
70
71 pub fn has_finished(&self) -> bool {
73 return self.is_done;
74 }
75
76 pub fn reset(&mut self, autoplay: bool) {
78 self.index = 0;
79 self.is_done = false;
80 self.is_playing = autoplay;
81 self.soft_reset();
82 }
83
84 fn soft_reset(&mut self) {
85 self.paused_time = None;
86 self.paused_duration = std::time::Duration::ZERO;
87 self.widget.widget_data().animation_data.reset();
88 }
89}
90
91impl<W: Widget, A: crate::Animation> Widget for AnimationContainer<W, A> {
92 fn draw(&mut self, canvas: &mut Canvas, state_frame: Option<&EventStateFrame>) {
93 let is_playing = self.is_playing();
94 let is_done = self.has_finished();
95
96 let child_data = self.widget.widget_data();
97
98 let static_rest = self.prev_transform.unwrap_or(canvas.original_transform());
101
102 if is_playing && is_done == false {
103 let offset: f64 = -self.paused_duration.as_secs_f64();
104
105 let (animation, is_single) = match self.sequence {
106 AnimationContainerSequence::Single(ref mut single) => (Some(single), true),
107 AnimationContainerSequence::Many(ref mut many) => (many.get_mut(self.index), false),
108 };
109
110 if let Some(animation) = animation {
111 canvas.animate_with_offset(
112 animation,
113 &child_data.animation_data,
114 self.new_start_transform,
115 offset
116 );
117
118 self.prev_transform = Some(canvas.transform);
119
120 if animation.is_done(
121 child_data.animation_data.duration()
122 .as_secs_f64() + offset,
123 ) {
124 if is_single {
125 self.is_done = true;
126 } else {
127 self.index += 1;
128 self.new_start_transform = Some(canvas.transform);
129 self.soft_reset();
130 }
131 }
132 }
133
134 else {
135 self.is_done = true;
136 canvas.transform = static_rest;
137 }
138 }
139
140 else {
141 canvas.transform = static_rest;
142 }
143
144 self.widget.draw(canvas, state_frame);
145 }
146
147 fn widget_info(&self) -> WidgetInfo {
148 return self.widget.widget_info();
149 }
150
151 fn widget_data(&mut self) -> &mut WidgetData {
152 return &mut self.widget_data;
153 }
154}