Config updates and helpers

This commit is contained in:
thecozies 2025-09-08 10:32:31 -05:00
parent bf05c8d9a5
commit d46ed007a5
2 changed files with 83 additions and 17 deletions

View file

@ -47,6 +47,13 @@ namespace recomp {
std::vector<ConfigOptionEnumOption>::const_iterator find_option_from_value(uint32_t value) const; std::vector<ConfigOptionEnumOption>::const_iterator find_option_from_value(uint32_t value) const;
// Verify an option has a unique key and a unique value // Verify an option has a unique key and a unique value
bool can_add_option(const std::string& option_key, uint32_t option_value) const; bool can_add_option(const std::string& option_key, uint32_t option_value) const;
ConfigOptionEnum() = default;
ConfigOptionEnum(const std::vector<ConfigOptionEnumOption>& options, uint32_t default_value = 0)
: options(options), default_value(default_value) {}
template <typename ENUM_TYPE = uint32_t>
ConfigOptionEnum(const std::vector<ConfigOptionEnumOption>& options, ENUM_TYPE default_value = 0)
: options(options), default_value(static_cast<uint32_t>(default_value)) {}
}; };
struct ConfigOptionNumber { struct ConfigOptionNumber {
@ -56,6 +63,17 @@ namespace recomp {
int precision = 0; int precision = 0;
bool percent = false; bool percent = false;
double default_value = 0.0; double default_value = 0.0;
static ConfigOptionNumber create_percent_option(double default_value = 0.0) {
return ConfigOptionNumber{
.min = 0.0,
.max = 100.0,
.step = 1.0,
.precision = 0,
.percent = true,
.default_value = default_value
};
}
}; };
struct ConfigOptionString { struct ConfigOptionString {
@ -167,6 +185,7 @@ namespace recomp {
bool hidden = false bool hidden = false
); );
// Allows you to add an enum option using an enum type instead of uint32_t.
template <typename ENUM_TYPE> template <typename ENUM_TYPE>
void add_enum_option( void add_enum_option(
const std::string &id, const std::string &id,
@ -192,6 +211,15 @@ namespace recomp {
bool hidden = false bool hidden = false
); );
// Convenience function for adding a percent number option
void add_percent_number_option(
const std::string &id,
const std::string &name,
const std::string &description,
double default_value,
bool hidden = false
);
void add_string_option( void add_string_option(
const std::string &id, const std::string &id,
const std::string &name, const std::string &name,
@ -208,15 +236,22 @@ namespace recomp {
bool hidden = false bool hidden = false
); );
const ConfigOption &get_option(size_t option_index) const;
const ConfigOption &get_option(const std::string& option_id) const;
template <typename T = ConfigOptionVariant>
const T &get_option_config(size_t option_index) const {
return std::get<T>(get_option(option_index).variant);
};
const ConfigValueVariant get_option_value(const std::string& option_id) const; const ConfigValueVariant get_option_value(const std::string& option_id) const;
const ConfigValueVariant get_temp_option_value(const std::string& option_id) const; const ConfigValueVariant get_temp_option_value(const std::string& option_id) const;
// This should only be used internally to recompui. Other changes to values should be done through update_option_value // This should only be used internally to recompui. Other changes to values should be done through update_option_value
// so rendering can be updated with your new set value. // so rendering can be updated with your new set value.
void set_option_value(const std::string& option_id, ConfigValueVariant value); void set_option_value(const std::string& option_id, ConfigValueVariant value);
bool get_enum_option_disabled(size_t option_index, uint32_t enum_index); bool get_enum_option_disabled(size_t option_index, uint32_t enum_index) const;
void add_option_change_callback(const std::string& option_id, on_option_change_callback callback); void add_option_change_callback(const std::string& option_id, on_option_change_callback callback);
void set_apply_callback(std::function<void()> callback) { void set_load_callback(std::function<void()> callback) {
apply_callback = callback; load_callback = callback;
} }
void set_save_callback(std::function<void()> callback) { void set_save_callback(std::function<void()> callback) {
save_callback = callback; save_callback = callback;
@ -263,17 +298,17 @@ namespace recomp {
bool save_config_json(nlohmann::json config_json) const; bool save_config_json(nlohmann::json config_json) const;
nlohmann::json get_json_config() const; nlohmann::json get_json_config() const;
void revert_temp_config(); void revert_temp_config();
bool is_dirty();
bool is_dirty() const;
std::vector<ConfigOptionUpdateContext> get_config_option_updates() { return config_option_updates; } std::vector<ConfigOptionUpdateContext> get_config_option_updates() { return config_option_updates; }
bool is_config_option_disabled(size_t option_index) { return disabled_options.contains(option_index); } bool is_config_option_disabled(size_t option_index) const { return disabled_options.contains(option_index); }
bool is_config_option_hidden(size_t option_index); bool is_config_option_hidden(size_t option_index) const;
void clear_config_option_updates() { void clear_config_option_updates() {
config_option_updates.clear(); config_option_updates.clear();
} }
std::string get_enum_option_details(size_t option_index); std::string get_enum_option_details(size_t option_index) const;
void on_json_parse_option(const std::string& option_id, parse_option_func callback) { void on_json_parse_option(const std::string& option_id, parse_option_func callback) {
json_parse_option_map[option_id] = callback; json_parse_option_map[option_id] = callback;
} }
@ -296,7 +331,7 @@ namespace recomp {
ConfigStorage temp_storage; ConfigStorage temp_storage;
std::unordered_map<size_t, on_option_change_callback> option_change_callbacks = {}; std::unordered_map<size_t, on_option_change_callback> option_change_callbacks = {};
std::function<void()> apply_callback = nullptr; std::function<void()> load_callback = nullptr;
std::function<void()> save_callback = nullptr; std::function<void()> save_callback = nullptr;
std::vector<ConfigOptionUpdateContext> config_option_updates = {}; std::vector<ConfigOptionUpdateContext> config_option_updates = {};
std::unordered_set<size_t> disabled_options = {}; std::unordered_set<size_t> disabled_options = {};

View file

@ -185,6 +185,23 @@ void Config::add_number_option(
add_option(option); add_option(option);
} }
void Config::add_percent_number_option(
const std::string &id,
const std::string &name,
const std::string &description,
double default_value,
bool hidden
) {
add_option(ConfigOption{
.id = id,
.name = name,
.description = description,
.hidden = hidden,
.type = ConfigOptionType::Number,
.variant = ConfigOptionNumber::create_percent_option(default_value)
});
}
void Config::add_string_option( void Config::add_string_option(
const std::string &id, const std::string &id,
const std::string &name, const std::string &name,
@ -244,6 +261,21 @@ const ConfigValueVariant Config::get_option_default_value(const std::string& opt
} }
} }
const ConfigOption &Config::get_option(size_t option_index) const {
if (option_index >= schema.options.size()) {
throw std::out_of_range("Option index out of range: " + std::to_string(option_index));
}
return schema.options[option_index];
}
const ConfigOption &Config::get_option(const std::string& option_id) const {
auto option_by_id_it = schema.options_by_id.find(option_id);
if (option_by_id_it == schema.options_by_id.end()) {
throw std::out_of_range("Option ID not found: " + option_id);
}
return schema.options[option_by_id_it->second];
}
const ConfigValueVariant Config::get_option_value_from_storage(const std::string& option_id, const ConfigStorage& src) const { const ConfigValueVariant Config::get_option_value_from_storage(const std::string& option_id, const ConfigStorage& src) const {
auto it = src.value_map.find(option_id); auto it = src.value_map.find(option_id);
if (it != src.value_map.end()) { if (it != src.value_map.end()) {
@ -297,7 +329,7 @@ void Config::set_option_value(const std::string& option_id, ConfigValueVariant v
} }
} }
bool Config::get_enum_option_disabled(size_t option_index, uint32_t enum_index) { bool Config::get_enum_option_disabled(size_t option_index, uint32_t enum_index) const {
auto enum_it = enum_options_disabled.find(option_index); auto enum_it = enum_options_disabled.find(option_index);
if (enum_it != enum_options_disabled.end()) { if (enum_it != enum_options_disabled.end()) {
return enum_it->second.contains(enum_index); return enum_it->second.contains(enum_index);
@ -386,10 +418,6 @@ bool Config::save_config() {
try_call_option_change_callback(option.id, cur_value, prev_value, OptionChangeContext::Permanent); try_call_option_change_callback(option.id, cur_value, prev_value, OptionChangeContext::Permanent);
} }
if (apply_callback && is_dirty()) {
apply_callback();
}
modified_options.clear(); modified_options.clear();
} }
@ -501,6 +529,9 @@ bool Config::load_config(std::function<bool(nlohmann::json &)> validate_callback
clear_config_option_updates(); clear_config_option_updates();
loaded_config = true; loaded_config = true;
if (load_callback != nullptr) {
load_callback();
}
return true; return true;
} }
@ -517,7 +548,7 @@ void Config::revert_temp_config() {
derive_all_config_option_dependencies(); derive_all_config_option_dependencies();
} }
bool Config::is_dirty() { bool Config::is_dirty() const {
return !modified_options.empty(); return !modified_options.empty();
} }
@ -627,14 +658,14 @@ void Config::add_option_hidden_dependency(const std::string& dependent_option_id
schema.hidden_dependencies.add_option_dependency(dependent_index, source_index, values); schema.hidden_dependencies.add_option_dependency(dependent_index, source_index, values);
} }
std::string Config::get_enum_option_details(size_t option_index) { std::string Config::get_enum_option_details(size_t option_index) const {
if (!enum_option_details.contains(option_index)) { if (!enum_option_details.contains(option_index)) {
return std::string(); return std::string();
} }
return enum_option_details[option_index]; return enum_option_details[option_index];
} }
bool Config::is_config_option_hidden(size_t option_index) { bool Config::is_config_option_hidden(size_t option_index) const {
return schema.options[option_index].hidden || hidden_options.contains(option_index); return schema.options[option_index].hidden || hidden_options.contains(option_index);
} }