#pragma once #include "thirdparty/toml.hpp" #include "log.hpp" #include #include #include #include #include #define OPTIONS (*Looper::Options::options) namespace Looper::Options { extern toml::table *options; void save_options(); void load_options(); extern std::optional options_path_override; std::string get_options_path(); inline bool option_set(std::string name) { toml::path path(name); auto *tmp = options; std::vector components; for (auto component : path) { components.push_back((std::string)component); } std::string last_component = components[components.size() - 1]; components.pop_back(); for (auto component : components) { auto &cur_tmp = *tmp; if (cur_tmp.contains(component)) { if (!cur_tmp[component].is_table()) { return false; } else { tmp = cur_tmp[component].as_table(); } } else { return false; } } if (tmp->contains(last_component)) { return true; } else { return false; } } inline void delete_option(std::string name) { toml::path path(name); auto *tmp = &OPTIONS; std::vector components; for (auto component : path) { std::string component_str = (std::string)component; components.push_back(component_str); } while (!path.empty()) { if (option_set(path.str())) { toml::path parent_path = path.parent(); auto &parent = OPTIONS.at(parent_path.str()); auto last_component = path[path.size() - 1]; if (parent.is_table()) { auto &table = *parent.as_table(); table.erase((std::string)last_component); if (!table.empty()) { return; } } else if (parent.is_array()) { auto &array = *parent.as_array(); array.erase(array.begin() + last_component.index()); if (!array.empty()) { return; } } path = parent_path; } else { break; } } save_options(); } template void set_option(std::string name, T value) { toml::path path(name); auto *tmp = &OPTIONS; std::vector components; for (auto component : path) { std::string component_str = (std::string)component; components.push_back(component_str); } auto last_component = components[components.size() - 1]; components.pop_back(); for (auto component : components) { auto &cur_tmp = *tmp; if (cur_tmp.contains(component)) { if (cur_tmp[component].is_table()) { tmp = cur_tmp[component].as_table(); } else { return; } } else { tmp->insert_or_assign(component, toml::table()); tmp = cur_tmp[component].as_table(); } } tmp->insert_or_assign(last_component, value); save_options(); } template inline void init_option(std::string name, T value) { if (!option_set(name)) { set_option(name, value); } } template T get_option(std::string name, std::optional initial_value = {}) { if (initial_value.has_value()) { init_option(name, initial_value.value()); } auto option = OPTIONS.at_path(name); return (**(option).as()); } template<> inline bool get_option(std::string name, std::optional initial_value) { if (initial_value.has_value()) { init_option(name, initial_value.value()); } auto option = OPTIONS.at_path(name).as(); if (option == nullptr) { return false; } return (option->get()); } } #define UI_BACKEND() (Looper::Options::get_option("ui.frontend", "imgui"))