diff --git a/file_list.c b/file_list.c index 18621a10d5..7117f0b8e5 100644 --- a/file_list.c +++ b/file_list.c @@ -100,6 +100,29 @@ void file_list_clear(file_list_t *list) list->size = 0; } +void file_list_copy(file_list_t *list, file_list_t *list_old) +{ + size_t i; + + list_old->size = list->size; + list_old->capacity = list->capacity; + + list_old->list = (struct item_file*)realloc(list_old->list, + list_old->capacity * sizeof(struct item_file)); + + for (i = 0; i < list->size; i++) + { + list_old->list[i].path = strdup(list->list[i].path); + list_old->list[i].label = strdup(list->list[i].label); + if (list->list[i].alt) + list_old->list[i].alt = strdup(list->list[i].alt); + list_old->list[i].type = list->list[i].type; + list_old->list[i].directory_ptr = list->list[i].directory_ptr; + list_old->list[i].userdata = list->list[i].userdata; + list_old->list[i].actiondata = list->list[i].actiondata; + } +} + void file_list_set_label_at_offset(file_list_t *list, size_t index, const char *label) { diff --git a/file_list.h b/file_list.h index 875a429eb4..4f604cf0fe 100644 --- a/file_list.h +++ b/file_list.h @@ -55,6 +55,7 @@ void file_list_push(file_list_t *userdata, const char *path, const char *label, unsigned type, size_t current_directory_ptr); void file_list_pop(file_list_t *list, size_t *directory_ptr); void file_list_clear(file_list_t *list); +void file_list_copy(file_list_t *list, file_list_t *list_old); void file_list_get_last(const file_list_t *list, const char **path, const char **label, diff --git a/frontend/menu/backend/menu_common_backend.c b/frontend/menu/backend/menu_common_backend.c index 0c58b26644..03787d15d9 100644 --- a/frontend/menu/backend/menu_common_backend.c +++ b/frontend/menu/backend/menu_common_backend.c @@ -223,6 +223,11 @@ static int menu_settings_iterate(unsigned action, break; case MENU_ACTION_CANCEL: +#ifdef HAVE_XMB + 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; +#endif apply_deferred_settings(); menu_list_pop_stack(driver.menu->menu_list); break; @@ -231,6 +236,11 @@ static int menu_settings_iterate(unsigned action, 0, driver.menu->selection_ptr); break; case MENU_ACTION_OK: +#ifdef HAVE_XMB + 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; +#endif if (cbs && cbs->action_ok) return cbs->action_ok(path, label, type, driver.menu->selection_ptr); /* fall-through */ @@ -635,10 +645,20 @@ static int menu_common_iterate(unsigned action) break; case MENU_ACTION_CANCEL: +#ifdef HAVE_XMB + 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; +#endif menu_list_pop_stack(driver.menu->menu_list); break; case MENU_ACTION_OK: +#ifdef HAVE_XMB + 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; +#endif ret = menu_action_ok(cbs); break; diff --git a/frontend/menu/disp/glui.c b/frontend/menu/disp/glui.c index 60d4be154a..1790938225 100644 --- a/frontend/menu/disp/glui.c +++ b/frontend/menu/disp/glui.c @@ -303,7 +303,7 @@ static void glui_frame(void) driver.menu->menu_list->selection_buf->list[i].label); (void)setting; - disp_set_label(&w, type, i, label, + disp_set_label(driver.menu->menu_list->selection_buf, &w, type, i, label, type_str, sizeof(type_str), entry_label, path, path_buf, sizeof(path_buf)); diff --git a/frontend/menu/disp/rgui.c b/frontend/menu/disp/rgui.c index 5364e48457..9e6e9a53b9 100644 --- a/frontend/menu/disp/rgui.c +++ b/frontend/menu/disp/rgui.c @@ -352,7 +352,7 @@ static void rgui_render(void) driver.menu->menu_list->selection_buf->list[i].label); (void)setting; - disp_set_label(&w, type, i, label, + disp_set_label(driver.menu->menu_list->selection_buf, &w, type, i, label, type_str, sizeof(type_str), entry_label, path, path_buf, sizeof(path_buf)); diff --git a/frontend/menu/disp/shared.h b/frontend/menu/disp/shared.h index fabacb042c..4da4dce9dc 100644 --- a/frontend/menu/disp/shared.h +++ b/frontend/menu/disp/shared.h @@ -129,7 +129,8 @@ static void get_title(const char *label, const char *dir, } } -static void disp_set_label(unsigned *w, unsigned type, unsigned i, +static void disp_set_label(file_list_t* list, + unsigned *w, unsigned type, unsigned i, const char *label, char *type_str, size_t type_str_size, const char *entry_label, @@ -148,7 +149,7 @@ static void disp_set_label(unsigned *w, unsigned type, unsigned i, if (type == MENU_FILE_CORE) { strlcpy(type_str, "(CORE)", type_str_size); - menu_list_get_alt_at_offset(driver.menu->menu_list->selection_buf, i, &path); + menu_list_get_alt_at_offset(list, i, &path); *w = 6; } else if (type == MENU_FILE_PLAIN) diff --git a/frontend/menu/disp/xmb.c b/frontend/menu/disp/xmb.c index 295ad856d1..7dc56e6901 100644 --- a/frontend/menu/disp/xmb.c +++ b/frontend/menu/disp/xmb.c @@ -43,7 +43,9 @@ typedef struct { float alpha; + float label_alpha; float zoom; + float x; float y; } xmb_node_t; @@ -84,6 +86,7 @@ typedef struct xmb_handle int icon_size; float x; float alpha; + float arrow_alpha; float hspacing; float vspacing; float font_size; @@ -371,9 +374,13 @@ static void xmb_selection_pointer_changed(void) if (!node) continue; - iy = (i < current) ? xmb->vspacing * - (i - current + xmb->above_item_offset) : - xmb->vspacing * (i - current + xmb->under_item_offset); + if (i < current) + if (xmb->depth > 1) + iy = xmb->vspacing * (i - (int)current + xmb->above_subitem_offset); + else + iy = xmb->vspacing * (i - (int)current + xmb->above_item_offset); + else + iy = xmb->vspacing * (i - (int)current + xmb->under_item_offset); if (i == current) { @@ -383,11 +390,86 @@ static void xmb_selection_pointer_changed(void) } add_tween(XMB_DELAY, ia, &node->alpha, &inOutQuad, NULL); + add_tween(XMB_DELAY, ia, &node->label_alpha, &inOutQuad, NULL); add_tween(XMB_DELAY, iz, &node->zoom, &inOutQuad, NULL); add_tween(XMB_DELAY, iy, &node->y, &inOutQuad, NULL); } } +static void xmb_list_open_old(file_list_t *list, int dir, size_t current) +{ + xmb_handle_t *xmb = (xmb_handle_t*)driver.menu->userdata; + + if (!xmb) + return; + + int i; + for (i = 0; i < file_list_get_size(list); i++) + { + xmb_node_t *node = NULL; + node = (xmb_node_t*)file_list_get_userdata_at_offset(list, i); + float ia = i == current ? xmb->i_active_alpha : 0; + if (dir == -1) ia = 0; + add_tween(XMB_DELAY, ia, &node->alpha, &inOutQuad, NULL); + add_tween(XMB_DELAY, 0, &node->label_alpha, &inOutQuad, NULL); + //if (i == current) + add_tween(XMB_DELAY, xmb->icon_size*dir*-2, &node->x, &inOutQuad, NULL); + //else + // add_tween(XMB_DELAY, xmb->icon_size*dir*-1, &node->x, &inOutQuad, NULL); + } +} + +static void xmb_list_open_new(file_list_t *list, int dir, size_t current) +{ + xmb_handle_t *xmb = (xmb_handle_t*)driver.menu->userdata; + + if (!xmb) + return; + + int i; + for (i = 0; i < file_list_get_size(list); i++) + { + xmb_node_t *node = NULL; + node = (xmb_node_t*)file_list_get_userdata_at_offset(list, i); + node->label_alpha = 0; + if (dir == 1 || (dir == -1 && i != current)) + node->alpha = 0; + //if (dir == 1 || (dir == -1 && i == current)) + node->x = xmb->icon_size*dir*2; + //else + // node->x = xmb->icon_size*dir; + + float iy = 0; + + if (i < current) + if (xmb->depth > 1) + iy = xmb->vspacing * (i - (int)current + xmb->above_subitem_offset); + else + iy = xmb->vspacing * (i - (int)current + xmb->above_item_offset); + else + iy = xmb->vspacing * (i - (int)current + xmb->under_item_offset); + + if (i == current) + iy = xmb->vspacing * xmb->active_item_factor; + + node->y = iy; + + if (i == current) + node->zoom = 1; + } + for (i = 0; i < file_list_get_size(list); i++) + { + xmb_node_t *node = NULL; + node = (xmb_node_t*)file_list_get_userdata_at_offset(list, i); + 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); + } + + xmb->old_depth = xmb->depth; +} + static void xmb_populate_entries(void *data, const char *path, const char *label, unsigned j) { @@ -397,45 +479,110 @@ static void xmb_populate_entries(void *data, const char *path, if (!xmb) return; - xmb->depth = menu_list_get_stack_size(driver.menu->menu_list); + xmb->depth = file_list_get_size(driver.menu->menu_list->menu_stack); - if (xmb->depth != xmb->old_depth) - add_tween(XMB_DELAY, xmb->x + (xmb->depth-xmb->old_depth)*-20, - &xmb->x, &inOutQuad, NULL); + int dir = 0; + if (xmb->depth > xmb->old_depth) + dir = 1; + else if (xmb->depth < xmb->old_depth) + dir = -1; - current = driver.menu->selection_ptr; - end = menu_list_get_size(driver.menu->menu_list); + xmb_list_open_old(driver.menu->menu_list->selection_buf_old, dir, driver.menu->selection_ptr_old); + xmb_list_open_new(driver.menu->menu_list->selection_buf, dir, driver.menu->selection_ptr); - for (i = 0; i < end; i++) - { - xmb_node_t *node = (xmb_node_t*)file_list_get_userdata_at_offset( - driver.menu->menu_list->selection_buf, i); + if (xmb->depth == 1 || xmb->depth == 2) + add_tween(XMB_DELAY, xmb->icon_size*-(xmb->depth*2-2), &xmb->x, &inOutQuad, NULL); - if (!node) - continue; + if (xmb->depth == 1) + add_tween(XMB_DELAY, 0, &xmb->arrow_alpha, &inOutQuad, NULL); - node->alpha = xmb->i_passive_alpha; - node->zoom = xmb->i_passive_zoom; - node->y = (i < current) ? xmb->vspacing * - (i - current + xmb->above_item_offset) : - xmb->vspacing * (i - current + xmb->under_item_offset); - - if (i == current) - { - node->alpha = xmb->i_active_alpha; - node->zoom = xmb->i_active_zoom; - node->y = xmb->vspacing * xmb->active_item_factor; - } - } + if (xmb->depth == 2) + add_tween(XMB_DELAY, 1, &xmb->arrow_alpha, &inOutQuad, NULL); xmb->old_depth = xmb->depth; } +static void xmb_draw_items(file_list_t *list, file_list_t *stack, size_t current) +{ + int i; + const char *dir = NULL; + const char *label = NULL; + unsigned menu_type = 0; + size_t end = file_list_get_size(list); + + xmb_handle_t *xmb = (xmb_handle_t*)driver.menu->userdata; + if (!xmb || !list->size) + return; + + file_list_get_last(stack, &dir, &label, &menu_type); + + for (i = 0; i < end; i++) + { + char val_buf[PATH_MAX], path_buf[PATH_MAX]; + char name[256], value[256]; + const char *path = NULL, *entry_label = NULL; + unsigned type = 0, w = 0; + xmb_node_t *node = NULL; + + menu_list_get_at_offset(list, i, &path, &entry_label, &type); + node = (xmb_node_t*)file_list_get_userdata_at_offset(list, i); + + disp_set_label(list, &w, type, i, label, + val_buf, sizeof(val_buf), + entry_label, path, + path_buf, sizeof(path_buf)); + + GLuint icon = 0; + switch(type) + { + case MENU_FILE_DIRECTORY: + icon = xmb->textures[XMB_TEXTURE_FOLDER].id; + break; + case MENU_FILE_PLAIN: + icon = xmb->textures[XMB_TEXTURE_FILE].id; + break; + case MENU_FILE_CARCHIVE: + icon = xmb->textures[XMB_TEXTURE_ZIP].id; + break; + case MENU_FILE_CORE: + icon = xmb->textures[XMB_TEXTURE_CORE].id; + break; + default: + icon = xmb->textures[XMB_TEXTURE_SETTING].id; + break; + } + + xmb_draw_icon(icon, + node->x + xmb->margin_left + xmb->hspacing - xmb->icon_size/2.0, + xmb->margin_top + node->y + xmb->icon_size/2.0, + node->alpha, + 0, + node->zoom); + + menu_ticker_line(name, 35, g_extern.frame_count / 20, path_buf, + (i == current)); + + xmb_draw_text(name, + node->x + xmb->margin_left + xmb->hspacing + xmb->label_margin_left, + xmb->margin_top + node->y + xmb->label_margin_top, + 1, + node->label_alpha); + + menu_ticker_line(value, 35, g_extern.frame_count / 20, val_buf, + (i == current)); + + xmb_draw_text(value, + node->x + xmb->margin_left + xmb->hspacing + + xmb->label_margin_left + xmb->setting_margin_left, + xmb->margin_top + node->y + xmb->label_margin_top, + 1, + node->label_alpha); + } +} + static void xmb_frame(void) { - int i, current; char title_msg[64]; - size_t end; const char *dir = NULL; const char *label = NULL; unsigned menu_type = 0; @@ -476,73 +623,21 @@ static void xmb_frame(void) xmb_draw_text(title_msg, xmb->title_margin_left, gl->win_height - xmb->title_margin_bottom, 1, 1); - end = menu_list_get_size(driver.menu->menu_list); - current = driver.menu->selection_ptr; + xmb_draw_icon(xmb->textures[XMB_TEXTURE_ARROW].id, + xmb->x + xmb->margin_left + xmb->hspacing - xmb->icon_size/2.0 + xmb->icon_size, + xmb->margin_top + xmb->icon_size/2.0 + xmb->vspacing * xmb->active_item_factor, + xmb->arrow_alpha, + 0, + 1); - for (i = 0; i < end; i++) - { - char val_buf[PATH_MAX], path_buf[PATH_MAX]; - char name[256], value[256]; - const char *path = NULL, *entry_label = NULL; - unsigned type = 0, w = 0; - xmb_node_t *node = NULL; - - menu_list_get_at_offset(driver.menu->menu_list->selection_buf, i, &path, - &entry_label, &type); - node = (xmb_node_t*)file_list_get_userdata_at_offset( - driver.menu->menu_list->selection_buf, i); - - disp_set_label(&w, type, i, label, - val_buf, sizeof(val_buf), - entry_label, path, - path_buf, sizeof(path_buf)); - - GLuint icon = 0; - switch(type) - { - case MENU_FILE_DIRECTORY: - icon = xmb->textures[XMB_TEXTURE_FOLDER].id; - break; - case MENU_FILE_PLAIN: - icon = xmb->textures[XMB_TEXTURE_FILE].id; - break; - case MENU_FILE_CARCHIVE: - icon = xmb->textures[XMB_TEXTURE_ZIP].id; - break; - case MENU_FILE_CORE: - icon = xmb->textures[XMB_TEXTURE_CORE].id; - break; - default: - icon = xmb->textures[XMB_TEXTURE_SETTING].id; - break; - } - - xmb_draw_icon(icon, - xmb->x + xmb->margin_left + xmb->hspacing - xmb->icon_size/2.0, - xmb->margin_top + node->y + xmb->icon_size/2.0, - node->alpha, - 0, - node->zoom); - - menu_ticker_line(name, 35, g_extern.frame_count / 20, path_buf, - (i == current)); - - xmb_draw_text(name, - xmb->x + xmb->margin_left + xmb->hspacing + xmb->label_margin_left, - xmb->margin_top + node->y + xmb->label_margin_top, - 1, - node->alpha); - - menu_ticker_line(value, 35, g_extern.frame_count / 20, val_buf, - (i == current)); - - xmb_draw_text(value, - xmb->x + xmb->margin_left + xmb->hspacing + - xmb->label_margin_left + xmb->setting_margin_left, - xmb->margin_top + node->y + xmb->label_margin_top, - 1, - node->alpha); - } + xmb_draw_items( + driver.menu->menu_list->selection_buf_old, + driver.menu->menu_list->menu_stack_old, + driver.menu->selection_ptr_old); + xmb_draw_items( + driver.menu->menu_list->selection_buf, + driver.menu->menu_list->menu_stack, + driver.menu->selection_ptr); xmb_draw_icon(xmb->textures[XMB_TEXTURE_SETTINGS].id, xmb->x + xmb->margin_left + xmb->hspacing - xmb->icon_size / 2.0, @@ -629,6 +724,7 @@ static void *xmb_init(void) xmb->x = 0; xmb->alpha = 1.0f; + xmb->arrow_alpha = 0; xmb->depth = 1; xmb->old_depth = 1; @@ -910,8 +1006,10 @@ static void xmb_list_insert(void *data, iy = xmb->vspacing * xmb->active_item_factor; node->alpha = (i == current) ? xmb->i_active_alpha : xmb->i_passive_alpha; + node->label_alpha = node->alpha; node->zoom = (i == current) ? xmb->i_active_zoom : xmb->i_passive_zoom; node->y = iy; + node->x = 0; } static void xmb_list_delete(void *data, size_t idx, diff --git a/frontend/menu/menu_driver.h b/frontend/menu/menu_driver.h index 413413a550..6a19411faa 100644 --- a/frontend/menu/menu_driver.h +++ b/frontend/menu/menu_driver.h @@ -81,6 +81,7 @@ typedef struct menu_list_t *menu_list; size_t selection_ptr; + size_t selection_ptr_old; bool need_refresh; bool msg_force; bool push_start_screen; diff --git a/frontend/menu/menu_list.c b/frontend/menu/menu_list.c index 0d592a0ed6..c9939811a8 100644 --- a/frontend/menu/menu_list.c +++ b/frontend/menu/menu_list.c @@ -57,6 +57,8 @@ void *menu_list_new(void) list->menu_stack = (file_list_t*)calloc(1, sizeof(file_list_t)); list->selection_buf = (file_list_t*)calloc(1, sizeof(file_list_t)); + list->menu_stack_old = (file_list_t*)calloc(1, sizeof(file_list_t)); + list->selection_buf_old = (file_list_t*)calloc(1, sizeof(file_list_t)); if (!list->menu_stack || !list->selection_buf) { diff --git a/frontend/menu/menu_list.h b/frontend/menu/menu_list.h index 3f78d0f02d..7120ccad1b 100644 --- a/frontend/menu/menu_list.h +++ b/frontend/menu/menu_list.h @@ -26,7 +26,9 @@ extern "C" { typedef struct menu_list { file_list_t *menu_stack; + file_list_t *menu_stack_old; file_list_t *selection_buf; + file_list_t *selection_buf_old; } menu_list_t; void menu_list_free(menu_list_t *menu_list);