diff --git a/gfx/drivers_font/gl_raster_font.c b/gfx/drivers_font/gl_raster_font.c index d2a6c1bba9..efa61e4b14 100644 --- a/gfx/drivers_font/gl_raster_font.c +++ b/gfx/drivers_font/gl_raster_font.c @@ -346,7 +346,7 @@ static void gl_raster_font_render_msg(void *data, const char *msg, settings_t *settings = config_get_ptr(); const struct font_params *params = (const struct font_params*)userdata; - if (!font) + if (!font || !msg || !*msg) return; gl = font->gl; diff --git a/menu/drivers/glui.c b/menu/drivers/glui.c index d8f192e673..a16fdf97ed 100644 --- a/menu/drivers/glui.c +++ b/menu/drivers/glui.c @@ -681,7 +681,7 @@ static void glui_navigation_set(bool scroll) } menu_animation_push(disp->animation, 10, scroll_pos, - &menu->scroll_y, EASING_IN_OUT_QUAD, NULL); + &menu->scroll_y, EASING_IN_OUT_QUAD, -1, NULL); } static void glui_navigation_clear(bool pending_push) diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index bd02ea9446..1c26a40d8a 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -583,7 +583,8 @@ static void xmb_update_boxart(xmb_handle_t *xmb, unsigned i) static void xmb_selection_pointer_changed(void) { - unsigned i, current, end; + unsigned i, current, end, tag, height, skip; + int threshold = 0; xmb_handle_t *xmb = NULL; menu_handle_t *menu = menu_driver_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); @@ -599,12 +600,20 @@ static void xmb_selection_pointer_changed(void) if (!xmb) return; - current = nav->selection_ptr; - end = menu_entries_get_end(); + current = nav->selection_ptr; + end = menu_entries_get_end(); + tag = (uintptr_t)menu_list; + threshold = xmb->icon.size*10; + + video_driver_get_size(NULL, &height); + + menu_animation_kill_by_tag(disp->animation, tag); + menu_entries_set_start(0); + skip = 0; for (i = 0; i < end; i++) { - float iy; + float iy, real_iy; float ia = xmb->item.passive.alpha; float iz = xmb->item.passive.zoom; xmb_node_t *node = (xmb_node_t*)menu_list_get_userdata_at_offset( @@ -613,7 +622,8 @@ static void xmb_selection_pointer_changed(void) if (!node) continue; - iy = xmb_item_y(xmb, i, current); + iy = xmb_item_y(xmb, i, current); + real_iy = iy + xmb->margins.screen.top; if (i == current) { @@ -624,21 +634,36 @@ static void xmb_selection_pointer_changed(void) xmb_update_boxart(xmb, i); } - menu_animation_push(disp->animation, - XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, NULL); - menu_animation_push(disp->animation, - XMB_DELAY, ia, &node->label_alpha, EASING_IN_OUT_QUAD, NULL); - menu_animation_push(disp->animation, - XMB_DELAY, iz, &node->zoom, EASING_IN_OUT_QUAD, NULL); - menu_animation_push(disp->animation, - XMB_DELAY, iy, &node->y, EASING_IN_OUT_QUAD, NULL); + if (real_iy < -threshold) + skip++; + + if (real_iy < -threshold || real_iy > height+threshold) + { + node->alpha = node->label_alpha = ia; + node->y = iy; + node->zoom = iz; + } + else + { + menu_animation_push(disp->animation, + XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, tag, NULL); + menu_animation_push(disp->animation, + XMB_DELAY, ia, &node->label_alpha, EASING_IN_OUT_QUAD, tag, NULL); + menu_animation_push(disp->animation, + XMB_DELAY, iz, &node->zoom, EASING_IN_OUT_QUAD, tag, NULL); + menu_animation_push(disp->animation, + XMB_DELAY, iy, &node->y, EASING_IN_OUT_QUAD, tag, NULL); + } } + + menu_entries_set_start(skip); } static void xmb_list_open_old(xmb_handle_t *xmb, file_list_t *list, int dir, size_t current) { - unsigned i; + unsigned i, height = 0; + int threshold = xmb->icon.size * 10; size_t end = 0; menu_display_t *disp = menu_display_get_ptr(); @@ -647,9 +672,12 @@ static void xmb_list_open_old(xmb_handle_t *xmb, end = file_list_get_size(list); + video_driver_get_size(NULL, &height); + for (i = 0; i < end; i++) { float ia = 0; + float real_y; xmb_node_t *node = (xmb_node_t*)menu_list_get_userdata_at_offset(list, i); if (!node) @@ -660,26 +688,41 @@ static void xmb_list_open_old(xmb_handle_t *xmb, if (dir == -1) ia = 0; - menu_animation_push(disp->animation, - XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, NULL); - menu_animation_push(disp->animation, - XMB_DELAY, 0, &node->label_alpha, EASING_IN_OUT_QUAD, NULL); - menu_animation_push(disp->animation, - XMB_DELAY, xmb->icon.size * dir * -2, &node->x, - EASING_IN_OUT_QUAD, NULL); + real_y = node->y + xmb->margins.screen.top; + + if (real_y < -threshold || real_y > height+threshold) + { + node->alpha = ia; + node->label_alpha = 0; + node->x = xmb->icon.size * dir * -2; + } + else + { + menu_animation_push(disp->animation, + XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, -1, NULL); + menu_animation_push(disp->animation, + XMB_DELAY, 0, &node->label_alpha, EASING_IN_OUT_QUAD, -1, NULL); + menu_animation_push(disp->animation, + XMB_DELAY, xmb->icon.size * dir * -2, &node->x, + EASING_IN_OUT_QUAD, -1, NULL); + } } } static void xmb_list_open_new(xmb_handle_t *xmb, file_list_t *list, int dir, size_t current) { - unsigned i; + unsigned i, height; + int threshold = xmb->icon.size * 10; menu_display_t *disp = menu_display_get_ptr(); size_t end = file_list_get_size(list); + video_driver_get_size(NULL, &height); + for (i = 0; i < end; i++) { float ia; + float real_y; xmb_node_t *node = (xmb_node_t*) menu_list_get_userdata_at_offset(list, i); @@ -696,6 +739,8 @@ static void xmb_list_open_new(xmb_handle_t *xmb, node->y = xmb_item_y(xmb, i, current); node->zoom = xmb->categories.passive.zoom; + real_y = node->y + xmb->margins.screen.top; + if (i == current) node->zoom = xmb->categories.active.zoom; @@ -703,12 +748,20 @@ static void xmb_list_open_new(xmb_handle_t *xmb, if (i == current) ia = xmb->item.active.alpha; - menu_animation_push(disp->animation, - XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, NULL); - menu_animation_push(disp->animation, - XMB_DELAY, ia, &node->label_alpha, EASING_IN_OUT_QUAD, NULL); - menu_animation_push(disp->animation, - XMB_DELAY, 0, &node->x, EASING_IN_OUT_QUAD, NULL); + if (real_y < -threshold || real_y > height+threshold) + { + node->alpha = node->label_alpha = ia; + node->x = 0; + } + else + { + menu_animation_push(disp->animation, + XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, -1, NULL); + menu_animation_push(disp->animation, + XMB_DELAY, ia, &node->label_alpha, EASING_IN_OUT_QUAD, -1, NULL); + menu_animation_push(disp->animation, + XMB_DELAY, 0, &node->x, EASING_IN_OUT_QUAD, -1, NULL); + } } xmb->old_depth = xmb->depth; @@ -752,11 +805,11 @@ static void xmb_push_animations(xmb_node_t *node, float ia, float ix) return; menu_animation_push(disp->animation, - XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, NULL); + XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, -1, NULL); menu_animation_push(disp->animation, - XMB_DELAY, ia, &node->label_alpha, EASING_IN_OUT_QUAD, NULL); + XMB_DELAY, ia, &node->label_alpha, EASING_IN_OUT_QUAD, -1, NULL); menu_animation_push(disp->animation, - XMB_DELAY, ix, &node->x, EASING_IN_OUT_QUAD, NULL); + XMB_DELAY, ix, &node->x, EASING_IN_OUT_QUAD, -1, NULL); } static void xmb_list_switch_old(xmb_handle_t *xmb, @@ -869,9 +922,9 @@ static void xmb_list_switch_horizontal_list(xmb_handle_t *xmb, menu_handle_t *me } menu_animation_push(menu->display.animation, - XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, NULL); + XMB_DELAY, ia, &node->alpha, EASING_IN_OUT_QUAD, -1, NULL); menu_animation_push(menu->display.animation, - XMB_DELAY, iz, &node->zoom, EASING_IN_OUT_QUAD, NULL); + XMB_DELAY, iz, &node->zoom, EASING_IN_OUT_QUAD, -1, NULL); } } @@ -896,7 +949,7 @@ static void xmb_list_switch(xmb_handle_t *xmb) menu_animation_push(disp->animation, XMB_DELAY, xmb->icon.spacing.horizontal * -(float)xmb->categories.selection_ptr, - &xmb->categories.x_pos, EASING_IN_OUT_QUAD, NULL); + &xmb->categories.x_pos, EASING_IN_OUT_QUAD, -1, NULL); dir = -1; if (xmb->categories.selection_ptr > xmb->categories.selection_ptr_old) @@ -934,7 +987,7 @@ static void xmb_list_open_horizontal_list(xmb_handle_t *xmb, menu_handle_t *menu ia = xmb->categories.passive.alpha; menu_animation_push(menu->display.animation, XMB_DELAY, ia, - &node->alpha, EASING_IN_OUT_QUAD, NULL); + &node->alpha, EASING_IN_OUT_QUAD, -1, NULL); } } @@ -968,18 +1021,18 @@ static void xmb_list_open(xmb_handle_t *xmb) case 1: menu_animation_push(disp->animation, XMB_DELAY, xmb->icon.size * -(xmb->depth*2-2), - &xmb->x, EASING_IN_OUT_QUAD, NULL); + &xmb->x, EASING_IN_OUT_QUAD, -1, NULL); menu_animation_push(disp->animation, XMB_DELAY, 0, &xmb->textures.arrow.alpha, - EASING_IN_OUT_QUAD, NULL); + EASING_IN_OUT_QUAD, -1, NULL); break; case 2: menu_animation_push(disp->animation, XMB_DELAY, xmb->icon.size * -(xmb->depth*2-2), - &xmb->x, EASING_IN_OUT_QUAD, NULL); + &xmb->x, EASING_IN_OUT_QUAD, -1, NULL); menu_animation_push(disp->animation, XMB_DELAY, 1, &xmb->textures.arrow.alpha, - EASING_IN_OUT_QUAD, NULL); + EASING_IN_OUT_QUAD, -1, NULL); break; } @@ -1319,37 +1372,29 @@ static void xmb_render(void) current = nav->selection_ptr; end = menu_list_get_size(menu_list); - menu_entries_set_start(0); - - for (i = 0; i < end; i++) + if (settings->menu.pointer.enable || settings->menu.mouse.enable) { - float item_y1 = xmb->margins.screen.top + xmb_item_y(xmb, i, current); - float item_y2 = item_y1 + xmb->icon.size; - - if (item_y2 < 0) + for (i = 0; i < end; i++) { - menu_entries_set_start(menu_entries_get_start() + 1); - continue; - } + float item_y1 = xmb->margins.screen.top + xmb_item_y(xmb, i, current); + float item_y2 = item_y1 + xmb->icon.size; - if (item_y1 > height) - continue; + if (settings->menu.pointer.enable) + { + if (menu_input->pointer.y > item_y1 && menu_input->pointer.y < item_y2) + menu_input->pointer.ptr = i; + } - if (settings->menu.pointer.enable) - { - if (menu_input->pointer.y > item_y1 && menu_input->pointer.y < item_y2) - menu_input->pointer.ptr = i; - } - - if (settings->menu.mouse.enable) - { - if (menu_input->mouse.y > item_y1 && menu_input->mouse.y < item_y2) - menu_input->mouse.ptr = i; + if (settings->menu.mouse.enable) + { + if (menu_input->mouse.y > item_y1 && menu_input->mouse.y < item_y2) + menu_input->mouse.ptr = i; + } } } - if (menu_entries_get_start() >= 5) - menu_entries_set_start(menu_entries_get_start() - 5); + if (menu_entries_get_start() >= end) + menu_entries_set_start(0); anim->is_active = false; anim->label.is_updated = false; @@ -2334,7 +2379,7 @@ static void xmb_toggle(bool menu_on) } menu_animation_push(disp->animation, XMB_DELAY, 1.0f, - &xmb->alpha, EASING_IN_OUT_QUAD, NULL); + &xmb->alpha, EASING_IN_OUT_QUAD, -1, NULL); xmb->prevent_populate = !menu_entries_needs_refresh(); diff --git a/menu/menu_animation.c b/menu/menu_animation.c index bc5cb45fab..c30ee8c2f3 100644 --- a/menu/menu_animation.c +++ b/menu/menu_animation.c @@ -293,8 +293,12 @@ void menu_animation_kill_by_subject(menu_animation_t *animation, { if (animation->list[i].subject == sub[j]) { - animation->list[i].alive = 0; + animation->list[i].alive = false; animation->list[i].subject = NULL; + + if (i < animation->first_dead) + animation->first_dead = i; + killed++; break; } @@ -302,25 +306,65 @@ void menu_animation_kill_by_subject(menu_animation_t *animation, } } -bool menu_animation_push( - menu_animation_t *anim, +void menu_animation_kill_by_tag(menu_animation_t *anim, unsigned tag) +{ + unsigned i; + + if (tag == -1) + return; + + for (i = 0; i < anim->size; ++i) + { + if (anim->list[i].tag == tag) + { + anim->list[i].alive = false; + anim->list[i].subject = NULL; + + if (i < anim->first_dead) + anim->first_dead = i; + } + } +} + +static void menu_animation_push_internal(menu_animation_t *anim, const struct tween *t) +{ + struct tween *target = NULL; + + if (anim->first_dead < anim->size && !anim->list[anim->first_dead].alive) + target = &anim->list[anim->first_dead++]; + else + { + if (anim->size >= anim->capacity) + { + anim->capacity++; + anim->list = (struct tween*)realloc(anim->list, + anim->capacity * sizeof(struct tween)); + } + + target = &anim->list[anim->size++]; + } + + *target = *t; +} + +bool menu_animation_push(menu_animation_t *anim, float duration, - float target_value, - float* subject, + float target_value, float* subject, enum menu_animation_easing_type easing_enum, - tween_cb cb) + unsigned tag, tween_cb cb) { struct tween t; if (!subject) return false; - t.alive = 1; + t.alive = true; t.duration = duration; t.running_since = 0; t.initial_value = *subject; t.target_value = target_value; t.subject = subject; + t.tag = tag; t.cb = cb; switch (easing_enum) @@ -441,23 +485,17 @@ bool menu_animation_push( if (!t.easing || t.duration == 0 || t.initial_value == t.target_value) return false; - if (anim->size >= anim->capacity) - { - anim->capacity++; - anim->list = (struct tween*)realloc(anim->list, - anim->capacity * sizeof(struct tween)); - } - - anim->list[anim->size++] = t; + menu_animation_push_internal(anim, &t); return true; } static int menu_animation_iterate( - struct tween *tween, - float dt, - unsigned *active_tweens) + menu_animation_t *anim, unsigned idx, + float dt, unsigned *active_tweens) { + struct tween *tween = &anim->list[idx]; + if (!tween->alive) return -1; @@ -472,7 +510,10 @@ static int menu_animation_iterate( if (tween->running_since >= tween->duration) { *tween->subject = tween->target_value; - tween->alive = 0; + tween->alive = false; + + if (idx < anim->first_dead) + anim->first_dead = idx; if (tween->cb) tween->cb(); @@ -490,11 +531,12 @@ bool menu_animation_update(menu_animation_t *anim, float dt) unsigned active_tweens = 0; for(i = 0; i < anim->size; i++) - menu_animation_iterate(&anim->list[i], dt, &active_tweens); + menu_animation_iterate(anim, i, dt, &active_tweens); if (!active_tweens) { anim->size = 0; + anim->first_dead = 0; return false; } diff --git a/menu/menu_animation.h b/menu/menu_animation.h index 94f465e2b2..c340eeb835 100644 --- a/menu/menu_animation.h +++ b/menu/menu_animation.h @@ -35,12 +35,13 @@ typedef void (*tween_cb) (void); struct tween { - int alive; + bool alive; float duration; float running_since; float initial_value; float target_value; float* subject; + unsigned tag; easingFunc easing; tween_cb cb; }; @@ -51,6 +52,7 @@ typedef struct menu_animation size_t capacity; size_t size; + size_t first_dead; bool is_active; /* Delta timing */ @@ -118,11 +120,15 @@ void menu_animation_kill_by_subject( size_t count, const void *subjects); +void menu_animation_kill_by_tag(menu_animation_t *anim, unsigned tag); + +/* Use -1 for untagged */ bool menu_animation_push( menu_animation_t *animation, float duration, float target_value, float* subject, - enum menu_animation_easing_type easing_enum, tween_cb cb); + enum menu_animation_easing_type easing_enum, + unsigned tag, tween_cb cb); bool menu_animation_update( menu_animation_t *animation, diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 49a32712bd..488f240f18 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -1935,6 +1935,7 @@ int menu_displaylist_push_list(menu_displaylist_info_t *info, unsigned type) ret = menu_displaylist_parse_load_core_list(info); need_push = true; + need_refresh = true; break; case DISPLAYLIST_OPTIONS: menu_list_clear(info->list); @@ -2179,6 +2180,7 @@ int menu_displaylist_push_list(menu_displaylist_info_t *info, unsigned type) menu_list_clear(info->list); menu_displaylist_parse_system_info(info); need_push = true; + need_refresh = true; break; case DISPLAYLIST_CORES_SUPPORTED: case DISPLAYLIST_CORES_COLLECTION_SUPPORTED: