fix setting value changes not being broadcast

This commit is contained in:
HJfod 2023-02-24 21:30:36 +02:00
parent 93bf3e7121
commit 7089194be9
6 changed files with 130 additions and 22 deletions

View file

@ -102,7 +102,34 @@ namespace geode {
bool hasSetting(std::string const& key) const;
std::optional<Setting> getSettingDefinition(std::string const& key) const;
SettingValue* getSetting(std::string const& key) const;
/**
* Register a custom setting's value class. See Mod::addCustomSetting
* for a convenience wrapper that creates the value in-place to avoid
* code duplication. Also see
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for
* more information about custom settings
* @param key The setting's key
* @param value The SettingValue class that shall handle this setting
* @see addCustomSetting
*/
void registerCustomSetting(std::string const& key, std::unique_ptr<SettingValue> value);
/**
* Register a custom setting's value class. The new SettingValue class
* will be created in-place using `std::make_unique`. See
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for
* more information about custom settings
* @param key The setting's key
* @param value The value of the custom setting
* @example
* $on_mod(Loaded) {
* Mod::get()->addCustomSetting<MySettingValue>("setting-key", DEFAULT_VALUE);
* }
*/
template <class T, class V>
void addCustomSetting(std::string const& key, V const& value) {
this->registerCustomSetting(key, std::make_unique<T>(key, this->getID(), value));
}
json::Value& getSaveContainer();

View file

@ -18,6 +18,9 @@ namespace geode {
struct JsonMaybeObject;
struct JsonMaybeValue;
/**
* A Setting for a boolean value. Represented in-game as a simple toggle
*/
struct GEODE_DLL BoolSetting final {
using ValueType = bool;
@ -28,6 +31,10 @@ namespace geode {
static Result<BoolSetting> parse(JsonMaybeObject& obj);
};
/**
* A Setting for an integer value. The value can be limited using the min
* and max options
*/
struct GEODE_DLL IntSetting final {
using ValueType = int64_t;
@ -49,6 +56,10 @@ namespace geode {
static Result<IntSetting> parse(JsonMaybeObject& obj);
};
/**
* A Setting for a float value. The value can be limited using the min
* and max options
*/
struct GEODE_DLL FloatSetting final {
using ValueType = double;
@ -70,17 +81,27 @@ namespace geode {
static Result<FloatSetting> parse(JsonMaybeObject& obj);
};
/**
* A Setting for a string value
*/
struct GEODE_DLL StringSetting final {
using ValueType = std::string;
std::optional<std::string> name;
std::optional<std::string> description;
ValueType defaultValue;
/**
* A regex the string must succesfully match against
*/
std::optional<std::string> match;
static Result<StringSetting> parse(JsonMaybeObject& obj);
};
/**
* A Setting for a file input. Lets the user select a file from their
* local device
*/
struct GEODE_DLL FileSetting final {
using ValueType = ghc::filesystem::path;
using Filter = utils::file::FilePickOptions::Filter;
@ -95,6 +116,10 @@ namespace geode {
static Result<FileSetting> parse(JsonMaybeObject& obj);
};
/**
* A Setting for an RGB color. See ColorAlphaSetting for a setting that
* also allows customizing alpha
*/
struct GEODE_DLL ColorSetting final {
using ValueType = cocos2d::ccColor3B;
@ -105,6 +130,10 @@ namespace geode {
static Result<ColorSetting> parse(JsonMaybeObject& obj);
};
/**
* A Setting for an RGBA color. See ColorSetting for a setting that doesn't
* have alpha
*/
struct GEODE_DLL ColorAlphaSetting final {
using ValueType = cocos2d::ccColor4B;
@ -115,6 +144,11 @@ namespace geode {
static Result<ColorAlphaSetting> parse(JsonMaybeObject& obj);
};
/**
* A custom setting, defined by the mod. See
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for more
* information about how to create custom settings
*/
struct GEODE_DLL CustomSetting final {
std::shared_ptr<ModJson> json;
};
@ -130,9 +164,19 @@ namespace geode {
CustomSetting
>;
/**
* Represents a saved value for a mod that can be customized by the user
* through an in-game UI. This class is for modeling the setting's
* definition - what values are accepted, its name etc.
* See [the tutorial page](https://docs.geode-sdk.org/mods/settings)
* for more information about how settings work
* @see SettingValue
* @see SettingNode
*/
struct GEODE_DLL Setting final {
private:
std::string m_key;
std::string m_modID;
SettingKind m_kind;
Setting() = default;
@ -140,9 +184,14 @@ namespace geode {
public:
static Result<Setting> parse(
std::string const& key,
std::string const& mod,
JsonMaybeValue& obj
);
Setting(std::string const& key, SettingKind const& kind);
Setting(
std::string const& key,
std::string const& mod,
SettingKind const& kind
);
template<class T>
std::optional<T> get() {
@ -156,13 +205,22 @@ namespace geode {
bool isCustom() const;
std::string getDisplayName() const;
std::optional<std::string> getDescription() const;
std::string getModID() const;
};
/**
* Stores the actual, current value of a Setting. See
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for more
* information, and how to create custom settings
*/
class GEODE_DLL SettingValue {
protected:
std::string m_key;
std::string m_modID;
SettingValue(std::string const& key);
SettingValue(std::string const& key, std::string const& mod);
void valueChanged();
public:
virtual ~SettingValue() = default;
@ -171,6 +229,7 @@ namespace geode {
virtual SettingNode* createNode(float width) = 0;
std::string getKey() const;
std::string getModID() const;
};
template<class T>
@ -187,8 +246,8 @@ namespace geode {
GEODE_DLL Valid toValid(ValueType const& value) const;
public:
GeodeSettingValue(std::string const& key, T const& definition)
: SettingValue(key),
GeodeSettingValue(std::string const& key, std::string const& modID, T const& definition)
: SettingValue(key, modID),
m_definition(definition),
m_value(definition.defaultValue) {}
@ -200,7 +259,7 @@ namespace geode {
return m_definition;
}
Setting getDefinition() const {
return Setting(m_key, m_definition);
return Setting(m_key, m_modID, m_definition);
}
ValueType getValue() const {

View file

@ -113,7 +113,7 @@ Result<ModInfo> ModInfo::Impl::createFromSchemaV010(ModJson const& rawJson) {
}
for (auto& [key, value] : root.has("settings").items()) {
GEODE_UNWRAP_INTO(auto sett, Setting::parse(key, value));
GEODE_UNWRAP_INTO(auto sett, Setting::parse(key, impl->m_id, value));
impl->m_settings.push_back({key, sett});
}

View file

@ -1,5 +1,6 @@
#include "../ui/internal/settings/GeodeSettingNode.hpp"
#include <Geode/loader/Mod.hpp>
#include <Geode/loader/Setting.hpp>
#include <Geode/loader/SettingEvent.hpp>
#include <Geode/loader/SettingNode.hpp>
@ -101,10 +102,12 @@ Result<ColorAlphaSetting> ColorAlphaSetting::parse(JsonMaybeObject& obj) {
Result<Setting> Setting::parse(
std::string const& key,
std::string const& mod,
JsonMaybeValue& value
) {
auto sett = Setting();
sett.m_key = key;
sett.m_modID = mod;
if (auto obj = value.obj()) {
std::string type;
obj.needs("type").into(type);
@ -156,31 +159,34 @@ Result<Setting> Setting::parse(
return Ok(sett);
}
Setting::Setting(std::string const& key, SettingKind const& kind)
: m_key(key), m_kind(kind) {}
Setting::Setting(
std::string const& key,
std::string const& mod,
SettingKind const& kind
) : m_key(key), m_modID(mod), m_kind(kind) {}
std::unique_ptr<SettingValue> Setting::createDefaultValue() const {
return std::visit(makeVisitor {
[&](BoolSetting const& sett) -> std::unique_ptr<SettingValue> {
return std::make_unique<BoolSettingValue>(m_key, sett);
return std::make_unique<BoolSettingValue>(m_key, m_modID, sett);
},
[&](IntSetting const& sett) -> std::unique_ptr<SettingValue> {
return std::make_unique<IntSettingValue>(m_key, sett);
return std::make_unique<IntSettingValue>(m_key, m_modID, sett);
},
[&](FloatSetting const& sett) -> std::unique_ptr<SettingValue> {
return std::make_unique<FloatSettingValue>(m_key, sett);
return std::make_unique<FloatSettingValue>(m_key, m_modID, sett);
},
[&](StringSetting const& sett) -> std::unique_ptr<SettingValue> {
return std::make_unique<StringSettingValue>(m_key, sett);
return std::make_unique<StringSettingValue>(m_key, m_modID, sett);
},
[&](FileSetting const& sett) -> std::unique_ptr<SettingValue> {
return std::make_unique<FileSettingValue>(m_key, sett);
return std::make_unique<FileSettingValue>(m_key, m_modID, sett);
},
[&](ColorSetting const& sett) -> std::unique_ptr<SettingValue> {
return std::make_unique<ColorSettingValue>(m_key, sett);
return std::make_unique<ColorSettingValue>(m_key, m_modID, sett);
},
[&](ColorAlphaSetting const& sett) -> std::unique_ptr<SettingValue> {
return std::make_unique<ColorAlphaSettingValue>(m_key, sett);
return std::make_unique<ColorAlphaSettingValue>(m_key, m_modID, sett);
},
[&](auto const& sett) -> std::unique_ptr<SettingValue> {
return nullptr;
@ -214,14 +220,31 @@ std::optional<std::string> Setting::getDescription() const {
}, m_kind);
}
std::string Setting::getModID() const {
return m_modID;
}
// SettingValue
SettingValue::SettingValue(std::string const& key) : m_key(key) {}
SettingValue::SettingValue(std::string const& key, std::string const& mod)
: m_key(key), m_modID(mod) {}
std::string SettingValue::getKey() const {
return m_key;
}
std::string SettingValue::getModID() const {
return m_modID;
}
void SettingValue::valueChanged() {
// this is actually p neat because now if the mod gets disabled this wont
// post the event so that side-effect is automatically handled :3
if (auto mod = Loader::get()->getLoadedMod(m_modID)) {
SettingChangedEvent(mod, this).post();
}
}
// GeodeSettingValue & SettingValueSetter specializations
#define IMPL_NODE_AND_SETTERS(type_) \
@ -236,6 +259,7 @@ std::string SettingValue::getKey() const {
type_##Setting \
>::setValue(ValueType const& value) { \
m_value = this->toValid(value).first; \
this->valueChanged(); \
} \
template<> \
Result<> GeodeSettingValue< \

View file

@ -107,6 +107,7 @@ BOOL WINAPI DllMain(HINSTANCE lib, DWORD reason, LPVOID) {
return TRUE;
}
#endif
$execute {
listenForSettingChanges("show-platform-console", +[](bool value) {
if (value) {

View file

@ -23,8 +23,8 @@ protected:
Icon m_icon;
public:
MySettingValue(std::string const& key, Icon icon)
: SettingValue(key), m_icon(icon) {}
MySettingValue(std::string const& key, std::string const& modID, Icon icon)
: SettingValue(key, modID), m_icon(icon) {}
bool load(json::Value const& json) override {
try {
@ -151,10 +151,7 @@ struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
};
$on_mod(Loaded) {
Mod::get()->registerCustomSetting(
"overcast-skies",
std::make_unique<MySettingValue>("overcast-skies", DEFAULT_ICON)
);
Mod::get()->addCustomSetting<MySettingValue>("overcast-skies", DEFAULT_ICON);
// Dispatcher::get()->addFunction<void(GJGarageLayer*)>("test-garage-open", [](GJGarageLayer*
// gl) { auto label = CCLabelBMFont::create("Dispatcher works!", "bigFont.fnt");