mirror of
https://github.com/libretro/RetroArch
synced 2025-03-28 19:20:35 +00:00
(RGUI) Savestate thumbnails (#14326)
This commit is contained in:
parent
245319c389
commit
c818024bc6
@ -114,8 +114,8 @@ int action_switch_thumbnail(const char *path,
|
||||
if (!settings)
|
||||
return -1;
|
||||
|
||||
/* RGUI is a special case where thumbnail 'switch' corresponds to
|
||||
* toggling thumbnail view on/off.
|
||||
/* RGUI has its own cycling for thumbnails in order to allow
|
||||
* cycling all images in fullscreen mode.
|
||||
* GLUI is a special case where thumbnail 'switch' corresponds to
|
||||
* changing thumbnail view mode.
|
||||
* For other menu drivers, we cycle through available thumbnail
|
||||
|
@ -284,6 +284,7 @@ typedef struct
|
||||
|
||||
unsigned mini_thumbnail_max_width;
|
||||
unsigned mini_thumbnail_max_height;
|
||||
unsigned mini_thumbnail_delay;
|
||||
unsigned last_width;
|
||||
unsigned last_height;
|
||||
unsigned window_width;
|
||||
@ -298,15 +299,24 @@ typedef struct
|
||||
|
||||
uint32_t thumbnail_queue_size;
|
||||
uint32_t left_thumbnail_queue_size;
|
||||
int8_t gfx_thumbnails_prev;
|
||||
|
||||
rgui_particle_t particles[RGUI_NUM_PARTICLES]; /* float alignment */
|
||||
|
||||
size_t playlist_index;
|
||||
int16_t scroll_y;
|
||||
rgui_colors_t colors; /* int16_t alignment */
|
||||
|
||||
struct scaler_ctx image_scaler;
|
||||
menu_input_pointer_t pointer;
|
||||
|
||||
/* These have to be huge, because runloop_st->name.savestate
|
||||
* has a hard-coded size of 8192...
|
||||
* (the extra space here is required to silence compiler
|
||||
* warnings...) */
|
||||
char savestate_thumbnail_file_path[8204];
|
||||
char prev_savestate_thumbnail_file_path[8204];
|
||||
|
||||
char msgbox[1024];
|
||||
char theme_preset_path[PATH_MAX_LENGTH]; /* Must be a fixed length array... */
|
||||
char theme_dynamic_path[PATH_MAX_LENGTH]; /* Must be a fixed length array... */
|
||||
@ -329,6 +339,8 @@ typedef struct
|
||||
bool shadow_enable;
|
||||
bool extended_ascii_enable;
|
||||
bool is_playlist;
|
||||
bool is_quick_menu;
|
||||
bool is_state_slot;
|
||||
bool entry_has_thumbnail;
|
||||
bool entry_has_left_thumbnail;
|
||||
bool show_fs_thumbnail;
|
||||
@ -2310,15 +2322,31 @@ static bool rgui_downscale_thumbnail(
|
||||
struct texture_image *image_src,
|
||||
struct texture_image *image_dst)
|
||||
{
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
bool thumbnail_core_aspect = !string_is_empty(rgui->savestate_thumbnail_file_path);
|
||||
/* Determine output dimensions */
|
||||
float display_aspect_ratio = (float)max_width / (float)max_height;
|
||||
float aspect_ratio = (float)image_src->width
|
||||
/ (float)image_src->height;
|
||||
float aspect_ratio = (float)image_src->width / (float)image_src->height;
|
||||
float core_aspect = (thumbnail_core_aspect && video_st)
|
||||
? video_st->av_info.geometry.aspect_ratio : aspect_ratio;
|
||||
|
||||
if (aspect_ratio > display_aspect_ratio)
|
||||
{
|
||||
image_dst->width = max_width;
|
||||
image_dst->height = image_src->height * max_width / image_src->width;
|
||||
|
||||
if (thumbnail_core_aspect)
|
||||
{
|
||||
image_dst->height = image_dst->height * (aspect_ratio / core_aspect);
|
||||
|
||||
if (image_dst->height > image_src->height)
|
||||
{
|
||||
image_dst->height = image_src->height;
|
||||
image_dst->width = (float)image_src->width * (image_dst->height / (float)image_src->height);
|
||||
image_dst->width = image_dst->width / (aspect_ratio / core_aspect);
|
||||
}
|
||||
}
|
||||
|
||||
/* Account for any possible rounding errors... */
|
||||
image_dst->height = (image_dst->height < 1) ? 1 : image_dst->height;
|
||||
image_dst->height = (image_dst->height > max_height) ? max_height : image_dst->height;
|
||||
@ -2327,6 +2355,10 @@ static bool rgui_downscale_thumbnail(
|
||||
{
|
||||
image_dst->height = max_height;
|
||||
image_dst->width = image_src->width * max_height / image_src->height;
|
||||
|
||||
if (thumbnail_core_aspect)
|
||||
image_dst->width = image_dst->width / (aspect_ratio / core_aspect);
|
||||
|
||||
/* Account for any possible rounding errors... */
|
||||
image_dst->width = (image_dst->width < 1) ? 1 : image_dst->width;
|
||||
image_dst->width = (image_dst->width > max_width) ? max_width : image_dst->width;
|
||||
@ -2531,11 +2563,26 @@ static bool rgui_load_image(void *userdata, void *data, enum menu_image_type typ
|
||||
{
|
||||
struct texture_image *image = (struct texture_image*)data;
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool menu_rgui_inline_thumbnails =
|
||||
settings->bools.menu_rgui_inline_thumbnails;
|
||||
bool savestate_thumbnail_enable =
|
||||
settings->bools.savestate_thumbnail_enable;
|
||||
unsigned menu_rgui_thumbnail_downscaler =
|
||||
settings->uints.menu_rgui_thumbnail_downscaler;
|
||||
rgui_process_thumbnail(rgui, &rgui->mini_left_thumbnail, &rgui->left_thumbnail_queue_size,
|
||||
menu_rgui_thumbnail_downscaler,
|
||||
image);
|
||||
|
||||
if (rgui->show_fs_thumbnail)
|
||||
rgui_process_thumbnail(rgui, &rgui->fs_thumbnail, &rgui->left_thumbnail_queue_size,
|
||||
menu_rgui_thumbnail_downscaler,
|
||||
image);
|
||||
else if (menu_rgui_inline_thumbnails || savestate_thumbnail_enable)
|
||||
rgui_process_thumbnail(rgui, &rgui->mini_left_thumbnail, &rgui->left_thumbnail_queue_size,
|
||||
menu_rgui_thumbnail_downscaler,
|
||||
image);
|
||||
else
|
||||
{
|
||||
if (rgui->left_thumbnail_queue_size > 0)
|
||||
rgui->left_thumbnail_queue_size--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -4705,6 +4752,20 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui, gfx_display_t *p_disp,
|
||||
bool delay_update);
|
||||
#endif
|
||||
|
||||
static bool rgui_is_running_quick_menu(void)
|
||||
{
|
||||
menu_entry_t entry;
|
||||
|
||||
MENU_ENTRY_INIT(entry);
|
||||
entry.path_enabled = false;
|
||||
entry.value_enabled = false;
|
||||
entry.sublabel_enabled = false;
|
||||
menu_entry_get(&entry, 0, 0, NULL, true);
|
||||
|
||||
return string_is_equal(entry.label, "resume_content") ||
|
||||
string_is_equal(entry.label, "state_slot");
|
||||
}
|
||||
|
||||
static void rgui_render(void *data,
|
||||
unsigned width, unsigned height,
|
||||
bool is_idle)
|
||||
@ -4745,7 +4806,7 @@ static void rgui_render(void *data,
|
||||
|
||||
bool show_fs_thumbnail =
|
||||
rgui->show_fs_thumbnail &&
|
||||
rgui->entry_has_thumbnail &&
|
||||
(rgui->entry_has_thumbnail || !string_is_empty(rgui->savestate_thumbnail_file_path)) &&
|
||||
(rgui->fs_thumbnail.is_valid || (rgui->thumbnail_queue_size > 0));
|
||||
gfx_animation_t *p_anim = anim_get_ptr();
|
||||
gfx_display_t *p_disp = disp_get_ptr();
|
||||
@ -4754,6 +4815,13 @@ static void rgui_render(void *data,
|
||||
if (!rgui || !rgui->frame_buf.data)
|
||||
return;
|
||||
|
||||
/* Show thumbnails only after certain period to prevent flashing */
|
||||
if (rgui->mini_thumbnail_delay > 0)
|
||||
{
|
||||
rgui_inline_thumbnails = false;
|
||||
rgui->mini_thumbnail_delay--;
|
||||
}
|
||||
|
||||
/* Apply pending aspect ratio update */
|
||||
if (rgui->aspect_update_pending)
|
||||
{
|
||||
@ -4948,14 +5016,35 @@ static void rgui_render(void *data,
|
||||
const char *thumbnail_title = NULL;
|
||||
char thumbnail_title_buf[255];
|
||||
unsigned title_x, title_width;
|
||||
bool is_state_slot = !string_is_empty(rgui->savestate_thumbnail_file_path);
|
||||
thumbnail_title_buf[0] = '\0';
|
||||
|
||||
/* Draw thumbnail */
|
||||
rgui_render_fs_thumbnail(rgui, fb_width, fb_height, fb_pitch);
|
||||
|
||||
/* Get thumbnail title */
|
||||
if (gfx_thumbnail_get_label(rgui->thumbnail_path_data, &thumbnail_title))
|
||||
if (gfx_thumbnail_get_label(rgui->thumbnail_path_data, &thumbnail_title) ||
|
||||
is_state_slot)
|
||||
{
|
||||
/* State slot title */
|
||||
if (is_state_slot)
|
||||
{
|
||||
if (rgui->is_quick_menu)
|
||||
{
|
||||
snprintf(thumbnail_title_buf, sizeof(thumbnail_title_buf), "%s %d",
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_STATE_SLOT),
|
||||
config_get_ptr()->ints.state_slot);
|
||||
thumbnail_title = thumbnail_title_buf;
|
||||
}
|
||||
else if (rgui->is_state_slot)
|
||||
{
|
||||
snprintf(thumbnail_title_buf, sizeof(thumbnail_title_buf), "%s %d",
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_STATE_SLOT),
|
||||
(int)menu_navigation_get_selection() - 1);
|
||||
thumbnail_title = thumbnail_title_buf;
|
||||
}
|
||||
}
|
||||
|
||||
/* Format thumbnail title */
|
||||
if (use_smooth_ticker)
|
||||
{
|
||||
@ -4993,7 +5082,7 @@ static void rgui_render(void *data,
|
||||
|
||||
/* Draw thumbnail title */
|
||||
blit_line(rgui, fb_width, ticker_x_offset + title_x,
|
||||
0, thumbnail_title_buf,
|
||||
1, thumbnail_title_buf,
|
||||
rgui->colors.hover_color, rgui->colors.shadow_color);
|
||||
}
|
||||
}
|
||||
@ -5011,9 +5100,12 @@ static void rgui_render(void *data,
|
||||
unsigned core_name_len = menu_timedate_enable ?
|
||||
((timedate_x - rgui->term_layout.start_x) / rgui->font_width_stride) - 3 :
|
||||
rgui->term_layout.width - 1;
|
||||
bool show_mini_thumbnails = rgui->is_playlist && rgui_inline_thumbnails;
|
||||
bool show_mini_thumbnails = rgui_inline_thumbnails &&
|
||||
(rgui->is_playlist || (rgui->is_quick_menu && !rgui_is_running_quick_menu()));
|
||||
bool show_thumbnail = false;
|
||||
bool show_left_thumbnail = false;
|
||||
bool show_savestate_thumbnail = (!string_is_empty(rgui->savestate_thumbnail_file_path) &&
|
||||
(rgui->is_state_slot || (rgui->is_quick_menu && rgui_is_running_quick_menu())));
|
||||
unsigned thumbnail_panel_width = 0;
|
||||
unsigned term_mid_point = 0;
|
||||
size_t powerstate_len = 0;
|
||||
@ -5373,7 +5465,16 @@ static void rgui_render(void *data,
|
||||
}
|
||||
|
||||
/* Draw mini thumbnails, if required */
|
||||
if (show_mini_thumbnails)
|
||||
if (show_savestate_thumbnail)
|
||||
{
|
||||
thumbnail_t *thumbnail_savestate = &rgui->mini_left_thumbnail;
|
||||
if (show_savestate_thumbnail && thumbnail_savestate)
|
||||
rgui_render_mini_thumbnail(rgui, thumbnail_savestate,
|
||||
rgui->frame_buf.data,
|
||||
GFX_THUMBNAIL_LEFT,
|
||||
fb_width, fb_height, fb_pitch, menu_rgui_swap_thumbnails);
|
||||
}
|
||||
else if (show_mini_thumbnails)
|
||||
{
|
||||
thumbnail_t *thumbnail1 = &rgui->mini_thumbnail;
|
||||
thumbnail_t *thumbnail2 = &rgui->mini_left_thumbnail;
|
||||
@ -5993,7 +6094,7 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui,
|
||||
|
||||
/* Allocate thumbnail buffer */
|
||||
rgui->fs_thumbnail.max_width = rgui->frame_buf.width;
|
||||
rgui->fs_thumbnail.max_height = rgui->frame_buf.height;
|
||||
rgui->fs_thumbnail.max_height = rgui->frame_buf.height - (unsigned)(rgui->font_height_stride * 2.0f) - 1;
|
||||
rgui->fs_thumbnail.data = (uint16_t*)calloc(
|
||||
rgui->fs_thumbnail.max_width * rgui->fs_thumbnail.max_height, sizeof(uint16_t));
|
||||
if (!rgui->fs_thumbnail.data)
|
||||
@ -6173,11 +6274,15 @@ static void *rgui_init(void **userdata, bool video_is_threaded)
|
||||
|
||||
rgui->thumbnail_queue_size = 0;
|
||||
rgui->left_thumbnail_queue_size = 0;
|
||||
rgui->gfx_thumbnails_prev = -1;
|
||||
rgui->thumbnail_load_pending = false;
|
||||
rgui->thumbnail_load_trigger_time = 0;
|
||||
/* Ensure that we start with fullscreen thumbnails disabled */
|
||||
rgui->show_fs_thumbnail = false;
|
||||
|
||||
rgui->savestate_thumbnail_file_path[0] = '\0';
|
||||
rgui->prev_savestate_thumbnail_file_path[0] = '\0';
|
||||
|
||||
/* Ensure that pointer device starts with well defined
|
||||
* values (shoult not be necessary, but some platforms may
|
||||
* not handle struct initialisation correctly...) */
|
||||
@ -6389,7 +6494,7 @@ static void rgui_load_current_thumbnails(rgui_t *rgui, bool download_missing)
|
||||
/* Left thumbnail
|
||||
* (Note: there is no need to load this when viewing
|
||||
* fullscreen thumbnails) */
|
||||
if (!rgui->show_fs_thumbnail)
|
||||
if (!rgui->show_fs_thumbnail && string_is_empty(rgui->savestate_thumbnail_file_path))
|
||||
{
|
||||
if (gfx_thumbnail_get_path(rgui->thumbnail_path_data,
|
||||
GFX_THUMBNAIL_LEFT, &left_thumbnail_path))
|
||||
@ -6400,7 +6505,18 @@ static void rgui_load_current_thumbnails(rgui_t *rgui, bool download_missing)
|
||||
left_thumbnail_path,
|
||||
&thumbnails_missing);
|
||||
}
|
||||
|
||||
else if (!string_is_empty(rgui->savestate_thumbnail_file_path))
|
||||
{
|
||||
if (gfx_thumbnail_get_path(rgui->thumbnail_path_data,
|
||||
GFX_THUMBNAIL_LEFT, &left_thumbnail_path))
|
||||
rgui->entry_has_left_thumbnail = rgui_request_thumbnail(
|
||||
&rgui->mini_left_thumbnail,
|
||||
GFX_THUMBNAIL_LEFT,
|
||||
&rgui->left_thumbnail_queue_size,
|
||||
rgui->savestate_thumbnail_file_path,
|
||||
&thumbnails_missing);
|
||||
}
|
||||
|
||||
/* Reset 'load pending' state */
|
||||
rgui->thumbnail_load_pending = false;
|
||||
|
||||
@ -6422,6 +6538,117 @@ static void rgui_load_current_thumbnails(rgui_t *rgui, bool download_missing)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rgui_update_savestate_thumbnail_path(void *data, unsigned i)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
rgui_t *rgui = (rgui_t*)data;
|
||||
int state_slot = settings->ints.state_slot;
|
||||
bool savestate_thumbnail_enable
|
||||
= settings->bools.savestate_thumbnail_enable;
|
||||
if (!rgui)
|
||||
return;
|
||||
|
||||
/* Cache previous savestate thumbnail path */
|
||||
strlcpy(
|
||||
rgui->prev_savestate_thumbnail_file_path,
|
||||
rgui->savestate_thumbnail_file_path,
|
||||
sizeof(rgui->prev_savestate_thumbnail_file_path));
|
||||
|
||||
rgui->savestate_thumbnail_file_path[0] = '\0';
|
||||
|
||||
/* Savestate thumbnails are only relevant
|
||||
* when viewing the running quick menu or state slots */
|
||||
if (!((rgui->is_quick_menu && rgui_is_running_quick_menu()) || rgui->is_state_slot))
|
||||
return;
|
||||
|
||||
if (savestate_thumbnail_enable)
|
||||
{
|
||||
menu_entry_t entry;
|
||||
|
||||
MENU_ENTRY_INIT(entry);
|
||||
entry.path_enabled = false;
|
||||
entry.rich_label_enabled = false;
|
||||
entry.value_enabled = false;
|
||||
entry.sublabel_enabled = false;
|
||||
menu_entry_get(&entry, 0, i, NULL, true);
|
||||
|
||||
if (!string_is_empty(entry.label))
|
||||
{
|
||||
if (string_to_unsigned(entry.label) == MENU_ENUM_LABEL_STATE_SLOT ||
|
||||
string_is_equal(entry.label, "state_slot") ||
|
||||
string_is_equal(entry.label, "loadstate") ||
|
||||
string_is_equal(entry.label, "savestate"))
|
||||
{
|
||||
char path[8204];
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
|
||||
path[0] = '\0';
|
||||
|
||||
/* State slot dropdown */
|
||||
if (string_to_unsigned(entry.label) == MENU_ENUM_LABEL_STATE_SLOT)
|
||||
{
|
||||
state_slot = i - 1;
|
||||
rgui->is_state_slot = true;
|
||||
}
|
||||
|
||||
if (state_slot > 0)
|
||||
snprintf(path, sizeof(path), "%s%d",
|
||||
runloop_st->name.savestate, state_slot);
|
||||
else if (state_slot < 0)
|
||||
fill_pathname_join_delim(path,
|
||||
runloop_st->name.savestate, "auto", '.', sizeof(path));
|
||||
else
|
||||
strlcpy(path, runloop_st->name.savestate, sizeof(path));
|
||||
|
||||
strlcat(path, FILE_PATH_PNG_EXTENSION, sizeof(path));
|
||||
|
||||
if (path_is_valid(path))
|
||||
{
|
||||
strlcpy(
|
||||
rgui->savestate_thumbnail_file_path, path,
|
||||
sizeof(rgui->savestate_thumbnail_file_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rgui_reset_savestate_thumbnail(void *data)
|
||||
{
|
||||
rgui_t *rgui = (rgui_t*)data;
|
||||
|
||||
rgui->mini_left_thumbnail.width = 0;
|
||||
rgui->mini_left_thumbnail.height = 0;
|
||||
rgui->mini_left_thumbnail.is_valid = false;
|
||||
rgui->mini_left_thumbnail.path[0] = '\0';
|
||||
}
|
||||
|
||||
static void rgui_update_savestate_thumbnail_image(void *data)
|
||||
{
|
||||
rgui_t *rgui = (rgui_t*)data;
|
||||
if (!rgui)
|
||||
return;
|
||||
|
||||
/* Savestate thumbnails are only relevant
|
||||
* when viewing the running quick menu or state slots */
|
||||
if (!((rgui->is_quick_menu && rgui_is_running_quick_menu()) || rgui->is_state_slot))
|
||||
return;
|
||||
|
||||
/* If path is empty, just reset thumbnail */
|
||||
if (string_is_empty(rgui->savestate_thumbnail_file_path))
|
||||
rgui_reset_savestate_thumbnail(rgui);
|
||||
else
|
||||
{
|
||||
bool thumbnails_missing = false;
|
||||
rgui->entry_has_left_thumbnail = rgui_request_thumbnail(
|
||||
&rgui->mini_left_thumbnail,
|
||||
GFX_THUMBNAIL_LEFT,
|
||||
&rgui->left_thumbnail_queue_size,
|
||||
rgui->savestate_thumbnail_file_path,
|
||||
&thumbnails_missing);
|
||||
}
|
||||
}
|
||||
|
||||
static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load)
|
||||
{
|
||||
bool has_thumbnail = false;
|
||||
@ -6435,7 +6662,7 @@ static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load)
|
||||
|
||||
/* Update thumbnail content/path */
|
||||
if ((rgui->show_fs_thumbnail || menu_rgui_inline_thumbnails)
|
||||
&& rgui->is_playlist)
|
||||
&& (rgui->is_playlist || rgui->is_quick_menu))
|
||||
{
|
||||
size_t selection = menu_navigation_get_selection();
|
||||
size_t list_size = menu_entries_get_size();
|
||||
@ -6443,14 +6670,24 @@ static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load)
|
||||
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))
|
||||
if (rgui->is_playlist)
|
||||
{
|
||||
/* 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;
|
||||
rgui->playlist_index = playlist_index;
|
||||
}
|
||||
}
|
||||
else if (rgui->is_quick_menu &&
|
||||
string_is_empty(rgui->savestate_thumbnail_file_path))
|
||||
{
|
||||
playlist_valid = true;
|
||||
playlist_index = list->list[selection].entry_idx;
|
||||
playlist_index = rgui->playlist_index;
|
||||
}
|
||||
|
||||
if (gfx_thumbnail_set_content_playlist(rgui->thumbnail_path_data,
|
||||
@ -6466,6 +6703,19 @@ static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load)
|
||||
}
|
||||
}
|
||||
|
||||
/* Save state thumbnails */
|
||||
if (rgui->is_quick_menu || rgui->is_state_slot)
|
||||
{
|
||||
size_t selection = menu_navigation_get_selection();
|
||||
size_t list_size = menu_entries_get_size();
|
||||
|
||||
if (selection < list_size)
|
||||
{
|
||||
rgui_update_savestate_thumbnail_path(rgui, selection);
|
||||
rgui_update_savestate_thumbnail_image(rgui);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether thumbnails should be loaded */
|
||||
if (has_thumbnail)
|
||||
{
|
||||
@ -6481,6 +6731,14 @@ static void rgui_scan_selected_entry_thumbnail(rgui_t *rgui, bool force_load)
|
||||
}
|
||||
}
|
||||
|
||||
static void rgui_update_thumbnail_image(void *data)
|
||||
{
|
||||
rgui_t *rgui = (rgui_t*)data;
|
||||
|
||||
if (rgui->is_playlist)
|
||||
rgui_scan_selected_entry_thumbnail(rgui, true);
|
||||
}
|
||||
|
||||
static void rgui_toggle_fs_thumbnail(rgui_t *rgui,
|
||||
bool menu_rgui_inline_thumbnails)
|
||||
{
|
||||
@ -6493,6 +6751,9 @@ static void rgui_toggle_fs_thumbnail(rgui_t *rgui,
|
||||
* currently inactive right thumbnail. */
|
||||
if (menu_rgui_inline_thumbnails)
|
||||
{
|
||||
if (!string_is_empty(rgui->savestate_thumbnail_file_path))
|
||||
rgui_reset_savestate_thumbnail(rgui);
|
||||
|
||||
if (rgui->show_fs_thumbnail)
|
||||
{
|
||||
rgui->mini_thumbnail.width = 0;
|
||||
@ -6693,6 +6954,12 @@ static void rgui_populate_entries(void *data,
|
||||
rgui->is_playlist = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_PLAYLIST_LIST))
|
||||
|| string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_LOAD_CONTENT_HISTORY))
|
||||
|| string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_FAVORITES_LIST));
|
||||
|
||||
/* Determine whether this is the quick menu */
|
||||
rgui->is_quick_menu = string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS)) ||
|
||||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CONTENT_SETTINGS)) ||
|
||||
string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_SAVESTATE_LIST));
|
||||
rgui->is_state_slot = string_to_unsigned(path) == MENU_ENUM_LABEL_STATE_SLOT;
|
||||
|
||||
/* Set menu title */
|
||||
menu_entries_get_title(rgui->menu_title, sizeof(rgui->menu_title));
|
||||
@ -7116,6 +7383,18 @@ static void rgui_toggle(void *userdata, bool menu_on)
|
||||
if (!rgui || !settings)
|
||||
return;
|
||||
|
||||
/* Have to reset this, otherwise savestate
|
||||
* thumbnail won't update after selecting
|
||||
* 'save state' option */
|
||||
if (rgui->is_quick_menu)
|
||||
{
|
||||
rgui_reset_savestate_thumbnail(rgui);
|
||||
|
||||
/* Prevent thumbnail flashing after toggling menu */
|
||||
if (!menu_on)
|
||||
rgui->mini_thumbnail_delay = 1;
|
||||
}
|
||||
|
||||
if (menu_on)
|
||||
{
|
||||
if (aspect_ratio_lock != RGUI_ASPECT_RATIO_LOCK_NONE)
|
||||
@ -7188,6 +7467,24 @@ static void rgui_context_destroy(void *data)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rgui_thumbnail_cycle_dupe(rgui_t *rgui)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (settings->uints.gfx_thumbnails == settings->uints.menu_left_thumbnails)
|
||||
{
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.gfx_thumbnails,
|
||||
(rgui->gfx_thumbnails_prev > 0)
|
||||
? rgui->gfx_thumbnails_prev
|
||||
: settings->uints.gfx_thumbnails + 1);
|
||||
|
||||
if (settings->uints.gfx_thumbnails > 3)
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.gfx_thumbnails, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static enum menu_action rgui_parse_menu_entry_action(
|
||||
rgui_t *rgui, menu_entry_t *entry,
|
||||
enum menu_action action)
|
||||
@ -7228,30 +7525,134 @@ static enum menu_action rgui_parse_menu_entry_action(
|
||||
rgui->restore_aspect_lock = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MENU_ACTION_SCAN:
|
||||
case MENU_ACTION_START:
|
||||
/* If this is a playlist, both the 'scan'
|
||||
* command and 'start' action are used to
|
||||
* toggle the fullscreen thumbnail view
|
||||
* > 'scan' is more ergonomic, which is a
|
||||
* benefit for RGUI because its low
|
||||
* resolution framebuffer means fullscreen
|
||||
* thumbnails are likely to be viewed far
|
||||
* more often than with other menu drivers
|
||||
* > 'start' is the regular toggle button
|
||||
* for all other menu drivers, and is
|
||||
* included as a fallback here for users
|
||||
* with gamepads with limited numbers of
|
||||
* face buttons (e.g. a NES-style pad
|
||||
* does not possess a RetroPad Y/'scan'
|
||||
* button) */
|
||||
if (rgui->is_playlist)
|
||||
|
||||
if (rgui->show_fs_thumbnail)
|
||||
{
|
||||
rgui_thumbnail_cycle_dupe(rgui);
|
||||
rgui_toggle_fs_thumbnail(rgui, config_get_ptr()->bools.menu_rgui_inline_thumbnails);
|
||||
|
||||
if (!rgui->is_state_slot && !rgui->is_playlist)
|
||||
new_action = MENU_ACTION_NOOP;
|
||||
}
|
||||
break;
|
||||
case MENU_ACTION_CANCEL:
|
||||
if (rgui->show_fs_thumbnail)
|
||||
{
|
||||
rgui_thumbnail_cycle_dupe(rgui);
|
||||
rgui_toggle_fs_thumbnail(rgui, config_get_ptr()->bools.menu_rgui_inline_thumbnails);
|
||||
new_action = MENU_ACTION_NOOP;
|
||||
}
|
||||
break;
|
||||
case MENU_ACTION_START:
|
||||
/* Playlist thumbnail fullscreen toggle */
|
||||
if (rgui->is_playlist || (rgui->is_quick_menu && !rgui_is_running_quick_menu()))
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (!rgui->show_fs_thumbnail && rgui->gfx_thumbnails_prev < 0)
|
||||
rgui->gfx_thumbnails_prev = settings->uints.gfx_thumbnails;
|
||||
|
||||
/* Show fullscreen image from the left slot if main slot is empty */
|
||||
if (!rgui->mini_thumbnail.is_valid && rgui->mini_left_thumbnail.is_valid)
|
||||
{
|
||||
if (rgui->show_fs_thumbnail && rgui->gfx_thumbnails_prev > 0)
|
||||
{
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.gfx_thumbnails,
|
||||
rgui->gfx_thumbnails_prev);
|
||||
}
|
||||
else if (!rgui->show_fs_thumbnail)
|
||||
{
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.gfx_thumbnails,
|
||||
settings->uints.menu_left_thumbnails);
|
||||
}
|
||||
}
|
||||
|
||||
/* Avoid showing the same thumbnail after returning from fullscreen mode after cycling images */
|
||||
if (rgui->show_fs_thumbnail)
|
||||
rgui_thumbnail_cycle_dupe(rgui);
|
||||
|
||||
rgui_toggle_fs_thumbnail(rgui, config_get_ptr()->bools.menu_rgui_inline_thumbnails);
|
||||
new_action = MENU_ACTION_NOOP;
|
||||
|
||||
if (!rgui->show_fs_thumbnail)
|
||||
rgui->gfx_thumbnails_prev = -1;
|
||||
}
|
||||
break;
|
||||
case MENU_ACTION_SCAN:
|
||||
/* Save state slot fullscreen toggle */
|
||||
if ((rgui->is_state_slot || rgui->is_quick_menu) &&
|
||||
!string_is_empty(rgui->savestate_thumbnail_file_path))
|
||||
{
|
||||
rgui_toggle_fs_thumbnail(rgui, true);
|
||||
new_action = MENU_ACTION_NOOP;
|
||||
}
|
||||
/* Playlist thumbnail cycle */
|
||||
else if (rgui->is_playlist)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (settings->uints.gfx_thumbnails == 0)
|
||||
{
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.menu_left_thumbnails,
|
||||
settings->uints.menu_left_thumbnails + 1);
|
||||
|
||||
if (!rgui->show_fs_thumbnail &&
|
||||
settings->uints.gfx_thumbnails == settings->uints.menu_left_thumbnails)
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.menu_left_thumbnails,
|
||||
settings->uints.menu_left_thumbnails + 1);
|
||||
|
||||
if (settings->uints.menu_left_thumbnails > 3)
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.menu_left_thumbnails, 1);
|
||||
|
||||
if (!rgui->show_fs_thumbnail &&
|
||||
settings->uints.gfx_thumbnails == settings->uints.menu_left_thumbnails)
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.menu_left_thumbnails,
|
||||
settings->uints.menu_left_thumbnails + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.gfx_thumbnails,
|
||||
settings->uints.gfx_thumbnails + 1);
|
||||
|
||||
if (!rgui->show_fs_thumbnail &&
|
||||
settings->uints.gfx_thumbnails == settings->uints.menu_left_thumbnails)
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.gfx_thumbnails,
|
||||
settings->uints.gfx_thumbnails + 1);
|
||||
|
||||
if (settings->uints.gfx_thumbnails > 3)
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.gfx_thumbnails, 1);
|
||||
|
||||
if (!rgui->show_fs_thumbnail &&
|
||||
settings->uints.gfx_thumbnails == settings->uints.menu_left_thumbnails)
|
||||
configuration_set_uint(settings,
|
||||
settings->uints.gfx_thumbnails,
|
||||
settings->uints.gfx_thumbnails + 1);
|
||||
}
|
||||
|
||||
rgui_refresh_thumbnail_image(rgui, 0);
|
||||
}
|
||||
break;
|
||||
case MENU_ACTION_UP:
|
||||
case MENU_ACTION_DOWN:
|
||||
case MENU_ACTION_SCROLL_UP:
|
||||
case MENU_ACTION_SCROLL_DOWN:
|
||||
if (rgui->show_fs_thumbnail && rgui->is_quick_menu)
|
||||
new_action = MENU_ACTION_NOOP;
|
||||
break;
|
||||
case MENU_ACTION_LEFT:
|
||||
case MENU_ACTION_RIGHT:
|
||||
if (rgui->show_fs_thumbnail && (rgui->is_quick_menu && !rgui_is_running_quick_menu()))
|
||||
new_action = MENU_ACTION_NOOP;
|
||||
break;
|
||||
default:
|
||||
/* In all other cases, pass through input
|
||||
* menu action without intervention */
|
||||
@ -7310,14 +7711,14 @@ menu_ctx_driver_t menu_ctx_rgui = {
|
||||
"rgui",
|
||||
rgui_environ,
|
||||
NULL, /* update_thumbnail_path */
|
||||
NULL, /* update_thumbnail_image */
|
||||
rgui_update_thumbnail_image,
|
||||
rgui_refresh_thumbnail_image,
|
||||
rgui_set_thumbnail_system,
|
||||
rgui_get_thumbnail_system,
|
||||
NULL, /* set_thumbnail_content */
|
||||
rgui_osk_ptr_at_pos,
|
||||
NULL, /* update_savestate_thumbnail_path */
|
||||
NULL, /* update_savestate_thumbnail_image */
|
||||
rgui_update_savestate_thumbnail_path,
|
||||
rgui_update_savestate_thumbnail_image,
|
||||
NULL, /* pointer_down */
|
||||
rgui_pointer_up,
|
||||
rgui_menu_entry_action
|
||||
|
Loading…
x
Reference in New Issue
Block a user