mirror of
https://github.com/libretro/RetroArch
synced 2025-02-07 21:39:54 +00:00
Merge pull request #11072 from jdgleaver/core-options-tweaks
Core option improvements
This commit is contained in:
commit
80f978b683
@ -1325,28 +1325,18 @@ static void menu_action_setting_disp_set_label_core_options(
|
||||
char *s2, size_t len2)
|
||||
{
|
||||
core_option_manager_t *coreopts = NULL;
|
||||
const char *core_opt = NULL;
|
||||
const char *coreopt_label = NULL;
|
||||
|
||||
*s = '\0';
|
||||
*w = 19;
|
||||
|
||||
if (rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts))
|
||||
{
|
||||
core_opt = core_option_manager_get_val_label(coreopts,
|
||||
coreopt_label = core_option_manager_get_val_label(coreopts,
|
||||
type - MENU_SETTINGS_CORE_OPTION_START);
|
||||
|
||||
strlcpy(s, "", len);
|
||||
|
||||
if (core_opt)
|
||||
{
|
||||
if (string_is_equal(core_opt,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ENABLED)))
|
||||
core_opt = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON);
|
||||
else if (string_is_equal(core_opt,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_DISABLED)))
|
||||
core_opt = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF);
|
||||
strlcpy(s, core_opt, len);
|
||||
}
|
||||
if (!string_is_empty(coreopt_label))
|
||||
strlcpy(s, coreopt_label, len);
|
||||
}
|
||||
|
||||
strlcpy(s2, path, len2);
|
||||
|
@ -3440,17 +3440,77 @@ static int action_ok_audio_run(const char *path,
|
||||
int action_ok_core_option_dropdown_list(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
char core_option_lbl[256];
|
||||
char core_option_idx[256];
|
||||
snprintf(core_option_lbl, sizeof(core_option_lbl),
|
||||
"core_option_%d", (int)idx);
|
||||
snprintf(core_option_idx, sizeof(core_option_idx), "%d",
|
||||
type);
|
||||
core_option_manager_t *coreopts = NULL;
|
||||
struct core_option *option = NULL;
|
||||
const char *value_label_0 = NULL;
|
||||
const char *value_label_1 = NULL;
|
||||
size_t option_index;
|
||||
char option_path_str[256];
|
||||
char option_lbl_str[256];
|
||||
|
||||
option_path_str[0] = '\0';
|
||||
option_lbl_str[0] = '\0';
|
||||
|
||||
/* Boolean options are toggled directly,
|
||||
* without the use of a drop-down list */
|
||||
|
||||
/* > Get current option index */
|
||||
if (type < MENU_SETTINGS_CORE_OPTION_START)
|
||||
goto push_dropdown_list;
|
||||
|
||||
option_index = type - MENU_SETTINGS_CORE_OPTION_START;
|
||||
|
||||
/* > Get core options struct */
|
||||
if (!rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts) ||
|
||||
(option_index >= coreopts->size))
|
||||
goto push_dropdown_list;
|
||||
|
||||
/* > Get current option, and check whether
|
||||
* it has exactly 2 values (i.e. on/off) */
|
||||
option = (struct core_option*)&coreopts->opts[option_index];
|
||||
|
||||
if (!option ||
|
||||
(option->vals->size != 2) ||
|
||||
((option->index != 0) &&
|
||||
(option->index != 1)))
|
||||
goto push_dropdown_list;
|
||||
|
||||
/* > Check whether option values correspond
|
||||
* to a boolean toggle */
|
||||
value_label_0 = option->val_labels->elems[0].data;
|
||||
value_label_1 = option->val_labels->elems[1].data;
|
||||
|
||||
if (string_is_empty(value_label_0) ||
|
||||
string_is_empty(value_label_1) ||
|
||||
!((string_is_equal(value_label_0, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON)) &&
|
||||
string_is_equal(value_label_1, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF))) ||
|
||||
(string_is_equal(value_label_0, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) &&
|
||||
string_is_equal(value_label_1, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON)))))
|
||||
goto push_dropdown_list;
|
||||
|
||||
/* > Update value and return */
|
||||
core_option_manager_set_val(coreopts, option_index,
|
||||
(option->index == 0) ? 1 : 0);
|
||||
|
||||
return 0;
|
||||
|
||||
push_dropdown_list:
|
||||
|
||||
/* If this option is not a boolean toggle,
|
||||
* push drop-down list */
|
||||
snprintf(option_path_str, sizeof(option_path_str),
|
||||
"core_option_%d", (int)idx);
|
||||
snprintf(option_lbl_str, sizeof(option_lbl_str),
|
||||
"%d", type);
|
||||
|
||||
/* TODO/FIXME: This should be refactored to make
|
||||
* use of a core-option-specific drop-down list,
|
||||
* rather than hijacking the generic one... */
|
||||
generic_action_ok_displaylist_push(
|
||||
core_option_lbl, NULL,
|
||||
core_option_idx, 0, idx, 0,
|
||||
option_path_str, NULL,
|
||||
option_lbl_str, 0, idx, 0,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -10531,25 +10531,21 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
|
||||
* toggles the Quick Menu off and on again (returning
|
||||
* to the Core Options menu) the menu must be refreshed
|
||||
* (or undefined behaviour occurs).
|
||||
* We therefore have to cache the last set menu size,
|
||||
* and compare this with the new size after processing
|
||||
* the current core_option_manager_t struct.
|
||||
* Note: It would be 'nicer' to only refresh the menu
|
||||
* if the selection marker is at an index higher than
|
||||
* the new size, but we don't really have access that
|
||||
* information at this stage (i.e. the selection can
|
||||
* change after this function is called) */
|
||||
static size_t prev_count = 0;
|
||||
* To prevent the menu selection from going out of bounds,
|
||||
* we therefore have to check that the current selection
|
||||
* index is less than the current number of menu entries
|
||||
* - if not, we reset the navigation pointer */
|
||||
size_t selection = menu_navigation_get_selection();
|
||||
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
|
||||
|
||||
if (rarch_ctl(RARCH_CTL_HAS_CORE_OPTIONS, NULL))
|
||||
{
|
||||
size_t opts = 0;
|
||||
size_t num_opts = 0;
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool game_specific_options = settings->bools.game_specific_options;
|
||||
|
||||
rarch_ctl(RARCH_CTL_GET_CORE_OPTION_SIZE, &opts);
|
||||
rarch_ctl(RARCH_CTL_GET_CORE_OPTION_SIZE, &num_opts);
|
||||
|
||||
if (game_specific_options)
|
||||
{
|
||||
@ -10575,20 +10571,19 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
|
||||
count++;
|
||||
}
|
||||
|
||||
if (opts != 0)
|
||||
if (num_opts != 0)
|
||||
{
|
||||
core_option_manager_t *coreopts = NULL;
|
||||
|
||||
rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts);
|
||||
|
||||
for (i = 0; i < opts; i++)
|
||||
if (rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts))
|
||||
{
|
||||
for (i = 0; i < num_opts; i++)
|
||||
{
|
||||
if (core_option_manager_get_visible(coreopts, i))
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
if (menu_entries_append_enum(info->list,
|
||||
core_option_manager_get_desc(coreopts, i), "",
|
||||
MENU_ENUM_LABEL_CORE_OPTION_ENTRY,
|
||||
(unsigned)(MENU_SETTINGS_CORE_OPTION_START + i), 0, 0);
|
||||
(unsigned)(MENU_SETTINGS_CORE_OPTION_START + i), 0, 0))
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@ -10602,11 +10597,10 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
|
||||
MENU_ENUM_LABEL_NO_CORE_OPTIONS_AVAILABLE,
|
||||
MENU_SETTINGS_CORE_OPTION_NONE, 0, 0);
|
||||
|
||||
if (count != prev_count)
|
||||
if (selection >= count)
|
||||
{
|
||||
info->need_refresh = true;
|
||||
info->need_navigation_clear = true;
|
||||
prev_count = count;
|
||||
}
|
||||
info->need_push = true;
|
||||
}
|
||||
|
105
retroarch.c
105
retroarch.c
@ -17354,11 +17354,64 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
/* CORE OPTIONS */
|
||||
static const char *core_option_manager_parse_value_label(
|
||||
const char *value, const char *value_label)
|
||||
{
|
||||
/* 'value_label' may be NULL */
|
||||
const char *label = string_is_empty(value_label) ?
|
||||
value : value_label;
|
||||
|
||||
if (string_is_empty(label))
|
||||
return NULL;
|
||||
|
||||
/* Any label starting with a digit (or +/-)
|
||||
* cannot be a boolean string, and requires
|
||||
* no further processing */
|
||||
if (isdigit((unsigned char)*label) ||
|
||||
(*label == '+') ||
|
||||
(*label == '-'))
|
||||
return label;
|
||||
|
||||
/* Core devs have a habit of using arbitrary
|
||||
* strings to label boolean values (i.e. enabled,
|
||||
* Enabled, on, On, ON, true, True, TRUE, disabled,
|
||||
* Disabled, off, Off, OFF, false, False, FALSE).
|
||||
* These should all be converted to standard ON/OFF
|
||||
* strings
|
||||
* > Note: We require some duplication here
|
||||
* (e.g. MENU_ENUM_LABEL_ENABLED *and*
|
||||
* MENU_ENUM_LABEL_VALUE_ENABLED) in order
|
||||
* to match both localised and non-localised
|
||||
* strings. This function is not performance
|
||||
* critical, so these extra comparisons do
|
||||
* no harm */
|
||||
if (string_is_equal_noncase(label, msg_hash_to_str(MENU_ENUM_LABEL_ENABLED)) ||
|
||||
string_is_equal_noncase(label, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ENABLED)) ||
|
||||
string_is_equal_noncase(label, "enable") ||
|
||||
string_is_equal_noncase(label, "on") ||
|
||||
string_is_equal_noncase(label, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON)) ||
|
||||
string_is_equal_noncase(label, "true") ||
|
||||
string_is_equal_noncase(label, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_TRUE)))
|
||||
label = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ON);
|
||||
else if (string_is_equal_noncase(label, msg_hash_to_str(MENU_ENUM_LABEL_DISABLED)) ||
|
||||
string_is_equal_noncase(label, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISABLED)) ||
|
||||
string_is_equal_noncase(label, "disable") ||
|
||||
string_is_equal_noncase(label, "off") ||
|
||||
string_is_equal_noncase(label, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF)) ||
|
||||
string_is_equal_noncase(label, "false") ||
|
||||
string_is_equal_noncase(label, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FALSE)))
|
||||
label = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OFF);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
static bool core_option_manager_parse_variable(
|
||||
core_option_manager_t *opt, size_t idx,
|
||||
const struct retro_variable *var,
|
||||
config_file_t *config_src)
|
||||
{
|
||||
size_t i;
|
||||
union string_list_elem_attr attr;
|
||||
const char *val_start = NULL;
|
||||
char *value = NULL;
|
||||
char *desc_end = NULL;
|
||||
@ -17391,13 +17444,30 @@ static bool core_option_manager_parse_variable(
|
||||
if (!option->vals)
|
||||
goto error;
|
||||
|
||||
/* Legacy core option interface has no concept of
|
||||
* value labels - use actual values for display purposes */
|
||||
option->val_labels = string_list_clone(option->vals);
|
||||
/* Legacy core option interface has no concept
|
||||
* of value labels
|
||||
* > Use actual values for display purposes */
|
||||
attr.i = 0;
|
||||
option->val_labels = string_list_new();
|
||||
|
||||
if (!option->val_labels)
|
||||
goto error;
|
||||
|
||||
/* > Loop over values and 'extract' labels */
|
||||
for (i = 0; i < option->vals->size; i++)
|
||||
{
|
||||
const char *value = option->vals->elems[i].data;
|
||||
const char *value_label = core_option_manager_parse_value_label(
|
||||
value, NULL);
|
||||
|
||||
/* Redundant safely check... */
|
||||
value_label = string_is_empty(value_label) ?
|
||||
value : value_label;
|
||||
|
||||
/* Append value label string */
|
||||
string_list_append(option->val_labels, value_label, attr);
|
||||
}
|
||||
|
||||
/* Legacy core option interface always uses first
|
||||
* defined value as the default */
|
||||
option->default_index = 0;
|
||||
@ -17411,8 +17481,6 @@ static bool core_option_manager_parse_variable(
|
||||
/* Set current config value */
|
||||
if (entry && !string_is_empty(entry->value))
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < option->vals->size; i++)
|
||||
{
|
||||
if (string_is_equal(option->vals->elems[i].data, entry->value))
|
||||
@ -17475,26 +17543,35 @@ static bool core_option_manager_parse_option(
|
||||
if (!option->vals || !option->val_labels)
|
||||
return false;
|
||||
|
||||
/* Initialse default value */
|
||||
/* Initialise default value */
|
||||
option->default_index = 0;
|
||||
option->index = 0;
|
||||
|
||||
/* Extract value/label pairs */
|
||||
for (i = 0; i < num_vals; i++)
|
||||
{
|
||||
/* We know that 'value' is valid */
|
||||
string_list_append(option->vals, values[i].value, attr);
|
||||
const char *value = values[i].value;
|
||||
const char *value_label = values[i].label;
|
||||
|
||||
/* Value 'label' may be NULL */
|
||||
if (!string_is_empty(values[i].label))
|
||||
string_list_append(option->val_labels, values[i].label, attr);
|
||||
else
|
||||
string_list_append(option->val_labels, values[i].value, attr);
|
||||
/* Append value string
|
||||
* > We know that 'value' is always valid */
|
||||
string_list_append(option->vals, value, attr);
|
||||
|
||||
/* Value label requires additional processing */
|
||||
value_label = core_option_manager_parse_value_label(
|
||||
value, value_label);
|
||||
|
||||
/* > Redundant safely check... */
|
||||
value_label = string_is_empty(value_label) ?
|
||||
value : value_label;
|
||||
|
||||
/* Append value label string */
|
||||
string_list_append(option->val_labels, value_label, attr);
|
||||
|
||||
/* Check whether this value is the default setting */
|
||||
if (!string_is_empty(option_def->default_value))
|
||||
{
|
||||
if (string_is_equal(option_def->default_value, values[i].value))
|
||||
if (string_is_equal(option_def->default_value, value))
|
||||
{
|
||||
option->default_index = i;
|
||||
option->index = i;
|
||||
|
Loading…
x
Reference in New Issue
Block a user