feat(anim): save custom_exec_cb in its own field
It allows deleting custom exec animations based on var an callbacks
This commit is contained in:
@@ -39,6 +39,7 @@ static int32_t lv_anim_path_cubic_bezier(const lv_anim_t * a, int32_t x1,
|
|||||||
static uint32_t convert_speed_to_time(uint32_t speed, int32_t start, int32_t end);
|
static uint32_t convert_speed_to_time(uint32_t speed, int32_t start, int32_t end);
|
||||||
static void resolve_time(lv_anim_t * a);
|
static void resolve_time(lv_anim_t * a);
|
||||||
static bool remove_concurrent_anims(lv_anim_t * a_current);
|
static bool remove_concurrent_anims(lv_anim_t * a_current);
|
||||||
|
static bool delete_core(void * var, void * cb, bool custom_exec_cb);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
@@ -105,12 +106,17 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a)
|
|||||||
new_anim->end_value += v_ofs;
|
new_anim->end_value += v_ofs;
|
||||||
|
|
||||||
/*Do not let two animations for the same 'var' with the same 'exec_cb'*/
|
/*Do not let two animations for the same 'var' with the same 'exec_cb'*/
|
||||||
if(a->exec_cb != NULL) remove_concurrent_anims(new_anim);
|
if(a->exec_cb || a->custom_exec_cb) remove_concurrent_anims(new_anim);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_time(new_anim);
|
resolve_time(new_anim);
|
||||||
|
|
||||||
if(new_anim->exec_cb && new_anim->var) new_anim->exec_cb(new_anim->var, new_anim->start_value);
|
if(new_anim->exec_cb && new_anim->var) {
|
||||||
|
new_anim->exec_cb(new_anim->var, new_anim->start_value);
|
||||||
|
}
|
||||||
|
if(new_anim->custom_exec_cb && new_anim->var) {
|
||||||
|
new_anim->custom_exec_cb(new_anim, new_anim->start_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Creating an animation changed the linked list.
|
/*Creating an animation changed the linked list.
|
||||||
@@ -123,9 +129,9 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a)
|
|||||||
|
|
||||||
uint32_t lv_anim_get_playtime(lv_anim_t * a)
|
uint32_t lv_anim_get_playtime(lv_anim_t * a)
|
||||||
{
|
{
|
||||||
|
if(a->repeat_cnt == LV_ANIM_REPEAT_INFINITE) {
|
||||||
if(a->repeat_cnt == LV_ANIM_REPEAT_INFINITE)
|
|
||||||
return LV_ANIM_PLAYTIME_INFINITE;
|
return LV_ANIM_PLAYTIME_INFINITE;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t repeate_cnt = a->repeat_cnt;
|
uint32_t repeate_cnt = a->repeat_cnt;
|
||||||
if(repeate_cnt < 1) repeate_cnt = 1;
|
if(repeate_cnt < 1) repeate_cnt = 1;
|
||||||
@@ -137,27 +143,7 @@ uint32_t lv_anim_get_playtime(lv_anim_t * a)
|
|||||||
|
|
||||||
bool lv_anim_delete(void * var, lv_anim_exec_xcb_t exec_cb)
|
bool lv_anim_delete(void * var, lv_anim_exec_xcb_t exec_cb)
|
||||||
{
|
{
|
||||||
lv_anim_t * a;
|
return delete_core(var, exec_cb, false);
|
||||||
bool del_any = false;
|
|
||||||
a = _lv_ll_get_head(anim_ll_p);
|
|
||||||
while(a != NULL) {
|
|
||||||
bool del = false;
|
|
||||||
if((a->var == var || var == NULL) && (a->exec_cb == exec_cb || exec_cb == NULL)) {
|
|
||||||
_lv_ll_remove(anim_ll_p, a);
|
|
||||||
if(a->deleted_cb != NULL) a->deleted_cb(a);
|
|
||||||
lv_free(a);
|
|
||||||
anim_mark_list_change(); /*Read by `anim_timer`. It need to know if a delete occurred in
|
|
||||||
the linked list*/
|
|
||||||
del_any = true;
|
|
||||||
del = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Always start from the head on delete, because we don't know
|
|
||||||
*how `anim_ll_p` was changes in `a->deleted_cb` */
|
|
||||||
a = del ? _lv_ll_get_head(anim_ll_p) : _lv_ll_get_next(anim_ll_p, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
return del_any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv_anim_delete_all(void)
|
void lv_anim_delete_all(void)
|
||||||
@@ -392,6 +378,7 @@ static void anim_timer(lv_timer_t * param)
|
|||||||
a->current_value = new_value;
|
a->current_value = new_value;
|
||||||
/*Apply the calculated value*/
|
/*Apply the calculated value*/
|
||||||
if(a->exec_cb) a->exec_cb(a->var, new_value);
|
if(a->exec_cb) a->exec_cb(a->var, new_value);
|
||||||
|
if(a->custom_exec_cb) a->custom_exec_cb(a, new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*If the time is elapsed the animation is ready*/
|
/*If the time is elapsed the animation is ready*/
|
||||||
@@ -514,7 +501,7 @@ static void resolve_time(lv_anim_t * a)
|
|||||||
*/
|
*/
|
||||||
static bool remove_concurrent_anims(lv_anim_t * a_current)
|
static bool remove_concurrent_anims(lv_anim_t * a_current)
|
||||||
{
|
{
|
||||||
if(a_current->exec_cb == NULL) return false;
|
if(a_current->exec_cb == NULL && a_current->custom_exec_cb == NULL) return false;
|
||||||
|
|
||||||
lv_anim_t * a;
|
lv_anim_t * a;
|
||||||
bool del_any = false;
|
bool del_any = false;
|
||||||
@@ -524,7 +511,8 @@ static bool remove_concurrent_anims(lv_anim_t * a_current)
|
|||||||
if(a != a_current &&
|
if(a != a_current &&
|
||||||
(a->act_time >= 0 || a->early_apply) &&
|
(a->act_time >= 0 || a->early_apply) &&
|
||||||
(a->var == a_current->var) &&
|
(a->var == a_current->var) &&
|
||||||
(a->exec_cb == a_current->exec_cb)) {
|
((a->exec_cb && a->exec_cb == a_current->exec_cb) ||
|
||||||
|
(a->custom_exec_cb && a->custom_exec_cb == a_current->custom_exec_cb))) {
|
||||||
_lv_ll_remove(anim_ll_p, a);
|
_lv_ll_remove(anim_ll_p, a);
|
||||||
if(a->deleted_cb != NULL) a->deleted_cb(a);
|
if(a->deleted_cb != NULL) a->deleted_cb(a);
|
||||||
lv_free(a);
|
lv_free(a);
|
||||||
@@ -542,3 +530,29 @@ static bool remove_concurrent_anims(lv_anim_t * a_current)
|
|||||||
|
|
||||||
return del_any;
|
return del_any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool delete_core(void * var, void * cb, bool custom_exec_cb)
|
||||||
|
{
|
||||||
|
lv_anim_t * a;
|
||||||
|
bool del_any = false;
|
||||||
|
a = _lv_ll_get_head(anim_ll_p);
|
||||||
|
while(a != NULL) {
|
||||||
|
bool del = false;
|
||||||
|
void * a_cb = custom_exec_cb ? (void *)a->custom_exec_cb : (void *)a->exec_cb;
|
||||||
|
if((a->var == var || var == NULL) && (a_cb == cb || cb == NULL)) {
|
||||||
|
_lv_ll_remove(anim_ll_p, a);
|
||||||
|
if(a->deleted_cb != NULL) a->deleted_cb(a);
|
||||||
|
lv_free(a);
|
||||||
|
anim_mark_list_change(); /*Read by `anim_timer`. It need to know if a delete occurred in
|
||||||
|
the linked list*/
|
||||||
|
del_any = true;
|
||||||
|
del = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Always start from the head on delete, because we don't know
|
||||||
|
*how `anim_ll_p` was changes in `a->deleted_cb` */
|
||||||
|
a = del ? _lv_ll_get_head(anim_ll_p) : _lv_ll_get_next(anim_ll_p, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return del_any;
|
||||||
|
}
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ typedef struct _lv_anim_bezier3_para_t {
|
|||||||
typedef struct _lv_anim_t {
|
typedef struct _lv_anim_t {
|
||||||
void * var; /**<Variable to animate*/
|
void * var; /**<Variable to animate*/
|
||||||
lv_anim_exec_xcb_t exec_cb; /**< Function to execute to animate*/
|
lv_anim_exec_xcb_t exec_cb; /**< Function to execute to animate*/
|
||||||
|
lv_anim_custom_exec_cb_t custom_exec_cb;/**< Function to execute to animate,
|
||||||
|
same purpose as exec_cb but different parameters*/
|
||||||
lv_anim_start_cb_t start_cb; /**< Call it when the animation is starts (considering `delay`)*/
|
lv_anim_start_cb_t start_cb; /**< Call it when the animation is starts (considering `delay`)*/
|
||||||
lv_anim_ready_cb_t ready_cb; /**< Call it when the animation is ready*/
|
lv_anim_ready_cb_t ready_cb; /**< Call it when the animation is ready*/
|
||||||
lv_anim_deleted_cb_t deleted_cb; /**< Call it when the animation is deleted*/
|
lv_anim_deleted_cb_t deleted_cb; /**< Call it when the animation is deleted*/
|
||||||
@@ -249,14 +251,12 @@ static inline void lv_anim_set_values(lv_anim_t * a, int32_t start, int32_t end)
|
|||||||
* `lv_anim_t * ` as its first parameter instead of `void *`.
|
* `lv_anim_t * ` as its first parameter instead of `void *`.
|
||||||
* This function might be used when LVGL is bound to other languages because
|
* This function might be used when LVGL is bound to other languages because
|
||||||
* it's more consistent to have `lv_anim_t *` as first parameter.
|
* it's more consistent to have `lv_anim_t *` as first parameter.
|
||||||
* The variable to animate can be stored in the animation's `user_data`
|
|
||||||
* @param a pointer to an initialized `lv_anim_t` variable
|
* @param a pointer to an initialized `lv_anim_t` variable
|
||||||
* @param exec_cb a function to execute.
|
* @param exec_cb a function to execute.
|
||||||
*/
|
*/
|
||||||
static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb)
|
static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec_cb_t exec_cb)
|
||||||
{
|
{
|
||||||
a->var = a;
|
a->custom_exec_cb = exec_cb;
|
||||||
a->exec_cb = (lv_anim_exec_xcb_t)exec_cb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -443,7 +443,7 @@ static inline void * lv_anim_get_user_data(lv_anim_t * a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an animation of a variable with a given animator function
|
* Delete animation(s) of a variable with a given animator function
|
||||||
* @param var pointer to variable
|
* @param var pointer to variable
|
||||||
* @param exec_cb a function pointer which is animating 'var',
|
* @param exec_cb a function pointer which is animating 'var',
|
||||||
* or NULL to ignore it and delete all the animations of 'var
|
* or NULL to ignore it and delete all the animations of 'var
|
||||||
|
|||||||
93
tests/src/test_cases/test_anim.c
Normal file
93
tests/src/test_cases/test_anim.c
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#if LV_BUILD_TEST || 1
|
||||||
|
#include "../lvgl.h"
|
||||||
|
|
||||||
|
#include "unity/unity.h"
|
||||||
|
#include "lv_test_helpers.h"
|
||||||
|
|
||||||
|
void setUp(void)
|
||||||
|
{
|
||||||
|
/* Function run before every test */
|
||||||
|
}
|
||||||
|
|
||||||
|
void tearDown(void)
|
||||||
|
{
|
||||||
|
/* Function run after every test */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exec_cb(void * var, int32_t v)
|
||||||
|
{
|
||||||
|
int32_t * var_i32 = var;
|
||||||
|
*var_i32 = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void custom_exec_cb(lv_anim_t * a, int32_t v)
|
||||||
|
{
|
||||||
|
int32_t * var_i32 = a->var;
|
||||||
|
*var_i32 = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_anim_delete(void)
|
||||||
|
{
|
||||||
|
int32_t var;
|
||||||
|
|
||||||
|
/*Start an animation*/
|
||||||
|
lv_anim_t a;
|
||||||
|
lv_anim_init(&a);
|
||||||
|
lv_anim_set_var(&a, &var);
|
||||||
|
lv_anim_set_values(&a, 0, 100);
|
||||||
|
lv_anim_set_exec_cb(&a, exec_cb);
|
||||||
|
lv_anim_set_time(&a, 100);
|
||||||
|
lv_anim_start(&a);
|
||||||
|
|
||||||
|
lv_test_wait(20);
|
||||||
|
TEST_ASSERT_EQUAL(19, var);
|
||||||
|
|
||||||
|
bool deleted;
|
||||||
|
/*Wrong variable, nothing should happen*/
|
||||||
|
deleted = lv_anim_delete(&a, exec_cb);
|
||||||
|
TEST_ASSERT_FALSE(deleted);
|
||||||
|
|
||||||
|
lv_test_wait(20);
|
||||||
|
TEST_ASSERT_EQUAL(39, var);
|
||||||
|
|
||||||
|
/*The value shouldn't change after delete*/
|
||||||
|
deleted = lv_anim_delete(&var, exec_cb);
|
||||||
|
TEST_ASSERT_TRUE(deleted);
|
||||||
|
|
||||||
|
lv_test_wait(20);
|
||||||
|
TEST_ASSERT_EQUAL(39, var);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_anim_delete_custom(void)
|
||||||
|
{
|
||||||
|
int32_t var;
|
||||||
|
|
||||||
|
/*Start an animation*/
|
||||||
|
lv_anim_t a;
|
||||||
|
lv_anim_init(&a);
|
||||||
|
lv_anim_set_var(&a, &var);
|
||||||
|
lv_anim_set_values(&a, 0, 100);
|
||||||
|
lv_anim_set_custom_exec_cb(&a, custom_exec_cb);
|
||||||
|
lv_anim_set_time(&a, 100);
|
||||||
|
lv_anim_start(&a);
|
||||||
|
|
||||||
|
lv_test_wait(20);
|
||||||
|
TEST_ASSERT_EQUAL(19, var);
|
||||||
|
|
||||||
|
bool deleted;
|
||||||
|
/*Wrong callback, nothing should happen*/
|
||||||
|
deleted = lv_anim_delete(&var, exec_cb);
|
||||||
|
TEST_ASSERT_FALSE(deleted);
|
||||||
|
|
||||||
|
lv_test_wait(20);
|
||||||
|
TEST_ASSERT_EQUAL(39, var);
|
||||||
|
|
||||||
|
/*The value shouldn't change after delete*/
|
||||||
|
deleted = lv_anim_delete(&var, NULL);
|
||||||
|
TEST_ASSERT_TRUE(deleted);
|
||||||
|
|
||||||
|
lv_test_wait(20);
|
||||||
|
TEST_ASSERT_EQUAL(39, var);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user