feat(anim): make animation time support speed as well

This commit is contained in:
Gabor Kiss-Vamosi
2023-11-13 22:14:01 +01:00
parent 2fe80e0aa1
commit 293937a1df
15 changed files with 91 additions and 84 deletions

View File

@@ -526,7 +526,7 @@ static void scroll_anim_y_cb(void * var, int32_t v)
static void scroll_anim(lv_obj_t * obj, int32_t y_max)
{
uint32_t t = lv_anim_speed_to_time(lv_display_get_dpi(NULL), 0, y_max);
uint32_t t = lv_anim_speed(lv_display_get_dpi(NULL));
lv_anim_t a;
lv_anim_init(&a);

View File

@@ -220,7 +220,7 @@ void lv_demo_widgets_start_slideshow(void)
lv_obj_t * tab = lv_obj_get_child(cont, 0);
int32_t v = lv_obj_get_scroll_bottom(tab);
uint32_t t = lv_anim_speed_to_time(lv_display_get_dpi(NULL), 0, v);
uint32_t t = lv_anim_speed(lv_display_get_dpi(NULL));
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_exec_cb(&a, scroll_anim_y_cb);
@@ -1648,7 +1648,7 @@ static void slideshow_anim_ready_cb(lv_anim_t * a_old)
lv_obj_update_layout(tv);
int32_t v = lv_obj_get_scroll_bottom(tab);
uint32_t t = lv_anim_speed_to_time(lv_display_get_dpi(NULL), 0, v);
uint32_t t = lv_anim_speed(lv_display_get_dpi(NULL));
lv_anim_t a;
lv_anim_init(&a);

View File

@@ -81,8 +81,7 @@ Drawing and rendering
Animations
~~~~~~~~~~
- |uncheck| Use `anim` events to replace many callbacks with one
- |uncheck| `lv_anim_time_to_speed` should work differently to remove
- |check| `lv_anim_time_to_speed` should work differently to remove
`style_anim_speed`. E.g. on large values of anim time store the
speed. Besides all widgets should use the `style_anim` property.
`anim` should clamp the time if it's calculated from speed, e.g

View File

@@ -810,15 +810,6 @@ The animation time in milliseconds. Its meaning is widget specific. E.g. blink t
<li style='display:inline; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
### anim_speed
The animation speed in pixel/sec. Its meaning is widget specific. E.g. scroll speed of label. See the widgets' documentation to learn more.
<ul>
<li style='display:inline; margin-right: 20px; margin-left: 0px'><strong>Default</strong> 0</li>
<li style='display:inline; margin-right: 20px; margin-left: 0px'><strong>Inherited</strong> No</li>
<li style='display:inline; margin-right: 20px; margin-left: 0px'><strong>Layout</strong> No</li>
<li style='display:inline; margin-right: 20px; margin-left: 0px'><strong>Ext. draw</strong> No</li>
</ul>
### transition
An initialized `lv_style_transition_dsc_t` to describe a transition.
<ul>

View File

@@ -361,10 +361,6 @@ props = [
'style_type': 'num', 'var_type': 'uint32_t' , 'default':0, 'inherited': 0, 'layout': 0, 'ext_draw': 0,
'dsc': "The animation time in milliseconds. Its meaning is widget specific. E.g. blink time of the cursor on the text area or scroll time of a roller. See the widgets' documentation to learn more."},
{'name': 'ANIM_SPEED',
'style_type': 'num', 'var_type': 'uint32_t' , 'default':0, 'inherited': 0, 'layout': 0, 'ext_draw': 0,
'dsc': "The animation speed in pixel/sec. Its meaning is widget specific. E.g. scroll speed of label. See the widgets' documentation to learn more."},
{'name': 'TRANSITION',
'style_type': 'ptr', 'var_type': 'const lv_style_transition_dsc_t *' , 'default':'`NULL`', 'inherited': 0, 'layout': 0, 'ext_draw': 0,
'dsc': "An initialized `lv_style_transition_dsc_t` to describe a transition."},

View File

@@ -312,9 +312,8 @@ void lv_obj_scroll_by(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t a
lv_anim_set_ready_cb(&a, scroll_anim_ready_cb);
if(dx) {
uint32_t t = lv_anim_speed_to_time((lv_display_get_horizontal_resolution(d) * 2) >> 2, 0, dx);
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
uint32_t t = lv_anim_speed_clamped((lv_display_get_horizontal_resolution(d)) >> 1, SCROLL_ANIM_TIME_MIN,
SCROLL_ANIM_TIME_MAX);
lv_anim_set_time(&a, t);
int32_t sx = lv_obj_get_scroll_x(obj);
lv_anim_set_values(&a, -sx, -sx + dx);
@@ -328,9 +327,8 @@ void lv_obj_scroll_by(lv_obj_t * obj, int32_t dx, int32_t dy, lv_anim_enable_t a
}
if(dy) {
uint32_t t = lv_anim_speed_to_time((lv_display_get_vertical_resolution(d) * 2) >> 2, 0, dy);
if(t < SCROLL_ANIM_TIME_MIN) t = SCROLL_ANIM_TIME_MIN;
if(t > SCROLL_ANIM_TIME_MAX) t = SCROLL_ANIM_TIME_MAX;
uint32_t t = lv_anim_speed_clamped((lv_display_get_vertical_resolution(d)) >> 1, SCROLL_ANIM_TIME_MIN,
SCROLL_ANIM_TIME_MAX);
lv_anim_set_time(&a, t);
int32_t sy = lv_obj_get_scroll_y(obj);
lv_anim_set_values(&a, -sy, -sy + dy);

View File

@@ -6,10 +6,8 @@
**********************************************************************
*/
#include "lv_obj.h"
void lv_obj_set_style_width(struct _lv_obj_t * obj, int32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
@@ -699,14 +697,6 @@ void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_TIME, v, selector);
}
void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_obj_set_local_style_prop(obj, LV_STYLE_ANIM_SPEED, v, selector);
}
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value,
lv_style_selector_t selector)
{
@@ -780,8 +770,7 @@ void lv_obj_set_style_flex_grow(struct _lv_obj_t * obj, uint8_t value, lv_style_
lv_obj_set_local_style_prop(obj, LV_STYLE_FLEX_GROW, v, selector);
}
void lv_obj_set_style_grid_column_dsc_array(struct _lv_obj_t * obj, const int32_t * value,
lv_style_selector_t selector)
void lv_obj_set_style_grid_column_dsc_array(struct _lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector)
{
lv_style_value_t v = {
.ptr = value

View File

@@ -597,12 +597,6 @@ static inline uint32_t lv_obj_get_style_anim_time(const struct _lv_obj_t * obj,
return (uint32_t)v.num;
}
static inline uint32_t lv_obj_get_style_anim_speed(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_ANIM_SPEED);
return (uint32_t)v.num;
}
static inline const lv_style_transition_dsc_t * lv_obj_get_style_transition(const struct _lv_obj_t * obj, uint32_t part)
{
lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_TRANSITION);
@@ -804,7 +798,6 @@ void lv_obj_set_style_color_filter_dsc(struct _lv_obj_t * obj, const lv_color_fi
void lv_obj_set_style_color_filter_opa(struct _lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector);
void lv_obj_set_style_anim(struct _lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector);
void lv_obj_set_style_anim_time(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
void lv_obj_set_style_anim_speed(struct _lv_obj_t * obj, uint32_t value, lv_style_selector_t selector);
void lv_obj_set_style_transition(struct _lv_obj_t * obj, const lv_style_transition_dsc_t * value,
lv_style_selector_t selector);
void lv_obj_set_style_blend_mode(struct _lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector);
@@ -818,8 +811,7 @@ void lv_obj_set_style_flex_grow(struct _lv_obj_t * obj, uint8_t value, lv_style_
void lv_obj_set_style_grid_column_dsc_array(struct _lv_obj_t * obj, const int32_t * value,
lv_style_selector_t selector);
void lv_obj_set_style_grid_column_align(struct _lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_row_dsc_array(struct _lv_obj_t * obj, const int32_t * value,
lv_style_selector_t selector);
void lv_obj_set_style_grid_row_dsc_array(struct _lv_obj_t * obj, const int32_t * value, lv_style_selector_t selector);
void lv_obj_set_style_grid_row_align(struct _lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_column_pos(struct _lv_obj_t * obj, int32_t value, lv_style_selector_t selector);
void lv_obj_set_style_grid_cell_x_align(struct _lv_obj_t * obj, lv_grid_align_t value, lv_style_selector_t selector);

View File

@@ -36,6 +36,8 @@ static void anim_mark_list_change(void);
static void anim_ready_handler(lv_anim_t * a);
static int32_t lv_anim_path_cubic_bezier(const lv_anim_t * a, int32_t x1,
int32_t y1, int32_t x2, int32_t y2);
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 VARIABLES
@@ -105,6 +107,8 @@ lv_anim_t * lv_anim_start(const lv_anim_t * a)
new_anim->end_value += v_ofs;
}
resolve_time(new_anim);
if(new_anim->exec_cb && new_anim->var) new_anim->exec_cb(new_anim->var, new_anim->start_value);
}
@@ -194,16 +198,34 @@ uint16_t lv_anim_count_running(void)
return cnt;
}
uint32_t lv_anim_speed_to_time(uint32_t speed, int32_t start, int32_t end)
uint32_t lv_anim_speed_clamped(uint32_t speed, uint32_t min_time, uint32_t max_time)
{
uint32_t d = LV_ABS(start - end);
uint32_t time = (d * 1000) / speed;
if(time == 0) {
time++;
if(speed > 10000) {
LV_LOG_WARN("speed is truncated to 10000 (was %d)", speed);
speed = 10230;
}
if(min_time > 10000) {
LV_LOG_WARN("min_time is truncated to 10000 (was %d)", min_time);
min_time = 10230;
}
if(max_time > 10000) {
LV_LOG_WARN("max_time is truncated to 10000 (was %d)", max_time);
max_time = 10230;
}
return time;
/*Lower the resolution to fit the 0.1023 range*/
speed = (speed + 5) / 10;
min_time = (min_time + 5) / 10;
max_time = (max_time + 5) / 10;
return 0x80000000 + (max_time << 20) + (min_time << 10) + speed;
}
uint32_t lv_anim_speed(uint32_t speed)
{
return lv_anim_speed_clamped(speed, 0, 1023);
}
void lv_anim_refr_now(void)
@@ -351,6 +373,9 @@ static void anim_timer(lv_timer_t * param)
a->start_value += v_ofs;
a->end_value += v_ofs;
}
resolve_time(a);
if(a->start_cb) a->start_cb(a);
a->start_cb_called = 1;
}
@@ -456,3 +481,26 @@ static int32_t lv_anim_path_cubic_bezier(const lv_anim_t * a, int32_t x1, int32_
return new_value;
}
static uint32_t convert_speed_to_time(uint32_t speed_or_time, int32_t start, int32_t end)
{
/*It was a simple time*/
if((speed_or_time & 0x80000000) == 0) return speed_or_time;
uint32_t d = LV_ABS(start - end);
uint32_t speed = speed_or_time & 0x3FF;
uint32_t time = (d * 100) / speed; /*Speed is in 10 units per sec*/
uint32_t max_time = (speed_or_time >> 20) & 0x3FF;
uint32_t min_time = (speed_or_time >> 10) & 0x3FF;
return LV_CLAMP(min_time * 10, time, max_time * 10);
}
static void resolve_time(lv_anim_t * a)
{
a->time = convert_speed_to_time(a->time, a->start_value, a->end_value);
a->act_time = -convert_speed_to_time(- a->act_time, a->start_value, a->end_value);
a->playback_time = convert_speed_to_time(a->playback_time, a->start_value, a->end_value);
a->playback_delay = convert_speed_to_time(a->playback_delay, a->start_value, a->end_value);
a->repeat_delay = convert_speed_to_time(a->repeat_delay, a->start_value, a->end_value);
}

View File

@@ -506,14 +506,27 @@ static inline lv_anim_t * lv_anim_custom_get(lv_anim_t * a, lv_anim_custom_exec_
*/
uint16_t lv_anim_count_running(void);
/**
* Calculate the time of an animation with a given speed and the start and end values
* @param speed speed of animation in unit/sec
* @param start start value of the animation
* @param end end value of the animation
* @return the required time [ms] for the animation with the given parameters
* Store the speed as a special value which can be used as time in animations.
* It will be converted to time internally based on the start and end values
* @param speed the speed of the animation in with 10 unit / sec resolution in 0..1023 range
* @return a special value which can be used as an animation time
*/
uint32_t lv_anim_speed_to_time(uint32_t speed, int32_t start, int32_t end);
uint32_t lv_anim_speed(uint32_t speed);
/**
* Store the speed as a special value which can be used as time in animations.
* It will be converted to time internally based on the start and end values
* @param speed the speed of the animation in as unit / sec resolution in 0..10k range
* @param min_time the minimum time in 0..10k range
* @param max_time the maximum time in 0..10k range
* @return a special value in where all three values are stored and can be used as an animation time
* @note internally speed is stored as 10 unit/sec
* @note internally min/max_time are stored with 10 ms unit
*
*/
uint32_t lv_anim_speed_clamped(uint32_t speed, uint32_t min_time, uint32_t max_time);
/**
* Manually refresh the state of the animations.

View File

@@ -129,7 +129,6 @@ const uint8_t _lv_style_builtin_prop_flag_lookup_table[_LV_STYLE_NUM_BUILT_IN_PR
[LV_STYLE_COLOR_FILTER_DSC] = LV_STYLE_PROP_FLAG_INHERITABLE,
[LV_STYLE_COLOR_FILTER_OPA] = LV_STYLE_PROP_FLAG_INHERITABLE,
[LV_STYLE_ANIM_TIME] = 0,
[LV_STYLE_ANIM_SPEED] = 0,
[LV_STYLE_TRANSITION] = 0,
[LV_STYLE_BLEND_MODE] = LV_STYLE_PROP_FLAG_LAYER_UPDATE,
[LV_STYLE_LAYOUT] = LV_STYLE_PROP_FLAG_LAYOUT_UPDATE,

View File

@@ -284,7 +284,6 @@ enum _lv_style_prop_t {
LV_STYLE_COLOR_FILTER_OPA = 98,
LV_STYLE_ANIM = 99,
LV_STYLE_ANIM_TIME = 100,
LV_STYLE_ANIM_SPEED = 101,
LV_STYLE_TRANSITION = 102,
LV_STYLE_BLEND_MODE = 103,
LV_STYLE_TRANSFORM_WIDTH = 104,

View File

@@ -868,16 +868,6 @@ void lv_style_set_anim_time(lv_style_t * style, uint32_t value)
const lv_style_prop_t _lv_style_const_prop_id_ANIM_TIME = LV_STYLE_ANIM_TIME;
void lv_style_set_anim_speed(lv_style_t * style, uint32_t value)
{
lv_style_value_t v = {
.num = (int32_t)value
};
lv_style_set_prop(style, LV_STYLE_ANIM_SPEED, v);
}
const lv_style_prop_t _lv_style_const_prop_id_ANIM_SPEED = LV_STYLE_ANIM_SPEED;
void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value)
{
lv_style_value_t v = {

View File

@@ -181,8 +181,6 @@ void lv_style_set_anim(lv_style_t * style, const lv_anim_t * value);
extern const lv_style_prop_t _lv_style_const_prop_id_ANIM;
void lv_style_set_anim_time(lv_style_t * style, uint32_t value);
extern const lv_style_prop_t _lv_style_const_prop_id_ANIM_TIME;
void lv_style_set_anim_speed(lv_style_t * style, uint32_t value);
extern const lv_style_prop_t _lv_style_const_prop_id_ANIM_SPEED;
void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value);
extern const lv_style_prop_t _lv_style_const_prop_id_TRANSITION;
void lv_style_set_blend_mode(lv_style_t * style, lv_blend_mode_t value);
@@ -652,11 +650,6 @@ extern const lv_style_prop_t _lv_style_const_prop_id_GRID_CELL_ROW_SPAN;
.prop_ptr = &_lv_style_const_prop_id_ANIM_TIME, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_ANIM_SPEED(val) \
{ \
.prop_ptr = &_lv_style_const_prop_id_ANIM_SPEED, .value = { .num = (int32_t)val } \
}
#define LV_STYLE_CONST_TRANSITION(val) \
{ \
.prop_ptr = &_lv_style_const_prop_id_TRANSITION, .value = { .ptr = val } \

View File

@@ -861,8 +861,8 @@ static void lv_label_refr_text(lv_obj_t * obj)
/*In scroll mode start an offset animation*/
if(label->long_mode == LV_LABEL_LONG_SCROLL) {
const lv_anim_t * anim_template = lv_obj_get_style_anim(obj, LV_PART_MAIN);
uint32_t anim_speed = lv_obj_get_style_anim_speed(obj, LV_PART_MAIN);
if(anim_speed == 0) anim_speed = LV_LABEL_DEF_SCROLL_SPEED;
uint32_t anim_time = lv_obj_get_style_anim_time(obj, LV_PART_MAIN);
if(anim_time == 0) anim_time = LV_LABEL_DEF_SCROLL_SPEED;
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, obj);
@@ -916,7 +916,7 @@ static void lv_label_refr_text(lv_obj_t * obj)
}
}
lv_anim_set_time(&a, lv_anim_speed_to_time(anim_speed, a.start_value, a.end_value));
lv_anim_set_time(&a, anim_time);
lv_anim_set_playback_time(&a, a.time);
/*If a template animation exists, overwrite some property*/
@@ -955,7 +955,7 @@ static void lv_label_refr_text(lv_obj_t * obj)
}
}
lv_anim_set_time(&a, lv_anim_speed_to_time(anim_speed, a.start_value, a.end_value));
lv_anim_set_time(&a, anim_time);
lv_anim_set_playback_time(&a, a.time);
/*If a template animation exists, overwrite some property*/
@@ -972,8 +972,8 @@ static void lv_label_refr_text(lv_obj_t * obj)
/*In roll inf. mode keep the size but start offset animations*/
else if(label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) {
const lv_anim_t * anim_template = lv_obj_get_style_anim(obj, LV_PART_MAIN);
uint32_t anim_speed = lv_obj_get_style_anim_speed(obj, LV_PART_MAIN);
if(anim_speed == 0) anim_speed = LV_LABEL_DEF_SCROLL_SPEED;
uint32_t anim_time = lv_obj_get_style_anim_time(obj, LV_PART_MAIN);
if(anim_time == 0) anim_time = LV_LABEL_DEF_SCROLL_SPEED;
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, obj);
@@ -1002,7 +1002,7 @@ static void lv_label_refr_text(lv_obj_t * obj)
lv_anim_set_values(&a, 0, -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT);
#endif
lv_anim_set_exec_cb(&a, set_ofs_x_anim);
lv_anim_set_time(&a, lv_anim_speed_to_time(anim_speed, a.start_value, a.end_value));
lv_anim_set_time(&a, anim_time);
lv_anim_t * anim_cur = lv_anim_get(obj, set_ofs_x_anim);
int32_t act_time = anim_cur ? anim_cur->act_time : 0;
@@ -1028,7 +1028,7 @@ static void lv_label_refr_text(lv_obj_t * obj)
if(size.y > lv_area_get_height(&txt_coords) && hor_anim == false) {
lv_anim_set_values(&a, 0, -size.y - (lv_font_get_line_height(font)));
lv_anim_set_exec_cb(&a, set_ofs_y_anim);
lv_anim_set_time(&a, lv_anim_speed_to_time(anim_speed, a.start_value, a.end_value));
lv_anim_set_time(&a, anim_time);
lv_anim_t * anim_cur = lv_anim_get(obj, set_ofs_y_anim);
int32_t act_time = anim_cur ? anim_cur->act_time : 0;