This change allows playlist icons to be replaced with Logos. (#16758)

* This change allows playlist icons to be replaced with Logos. the art is loaded to the Thumbnail Named_Logos folder. It is treated the same as other thumbnails for naming and for automatic download. There is a settings menu option to turn it on and off. It is off by default. This only applies to the xmb menu driver.

* Removed commented out code against the style guide.

* Code cleanup for C89 compatibitity

* Cleaned up errors from Automated CI.

* Cleaned up comments.

* Update gfx_display.c

change strcpy to strlcpy

* Update gfx_thumbnail_path.c

fix code formatting

* Update xmb.c

code formatting changes
This commit is contained in:
Jason Breitweiser 2024-08-07 11:39:57 -04:00 committed by GitHub
parent b14fc30d1a
commit 11d9a841f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 572 additions and 20 deletions

View File

@ -1620,6 +1620,7 @@
#define DEFAULT_GFX_THUMBNAILS_DEFAULT 3
#define DEFAULT_MENU_LEFT_THUMBNAILS_DEFAULT 0
#define DEFAULT_MENU_ICON_THUMBNAILS_DEFAULT 0
#define DEFAULT_GFX_THUMBNAIL_UPSCALE_THRESHOLD 0

View File

@ -2352,6 +2352,7 @@ static struct config_uint_setting *populate_settings_uint(
SETTING_UINT("quit_on_close_content", &settings->uints.quit_on_close_content, true, DEFAULT_QUIT_ON_CLOSE_CONTENT, false);
SETTING_UINT("menu_thumbnails", &settings->uints.gfx_thumbnails, true, DEFAULT_GFX_THUMBNAILS_DEFAULT, false);
SETTING_UINT("menu_left_thumbnails", &settings->uints.menu_left_thumbnails, true, DEFAULT_MENU_LEFT_THUMBNAILS_DEFAULT, false);
SETTING_UINT("menu_icon_thumbnails", &settings->uints.menu_icon_thumbnails, true, DEFAULT_MENU_ICON_THUMBNAILS_DEFAULT, false);
SETTING_UINT("menu_thumbnail_upscale_threshold", &settings->uints.gfx_thumbnail_upscale_threshold, true, DEFAULT_GFX_THUMBNAIL_UPSCALE_THRESHOLD, false);
SETTING_UINT("menu_timedate_style", &settings->uints.menu_timedate_style, true, DEFAULT_MENU_TIMEDATE_STYLE, false);
SETTING_UINT("menu_timedate_date_separator", &settings->uints.menu_timedate_date_separator, true, DEFAULT_MENU_TIMEDATE_DATE_SEPARATOR, false);

View File

@ -274,6 +274,7 @@ typedef struct settings
unsigned menu_timedate_date_separator;
unsigned gfx_thumbnails;
unsigned menu_left_thumbnails;
unsigned menu_icon_thumbnails;
unsigned gfx_thumbnail_upscale_threshold;
unsigned menu_rgui_thumbnail_downscaler;
unsigned menu_rgui_thumbnail_delay;

View File

@ -1127,6 +1127,39 @@ bool gfx_display_reset_textures_list(
return true;
}
bool gfx_display_reset_icon_texture(
const char *texture_path,
uintptr_t *item, enum texture_filter_type filter_type,
unsigned *width, unsigned *height)
{
char texpath[PATH_MAX_LENGTH];
struct texture_image ti;
ti.width = 0;
ti.height = 0;
ti.pixels = NULL;
ti.supports_rgba = video_driver_supports_rgba();
if (string_is_empty(texture_path))
return false;
strlcpy(texpath, texture_path, sizeof(texpath));
if (!image_texture_load(&ti, texpath))
return false;
if (width)
*width = ti.width;
if (height)
*height = ti.height;
video_driver_texture_load(&ti, filter_type, item);
image_texture_free(&ti);
return true;
}
void gfx_display_deinit_white_texture(void)
{
if (gfx_white_texture)

View File

@ -293,6 +293,11 @@ bool gfx_display_reset_textures_list(
unsigned *width,
unsigned *height);
bool gfx_display_reset_icon_texture(
const char *texture_path,
uintptr_t *item, enum texture_filter_type filter_type,
unsigned *width, unsigned *height);
bool gfx_display_reset_textures_list_buffer(
uintptr_t *item,
enum texture_filter_type filter_type,

View File

@ -94,6 +94,9 @@ static const char *gfx_thumbnail_get_type(
else
type = menu_left_thumbnails;
break;
case GFX_THUMBNAIL_ICON:
type = 4;
break;
default:
goto end;
}
@ -106,6 +109,8 @@ static const char *gfx_thumbnail_get_type(
return "Named_Titles";
case 3:
return "Named_Boxarts";
case 4:
return "Named_Logos";
case 0:
default:
break;
@ -167,6 +172,8 @@ bool gfx_thumbnail_is_enabled(gfx_thumbnail_path_data_t *path_data, enum gfx_thu
settings_t *settings = config_get_ptr();
unsigned gfx_thumbnails = settings->uints.gfx_thumbnails;
unsigned menu_left_thumbnails = settings->uints.menu_left_thumbnails;
unsigned menu_icon_thumbnails = settings->uints.menu_icon_thumbnails;
switch (thumbnail_id)
{
case GFX_THUMBNAIL_RIGHT:
@ -177,6 +184,10 @@ bool gfx_thumbnail_is_enabled(gfx_thumbnail_path_data_t *path_data, enum gfx_thu
if (path_data->playlist_left_mode != PLAYLIST_THUMBNAIL_MODE_DEFAULT)
return path_data->playlist_left_mode != PLAYLIST_THUMBNAIL_MODE_OFF;
return menu_left_thumbnails != 0;
case GFX_THUMBNAIL_ICON:
if (path_data->playlist_icon_mode != PLAYLIST_THUMBNAIL_MODE_DEFAULT)
return path_data->playlist_left_mode != PLAYLIST_THUMBNAIL_MODE_OFF;
return menu_icon_thumbnails != 0;
default:
break;
}
@ -555,6 +566,168 @@ bool gfx_thumbnail_set_content_playlist(
return true;
}
bool gfx_thumbnail_set_icon_playlist(
gfx_thumbnail_path_data_t *path_data, playlist_t *playlist, size_t idx)
{
const char *content_path = NULL;
const char *content_label = NULL;
const char *core_name = NULL;
const char *db_name = NULL;
const struct playlist_entry *entry = NULL;
char content_dir[PATH_MAX_LENGTH];
const char *dir_thumbnails = NULL;
settings_t *settings = config_get_ptr();
if (!path_data)
return false;
/* When content is updated, must regenerate icon
* thumbnail paths */
path_data->icon_path[0] = '\0';
/* 'Reset' path_data content strings */
path_data->content_path[0] = '\0';
path_data->content_label[0] = '\0';
path_data->content_core_name[0] = '\0';
path_data->content_db_name[0] = '\0';
path_data->content_img[0] = '\0';
path_data->content_img_full[0] = '\0';
path_data->content_img_short[0] = '\0';
/* Must also reset playlist thumbnail display modes */
path_data->playlist_icon_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
path_data->playlist_index = 0;
if (!playlist)
return false;
if (idx >= playlist_get_size(playlist))
return false;
/* Read playlist values */
playlist_get_index(playlist, idx, &entry);
if (!entry)
return false;
content_path = entry->path;
content_label = entry->label;
core_name = entry->core_name;
db_name = entry->db_name;
/* Content without a path is invalid by definition */
if (string_is_empty(content_path))
return false;
/* Cache content path
* (This is required for imageviewer, history and favourites content) */
strlcpy(path_data->content_path,
content_path, sizeof(path_data->content_path));
/* Cache core name
* (This is required for imageviewer content) */
if (!string_is_empty(core_name))
strlcpy(path_data->content_core_name,
core_name, sizeof(path_data->content_core_name));
/* Get content label */
if (!string_is_empty(content_label))
strlcpy(path_data->content_label,
content_label, sizeof(path_data->content_label));
else
fill_pathname(path_data->content_label,
path_basename(content_path),
"", sizeof(path_data->content_label));
/* Determine content image name */
{
char* content_name_no_ext = NULL;
char tmp_buf[PATH_MAX_LENGTH];
/* Remove rom file extension
* > path_remove_extension() requires a char * (not const)
* so have to use a temporary buffer... */
const char* base_name = path_basename(path_data->content_path);
strlcpy(tmp_buf, base_name, sizeof(tmp_buf));
content_name_no_ext = path_remove_extension(tmp_buf);
if (!content_name_no_ext)
content_name_no_ext = tmp_buf;
gfx_thumbnail_fill_content_img(path_data->content_img_full,
sizeof(path_data->content_img_full), content_name_no_ext,false);
gfx_thumbnail_fill_content_img(path_data->content_img,
sizeof(path_data->content_img), path_data->content_label,false);
/* Explicit zero if full name is same as standard name - saves some queries later. */
if(strcmp(path_data->content_img, path_data->content_img_full) == 0)
{
path_data->content_img_full[0] = '\0';
}
gfx_thumbnail_fill_content_img(path_data->content_img_short,
sizeof(path_data->content_img_short), path_data->content_label,true);
}
/* Store playlist index */
path_data->playlist_index = idx;
/* Redundant error check... */
if (string_is_empty(path_data->content_img))
return false;
/* Thumbnail image name is done -> now check if
* per-content database name is defined */
if (string_is_empty(db_name))
playlist_get_db_name(playlist, idx, &db_name);
if (!string_is_empty(db_name))
{
/* Hack: There is only one MAME thumbnail repo,
* so filter any input starting with 'MAME...' */
if (strncmp(db_name, "MAME", 4) == 0)
{
path_data->content_db_name[0] = path_data->content_db_name[2] = 'M';
path_data->content_db_name[1] = 'A';
path_data->content_db_name[3] = 'E';
path_data->content_db_name[4] = '\0';
}
else
{
char *db_name_no_ext = NULL;
char tmp_buf[PATH_MAX_LENGTH];
const char* pos = strchr(db_name, '|');
if (pos && (size_t) (pos - db_name)+1 < sizeof(tmp_buf)) {
/* If db_name comes from core info, and there are multiple
* databases mentioned separated by |, use only first one */
strlcpy(tmp_buf, db_name, (size_t) (pos - db_name)+1);
}
else
{
/* Remove .lpl extension
* > path_remove_extension() requires a char * (not const)
* so have to use a temporary buffer... */
strlcpy(tmp_buf, db_name, sizeof(tmp_buf));
}
db_name_no_ext = path_remove_extension(tmp_buf);
if (!string_is_empty(db_name_no_ext))
strlcpy(path_data->content_db_name,
db_name_no_ext, sizeof(path_data->content_db_name));
else
strlcpy(path_data->content_db_name,
tmp_buf, sizeof(path_data->content_db_name));
}
}
gfx_thumbnail_update_path(path_data, GFX_THUMBNAIL_ICON);
/* Playlist entry is valid -> it is now 'safe' to
* extract any remaining playlist metadata
* (i.e. thumbnail display modes) */
path_data->playlist_icon_mode = PLAYLIST_THUMBNAIL_MODE_DEFAULT;
return true;
}
/* Updaters */
/* Updates path for specified thumbnail identifier (right, left).
@ -589,6 +762,9 @@ bool gfx_thumbnail_update_path(
case GFX_THUMBNAIL_LEFT:
thumbnail_path = path_data->left_path;
break;
case GFX_THUMBNAIL_ICON:
thumbnail_path = path_data->icon_path;
break;
default:
return false;
}
@ -752,6 +928,13 @@ bool gfx_thumbnail_get_path(
*path = thumbnail_path;
return true;
}
case GFX_THUMBNAIL_ICON:
if (!string_is_empty(path_data->icon_path))
{
thumbnail_path = path_data->icon_path;
*path = thumbnail_path;
return true;
}
break;
default:
break;

View File

@ -44,7 +44,8 @@ RETRO_BEGIN_DECLS
enum gfx_thumbnail_id
{
GFX_THUMBNAIL_RIGHT = 0,
GFX_THUMBNAIL_LEFT
GFX_THUMBNAIL_LEFT,
GFX_THUMBNAIL_ICON
};
/* Prevent direct access to gfx_thumbnail_path_data_t members */
@ -57,6 +58,7 @@ struct gfx_thumbnail_path_data
{
enum playlist_thumbnail_mode playlist_right_mode;
enum playlist_thumbnail_mode playlist_left_mode;
enum playlist_thumbnail_mode playlist_icon_mode;
size_t playlist_index;
char content_path[PATH_MAX_LENGTH];
char content_img[PATH_MAX_LENGTH];
@ -64,6 +66,7 @@ struct gfx_thumbnail_path_data
char content_img_full[PATH_MAX_LENGTH];
char right_path[PATH_MAX_LENGTH];
char left_path[PATH_MAX_LENGTH];
char icon_path[PATH_MAX_LENGTH];
char content_label[256];
char content_core_name[256];
char system[256];
@ -116,6 +119,8 @@ bool gfx_thumbnail_set_content_image(gfx_thumbnail_path_data_t *path_data, const
* core name). 'Real' labels should be extracted from source */
bool gfx_thumbnail_set_content_playlist(gfx_thumbnail_path_data_t *path_data, playlist_t *playlist, size_t idx);
bool gfx_thumbnail_set_icon_playlist(
gfx_thumbnail_path_data_t *path_data, playlist_t *playlist, size_t idx);
/* Updaters */
/* Updates path for specified thumbnail identifier (right, left).

View File

@ -3893,6 +3893,10 @@ MSG_HASH(
MENU_ENUM_LABEL_SYSTEM_INFO_ENTRY,
"system_info_entry"
)
MSG_HASH(
MENU_ENUM_LABEL_ICON_THUMBNAILS,
"icon_thumbnails"
)
MSG_HASH(
MENU_ENUM_LABEL_TAKE_SCREENSHOT,
"take_screenshot"

View File

@ -6955,6 +6955,14 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_SETTINGS_SHOW_USER,
"Show 'User'"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_ICON_THUMBNAILS,
"Playlist Icons"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_ICON_THUMBNAILS,
"Type of Playlist icon thumbnail to display."
)
MSG_HASH(
MENU_ENUM_SUBLABEL_SETTINGS_SHOW_USER,
"Show 'User' settings."
@ -11121,6 +11129,10 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_TITLE_SCREENS,
"Title Screen"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_LOGOS,
"Content Logo"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_SCROLL_NORMAL,
"Normal"

View File

@ -912,6 +912,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_nat_traversal, MENU_
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_stdin_cmd_enable, MENU_ENUM_SUBLABEL_STDIN_CMD_ENABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_mouse_enable, MENU_ENUM_SUBLABEL_MOUSE_ENABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_pointer_enable, MENU_ENUM_SUBLABEL_POINTER_ENABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_icon_thumbnails, MENU_ENUM_SUBLABEL_ICON_THUMBNAILS)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_thumbnails, MENU_ENUM_SUBLABEL_THUMBNAILS)
#ifdef HAVE_MATERIALUI
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_thumbnails_materialui, MENU_ENUM_SUBLABEL_THUMBNAILS_MATERIALUI)
@ -3675,6 +3676,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
}
}
break;
case MENU_ENUM_LABEL_ICON_THUMBNAILS:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_icon_thumbnails);
break;
case MENU_ENUM_LABEL_MENU_THUMBNAIL_UPSCALE_THRESHOLD:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_menu_thumbnail_upscale_threshold);
break;

View File

@ -148,6 +148,24 @@ static int action_get_title_remap_port(
return 1;
}
static int action_get_title_icon_thumbnails(
const char *path, const char *label, unsigned menu_type,
char *s, size_t len)
{
const char *title = NULL;
enum msg_hash_enums label_value = MENU_ENUM_LABEL_VALUE_ICON_THUMBNAILS;
title = msg_hash_to_str(label_value);
if (s && !string_is_empty(title))
{
SANITIZE_TO_STRING(s, title, len);
return 1;
}
return 0;
}
static int action_get_title_thumbnails(
const char *path, const char *label, unsigned menu_type,
char *s, size_t len)
@ -1814,6 +1832,7 @@ int menu_cbs_init_bind_title(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_SORT_MODE, action_get_title_dropdown_playlist_sort_mode_item},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE, action_get_title_thumbnails},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE, action_get_title_left_thumbnails},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_ICON_THUMBNAIL_MODE, action_get_title_icon_thumbnails},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME, action_get_title_dropdown_manual_content_scan_system_name_item},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME, action_get_title_dropdown_manual_content_scan_core_name_item},
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_DISK_INDEX, action_get_title_dropdown_disk_index},

View File

@ -280,9 +280,16 @@ enum xmb_pending_thumbnail_type
XMB_PENDING_THUMBNAIL_NONE = 0,
XMB_PENDING_THUMBNAIL_RIGHT,
XMB_PENDING_THUMBNAIL_LEFT,
XMB_PENDING_THUMBNAIL_BOTH
XMB_PENDING_THUMBNAIL_BOTH,
XMB_PENDING_THUMBNAIL_ICONS
};
typedef struct
{
gfx_thumbnail_path_data_t thumbnail_path_data;
gfx_thumbnail_t icon;
} xmb_icons_t;
/* NOTE: If you change this you HAVE to update
* xmb_alloc_node() and xmb_copy_node() */
typedef struct
@ -291,6 +298,7 @@ typedef struct
char *console_name;
uintptr_t icon;
uintptr_t content_icon;
xmb_icons_t thumbnail_icon;
float alpha;
float label_alpha;
float zoom;
@ -348,6 +356,7 @@ typedef struct xmb_handle
gfx_thumbnail_t left;
gfx_thumbnail_t savestate;
enum xmb_pending_thumbnail_type pending;
enum xmb_pending_thumbnail_type pending_icons;
} thumbnails;
struct
@ -597,6 +606,7 @@ static xmb_node_t *xmb_alloc_node(void)
node->alpha = node->label_alpha = 0;
node->zoom = node->x = node->y = 0;
node->icon = node->content_icon = 0;
node->thumbnail_icon.icon.texture = 0;
node->fullpath = NULL;
node->console_name = NULL;
@ -612,6 +622,7 @@ static void xmb_free_node(xmb_node_t *node)
free(node->fullpath);
node->fullpath = NULL;
gfx_thumbnail_reset(&node->thumbnail_icon.icon);
free(node);
}
@ -652,6 +663,7 @@ static xmb_node_t *xmb_copy_node(const xmb_node_t *old_node)
*new_node = *old_node;
new_node->fullpath = old_node->fullpath ? strdup(old_node->fullpath) : NULL;
new_node->console_name = old_node->console_name ? strdup(old_node->console_name) : NULL;
new_node->thumbnail_icon.icon.texture = 0;
return new_node;
}
@ -891,7 +903,8 @@ static void xmb_draw_icon(
unsigned video_width,
unsigned video_height,
bool shadows_enable,
int icon_size,
int icon_size_x,
int icon_size_y,
uintptr_t texture,
float x,
float y,
@ -907,10 +920,10 @@ static void xmb_draw_icon(
gfx_display_ctx_draw_t draw;
struct video_coords coords;
if ( (x < (-icon_size / 2.0f))
if ( (x < (-icon_size_x / 2.0f))
|| (x > width)
|| (y < (icon_size / 2.0f))
|| (y > height + icon_size)
|| (y < (icon_size_y / 2.0f))
|| (y > height + icon_size_y)
)
return;
@ -919,8 +932,8 @@ static void xmb_draw_icon(
coords.tex_coord = NULL;
coords.lut_tex_coord = NULL;
draw.width = icon_size;
draw.height = icon_size;
draw.width = icon_size_x;
draw.height = icon_size_y;
draw.rotation = rotation;
draw.scale_factor = scale_factor;
#if defined(VITA) || defined(WIIU) || defined(__PS3__)
@ -944,8 +957,8 @@ static void xmb_draw_icon(
#if defined(VITA) || defined(WIIU) || defined(__PS3__)
if (scale_factor < 1)
{
draw.x = draw.x + (icon_size-draw.width)/2;
draw.y = draw.y + (icon_size-draw.width)/2;
draw.x = draw.x + (icon_size_x-draw.width)/2;
draw.y = draw.y + (icon_size_y-draw.width)/2;
}
#endif
if (draw.height > 0 && draw.width > 0)
@ -960,8 +973,8 @@ static void xmb_draw_icon(
#if defined(VITA) || defined(WIIU) || defined(__PS3__)
if (scale_factor < 1)
{
draw.x = draw.x + (icon_size-draw.width)/2;
draw.y = draw.y + (icon_size-draw.width)/2;
draw.x = draw.x + (icon_size_x-draw.width)/2;
draw.y = draw.y + (icon_size_y-draw.width)/2;
}
#endif
if (draw.height > 0 && draw.width > 0)
@ -1384,6 +1397,28 @@ static void xmb_unload_thumbnail_textures(void *data)
gfx_thumbnail_reset(&xmb->thumbnails.savestate);
}
static void xmb_unload_icon_thumbnail_textures(void *xmb_handle_ptr)
{
xmb_handle_t *xmb = (xmb_handle_t*)xmb_handle_ptr;
struct menu_state *menu_st = menu_state_get_ptr();
menu_list_t *menu_list = menu_st->entries.list;
file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, 0);
size_t list_size = (unsigned)selection_buf->size;
size_t i;
if (!xmb)
return;
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_cancel_pending_requests();
for(i =0; i < list_size ; i++)
{
xmb_node_t *node = (xmb_node_t*)selection_buf->list[i].userdata;
if(node)
gfx_thumbnail_reset(&node->thumbnail_icon.icon);
}
}
static void xmb_set_thumbnail_content(void *data, const char *s)
{
xmb_handle_t *xmb = (xmb_handle_t*)data;
@ -1496,6 +1531,45 @@ static void xmb_set_thumbnail_content(void *data, const char *s)
}
}
static void xmb_set_dynamic_icon_content(
void *xmb_handle_ptr,
const char *s,
size_t selection,
xmb_icons_t *thumbnail_icon)
{
xmb_handle_t *xmb = (xmb_handle_t*)xmb_handle_ptr;
struct menu_state *menu_st = menu_state_get_ptr();
gfx_thumbnail_path_data_t *thumbnail_path_data = &thumbnail_icon->thumbnail_path_data;
if (!xmb)
return;
if (xmb->is_playlist)
{
/* Playlist content */
if (string_is_empty(s))
{
menu_list_t *menu_list = menu_st->entries.list;
size_t list_size = (unsigned)MENU_LIST_GET_SELECTION(menu_list, 0)->size;
file_list_t *list = MENU_LIST_GET_SELECTION(menu_list, 0);
bool playlist_valid = false;
size_t playlist_index = selection;
/* Get playlist index corresponding
* to the selected entry */
if ( list
&& (selection < list_size)
&& (list->list[selection].type == FILE_TYPE_RPL_ENTRY))
{
playlist_valid = true;
playlist_index = list->list[selection].entry_idx;
}
gfx_thumbnail_set_icon_playlist(thumbnail_path_data,
playlist_valid ? playlist_get_cached() : NULL, playlist_index);
}
}
}
static void xmb_update_savestate_thumbnail_image(void *data)
{
xmb_handle_t *xmb = (xmb_handle_t*)data;
@ -1528,7 +1602,7 @@ static void xmb_update_savestate_thumbnail_image(void *data)
static void xmb_selection_pointer_changed(
xmb_handle_t *xmb, bool allow_animations)
{
unsigned i, end, height;
unsigned i, end, height, entry_start, entry_end;
size_t num = 0;
int threshold = 0;
struct menu_state *menu_st = menu_state_get_ptr();
@ -1550,6 +1624,7 @@ static void xmb_selection_pointer_changed(
menu_st->entries.begin = num;
video_driver_get_size(NULL, &height);
xmb_calculate_visible_range(xmb, height, end, (unsigned)selection, &entry_start, &entry_end);
for (i = 0; i < end; i++)
{
@ -1564,6 +1639,21 @@ static void xmb_selection_pointer_changed(
iy = xmb_item_y(xmb, i, selection);
real_iy = iy + xmb->margins_screen_top;
if (xmb->is_playlist)
{
xmb_icons_t *thumbnail_icon = &node->thumbnail_icon;
if(i>=entry_start && i<=entry_end)
{
/* Playlist updates */
xmb_set_dynamic_icon_content(xmb, NULL, i, thumbnail_icon);
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_cancel_pending_requests();
if (gfx_thumbnail_is_enabled(menu_st->thumbnail_path_data, GFX_THUMBNAIL_ICON))
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
}
}
if (i == selection)
{
unsigned depth = (unsigned)xmb_list_get_size(xmb, MENU_LIST_PLAIN);
@ -2184,6 +2274,45 @@ static void xmb_tab_set_selection(void *data)
}
}
static void xmb_populate_dynamic_icons(xmb_handle_t *xmb)
{
unsigned i, entry_start, entry_end, height;
struct menu_state *menu_st = menu_state_get_ptr();
menu_list_t *menu_list = menu_st->entries.list;
file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, 0);
unsigned end = (unsigned)selection_buf->size;
size_t selection = menu_st->selection_ptr;
if (gfx_thumbnail_is_enabled(menu_st->thumbnail_path_data, GFX_THUMBNAIL_ICON))
{
/* Clear current textures if they are there */
xmb_unload_icon_thumbnail_textures(xmb);
entry_start = 0;
entry_end = end;
video_driver_get_size(NULL, &height);
xmb_calculate_visible_range(xmb, height, end, (unsigned)selection, &entry_start, &entry_end);
if(xmb->is_playlist)
{
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
for (i = entry_start; i <= entry_end; i++)
{
xmb_icons_t *thumbnail_icon;
xmb_node_t *node = (xmb_node_t*)selection_buf->list[i].userdata;
if(!node)
continue;
thumbnail_icon = &node->thumbnail_icon;
xmb_set_dynamic_icon_content(xmb, NULL, i, thumbnail_icon);
gfx_thumbnail_cancel_pending_requests();
}
}
}
}
static void xmb_list_switch(xmb_handle_t *xmb)
{
gfx_animation_ctx_entry_t anim_entry;
@ -2829,6 +2958,11 @@ static void xmb_populate_entries(void *data,
xmb_set_title(xmb);
if(xmb->is_playlist)
{
xmb_populate_dynamic_icons(xmb);
}
if (xmb->allow_dynamic_wallpaper)
xmb_update_dynamic_wallpaper(xmb, false);
@ -4238,7 +4372,7 @@ static int xmb_draw_item(
unsigned height)
{
menu_entry_t entry;
float icon_x, icon_y, label_offset;
float icon_x, icon_y, label_offset, gfx_icon_x, gfx_icon_y, gfx_icon_height, gfx_icon_width;
gfx_animation_ctx_ticker_t ticker;
gfx_animation_ctx_ticker_smooth_t ticker_smooth;
char tmp[255];
@ -4261,6 +4395,7 @@ static int xmb_draw_item(
bool show_switch_icons = settings->bools.menu_xmb_switch_icons;
unsigned show_history_icons = settings->uints.playlist_show_history_icons;
unsigned vertical_fade_factor = settings->uints.menu_xmb_vertical_fade_factor;
bool show_icon_thumbnail;
/* Initial ticker configuration */
if (use_smooth_ticker)
@ -4808,6 +4943,29 @@ static int xmb_draw_item(
}
}
gfx_icon_x = x;
gfx_icon_y = y;
gfx_icon_height = gfx_icon_width = xmb->icon_size;
show_icon_thumbnail =
(xmb->is_playlist
&& gfx_thumbnail_is_enabled(&node->thumbnail_icon.thumbnail_path_data, GFX_THUMBNAIL_ICON)
&& (node->thumbnail_icon.icon.status == GFX_THUMBNAIL_STATUS_AVAILABLE));
if (show_icon_thumbnail)
{
texture = node->thumbnail_icon.icon.texture;
gfx_icon_width = gfx_icon_height = (xmb->icon_size * 1.8);
gfx_thumbnail_get_draw_dimensions(
&node->thumbnail_icon.icon,
gfx_icon_width, gfx_icon_height, 1.0f,
&gfx_icon_width, &gfx_icon_height);
/* Adjust icon location by recentering with half width and height */
gfx_icon_x = gfx_icon_x + xmb->icon_size - gfx_icon_width;
gfx_icon_y = gfx_icon_y - (xmb->icon_size / 2) + (gfx_icon_height / 2);
}
xmb_draw_icon(
userdata,
p_disp,
@ -4815,10 +4973,11 @@ static int xmb_draw_item(
video_width,
video_height,
shadows_enable,
xmb->icon_size,
gfx_icon_width,
gfx_icon_height,
texture,
x,
y,
gfx_icon_x,
gfx_icon_y,
width,
height,
1.0,
@ -4844,6 +5003,7 @@ static int xmb_draw_item(
video_height,
shadows_enable,
xmb->icon_size,
xmb->icon_size,
texture_switch,
node->x + xmb->margins_screen_left
+ xmb->icon_spacing_horizontal
@ -5351,6 +5511,36 @@ static int xmb_menu_entry_action(
return generic_menu_entry_action(userdata, entry, i, new_action);
}
static bool xmb_load_dynamic_icon(const char *icon_path,
gfx_thumbnail_t *icon)
{
unsigned width, height;
/* Wierd unwanted state */
if(icon->status == GFX_THUMBNAIL_STATUS_UNKNOWN &&
icon->texture > 0)
gfx_thumbnail_reset(icon);
if(gfx_display_reset_icon_texture(
icon_path,
&icon->texture,
TEXTURE_FILTER_MIPMAP_LINEAR,
&width,
&height))
{
icon->width = width;
icon->height = height;
icon->alpha = 0.0f;
icon->delay_timer = 0.0f;
icon->flags &= ~(GFX_THUMB_FLAG_FADE_ACTIVE
| GFX_THUMB_FLAG_CORE_ASPECT);
icon->status = GFX_THUMBNAIL_STATUS_AVAILABLE;
return true;
}
return false;
}
static void xmb_render(void *data,
unsigned width, unsigned height, bool is_idle)
{
@ -5369,9 +5559,16 @@ static void xmb_render(void *data,
struct menu_state *menu_st = menu_state_get_ptr();
menu_input_t *menu_input = &menu_st->input_state;
menu_list_t *menu_list = menu_st->entries.list;
size_t end = MENU_LIST_GET_SELECTION(menu_list, 0)->size;
file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, 0);
size_t end = selection_buf->size;
gfx_display_t *p_disp = disp_get_ptr();
gfx_animation_t *p_anim = anim_get_ptr();
size_t selection = menu_st->selection_ptr;
playlist_t *playlist = playlist_get_cached();
unsigned first = 0;
unsigned last = (unsigned)end;
unsigned gfx_thumbnail_upscale_threshold = settings->uints.gfx_thumbnail_upscale_threshold;
bool network_on_demand_thumbnails = settings->bools.network_on_demand_thumbnails;
if (!xmb)
return;
@ -5551,6 +5748,40 @@ static void xmb_render(void *data,
}
}
}
/* Handle any pending icon thumbnail load requests */
if (xmb->thumbnails.pending_icons != XMB_PENDING_THUMBNAIL_NONE)
{
/* Based on height of screen calculate the available entries that are visible */
if (height)
xmb_calculate_visible_range(xmb, height, end, (unsigned)selection, &first, &last);
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_NONE;
for (i = first; i <= last; i++)
{
xmb_node_t *node = (xmb_node_t*)selection_buf->list[i].userdata;
xmb_icons_t *thumbnail_icon = &node->thumbnail_icon;
if(thumbnail_icon->icon.status == GFX_THUMBNAIL_STATUS_UNKNOWN)
{
if(!xmb_load_dynamic_icon(thumbnail_icon->thumbnail_path_data.icon_path,
&thumbnail_icon->icon))
{
gfx_thumbnail_request_stream(
&thumbnail_icon->thumbnail_path_data,
p_anim,
GFX_THUMBNAIL_ICON,
playlist, i,
&thumbnail_icon->icon,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
}
}
if (thumbnail_icon->icon.status == GFX_THUMBNAIL_STATUS_UNKNOWN)
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
}
}
/* Handle any pending thumbnail load requests */
if (xmb->thumbnails.pending != XMB_PENDING_THUMBNAIL_NONE)
@ -6359,6 +6590,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
video_height,
shadows_enable,
xmb->icon_size,
xmb->icon_size,
xmb->textures.list[XMB_TEXTURE_ARROW],
xmb->x + xmb->margins_screen_left +
xmb->icon_spacing_horizontal -
@ -6667,6 +6899,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
video_height,
shadows_enable,
xmb->icon_size,
xmb->icon_size,
xmb->textures.list[
powerstate.charging? XMB_TEXTURE_BATTERY_CHARGING :
(powerstate.percent > 80)? XMB_TEXTURE_BATTERY_FULL :
@ -6726,6 +6959,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
video_height,
shadows_enable,
xmb->icon_size,
xmb->icon_size,
xmb->textures.list[XMB_TEXTURE_CLOCK],
video_width - xmb->margins_title_left + margin_offset - x_pos,
xmb->icon_size + xmb->margins_title_top + margin_offset,
@ -6838,6 +7072,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
video_height,
shadows_enable,
xmb->icon_size,
xmb->icon_size,
texture,
x,
y,
@ -8311,6 +8546,7 @@ static void xmb_context_destroy(void *data)
video_driver_texture_unload(&xmb->textures.list[i]);
xmb_unload_thumbnail_textures(xmb);
xmb_unload_icon_thumbnail_textures(xmb);
xmb_context_destroy_horizontal_list(xmb);
xmb_context_bg_destroy(xmb);

View File

@ -11496,6 +11496,7 @@ unsigned menu_displaylist_build_list(
{MENU_ENUM_LABEL_MENU_RGUI_INLINE_THUMBNAILS, PARSE_ONLY_BOOL, true},
{MENU_ENUM_LABEL_THUMBNAILS, PARSE_ONLY_UINT, true},
{MENU_ENUM_LABEL_LEFT_THUMBNAILS, PARSE_ONLY_UINT, true},
{MENU_ENUM_LABEL_ICON_THUMBNAILS, PARSE_ONLY_UINT, true},
{MENU_ENUM_LABEL_XMB_VERTICAL_THUMBNAILS, PARSE_ONLY_BOOL, true},
{MENU_ENUM_LABEL_MENU_XMB_THUMBNAIL_SCALE_FACTOR, PARSE_ONLY_UINT, true},
{MENU_ENUM_LABEL_OZONE_THUMBNAIL_SCALE_FACTOR, PARSE_ONLY_FLOAT, true},

View File

@ -3369,6 +3369,27 @@ static void setting_get_string_representation_uint_menu_left_thumbnails(
}
}
static void setting_get_string_representation_uint_menu_icon_thumbnails(
rarch_setting_t *setting,
char *s, size_t len)
{
if (!setting)
return;
switch (*setting->value.target.unsigned_integer)
{
case 0:
strlcpy(s, msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_OFF), len);
break;
case 1:
strlcpy(s,
msg_hash_to_str(
MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_LOGOS), len);
break;
}
}
static void setting_set_string_representation_timedate_date_seperator(char *s)
{
settings_t *settings = config_get_ptr();
@ -19884,6 +19905,23 @@ static bool setting_append_list(
&setting_get_string_representation_uint_menu_left_thumbnails;
menu_settings_list_current_add_range(list, list_info, 0, 3, 1, true, true);
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_RADIO_BUTTONS;
CONFIG_UINT(
list, list_info,
&settings->uints.menu_icon_thumbnails,
MENU_ENUM_LABEL_ICON_THUMBNAILS,
MENU_ENUM_LABEL_VALUE_ICON_THUMBNAILS,
DEFAULT_MENU_ICON_THUMBNAILS_DEFAULT,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler);
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
(*list)[list_info->index - 1].get_string_representation =
&setting_get_string_representation_uint_menu_icon_thumbnails;
menu_settings_list_current_add_range(list, list_info, 0, 1, 1, true, true);
(*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_RADIO_BUTTONS;
}
if (string_is_equal(settings->arrays.menu_driver, "xmb"))

View File

@ -1618,6 +1618,7 @@ enum msg_hash_enums
MENU_LABEL(LEFT_THUMBNAILS_RGUI),
MENU_LABEL(LEFT_THUMBNAILS_OZONE),
MENU_LABEL(LEFT_THUMBNAILS_MATERIALUI),
MENU_LABEL(ICON_THUMBNAILS),
MENU_LABEL(XMB_VERTICAL_THUMBNAILS),
MENU_LABEL(MENU_XMB_THUMBNAIL_SCALE_FACTOR),
MENU_LABEL(MENU_XMB_VERTICAL_FADE_FACTOR),
@ -1977,6 +1978,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LABEL_DISPLAY_MODE,
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_RIGHT_THUMBNAIL_MODE,
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_LEFT_THUMBNAIL_MODE,
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_ICON_THUMBNAIL_MODE,
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_PLAYLIST_SORT_MODE,
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_MANUAL_CONTENT_SCAN_CORE_NAME,
@ -3680,6 +3682,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_BOXARTS,
MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_SCREENSHOTS,
MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_TITLE_SCREENS,
MENU_ENUM_LABEL_VALUE_THUMBNAIL_MODE_LOGOS,
MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_POINT,
MENU_ENUM_LABEL_VALUE_RGUI_THUMB_SCALE_BILINEAR,

View File

@ -3467,6 +3467,10 @@ void playlist_set_thumbnail_mode(
playlist->left_thumbnail_mode = thumbnail_mode;
playlist->modified = true;
break;
case PLAYLIST_THUMBNAIL_ICON:
/* should never be reached. Do Nothing */
break;
}
}

View File

@ -61,7 +61,8 @@ enum playlist_thumbnail_mode
PLAYLIST_THUMBNAIL_MODE_OFF,
PLAYLIST_THUMBNAIL_MODE_SCREENSHOTS,
PLAYLIST_THUMBNAIL_MODE_TITLE_SCREENS,
PLAYLIST_THUMBNAIL_MODE_BOXARTS
PLAYLIST_THUMBNAIL_MODE_BOXARTS,
PLAYLIST_THUMBNAIL_MODE_LOGO
};
enum playlist_thumbnail_match_mode
@ -84,7 +85,8 @@ enum playlist_sort_mode
enum playlist_thumbnail_id
{
PLAYLIST_THUMBNAIL_RIGHT = 0,
PLAYLIST_THUMBNAIL_LEFT
PLAYLIST_THUMBNAIL_LEFT,
PLAYLIST_THUMBNAIL_ICON
};
enum playlist_thumbnail_name_flags