1 /**
2  * @file lv_anim_timeline.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_anim_timeline.h"
10 #include "lv_mem.h"
11 #include "lv_assert.h"
12 
13 /*********************
14  *      DEFINES
15  *********************/
16 
17 /**********************
18  *      TYPEDEFS
19  **********************/
20 
21 /*Data of anim_timeline_dsc*/
22 typedef struct {
23     lv_anim_t anim;
24     uint32_t start_time;
25 } lv_anim_timeline_dsc_t;
26 
27 /*Data of anim_timeline*/
28 struct _lv_anim_timeline_t {
29     lv_anim_timeline_dsc_t * anim_dsc;  /**< Dynamically allocated anim dsc array*/
30     uint32_t anim_dsc_cnt;              /**< The length of anim dsc array*/
31     bool reverse;                       /**< Reverse playback*/
32 };
33 
34 /**********************
35  *  STATIC PROTOTYPES
36  **********************/
37 static void lv_anim_timeline_virtual_exec_cb(void * var, int32_t v);
38 
39 /**********************
40  *  STATIC VARIABLES
41  **********************/
42 
43 /**********************
44  *      MACROS
45  **********************/
46 
47 /**********************
48  *   GLOBAL FUNCTIONS
49  **********************/
50 
lv_anim_timeline_create(void)51 lv_anim_timeline_t * lv_anim_timeline_create(void)
52 {
53     lv_anim_timeline_t * at = (lv_anim_timeline_t *)lv_mem_alloc(sizeof(lv_anim_timeline_t));
54 
55     LV_ASSERT_MALLOC(at);
56 
57     if(at) lv_memset_00(at, sizeof(lv_anim_timeline_t));
58 
59     return at;
60 }
61 
lv_anim_timeline_del(lv_anim_timeline_t * at)62 void lv_anim_timeline_del(lv_anim_timeline_t * at)
63 {
64     LV_ASSERT_NULL(at);
65 
66     lv_anim_timeline_stop(at);
67 
68     lv_mem_free(at->anim_dsc);
69     lv_mem_free(at);
70 }
71 
lv_anim_timeline_add(lv_anim_timeline_t * at,uint32_t start_time,lv_anim_t * a)72 void lv_anim_timeline_add(lv_anim_timeline_t * at, uint32_t start_time, lv_anim_t * a)
73 {
74     LV_ASSERT_NULL(at);
75 
76     at->anim_dsc_cnt++;
77     at->anim_dsc = lv_mem_realloc(at->anim_dsc, at->anim_dsc_cnt * sizeof(lv_anim_timeline_dsc_t));
78 
79     LV_ASSERT_MALLOC(at->anim_dsc);
80 
81     at->anim_dsc[at->anim_dsc_cnt - 1].anim = *a;
82     at->anim_dsc[at->anim_dsc_cnt - 1].start_time = start_time;
83 
84     /*Add default var and virtual exec_cb, used to delete animation.*/
85     if(a->var == NULL && a->exec_cb == NULL) {
86         at->anim_dsc[at->anim_dsc_cnt - 1].anim.var = at;
87         at->anim_dsc[at->anim_dsc_cnt - 1].anim.exec_cb = lv_anim_timeline_virtual_exec_cb;
88     }
89 }
90 
lv_anim_timeline_start(lv_anim_timeline_t * at)91 uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at)
92 {
93     LV_ASSERT_NULL(at);
94 
95     const uint32_t playtime = lv_anim_timeline_get_playtime(at);
96     bool reverse = at->reverse;
97 
98     for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
99         lv_anim_t a = at->anim_dsc[i].anim;
100         uint32_t start_time = at->anim_dsc[i].start_time;
101 
102         if(reverse) {
103             int32_t temp = a.start_value;
104             a.start_value = a.end_value;
105             a.end_value = temp;
106             lv_anim_set_delay(&a, playtime - (start_time + a.time));
107         }
108         else {
109             lv_anim_set_delay(&a, start_time);
110         }
111 
112         lv_anim_start(&a);
113     }
114 
115     return playtime;
116 }
117 
lv_anim_timeline_stop(lv_anim_timeline_t * at)118 void lv_anim_timeline_stop(lv_anim_timeline_t * at)
119 {
120     LV_ASSERT_NULL(at);
121 
122     for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
123         lv_anim_t * a = &(at->anim_dsc[i].anim);
124         lv_anim_del(a->var, a->exec_cb);
125     }
126 }
127 
lv_anim_timeline_set_reverse(lv_anim_timeline_t * at,bool reverse)128 void lv_anim_timeline_set_reverse(lv_anim_timeline_t * at, bool reverse)
129 {
130     LV_ASSERT_NULL(at);
131     at->reverse = reverse;
132 }
133 
lv_anim_timeline_set_progress(lv_anim_timeline_t * at,uint16_t progress)134 void lv_anim_timeline_set_progress(lv_anim_timeline_t * at, uint16_t progress)
135 {
136     LV_ASSERT_NULL(at);
137 
138     const uint32_t playtime = lv_anim_timeline_get_playtime(at);
139     const uint32_t act_time = progress * playtime / 0xFFFF;
140 
141     for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
142         lv_anim_t * a = &(at->anim_dsc[i].anim);
143 
144         if(a->exec_cb == NULL) {
145             continue;
146         }
147 
148         uint32_t start_time = at->anim_dsc[i].start_time;
149         int32_t value = 0;
150 
151         if(act_time < start_time) {
152             value = a->start_value;
153         }
154         else if(act_time < (start_time + a->time)) {
155             a->act_time = act_time - start_time;
156             value = a->path_cb(a);
157         }
158         else {
159             value = a->end_value;
160         }
161 
162         a->exec_cb(a->var, value);
163     }
164 }
165 
lv_anim_timeline_get_playtime(lv_anim_timeline_t * at)166 uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t * at)
167 {
168     LV_ASSERT_NULL(at);
169 
170     uint32_t playtime = 0;
171     for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) {
172         uint32_t end = lv_anim_get_playtime(&at->anim_dsc[i].anim);
173         if(end == LV_ANIM_PLAYTIME_INFINITE)
174             return end;
175         end += at->anim_dsc[i].start_time;
176         if(end > playtime) {
177             playtime = end;
178         }
179     }
180 
181     return playtime;
182 }
183 
lv_anim_timeline_get_reverse(lv_anim_timeline_t * at)184 bool lv_anim_timeline_get_reverse(lv_anim_timeline_t * at)
185 {
186     LV_ASSERT_NULL(at);
187     return at->reverse;
188 }
189 
190 /**********************
191  *   STATIC FUNCTIONS
192  **********************/
193 
lv_anim_timeline_virtual_exec_cb(void * var,int32_t v)194 static void lv_anim_timeline_virtual_exec_cb(void * var, int32_t v)
195 {
196     LV_UNUSED(var);
197     LV_UNUSED(v);
198 }
199