From d46ed007a56d6ad1d6c9d687889ffc9acab1eb19 Mon Sep 17 00:00:00 2001 From: thecozies <79979276+thecozies@users.noreply.github.com> Date: Mon, 8 Sep 2025 10:32:31 -0500 Subject: [PATCH] Config updates and helpers --- librecomp/include/librecomp/config.hpp | 53 +++++++++++++++++++++----- librecomp/src/config.cpp | 47 +++++++++++++++++++---- 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/librecomp/include/librecomp/config.hpp b/librecomp/include/librecomp/config.hpp index d989b67..5b5edab 100644 --- a/librecomp/include/librecomp/config.hpp +++ b/librecomp/include/librecomp/config.hpp @@ -47,6 +47,13 @@ namespace recomp { std::vector::const_iterator find_option_from_value(uint32_t value) const; // 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; + + ConfigOptionEnum() = default; + ConfigOptionEnum(const std::vector& options, uint32_t default_value = 0) + : options(options), default_value(default_value) {} + template + ConfigOptionEnum(const std::vector& options, ENUM_TYPE default_value = 0) + : options(options), default_value(static_cast(default_value)) {} }; struct ConfigOptionNumber { @@ -56,6 +63,17 @@ namespace recomp { int precision = 0; bool percent = false; 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 { @@ -167,6 +185,7 @@ namespace recomp { bool hidden = false ); + // Allows you to add an enum option using an enum type instead of uint32_t. template void add_enum_option( const std::string &id, @@ -192,6 +211,15 @@ namespace recomp { 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( const std::string &id, const std::string &name, @@ -208,15 +236,22 @@ namespace recomp { bool hidden = false ); + const ConfigOption &get_option(size_t option_index) const; + const ConfigOption &get_option(const std::string& option_id) const; + template + const T &get_option_config(size_t option_index) const { + return std::get(get_option(option_index).variant); + }; + const ConfigValueVariant get_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 // so rendering can be updated with your new set 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 set_apply_callback(std::function callback) { - apply_callback = callback; + void set_load_callback(std::function callback) { + load_callback = callback; } void set_save_callback(std::function callback) { save_callback = callback; @@ -263,17 +298,17 @@ namespace recomp { bool save_config_json(nlohmann::json config_json) const; nlohmann::json get_json_config() const; - void revert_temp_config(); - bool is_dirty(); + + bool is_dirty() const; std::vector 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_hidden(size_t 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) const; void clear_config_option_updates() { 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) { json_parse_option_map[option_id] = callback; } @@ -296,7 +331,7 @@ namespace recomp { ConfigStorage temp_storage; std::unordered_map option_change_callbacks = {}; - std::function apply_callback = nullptr; + std::function load_callback = nullptr; std::function save_callback = nullptr; std::vector config_option_updates = {}; std::unordered_set disabled_options = {}; diff --git a/librecomp/src/config.cpp b/librecomp/src/config.cpp index 5bd85ab..7a7d852 100644 --- a/librecomp/src/config.cpp +++ b/librecomp/src/config.cpp @@ -185,6 +185,23 @@ void Config::add_number_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( const std::string &id, 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 { auto it = src.value_map.find(option_id); 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); if (enum_it != enum_options_disabled.end()) { 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); } - if (apply_callback && is_dirty()) { - apply_callback(); - } - modified_options.clear(); } @@ -501,6 +529,9 @@ bool Config::load_config(std::function validate_callback clear_config_option_updates(); loaded_config = true; + if (load_callback != nullptr) { + load_callback(); + } return true; } @@ -517,7 +548,7 @@ void Config::revert_temp_config() { derive_all_config_option_dependencies(); } -bool Config::is_dirty() { +bool Config::is_dirty() const { 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); } -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)) { return std::string(); } 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); }