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