diff --git a/menu/backend/menu_backend.h b/menu/backend/menu_backend.h index 845275ef24..2527ebad04 100644 --- a/menu/backend/menu_backend.h +++ b/menu/backend/menu_backend.h @@ -12,6 +12,8 @@ typedef struct menu_file_list_cbs int (*action_ok)(const char *path, const char *label, unsigned type, size_t idx); int (*action_start)(unsigned type, const char *label, unsigned action); + int (*action_content_list_switch)(void *data, void *userdata, const char + *path, const char *label, unsigned type); int (*action_toggle)(unsigned type, const char *label, unsigned action); } menu_file_list_cbs_t; diff --git a/menu/backend/menu_common_backend.c b/menu/backend/menu_common_backend.c index 342324c04f..b68c3e7f6f 100644 --- a/menu/backend/menu_common_backend.c +++ b/menu/backend/menu_common_backend.c @@ -585,7 +585,6 @@ static int menu_common_iterate(unsigned action) menu_navigation_clear(driver.menu, false); break; - case MENU_ACTION_SCROLL_UP: menu_navigation_descend_alphabet(driver.menu, &driver.menu->selection_ptr); break; @@ -615,7 +614,25 @@ static int menu_common_iterate(unsigned action) break; case MENU_ACTION_LEFT: case MENU_ACTION_RIGHT: - if (is_category) + if (file_list_get_size(driver.menu->menu_list->menu_stack) == 1 && !strcmp(driver.menu_ctx->ident, "xmb")) + { + if (action == MENU_ACTION_LEFT && driver.menu->cat_selection_ptr == 0) + break; + file_list_copy(driver.menu->menu_list->selection_buf, driver.menu->menu_list->selection_buf_old); + file_list_copy(driver.menu->menu_list->menu_stack, driver.menu->menu_list->menu_stack_old); + driver.menu->selection_ptr_old = driver.menu->selection_ptr; + driver.menu->cat_selection_ptr_old = driver.menu->cat_selection_ptr; + driver.menu->cat_selection_ptr += action == MENU_ACTION_LEFT ? -1 : 1; + driver.menu->selection_ptr = 0; + if (cbs && cbs->action_content_list_switch) + return cbs->action_content_list_switch( + driver.menu->menu_list->selection_buf, + driver.menu->menu_list->menu_stack, + "", + "", + 0); + } + else if (is_category) { if (cbs && cbs->action_toggle) ret = cbs->action_toggle(type_offset, label_offset, action); diff --git a/menu/disp/xmb.c b/menu/disp/xmb.c index 21cdec598b..717c7eed1b 100644 --- a/menu/disp/xmb.c +++ b/menu/disp/xmb.c @@ -541,22 +541,91 @@ static xmb_node_t* xmb_node_for_core(int i) return node; } -static void xmb_populate_entries(void *data, const char *path, - const char *label, unsigned k) +static void xmb_list_switch_old(file_list_t *list, int dir, size_t current) { - unsigned i, j, current, end; + int i; xmb_handle_t *xmb = (xmb_handle_t*)driver.menu->userdata; if (!xmb) return; - - (void)current; - (void)end; - (void)i; + + for (i = 0; i < file_list_get_size(list); i++) + { + xmb_node_t *node = (xmb_node_t*)file_list_get_userdata_at_offset(list, i); + + if (!xmb) + continue; + + add_tween(XMB_DELAY, 0, &node->alpha, &inOutQuad, NULL); + add_tween(XMB_DELAY, 0, &node->label_alpha, &inOutQuad, NULL); + add_tween(XMB_DELAY, -xmb->hspacing*dir, &node->x, &inOutQuad, NULL); + } +} + +static void xmb_list_switch_new(file_list_t *list, int dir, size_t current) +{ + int i; + xmb_handle_t *xmb = (xmb_handle_t*)driver.menu->userdata; + + if (!xmb) + return; + + for (i = 0; i < file_list_get_size(list); i++) + { + xmb_node_t *node = (xmb_node_t*)file_list_get_userdata_at_offset(list, i); + + if (!xmb) + continue; + + node->x = xmb->hspacing * dir; + + float ia = (i == current) ? 1.0 : 0.5; + add_tween(XMB_DELAY, ia, &node->alpha, &inOutQuad, NULL); + add_tween(XMB_DELAY, ia, &node->label_alpha, &inOutQuad, NULL); + add_tween(XMB_DELAY, 0, &node->x, &inOutQuad, NULL); + } +} + +static void xmb_populate_entries(void *data, const char *path, + const char *label, unsigned k) +{ + int dir; + unsigned j; + xmb_handle_t *xmb = (xmb_handle_t*)driver.menu->userdata; + + if (!xmb) + return; + + if (driver.menu->cat_selection_ptr_old != driver.menu->cat_selection_ptr) + { + dir = driver.menu->cat_selection_ptr > driver.menu->cat_selection_ptr_old ? 1 : -1; + + xmb->active_category += dir; + + for (j = 0; j < xmb->num_categories; j++) + { + xmb_node_t *node = j ? xmb_node_for_core(j-1) : &xmb->settings_node; + + if (!node) + continue; + + float ia = j == xmb->active_category ? xmb->c_active_alpha : xmb->c_passive_alpha; + float iz = j == xmb->active_category ? xmb->c_active_zoom : xmb->c_passive_zoom; + add_tween(XMB_DELAY, ia, &node->alpha, &inOutQuad, NULL); + add_tween(XMB_DELAY, iz, &node->zoom, &inOutQuad, NULL); + } + + add_tween(XMB_DELAY, xmb->hspacing*-(float)driver.menu->cat_selection_ptr, &xmb->x, &inOutQuad, NULL); + dir = driver.menu->cat_selection_ptr > driver.menu->cat_selection_ptr_old ? 1 : -1; + xmb_list_switch_old(driver.menu->menu_list->selection_buf_old, dir, driver.menu->selection_ptr_old); + xmb_list_switch_new(driver.menu->menu_list->selection_buf, dir, driver.menu->selection_ptr); + driver.menu->cat_selection_ptr_old = driver.menu->cat_selection_ptr; + return; + } xmb->depth = file_list_get_size(driver.menu->menu_list->menu_stack); - int dir = 0; + dir = 0; if (xmb->depth > xmb->old_depth) dir = 1; else if (xmb->depth < xmb->old_depth) @@ -1255,6 +1324,16 @@ static void xmb_context_destroy(void *data) for (i = 0; i < XMB_TEXTURE_LAST; i++) glDeleteTextures(1, &xmb->textures[i].id); + + for (i = 1; i < xmb->num_categories; i++) + { + xmb_node_t *node = xmb_node_for_core(i-1); + + if (!node) + continue; + + glDeleteTextures(1, &node->icon); + } } diff --git a/menu/menu_driver.h b/menu/menu_driver.h index a648ac9e14..831b0aa948 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -78,6 +78,8 @@ typedef struct size_t begin; menu_list_t *menu_list; + size_t cat_selection_ptr; + size_t cat_selection_ptr_old; size_t selection_ptr; size_t selection_ptr_old; bool need_refresh; diff --git a/menu/menu_entries.c b/menu/menu_entries.c index ad094d82b6..6374fcf257 100644 --- a/menu/menu_entries.c +++ b/menu/menu_entries.c @@ -129,7 +129,7 @@ int setting_set_flags(rarch_setting_t *setting) return 0; } -static int entries_push_main_menu_list(menu_handle_t *menu, +int entries_push_main_menu_list(menu_handle_t *menu, file_list_t *list, const char *path, const char *label, unsigned menu_type) diff --git a/menu/menu_entries.h b/menu/menu_entries.h index 05a7fa19b1..ae7f747462 100644 --- a/menu/menu_entries.h +++ b/menu/menu_entries.h @@ -40,6 +40,11 @@ void menu_entries_build_scroll_indices(file_list_t *list); int setting_set_flags(rarch_setting_t *setting); +int entries_push_main_menu_list(menu_handle_t *menu, + file_list_t *list, + const char *path, const char *label, + unsigned menu_type); + #ifdef __cplusplus } #endif diff --git a/menu/menu_entries_cbs.c b/menu/menu_entries_cbs.c index b601ef79ae..b73bc67617 100644 --- a/menu/menu_entries_cbs.c +++ b/menu/menu_entries_cbs.c @@ -1663,6 +1663,58 @@ static int deferred_push_history_list(void *data, void *userdata, return 0; } +static int deferred_push_content_list(void *data, void *userdata, + const char *path, const char *label, unsigned type) +{ + unsigned i; + size_t list_size = 0; + file_list_t *list = (file_list_t*)data; + + if (!list || !driver.menu) + return -1; + + if (driver.menu->cat_selection_ptr == 0) + { + menu_navigation_clear(driver.menu, true); + entries_push_main_menu_list(driver.menu, driver.menu->menu_list->selection_buf, + "", "Main Menu", 0); + return 0; + } + + menu_list_clear(list); + list_size = content_playlist_size(g_defaults.history); + + for (i = 0; i < list_size; i++) + { + char fill_buf[PATH_MAX]; + const char *core_name = NULL; + + content_playlist_get_index(g_defaults.history, i, + &path, NULL, &core_name); + strlcpy(fill_buf, core_name, sizeof(fill_buf)); + + if (path) + { + char path_short[PATH_MAX]; + fill_short_pathname_representation(path_short,path,sizeof(path_short)); + snprintf(fill_buf,sizeof(fill_buf),"%s (%s)", + path_short,core_name); + } + + menu_list_push(list, fill_buf, "", + MENU_FILE_PLAYLIST_ENTRY, 0); + } + + driver.menu->scroll_indices_size = 0; + menu_entries_build_scroll_indices(list); + menu_entries_refresh(list); + + if (driver.menu_ctx && driver.menu_ctx->populate_entries) + driver.menu_ctx->populate_entries(driver.menu, path, label, type); + + return 0; +} + static int deferred_push_configurations(void *data, void *userdata, const char *path, const char *label, unsigned type) { @@ -1942,6 +1994,15 @@ static void menu_entries_cbs_init_bind_start(menu_file_list_cbs_t *cbs, cbs->action_start = action_start_core_setting; } +static void menu_entries_cbs_init_bind_content_list_switch(menu_file_list_cbs_t *cbs, + const char *path, const char *label, unsigned type, size_t idx) +{ + if (!cbs) + return; + + cbs->action_content_list_switch = deferred_push_content_list; +} + static void menu_entries_cbs_init_bind_ok(menu_file_list_cbs_t *cbs, const char *path, const char *label, unsigned type, size_t idx) { @@ -2106,6 +2167,7 @@ void menu_entries_cbs_init(void *data, { menu_entries_cbs_init_bind_ok(cbs, path, label, type, idx); menu_entries_cbs_init_bind_start(cbs, path, label, type, idx); + menu_entries_cbs_init_bind_content_list_switch(cbs, path, label, type, idx); menu_entries_cbs_init_bind_toggle(cbs, path, label, type, idx); menu_entries_cbs_init_bind_deferred_push(cbs, path, label, type, idx); }