make SettingValueNodeV3 keep track of the current value + some docs
Some checks are pending
Build Binaries / Build Windows (push) Waiting to run
Build Binaries / Build macOS (push) Waiting to run
Build Binaries / Build Android (64-bit) (push) Waiting to run
Build Binaries / Build Android (32-bit) (push) Waiting to run
Build Binaries / Publish (push) Blocked by required conditions

This commit is contained in:
HJfod 2024-09-08 12:07:10 +03:00
parent 474d85d6fe
commit f1715cda28
5 changed files with 78 additions and 102 deletions

View file

@ -173,13 +173,30 @@ namespace geode {
*/
std::filesystem::path getConfigDir(bool create = true) const;
/**
* Returns true if this mod has any settings
*/
bool hasSettings() const;
/**
* Get a list of all this mod's setting keys (in the order they were
* declared in `mod.json`)
*/
std::vector<std::string> getSettingKeys() const;
bool hasSetting(std::string_view const key) const;
// todo in v4: remove these
[[deprecated("Use Mod::getSettingV3")]]
std::optional<Setting> getSettingDefinition(std::string_view const key) const;
[[deprecated("Use Mod::getSettingV3")]]
SettingValue* getSetting(std::string_view const key) const;
// todo in v4: possibly rename this to getSetting?
/**
* Get the definition of a setting, or null if the setting was not found,
* or if it's a custom setting that has not yet been registered using
* `Mod::registerCustomSettingType`
* @param key The key of the setting as defined in `mod.json`
*/
std::shared_ptr<SettingV3> getSettingV3(std::string_view const key) const;
/**
@ -213,7 +230,12 @@ namespace geode {
}
/**
* Register a custom setting type
* Register a custom setting type. See
* [the setting docs](https://docs.geode-sdk.org/mods/settings) for more
* @param type The type of the setting. This should **not** include the
* `custom:` prefix!
* @param generator A pointer to a function that, when called, returns a
* newly-created instance of the setting type
*/
Result<> registerCustomSettingType(std::string_view type, SettingGenerator generator);

View file

@ -522,34 +522,46 @@ namespace geode {
*/
template <class S>
class SettingValueNodeV3 : public SettingNodeV3 {
protected:
private:
class Impl final {
private:
typename S::ValueType currentValue;
friend class SettingValueNodeV3;
};
std::shared_ptr<Impl> m_impl;
protected:
bool init(std::shared_ptr<S> setting, float width) {
if (!SettingNodeV3::init(setting, width))
return false;
m_impl = std::make_shared<Impl>();
m_impl->currentValue = setting->getValue();
return true;
}
void onCommit() override {
this->getSetting()->setValue(this->getValue());
this->getSetting()->setValue(m_impl->currentValue);
}
bool hasUncommittedChanges() const override {
return this->getValue() != this->getSetting()->getValue();
return m_impl->currentValue != this->getSetting()->getValue();
}
bool hasNonDefaultValue() const override {
return this->getValue() != this->getSetting()->getDefaultValue();
return m_impl->currentValue != this->getSetting()->getDefaultValue();
}
void onResetToDefault() override {
this->setValue(this->getSetting()->getDefaultValue(), nullptr);
}
virtual void onSetValue(typename S::ValueAssignType value) = 0;
public:
/**
* Get the **uncommitted** value for this node
*/
virtual typename S::ValueType getValue() const = 0;
typename S::ValueType getValue() const {
return m_impl->currentValue;
}
/**
* Set the **uncommitted** value for this node
* @param value The value to set
@ -557,7 +569,7 @@ namespace geode {
* for `SettingNodeV3::updateState` to know more
*/
void setValue(typename S::ValueAssignType value, cocos2d::CCNode* invoker) {
this->onSetValue(value);
m_impl->currentValue = value;
this->markChanged(invoker);
}

View file

@ -278,6 +278,7 @@ bool BoolSettingNodeV3::init(std::shared_ptr<BoolSettingV3> setting, float width
void BoolSettingNodeV3::updateState(CCNode* invoker) {
SettingNodeV3::updateState(invoker);
auto enable = this->getSetting()->shouldEnable();
m_toggle->toggle(this->getValue());
m_toggle->setCascadeColorEnabled(true);
m_toggle->setCascadeOpacityEnabled(true);
m_toggle->setEnabled(enable);
@ -286,17 +287,10 @@ void BoolSettingNodeV3::updateState(CCNode* invoker) {
}
void BoolSettingNodeV3::onToggle(CCObject*) {
m_toggle->toggle(!m_toggle->isToggled());
this->setValue(!m_toggle->isToggled(), m_toggle);
this->markChanged(m_toggle);
}
bool BoolSettingNodeV3::getValue() const {
return m_toggle->isToggled();
}
void BoolSettingNodeV3::onSetValue(bool value) {
m_toggle->toggle(value);
}
BoolSettingNodeV3* BoolSettingNodeV3::create(std::shared_ptr<BoolSettingV3> setting, float width) {
auto ret = new BoolSettingNodeV3();
if (ret && ret->init(setting, width)) {
@ -352,6 +346,11 @@ bool StringSettingNodeV3::init(std::shared_ptr<StringSettingV3> setting, float w
void StringSettingNodeV3::updateState(CCNode* invoker) {
SettingNodeV3::updateState(invoker);
if (invoker != m_input) {
m_input->setString(this->getValue());
}
auto enable = this->getSetting()->shouldEnable();
if (!this->getSetting()->getEnumOptions()) {
m_input->setEnabled(enable);
@ -366,22 +365,14 @@ void StringSettingNodeV3::updateState(CCNode* invoker) {
void StringSettingNodeV3::onArrow(CCObject* sender) {
auto options = *this->getSetting()->getEnumOptions();
auto index = ranges::indexOf(options, m_input->getString()).value_or(0);
auto index = ranges::indexOf(options, this->getValue()).value_or(0);
if (sender->getTag() > 0) {
index = index < options.size() - 1 ? index + 1 : 0;
}
else {
index = index > 0 ? index - 1 : options.size() - 1;
}
m_input->setString(options.at(index));
this->updateState(static_cast<CCNode*>(sender));
}
std::string StringSettingNodeV3::getValue() const {
return m_input->getString();
}
void StringSettingNodeV3::onSetValue(std::string_view value) {
m_input->setString(std::string(value));
this->setValue(options.at(index), static_cast<CCNode*>(sender));
}
StringSettingNodeV3* StringSettingNodeV3::create(std::shared_ptr<StringSettingV3> setting, float width) {
@ -400,8 +391,6 @@ bool FileSettingNodeV3::init(std::shared_ptr<FileSettingV3> setting, float width
if (!SettingValueNodeV3::init(setting, width))
return false;
m_path = setting->getValue();
auto labelBG = extension::CCScale9Sprite::create("square02b_001.png", { 0, 0, 80, 80 });
labelBG->setScale(.25f);
labelBG->setColor({ 0, 0, 0 });
@ -433,13 +422,13 @@ void FileSettingNodeV3::updateState(CCNode* invoker) {
this->getSetting()->isFolder() ? "folderIcon_001.png" : "file.png"_spr
));
limitNodeSize(m_fileIcon, ccp(10, 10), 1.f, .1f);
if (m_path.empty()) {
if (this->getValue().empty()) {
m_nameLabel->setString(this->getSetting()->isFolder() ? "No Folder Selected" : "No File Selected");
m_nameLabel->setColor(ccGRAY);
m_nameLabel->setOpacity(155);
}
else {
m_nameLabel->setString(m_path.filename().string().c_str());
m_nameLabel->setString(this->getValue().filename().string().c_str());
m_nameLabel->setColor(ccWHITE);
m_nameLabel->setOpacity(255);
}
@ -458,8 +447,7 @@ void FileSettingNodeV3::onPickFile(CCObject*) {
return;
}
if (value->isOk()) {
m_path = value->unwrap().string();
this->markChanged(nullptr);
this->setValue(value->unwrap(), nullptr);
}
else {
FLAlertLayer::create(
@ -476,19 +464,14 @@ void FileSettingNodeV3::onPickFile(CCObject*) {
(this->getSetting()->useSaveDialog() ? file::PickMode::SaveFile : file::PickMode::OpenFile),
{
// Prefer opening the current path directly if possible
m_path.empty() || !std::filesystem::exists(m_path.parent_path(), ec) ? dirs::getGameDir() : m_path,
this->getValue().empty() || !std::filesystem::exists(this->getValue().parent_path(), ec) ?
dirs::getGameDir() :
this->getValue(),
this->getSetting()->getFilters().value_or(std::vector<file::FilePickOptions::Filter>())
}
));
}
std::filesystem::path FileSettingNodeV3::getValue() const {
return m_path;
}
void FileSettingNodeV3::onSetValue(std::filesystem::path const& value) {
m_path = value;
}
FileSettingNodeV3* FileSettingNodeV3::create(std::shared_ptr<FileSettingV3> setting, float width) {
auto ret = new FileSettingNodeV3();
if (ret && ret->init(setting, width)) {
@ -505,8 +488,6 @@ bool Color3BSettingNodeV3::init(std::shared_ptr<Color3BSettingV3> setting, float
if (!SettingValueNodeV3::init(setting, width))
return false;
m_value = setting->getValue();
m_colorSprite = ColorChannelSprite::create();
m_colorSprite->setScale(.65f);
@ -522,7 +503,7 @@ bool Color3BSettingNodeV3::init(std::shared_ptr<Color3BSettingV3> setting, float
void Color3BSettingNodeV3::updateState(CCNode* invoker) {
SettingNodeV3::updateState(invoker);
m_colorSprite->setColor(m_value);
m_colorSprite->setColor(this->getValue());
auto enable = this->getSetting()->shouldEnable();
m_colorSprite->setOpacity(enable ? 255 : 155);
@ -530,20 +511,12 @@ void Color3BSettingNodeV3::updateState(CCNode* invoker) {
}
void Color3BSettingNodeV3::onSelectColor(CCObject*) {
auto popup = ColorPickPopup::create(m_value);
auto popup = ColorPickPopup::create(this->getValue());
popup->setDelegate(this);
popup->show();
}
void Color3BSettingNodeV3::updateColor(ccColor4B const& color) {
m_value = to3B(color);
this->markChanged(nullptr);
}
ccColor3B Color3BSettingNodeV3::getValue() const {
return m_value;
}
void Color3BSettingNodeV3::onSetValue(ccColor3B value) {
m_value = value;
this->setValue(to3B(color), nullptr);
}
Color3BSettingNodeV3* Color3BSettingNodeV3::create(std::shared_ptr<Color3BSettingV3> setting, float width) {
@ -562,8 +535,6 @@ bool Color4BSettingNodeV3::init(std::shared_ptr<Color4BSettingV3> setting, float
if (!SettingValueNodeV3::init(setting, width))
return false;
m_value = setting->getValue();
m_colorSprite = ColorChannelSprite::create();
m_colorSprite->setScale(.65f);
@ -579,8 +550,8 @@ bool Color4BSettingNodeV3::init(std::shared_ptr<Color4BSettingV3> setting, float
void Color4BSettingNodeV3::updateState(CCNode* invoker) {
SettingNodeV3::updateState(invoker);
m_colorSprite->setColor(to3B(m_value));
m_colorSprite->updateOpacity(m_value.a / 255.f);
m_colorSprite->setColor(to3B(this->getValue()));
m_colorSprite->updateOpacity(this->getValue().a / 255.f);
auto enable = this->getSetting()->shouldEnable();
m_colorSprite->setOpacity(enable ? 255 : 155);
@ -588,20 +559,12 @@ void Color4BSettingNodeV3::updateState(CCNode* invoker) {
}
void Color4BSettingNodeV3::onSelectColor(CCObject*) {
auto popup = ColorPickPopup::create(m_value);
auto popup = ColorPickPopup::create(this->getValue());
popup->setDelegate(this);
popup->show();
}
void Color4BSettingNodeV3::updateColor(ccColor4B const& color) {
m_value = color;
this->markChanged(nullptr);
}
ccColor4B Color4BSettingNodeV3::getValue() const {
return m_value;
}
void Color4BSettingNodeV3::onSetValue(ccColor4B value) {
m_value = value;
this->setValue(color, nullptr);
}
Color4BSettingNodeV3* Color4BSettingNodeV3::create(std::shared_ptr<Color4BSettingV3> setting, float width) {

View file

@ -36,9 +36,6 @@ protected:
void onToggle(CCObject*);
public:
bool getValue() const override;
void onSetValue(bool value) override;
static BoolSettingNodeV3* create(std::shared_ptr<BoolSettingV3> setting, float width);
};
@ -172,6 +169,10 @@ protected:
m_input->setEnabled(enable);
}
if (invoker != m_input) {
m_input->setString(numToString(this->getValue()));
}
auto min = this->getSetting()->getMinValue();
auto enableLeft = enable && (!min || this->getValue() > *min);
m_arrowLeftBtn->setEnabled(enableLeft);
@ -215,14 +216,6 @@ protected:
this->setValue(this->valueFromSlider(m_slider->m_touchLogic->m_thumb->getValue()), m_slider);
}
ValueType getValue() const override {
return numFromString<ValueType>(m_input->getString())
.value_or(this->getSetting()->getDefaultValue());
}
void onSetValue(ValueAssignType value) override {
m_input->setString(numToString(value));
}
public:
static NumberSettingNodeV3* create(std::shared_ptr<S> setting, float width) {
auto ret = new NumberSettingNodeV3();
@ -250,15 +243,11 @@ protected:
public:
static StringSettingNodeV3* create(std::shared_ptr<StringSettingV3> setting, float width);
std::string getValue() const override;
void onSetValue(std::string_view value) override;
};
class FileSettingNodeV3 : public SettingValueNodeV3<FileSettingV3> {
protected:
CCSprite* m_fileIcon;
std::filesystem::path m_path;
CCLabelBMFont* m_nameLabel;
EventListener<Task<Result<std::filesystem::path>>> m_pickListener;
CCMenuItemSpriteExtra* m_selectBtn;
@ -270,14 +259,10 @@ protected:
public:
static FileSettingNodeV3* create(std::shared_ptr<FileSettingV3> setting, float width);
std::filesystem::path getValue() const override;
void onSetValue(std::filesystem::path const& value) override;
};
class Color3BSettingNodeV3 : public SettingValueNodeV3<Color3BSettingV3>, public ColorPickPopupDelegate {
protected:
ccColor3B m_value;
CCMenuItemSpriteExtra* m_colorBtn;
ColorChannelSprite* m_colorSprite;
@ -288,14 +273,10 @@ protected:
public:
static Color3BSettingNodeV3* create(std::shared_ptr<Color3BSettingV3> setting, float width);
ccColor3B getValue() const override;
void onSetValue(ccColor3B value) override;
};
class Color4BSettingNodeV3 : public SettingValueNodeV3<Color4BSettingV3>, public ColorPickPopupDelegate {
protected:
ccColor4B m_value;
CCMenuItemSpriteExtra* m_colorBtn;
ColorChannelSprite* m_colorSprite;
@ -306,9 +287,6 @@ protected:
public:
static Color4BSettingNodeV3* create(std::shared_ptr<Color4BSettingV3> setting, float width);
ccColor4B getValue() const override;
void onSetValue(ccColor4B value) override;
};
class UnresolvedCustomSettingNodeV3 : public SettingNodeV3 {

View file

@ -1055,17 +1055,18 @@ Result<std::shared_ptr<FileSettingV3>> FileSettingV3::parse(std::string const& k
key, modID
);
}
std::string dialogType;
root.has("dialog").into(dialogType);
switch (hash(dialogType)) {
case hash("save"): ret->m_impl->useSaveDialog = true; break;
case hash("open"): ret->m_impl->useSaveDialog = false; break;
case hash(""): break;
default: return Err("Setting '{}' in mod {}: unknown \"dialog\" type \"{}\"", key, modID, dialogType);
}
// Filter controls only make sense for files but not for folders
// Controls only make sense for files but not for folders
if (auto controls = root.has("control")) {
std::string dialogType;
controls.has("dialog").into(dialogType);
switch (hash(dialogType)) {
case hash("save"): ret->m_impl->useSaveDialog = true; break;
case hash("open"): ret->m_impl->useSaveDialog = false; break;
case hash(""): break;
default: return Err("Setting '{}' in mod {}: unknown \"dialog\" type \"{}\"", key, modID, dialogType);
}
auto filters = std::vector<file::FilePickOptions::Filter>();
for (auto& item : controls.has("filters").items()) {
utils::file::FilePickOptions::Filter filter;