18#include <unordered_map>
22namespace toast::settings {
49using Value = std::variant<bool, int64_t, double, std::string>;
73 Type type = Type::boolean;
78 std::vector<std::function<void(
const Value&)>> on_change;
97 auto declareBool(std::string_view key,
bool default_value,
Meta meta = {}) ->
Entry*;
98 auto declareInt(std::string_view key, int64_t default_value,
Meta meta = {}) ->
Entry*;
99 auto declareFloat(std::string_view key,
double default_value,
Meta meta = {}) ->
Entry*;
100 auto declareString(std::string_view key, std::string default_value,
Meta meta = {}) ->
Entry*;
104 auto find(std::string_view key) ->
Entry*;
111 auto entries() -> std::vector<Entry*>;
115 auto value(std::string_view key) -> std::optional<Value>;
125 auto setValue(std::string_view key,
const Value&
value) -> bool;
128 auto reset(std::string_view key) -> bool;
134 void setPaths(std::filesystem::path project_file, std::filesystem::path user_file);
143 auto activeLayer()
const ->
Layer {
144 return m_active_layer;
150 return m_active_layer == Layer::project ? m_project_path : m_user_path;
167 auto dirty() const ->
bool {
172 auto saveIfDirty() -> bool;
175 auto declare(std::string_view key, Type type, Value default_value, Meta meta) -> Entry*;
176 void resolveEntry(Entry& entry);
177 auto loadFile(
const std::filesystem::path& path, Layer layer) -> bool;
180 struct TransparentHash {
181 using is_transparent = void;
183 auto operator()(std::string_view key)
const ->
size_t {
return std::hash<std::string_view> {}(key); }
186 std::recursive_mutex m_mutex;
187 std::deque<Entry> m_entries;
188 std::unordered_map<std::string, Entry*, TransparentHash, std::equal_to<>> m_by_key;
195 std::array<std::unordered_map<std::string, Value>, k_layer_count> m_pending;
197 std::filesystem::path m_project_path;
198 std::filesystem::path m_user_path;
199 Layer m_active_layer = Layer::user;
200 bool m_dirty =
false;
214 explicit Setting(
Entry* entry) : m_entry(entry) { }
217 auto valid()
const ->
bool {
218 return m_entry !=
nullptr;
222 auto value()
const -> T {
223 if (m_entry ==
nullptr) {
228 const Value resolved = Settings::get().resolved(m_entry);
229 if (
const auto* typed = std::get_if<T>(&resolved)) {
240 if (m_entry !=
nullptr) {
241 Settings::get().setValue(m_entry->key, Value {std::move(v)});
250 if (m_entry ==
nullptr) {
253 auto wrapper = [callback = std::move(callback)](
const Value& v) {
254 if (
const auto* typed = std::get_if<T>(&v)) {
258 wrapper(Value {value()});
259 m_entry->on_change.emplace_back(std::move(wrapper));
263 auto entry() const ->
Entry* {
268 Entry* m_entry =
nullptr;
272inline auto declareBool(std::string_view key,
bool default_value,
Meta meta = {}) -> Setting<bool> {
273 return Setting<bool> {Settings::get().declareBool(key, default_value, std::move(meta))};
276inline auto declareInt(std::string_view key, int64_t default_value,
Meta meta = {}) ->
Setting<int64_t> {
277 return Setting<int64_t> {Settings::get().declareInt(key, default_value, std::move(meta))};
280inline auto declareFloat(std::string_view key,
double default_value,
Meta meta = {}) ->
Setting<double> {
281 return Setting<double> {Settings::get().declareFloat(key, default_value, std::move(meta))};
285 return Setting<std::string> {Settings::get().declareString(key, std::move(default_value), std::move(meta))};
Typed handle to a declared setting.
Definition settings.hpp:210
void onChange(std::function< void(T)> callback)
Runs callback whenever this setting changes, and once immediately with the current value.
Definition settings.hpp:249
The engine-wide settings registry.
Definition settings.hpp:93
void setPaths(std::filesystem::path project_file, std::filesystem::path user_file)
Points the two writable layers at their files; neither has to exist yet.
Definition settings.cpp:340
auto reset(std::string_view key) -> bool
Drops key's override in the active layer, exposing whatever is underneath.
Definition settings.cpp:294
auto find(std::string_view key) -> Entry *
Definition settings.cpp:221
auto entries() -> std::vector< Entry * >
Every declared setting, in declaration order.
Definition settings.cpp:227
void setActiveLayer(Layer layer)
Which layer setValue() writes to.
Definition settings.cpp:346
auto resolved(const Entry *entry) -> Value
Definition settings.cpp:246
auto activeFilePath() const -> const std::filesystem::path &
Definition settings.hpp:149
auto setValue(std::string_view key, const Value &value) -> bool
Writes value into the active layer and fires the setting's change callbacks.
Definition settings.cpp:254
void resetAll()
reset() for every declared setting
Definition settings.cpp:326
auto value(std::string_view key) -> std::optional< Value >
Definition settings.cpp:237
Type
Storage type of a setting; the editor picks its widget from this.
Definition settings.hpp:25
auto declareBool(std::string_view key, bool default_value, Meta meta={}) -> Setting< bool >
declare* wrappers returning a typed handle, which is what call sites actually want
Definition settings.hpp:272
Layer
Where a value comes from, lowest priority first.
Definition settings.hpp:41
constexpr size_t k_layer_count
Writable layers; code lives in Entry::default_value.
Definition settings.hpp:47
One registered setting. Held by the registry; Setting<T> is a handle to it.
Definition settings.hpp:71
std::array< std::optional< Value >, k_layer_count > overrides
Indexed by Layer minus one.
Definition settings.hpp:76