From 57dd10b5eb43a14c217330d07e668e36b7d6a8f1 Mon Sep 17 00:00:00 2001 From: natinusala Date: Wed, 27 Feb 2019 19:05:22 +0100 Subject: [PATCH] ozone: first pass of thumbnails support --- .vscode/settings.json | 5 +- menu/drivers/ozone/ozone.c | 508 ++++++++++++++++++++++++++++- menu/drivers/ozone/ozone.h | 21 +- menu/drivers/ozone/ozone_entries.c | 123 ++++++- menu/drivers/ozone/ozone_sidebar.c | 10 +- 5 files changed, 648 insertions(+), 19 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9740a3edac..e6425ac914 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,7 +63,10 @@ "xiosbase": "c", "xstring": "c", "xtree": "c", - "xutility": "c" + "xutility": "c", + "menu_input_dialog.h": "c", + "menu_filebrowser.h": "c", + "ozone_sidebar.h": "c" }, "C_Cpp.dimInactiveRegions": false, } \ No newline at end of file diff --git a/menu/drivers/ozone/ozone.c b/menu/drivers/ozone/ozone.c index 56c93db027..a2da8d94f7 100644 --- a/menu/drivers/ozone/ozone.c +++ b/menu/drivers/ozone/ozone.c @@ -41,9 +41,11 @@ #include "../../menu_driver.h" #include "../../menu_animation.h" #include "../../menu_input.h" +#include "../../playlist.h" #include "../../widgets/menu_input_dialog.h" #include "../../widgets/menu_osk.h" +#include "../../widgets/menu_filebrowser.h" #include "../../../configuration.h" #include "../../../content.h" @@ -54,6 +56,32 @@ #include "../../../tasks/tasks_internal.h" #include "../../../dynamic.h" +const char *ozone_thumbnails_ident(char pos) +{ + char folder = 0; + settings_t *settings = config_get_ptr(); + + if (pos == 'R') + folder = settings->uints.menu_thumbnails; + if (pos == 'L') + folder = settings->uints.menu_left_thumbnails; + + switch (folder) + { + case 1: + return "Named_Snaps"; + case 2: + return "Named_Titles"; + case 3: + return "Named_Boxarts"; + case 0: + default: + break; + } + + return msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF); +} + ozone_node_t *ozone_alloc_node(void) { ozone_node_t *node = (ozone_node_t*)malloc(sizeof(*node)); @@ -63,6 +91,7 @@ ozone_node_t *ozone_alloc_node(void) node->console_name = NULL; node->icon = 0; node->content_icon = 0; + node->fullpath = NULL; return node; } @@ -97,6 +126,13 @@ static void ozone_free_node(ozone_node_t *node) if (node->console_name) free(node->console_name); + node->console_name = NULL; + + if (node->fullpath) + free(node->fullpath); + + node->fullpath = NULL; + free(node); } @@ -338,6 +374,200 @@ static void ozone_free(void *data) if (!string_is_empty(ozone->pending_message)) free(ozone->pending_message); + + if (!string_is_empty(ozone->thumbnail_content)) + free(ozone->thumbnail_content); + + if (!string_is_empty(ozone->thumbnail_system)) + free(ozone->thumbnail_system); + + if (!string_is_empty(ozone->thumbnail_file_path)) + free(ozone->thumbnail_file_path); + + if (!string_is_empty(ozone->left_thumbnail_file_path)) + free(ozone->left_thumbnail_file_path); + } +} + +static void ozone_update_thumbnail_path(void *data, unsigned i, char pos) +{ + menu_entry_t entry; + unsigned entry_type = 0; + char new_path[PATH_MAX_LENGTH] = {0}; + settings_t *settings = config_get_ptr(); + ozone_handle_t *ozone = (ozone_handle_t*)data; + playlist_t *playlist = NULL; + const char *dir_thumbnails = settings->paths.directory_thumbnails; + + menu_entry_init(&entry); + + if (!ozone || string_is_empty(dir_thumbnails)) + goto end; + + menu_entry_get(&entry, 0, i, NULL, true); + + entry_type = menu_entry_get_type_new(&entry); + + if (entry_type == FILE_TYPE_IMAGEVIEWER || entry_type == FILE_TYPE_IMAGE) + { + file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); + ozone_node_t *node = (ozone_node_t*) + file_list_get_userdata_at_offset(selection_buf, i); + + if (node && !string_is_empty(node->fullpath) && + (pos == 'R' || (pos == 'L' && string_is_equal(ozone_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))))) + { + if (!string_is_empty(entry.path)) + fill_pathname_join( + new_path, + node->fullpath, + entry.path, + sizeof(new_path)); + + goto end; + } + } + else if (filebrowser_get_type() != FILEBROWSER_NONE) + { + video_driver_texture_unload(&ozone->thumbnail); + goto end; + } + + playlist = playlist_get_cached(); + + if (playlist) + { + const char *core_name = NULL; + playlist_get_index(playlist, i, + NULL, NULL, NULL, &core_name, NULL, NULL); + + if (string_is_equal(core_name, "imageviewer")) + { + if ( + (pos == 'R') || + ( + pos == 'L' && + string_is_equal(ozone_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) + ) + ) + { + if (!string_is_empty(entry.label)) + strlcpy(new_path, entry.label, + sizeof(new_path)); + } + else + video_driver_texture_unload(&ozone->left_thumbnail); + goto end; + } + } + + /* Append thumbnail system directory */ + if (!string_is_empty(ozone->thumbnail_system)) + fill_pathname_join( + new_path, + dir_thumbnails, + ozone->thumbnail_system, + sizeof(new_path)); + + if (!string_is_empty(new_path)) + { + char *tmp_new2 = (char*) + malloc(PATH_MAX_LENGTH * sizeof(char)); + + tmp_new2[0] = '\0'; + + /* Append Named_Snaps/Named_Boxarts/Named_Titles */ + if (pos == 'R') + fill_pathname_join(tmp_new2, new_path, + ozone_thumbnails_ident('R'), PATH_MAX_LENGTH * sizeof(char)); + if (pos == 'L') + fill_pathname_join(tmp_new2, new_path, + ozone_thumbnails_ident('L'), PATH_MAX_LENGTH * sizeof(char)); + + strlcpy(new_path, tmp_new2, + PATH_MAX_LENGTH * sizeof(char)); + free(tmp_new2); + } + + /* Scrub characters that are not cross-platform and/or violate the + * No-Intro filename standard: + * http://datomatic.no-intro.org/stuff/The%20Official%20No-Intro%20Convention%20(20071030).zip + * Replace these characters in the entry name with underscores. + */ + if (!string_is_empty(ozone->thumbnail_content)) + { + char *scrub_char_pointer = NULL; + char *tmp_new = (char*) + malloc(PATH_MAX_LENGTH * sizeof(char)); + char *tmp = strdup(ozone->thumbnail_content); + + tmp_new[0] = '\0'; + + while((scrub_char_pointer = strpbrk(tmp, "&*/:`\"<>?\\|"))) + *scrub_char_pointer = '_'; + + /* Look for thumbnail file with this scrubbed filename */ + + fill_pathname_join(tmp_new, + new_path, + tmp, PATH_MAX_LENGTH * sizeof(char)); + + if (!string_is_empty(tmp_new)) + strlcpy(new_path, + tmp_new, sizeof(new_path)); + + free(tmp_new); + free(tmp); + } + + /* Append png extension */ + if (!string_is_empty(new_path)) + strlcat(new_path, + file_path_str(FILE_PATH_PNG_EXTENSION), + sizeof(new_path)); + +end: + if (ozone && !string_is_empty(new_path)) + { + if (pos == 'R') + ozone->thumbnail_file_path = strdup(new_path); + if (pos == 'L') + ozone->left_thumbnail_file_path = strdup(new_path); + } + + menu_entry_free(&entry); +} + +static void ozone_update_thumbnail_image(void *data) +{ + ozone_handle_t *ozone = (ozone_handle_t*)data; + if (!ozone) + return; + + if (!(string_is_empty(ozone->thumbnail_file_path))) + { + if (filestream_exists(ozone->thumbnail_file_path)) + task_push_image_load(ozone->thumbnail_file_path, + menu_display_handle_thumbnail_upload, NULL); + else + video_driver_texture_unload(&ozone->thumbnail); + + free(ozone->thumbnail_file_path); + ozone->thumbnail_file_path = NULL; + } + + if (!(string_is_empty(ozone->left_thumbnail_file_path))) + { + if (filestream_exists(ozone->left_thumbnail_file_path)) + task_push_image_load(ozone->left_thumbnail_file_path, + menu_display_handle_left_thumbnail_upload, NULL); + else + video_driver_texture_unload(&ozone->left_thumbnail); + + free(ozone->left_thumbnail_file_path); + ozone->left_thumbnail_file_path = NULL; } } @@ -405,7 +635,12 @@ static void ozone_context_reset(void *data, bool is_threaded) ozone->dimensions.sidebar_width = (float) ozone->dimensions.sidebar_width_normal; - ozone->dimensions.thumbnail_bar_width = ozone->dimensions.sidebar_width_normal/2; + ozone->dimensions.thumbnail_bar_width = ozone->dimensions.sidebar_width_normal + - ozone->dimensions.sidebar_entry_icon_size + - ozone->dimensions.sidebar_entry_icon_padding; + + ozone->dimensions.thumbnail_width = ozone->dimensions.thumbnail_bar_width - ozone->dimensions.sidebar_entry_icon_padding * 2; + ozone->dimensions.left_thumbnail_width = ozone->dimensions.thumbnail_width; ozone->dimensions.cursor_size = CURSOR_SIZE * scale; @@ -518,6 +753,22 @@ static void ozone_context_reset(void *data, bool is_threaded) runloop_msg_queue_push(msg_hash_to_str(MSG_MISSING_ASSETS), 1, 256, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } + /* Thumbnails */ + if (!string_is_equal(ozone_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, 0, 'R'); + ozone_update_thumbnail_image(ozone); + } + if (!string_is_equal(ozone_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, 0, 'L'); + ozone_update_thumbnail_image(ozone); + } + + /* TODO: update savestate thumbnail image */ + ozone_restart_cursor_animation(ozone); } } @@ -552,6 +803,10 @@ static void ozone_context_destroy(void *data) for (i = 0; i < OZONE_TAB_TEXTURE_LAST; i++) video_driver_texture_unload(&ozone->tab_textures[i]); + /* Thumbnails */ + video_driver_texture_unload(&ozone->thumbnail); + video_driver_texture_unload(&ozone->left_thumbnail); + video_driver_texture_unload(&menu_display_white_texture); menu_display_font_free(ozone->fonts.footer); @@ -1007,6 +1262,41 @@ static void ozone_draw_footer(ozone_handle_t *ozone, video_frame_info_t *video_i menu_display_blend_end(video_info); } + +static void ozone_set_thumbnail_content(void *data, char *s, size_t len) +{ + ozone_handle_t *ozone = (ozone_handle_t*)data; + if (!ozone) + return; + if (!string_is_empty(ozone->thumbnail_content)) + free(ozone->thumbnail_content); + ozone->thumbnail_content = strdup(s); +} + +static void ozone_reset_thumbnail_content(void *data) +{ + ozone_handle_t *ozone = (ozone_handle_t*)data; + if (!ozone) + return; + if (!string_is_empty(ozone->thumbnail_content)) + free(ozone->thumbnail_content); + ozone->thumbnail_content = NULL; +} + +static void ozone_set_thumbnail_system(void *data, char*s, size_t len) +{ + ozone_handle_t *ozone = (ozone_handle_t*)data; + if (!ozone) + return; + + if (!string_is_empty(ozone->thumbnail_system)) + free(ozone->thumbnail_system); + /* There is only one mame thumbnail repo */ + if (strncmp("MAME", s, 4) == 0) + strcpy(s, "MAME"); + ozone->thumbnail_system = strdup(s); +} + static void ozone_selection_changed(ozone_handle_t *ozone, bool allow_animation) { file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); @@ -1015,6 +1305,9 @@ static void ozone_selection_changed(ozone_handle_t *ozone, bool allow_animation) size_t new_selection = menu_navigation_get_selection(); ozone_node_t *node = (ozone_node_t*) file_list_get_userdata_at_offset(selection_buf, new_selection); + const char *thumb_ident = ozone_thumbnails_ident('R'); + const char *left_thumb_ident = ozone_thumbnails_ident('L'); + if (!node) return; @@ -1026,8 +1319,85 @@ static void ozone_selection_changed(ozone_handle_t *ozone, bool allow_animation) ozone->cursor_in_sidebar_old = ozone->cursor_in_sidebar; menu_animation_kill_by_tag(&tag); - ozone_update_scroll(ozone, allow_animation, node); + + /* Update thumbnail */ + ozone_node_t *node = (ozone_node_t*) + file_list_get_userdata_at_offset(selection_buf, ozone->selection); + + if (node) + { + if (!string_is_equal(thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) || !string_is_equal(left_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + menu_entry_t entry; + unsigned entry_type; + unsigned i = ozone->selection; + + menu_entry_init(&entry); + menu_entry_get(&entry, 0, (unsigned)i, NULL, true); + entry_type = menu_entry_get_type_new(&entry); + + /* TODO: Fix all conditions here to make sure that + * all expected thumbnails show up + * (except for savestates which will come later) */ + if (ozone->is_playlist && ozone->depth == 1) + { + if (!string_is_empty(entry.path)) + ozone_set_thumbnail_content(ozone, entry.path, 0 /* will be ignored */); + if (!string_is_equal(thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, i, 'R'); + ozone_update_thumbnail_image(ozone); + } + if (!string_is_equal(left_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, i, 'L'); + ozone_update_thumbnail_image(ozone); + } + } + else if (((entry_type == FILE_TYPE_IMAGE || entry_type == FILE_TYPE_IMAGEVIEWER || + entry_type == FILE_TYPE_RDB || entry_type == FILE_TYPE_RDB_ENTRY) + && ozone->tabs[ozone->categories_selection_ptr] <= OZONE_SYSTEM_TAB_SETTINGS)) + { + if (!string_is_empty(entry.path)) + ozone_set_thumbnail_content(ozone, entry.path, 0 /* will be ignored */); + if (!string_is_equal(thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, i, 'R'); + ozone_update_thumbnail_image(ozone); + } + else if (!string_is_equal(left_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, i, 'L'); + ozone_update_thumbnail_image(ozone); + } + } + else if (filebrowser_get_type() != FILEBROWSER_NONE) + { + ozone_reset_thumbnail_content(ozone); + if (!string_is_equal(thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, i, 'R'); + ozone_update_thumbnail_image(ozone); + } + else if (!string_is_equal(left_thumb_ident, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, i, 'L'); + ozone_update_thumbnail_image(ozone); + } + } + menu_entry_free(&entry); + } + /* TODO: Update savestate thumbnail */ + } } } @@ -1149,7 +1519,7 @@ static void ozone_frame(void *data, video_frame_info_t *video_info) ozone_draw_sidebar(ozone, video_info); /* Menu entries */ - menu_display_scissor_begin(video_info, ozone->sidebar_offset + (unsigned) ozone->dimensions.sidebar_width, ozone->dimensions.header_height, video_info->width - (unsigned) ozone->dimensions.sidebar_width + (-ozone->sidebar_offset), video_info->height - ozone->dimensions.header_height - ozone->dimensions.footer_height); + menu_display_scissor_begin(video_info, ozone->sidebar_offset + (unsigned) ozone->dimensions.sidebar_width, ozone->dimensions.header_height + 1, video_info->width - (unsigned) ozone->dimensions.sidebar_width + (-ozone->sidebar_offset), video_info->height - ozone->dimensions.header_height - ozone->dimensions.footer_height - 1); /* Current list */ ozone_draw_entries(ozone, @@ -1174,6 +1544,10 @@ static void ozone_frame(void *data, video_frame_info_t *video_info) ozone->is_playlist_old ); + /* Thumbnail bar */ + if (ozone->show_thumbnail_bar) + ozone_draw_thumbnail_bar(ozone, video_info); + menu_display_scissor_end(video_info); /* Flush first layer of text */ @@ -1309,10 +1683,10 @@ static void ozone_list_open(ozone_handle_t *ozone) menu_animation_push(&entry); /* Sidebar animation */ + ozone_sidebar_update_collapse(ozone, true); + if (ozone->depth == 1) { - ozone_sidebar_update_collapse(ozone, false); - ozone->draw_sidebar = true; entry.cb = NULL; @@ -1356,7 +1730,21 @@ static void ozone_populate_entries(void *data, const char *path, const char *lab { menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL); - /* TODO: Update thumbnails */ + /* Thumbnails */ + if (!string_is_equal(ozone_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, 0, 'R'); + ozone_update_thumbnail_image(ozone); + } + /* TODO: update savestate thumbnail image */ + if (!string_is_equal(ozone_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + ozone_update_thumbnail_path(ozone, 0, 'L'); + ozone_update_thumbnail_image(ozone); + } + ozone_selection_changed(ozone, false); return; } @@ -1373,6 +1761,42 @@ static void ozone_populate_entries(void *data, const char *path, const char *lab { ozone_list_open(ozone); } + else + { + /* Thumbnails */ + if (!string_is_equal(ozone_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + menu_entry_t entry; + + menu_entry_init(&entry); + menu_entry_get(&entry, 0, ozone->selection, NULL, true); + + if (!string_is_empty(entry.path)) + ozone_set_thumbnail_content(ozone, entry.path, 0 /* will be ignored */); + + menu_entry_free(&entry); + + ozone_update_thumbnail_path(ozone, 0, 'R'); + ozone_update_thumbnail_image(ozone); + } + if (!string_is_equal(ozone_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) + { + menu_entry_t entry; + + menu_entry_init(&entry); + menu_entry_get(&entry, 0, ozone->selection, NULL, true); + + if (!string_is_empty(entry.path)) + ozone_set_thumbnail_content(ozone, entry.path, 0 /* will be ignored */); + + menu_entry_free(&entry); + + ozone_update_thumbnail_path(ozone, 0, 'L'); + ozone_update_thumbnail_image(ozone); + } + } } static int ozone_menu_iterate(menu_handle_t *menu, void *userdata, enum menu_action action) @@ -1565,6 +1989,7 @@ static ozone_node_t *ozone_copy_node(const ozone_node_t *old_node) ozone_node_t *new_node = (ozone_node_t*)malloc(sizeof(*new_node)); *new_node = *old_node; + new_node->fullpath = old_node->fullpath ? strdup(old_node->fullpath) : NULL; return new_node; } @@ -1820,6 +2245,65 @@ static int ozone_pointer_tap(void *userdata, return 0; } +static bool ozone_load_image(void *userdata, void *data, enum menu_image_type type) +{ + ozone_handle_t *ozone = (ozone_handle_t*) userdata; + unsigned sidebar_height; + unsigned height; + unsigned maximum_height; + + if (!ozone || !data) + return false; + + video_driver_get_size(NULL, &height); + + sidebar_height = height - ozone->dimensions.header_height - 55 - ozone->dimensions.footer_height; + maximum_height = sidebar_height / 2; + + switch (type) + { + case MENU_IMAGE_THUMBNAIL: + { + struct texture_image *img = (struct texture_image*)data; + ozone->dimensions.thumbnail_height = ozone->dimensions.thumbnail_width + * (float)img->height / (float)img->width; + + if (ozone->dimensions.thumbnail_height > maximum_height) + { + float scale_down = (float) maximum_height / (float) ozone->dimensions.thumbnail_height; + ozone->dimensions.thumbnail_height *= scale_down; + ozone->dimensions.thumbnail_width *= scale_down; + } + + video_driver_texture_unload(&ozone->thumbnail); + video_driver_texture_load(data, + TEXTURE_FILTER_MIPMAP_LINEAR, &ozone->thumbnail); + break; + } + case MENU_IMAGE_LEFT_THUMBNAIL: + { + struct texture_image *img = (struct texture_image*)data; + ozone->dimensions.left_thumbnail_height = ozone->dimensions.left_thumbnail_width + * (float)img->height / (float)img->width; + + if (ozone->dimensions.left_thumbnail_height > maximum_height) + { + float scale_down = (float) maximum_height / (float) ozone->dimensions.left_thumbnail_height; + ozone->dimensions.left_thumbnail_height *= scale_down; + ozone->dimensions.left_thumbnail_width *= scale_down; + } + video_driver_texture_unload(&ozone->left_thumbnail); + video_driver_texture_load(data, + TEXTURE_FILTER_MIPMAP_LINEAR, &ozone->left_thumbnail); + break; + } + default: + break; + } + return true; +} + + menu_ctx_driver_t menu_ctx_ozone = { NULL, /* set_texture */ ozone_messagebox, @@ -1850,15 +2334,15 @@ menu_ctx_driver_t menu_ctx_ozone = { ozone_list_get_size, ozone_list_get_entry, NULL, /* list_set_selection */ - ozone_list_bind_init, /* bind_init */ - NULL, /* load_image */ + ozone_list_bind_init, + ozone_load_image, "ozone", ozone_environ_cb, ozone_pointer_tap, - NULL, /* update_thumbnail_path */ - NULL, /* update_thumbnail_image */ - NULL, /* set_thumbnail_system */ - NULL, /* set_thumbnail_content */ + ozone_update_thumbnail_path, + ozone_update_thumbnail_image, + ozone_set_thumbnail_system, + ozone_set_thumbnail_content, menu_display_osk_ptr_at_pos, NULL, /* update_savestate_thumbnail_path */ NULL, /* update_savestate_thumbnail_image */ diff --git a/menu/drivers/ozone/ozone.h b/menu/drivers/ozone/ozone.h index 323d2380a3..b1bf3d4379 100644 --- a/menu/drivers/ozone/ozone.h +++ b/menu/drivers/ozone/ozone.h @@ -124,7 +124,7 @@ struct ozone_handle float messagebox_alpha; float sidebar_text_alpha; - float thumbnail_bar_position; /* 0 = hidden */ + float thumbnail_bar_position; } animations; bool fade_direction; /* false = left to right, true = right to left */ @@ -210,6 +210,11 @@ struct ozone_handle int cursor_size; int thumbnail_bar_width; + + float thumbnail_width; /* set at layout time */ + float thumbnail_height; /* set later to thumbnail_width * image aspect ratio */ + float left_thumbnail_width; /* set at layout time */ + float left_thumbnail_height; /* set later to left_thumbnail_width * image aspect ratio */ } dimensions; bool show_cursor; @@ -220,7 +225,16 @@ struct ozone_handle bool sidebar_collapsed; + /* Thumbnails data */ bool show_thumbnail_bar; + + char *thumbnail_content; + char *thumbnail_system; + char *thumbnail_file_path; + char *left_thumbnail_file_path; /* name taken from xmb for consistency but not actually on the left */ + + uintptr_t thumbnail; + uintptr_t left_thumbnail; }; /* If you change this struct, also @@ -232,6 +246,7 @@ typedef struct ozone_node unsigned height; unsigned position_y; bool wrap; + char *fullpath; /* Console tabs */ char *console_name; @@ -284,4 +299,8 @@ void ozone_sidebar_update_collapse(ozone_handle_t *ozone, bool allow_animation); void ozone_entries_update_thumbnail_bar(ozone_handle_t *ozone, bool is_playlist, bool allow_animation); +void ozone_draw_thumbnail_bar(ozone_handle_t *ozone, video_frame_info_t *video_info); + +const char *ozone_thumbnails_ident(char pos); + #endif diff --git a/menu/drivers/ozone/ozone_entries.c b/menu/drivers/ozone/ozone_entries.c index 1ecc4806f0..b8b239850e 100644 --- a/menu/drivers/ozone/ozone_entries.c +++ b/menu/drivers/ozone/ozone_entries.c @@ -277,9 +277,60 @@ void ozone_compute_entries_position(ozone_handle_t *ozone) ozone_update_scroll(ozone, false, (ozone_node_t*) file_list_get_userdata_at_offset(selection_buf, ozone->selection)); } +static void ozone_thumbnail_bar_hide_end(void *userdata) +{ + ozone_handle_t *ozone = (ozone_handle_t*) userdata; + ozone->show_thumbnail_bar = false; +} + void ozone_entries_update_thumbnail_bar(ozone_handle_t *ozone, bool is_playlist, bool allow_animation) { - /* TODO Animate it and draw it */ + struct menu_animation_ctx_entry entry; + menu_animation_ctx_tag tag = (uintptr_t) &ozone->show_thumbnail_bar; + + entry.duration = ANIMATION_CURSOR_DURATION; + entry.easing_enum = EASING_OUT_QUAD; + entry.tag = tag; + entry.subject = &ozone->animations.thumbnail_bar_position; + + menu_animation_kill_by_tag(&tag); + + /* Show it */ + if (is_playlist && !ozone->cursor_in_sidebar && !ozone->show_thumbnail_bar && ozone->depth == 1) + { + if (allow_animation) + { + ozone->show_thumbnail_bar = true; + + entry.cb = NULL; + entry.userdata = NULL; + entry.target_value = ozone->dimensions.thumbnail_bar_width; + + menu_animation_push(&entry); + } + else + { + ozone->animations.thumbnail_bar_position = ozone->dimensions.thumbnail_bar_width; + ozone->show_thumbnail_bar = true; + } + } + /* Hide it */ + else + { + if (allow_animation) + { + entry.cb = ozone_thumbnail_bar_hide_end; + entry.userdata = ozone; + entry.target_value = 0.0f; + + menu_animation_push(&entry); + } + else + { + ozone->animations.thumbnail_bar_position = 0.0f; + ozone_thumbnail_bar_hide_end(ozone); + } + } } void ozone_draw_entries(ozone_handle_t *ozone, video_frame_info_t *video_info, @@ -531,7 +582,7 @@ border_iterate: ticker.s = entry_value_ticker; ticker.str = entry_value; ticker.selected = entry_selected && !ozone->cursor_in_sidebar; - ticker.len = (entry_width - ozone->dimensions.entry_icon_size - ozone->dimensions.entry_icon_padding * 2 - + ticker.len = (entry_width - ozone->dimensions.entry_icon_size - ozone->dimensions.entry_icon_padding * 2 - ((int)utf8len(entry_rich_label) * ozone->entry_font_glyph_width)) / ozone->entry_font_glyph_width; menu_animation_ticker(&ticker); @@ -553,3 +604,71 @@ icons_iterate: font_driver_flush(video_info->width, video_info->height, ozone->fonts.entries_label, video_info); font_driver_flush(video_info->width, video_info->height, ozone->fonts.entries_sublabel, video_info); } + +void ozone_draw_thumbnail_bar(ozone_handle_t *ozone, video_frame_info_t *video_info) +{ + unsigned sidebar_height = video_info->height - ozone->dimensions.header_height - 55 - ozone->dimensions.footer_height; + unsigned sidebar_width = ozone->dimensions.thumbnail_bar_width; + unsigned x_position = video_info->width - (unsigned) ozone->animations.thumbnail_bar_position; + + bool thumbnail; + bool left_thumbnail; + + //Background + if (!video_info->libretro_running) + { + menu_display_draw_quad(video_info, x_position, ozone->dimensions.header_height + 1, (unsigned) ozone->animations.thumbnail_bar_position, 55/2, video_info->width, video_info->height, ozone->theme->sidebar_top_gradient); + menu_display_draw_quad(video_info, x_position, ozone->dimensions.header_height + 1 + 55/2, (unsigned) ozone->animations.thumbnail_bar_position, sidebar_height, video_info->width, video_info->height, ozone->theme->sidebar_background); + menu_display_draw_quad(video_info, x_position, video_info->height - ozone->dimensions.footer_height - 55/2 - 1, (unsigned) ozone->animations.thumbnail_bar_position, 55/2 + 1, video_info->width, video_info->height, ozone->theme->sidebar_bottom_gradient); + } + + //Thumbnails + thumbnail = ozone->thumbnail && + !string_is_equal(ozone_thumbnails_ident('R'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)); + left_thumbnail = ozone->left_thumbnail && + !string_is_equal(ozone_thumbnails_ident('L'), + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)); + + if (thumbnail) + { + unsigned thumb_x_position = x_position + sidebar_width/2 - (ozone->dimensions.thumbnail_width + ozone->dimensions.sidebar_entry_icon_padding) / 2; + unsigned thumb_y_position = video_info->height / 2 - ozone->dimensions.thumbnail_height / 2; + + thumb_y_position -= ozone->dimensions.thumbnail_height / 2 + ozone->dimensions.sidebar_entry_icon_padding/2; + + ozone_draw_icon(video_info, + ozone->dimensions.thumbnail_width, + ozone->dimensions.thumbnail_height, + ozone->thumbnail, + thumb_x_position, + thumb_y_position, + video_info->width, video_info->height, + 0, 1, + ozone_pure_white + ); + } + + if (left_thumbnail) + { + unsigned thumb_x_position = x_position + sidebar_width/2 - (ozone->dimensions.left_thumbnail_width + ozone->dimensions.sidebar_entry_icon_padding) / 2; + unsigned thumb_y_position = video_info->height / 2 + ozone->dimensions.sidebar_entry_icon_padding / 2; + + ozone_draw_icon(video_info, + ozone->dimensions.left_thumbnail_width, + ozone->dimensions.left_thumbnail_height, + ozone->left_thumbnail, + thumb_x_position, + thumb_y_position, + video_info->width, video_info->height, + 0, 1, + ozone_pure_white + ); + } + else + { + /* TODO: Content metadata */ + } +} + + diff --git a/menu/drivers/ozone/ozone_sidebar.c b/menu/drivers/ozone/ozone_sidebar.c index b28aecf934..f69682ac62 100644 --- a/menu/drivers/ozone/ozone_sidebar.c +++ b/menu/drivers/ozone/ozone_sidebar.c @@ -338,7 +338,7 @@ void ozone_sidebar_update_collapse(ozone_handle_t *ozone, bool allow_animation) /* Collapse sidebar if needed */ settings_t *settings = config_get_ptr(); bool is_playlist = ozone_is_playlist(ozone, false); - menu_animation_ctx_tag tag = (uintptr_t)NULL; + menu_animation_ctx_tag tag = (uintptr_t) &ozone->sidebar_collapsed; struct menu_animation_ctx_entry entry; @@ -347,7 +347,10 @@ void ozone_sidebar_update_collapse(ozone_handle_t *ozone, bool allow_animation) entry.userdata = ozone; entry.duration = ANIMATION_CURSOR_DURATION; - if (settings->bools.ozone_collapse_sidebar || (is_playlist && !ozone->cursor_in_sidebar && !ozone->sidebar_collapsed)) + menu_animation_kill_by_tag(&tag); + + //Collapse it + if (settings->bools.ozone_collapse_sidebar || (is_playlist && !ozone->cursor_in_sidebar)) { if (allow_animation) { @@ -372,7 +375,8 @@ void ozone_sidebar_update_collapse(ozone_handle_t *ozone, bool allow_animation) ozone_sidebar_collapse_end(ozone); } } - else if (ozone->cursor_in_sidebar && ozone->sidebar_collapsed) + //Show it + else if (ozone->cursor_in_sidebar) { if (allow_animation) {