Add environment callback for enabling core option menu visibility updates without toggling Quick Menu

This commit is contained in:
jdgleaver 2021-08-17 17:31:41 +01:00
parent 97b9a79fc0
commit 0e98b4ddea
9 changed files with 232 additions and 41 deletions

View file

@ -20,6 +20,10 @@
#include "cheevos/cheevos.h"
#endif
#ifdef HAVE_MENU
#include "menu/menu_driver.h"
#endif
#include "core_option_manager.h"
#define CORE_OPTION_MANAGER_MAP_TAG "#"
@ -1637,15 +1641,24 @@ bool core_option_manager_get_visible(core_option_manager_t *opt,
/**
* core_option_manager_set_val:
*
* @opt : options manager handle
* @idx : core option index
* @val_idx : index of the value to set
* @opt : options manager handle
* @idx : core option index
* @val_idx : index of the value to set
* @refresh_menu : flag specifying whether menu
* should be refreshed if changes
* to option visibility are detected
*
* Sets the core option at index @idx to the
* option value corresponding to @val_idx.
* After setting the option value, a request
* will be made for the core to update the
* in-menu visibility of all options; if
* visibility changes are detected and
* @refresh_menu is true, the menu will be
* redrawn.
**/
void core_option_manager_set_val(core_option_manager_t *opt,
size_t idx, size_t val_idx)
size_t idx, size_t val_idx, bool refresh_menu)
{
struct core_option *option = NULL;
@ -1660,22 +1673,44 @@ void core_option_manager_set_val(core_option_manager_t *opt,
#ifdef HAVE_CHEEVOS
rcheevos_validate_config_settings();
#endif
#ifdef HAVE_MENU
/* Refresh menu (if required) if core option
* visibility has changed as a result of modifying
* the current option value */
if (rarch_ctl(RARCH_CTL_CORE_OPTION_UPDATE_DISPLAY, NULL) &&
refresh_menu)
{
bool refresh = false;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
}
#endif
}
/**
* core_option_manager_adjust_val:
*
* @opt : options manager handle
* @idx : core option index
* @adjustment : offset to apply from current
* value index
* @opt : options manager handle
* @idx : core option index
* @adjustment : offset to apply from current
* value index
* @refresh_menu : flag specifying whether menu
* should be refreshed if changes
* to option visibility are detected
*
* Modifies the value of the core option at index
* @idx by incrementing the current option value index
* by @adjustment.
* Modifies the value of the core option at
* index @idx by incrementing the current option
* value index by @adjustment.
* After setting the option value, a request
* will be made for the core to update the
* in-menu visibility of all options; if
* visibility changes are detected and
* @refresh_menu is true, the menu will be
* redrawn.
**/
void core_option_manager_adjust_val(core_option_manager_t* opt,
size_t idx, int adjustment)
size_t idx, int adjustment, bool refresh_menu)
{
struct core_option* option = NULL;
@ -1690,18 +1725,41 @@ void core_option_manager_adjust_val(core_option_manager_t* opt,
#ifdef HAVE_CHEEVOS
rcheevos_validate_config_settings();
#endif
#ifdef HAVE_MENU
/* Refresh menu (if required) if core option
* visibility has changed as a result of modifying
* the current option value */
if (rarch_ctl(RARCH_CTL_CORE_OPTION_UPDATE_DISPLAY, NULL) &&
refresh_menu)
{
bool refresh = false;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
}
#endif
}
/**
* core_option_manager_set_default:
*
* @opt : options manager handle
* @idx : core option index
* @opt : options manager handle
* @idx : core option index
* @refresh_menu : flag specifying whether menu
* should be refreshed if changes
* to option visibility are detected
*
* Resets the core option at index @idx to its
* default value.
* Resets the core option at index @idx to
* its default value.
* After setting the option value, a request
* will be made for the core to update the
* in-menu visibility of all options; if
* visibility changes are detected and
* @refresh_menu is true, the menu will be
* redrawn.
**/
void core_option_manager_set_default(core_option_manager_t *opt, size_t idx)
void core_option_manager_set_default(core_option_manager_t *opt,
size_t idx, bool refresh_menu)
{
if (!opt ||
(idx >= opt->size))
@ -1713,6 +1771,19 @@ void core_option_manager_set_default(core_option_manager_t *opt, size_t idx)
#ifdef HAVE_CHEEVOS
rcheevos_validate_config_settings();
#endif
#ifdef HAVE_MENU
/* Refresh menu (if required) if core option
* visibility has changed as a result of modifying
* the current option value */
if (rarch_ctl(RARCH_CTL_CORE_OPTION_UPDATE_DISPLAY, NULL) &&
refresh_menu)
{
bool refresh = false;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
}
#endif
}
/**

View file

@ -373,41 +373,69 @@ bool core_option_manager_get_visible(core_option_manager_t *opt,
/**
* core_option_manager_set_val:
*
* @opt : options manager handle
* @idx : core option index
* @val_idx : index of the value to set
* @opt : options manager handle
* @idx : core option index
* @val_idx : index of the value to set
* @refresh_menu : flag specifying whether menu
* should be refreshed if changes
* to option visibility are detected
*
* Sets the core option at index @idx to the
* option value corresponding to @val_idx.
* After setting the option value, a request
* will be made for the core to update the
* in-menu visibility of all options; if
* visibility changes are detected and
* @refresh_menu is true, the menu will be
* redrawn.
**/
void core_option_manager_set_val(core_option_manager_t *opt,
size_t idx, size_t val_idx);
size_t idx, size_t val_idx, bool refresh_menu);
/**
* core_option_manager_adjust_val:
*
* @opt : options manager handle
* @idx : core option index
* @adjustment : offset to apply from current
* value index
* @opt : options manager handle
* @idx : core option index
* @adjustment : offset to apply from current
* value index
* @refresh_menu : flag specifying whether menu
* should be refreshed if changes
* to option visibility are detected
*
* Modifies the value of the core option at index
* @idx by incrementing the current option value index
* by @adjustment.
* Modifies the value of the core option at
* index @idx by incrementing the current option
* value index by @adjustment.
* After setting the option value, a request
* will be made for the core to update the
* in-menu visibility of all options; if
* visibility changes are detected and
* @refresh_menu is true, the menu will be
* redrawn.
**/
void core_option_manager_adjust_val(core_option_manager_t* opt,
size_t idx, int adjustment);
size_t idx, int adjustment, bool refresh_menu);
/**
* core_option_manager_set_default:
*
* @opt : options manager handle
* @idx : core option index
* @opt : options manager handle
* @idx : core option index
* @refresh_menu : flag specifying whether menu
* should be refreshed if changes
* to option visibility are detected
*
* Resets the core option at index @idx to its
* default value.
* Resets the core option at index @idx to
* its default value.
* After setting the option value, a request
* will be made for the core to update the
* in-menu visibility of all options; if
* visibility changes are detected and
* @refresh_menu is true, the menu will be
* redrawn.
**/
void core_option_manager_set_default(core_option_manager_t *opt, size_t idx);
void core_option_manager_set_default(core_option_manager_t *opt,
size_t idx, bool refresh_menu);
/**
* core_option_manager_set_visible:

View file

@ -1712,6 +1712,16 @@ enum retro_mod
* the retro_core_options_v2_intl::local struct will be ignored.
*/
#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK 69
/* const struct retro_core_options_update_display_callback * --
* Allows a frontend to signal that a core must update
* the visibility of any dynamically hidden core options,
* and enables the frontend to detect visibility changes.
* Used by the frontend to update the menu display status
* of core options without requiring a call of retro_run().
* Must be called in retro_set_environment().
*/
/* VFS functionality */
/* File paths:
@ -3551,6 +3561,25 @@ struct retro_core_options_v2_intl
struct retro_core_options_v2 *local;
};
/* Used by the frontend to monitor changes in core option
* visibility. May be called each time any core option
* value is set via the frontend.
* - On each invocation, the core must update the visibility
* of any dynamically hidden options using the
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY environment
* callback.
* - On the first invocation, returns 'true' if the visibility
* of any core option has changed since the last call of
* retro_load_game() or retro_load_game_special().
* - On each subsequent invocation, returns 'true' if the
* visibility of any core option has changed since the last
* time the function was called. */
typedef bool (RETRO_CALLCONV *retro_core_options_update_display_callback_t)(void);
struct retro_core_options_update_display_callback
{
retro_core_options_update_display_callback_t callback;
};
struct retro_game_info
{
const char *path; /* Path to game, UTF-8 encoded.

View file

@ -3826,7 +3826,7 @@ int action_ok_core_option_dropdown_list(const char *path,
/* > Update value and return */
core_option_manager_set_val(coreopts, option_index,
(option->index == 0) ? 1 : 0);
(option->index == 0) ? 1 : 0, true);
return 0;
@ -6051,7 +6051,8 @@ static int action_ok_push_dropdown_setting_core_options_item_special(
if (!coreopts)
return -1;
core_option_manager_set_val(coreopts, core_option_idx, idx);
core_option_manager_set_val(coreopts,
core_option_idx, idx, false);
return action_cancel_pop_default(NULL, NULL, 0, 0);
}
@ -6066,7 +6067,8 @@ static int action_ok_push_dropdown_setting_core_options_item(const char *path,
if (!coreopts)
return -1;
core_option_manager_set_val(coreopts, core_option_idx, idx);
core_option_manager_set_val(coreopts,
core_option_idx, idx, false);
return action_cancel_pop_default(NULL, NULL, 0, 0);
}

View file

@ -369,7 +369,7 @@ static int action_start_core_setting(
core_option_manager_t *coreopts = NULL;
if (rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts))
core_option_manager_set_default(coreopts, core_idx);
core_option_manager_set_default(coreopts, core_idx, true);
return 0;
}

View file

@ -13521,6 +13521,12 @@ static void retroarch_fastmotion_override_free(struct rarch_state *p_rarch,
retroarch_set_frame_limit(p_rarch, fastforward_ratio);
}
static void retroarch_core_options_callback_free(runloop_state_t *p_runloop)
{
/* Only a single core options callback is used at present */
p_runloop->core_options_callback.update_display = NULL;
}
static void retroarch_system_info_free(struct rarch_state *p_rarch)
{
rarch_system_info_t *sys_info = &runloop_state.system;
@ -16667,6 +16673,23 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
}
break;
case RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK:
RARCH_DBG("[Environ]: RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK.\n");
{
const struct retro_core_options_update_display_callback
*update_display_callback =
(const struct retro_core_options_update_display_callback*)data;
if (update_display_callback &&
update_display_callback->callback)
runloop_state.core_options_callback.update_display =
update_display_callback->callback;
else
runloop_state.core_options_callback.update_display = NULL;
}
break;
case RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION:
RARCH_LOG("[Environ]: GET_MESSAGE_INTERFACE_VERSION.\n");
/* Current API version is 1 */
@ -18463,6 +18486,7 @@ static void uninit_libretro_symbols(
retroarch_audio_buffer_status_free(p_rarch);
retroarch_game_focus_free(p_rarch);
retroarch_fastmotion_override_free(p_rarch, &runloop_state);
retroarch_core_options_callback_free(&runloop_state);
p_rarch->camera_driver_active = false;
p_rarch->location_driver_active = false;
@ -36257,6 +36281,23 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
*coreopts = runloop_state.core_options;
}
break;
case RARCH_CTL_CORE_OPTION_UPDATE_DISPLAY:
if (runloop_state.core_options &&
runloop_state.core_options_callback.update_display)
{
/* Note: The update_display() callback may read
* core option values via RETRO_ENVIRONMENT_GET_VARIABLE.
* This will reset the 'options updated' flag.
* We therefore have to cache the current 'options updated'
* state and restore it after the update_display() function
* returns */
bool values_updated = runloop_state.core_options->updated;
bool display_updated = runloop_state.core_options_callback.update_display();
runloop_state.core_options->updated = values_updated;
return display_updated;
}
return false;
#ifdef HAVE_CONFIGFILE
case RARCH_CTL_IS_OVERRIDES_ACTIVE:
return runloop_state.overrides_active;
@ -36325,6 +36366,7 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
retroarch_audio_buffer_status_free(p_rarch);
retroarch_game_focus_free(p_rarch);
retroarch_fastmotion_override_free(p_rarch, &runloop_state);
retroarch_core_options_callback_free(&runloop_state);
memset(&p_rarch->input_driver_analog_requested, 0,
sizeof(p_rarch->input_driver_analog_requested));
break;
@ -36360,7 +36402,8 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
unsigned *idx = (unsigned*)data;
if (!idx || !runloop_state.core_options)
return false;
core_option_manager_adjust_val(runloop_state.core_options, *idx, -1);
core_option_manager_adjust_val(runloop_state.core_options,
*idx, -1, true);
}
break;
case RARCH_CTL_CORE_OPTION_NEXT:
@ -36372,7 +36415,8 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
unsigned* idx = (unsigned*)data;
if (!idx || !runloop_state.core_options)
return false;
core_option_manager_adjust_val(runloop_state.core_options, *idx, 1);
core_option_manager_adjust_val(runloop_state.core_options,
*idx, 1, true);
}
break;

View file

@ -158,6 +158,7 @@ enum rarch_ctl_state
RARCH_CTL_CORE_OPTIONS_LIST_GET,
RARCH_CTL_CORE_OPTION_PREV,
RARCH_CTL_CORE_OPTION_NEXT,
RARCH_CTL_CORE_OPTION_UPDATE_DISPLAY,
RARCH_CTL_CORE_IS_RUNNING,
/* BSV Movie */

View file

@ -1668,6 +1668,20 @@ struct discord_state
typedef struct discord_state discord_state_t;
#endif
/* Contains all callbacks associated with
* core options.
* > At present there is only a single
* callback, 'update_display' - but we
* may wish to add more in the future
* (e.g. for directly informing a core of
* core option value changes, or getting/
* setting extended/non-standard option
* value data types) */
typedef struct core_options_callbacks
{
retro_core_options_update_display_callback_t update_display;
} core_options_callbacks_t;
struct runloop
{
retro_usec_t frame_time_last; /* int64_t alignment */
@ -1679,6 +1693,8 @@ struct runloop
size_t msg_queue_size;
core_option_manager_t *core_options;
core_options_callbacks_t core_options_callback; /* ptr alignment */
retro_keyboard_event_t key_event; /* ptr alignment */
retro_keyboard_event_t frontend_key_event; /* ptr alignment */

View file

@ -1089,7 +1089,7 @@ void CoreOptionsDialog::onCoreOptionComboBoxCurrentIndexChanged(int index)
QString str = option->vals->elems[k].data;
if (!str.isEmpty() && str == val)
core_option_manager_set_val(coreopts, i, k);
core_option_manager_set_val(coreopts, i, k, true);
}
}
}