From dc6637e1306fc9ed024c194078fc75940ace1cad Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Fri, 23 Aug 2024 12:36:49 +0300 Subject: [PATCH] string setting nodes + move number setting nodes to a shared class + legacy custom setting nodes proven to work --- loader/src/loader/SettingNodeV3.cpp | 384 ++++++---------------------- loader/src/loader/SettingNodeV3.hpp | 203 ++++++++++++--- loader/src/loader/SettingV3.cpp | 11 +- 3 files changed, 244 insertions(+), 354 deletions(-) diff --git a/loader/src/loader/SettingNodeV3.cpp b/loader/src/loader/SettingNodeV3.cpp index a8a25cb8..58973ef9 100644 --- a/loader/src/loader/SettingNodeV3.cpp +++ b/loader/src/loader/SettingNodeV3.cpp @@ -1,27 +1,6 @@ #include "SettingNodeV3.hpp" #include -template -static float valueToSlider(std::shared_ptr setting, typename T::ValueType value) { - auto min = setting->getMinValue().value_or(-100); - auto max = setting->getMaxValue().value_or(+100); - auto range = max - min; - return static_cast(clamp(static_cast(value - min) / range, 0.0, 1.0)); -} -template -static typename T::ValueType valueFromSlider(std::shared_ptr setting, float num) { - auto min = setting->getMinValue().value_or(-100); - auto max = setting->getMaxValue().value_or(+100); - auto range = max - min; - auto value = static_cast(num * range + min); - if (auto step = setting->getSliderSnap()) { - value = static_cast( - round(value / *step) * (*step) - ); - } - return value; -} - class SettingNodeSizeChangeEventV3::Impl final { public: SettingNodeV3* node; @@ -71,7 +50,7 @@ bool SettingNodeV3::init(std::shared_ptr setting, float width) { m_impl->setting = setting; m_impl->nameMenu = CCMenu::create(); - m_impl->nameMenu->setContentWidth(width / 2 - 20); + m_impl->nameMenu->setContentWidth(width / 2 + 25); m_impl->nameLabel = CCLabelBMFont::create(setting->getDisplayName().c_str(), "bigFont.fnt"); m_impl->nameLabel->setLayoutOptions(AxisLayoutOptions::create()->setScaleLimits(.1f, .4f)->setScalePriority(1)); @@ -97,8 +76,8 @@ bool SettingNodeV3::init(std::shared_ptr setting, float width) { this->addChildAtPosition(m_impl->nameMenu, Anchor::Left, ccp(10, 0), ccp(0, .5f)); m_impl->buttonMenu = CCMenu::create(); - m_impl->buttonMenu->setContentWidth(width / 2 - 20); - m_impl->buttonMenu->setLayout(RowLayout::create()->setAxisAlignment(AxisAlignment::End)); + m_impl->buttonMenu->setContentSize({ width / 2 - 55, 30 }); + m_impl->buttonMenu->setLayout(AnchorLayout::create()); this->addChildAtPosition(m_impl->buttonMenu, Anchor::Right, ccp(-10, 0), ccp(1, .5f)); this->setAnchorPoint({ .5f, .5f }); @@ -120,7 +99,7 @@ void SettingNodeV3::onDescription(CCObject*) { title.c_str(), m_impl->setting->getDescription().value_or("No description provided"), "OK", nullptr, - clamp(title.size() * 16, 240, 400) + clamp(title.size() * 16, 300, 400) )->show(); } void SettingNodeV3::onReset(CCObject*) { @@ -228,8 +207,10 @@ bool BoolSettingNodeV3::init(std::shared_ptr setting, float width m_toggle->m_offButton->getNormalImage()->setPosition(ccp(25, 25) / 2); m_toggle->m_notClickable = true; m_toggle->toggle(setting->getValue()); - this->getButtonMenu()->addChild(m_toggle); - this->getButtonMenu()->updateLayout(); + this->getButtonMenu()->addChildAtPosition(m_toggle, Anchor::Right, ccp(-10, 0)); + + this->getNameMenu()->setContentWidth(width - 50); + this->getNameMenu()->updateLayout(); this->updateState(); @@ -268,303 +249,75 @@ BoolSettingNodeV3* BoolSettingNodeV3::create(std::shared_ptr sett return nullptr; } -// IntSettingNodeV3 - -bool IntSettingNodeV3::init(std::shared_ptr setting, float width) { - if (!SettingNodeV3::init(setting, width)) - return false; - - auto bigArrowLeftSpr = CCSprite::create(); - auto bigArrowLeftSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - auto bigArrowLeftSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - - bigArrowLeftSpr->setContentSize(bigArrowLeftSpr1->getContentSize() + ccp(20, 0)); - bigArrowLeftSpr->addChildAtPosition(bigArrowLeftSpr2, Anchor::Center, ccp(10, 0)); - bigArrowLeftSpr->addChildAtPosition(bigArrowLeftSpr1, Anchor::Center, ccp(-10, 0)); - bigArrowLeftSpr->setScale(.45f); - - auto bigArrowLeftBtn = CCMenuItemSpriteExtra::create( - bigArrowLeftSpr, this, menu_selector(IntSettingNodeV3::onArrow) - ); - bigArrowLeftBtn->setTag(-setting->getBigArrowStepSize()); - bigArrowLeftBtn->setVisible(setting->isBigArrowsEnabled()); - this->getButtonMenu()->addChild(bigArrowLeftBtn); - - auto arrowLeftSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"); - arrowLeftSpr->setScale(.65f); - auto arrowLeftBtn = CCMenuItemSpriteExtra::create( - arrowLeftSpr, this, menu_selector(IntSettingNodeV3::onArrow) - ); - arrowLeftBtn->setTag(-setting->getArrowStepSize()); - arrowLeftBtn->setVisible(setting->isArrowsEnabled()); - this->getButtonMenu()->addChild(arrowLeftBtn); - - m_input = TextInput::create(width / 2 - 70, "Num"); - m_input->setCallback([this](auto const&) { - this->markChanged(); - }); - if (!setting->isInputEnabled()) { - m_input->getBGSprite()->setVisible(false); - m_input->setEnabled(false); - } - this->getButtonMenu()->addChild(m_input); - - auto arrowRightSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"); - arrowRightSpr->setFlipX(true); - arrowRightSpr->setScale(.65f); - auto arrowRightBtn = CCMenuItemSpriteExtra::create( - arrowRightSpr, this, menu_selector(IntSettingNodeV3::onArrow) - ); - arrowRightBtn->setTag(setting->getArrowStepSize()); - arrowRightBtn->setVisible(setting->isArrowsEnabled()); - this->getButtonMenu()->addChild(arrowRightBtn); - - auto bigArrowRightSpr = CCSprite::create(); - auto bigArrowRightSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - bigArrowRightSpr1->setFlipX(true); - auto bigArrowRightSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - bigArrowRightSpr2->setFlipX(true); - - bigArrowRightSpr->setContentSize(bigArrowRightSpr1->getContentSize() + ccp(20, 0)); - bigArrowRightSpr->addChildAtPosition(bigArrowRightSpr1, Anchor::Center, ccp(-10, 0)); - bigArrowRightSpr->addChildAtPosition(bigArrowRightSpr2, Anchor::Center, ccp(10, 0)); - bigArrowRightSpr->setScale(.45f); - - auto bigArrowRightBtn = CCMenuItemSpriteExtra::create( - bigArrowRightSpr, this, menu_selector(IntSettingNodeV3::onArrow) - ); - bigArrowRightBtn->setTag(setting->getBigArrowStepSize()); - bigArrowRightBtn->setVisible(setting->isBigArrowsEnabled()); - this->getButtonMenu()->addChild(bigArrowRightBtn); - - if (setting->isSliderEnabled()) { - this->setContentHeight(45); - this->getButtonMenu()->updateAnchoredPosition(Anchor::Right, ccp(0, 7)); - - m_slider = Slider::create(this, menu_selector(IntSettingNodeV3::onSlider)); - m_slider->setScale(.5f); - this->addChildAtPosition(m_slider, Anchor::Right, ccp(-75, -12), ccp(0, 0)); - } - - this->setCurrentValue(setting->getValue()); - this->getButtonMenu()->updateLayout(); - this->updateState(); - - return true; -} - -void IntSettingNodeV3::updateState() { - SettingNodeV3::updateState(); - m_slider->m_touchLogic->m_thumb->setValue(valueToSlider( - this->getSetting(), this->getCurrentValue() - )); - m_slider->updateBar(); -} - -int64_t IntSettingNodeV3::getCurrentValue() const { - return numFromString(m_input->getString()).value_or(this->getSetting()->getDefaultValue()); -} -void IntSettingNodeV3::setCurrentValue(int64_t value) { - m_input->setString(std::to_string(value)); - this->markChanged(); -} - -void IntSettingNodeV3::onCommit() { - this->getSetting()->setValue(this->getCurrentValue()); -} -void IntSettingNodeV3::onArrow(CCObject* sender) { - this->setCurrentValue(this->getCurrentValue() + sender->getTag()); - this->updateState(); -} -void IntSettingNodeV3::onSlider(CCObject* sender) { - this->setCurrentValue(valueFromSlider( - this->getSetting(), - m_slider->m_touchLogic->m_thumb->getValue() - )); -} - -bool IntSettingNodeV3::hasUncommittedChanges() const { - return this->getSetting()->getValue() != this->getCurrentValue(); -} -bool IntSettingNodeV3::hasNonDefaultValue() const { - return this->getSetting()->getDefaultValue() != this->getCurrentValue(); -} -void IntSettingNodeV3::onResetToDefault() { - this->setCurrentValue(this->getSetting()->getDefaultValue()); -} - -std::shared_ptr IntSettingNodeV3::getSetting() const { - return std::static_pointer_cast(SettingNodeV3::getSetting()); -} - -IntSettingNodeV3* IntSettingNodeV3::create(std::shared_ptr setting, float width) { - auto ret = new IntSettingNodeV3(); - if (ret && ret->init(setting, width)) { - ret->autorelease(); - return ret; - } - CC_SAFE_DELETE(ret); - return nullptr; -} - -// FloatSettingNodeV3 - -bool FloatSettingNodeV3::init(std::shared_ptr setting, float width) { - if (!SettingNodeV3::init(setting, width)) - return false; - - auto bigArrowLeftSpr = CCSprite::create(); - auto bigArrowLeftSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - auto bigArrowLeftSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - - bigArrowLeftSpr->setContentSize(bigArrowLeftSpr1->getContentSize() + ccp(20, 0)); - bigArrowLeftSpr->addChildAtPosition(bigArrowLeftSpr2, Anchor::Center, ccp(10, 0)); - bigArrowLeftSpr->addChildAtPosition(bigArrowLeftSpr1, Anchor::Center, ccp(-10, 0)); - bigArrowLeftSpr->setScale(.45f); - - auto bigArrowLeftBtn = CCMenuItemSpriteExtra::create( - bigArrowLeftSpr, this, menu_selector(FloatSettingNodeV3::onArrow) - ); - bigArrowLeftBtn->setTag(-setting->getBigArrowStepSize()); - bigArrowLeftBtn->setVisible(setting->isBigArrowsEnabled()); - this->getButtonMenu()->addChild(bigArrowLeftBtn); - - auto arrowLeftSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"); - arrowLeftSpr->setScale(.65f); - auto arrowLeftBtn = CCMenuItemSpriteExtra::create( - arrowLeftSpr, this, menu_selector(FloatSettingNodeV3::onArrow) - ); - arrowLeftBtn->setTag(-setting->getArrowStepSize()); - arrowLeftBtn->setVisible(setting->isArrowsEnabled()); - this->getButtonMenu()->addChild(arrowLeftBtn); - - m_input = TextInput::create(width / 2 - 70, "Num"); - m_input->setCallback([this](auto const&) { - this->markChanged(); - }); - if (!setting->isInputEnabled()) { - m_input->getBGSprite()->setVisible(false); - m_input->setEnabled(false); - } - this->getButtonMenu()->addChild(m_input); - - auto arrowRightSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"); - arrowRightSpr->setFlipX(true); - arrowRightSpr->setScale(.65f); - auto arrowRightBtn = CCMenuItemSpriteExtra::create( - arrowRightSpr, this, menu_selector(FloatSettingNodeV3::onArrow) - ); - arrowRightBtn->setTag(setting->getArrowStepSize()); - arrowRightBtn->setVisible(setting->isArrowsEnabled()); - this->getButtonMenu()->addChild(arrowRightBtn); - - auto bigArrowRightSpr = CCSprite::create(); - auto bigArrowRightSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - bigArrowRightSpr1->setFlipX(true); - auto bigArrowRightSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); - bigArrowRightSpr2->setFlipX(true); - - bigArrowRightSpr->setContentSize(bigArrowRightSpr1->getContentSize() + ccp(20, 0)); - bigArrowRightSpr->addChildAtPosition(bigArrowRightSpr1, Anchor::Center, ccp(-10, 0)); - bigArrowRightSpr->addChildAtPosition(bigArrowRightSpr2, Anchor::Center, ccp(10, 0)); - bigArrowRightSpr->setScale(.45f); - - auto bigArrowRightBtn = CCMenuItemSpriteExtra::create( - bigArrowRightSpr, this, menu_selector(FloatSettingNodeV3::onArrow) - ); - bigArrowRightBtn->setTag(setting->getBigArrowStepSize()); - bigArrowRightBtn->setVisible(setting->isBigArrowsEnabled()); - this->getButtonMenu()->addChild(bigArrowRightBtn); - - if (setting->isSliderEnabled()) { - this->setContentHeight(45); - this->getButtonMenu()->updateAnchoredPosition(Anchor::Right, ccp(0, 7)); - - m_slider = Slider::create(this, menu_selector(FloatSettingNodeV3::onSlider)); - m_slider->setScale(.5f); - this->addChildAtPosition(m_slider, Anchor::Right, ccp(-75, -12), ccp(0, 0)); - } - - this->setCurrentValue(setting->getValue()); - this->getButtonMenu()->updateLayout(); - this->updateState(); - - return true; -} - -void FloatSettingNodeV3::updateState() { - SettingNodeV3::updateState(); - m_slider->m_touchLogic->m_thumb->setValue(valueToSlider( - this->getSetting(), this->getCurrentValue() - )); - m_slider->updateBar(); -} - -double FloatSettingNodeV3::getCurrentValue() const { - return numFromString(m_input->getString()).value_or(this->getSetting()->getDefaultValue()); -} -void FloatSettingNodeV3::setCurrentValue(double value) { - m_input->setString(numToString(value)); -} - -void FloatSettingNodeV3::onCommit() { - this->getSetting()->setValue(this->getCurrentValue()); -} -void FloatSettingNodeV3::onArrow(CCObject* sender) { - this->setCurrentValue(this->getCurrentValue() + sender->getTag()); - this->updateState(); -} -void FloatSettingNodeV3::onSlider(CCObject* sender) { - this->setCurrentValue(valueFromSlider( - this->getSetting(), - m_slider->m_touchLogic->m_thumb->getValue() - )); -} - -bool FloatSettingNodeV3::hasUncommittedChanges() const { - return this->getSetting()->getValue() != this->getCurrentValue(); -} -bool FloatSettingNodeV3::hasNonDefaultValue() const { - return this->getSetting()->getDefaultValue() != this->getCurrentValue(); -} -void FloatSettingNodeV3::onResetToDefault() { - this->setCurrentValue(this->getSetting()->getDefaultValue()); -} - -std::shared_ptr FloatSettingNodeV3::getSetting() const { - return std::static_pointer_cast(SettingNodeV3::getSetting()); -} - -FloatSettingNodeV3* FloatSettingNodeV3::create(std::shared_ptr setting, float width) { - auto ret = new FloatSettingNodeV3(); - if (ret && ret->init(setting, width)) { - ret->autorelease(); - return ret; - } - CC_SAFE_DELETE(ret); - return nullptr; -} - // StringSettingNodeV3 bool StringSettingNodeV3::init(std::shared_ptr setting, float width) { if (!SettingNodeV3::init(setting, width)) return false; + + m_input = TextInput::create(width / 2 - 50, "Num"); + m_input->setCallback([this](auto const&) { + this->markChanged(); + }); + m_input->setScale(.7f); + m_input->setString(this->getSetting()->getValue()); + this->getButtonMenu()->addChildAtPosition(m_input, Anchor::Center); - // todo + if (setting->getEnumOptions()) { + m_input->getBGSprite()->setVisible(false); + m_input->setEnabled(false); + m_input->getInputNode()->m_placeholderLabel->setOpacity(255); + m_input->getInputNode()->m_placeholderLabel->setColor(ccWHITE); + + auto arrowLeftSpr = CCSprite::createWithSpriteFrameName("navArrowBtn_001.png"); + arrowLeftSpr->setFlipX(true); + arrowLeftSpr->setScale(.4f); + auto arrowLeftBtn = CCMenuItemSpriteExtra::create( + arrowLeftSpr, this, menu_selector(StringSettingNodeV3::onArrow) + ); + arrowLeftBtn->setTag(-1); + this->getButtonMenu()->addChildAtPosition(arrowLeftBtn, Anchor::Left, ccp(5, 0)); + + auto arrowRightSpr = CCSprite::createWithSpriteFrameName("navArrowBtn_001.png"); + arrowRightSpr->setScale(.4f); + auto arrowRightBtn = CCMenuItemSpriteExtra::create( + arrowRightSpr, this, menu_selector(StringSettingNodeV3::onArrow) + ); + arrowRightBtn->setTag(1); + this->getButtonMenu()->addChildAtPosition(arrowRightBtn, Anchor::Right, ccp(-5, 0)); + } + + this->updateState(); return true; } -void StringSettingNodeV3::onCommit() {} +void StringSettingNodeV3::onArrow(CCObject* sender) { + auto options = *this->getSetting()->getEnumOptions(); + auto index = ranges::indexOf(options, m_input->getString()).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(); +} + +void StringSettingNodeV3::onCommit() { + this->getSetting()->setValue(m_input->getString()); +} bool StringSettingNodeV3::hasUncommittedChanges() const { - return false; + return m_input->getString() != this->getSetting()->getValue(); } bool StringSettingNodeV3::hasNonDefaultValue() const { - return false; + return m_input->getString() != this->getSetting()->getDefaultValue(); +} +void StringSettingNodeV3::onResetToDefault() { + m_input->setString(this->getSetting()->getDefaultValue()); } -void StringSettingNodeV3::onResetToDefault() {} std::shared_ptr StringSettingNodeV3::getSetting() const { return std::static_pointer_cast(SettingNodeV3::getSetting()); @@ -732,14 +485,25 @@ UnresolvedCustomSettingNodeV3* UnresolvedCustomSettingNodeV3::create(std::shared bool LegacyCustomSettingToV3Node::init(std::shared_ptr original, float width) { if (!SettingNodeV3::init(original, width)) return false; + + this->getNameMenu()->setVisible(false); + this->getButtonMenu()->setVisible(false); m_original = original->getValue()->createNode(width); + m_original->setDelegate(this); this->setContentSize({ width, m_original->getContentHeight() }); - this->addChildAtPosition(m_original, Anchor::Center); + this->addChildAtPosition(m_original, Anchor::BottomLeft, ccp(0, 0), ccp(0, 0)); return true; } +void LegacyCustomSettingToV3Node::settingValueChanged(SettingNode*) { + SettingNodeValueChangeEventV3(false).post(); +} +void LegacyCustomSettingToV3Node::settingValueCommitted(SettingNode*) { + SettingNodeValueChangeEventV3(true).post(); +} + void LegacyCustomSettingToV3Node::onCommit() { m_original->commit(); } diff --git a/loader/src/loader/SettingNodeV3.hpp b/loader/src/loader/SettingNodeV3.hpp index 419522ba..09458b9a 100644 --- a/loader/src/loader/SettingNodeV3.hpp +++ b/loader/src/loader/SettingNodeV3.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include using namespace geode::prelude; @@ -44,64 +45,182 @@ public: std::shared_ptr getSetting() const; }; -class IntSettingNodeV3 : public SettingNodeV3 { +template +class NumberSettingNodeV3 : public SettingNodeV3 { protected: + using ValueType = typename S::ValueType; + TextInput* m_input; Slider* m_slider; - bool init(std::shared_ptr setting, float width); + float valueToSlider(ValueType value) { + auto min = this->getSetting()->getMinValue().value_or(-100); + auto max = this->getSetting()->getMaxValue().value_or(+100); + auto range = max - min; + return static_cast(clamp(static_cast(value - min) / range, 0.0, 1.0)); + } + ValueType valueFromSlider(float num) { + auto min = this->getSetting()->getMinValue().value_or(-100); + auto max = this->getSetting()->getMaxValue().value_or(+100); + auto range = max - min; + auto value = static_cast(num * range + min); + if (auto step = this->getSetting()->getSliderSnap()) { + value = static_cast(round(value / *step) * (*step)); + } + return value; + } - void updateState() override; + bool init(std::shared_ptr setting, float width) { + if (!SettingNodeV3::init(setting, width)) + return false; - void onCommit() override; - void onArrow(CCObject* sender); - void onSlider(CCObject*); + auto bigArrowLeftSpr = CCSprite::create(); + auto bigArrowLeftSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); + auto bigArrowLeftSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); + + bigArrowLeftSpr->setContentSize(bigArrowLeftSpr1->getContentSize() + ccp(20, 0)); + bigArrowLeftSpr->addChildAtPosition(bigArrowLeftSpr2, Anchor::Center, ccp(10, 0)); + bigArrowLeftSpr->addChildAtPosition(bigArrowLeftSpr1, Anchor::Center, ccp(-10, 0)); + bigArrowLeftSpr->setScale(.3f); - int64_t getCurrentValue() const; - void setCurrentValue(int64_t value); + auto bigArrowLeftBtn = CCMenuItemSpriteExtra::create( + bigArrowLeftSpr, this, menu_selector(NumberSettingNodeV3::onArrow) + ); + bigArrowLeftBtn->setTag(-setting->getBigArrowStepSize()); + bigArrowLeftBtn->setVisible(setting->isBigArrowsEnabled()); + this->getButtonMenu()->addChildAtPosition(bigArrowLeftBtn, Anchor::Left, ccp(5, 0)); + + auto arrowLeftSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"); + arrowLeftSpr->setScale(.5f); + auto arrowLeftBtn = CCMenuItemSpriteExtra::create( + arrowLeftSpr, this, menu_selector(NumberSettingNodeV3::onArrow) + ); + arrowLeftBtn->setTag(-setting->getArrowStepSize()); + arrowLeftBtn->setVisible(setting->isArrowsEnabled()); + this->getButtonMenu()->addChildAtPosition(arrowLeftBtn, Anchor::Left, ccp(22, 0)); + + m_input = TextInput::create(this->getButtonMenu()->getContentWidth() - 40, "Num"); + m_input->setScale(.7f); + m_input->setCallback([this](auto const&) { + this->markChanged(); + }); + if (!setting->isInputEnabled()) { + m_input->getBGSprite()->setVisible(false); + m_input->setEnabled(false); + m_input->getInputNode()->m_placeholderLabel->setOpacity(255); + m_input->getInputNode()->m_placeholderLabel->setColor(ccWHITE); + } + this->getButtonMenu()->addChildAtPosition(m_input, Anchor::Center); + + auto arrowRightSpr = CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"); + arrowRightSpr->setFlipX(true); + arrowRightSpr->setScale(.5f); + auto arrowRightBtn = CCMenuItemSpriteExtra::create( + arrowRightSpr, this, menu_selector(NumberSettingNodeV3::onArrow) + ); + arrowRightBtn->setTag(setting->getArrowStepSize()); + arrowRightBtn->setVisible(setting->isArrowsEnabled()); + this->getButtonMenu()->addChildAtPosition(arrowRightBtn, Anchor::Right, ccp(-22, 0)); + + auto bigArrowRightSpr = CCSprite::create(); + auto bigArrowRightSpr1 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); + bigArrowRightSpr1->setFlipX(true); + auto bigArrowRightSpr2 = CCSprite::createWithSpriteFrameName("GJ_arrow_03_001.png"); + bigArrowRightSpr2->setFlipX(true); + + bigArrowRightSpr->setContentSize(bigArrowRightSpr1->getContentSize() + ccp(20, 0)); + bigArrowRightSpr->addChildAtPosition(bigArrowRightSpr1, Anchor::Center, ccp(-10, 0)); + bigArrowRightSpr->addChildAtPosition(bigArrowRightSpr2, Anchor::Center, ccp(10, 0)); + bigArrowRightSpr->setScale(.3f); + + auto bigArrowRightBtn = CCMenuItemSpriteExtra::create( + bigArrowRightSpr, this, menu_selector(NumberSettingNodeV3::onArrow) + ); + bigArrowRightBtn->setTag(setting->getBigArrowStepSize()); + bigArrowRightBtn->setVisible(setting->isBigArrowsEnabled()); + this->getButtonMenu()->addChildAtPosition(bigArrowRightBtn, Anchor::Right, ccp(-5, 0)); + + if (setting->isSliderEnabled()) { + this->setContentHeight(45); + this->getButtonMenu()->updateAnchoredPosition(Anchor::Right, ccp(-10, 7)); + + m_slider = Slider::create(this, menu_selector(NumberSettingNodeV3::onSlider)); + m_slider->setScale(.5f); + this->getButtonMenu()->addChildAtPosition(m_slider, Anchor::Center, ccp(0, -20), ccp(0, 0)); + } + + this->setCurrentValue(setting->getValue()); + this->updateState(); + + return true; + } + + void updateState() override { + SettingNodeV3::updateState(); + if (m_slider) { + m_slider->m_touchLogic->m_thumb->setValue(this->valueToSlider(this->getCurrentValue())); + m_slider->updateBar(); + } + } + + void onCommit() override { + this->getSetting()->setValue(this->getCurrentValue()); + } + void onArrow(CCObject* sender) { + this->setCurrentValue(this->getCurrentValue() + sender->getTag()); + } + void onSlider(CCObject*) { + this->setCurrentValue(this->valueFromSlider(m_slider->m_touchLogic->m_thumb->getValue())); + } + + ValueType getCurrentValue() const { + return numFromString(m_input->getString()) + .value_or(this->getSetting()->getDefaultValue()); + } + void setCurrentValue(ValueType value) { + m_input->setString(numToString(value)); + this->markChanged(); + } public: - static IntSettingNodeV3* create(std::shared_ptr setting, float width); + static NumberSettingNodeV3* create(std::shared_ptr setting, float width) { + auto ret = new NumberSettingNodeV3(); + if (ret && ret->init(setting, width)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; + } - bool hasUncommittedChanges() const override; - bool hasNonDefaultValue() const override; - void onResetToDefault() override; + bool hasUncommittedChanges() const override { + return this->getSetting()->getValue() != this->getCurrentValue(); + } + bool hasNonDefaultValue() const override { + return this->getSetting()->getDefaultValue() != this->getCurrentValue(); + } + void onResetToDefault() override { + this->setCurrentValue(this->getSetting()->getDefaultValue()); + } - std::shared_ptr getSetting() const; + std::shared_ptr getSetting() const { + return std::static_pointer_cast(SettingNodeV3::getSetting()); + } }; -class FloatSettingNodeV3 : public SettingNodeV3 { -protected: - TextInput* m_input; - Slider* m_slider; - - bool init(std::shared_ptr setting, float width); - - void updateState() override; - - void onCommit() override; - void onArrow(CCObject* sender); - void onSlider(CCObject*); - - double getCurrentValue() const; - void setCurrentValue(double value); - -public: - static FloatSettingNodeV3* create(std::shared_ptr setting, float width); - - bool hasUncommittedChanges() const override; - bool hasNonDefaultValue() const override; - void onResetToDefault() override; - - std::shared_ptr getSetting() const; -}; +using IntSettingNodeV3 = NumberSettingNodeV3; +using FloatSettingNodeV3 = NumberSettingNodeV3; class StringSettingNodeV3 : public SettingNodeV3 { protected: + TextInput* m_input; + bool init(std::shared_ptr setting, float width); void onCommit() override; + void onArrow(CCObject* sender); + public: static StringSettingNodeV3* create(std::shared_ptr setting, float width); @@ -176,9 +295,10 @@ public: std::shared_ptr getSetting() const; }; -// If these classes do get exposed in headers, this SHOULD NOT BE EXPOSED!!!!!! DO NOT DO THAT!!!! +// If these classes do get exposed in headers, +// LegacyCustomSettingToV3Node SHOULD NOT BE EXPOSED!!!!!! DO NOT DO THAT!!!! -class LegacyCustomSettingToV3Node : public SettingNodeV3 { +class LegacyCustomSettingToV3Node : public SettingNodeV3, public SettingNodeDelegate { protected: SettingNode* m_original; @@ -186,6 +306,9 @@ protected: void onCommit() override; + void settingValueChanged(SettingNode*) override; + void settingValueCommitted(SettingNode*) override; + public: static LegacyCustomSettingToV3Node* create(std::shared_ptr original, float width); diff --git a/loader/src/loader/SettingV3.cpp b/loader/src/loader/SettingV3.cpp index d44574a7..6c7390f1 100644 --- a/loader/src/loader/SettingV3.cpp +++ b/loader/src/loader/SettingV3.cpp @@ -364,11 +364,11 @@ public: struct { // 0 means not enabled - size_t arrowStepSize; - size_t bigArrowStepSize; - bool sliderEnabled; + size_t arrowStepSize = 1; + size_t bigArrowStepSize = 5; + bool sliderEnabled = true; std::optional sliderSnap; - bool textInputEnabled; + bool textInputEnabled = true; } controls; }; @@ -521,6 +521,9 @@ Result> StringSettingV3::parse(std::string cons root.has("match").into(ret->m_impl->match); root.has("filter").into(ret->m_impl->filter); root.has("one-of").into(ret->m_impl->oneOf); + if (ret->m_impl->oneOf && ret->m_impl->oneOf->empty()) { + return Err("Setting '{}' in mod {} - \"one-of\" may not be empty!", key, modID); + } root.checkUnknownKeys(); return root.ok(ret);