mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
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:
parent
1320f4fc02
commit
ce99983d4f
@ -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 void resolve_time(lv_anim_t * a);
|
||||
static bool remove_concurrent_anims(lv_anim_t * a_current);
|
||||
static bool delete_core(void * var, void * cb, bool custom_exec_cb);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -105,12 +106,17 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a)
|
||||
new_anim->end_value += v_ofs;
|
||||
|
||||
/*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);
|
||||
|
||||
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.
|
||||
@ -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)
|
||||
{
|
||||
|
||||
if(a->repeat_cnt == LV_ANIM_REPEAT_INFINITE)
|
||||
if(a->repeat_cnt == LV_ANIM_REPEAT_INFINITE) {
|
||||
return LV_ANIM_PLAYTIME_INFINITE;
|
||||
}
|
||||
|
||||
uint32_t repeate_cnt = a->repeat_cnt;
|
||||
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)
|
||||
{
|
||||
lv_anim_t * a;
|
||||
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;
|
||||
return delete_core(var, exec_cb, false);
|
||||
}
|
||||
|
||||
void lv_anim_delete_all(void)
|
||||
@ -392,6 +378,7 @@ static void anim_timer(lv_timer_t * param)
|
||||
a->current_value = new_value;
|
||||
/*Apply the calculated 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*/
|
||||
@ -514,7 +501,7 @@ static void resolve_time(lv_anim_t * a)
|
||||
*/
|
||||
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;
|
||||
bool del_any = false;
|
||||
@ -524,7 +511,8 @@ static bool remove_concurrent_anims(lv_anim_t * a_current)
|
||||
if(a != a_current &&
|
||||
(a->act_time >= 0 || a->early_apply) &&
|
||||
(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);
|
||||
if(a->deleted_cb != NULL) a->deleted_cb(a);
|
||||
lv_free(a);
|
||||
@ -542,3 +530,29 @@ static bool remove_concurrent_anims(lv_anim_t * a_current)
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -134,8 +134,10 @@ typedef struct _lv_anim_bezier3_para_t {
|
||||
|
||||
/** Describes an animation*/
|
||||
typedef struct _lv_anim_t {
|
||||
void * var; /**<Variable to animate*/
|
||||
lv_anim_exec_xcb_t exec_cb; /**< Function to execute to animate*/
|
||||
void * var; /**<Variable 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_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*/
|
||||
@ -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 *`.
|
||||
* 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.
|
||||
* The variable to animate can be stored in the animation's `user_data`
|
||||
* @param a pointer to an initialized `lv_anim_t` variable
|
||||
* @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)
|
||||
{
|
||||
a->var = a;
|
||||
a->exec_cb = (lv_anim_exec_xcb_t)exec_cb;
|
||||
a->custom_exec_cb = 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 exec_cb a function pointer which is animating '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
|
Loading…
x
Reference in New Issue
Block a user