mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
path settings done
This commit is contained in:
parent
3f3b52104f
commit
766b71dfbd
4 changed files with 252 additions and 84 deletions
|
@ -267,8 +267,8 @@ namespace geode {
|
||||||
|
|
||||||
bool isArrowsEnabled() const;
|
bool isArrowsEnabled() const;
|
||||||
bool isBigArrowsEnabled() const;
|
bool isBigArrowsEnabled() const;
|
||||||
size_t getArrowStepSize() const;
|
double getArrowStepSize() const;
|
||||||
size_t getBigArrowStepSize() const;
|
double getBigArrowStepSize() const;
|
||||||
bool isSliderEnabled() const;
|
bool isSliderEnabled() const;
|
||||||
std::optional<double> getSliderSnap() const;
|
std::optional<double> getSliderSnap() const;
|
||||||
bool isInputEnabled() const;
|
bool isInputEnabled() const;
|
||||||
|
@ -328,9 +328,17 @@ namespace geode {
|
||||||
FileSettingV3(PrivateMarker);
|
FileSettingV3(PrivateMarker);
|
||||||
static Result<std::shared_ptr<FileSettingV3>> parse(std::string const& key, std::string const& modID, matjson::Value const& json);
|
static Result<std::shared_ptr<FileSettingV3>> parse(std::string const& key, std::string const& modID, matjson::Value const& json);
|
||||||
|
|
||||||
|
enum class FileType {
|
||||||
|
Any = 0,
|
||||||
|
File = 1,
|
||||||
|
Folder = 2,
|
||||||
|
};
|
||||||
|
|
||||||
std::filesystem::path getDefaultValue() const override;
|
std::filesystem::path getDefaultValue() const override;
|
||||||
Result<> isValid(std::filesystem::path const& value) const override;
|
Result<> isValid(std::filesystem::path const& value) const override;
|
||||||
|
|
||||||
|
FileType getFileType() const;
|
||||||
|
|
||||||
std::optional<std::vector<utils::file::FilePickOptions::Filter>> getFilters() const;
|
std::optional<std::vector<utils::file::FilePickOptions::Filter>> getFilters() const;
|
||||||
|
|
||||||
bool load(matjson::Value const& json) override;
|
bool load(matjson::Value const& json) override;
|
||||||
|
|
|
@ -73,6 +73,7 @@ bool SettingNodeV3::init(std::shared_ptr<SettingV3> setting, float width) {
|
||||||
m_impl->nameMenu->addChild(m_impl->resetButton);
|
m_impl->nameMenu->addChild(m_impl->resetButton);
|
||||||
|
|
||||||
m_impl->nameMenu->setLayout(RowLayout::create()->setAxisAlignment(AxisAlignment::Start));
|
m_impl->nameMenu->setLayout(RowLayout::create()->setAxisAlignment(AxisAlignment::Start));
|
||||||
|
m_impl->nameMenu->getLayout()->ignoreInvisibleChildren(true);
|
||||||
this->addChildAtPosition(m_impl->nameMenu, Anchor::Left, ccp(10, 0), ccp(0, .5f));
|
this->addChildAtPosition(m_impl->nameMenu, Anchor::Left, ccp(10, 0), ccp(0, .5f));
|
||||||
|
|
||||||
m_impl->buttonMenu = CCMenu::create();
|
m_impl->buttonMenu = CCMenu::create();
|
||||||
|
@ -198,6 +199,10 @@ bool BoolSettingNodeV3::init(std::shared_ptr<BoolSettingV3> setting, float width
|
||||||
if (!SettingNodeV3::init(setting, width))
|
if (!SettingNodeV3::init(setting, width))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
this->getButtonMenu()->setContentWidth(20);
|
||||||
|
this->getNameMenu()->setContentWidth(width - 50);
|
||||||
|
this->getNameMenu()->updateLayout();
|
||||||
|
|
||||||
m_toggle = CCMenuItemToggler::createWithStandardSprites(
|
m_toggle = CCMenuItemToggler::createWithStandardSprites(
|
||||||
this, menu_selector(BoolSettingNodeV3::onToggle), .55f
|
this, menu_selector(BoolSettingNodeV3::onToggle), .55f
|
||||||
);
|
);
|
||||||
|
@ -209,9 +214,6 @@ bool BoolSettingNodeV3::init(std::shared_ptr<BoolSettingV3> setting, float width
|
||||||
m_toggle->toggle(setting->getValue());
|
m_toggle->toggle(setting->getValue());
|
||||||
this->getButtonMenu()->addChildAtPosition(m_toggle, Anchor::Right, ccp(-10, 0));
|
this->getButtonMenu()->addChildAtPosition(m_toggle, Anchor::Right, ccp(-10, 0));
|
||||||
|
|
||||||
this->getNameMenu()->setContentWidth(width - 50);
|
|
||||||
this->getNameMenu()->updateLayout();
|
|
||||||
|
|
||||||
this->updateState();
|
this->updateState();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -255,7 +257,7 @@ bool StringSettingNodeV3::init(std::shared_ptr<StringSettingV3> setting, float w
|
||||||
if (!SettingNodeV3::init(setting, width))
|
if (!SettingNodeV3::init(setting, width))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_input = TextInput::create(width / 2 - 50, "Num");
|
m_input = TextInput::create(setting->getEnumOptions() ? width / 2 - 50 : width / 2, "Text");
|
||||||
m_input->setCallback([this](auto const&) {
|
m_input->setCallback([this](auto const&) {
|
||||||
this->markChanged();
|
this->markChanged();
|
||||||
});
|
});
|
||||||
|
@ -339,20 +341,91 @@ bool FileSettingNodeV3::init(std::shared_ptr<FileSettingV3> setting, float width
|
||||||
if (!SettingNodeV3::init(setting, width))
|
if (!SettingNodeV3::init(setting, width))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// todo
|
m_path = setting->getValue();
|
||||||
|
|
||||||
|
auto labelBG = extension::CCScale9Sprite::create("square02b_001.png", { 0, 0, 80, 80 });
|
||||||
|
labelBG->setScale(.25f);
|
||||||
|
labelBG->setColor({ 0, 0, 0 });
|
||||||
|
labelBG->setOpacity(90);
|
||||||
|
labelBG->setContentSize({ 400, 80 });
|
||||||
|
this->getButtonMenu()->addChildAtPosition(labelBG, Anchor::Center, ccp(-15, 0));
|
||||||
|
|
||||||
|
m_fileIcon = CCSprite::create();
|
||||||
|
this->getButtonMenu()->addChildAtPosition(m_fileIcon, Anchor::Left, ccp(3, 0));
|
||||||
|
|
||||||
|
m_nameLabel = CCLabelBMFont::create("", "bigFont.fnt");
|
||||||
|
this->getButtonMenu()->addChildAtPosition(m_nameLabel, Anchor::Left, ccp(11, 0), ccp(0, .5f));
|
||||||
|
|
||||||
|
auto selectSpr = CCSprite::createWithSpriteFrameName("GJ_plus2Btn_001.png");
|
||||||
|
selectSpr->setScale(.75f);
|
||||||
|
auto selectBtn = CCMenuItemSpriteExtra::create(
|
||||||
|
selectSpr, this, menu_selector(FileSettingNodeV3::onPickFile)
|
||||||
|
);
|
||||||
|
this->getButtonMenu()->addChildAtPosition(selectBtn, Anchor::Right, ccp(-5, 0));
|
||||||
|
|
||||||
|
this->updateState();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSettingNodeV3::onCommit() {}
|
void FileSettingNodeV3::updateState() {
|
||||||
|
SettingNodeV3::updateState();
|
||||||
|
auto ty = this->getSetting()->getFileType();
|
||||||
|
if (ty == FileSettingV3::FileType::Any) {
|
||||||
|
ty = std::filesystem::is_directory(m_path) ?
|
||||||
|
FileSettingV3::FileType::Folder :
|
||||||
|
FileSettingV3::FileType::File;
|
||||||
|
}
|
||||||
|
m_fileIcon->setDisplayFrame(CCSpriteFrameCache::get()->spriteFrameByName(
|
||||||
|
ty == FileSettingV3::FileType::File ? "file.png"_spr : "folderIcon_001.png"
|
||||||
|
));
|
||||||
|
limitNodeSize(m_fileIcon, ccp(10, 10), 1.f, .1f);
|
||||||
|
m_nameLabel->setString(m_path.filename().string().c_str());
|
||||||
|
m_nameLabel->limitLabelWidth(75, .4f, .1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSettingNodeV3::onCommit() {
|
||||||
|
this->getSetting()->setValue(m_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSettingNodeV3::onPickFile(CCObject*) {
|
||||||
|
m_pickListener.bind([this](auto* event) {
|
||||||
|
auto value = event->getValue();
|
||||||
|
if (!value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value->isOk()) {
|
||||||
|
m_path = value->unwrap().string();
|
||||||
|
this->markChanged();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FLAlertLayer::create(
|
||||||
|
"Failed",
|
||||||
|
fmt::format("Failed to pick file: {}", value->unwrapErr()),
|
||||||
|
"Ok"
|
||||||
|
)->show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_pickListener.setFilter(file::pick(
|
||||||
|
this->getSetting()->getFileType() == FileSettingV3::FileType::Folder ?
|
||||||
|
file::PickMode::OpenFolder :
|
||||||
|
file::PickMode::OpenFile,
|
||||||
|
{
|
||||||
|
dirs::getGameDir(),
|
||||||
|
this->getSetting()->getFilters().value_or(std::vector<file::FilePickOptions::Filter>())
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
bool FileSettingNodeV3::hasUncommittedChanges() const {
|
bool FileSettingNodeV3::hasUncommittedChanges() const {
|
||||||
return false;
|
return m_path != this->getSetting()->getValue();
|
||||||
}
|
}
|
||||||
bool FileSettingNodeV3::hasNonDefaultValue() const {
|
bool FileSettingNodeV3::hasNonDefaultValue() const {
|
||||||
return false;
|
return m_path != this->getSetting()->getDefaultValue();
|
||||||
|
}
|
||||||
|
void FileSettingNodeV3::onResetToDefault() {
|
||||||
|
m_path = this->getSetting()->getDefaultValue();
|
||||||
}
|
}
|
||||||
void FileSettingNodeV3::onResetToDefault() {}
|
|
||||||
|
|
||||||
std::shared_ptr<FileSettingV3> FileSettingNodeV3::getSetting() const {
|
std::shared_ptr<FileSettingV3> FileSettingNodeV3::getSetting() const {
|
||||||
return std::static_pointer_cast<FileSettingV3>(SettingNodeV3::getSetting());
|
return std::static_pointer_cast<FileSettingV3>(SettingNodeV3::getSetting());
|
||||||
|
|
|
@ -52,6 +52,10 @@ protected:
|
||||||
|
|
||||||
TextInput* m_input;
|
TextInput* m_input;
|
||||||
Slider* m_slider;
|
Slider* m_slider;
|
||||||
|
CCMenuItemSpriteExtra* m_arrowLeftBtn;
|
||||||
|
CCMenuItemSpriteExtra* m_bigArrowLeftBtn;
|
||||||
|
CCMenuItemSpriteExtra* m_arrowRightBtn;
|
||||||
|
CCMenuItemSpriteExtra* m_bigArrowRightBtn;
|
||||||
|
|
||||||
float valueToSlider(ValueType value) {
|
float valueToSlider(ValueType value) {
|
||||||
auto min = this->getSetting()->getMinValue().value_or(-100);
|
auto min = this->getSetting()->getMinValue().value_or(-100);
|
||||||
|
@ -75,6 +79,8 @@ protected:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto bigArrowLeftSpr = CCSprite::create();
|
auto bigArrowLeftSpr = CCSprite::create();
|
||||||
|
bigArrowLeftSpr->setCascadeColorEnabled(true);
|
||||||
|
bigArrowLeftSpr->setCascadeOpacityEnabled(true);
|
||||||
auto bigArrowLeftSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
|
auto bigArrowLeftSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
|
||||||
auto bigArrowLeftSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
|
auto bigArrowLeftSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
|
||||||
|
|
||||||
|
@ -83,21 +89,21 @@ protected:
|
||||||
bigArrowLeftSpr->addChildAtPosition(bigArrowLeftSpr1, Anchor::Center, ccp(-10, 0));
|
bigArrowLeftSpr->addChildAtPosition(bigArrowLeftSpr1, Anchor::Center, ccp(-10, 0));
|
||||||
bigArrowLeftSpr->setScale(.3f);
|
bigArrowLeftSpr->setScale(.3f);
|
||||||
|
|
||||||
auto bigArrowLeftBtn = CCMenuItemSpriteExtra::create(
|
m_bigArrowLeftBtn = CCMenuItemSpriteExtra::create(
|
||||||
bigArrowLeftSpr, this, menu_selector(NumberSettingNodeV3::onArrow)
|
bigArrowLeftSpr, this, menu_selector(NumberSettingNodeV3::onArrow)
|
||||||
);
|
);
|
||||||
bigArrowLeftBtn->setTag(-setting->getBigArrowStepSize());
|
m_bigArrowLeftBtn->setUserObject(ObjWrapper<ValueType>::create(-setting->getBigArrowStepSize()));
|
||||||
bigArrowLeftBtn->setVisible(setting->isBigArrowsEnabled());
|
m_bigArrowLeftBtn->setVisible(setting->isBigArrowsEnabled());
|
||||||
this->getButtonMenu()->addChildAtPosition(bigArrowLeftBtn, Anchor::Left, ccp(5, 0));
|
this->getButtonMenu()->addChildAtPosition(m_bigArrowLeftBtn, Anchor::Left, ccp(5, 0));
|
||||||
|
|
||||||
auto arrowLeftSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png");
|
auto arrowLeftSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png");
|
||||||
arrowLeftSpr->setScale(.5f);
|
arrowLeftSpr->setScale(.5f);
|
||||||
auto arrowLeftBtn = CCMenuItemSpriteExtra::create(
|
m_arrowLeftBtn = CCMenuItemSpriteExtra::create(
|
||||||
arrowLeftSpr, this, menu_selector(NumberSettingNodeV3::onArrow)
|
arrowLeftSpr, this, menu_selector(NumberSettingNodeV3::onArrow)
|
||||||
);
|
);
|
||||||
arrowLeftBtn->setTag(-setting->getArrowStepSize());
|
m_arrowLeftBtn->setUserObject(ObjWrapper<ValueType>::create(-setting->getArrowStepSize()));
|
||||||
arrowLeftBtn->setVisible(setting->isArrowsEnabled());
|
m_arrowLeftBtn->setVisible(setting->isArrowsEnabled());
|
||||||
this->getButtonMenu()->addChildAtPosition(arrowLeftBtn, Anchor::Left, ccp(22, 0));
|
this->getButtonMenu()->addChildAtPosition(m_arrowLeftBtn, Anchor::Left, ccp(22, 0));
|
||||||
|
|
||||||
m_input = TextInput::create(this->getButtonMenu()->getContentWidth() - 40, "Num");
|
m_input = TextInput::create(this->getButtonMenu()->getContentWidth() - 40, "Num");
|
||||||
m_input->setScale(.7f);
|
m_input->setScale(.7f);
|
||||||
|
@ -115,14 +121,16 @@ protected:
|
||||||
auto arrowRightSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png");
|
auto arrowRightSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png");
|
||||||
arrowRightSpr->setFlipX(true);
|
arrowRightSpr->setFlipX(true);
|
||||||
arrowRightSpr->setScale(.5f);
|
arrowRightSpr->setScale(.5f);
|
||||||
auto arrowRightBtn = CCMenuItemSpriteExtra::create(
|
m_arrowRightBtn = CCMenuItemSpriteExtra::create(
|
||||||
arrowRightSpr, this, menu_selector(NumberSettingNodeV3::onArrow)
|
arrowRightSpr, this, menu_selector(NumberSettingNodeV3::onArrow)
|
||||||
);
|
);
|
||||||
arrowRightBtn->setTag(setting->getArrowStepSize());
|
m_arrowRightBtn->setUserObject(ObjWrapper<ValueType>::create(setting->getArrowStepSize()));
|
||||||
arrowRightBtn->setVisible(setting->isArrowsEnabled());
|
m_arrowRightBtn->setVisible(setting->isArrowsEnabled());
|
||||||
this->getButtonMenu()->addChildAtPosition(arrowRightBtn, Anchor::Right, ccp(-22, 0));
|
this->getButtonMenu()->addChildAtPosition(m_arrowRightBtn, Anchor::Right, ccp(-22, 0));
|
||||||
|
|
||||||
auto bigArrowRightSpr = CCSprite::create();
|
auto bigArrowRightSpr = CCSprite::create();
|
||||||
|
bigArrowRightSpr->setCascadeColorEnabled(true);
|
||||||
|
bigArrowRightSpr->setCascadeOpacityEnabled(true);
|
||||||
auto bigArrowRightSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
|
auto bigArrowRightSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
|
||||||
bigArrowRightSpr1->setFlipX(true);
|
bigArrowRightSpr1->setFlipX(true);
|
||||||
auto bigArrowRightSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
|
auto bigArrowRightSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png");
|
||||||
|
@ -133,12 +141,12 @@ protected:
|
||||||
bigArrowRightSpr->addChildAtPosition(bigArrowRightSpr2, Anchor::Center, ccp(10, 0));
|
bigArrowRightSpr->addChildAtPosition(bigArrowRightSpr2, Anchor::Center, ccp(10, 0));
|
||||||
bigArrowRightSpr->setScale(.3f);
|
bigArrowRightSpr->setScale(.3f);
|
||||||
|
|
||||||
auto bigArrowRightBtn = CCMenuItemSpriteExtra::create(
|
m_bigArrowRightBtn = CCMenuItemSpriteExtra::create(
|
||||||
bigArrowRightSpr, this, menu_selector(NumberSettingNodeV3::onArrow)
|
bigArrowRightSpr, this, menu_selector(NumberSettingNodeV3::onArrow)
|
||||||
);
|
);
|
||||||
bigArrowRightBtn->setTag(setting->getBigArrowStepSize());
|
m_bigArrowRightBtn->setUserObject(ObjWrapper<ValueType>::create(setting->getBigArrowStepSize()));
|
||||||
bigArrowRightBtn->setVisible(setting->isBigArrowsEnabled());
|
m_bigArrowRightBtn->setVisible(setting->isBigArrowsEnabled());
|
||||||
this->getButtonMenu()->addChildAtPosition(bigArrowRightBtn, Anchor::Right, ccp(-5, 0));
|
this->getButtonMenu()->addChildAtPosition(m_bigArrowRightBtn, Anchor::Right, ccp(-5, 0));
|
||||||
|
|
||||||
if (setting->isSliderEnabled()) {
|
if (setting->isSliderEnabled()) {
|
||||||
this->setContentHeight(45);
|
this->setContentHeight(45);
|
||||||
|
@ -161,13 +169,40 @@ protected:
|
||||||
m_slider->m_touchLogic->m_thumb->setValue(this->valueToSlider(this->getCurrentValue()));
|
m_slider->m_touchLogic->m_thumb->setValue(this->valueToSlider(this->getCurrentValue()));
|
||||||
m_slider->updateBar();
|
m_slider->updateBar();
|
||||||
}
|
}
|
||||||
|
if (auto min = this->getSetting()->getMinValue()) {
|
||||||
|
auto enable = this->getCurrentValue() > *min;
|
||||||
|
m_arrowLeftBtn->setEnabled(enable);
|
||||||
|
m_bigArrowLeftBtn->setEnabled(enable);
|
||||||
|
static_cast<CCSprite*>(m_arrowLeftBtn->getNormalImage())->setOpacity(enable ? 255 : 155);
|
||||||
|
static_cast<CCSprite*>(m_arrowLeftBtn->getNormalImage())->setColor(enable ? ccWHITE : ccGRAY);
|
||||||
|
static_cast<CCSprite*>(m_bigArrowLeftBtn->getNormalImage())->setOpacity(enable ? 255 : 155);
|
||||||
|
static_cast<CCSprite*>(m_bigArrowLeftBtn->getNormalImage())->setColor(enable ? ccWHITE : ccGRAY);
|
||||||
|
}
|
||||||
|
if (auto max = this->getSetting()->getMaxValue()) {
|
||||||
|
auto enable = this->getCurrentValue() < *max;
|
||||||
|
m_arrowRightBtn->setEnabled(enable);
|
||||||
|
m_bigArrowRightBtn->setEnabled(enable);
|
||||||
|
static_cast<CCSprite*>(m_arrowRightBtn->getNormalImage())->setOpacity(enable ? 255 : 155);
|
||||||
|
static_cast<CCSprite*>(m_arrowRightBtn->getNormalImage())->setColor(enable ? ccWHITE : ccGRAY);
|
||||||
|
static_cast<CCSprite*>(m_bigArrowRightBtn->getNormalImage())->setOpacity(enable ? 255 : 155);
|
||||||
|
static_cast<CCSprite*>(m_bigArrowRightBtn->getNormalImage())->setColor(enable ? ccWHITE : ccGRAY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCommit() override {
|
void onCommit() override {
|
||||||
this->getSetting()->setValue(this->getCurrentValue());
|
this->getSetting()->setValue(this->getCurrentValue());
|
||||||
}
|
}
|
||||||
void onArrow(CCObject* sender) {
|
void onArrow(CCObject* sender) {
|
||||||
this->setCurrentValue(this->getCurrentValue() + sender->getTag());
|
auto value = this->getCurrentValue() + static_cast<ObjWrapper<ValueType>*>(
|
||||||
|
static_cast<CCNode*>(sender)->getUserObject()
|
||||||
|
)->getValue();
|
||||||
|
if (auto min = this->getSetting()->getMinValue()) {
|
||||||
|
value = std::max(*min, value);
|
||||||
|
}
|
||||||
|
if (auto max = this->getSetting()->getMaxValue()) {
|
||||||
|
value = std::min(*max, value);
|
||||||
|
}
|
||||||
|
this->setCurrentValue(value);
|
||||||
}
|
}
|
||||||
void onSlider(CCObject*) {
|
void onSlider(CCObject*) {
|
||||||
this->setCurrentValue(this->valueFromSlider(m_slider->m_touchLogic->m_thumb->getValue()));
|
this->setCurrentValue(this->valueFromSlider(m_slider->m_touchLogic->m_thumb->getValue()));
|
||||||
|
@ -233,9 +268,17 @@ public:
|
||||||
|
|
||||||
class FileSettingNodeV3 : public SettingNodeV3 {
|
class FileSettingNodeV3 : public SettingNodeV3 {
|
||||||
protected:
|
protected:
|
||||||
|
CCSprite* m_fileIcon;
|
||||||
|
std::filesystem::path m_path;
|
||||||
|
CCLabelBMFont* m_nameLabel;
|
||||||
|
EventListener<Task<Result<std::filesystem::path>>> m_pickListener;
|
||||||
|
|
||||||
bool init(std::shared_ptr<FileSettingV3> setting, float width);
|
bool init(std::shared_ptr<FileSettingV3> setting, float width);
|
||||||
|
|
||||||
|
void updateState() override;
|
||||||
|
|
||||||
void onCommit() override;
|
void onCommit() override;
|
||||||
|
void onPickFile(CCObject*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static FileSettingNodeV3* create(std::shared_ptr<FileSettingV3> setting, float width);
|
static FileSettingNodeV3* create(std::shared_ptr<FileSettingV3> setting, float width);
|
||||||
|
|
|
@ -26,6 +26,7 @@ Result<> SettingV3::parseSharedProperties(std::string const& key, std::string co
|
||||||
void SettingV3::parseSharedProperties(std::string const& key, std::string const& modID, JsonExpectedValue& value, bool onlyNameAndDesc) {
|
void SettingV3::parseSharedProperties(std::string const& key, std::string const& modID, JsonExpectedValue& value, bool onlyNameAndDesc) {
|
||||||
this->init(key, modID);
|
this->init(key, modID);
|
||||||
value.needs("type");
|
value.needs("type");
|
||||||
|
value.has("platforms");
|
||||||
value.has("name").into(m_impl->name);
|
value.has("name").into(m_impl->name);
|
||||||
value.has("description").into(m_impl->description);
|
value.has("description").into(m_impl->description);
|
||||||
if (!onlyNameAndDesc) {
|
if (!onlyNameAndDesc) {
|
||||||
|
@ -239,32 +240,40 @@ Result<std::shared_ptr<IntSettingV3>> IntSettingV3::parse(std::string const& key
|
||||||
root.has("min").into(ret->m_impl->minValue);
|
root.has("min").into(ret->m_impl->minValue);
|
||||||
root.has("max").into(ret->m_impl->maxValue);
|
root.has("max").into(ret->m_impl->maxValue);
|
||||||
if (auto controls = root.has("control")) {
|
if (auto controls = root.has("control")) {
|
||||||
|
controls.has("arrows");
|
||||||
|
controls.has("big-arrows");
|
||||||
controls.has("arrow-step").into(ret->m_impl->controls.arrowStepSize);
|
controls.has("arrow-step").into(ret->m_impl->controls.arrowStepSize);
|
||||||
if (!controls.has("arrows").template get<bool>()) {
|
|
||||||
ret->m_impl->controls.arrowStepSize = 0;
|
|
||||||
}
|
|
||||||
controls.has("big-arrow-step").into(ret->m_impl->controls.bigArrowStepSize);
|
controls.has("big-arrow-step").into(ret->m_impl->controls.bigArrowStepSize);
|
||||||
if (!controls.has("big-arrows").template get<bool>()) {
|
|
||||||
ret->m_impl->controls.bigArrowStepSize = 0;
|
|
||||||
}
|
|
||||||
controls.has("slider").into(ret->m_impl->controls.sliderEnabled);
|
controls.has("slider").into(ret->m_impl->controls.sliderEnabled);
|
||||||
controls.has("slider-step").into(ret->m_impl->controls.sliderSnap);
|
controls.has("slider-step").into(ret->m_impl->controls.sliderSnap);
|
||||||
controls.has("input").into(ret->m_impl->controls.textInputEnabled);
|
controls.has("input").into(ret->m_impl->controls.textInputEnabled);
|
||||||
// Without "min" or "max" slider makes no sense
|
|
||||||
if (!ret->m_impl->minValue || !ret->m_impl->maxValue) {
|
|
||||||
if (ret->m_impl->controls.sliderEnabled) {
|
|
||||||
log::warn(
|
|
||||||
"Setting '{}' has \"controls.slider\" enabled but doesn't "
|
|
||||||
"have both \"min\" and \"max\" defined - the slider has "
|
|
||||||
"been force-disabled!",
|
|
||||||
key
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ret->m_impl->controls.sliderEnabled = false;
|
|
||||||
}
|
|
||||||
controls.checkUnknownKeys();
|
controls.checkUnknownKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable arrows if they aren't enabled
|
||||||
|
// This silly code is because step size being 0 is what defines if they are enabled
|
||||||
|
|
||||||
|
// Small arrows are enabled by default
|
||||||
|
if (!root.has("control").has("arrows").template get<bool>(true)) {
|
||||||
|
ret->m_impl->controls.arrowStepSize = 0;
|
||||||
|
}
|
||||||
|
if (!root.has("control").has("big-arrows").template get<bool>()) {
|
||||||
|
ret->m_impl->controls.bigArrowStepSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Without "min" or "max" slider makes no sense
|
||||||
|
if (!ret->m_impl->minValue || !ret->m_impl->maxValue) {
|
||||||
|
if (ret->m_impl->controls.sliderEnabled && root.has("control").has("slider")) {
|
||||||
|
log::warn(
|
||||||
|
"Setting '{}' has \"controls.slider\" enabled but doesn't "
|
||||||
|
"have both \"min\" and \"max\" defined - the slider has "
|
||||||
|
"been force-disabled!",
|
||||||
|
key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ret->m_impl->controls.sliderEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
root.checkUnknownKeys();
|
root.checkUnknownKeys();
|
||||||
return root.ok(ret);
|
return root.ok(ret);
|
||||||
}
|
}
|
||||||
|
@ -279,10 +288,10 @@ int64_t IntSettingV3::getDefaultValue() const {
|
||||||
}
|
}
|
||||||
Result<> IntSettingV3::isValid(int64_t value) const {
|
Result<> IntSettingV3::isValid(int64_t value) const {
|
||||||
if (m_impl->minValue && value < *m_impl->minValue) {
|
if (m_impl->minValue && value < *m_impl->minValue) {
|
||||||
return Err("value must be at least {}", *m_impl->minValue);
|
return Err("Value must be at least {}", *m_impl->minValue);
|
||||||
}
|
}
|
||||||
if (m_impl->maxValue && value > *m_impl->maxValue) {
|
if (m_impl->maxValue && value > *m_impl->maxValue) {
|
||||||
return Err("value must be at most {}", *m_impl->maxValue);
|
return Err("Value must be at most {}", *m_impl->maxValue);
|
||||||
}
|
}
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
@ -364,8 +373,8 @@ public:
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
// 0 means not enabled
|
// 0 means not enabled
|
||||||
size_t arrowStepSize = 1;
|
double arrowStepSize = 1;
|
||||||
size_t bigArrowStepSize = 5;
|
double bigArrowStepSize = 5;
|
||||||
bool sliderEnabled = true;
|
bool sliderEnabled = true;
|
||||||
std::optional<double> sliderSnap;
|
std::optional<double> sliderSnap;
|
||||||
bool textInputEnabled = true;
|
bool textInputEnabled = true;
|
||||||
|
@ -385,32 +394,38 @@ Result<std::shared_ptr<FloatSettingV3>> FloatSettingV3::parse(std::string const&
|
||||||
root.has("min").into(ret->m_impl->minValue);
|
root.has("min").into(ret->m_impl->minValue);
|
||||||
root.has("max").into(ret->m_impl->maxValue);
|
root.has("max").into(ret->m_impl->maxValue);
|
||||||
if (auto controls = root.has("control")) {
|
if (auto controls = root.has("control")) {
|
||||||
|
controls.has("arrows");
|
||||||
|
controls.has("big-arrows");
|
||||||
controls.has("arrow-step").into(ret->m_impl->controls.arrowStepSize);
|
controls.has("arrow-step").into(ret->m_impl->controls.arrowStepSize);
|
||||||
if (!controls.has("arrows").template get<bool>()) {
|
|
||||||
ret->m_impl->controls.arrowStepSize = 0;
|
|
||||||
}
|
|
||||||
controls.has("big-arrow-step").into(ret->m_impl->controls.bigArrowStepSize);
|
controls.has("big-arrow-step").into(ret->m_impl->controls.bigArrowStepSize);
|
||||||
if (!controls.has("big-arrows").template get<bool>()) {
|
|
||||||
ret->m_impl->controls.bigArrowStepSize = 0;
|
|
||||||
}
|
|
||||||
controls.has("slider").into(ret->m_impl->controls.sliderEnabled);
|
controls.has("slider").into(ret->m_impl->controls.sliderEnabled);
|
||||||
controls.has("slider-step").into(ret->m_impl->controls.sliderSnap);
|
controls.has("slider-step").into(ret->m_impl->controls.sliderSnap);
|
||||||
controls.has("input").into(ret->m_impl->controls.textInputEnabled);
|
controls.has("input").into(ret->m_impl->controls.textInputEnabled);
|
||||||
// Without "min" or "max" slider makes no sense
|
|
||||||
if (!ret->m_impl->minValue || !ret->m_impl->maxValue) {
|
|
||||||
if (ret->m_impl->controls.sliderEnabled) {
|
|
||||||
log::warn(
|
|
||||||
"Setting '{}' has \"controls.slider\" enabled but doesn't "
|
|
||||||
"have both \"min\" and \"max\" defined - the slider has "
|
|
||||||
"been force-disabled!",
|
|
||||||
key
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ret->m_impl->controls.sliderEnabled = false;
|
|
||||||
}
|
|
||||||
controls.checkUnknownKeys();
|
controls.checkUnknownKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable arrows if they aren't enabled
|
||||||
|
// Small arrows are enabled by default
|
||||||
|
if (!root.has("control").has("arrows").template get<bool>(true)) {
|
||||||
|
ret->m_impl->controls.arrowStepSize = 0;
|
||||||
|
}
|
||||||
|
if (!root.has("control").has("big-arrows").template get<bool>()) {
|
||||||
|
ret->m_impl->controls.bigArrowStepSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Without "min" or "max" slider makes no sense
|
||||||
|
if (!ret->m_impl->minValue || !ret->m_impl->maxValue) {
|
||||||
|
if (ret->m_impl->controls.sliderEnabled && root.has("control").has("slider")) {
|
||||||
|
log::warn(
|
||||||
|
"Setting '{}' has \"controls.slider\" enabled but doesn't "
|
||||||
|
"have both \"min\" and \"max\" defined - the slider has "
|
||||||
|
"been force-disabled!",
|
||||||
|
key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ret->m_impl->controls.sliderEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
root.checkUnknownKeys();
|
root.checkUnknownKeys();
|
||||||
return root.ok(ret);
|
return root.ok(ret);
|
||||||
}
|
}
|
||||||
|
@ -423,10 +438,10 @@ double FloatSettingV3::getDefaultValue() const {
|
||||||
}
|
}
|
||||||
Result<> FloatSettingV3::isValid(double value) const {
|
Result<> FloatSettingV3::isValid(double value) const {
|
||||||
if (m_impl->minValue && value < *m_impl->minValue) {
|
if (m_impl->minValue && value < *m_impl->minValue) {
|
||||||
return Err("value must be at least {}", *m_impl->minValue);
|
return Err("Value must be at least {}", *m_impl->minValue);
|
||||||
}
|
}
|
||||||
if (m_impl->maxValue && value > *m_impl->maxValue) {
|
if (m_impl->maxValue && value > *m_impl->maxValue) {
|
||||||
return Err("value must be at most {}", *m_impl->maxValue);
|
return Err("Value must be at most {}", *m_impl->maxValue);
|
||||||
}
|
}
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
@ -444,10 +459,10 @@ bool FloatSettingV3::isArrowsEnabled() const {
|
||||||
bool FloatSettingV3::isBigArrowsEnabled() const {
|
bool FloatSettingV3::isBigArrowsEnabled() const {
|
||||||
return m_impl->controls.bigArrowStepSize > 0;
|
return m_impl->controls.bigArrowStepSize > 0;
|
||||||
}
|
}
|
||||||
size_t FloatSettingV3::getArrowStepSize() const {
|
double FloatSettingV3::getArrowStepSize() const {
|
||||||
return m_impl->controls.arrowStepSize;
|
return m_impl->controls.arrowStepSize;
|
||||||
}
|
}
|
||||||
size_t FloatSettingV3::getBigArrowStepSize() const {
|
double FloatSettingV3::getBigArrowStepSize() const {
|
||||||
return m_impl->controls.bigArrowStepSize;
|
return m_impl->controls.bigArrowStepSize;
|
||||||
}
|
}
|
||||||
bool FloatSettingV3::isSliderEnabled() const {
|
bool FloatSettingV3::isSliderEnabled() const {
|
||||||
|
@ -487,8 +502,8 @@ std::optional<Setting> FloatSettingV3::convertToLegacy() const {
|
||||||
.controls = {
|
.controls = {
|
||||||
.arrows = this->isArrowsEnabled(),
|
.arrows = this->isArrowsEnabled(),
|
||||||
.bigArrows = this->isBigArrowsEnabled(),
|
.bigArrows = this->isBigArrowsEnabled(),
|
||||||
.arrowStep = this->getArrowStepSize(),
|
.arrowStep = static_cast<size_t>(this->getArrowStepSize()),
|
||||||
.bigArrowStep = this->getBigArrowStepSize(),
|
.bigArrowStep = static_cast<size_t>(this->getBigArrowStepSize()),
|
||||||
.slider = this->isSliderEnabled(),
|
.slider = this->isSliderEnabled(),
|
||||||
.sliderStep = this->getSliderSnap(),
|
.sliderStep = this->getSliderSnap(),
|
||||||
.input = this->isInputEnabled(),
|
.input = this->isInputEnabled(),
|
||||||
|
@ -538,12 +553,12 @@ std::string StringSettingV3::getDefaultValue() const {
|
||||||
Result<> StringSettingV3::isValid(std::string_view value) const {
|
Result<> StringSettingV3::isValid(std::string_view value) const {
|
||||||
if (m_impl->match) {
|
if (m_impl->match) {
|
||||||
if (!std::regex_match(std::string(value), std::regex(*m_impl->match))) {
|
if (!std::regex_match(std::string(value), std::regex(*m_impl->match))) {
|
||||||
return Err("value must match regex {}", *m_impl->match);
|
return Err("Value must match regex {}", *m_impl->match);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_impl->oneOf) {
|
else if (m_impl->oneOf) {
|
||||||
if (!ranges::contains(*m_impl->oneOf, std::string(value))) {
|
if (!ranges::contains(*m_impl->oneOf, std::string(value))) {
|
||||||
return Err("value must be one of {}", fmt::join(*m_impl->oneOf, ", "));
|
return Err("Value must be one of {}", fmt::join(*m_impl->oneOf, ", "));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok();
|
return Ok();
|
||||||
|
@ -594,6 +609,7 @@ class FileSettingV3::Impl final {
|
||||||
public:
|
public:
|
||||||
std::filesystem::path value;
|
std::filesystem::path value;
|
||||||
std::filesystem::path defaultValue;
|
std::filesystem::path defaultValue;
|
||||||
|
FileType fileType;
|
||||||
std::optional<std::vector<utils::file::FilePickOptions::Filter>> filters;
|
std::optional<std::vector<utils::file::FilePickOptions::Filter>> filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -611,18 +627,31 @@ Result<std::shared_ptr<FileSettingV3>> FileSettingV3::parse(std::string const& k
|
||||||
try {
|
try {
|
||||||
ret->m_impl->defaultValue = fmt::format(
|
ret->m_impl->defaultValue = fmt::format(
|
||||||
fmt::runtime(ret->m_impl->defaultValue.string()),
|
fmt::runtime(ret->m_impl->defaultValue.string()),
|
||||||
fmt::arg("gd-save-dir", dirs::getSaveDir()),
|
fmt::arg("gd_dir", dirs::getGameDir()),
|
||||||
fmt::arg("gd-game-dir", dirs::getGameDir()),
|
fmt::arg("gd_save_dir", dirs::getSaveDir()),
|
||||||
fmt::arg("mod-config-dir", dirs::getModConfigDir() / modID),
|
fmt::arg("mod_config_dir", dirs::getModConfigDir() / modID),
|
||||||
fmt::arg("mod-save-dir", dirs::getModsSaveDir() / modID),
|
fmt::arg("mod_save_dir", dirs::getModsSaveDir() / modID),
|
||||||
fmt::arg("temp-dir", dirs::getTempDir())
|
fmt::arg("temp_dir", dirs::getTempDir())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch(fmt::format_error const&) {
|
catch(fmt::format_error const& e) {
|
||||||
return Err("Invalid format string for file setting path");
|
return Err("Invalid format string for file setting path: {}", e.what());
|
||||||
}
|
}
|
||||||
ret->m_impl->value = ret->m_impl->defaultValue;
|
ret->m_impl->value = ret->m_impl->defaultValue;
|
||||||
|
|
||||||
|
if (auto ty = root.has("filetype")) {
|
||||||
|
ty.assertIsString();
|
||||||
|
switch (hash(ty.template get<std::string>())) {
|
||||||
|
case hash("any"): ret->m_impl->fileType = FileType::Any; break;
|
||||||
|
case hash("file"): ret->m_impl->fileType = FileType::File; break;
|
||||||
|
case hash("folder"): ret->m_impl->fileType = FileType::Folder; break;
|
||||||
|
default: return Err(
|
||||||
|
"Setting '{}' in mod {}: Invalid filetype \"{}\"",
|
||||||
|
key, modID, ty.template get<std::string>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (auto controls = root.has("control")) {
|
if (auto controls = root.has("control")) {
|
||||||
auto filters = std::vector<file::FilePickOptions::Filter>();
|
auto filters = std::vector<file::FilePickOptions::Filter>();
|
||||||
for (auto& item : controls.has("filters").items()) {
|
for (auto& item : controls.has("filters").items()) {
|
||||||
|
@ -647,9 +676,24 @@ std::filesystem::path FileSettingV3::getDefaultValue() const {
|
||||||
return m_impl->defaultValue;
|
return m_impl->defaultValue;
|
||||||
}
|
}
|
||||||
Result<> FileSettingV3::isValid(std::filesystem::path const& value) const {
|
Result<> FileSettingV3::isValid(std::filesystem::path const& value) const {
|
||||||
|
if (m_impl->fileType != FileType::Any) {
|
||||||
|
if (!std::filesystem::exists(value)) {
|
||||||
|
return Err("{} must exist", m_impl->fileType == FileType::File ? "File" : "Folder");
|
||||||
|
}
|
||||||
|
if (m_impl->fileType == FileType::File && !std::filesystem::is_regular_file(value)) {
|
||||||
|
return Err("Value must be a file");
|
||||||
|
}
|
||||||
|
if (m_impl->fileType == FileType::Folder && !std::filesystem::is_directory(value)) {
|
||||||
|
return Err("Value must be a folder");
|
||||||
|
}
|
||||||
|
}
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileSettingV3::FileType FileSettingV3::getFileType() const {
|
||||||
|
return m_impl->fileType;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::vector<utils::file::FilePickOptions::Filter>> FileSettingV3::getFilters() const {
|
std::optional<std::vector<utils::file::FilePickOptions::Filter>> FileSettingV3::getFilters() const {
|
||||||
return m_impl->filters;
|
return m_impl->filters;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue