1
0
mirror of https://github.com/libretro/RetroArch synced 2025-04-01 13:20:43 +00:00

(GLUI) Fix ragged/broken scrolling when navigating at very high speed via gamepad/keyboard/mouse wheel

This commit is contained in:
jdgleaver 2020-03-12 15:59:24 +00:00
parent 28eec1489a
commit 050ac1e9cf

@ -1294,6 +1294,10 @@ typedef struct materialui_handle
float scroll_y; float scroll_y;
float content_height; float content_height;
/* Used to track scroll animations */
bool scroll_animation_active;
size_t scroll_animation_selection;
char msgbox[1024]; char msgbox[1024];
char menu_title[255]; char menu_title[255];
@ -2250,6 +2254,8 @@ static bool INLINE materialui_entry_onscreen(
* moves selection to specified on screen target * moves selection to specified on screen target
* > Does nothing if currently selected item is * > Does nothing if currently selected item is
* already on screen * already on screen
* > Does nothing if we are already scrolling
* towards currently selected item
* > Returns index of selected item */ * > Returns index of selected item */
static size_t materialui_auto_select_onscreen_entry( static size_t materialui_auto_select_onscreen_entry(
materialui_handle_t *mui, materialui_handle_t *mui,
@ -2261,6 +2267,13 @@ static size_t materialui_auto_select_onscreen_entry(
if (materialui_entry_onscreen(mui, selection)) if (materialui_entry_onscreen(mui, selection))
return selection; return selection;
/* If selected item is off screen but we are
* currently scrolling towards it (via an animation),
* no action is required */
if (mui->scroll_animation_active &&
(mui->scroll_animation_selection == selection))
return selection;
/* Update selection index */ /* Update selection index */
switch (target_entry) switch (target_entry)
{ {
@ -2283,6 +2296,20 @@ static size_t materialui_auto_select_onscreen_entry(
return selection; return selection;
} }
/* Kills any existing scroll animation and
* resets scroll acceleration */
static INLINE void materialui_kill_scroll_animation(
materialui_handle_t *mui)
{
gfx_animation_ctx_tag scroll_tag = (uintptr_t)&mui->scroll_y;
gfx_animation_kill_by_tag(&scroll_tag);
menu_input_set_pointer_y_accel(0.0f);
mui->scroll_animation_active = false;
mui->scroll_animation_selection = 0;
}
static void materialui_layout( static void materialui_layout(
materialui_handle_t *mui, bool video_is_threaded); materialui_handle_t *mui, bool video_is_threaded);
@ -2357,8 +2384,6 @@ static void materialui_render(void *data,
if (mui->need_compute) if (mui->need_compute)
{ {
gfx_animation_ctx_tag tag = (uintptr_t)&mui->scroll_y;
if (mui->font_data.list.font && mui->font_data.hint.font) if (mui->font_data.list.font && mui->font_data.hint.font)
materialui_compute_entries_box(mui, width, height, header_height); materialui_compute_entries_box(mui, width, height, header_height);
@ -2369,11 +2394,9 @@ static void materialui_render(void *data,
* has been called, so we delay it until here, when * has been called, so we delay it until here, when
* mui->need_compute is acted upon. */ * mui->need_compute is acted upon. */
/* Kill any existing scroll animation */ /* Kill any existing scroll animation
gfx_animation_kill_by_tag(&tag); * and reset scroll acceleration */
materialui_kill_scroll_animation(mui);
/* Reset scroll acceleration */
menu_input_set_pointer_y_accel(0.0f);
/* Get new scroll position */ /* Get new scroll position */
mui->scroll_y = materialui_get_scroll(mui); mui->scroll_y = materialui_get_scroll(mui);
@ -4535,7 +4558,6 @@ static void materialui_show_fullscreen_thumbnails(
gfx_animation_ctx_entry_t animation_entry; gfx_animation_ctx_entry_t animation_entry;
gfx_thumbnail_t *primary_thumbnail = NULL; gfx_thumbnail_t *primary_thumbnail = NULL;
gfx_thumbnail_t *secondary_thumbnail = NULL; gfx_thumbnail_t *secondary_thumbnail = NULL;
gfx_animation_ctx_tag scroll_tag = (uintptr_t)&mui->scroll_y;
gfx_animation_ctx_tag alpha_tag = (uintptr_t)&mui->fullscreen_thumbnail_alpha; gfx_animation_ctx_tag alpha_tag = (uintptr_t)&mui->fullscreen_thumbnail_alpha;
const char *thumbnail_label = NULL; const char *thumbnail_label = NULL;
@ -4572,10 +4594,9 @@ static void materialui_show_fullscreen_thumbnails(
/* Menu list must be stationary while fullscreen /* Menu list must be stationary while fullscreen
* thumbnails are shown * thumbnails are shown
* > Kill any existing scroll animations and * > Kill any existing scroll animation
* reset scroll acceleration */ * and reset scroll acceleration */
gfx_animation_kill_by_tag(&scroll_tag); materialui_kill_scroll_animation(mui);
menu_input_set_pointer_y_accel(0.0f);
/* Cache selected entry label /* Cache selected entry label
* (used as menu title when fullscreen thumbnails * (used as menu title when fullscreen thumbnails
@ -5936,6 +5957,9 @@ static void *materialui_init(void **userdata, bool video_is_threaded)
mui->transition_x_offset = 0.0f; mui->transition_x_offset = 0.0f;
mui->last_stack_size = 1; mui->last_stack_size = 1;
mui->scroll_animation_active = false;
mui->scroll_animation_selection = 0;
/* Ensure message box string is empty */ /* Ensure message box string is empty */
mui->msgbox[0] = '\0'; mui->msgbox[0] = '\0';
@ -6063,6 +6087,13 @@ static bool materialui_load_image(void *userdata, void *data, enum menu_image_ty
return true; return true;
} }
static void materialui_scroll_animation_end(void *userdata)
{
materialui_handle_t *mui = (materialui_handle_t*)userdata;
mui->scroll_animation_active = false;
mui->scroll_animation_selection = 0;
}
static void materialui_animate_scroll( static void materialui_animate_scroll(
materialui_handle_t *mui, float scroll_pos, float duration) materialui_handle_t *mui, float scroll_pos, float duration)
{ {
@ -6077,14 +6108,18 @@ static void materialui_animate_scroll(
* potential conflicts */ * potential conflicts */
menu_input_set_pointer_y_accel(0.0f); menu_input_set_pointer_y_accel(0.0f);
/* Set 'animation active' flag */
mui->scroll_animation_active = true;
mui->scroll_animation_selection = menu_navigation_get_selection();
/* Configure animation */ /* Configure animation */
animation_entry.easing_enum = EASING_IN_OUT_QUAD; animation_entry.easing_enum = EASING_IN_OUT_QUAD;
animation_entry.tag = animation_tag; animation_entry.tag = animation_tag;
animation_entry.duration = duration; animation_entry.duration = duration;
animation_entry.target_value = scroll_pos; animation_entry.target_value = scroll_pos;
animation_entry.subject = &mui->scroll_y; animation_entry.subject = &mui->scroll_y;
animation_entry.cb = NULL; animation_entry.cb = materialui_scroll_animation_end;
animation_entry.userdata = NULL; animation_entry.userdata = mui;
/* Push animation */ /* Push animation */
gfx_animation_push(&animation_entry); gfx_animation_push(&animation_entry);
@ -7203,8 +7238,7 @@ static int materialui_pointer_down(void *userdata,
* fullscreen thumbnails) */ * fullscreen thumbnails) */
if (mui->scrollbar.active && !mui->show_fullscreen_thumbnails) if (mui->scrollbar.active && !mui->show_fullscreen_thumbnails)
{ {
unsigned header_height = gfx_display_get_header_height(); unsigned header_height = gfx_display_get_header_height();
gfx_animation_ctx_tag tag = (uintptr_t)&mui->scroll_y;
unsigned width; unsigned width;
unsigned height; unsigned height;
int drag_margin_horz; int drag_margin_horz;
@ -7257,10 +7291,9 @@ static int materialui_pointer_down(void *userdata,
/* User has 'selected' scrollbar */ /* User has 'selected' scrollbar */
/* > Kill any existing scroll animations /* > Kill any existing scroll animation
* and reset scroll acceleration */ * and reset scroll acceleration */
gfx_animation_kill_by_tag(&tag); materialui_kill_scroll_animation(mui);
menu_input_set_pointer_y_accel(0.0f);
/* > Enable dragging */ /* > Enable dragging */
mui->scrollbar.dragged = true; mui->scrollbar.dragged = true;