Merge pull request #9391 from jdgleaver/smooth-line-ticker

(XMB) Add smooth scrolling vertical line ticker (for sublabels)
This commit is contained in:
Twinaphex 2019-08-30 16:19:23 +02:00 committed by GitHub
commit c4e9661b66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 524 additions and 49 deletions

View File

@ -1329,7 +1329,6 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("frame_time_counter_reset_after_load_state", &settings->bools.frame_time_counter_reset_after_load_state, true, false, false);
SETTING_BOOL("frame_time_counter_reset_after_save_state", &settings->bools.frame_time_counter_reset_after_save_state, true, false, false);
SETTING_BOOL("crt_switch_resolution_use_custom_refresh_rate", &settings->bools.crt_switch_custom_refresh_enable, true, false, false);
SETTING_BOOL("crt_switch_resolution_use_custom_refresh_rate", &settings->bools.crt_switch_custom_refresh_enable, true, false, false);
SETTING_BOOL("automatically_add_content_to_playlist", &settings->bools.automatically_add_content_to_playlist, true, DEFAULT_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, false);
SETTING_BOOL("ui_companion_start_on_boot", &settings->bools.ui_companion_start_on_boot, true, ui_companion_start_on_boot, false);
SETTING_BOOL("ui_companion_enable", &settings->bools.ui_companion_enable, true, ui_companion_enable, false);

View File

@ -3037,35 +3037,103 @@ static int xmb_draw_item(
if (i == current && width > 320 && height > 240
&& !string_is_empty(entry->sublabel))
{
menu_animation_ctx_line_ticker_t line_ticker;
char entry_sublabel[MENU_SUBLABEL_MAX_LENGTH];
char entry_sublabel_top_fade[MENU_SUBLABEL_MAX_LENGTH >> 2];
char entry_sublabel_bottom_fade[MENU_SUBLABEL_MAX_LENGTH >> 2];
menu_animation_ctx_line_ticker_t line_ticker;
menu_animation_ctx_line_ticker_smooth_t line_ticker_smooth;
float ticker_y_offset = 0.0f;
float ticker_top_fade_y_offset = 0.0f;
float ticker_bottom_fade_y_offset = 0.0f;
float ticker_top_fade_alpha = 0.0f;
float ticker_bottom_fade_alpha = 0.0f;
float sublabel_x = node->x + xmb->margins_screen_left +
xmb->icon_spacing_horizontal + xmb->margins_label_left;
float sublabel_y = xmb->margins_screen_top +
node->y + (xmb->margins_label_top * 3.5f);
entry_sublabel[0] = '\0';
entry_sublabel[0] = '\0';
entry_sublabel_top_fade[0] = '\0';
entry_sublabel_bottom_fade[0] = '\0';
line_ticker.type_enum = (enum menu_animation_ticker_type)settings->uints.menu_ticker_type;
line_ticker.idx = menu_animation_get_ticker_idx();
if (use_smooth_ticker)
{
line_ticker_smooth.fade_enabled = true;
line_ticker_smooth.type_enum = (enum menu_animation_ticker_type)settings->uints.menu_ticker_type;
line_ticker_smooth.idx = menu_animation_get_ticker_pixel_idx();
line_ticker.line_width = (size_t)(line_ticker_width);
/* Note: max_lines should be calculated at runtime,
* but this is a nuisance. There is room for 4 lines
* to be displayed when using all existing XMB themes,
* so leave this value hard coded for now. */
line_ticker.max_lines = 4;
line_ticker_smooth.font = xmb->font2;
line_ticker_smooth.font_scale = 1.0f;
line_ticker.s = entry_sublabel;
line_ticker.len = sizeof(entry_sublabel);
line_ticker.str = entry->sublabel;
line_ticker_smooth.field_width = (unsigned)(xmb->font2_size * 0.6f * line_ticker_width);
/* The calculation here is incredibly obtuse. I think
* this is correct... (c.f. xmb_item_y()) */
line_ticker_smooth.field_height = (unsigned)(
(xmb->icon_spacing_vertical * ((1 + xmb->under_item_offset) - xmb->active_item_factor)) -
(xmb->margins_label_top * 3.5f) -
xmb->under_item_offset); /* This last one is just a little extra padding (seems to help) */
menu_animation_line_ticker(&line_ticker);
line_ticker_smooth.src_str = entry->sublabel;
line_ticker_smooth.dst_str = entry_sublabel;
line_ticker_smooth.dst_str_len = sizeof(entry_sublabel);
line_ticker_smooth.y_offset = &ticker_y_offset;
line_ticker_smooth.top_fade_str = entry_sublabel_top_fade;
line_ticker_smooth.top_fade_str_len = sizeof(entry_sublabel_top_fade);
line_ticker_smooth.top_fade_y_offset = &ticker_top_fade_y_offset;
line_ticker_smooth.top_fade_alpha = &ticker_top_fade_alpha;
line_ticker_smooth.bottom_fade_str = entry_sublabel_bottom_fade;
line_ticker_smooth.bottom_fade_str_len = sizeof(entry_sublabel_bottom_fade);
line_ticker_smooth.bottom_fade_y_offset = &ticker_bottom_fade_y_offset;
line_ticker_smooth.bottom_fade_alpha = &ticker_bottom_fade_alpha;
menu_animation_line_ticker_smooth(&line_ticker_smooth);
}
else
{
line_ticker.type_enum = (enum menu_animation_ticker_type)settings->uints.menu_ticker_type;
line_ticker.idx = menu_animation_get_ticker_idx();
line_ticker.line_len = (size_t)(line_ticker_width);
/* Note: max_lines should be calculated at runtime,
* but this is a nuisance. There is room for 4 lines
* to be displayed when using all existing XMB themes,
* so leave this value hard coded for now. */
line_ticker.max_lines = 4;
line_ticker.s = entry_sublabel;
line_ticker.len = sizeof(entry_sublabel);
line_ticker.str = entry->sublabel;
menu_animation_line_ticker(&line_ticker);
}
label_offset = - xmb->margins_label_top;
/* Draw sublabel */
xmb_draw_text(video_info, xmb, entry_sublabel,
node->x + xmb->margins_screen_left +
xmb->icon_spacing_horizontal + xmb->margins_label_left,
xmb->margins_screen_top + node->y + xmb->margins_label_top*3.5,
sublabel_x, ticker_y_offset + sublabel_y,
1, node->label_alpha, TEXT_ALIGN_LEFT,
width, height, xmb->font2);
/* Draw top/bottom line fade effect, if required */
if (use_smooth_ticker)
{
if (!string_is_empty(entry_sublabel_top_fade) &&
ticker_top_fade_alpha > 0.0f)
xmb_draw_text(video_info, xmb, entry_sublabel_top_fade,
sublabel_x, ticker_top_fade_y_offset + sublabel_y,
1, ticker_top_fade_alpha * node->label_alpha, TEXT_ALIGN_LEFT,
width, height, xmb->font2);
if (!string_is_empty(entry_sublabel_bottom_fade) &&
ticker_bottom_fade_alpha > 0.0f)
xmb_draw_text(video_info, xmb, entry_sublabel_bottom_fade,
sublabel_x, ticker_bottom_fade_y_offset + sublabel_y,
1, ticker_bottom_fade_alpha * node->label_alpha, TEXT_ALIGN_LEFT,
width, height, xmb->font2);
}
}
}

View File

@ -779,23 +779,23 @@ static void menu_animation_ticker_smooth_loop(uint64_t idx,
}
}
static size_t get_line_display_ticks(size_t line_width)
static size_t get_line_display_ticks(size_t line_len)
{
/* Mean human reading speed for all western languages,
* characters per minute */
float cpm = 1000.0f;
/* Base time for which a line should be shown, in us */
float line_duration = (line_width * 60.0f * 1000.0f * 1000.0f) / cpm;
float line_duration = (line_len * 60.0f * 1000.0f * 1000.0f) / cpm;
/* Ticker updates (nominally) once every TICKER_SPEED us
* > Return base number of ticks for which line should be shown */
return (size_t)(line_duration / (float)TICKER_SPEED);
}
static void menu_animation_line_ticker_generic(uint64_t idx,
size_t line_width, size_t max_lines, size_t num_lines,
size_t line_len, size_t max_lines, size_t num_lines,
size_t *line_offset)
{
size_t line_ticks = get_line_display_ticks(line_width);
size_t line_ticks = get_line_display_ticks(line_len);
/* Note: This function is only called if num_lines > max_lines */
size_t excess_lines = num_lines - max_lines;
/* Ticker will pause for one line duration when the first
@ -822,10 +822,10 @@ static void menu_animation_line_ticker_generic(uint64_t idx,
}
static void menu_animation_line_ticker_loop(uint64_t idx,
size_t line_width, size_t num_lines,
size_t line_len, size_t num_lines,
size_t *line_offset)
{
size_t line_ticks = get_line_display_ticks(line_width);
size_t line_ticks = get_line_display_ticks(line_len);
size_t ticker_period = num_lines + 1;
size_t phase = (idx / line_ticks) % ticker_period;
@ -833,6 +833,188 @@ static void menu_animation_line_ticker_loop(uint64_t idx,
*line_offset = phase;
}
static size_t get_line_smooth_scroll_ticks(size_t line_len)
{
/* Mean human reading speed for all western languages,
* characters per minute */
float cpm = 1000.0f;
/* Base time for which a line should be shown, in ms */
float line_duration = (line_len * 60.0f * 1000.0f) / cpm;
/* Ticker updates (nominally) once every ticker_pixel_period ms
* > Return base number of ticks for which text should scroll
* from one line to the next */
return (size_t)(line_duration / ticker_pixel_period);
}
static void set_line_smooth_fade_parameters(
bool scroll_up, size_t scroll_ticks, size_t line_phase, size_t line_height,
size_t num_lines, size_t num_display_lines, size_t line_offset, float y_offset,
size_t *top_fade_line_offset, float *top_fade_y_offset, float *top_fade_alpha,
size_t *bottom_fade_line_offset, float *bottom_fade_y_offset, float *bottom_fade_alpha)
{
float fade_out_alpha = 0.0f;
float fade_in_alpha = 0.0f;
/* When a line fades out, alpha transitions from
* 1 to 0 over the course of one half of the
* scrolling line height. When a line fades in,
* it's the other way around */
fade_out_alpha = ((float)scroll_ticks - ((float)line_phase * 2.0f)) / (float)scroll_ticks;
fade_in_alpha = -1.0f * fade_out_alpha;
fade_out_alpha = (fade_out_alpha < 0.0f) ? 0.0f : fade_out_alpha;
fade_in_alpha = (fade_in_alpha < 0.0f) ? 0.0f : fade_in_alpha;
*top_fade_line_offset = (line_offset > 0) ? line_offset - 1 : num_lines;
*top_fade_y_offset = y_offset - (float)line_height;
*top_fade_alpha = scroll_up ? fade_out_alpha : fade_in_alpha;
*bottom_fade_line_offset = line_offset + num_display_lines;
*bottom_fade_y_offset = y_offset + (float)(line_height * num_display_lines);
*bottom_fade_alpha = scroll_up ? fade_in_alpha : fade_out_alpha;
}
static void set_line_smooth_fade_parameters_default(
size_t *top_fade_line_offset, float *top_fade_y_offset, float *top_fade_alpha,
size_t *bottom_fade_line_offset, float *bottom_fade_y_offset, float *bottom_fade_alpha)
{
*top_fade_line_offset = 0;
*top_fade_y_offset = 0.0f;
*top_fade_alpha = 0.0f;
*bottom_fade_line_offset = 0;
*bottom_fade_y_offset = 0.0f;
*bottom_fade_alpha = 0.0f;
}
static void menu_animation_line_ticker_smooth_generic(uint64_t idx,
bool fade_enabled, size_t line_len, size_t line_height,
size_t max_display_lines, size_t num_lines,
size_t *num_display_lines, size_t *line_offset, float *y_offset,
bool *fade_active,
size_t *top_fade_line_offset, float *top_fade_y_offset, float *top_fade_alpha,
size_t *bottom_fade_line_offset, float *bottom_fade_y_offset, float *bottom_fade_alpha)
{
size_t scroll_ticks = get_line_smooth_scroll_ticks(line_len);
/* Note: This function is only called if num_lines > max_display_lines */
size_t excess_lines = num_lines - max_display_lines;
/* Ticker will pause for one line duration when the first
* or last line is reached */
size_t ticker_period = ((excess_lines * 2) + 2) * scroll_ticks;
size_t phase = idx % ticker_period;
size_t line_phase = 0;
bool pause = false;
bool scroll_up = true;
/* Pause on first line */
if (phase < scroll_ticks)
pause = true;
phase = (phase >= scroll_ticks) ? phase - scroll_ticks : 0;
/* Pause on last line and change direction */
if (phase >= excess_lines * scroll_ticks)
{
scroll_up = false;
if (phase < (excess_lines + 1) * scroll_ticks)
{
pause = true;
phase = 0;
}
else
phase -= (excess_lines + 1) * scroll_ticks;
}
line_phase = phase % scroll_ticks;
if (pause || (line_phase == 0))
{
/* Static display of max_display_lines
* (no animation) */
*num_display_lines = max_display_lines;
*y_offset = 0.0f;
*fade_active = false;
if (pause)
*line_offset = scroll_up ? 0 : excess_lines;
else
*line_offset = scroll_up ? (phase / scroll_ticks) : (excess_lines - (phase / scroll_ticks));
}
else
{
/* Scroll animation is active */
*num_display_lines = max_display_lines - 1;
*fade_active = fade_enabled;
if (scroll_up)
{
*line_offset = (phase / scroll_ticks) + 1;
*y_offset = (float)line_height * (float)(scroll_ticks - line_phase) / (float)scroll_ticks;
}
else
{
*line_offset = excess_lines - (phase / scroll_ticks);
*y_offset = (float)line_height * (1.0f - (float)(scroll_ticks - line_phase) / (float)scroll_ticks);
}
/* Set fade parameters if fade animation is active */
if (*fade_active)
set_line_smooth_fade_parameters(
scroll_up, scroll_ticks, line_phase, line_height,
num_lines, *num_display_lines, *line_offset, *y_offset,
top_fade_line_offset, top_fade_y_offset, top_fade_alpha,
bottom_fade_line_offset, bottom_fade_y_offset, bottom_fade_alpha);
}
/* Set 'default' fade parameters if fade animation
* is inactive */
if (!*fade_active)
set_line_smooth_fade_parameters_default(
top_fade_line_offset, top_fade_y_offset, top_fade_alpha,
bottom_fade_line_offset, bottom_fade_y_offset, bottom_fade_alpha);
}
static void menu_animation_line_ticker_smooth_loop(uint64_t idx,
bool fade_enabled, size_t line_len, size_t line_height,
size_t max_display_lines, size_t num_lines,
size_t *num_display_lines, size_t *line_offset, float *y_offset,
bool *fade_active,
size_t *top_fade_line_offset, float *top_fade_y_offset, float *top_fade_alpha,
size_t *bottom_fade_line_offset, float *bottom_fade_y_offset, float *bottom_fade_alpha)
{
size_t scroll_ticks = get_line_smooth_scroll_ticks(line_len);
size_t ticker_period = (num_lines + 1) * scroll_ticks;
size_t phase = idx % ticker_period;
size_t line_phase = phase % scroll_ticks;
*line_offset = phase / scroll_ticks;
if (line_phase == (scroll_ticks - 1))
{
/* Static display of max_display_lines
* (no animation) */
*num_display_lines = max_display_lines;
*fade_active = false;
}
else
{
*num_display_lines = max_display_lines - 1;
*fade_active = fade_enabled;
}
*y_offset = (float)line_height * (float)(scroll_ticks - line_phase) / (float)scroll_ticks;
/* Set fade parameters */
if (*fade_active)
set_line_smooth_fade_parameters(
true, scroll_ticks, line_phase, line_height,
num_lines, *num_display_lines, *line_offset, *y_offset,
top_fade_line_offset, top_fade_y_offset, top_fade_alpha,
bottom_fade_line_offset, bottom_fade_y_offset, bottom_fade_alpha);
else
set_line_smooth_fade_parameters_default(
top_fade_line_offset, top_fade_y_offset, top_fade_alpha,
bottom_fade_line_offset, bottom_fade_y_offset, bottom_fade_alpha);
}
static void menu_delayed_animation_cb(void *userdata)
{
menu_delayed_animation_t *delayed_animation = (menu_delayed_animation_t*) userdata;
@ -1656,9 +1838,31 @@ end:
return is_active;
}
bool menu_animation_line_ticker(menu_animation_ctx_line_ticker_t *line_ticker)
static void build_line_ticker_string(
size_t num_display_lines, size_t line_offset, struct string_list *lines,
char *dest_str, size_t dest_str_len)
{
size_t i;
for (i = 0; i < num_display_lines; i++)
{
size_t offset = i + line_offset;
size_t line_index = offset % (lines->size + 1);
bool line_valid = true;
if (line_index >= lines->size)
line_valid = false;
if (line_valid)
strlcat(dest_str, lines->elems[line_index].data, dest_str_len);
if (i < num_display_lines - 1)
strlcat(dest_str, "\n", dest_str_len);
}
}
bool menu_animation_line_ticker(menu_animation_ctx_line_ticker_t *line_ticker)
{
char *wrapped_str = NULL;
struct string_list *lines = NULL;
size_t line_offset = 0;
@ -1670,7 +1874,7 @@ bool menu_animation_line_ticker(menu_animation_ctx_line_ticker_t *line_ticker)
return false;
if (string_is_empty(line_ticker->str) ||
(line_ticker->line_width < 1) ||
(line_ticker->line_len < 1) ||
(line_ticker->max_lines < 1))
goto end;
@ -1682,7 +1886,7 @@ bool menu_animation_line_ticker(menu_animation_ctx_line_ticker_t *line_ticker)
word_wrap(
wrapped_str,
line_ticker->str,
(int)line_ticker->line_width,
(int)line_ticker->line_len,
true, 0);
if (string_is_empty(wrapped_str))
@ -1709,7 +1913,7 @@ bool menu_animation_line_ticker(menu_animation_ctx_line_ticker_t *line_ticker)
{
menu_animation_line_ticker_loop(
line_ticker->idx,
line_ticker->line_width,
line_ticker->line_len,
lines->size,
&line_offset);
@ -1720,7 +1924,7 @@ bool menu_animation_line_ticker(menu_animation_ctx_line_ticker_t *line_ticker)
{
menu_animation_line_ticker_generic(
line_ticker->idx,
line_ticker->line_width,
line_ticker->line_len,
line_ticker->max_lines,
lines->size,
&line_offset);
@ -1730,25 +1934,9 @@ bool menu_animation_line_ticker(menu_animation_ctx_line_ticker_t *line_ticker)
}
/* Build output string from required lines */
for (i = 0; i < line_ticker->max_lines; i++)
{
size_t offset = i + line_offset;
size_t line_index = 0;
bool line_valid = true;
if (offset < lines->size)
line_index = offset;
else if (offset > lines->size)
line_index = (offset - 1) - lines->size;
else
line_valid = false;
if (line_valid)
strlcat(line_ticker->s, lines->elems[line_index].data, line_ticker->len);
if (i < line_ticker->max_lines - 1)
strlcat(line_ticker->s, "\n", line_ticker->len);
}
build_line_ticker_string(
line_ticker->max_lines, line_offset, lines,
line_ticker->s, line_ticker->len);
success = true;
is_active = true;
@ -1775,6 +1963,201 @@ end:
return is_active;
}
bool menu_animation_line_ticker_smooth(menu_animation_ctx_line_ticker_smooth_t *line_ticker)
{
char *wrapped_str = NULL;
struct string_list *lines = NULL;
int glyph_width = 0;
int glyph_height = 0;
size_t line_len = 0;
size_t max_display_lines = 0;
size_t num_display_lines = 0;
size_t line_offset = 0;
size_t top_fade_line_offset = 0;
size_t bottom_fade_line_offset = 0;
bool fade_active = false;
bool success = false;
bool is_active = false;
/* Sanity check */
if (!line_ticker)
return false;
if (!line_ticker->font ||
string_is_empty(line_ticker->src_str) ||
(line_ticker->field_width < 1) ||
(line_ticker->field_height < 1))
goto end;
/* Get font dimensions */
/* > Width
* This is a bit of a fudge. Performing a 'font aware'
* (i.e. character display width) word wrap is too CPU
* intensive, so we just sample the width of a common
* character and hope for the best. (We choose 'a' because
* this is what Ozone uses for spacing calculations, and
* it is proven to work quite well) */
glyph_width = font_driver_get_message_width(
line_ticker->font, "a", 1, line_ticker->font_scale);
if (glyph_width < 0)
goto end;
/* > Height */
glyph_height = font_driver_get_line_height(
line_ticker->font, line_ticker->font_scale);
if (glyph_height < 0)
goto end;
/* Determine line wrap parameters */
line_len = (size_t)(line_ticker->field_width / glyph_width);
max_display_lines = (size_t)(line_ticker->field_height / glyph_height);
if ((line_len < 1) || (max_display_lines < 1))
goto end;
/* Line wrap input string */
wrapped_str = (char*)malloc((strlen(line_ticker->src_str) + 1) * sizeof(char));
if (!wrapped_str)
goto end;
word_wrap(
wrapped_str,
line_ticker->src_str,
(int)line_len,
true, 0);
if (string_is_empty(wrapped_str))
goto end;
/* Split into component lines */
lines = string_split(wrapped_str, "\n");
if (!lines)
goto end;
/* Check whether total number of lines fits within
* the set field limit */
if (lines->size <= max_display_lines)
{
strlcpy(line_ticker->dst_str, wrapped_str, line_ticker->dst_str_len);
*line_ticker->y_offset = 0.0f;
/* No fade animation is required */
if (line_ticker->fade_enabled)
{
if (line_ticker->top_fade_str_len > 0)
line_ticker->top_fade_str[0] = '\0';
if (line_ticker->bottom_fade_str_len > 0)
line_ticker->bottom_fade_str[0] = '\0';
*line_ticker->top_fade_y_offset = 0.0f;
*line_ticker->bottom_fade_y_offset = 0.0f;
*line_ticker->top_fade_alpha = 0.0f;
*line_ticker->bottom_fade_alpha = 0.0f;
}
success = true;
goto end;
}
/* Determine which lines should be shown, along with
* y axis draw offset */
switch (line_ticker->type_enum)
{
case TICKER_TYPE_LOOP:
{
menu_animation_line_ticker_smooth_loop(
line_ticker->idx,
line_ticker->fade_enabled,
line_len, (size_t)glyph_height,
max_display_lines, lines->size,
&num_display_lines, &line_offset, line_ticker->y_offset,
&fade_active,
&top_fade_line_offset, line_ticker->top_fade_y_offset, line_ticker->top_fade_alpha,
&bottom_fade_line_offset, line_ticker->bottom_fade_y_offset, line_ticker->bottom_fade_alpha);
break;
}
case TICKER_TYPE_BOUNCE:
default:
{
menu_animation_line_ticker_smooth_generic(
line_ticker->idx,
line_ticker->fade_enabled,
line_len, (size_t)glyph_height,
max_display_lines, lines->size,
&num_display_lines, &line_offset, line_ticker->y_offset,
&fade_active,
&top_fade_line_offset, line_ticker->top_fade_y_offset, line_ticker->top_fade_alpha,
&bottom_fade_line_offset, line_ticker->bottom_fade_y_offset, line_ticker->bottom_fade_alpha);
break;
}
}
/* Build output string from required lines */
build_line_ticker_string(
num_display_lines, line_offset, lines,
line_ticker->dst_str, line_ticker->dst_str_len);
/* Extract top/bottom fade strings, if required */
if (fade_active)
{
/* We waste a handful of clock cycles by using
* build_line_ticker_string() here, but it saves
* rewriting a heap of code... */
build_line_ticker_string(
1, top_fade_line_offset, lines,
line_ticker->top_fade_str, line_ticker->top_fade_str_len);
build_line_ticker_string(
1, bottom_fade_line_offset, lines,
line_ticker->bottom_fade_str, line_ticker->bottom_fade_str_len);
}
success = true;
is_active = true;
ticker_is_active = true;
end:
if (wrapped_str)
{
free(wrapped_str);
wrapped_str = NULL;
}
if (lines)
{
string_list_free(lines);
lines = NULL;
}
if (!success)
{
if (line_ticker->dst_str_len > 0)
line_ticker->dst_str[0] = '\0';
if (line_ticker->fade_enabled)
{
if (line_ticker->top_fade_str_len > 0)
line_ticker->top_fade_str[0] = '\0';
if (line_ticker->bottom_fade_str_len > 0)
line_ticker->bottom_fade_str[0] = '\0';
*line_ticker->top_fade_alpha = 0.0f;
*line_ticker->bottom_fade_alpha = 0.0f;
}
}
return is_active;
}
bool menu_animation_is_active(void)
{
return animation_is_active || ticker_is_active;

View File

@ -147,7 +147,7 @@ typedef struct menu_animation_ctx_ticker_smooth
typedef struct menu_animation_ctx_line_ticker
{
size_t line_width;
size_t line_len;
size_t max_lines;
uint64_t idx;
enum menu_animation_ticker_type type_enum;
@ -156,6 +156,29 @@ typedef struct menu_animation_ctx_line_ticker
const char *str;
} menu_animation_ctx_line_ticker_t;
typedef struct menu_animation_ctx_line_ticker_smooth
{
bool fade_enabled;
font_data_t *font;
float font_scale;
unsigned field_width;
unsigned field_height;
enum menu_animation_ticker_type type_enum;
uint64_t idx;
const char *src_str;
char *dst_str;
size_t dst_str_len;
float *y_offset;
char *top_fade_str;
size_t top_fade_str_len;
float *top_fade_y_offset;
float *top_fade_alpha;
char *bottom_fade_str;
size_t bottom_fade_str_len;
float *bottom_fade_y_offset;
float *bottom_fade_alpha;
} menu_animation_ctx_line_ticker_smooth_t;
typedef float menu_timer_t;
typedef struct menu_timer_ctx_entry
@ -183,6 +206,8 @@ bool menu_animation_ticker_smooth(menu_animation_ctx_ticker_smooth_t *ticker);
bool menu_animation_line_ticker(menu_animation_ctx_line_ticker_t *line_ticker);
bool menu_animation_line_ticker_smooth(menu_animation_ctx_line_ticker_smooth_t *line_ticker);
float menu_animation_get_delta_time(void);
bool menu_animation_is_active(void);