From b44bcaee17b7ed37fd808a86fc9cd0c91e851e28 Mon Sep 17 00:00:00 2001 From: TridentTD Date: Thu, 9 May 2024 16:32:59 +0700 Subject: [PATCH] feat(anim_timeline): add anim's `completed_cb` support (#6085) --- src/misc/lv_anim_timeline.c | 82 ++++++++++++- tests/src/test_cases/test_anim_timeline.c | 139 +++++++++++++++++++++- 2 files changed, 218 insertions(+), 3 deletions(-) diff --git a/src/misc/lv_anim_timeline.c b/src/misc/lv_anim_timeline.c index 0acd24312a..d2e6dff36e 100644 --- a/src/misc/lv_anim_timeline.c +++ b/src/misc/lv_anim_timeline.c @@ -22,6 +22,8 @@ typedef struct { lv_anim_t anim; uint32_t start_time; + uint8_t is_started : 1; + uint8_t is_completed : 1; } lv_anim_timeline_dsc_t; /*Data of anim_timeline*/ @@ -90,6 +92,13 @@ uint32_t lv_anim_timeline_start(lv_anim_timeline_t * at) uint32_t end = at->reverse ? 0 : playtime; uint32_t duration = end > start ? end - start : start - end; + if((!at->reverse && at->act_time == 0) || (at->reverse && at->act_time == playtime)) { + for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { + at->anim_dsc[i].is_started = 0; + at->anim_dsc[i].is_completed = 0; + } + } + lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, at); @@ -161,30 +170,99 @@ uint16_t lv_anim_timeline_get_progress(lv_anim_timeline_t * at) static void anim_timeline_set_act_time(lv_anim_timeline_t * at, uint32_t act_time) { at->act_time = act_time; + bool anim_timeline_is_started = (lv_anim_get(at, anim_timeline_exec_cb) != NULL); for(uint32_t i = 0; i < at->anim_dsc_cnt; i++) { - lv_anim_t * a = &(at->anim_dsc[i].anim); + lv_anim_timeline_dsc_t * anim_dsc = &(at->anim_dsc[i]); + lv_anim_t * a = &(anim_dsc->anim); if(a->exec_cb == NULL && a->custom_exec_cb == NULL) { continue; } - uint32_t start_time = at->anim_dsc[i].start_time; + uint32_t start_time = anim_dsc->start_time; int32_t value = 0; + if(act_time < start_time && a->early_apply) { + if(anim_timeline_is_started) { + if(at->reverse) { + if(!anim_dsc->is_started && a->start_cb) a->start_cb(a); + anim_dsc->is_started = 1; + } + else { + anim_dsc->is_started = 0; + } + } + value = a->start_value; if(a->exec_cb) a->exec_cb(a->var, value); if(a->custom_exec_cb) a->custom_exec_cb(a, value); + + if(anim_timeline_is_started) { + if(at->reverse) { + if(!anim_dsc->is_completed && a->completed_cb) a->completed_cb(a); + anim_dsc->is_completed = 1; + } + else { + anim_dsc->is_completed = 0; + } + } } else if(act_time >= start_time && act_time <= (start_time + a->duration)) { + if(anim_timeline_is_started) { + if(!anim_dsc->is_started && a->start_cb) a->start_cb(a); + anim_dsc->is_started = 1; + } + a->act_time = act_time - start_time; value = a->path_cb(a); if(a->exec_cb) a->exec_cb(a->var, value); if(a->custom_exec_cb) a->custom_exec_cb(a, value); + + if(anim_timeline_is_started) { + if(at->reverse) { + if(act_time == start_time) { + if(!anim_dsc->is_completed && a->completed_cb) a->completed_cb(a); + anim_dsc->is_completed = 1; + } + else { + anim_dsc->is_completed = 0; + } + } + else { + if(act_time == (start_time + a->duration)) { + if(!anim_dsc->is_completed && a->completed_cb) a->completed_cb(a); + anim_dsc->is_completed = 1; + } + else { + anim_dsc->is_completed = 0; + } + } + } } else if(act_time > start_time + a->duration) { + if(anim_timeline_is_started) { + if(at->reverse) { + anim_dsc->is_started = 0; + } + else { + if(!anim_dsc->is_started && a->start_cb) a->start_cb(a); + anim_dsc->is_started = 1; + } + } + value = a->end_value; if(a->exec_cb) a->exec_cb(a->var, value); if(a->custom_exec_cb) a->custom_exec_cb(a, value); + + if(anim_timeline_is_started) { + if(at->reverse) { + anim_dsc->is_completed = 0; + } + else { + if(!anim_dsc->is_completed && a->completed_cb) a->completed_cb(a); + anim_dsc->is_completed = 1; + } + } } } } diff --git a/tests/src/test_cases/test_anim_timeline.c b/tests/src/test_cases/test_anim_timeline.c index 50edd4e36b..293cd4fe6f 100644 --- a/tests/src/test_cases/test_anim_timeline.c +++ b/tests/src/test_cases/test_anim_timeline.c @@ -7,6 +7,11 @@ static lv_anim_timeline_t * anim_timeline; +static uint32_t anim1_start_called; +static uint32_t anim2_start_called; +static uint32_t anim1_completed_called; +static uint32_t anim2_completed_called; + void setUp(void) { /* Function run before every test */ @@ -18,7 +23,6 @@ void tearDown(void) /* Function run after every test */ if(anim_timeline) lv_anim_timeline_delete(anim_timeline); lv_obj_clean(lv_screen_active()); - } void test_anim_timeline_progress_1(void) @@ -322,4 +326,137 @@ void test_anim_timeline_reverse(void) TEST_ASSERT_EQUAL(20, lv_obj_get_x(obj)); } +void anim1_exec_cb(void * var, int32_t v) +{ + LV_UNUSED(var); + printf("[anim1] %d\n", v); +} +void anim1_start(lv_anim_t * a) +{ + LV_UNUSED(a); + printf("[anim1] start\n"); + anim1_start_called++; +} +void anim1_completed(lv_anim_t * a) +{ + LV_UNUSED(a); + printf("[anim1] completed\n"); + anim1_completed_called++; +} + +void anim2_exec_cb(void * var, int32_t v) +{ + LV_UNUSED(var); + printf(" [anim2] %d\n", v); +} +void anim2_start(lv_anim_t * a) +{ + LV_UNUSED(a); + printf(" [anim2] start\n"); + anim2_start_called++; +} +void anim2_completed(lv_anim_t * a) +{ + LV_UNUSED(a); + printf(" [anim2] completed\n"); + anim2_completed_called++; +} + +void test_anim_timeline_with_anim_start_cb_and_completed_cb(void) +{ + lv_anim_t anim1; + lv_anim_t anim2; + + lv_anim_init(&anim1); + lv_anim_set_values(&anim1, 0, 1024); + lv_anim_set_duration(&anim1, 300); + lv_anim_set_exec_cb(&anim1, anim1_exec_cb); + lv_anim_set_start_cb(&anim1, anim1_start); + lv_anim_set_completed_cb(&anim1, anim1_completed); + anim1_start_called = 0; + anim1_completed_called = 0; + + lv_memcpy(&anim2, &anim1, sizeof(anim1)); + lv_anim_set_duration(&anim2, 300); + lv_anim_set_path_cb(&anim2, lv_anim_path_overshoot); + lv_anim_set_exec_cb(&anim2, anim2_exec_cb); + lv_anim_set_start_cb(&anim2, anim2_start); + lv_anim_set_completed_cb(&anim2, anim2_completed); + anim2_start_called = 0; + anim2_completed_called = 0; + + anim_timeline = lv_anim_timeline_create(); + lv_anim_timeline_add(anim_timeline, 0, &anim1); + lv_anim_timeline_add(anim_timeline, 200, &anim2); + lv_anim_timeline_set_progress(anim_timeline, 0); + lv_anim_timeline_start(anim_timeline); + + lv_refr_now(NULL); + + /* |----- Reverse ------| + * |-----anim1-----| |--anim1 rvs--| + * |----anim2----| |--anim2 rvs--| + * + * 0 200 300 500 600 800 900 1100 + */ + + lv_test_wait(20); /*Wait 20 ms*/ + TEST_ASSERT_EQUAL(1, anim1_start_called); + TEST_ASSERT_EQUAL(0, anim1_completed_called); + TEST_ASSERT_EQUAL(0, anim2_start_called); + TEST_ASSERT_EQUAL(0, anim2_completed_called); + + lv_test_wait(200); /*Now we are at 220ms */ + TEST_ASSERT_EQUAL(1, anim1_start_called); + TEST_ASSERT_EQUAL(0, anim1_completed_called); + TEST_ASSERT_EQUAL(1, anim2_start_called); + TEST_ASSERT_EQUAL(0, anim2_completed_called); + + lv_test_wait(100); /*Now we are at 320ms */ + TEST_ASSERT_EQUAL(1, anim1_start_called); + TEST_ASSERT_EQUAL(1, anim1_completed_called); + TEST_ASSERT_EQUAL(1, anim2_start_called); + TEST_ASSERT_EQUAL(0, anim2_completed_called); + + lv_test_wait(200); /*Now we are at 520ms */ + TEST_ASSERT_EQUAL(1, anim1_start_called); + TEST_ASSERT_EQUAL(1, anim1_completed_called); + TEST_ASSERT_EQUAL(1, anim2_start_called); + TEST_ASSERT_EQUAL(1, anim2_completed_called); + + lv_test_wait(80); /*Now we are at 600ms */ + anim1_start_called = 0; + anim1_completed_called = 0; + anim2_start_called = 0; + anim2_completed_called = 0; + + lv_anim_timeline_set_reverse(anim_timeline, true); + lv_anim_timeline_set_progress(anim_timeline, LV_ANIM_TIMELINE_PROGRESS_MAX); + lv_anim_timeline_start(anim_timeline); + + lv_test_wait(20); /*Now we are at 620ms */ + TEST_ASSERT_EQUAL(0, anim1_start_called); + TEST_ASSERT_EQUAL(0, anim1_completed_called); + TEST_ASSERT_EQUAL(1, anim2_start_called); + TEST_ASSERT_EQUAL(0, anim2_completed_called); + + lv_test_wait(200); /*Now we are at 820ms */ + TEST_ASSERT_EQUAL(1, anim1_start_called); + TEST_ASSERT_EQUAL(0, anim1_completed_called); + TEST_ASSERT_EQUAL(1, anim2_start_called); + TEST_ASSERT_EQUAL(0, anim2_completed_called); + + lv_test_wait(100); /*Now we are at 920ms */ + TEST_ASSERT_EQUAL(1, anim1_start_called); + TEST_ASSERT_EQUAL(0, anim1_completed_called); + TEST_ASSERT_EQUAL(1, anim2_start_called); + TEST_ASSERT_EQUAL(1, anim2_completed_called); + + lv_test_wait(200); /*Now we are at 1120ms */ + TEST_ASSERT_EQUAL(1, anim1_start_called); + TEST_ASSERT_EQUAL(1, anim1_completed_called); + TEST_ASSERT_EQUAL(1, anim2_start_called); + TEST_ASSERT_EQUAL(1, anim2_completed_called); +} + #endif