1 /**
2  * @file lv_anim_timeline.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_anim_private.h"
10 #include "lv_assert.h"
11 #include "lv_anim_timeline.h"
12 #include "../stdlib/lv_mem.h"
13 #include "../stdlib/lv_string.h"
14 
15 /*********************
16  *      DEFINES
17  *********************/
18 
19 /**********************
20  *      TYPEDEFS
21  **********************/
22 /*Data of anim_timeline_dsc*/
23 typedef struct {
24     lv_anim_t anim;
25     uint32_t start_time;
26     uint8_t is_started : 1;
27     uint8_t is_completed : 1;
28 } lv_anim_timeline_dsc_t;
29 
30 /*Data of anim_timeline*/
31 struct _lv_anim_timeline_t {
32     lv_anim_timeline_dsc_t * anim_dsc;  /**< Dynamically allocated anim dsc array*/
33     uint32_t anim_dsc_cnt;              /**< The length of anim dsc array*/
34     uint32_t act_time;                  /**< Current time of the animation*/
35     bool reverse;                       /**< Reverse playback*/
36     uint32_t repeat_count;              /**< Repeat count*/
37     uint32_t repeat_delay;              /**< Wait before repeat*/
38 };
39 
40 /**********************
41  *  STATIC PROTOTYPES
42  **********************/
43 static void anim_timeline_exec_cb(void * var, int32_t v);
44 static void anim_timeline_set_act_time(lv_anim_timeline_t * at, uint32_t act_time);
45 static int32_t anim_timeline_path_cb(const lv_anim_t * a);
46 
47 /**********************
48  *  STATIC VARIABLES
49  **********************/
50 
51 /**********************
52  *      MACROS
53  **********************/
54 
55 /**********************
56  *   GLOBAL FUNCTIONS
57  **********************/
58 
lv_anim_timeline_create(void)59 lv_anim_timeline_t * lv_anim_timeline_create(void)
60 {
61     lv_anim_timeline_t * at = lv_malloc_zeroed(sizeof(lv_anim_timeline_t));
62     LV_ASSERT_MALLOC(at);
63     return at;
64 }
65 
lv_anim_timeline_delete(lv_anim_timeline_t * at)66 void lv_anim_timeline_delete(lv_anim_timeline_t * at)
67 {
68     LV_ASSERT_NULL(at);
69 
70     lv_anim_timeline_pause(at);
71 
72     lv_free(at->anim_dsc);
73     lv_free(at);
74 }
75 
lv_anim_timeline_add(lv_anim_timeline_t * at,uint32_t start_time,const lv_anim_t * a)76 void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, const lv_anim_t * a)
77 {
78     LV_ASSERT_NULL(at);
79 
80     at->anim_dsc_cnt++;
81     at->anim_dsc = lv_realloc(at->anim_dsc, at->anim_dsc_cnt * sizeof(lv_anim_timeline_dsc_t));
82 
83     LV_ASSERT_MALLOC(at->anim_dsc);
84 
85     at->anim_dsc[at->anim_dsc_cnt - 1].anim = *a;
86     at->anim_dsc[at->anim_dsc_cnt - 1].start_time = start_time;
87 }
88 
lv_anim_timeline_start(lv_anim_timeline_t * at)89 uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at)
90 {
91     LV_ASSERT_NULL(at);
92 
93     uint32_t playtime = lv_anim_timeline_get_playtime(at);
94     uint32_t repeat = at->repeat_count;
95     uint32_t delay = at->repeat_delay;
96     uint32_t start = at->act_time;
97     uint32_t end = at->reverse ? 0 : playtime;
98     uint32_t duration = end > start ? end - start : start - end;
99 
100     if((!at->reverse && at->act_time == 0) || (at->reverse && at->act_time == playtime)) {
101         for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
102             at->anim_dsc[i].is_started   = 0;
103             at->anim_dsc[i].is_completed = 0;
104         }
105     }
106 
107     lv_anim_t a;
108     lv_anim_init(&a);
109     lv_anim_set_var(&a, at);
110     lv_anim_set_exec_cb(&a, anim_timeline_exec_cb);
111     lv_anim_set_values(&a, start, end);
112     lv_anim_set_duration(&a, duration);
113     lv_anim_set_path_cb(&a, anim_timeline_path_cb);
114     lv_anim_set_repeat_count(&a, repeat);
115     lv_anim_set_repeat_delay(&a, delay);
116     lv_anim_start(&a);
117     return playtime;
118 }
119 
lv_anim_timeline_pause(lv_anim_timeline_t * at)120 void lv_anim_timeline_pause(lv_anim_timeline_t * at)
121 {
122     LV_ASSERT_NULL(at);
123 
124     lv_anim_delete(at, anim_timeline_exec_cb);
125 }
126 
lv_anim_timeline_set_reverse(lv_anim_timeline_t * at,bool reverse)127 void lv_anim_timeline_set_reverse(lv_anim_timeline_t * at, bool reverse)
128 {
129     LV_ASSERT_NULL(at);
130     at->reverse = reverse;
131 }
132 
lv_anim_timeline_set_repeat_count(lv_anim_timeline_t * at,uint32_t cnt)133 void lv_anim_timeline_set_repeat_count(lv_anim_timeline_t * at, uint32_t cnt)
134 {
135     LV_ASSERT_NULL(at);
136     at->repeat_count = cnt;
137 }
138 
lv_anim_timeline_set_repeat_delay(lv_anim_timeline_t * at,uint32_t delay)139 void lv_anim_timeline_set_repeat_delay(lv_anim_timeline_t * at, uint32_t delay)
140 {
141     LV_ASSERT_NULL(at);
142     at->repeat_delay = delay;
143 }
144 
lv_anim_timeline_set_progress(lv_anim_timeline_t * at,uint16_t progress)145 void lv_anim_timeline_set_progress(lv_anim_timeline_t * at, uint16_t progress)
146 {
147     LV_ASSERT_NULL(at);
148 
149     uint32_t playtime = lv_anim_timeline_get_playtime(at);
150     uint32_t act_time = lv_map(progress, 0, LV_ANIM_TIMELINE_PROGRESS_MAX, 0, playtime);
151     anim_timeline_set_act_time(at, act_time);
152 }
153 
lv_anim_timeline_get_playtime(lv_anim_timeline_t * at)154 uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at)
155 {
156     LV_ASSERT_NULL(at);
157 
158     uint32_t playtime = 0;
159     for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
160         uint32_t end = lv_anim_get_playtime(&at->anim_dsc[i].anim);
161         if(end == LV_ANIM_PLAYTIME_INFINITE)
162             return end;
163         end += at->anim_dsc[i].start_time;
164         if(end > playtime) {
165             playtime = end;
166         }
167     }
168 
169     return playtime;
170 }
171 
lv_anim_timeline_get_reverse(lv_anim_timeline_t * at)172 bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at)
173 {
174     LV_ASSERT_NULL(at);
175     return at->reverse;
176 }
177 
lv_anim_timeline_get_progress(lv_anim_timeline_t * at)178 uint16_t lv_anim_timeline_get_progress(lv_anim_timeline_t * at)
179 {
180     LV_ASSERT_NULL(at);
181     uint32_t playtime = lv_anim_timeline_get_playtime(at);
182     return lv_map(at->act_time, 0, playtime, 0, LV_ANIM_TIMELINE_PROGRESS_MAX);
183 }
184 
lv_anim_timeline_get_repeat_count(lv_anim_timeline_t * at)185 uint32_t lv_anim_timeline_get_repeat_count(lv_anim_timeline_t * at)
186 {
187     LV_ASSERT_NULL(at);
188     return  at->repeat_count;
189 }
190 
lv_anim_timeline_get_repeat_delay(lv_anim_timeline_t * at)191 uint32_t lv_anim_timeline_get_repeat_delay(lv_anim_timeline_t * at)
192 {
193     LV_ASSERT_NULL(at);
194     return  at->repeat_delay;
195 }
196 
197 /**********************
198  *   STATIC FUNCTIONS
199  **********************/
200 
anim_timeline_set_act_time(lv_anim_timeline_t * at,uint32_t act_time)201 static void anim_timeline_set_act_time(lv_anim_timeline_t * at, uint32_t act_time)
202 {
203     at->act_time = act_time;
204     bool anim_timeline_is_started = (lv_anim_get(at, anim_timeline_exec_cb) != NULL);
205     for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
206         lv_anim_timeline_dsc_t * anim_dsc = &(at->anim_dsc[i]);
207         lv_anim_t * a = &(anim_dsc->anim);
208 
209         uint32_t start_time = anim_dsc->start_time;
210         int32_t value = 0;
211 
212         if(act_time < start_time && a->early_apply) {
213             if(anim_timeline_is_started) {
214                 if(at->reverse) {
215                     if(!anim_dsc->is_started && a->start_cb)  a->start_cb(a);
216                     anim_dsc->is_started = 1;
217                 }
218                 else {
219                     anim_dsc->is_started = 0;
220                 }
221             }
222 
223             value = a->start_value;
224             if(a->exec_cb) a->exec_cb(a->var, value);
225             if(a->custom_exec_cb) a->custom_exec_cb(a, value);
226 
227             if(anim_timeline_is_started) {
228                 if(at->reverse) {
229                     if(!anim_dsc->is_completed && a->completed_cb) a->completed_cb(a);
230                     anim_dsc->is_completed = 1;
231                 }
232                 else {
233                     anim_dsc->is_completed = 0;
234                 }
235             }
236         }
237         else if(act_time >= start_time && act_time <= (start_time + a->duration)) {
238             if(anim_timeline_is_started) {
239                 if(!anim_dsc->is_started && a->start_cb) a->start_cb(a);
240                 anim_dsc->is_started = 1;
241             }
242 
243             a->act_time = act_time - start_time;
244             value = a->path_cb(a);
245             if(a->exec_cb) a->exec_cb(a->var, value);
246             if(a->custom_exec_cb) a->custom_exec_cb(a, value);
247 
248             if(anim_timeline_is_started) {
249                 if(at->reverse) {
250                     if(act_time == start_time) {
251                         if(!anim_dsc->is_completed && a->completed_cb) a->completed_cb(a);
252                         anim_dsc->is_completed = 1;
253                     }
254                     else {
255                         anim_dsc->is_completed = 0;
256                     }
257                 }
258                 else {
259                     if(act_time == (start_time + a->duration)) {
260                         if(!anim_dsc->is_completed && a->completed_cb) a->completed_cb(a);
261                         anim_dsc->is_completed = 1;
262                     }
263                     else {
264                         anim_dsc->is_completed = 0;
265                     }
266                 }
267             }
268         }
269         else if(act_time > start_time + a->duration) {
270             if(anim_timeline_is_started) {
271                 if(at->reverse) {
272                     anim_dsc->is_started = 0;
273                 }
274                 else {
275                     if(!anim_dsc->is_started && a->start_cb) a->start_cb(a);
276                     anim_dsc->is_started = 1;
277                 }
278             }
279 
280             value = a->end_value;
281             if(a->exec_cb) a->exec_cb(a->var, value);
282             if(a->custom_exec_cb) a->custom_exec_cb(a, value);
283 
284             if(anim_timeline_is_started) {
285                 if(at->reverse) {
286                     anim_dsc->is_completed = 0;
287                 }
288                 else {
289                     if(!anim_dsc->is_completed && a->completed_cb) a->completed_cb(a);
290                     anim_dsc->is_completed = 1;
291                 }
292             }
293         }
294     }
295 }
296 
anim_timeline_path_cb(const lv_anim_t * a)297 static int32_t anim_timeline_path_cb(const lv_anim_t * a)
298 {
299     /* Directly map original timestamps to avoid loss of accuracy */
300     return lv_map(a->act_time, 0, a->duration, a->start_value, a->end_value);
301 }
302 
anim_timeline_exec_cb(void * var,int32_t v)303 static void anim_timeline_exec_cb(void * var, int32_t v)
304 {
305     lv_anim_timeline_t * at = var;
306     anim_timeline_set_act_time(at, v);
307 }
308