1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

finialze screen animations

This commit is contained in:
Gabor Kiss-Vamosi 2020-06-25 12:37:46 +02:00
parent f10f94bea3
commit eb006b3d39
7 changed files with 312 additions and 22 deletions

View File

@ -8,6 +8,7 @@
*********************/
#include "lv_disp.h"
#include "../lv_misc/lv_math.h"
#include "../lv_core/lv_refr.h"
/*********************
* DEFINES
@ -20,7 +21,12 @@
/**********************
* STATIC PROTOTYPES
**********************/
#if LV_USE_ANIMATION
static void scr_load_anim_start(lv_anim_t * a);
static void opa_scale_anim(lv_obj_t * obj, lv_anim_value_t v);
static void scr_anim_ready(lv_anim_t * a);
#endif
/**********************
* STATIC VARIABLES
@ -44,13 +50,30 @@ lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp)
{
if(!disp) disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("lv_scr_act: no display registered to get its act. screen");
LV_LOG_WARN("no display registered to get its active screen");
return NULL;
}
return disp->act_scr;
}
/**
* Return with a pointer to the previous screen. Only used during screen transitions.
* @param disp pointer to display which previous screen should be get. (NULL to use the default
* screen)
* @return pointer to the previous screen object or NULL if not used now
*/
lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp)
{
if(!disp) disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("no display registered to get its previous screen");
return NULL;
}
return disp->prev_scr;
}
/**
* Make a screen active
* @param scr pointer to a screen
@ -97,6 +120,7 @@ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp)
return disp->sys_layer;
}
/**
* Assign a screen to a display.
* @param disp pointer to a display where to assign the screen
@ -116,21 +140,176 @@ void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr)
_lv_ll_chg_list(&old_disp->scr_ll, &disp->scr_ll, scr, true);
}
void lv_scr_load_anim(lv_obj_t * scr)
/**
* Set the background color of a display
* @param disp pointer to a display
* @param color color of the background
*/
void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color)
{
lv_disp_t * d = lv_obj_get_disp(scr);
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) lv_obj_set_x);
lv_anim_set_start_cb(&a, scr_load_anim_start);
lv_anim_set_time(&a, 2000);
lv_anim_set_delay(&a, 1000);
lv_anim_set_values(&a, lv_disp_get_hor_res(d), 0);
lv_anim_set_var(&a, scr);
lv_anim_start(&a);
if(!disp) disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("no display registered");
return;
}
disp->bg_color = color;
lv_area_t a;
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
_lv_inv_area(disp, &a);
}
/**
* Set the background image of a display
* @param disp pointer to a display
* @param img_src path to file or pointer to an `lv_img_dsc_t` variable
*/
void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src)
{
if(!disp) disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("no display registered");
return;
}
disp->bg_img = img_src;
lv_area_t a;
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
_lv_inv_area(disp, &a);
}
/**
* Opacity of the background
* @param disp pointer to a display
* @param opa opacity (0..255)
*/
void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa)
{
if(!disp) disp = lv_disp_get_default();
if(!disp) {
LV_LOG_WARN("no display registered");
return;
}
disp->bg_opa = opa;
lv_area_t a;
lv_area_set(&a, 0, 0, lv_disp_get_hor_res(disp) - 1, lv_disp_get_ver_res(disp) - 1);
_lv_inv_area(disp, &a);
}
#if LV_USE_ANIMATION
/**
* Switch screen with animation
* @param scr pointer to the new screen to load
* @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
* @param time time of the animation
* @param delay delay before the transition
* @param auto_del true: automatically delete the old screen
*/
void lv_scr_load_anim(lv_obj_t * new_scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del)
{
lv_disp_t * d = lv_obj_get_disp(new_scr);
if(d->prev_scr && d->del_prev) {
lv_obj_del(d->prev_scr);
d->prev_scr = NULL;
}
d->del_prev = auto_del;
/*Be sure there is no other animation on the screens*/
lv_anim_del(new_scr, NULL);
lv_anim_del(lv_scr_act(), NULL);
/*Be sure both screens are in a normal position*/
lv_obj_set_pos(new_scr, 0, 0);
lv_obj_set_pos(lv_scr_act(), 0, 0);
lv_style_remove_prop(lv_obj_get_local_style(new_scr, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE);
lv_style_remove_prop(lv_obj_get_local_style(lv_scr_act(), LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE);
lv_anim_t a_new;
lv_anim_init(&a_new);
lv_anim_set_var(&a_new, new_scr);
lv_anim_set_start_cb(&a_new, scr_load_anim_start);
lv_anim_set_ready_cb(&a_new, scr_anim_ready);
lv_anim_set_time(&a_new, time);
lv_anim_set_delay(&a_new, delay);
lv_anim_t a_old;
lv_anim_init(&a_old);
lv_anim_set_var(&a_old, d->act_scr);
lv_anim_set_time(&a_old, time);
lv_anim_set_delay(&a_old, delay);
switch(anim_type) {
case LV_SCR_LOAD_ANIM_NONE:
/* Create a dummy animation to apply the delay*/
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
lv_anim_set_values(&a_new, 0, 0);
break;
case LV_SCR_LOAD_ANIM_OVER_LEFT:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
break;
case LV_SCR_LOAD_ANIM_OVER_RIGHT:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
break;
case LV_SCR_LOAD_ANIM_OVER_TOP:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_y);
lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
break;
case LV_SCR_LOAD_ANIM_OVER_BOTTOM:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_y);
lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
break;
case LV_SCR_LOAD_ANIM_MOVE_LEFT:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
lv_anim_set_values(&a_new, lv_disp_get_hor_res(d), 0);
lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t) lv_obj_set_x);
lv_anim_set_values(&a_old, 0, -lv_disp_get_hor_res(d));
break;
case LV_SCR_LOAD_ANIM_MOVE_RIGHT:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_x);
lv_anim_set_values(&a_new, -lv_disp_get_hor_res(d), 0);
lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t) lv_obj_set_x);
lv_anim_set_values(&a_old, 0, lv_disp_get_hor_res(d));
break;
case LV_SCR_LOAD_ANIM_MOVE_TOP:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_y);
lv_anim_set_values(&a_new, lv_disp_get_ver_res(d), 0);
lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t) lv_obj_set_y);
lv_anim_set_values(&a_old, 0, -lv_disp_get_ver_res(d));
break;
case LV_SCR_LOAD_ANIM_MOVE_BOTTOM:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) lv_obj_set_y);
lv_anim_set_values(&a_new, -lv_disp_get_ver_res(d), 0);
lv_anim_set_exec_cb(&a_old, (lv_anim_exec_xcb_t) lv_obj_set_y);
lv_anim_set_values(&a_old, 0, lv_disp_get_ver_res(d));
break;
case LV_SCR_LOAD_ANIM_FADE_ON:
lv_anim_set_exec_cb(&a_new, (lv_anim_exec_xcb_t) opa_scale_anim);
lv_anim_set_values(&a_new, LV_OPA_TRANSP, LV_OPA_COVER);
break;
}
lv_anim_start(&a_new);
lv_anim_start(&a_old);
}
#endif
/**
* Get elapsed time since last user activity on a display (e.g. click)
* @param disp pointer to an display (NULL to get the overall smallest inactivity)
@ -195,7 +374,27 @@ lv_task_t * _lv_disp_get_refr_task(lv_disp_t * disp)
* STATIC FUNCTIONS
**********************/
#if LV_USE_ANIMATION
static void scr_load_anim_start(lv_anim_t * a)
{
lv_disp_t * d = lv_obj_get_disp(a->var);
d->prev_scr = lv_scr_act();
lv_disp_load_scr(a->var);
}
static void opa_scale_anim(lv_obj_t * obj, lv_anim_value_t v)
{
lv_obj_set_style_local_opa_scale(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, v);
}
static void scr_anim_ready(lv_anim_t * a)
{
lv_disp_t * d = lv_obj_get_disp(a->var);
if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr);
d->prev_scr = NULL;
lv_style_remove_prop(lv_obj_get_local_style(a->var, LV_OBJ_PART_MAIN), LV_STYLE_OPA_SCALE);
}
#endif

View File

@ -24,6 +24,19 @@ extern "C" {
* TYPEDEFS
**********************/
typedef enum {
LV_SCR_LOAD_ANIM_NONE,
LV_SCR_LOAD_ANIM_OVER_LEFT,
LV_SCR_LOAD_ANIM_OVER_RIGHT,
LV_SCR_LOAD_ANIM_OVER_TOP,
LV_SCR_LOAD_ANIM_OVER_BOTTOM,
LV_SCR_LOAD_ANIM_MOVE_LEFT,
LV_SCR_LOAD_ANIM_MOVE_RIGHT,
LV_SCR_LOAD_ANIM_MOVE_TOP,
LV_SCR_LOAD_ANIM_MOVE_BOTTOM,
LV_SCR_LOAD_ANIM_FADE_ON,
}lv_scr_load_anim_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
@ -36,6 +49,14 @@ extern "C" {
*/
lv_obj_t * lv_disp_get_scr_act(lv_disp_t * disp);
/**
* Return with a pointer to the previous screen. Only used during screen transitions.
* @param disp pointer to display which previous screen should be get. (NULL to use the default
* screen)
* @return pointer to the previous screen object or NULL if not used now
*/
lv_obj_t * lv_disp_get_scr_prev(lv_disp_t * disp);
/**
* Make a screen active
* @param scr pointer to a screen
@ -64,6 +85,41 @@ lv_obj_t * lv_disp_get_layer_sys(lv_disp_t * disp);
*/
void lv_disp_assign_screen(lv_disp_t * disp, lv_obj_t * scr);
/**
* Set the background color of a display
* @param disp pointer to a display
* @param color color of the background
*/
void lv_disp_set_bg_color(lv_disp_t * disp, lv_color_t color);
/**
* Set the background image of a display
* @param disp pointer to a display
* @param img_src path to file or pointer to an `lv_img_dsc_t` variable
*/
void lv_disp_set_bg_image(lv_disp_t * disp, const void * img_src);
/**
* Opacity of the background
* @param disp pointer to a display
* @param opa opacity (0..255)
*/
void lv_disp_set_bg_opa(lv_disp_t * disp, lv_opa_t opa);
#if LV_USE_ANIMATION
/**
* Switch screen with animation
* @param scr pointer to the new screen to load
* @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
* @param time time of the animation
* @param delay delay before the transition
* @param auto_del true: automatically delete the old screen
*/
void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del);
#endif
/**
* Get elapsed time since last user activity on a display (e.g. click)
* @param disp pointer to an display (NULL to get the overall smallest inactivity)
@ -123,8 +179,6 @@ static inline void lv_scr_load(lv_obj_t * scr)
}
void lv_scr_load_anim(lv_obj_t * scr);
/**********************
* MACROS
**********************/

View File

@ -501,10 +501,12 @@ void lv_obj_invalidate_area(const lv_obj_t * obj, const lv_area_t * area)
if(lv_obj_get_hidden(obj)) return;
/*Invalidate the object only if it belongs to the 'LV_GC_ROOT(_lv_act_scr)'*/
/*Invalidate the object only if it belongs to the curent or previous'*/
lv_obj_t * obj_scr = lv_obj_get_screen(obj);
lv_disp_t * disp = lv_obj_get_disp(obj_scr);
if(obj_scr == lv_disp_get_scr_act(disp) || obj_scr == lv_disp_get_layer_top(disp) ||
if(obj_scr == lv_disp_get_scr_act(disp) ||
obj_scr == lv_disp_get_scr_prev(disp) ||
obj_scr == lv_disp_get_layer_top(disp) ||
obj_scr == lv_disp_get_layer_sys(disp)) {
/*Truncate the area to the object*/

View File

@ -506,11 +506,28 @@ static void lv_refr_area_part(const lv_area_t * area_p)
/*Draw a display background if there is no top object*/
if(top_act_scr == NULL && top_prev_scr == NULL) {
if(disp_refr->bg_img) {
lv_draw_img_dsc_t dsc;
lv_draw_img_dsc_init(&dsc);
dsc.opa = disp_refr->bg_opa;
lv_img_header_t header;
lv_res_t res;
res = lv_img_decoder_get_info(disp_refr->bg_img, &header);
if(res == LV_RES_OK) {
lv_area_t a;
lv_area_set(&a, 0, 0, header.w - 1, header.h - 1);
lv_draw_img(&a, &start_mask, disp_refr->bg_img, &dsc);
} else {
LV_LOG_WARN("Can't draw the background image")
}
} else {
lv_draw_rect_dsc_t dsc;
lv_draw_rect_dsc_init(&dsc);
dsc.bg_color = LV_COLOR_RED;
dsc.bg_color = disp_refr->bg_color;
dsc.bg_opa = disp_refr->bg_opa;
lv_draw_rect(&start_mask, &start_mask, &dsc);
}
}
/*Refresh the previous screen if any*/
if(disp_refr->prev_scr) {

View File

@ -89,6 +89,9 @@ void _lv_img_decoder_init(void)
lv_res_t lv_img_decoder_get_info(const char * src, lv_img_header_t * header)
{
header->always_zero = 0;
header->h = 0;
header->w = 0;
header->cf = LV_IMG_CF_UNKNOWN;
lv_res_t res = LV_RES_INV;
lv_img_decoder_t * d;

View File

@ -144,6 +144,15 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver)
disp->inv_p = 0;
disp->last_activity_time = 0;
disp->bg_color = LV_COLOR_WHITE;
disp->bg_img = NULL;
#if LV_COLOR_SCREEN_TRANSP
disp->bg_opa = LV_OPA_TRANSP;
#else
disp->bg_opa = LV_OPA_COVER;
#endif
disp->prev_scr = NULL;
disp->act_scr = lv_obj_create(NULL, NULL); /*Create a default screen on the display*/
disp->top_layer = lv_obj_create(NULL, NULL); /*Create top layer on the display*/
disp->sys_layer = lv_obj_create(NULL, NULL); /*Create sys layer on the display*/

View File

@ -151,6 +151,12 @@ typedef struct _disp_t {
struct _lv_obj_t * top_layer; /**< @see lv_disp_get_layer_top */
struct _lv_obj_t * sys_layer; /**< @see lv_disp_get_layer_sys */
uint8_t del_prev :1; /**< 1: Automatically delete the previous screen when the screen load animation is ready */
lv_color_t bg_color; /**< Default display color when screens are transparent*/
const void * bg_img; /**< An image source to display as wallpaper*/
lv_opa_t bg_opa; /**<Opacity of the background color or wallpaper */
/** Invalidated (marked to redraw) areas*/
lv_area_t inv_areas[LV_INV_BUF_SIZE];
uint8_t inv_area_joined[LV_INV_BUF_SIZE];