mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-14 19:15:05 -05:00
Merge branch 'main' of https://github.com/geode-sdk/geode into main
This commit is contained in:
commit
e7f82381a1
15 changed files with 283 additions and 280 deletions
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
@ -17,12 +17,12 @@ jobs:
|
|||
os: windows-2019
|
||||
prefixes: ''
|
||||
extra_flags: '-G "Visual Studio 16 2019" -T host=x86 -A win32'
|
||||
out_paths: './bin/nightly/geode.dll ./bin/nightly/geode.lib ./bin/nightly/XInput9_1_0.dll'
|
||||
out_paths: './bin/nightly/geode.dll ./bin/nightly/GeodeBootstrapper.dll ./bin/nightly/geode.lib ./bin/nightly/XInput9_1_0.dll'
|
||||
- name: "macOS"
|
||||
os: macos-latest
|
||||
prefixes: 'PATH="/usr/local/opt/ccache/libexec:$PATH"'
|
||||
extra_flags: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON"
|
||||
out_paths: './bin/nightly/Geode.dylib'
|
||||
out_paths: './bin/nightly/Geode.dylib ./bin/nightly/GeodeBootstrapper.dylib'
|
||||
name: ${{ matrix.config.name }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
|
|
|
@ -573,7 +573,7 @@ class CCTextInputNode : cocos2d::CCLayer, cocos2d::CCIMEDelegate, cocos2d::CCTex
|
|||
bool init(float width, float height, const char* caption, const char* thonburi, int maxCharCount, const char* font) = mac 0x5d180, win 0x20e50, ios 0xe261c;
|
||||
|
||||
void refreshLabel() = mac 0x5d730, win 0x21330, ios 0xe2af4;
|
||||
void updateLabel(gd::string) = mac 0x5d4a0, win 0x0, ios 0x0;
|
||||
void updateLabel(gd::string) = mac 0x5d4a0, win 0x21190, ios 0x0;
|
||||
void updateBlinkLabel() = mac 0x5d920;
|
||||
virtual void registerWithTouchDispatcher() = mac 0x5eec0, win 0x220e0, ios 0x0;
|
||||
virtual void visit() = mac 0x5d380, win 0x21000, ios 0x0;
|
||||
|
@ -691,7 +691,7 @@ class ColorSelectDelegate {
|
|||
}
|
||||
|
||||
class ColorSelectLiveOverlay : FLAlertLayer {
|
||||
bool init(ColorAction*, ColorAction*, EffectGameObject*) = mac 0x2e2790;
|
||||
bool init(ColorAction*, ColorAction*, EffectGameObject*) = mac 0x2e2790, win 0x41db0;
|
||||
void sliderChanged(cocos2d::CCObject*) = mac 0x2e3830;
|
||||
EffectGameObject* m_effectGameObject;
|
||||
cocos2d::CCArray* m_barSprites;
|
||||
|
@ -707,7 +707,7 @@ class ColorSelectPopup : FLAlertLayer, cocos2d::extension::ColorPickerDelegate,
|
|||
bool init(EffectGameObject* triggerObj, cocos2d::CCArray* triggerObjs, ColorAction* colorAction) = mac 0x41ee70, win 0x43ae0, ios 0x0;
|
||||
void updateColorValue() = mac 0x0, win 0x46f30, ios 0x0;
|
||||
void updateCopyColorTextInputLabel() = mac 0x0, win 0x479c0, ios 0x0;
|
||||
void closeColorSelect(cocos2d::CCObject* sender) = mac 0x421af0;
|
||||
void closeColorSelect(cocos2d::CCObject* sender) = mac 0x421af0, win 0x46d80;
|
||||
|
||||
cocos2d::extension::CCControlColourPicker* m_colorPicker;
|
||||
cocos2d::CCLabelBMFont* m_unk1DC;
|
||||
|
@ -2766,10 +2766,10 @@ class GameManager : GManager {
|
|||
bool getGameVariable(const char*) = mac 0x1cccd0, win 0xc9d30, ios 0x0;
|
||||
int getIntGameVariable(const char*) = mac 0x1cd1d0, win 0xca330, ios 0x0;
|
||||
bool getUGV(const char*) = mac 0x1ccfa0, win 0xca0d0, ios 0x0;
|
||||
void loadBackground(int) = mac 0x1cc820;
|
||||
void loadBackground(int) = mac 0x1cc820, win 0xc9990;
|
||||
void loadDeathEffect(int) = mac 0x1cc690, win 0x0, ios 0x0;
|
||||
void loadFont(int) = mac 0x1cc550, win 0x0, ios 0x0;
|
||||
void loadGround(int) = mac 0x1cc8e0;
|
||||
void loadFont(int) = mac 0x1cc550, win 0xc9770, ios 0x0;
|
||||
void loadGround(int) = mac 0x1cc8e0, win 0xc9a50;
|
||||
void reloadAll(bool, bool, bool) = mac 0x1d08a0, win 0xce950, ios 0x0;
|
||||
void reloadAllStep2() = mac 0x1d0940, win 0xce9e0, ios 0x23b1f4;
|
||||
void reloadAllStep5() = mac 0x1d0b00, win 0x0, ios 0x0;
|
||||
|
@ -3799,8 +3799,8 @@ class LevelSettingsObject : cocos2d::CCNode {
|
|||
virtual ~LevelSettingsObject() = mac 0xa5650, win 0x16e800, ios 0x0;
|
||||
virtual bool init() = mac 0xa5690, win 0x16e940, ios 0x0;
|
||||
static LevelSettingsObject* create() = mac 0x92760, win 0x16e8a0, ios 0x0;
|
||||
static LevelSettingsObject* objectFromDict(cocos2d::CCDictionary*) = mac 0xa5810, win 0x0, ios 0x0;
|
||||
static LevelSettingsObject* objectFromString(gd::string) = mac 0x945a0, win 0x0, ios 0x0;
|
||||
static LevelSettingsObject* objectFromDict(cocos2d::CCDictionary*) = mac 0xa5810, win 0x16f4d0, ios 0x0;
|
||||
static LevelSettingsObject* objectFromString(gd::string) = mac 0x945a0, win 0x16f440, ios 0x0;
|
||||
void setupColorsFromLegacyMode(cocos2d::CCDictionary*) = mac 0xa6a30, win 0x170050, ios 0x0;
|
||||
|
||||
gd::string getSaveString() = mac 0x979c0, win 0x16ebf0;
|
||||
|
|
|
@ -41,11 +41,17 @@ function(create_geode_file proname)
|
|||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Creating geode file for ${proname}")
|
||||
|
||||
# what is this for
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mod.json ${CMAKE_CURRENT_BINARY_DIR}/what.txt)
|
||||
set_target_properties(${proname} PROPERTIES CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/mod.json)
|
||||
|
||||
if(GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
|
||||
message(WARNING "create_geode_file called, but Geode CLI was not found - You will need to manually package the .geode files")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Creating geode file for ${proname}")
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GEODE_CLI} package get-id ${CMAKE_CURRENT_SOURCE_DIR} --raw
|
||||
OUTPUT_VARIABLE MOD_ID
|
||||
|
@ -53,16 +59,11 @@ function(create_geode_file proname)
|
|||
|
||||
set_target_properties(${proname} PROPERTIES PREFIX "")
|
||||
set_target_properties(${proname} PROPERTIES OUTPUT_NAME ${MOD_ID})
|
||||
|
||||
if(GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
|
||||
message(WARNING "create_geode_file called, but Geode CLI was not found - You will need to manually package the .geode files")
|
||||
else()
|
||||
add_custom_target(${proname}_PACKAGE ALL
|
||||
DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json
|
||||
COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} --binary $<TARGET_FILE:${proname}> --output $<TARGET_FILE_DIR:${proname}>/${proname}.geode --install
|
||||
VERBATIM USES_TERMINAL
|
||||
)
|
||||
endif()
|
||||
add_custom_target(${proname}_PACKAGE ALL
|
||||
DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json
|
||||
COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} --binary $<TARGET_FILE:${proname}> --output $<TARGET_FILE_DIR:${proname}>/${proname}.geode --install
|
||||
VERBATIM USES_TERMINAL
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(package_geode_resources proname src dest)
|
||||
|
|
|
@ -155,6 +155,10 @@ namespace geode {
|
|||
return m_name;
|
||||
}
|
||||
|
||||
std::string getDisplayName() const {
|
||||
return m_name.value_or(m_key);
|
||||
}
|
||||
|
||||
std::optional<std::string> getDescription() const {
|
||||
return m_description;
|
||||
}
|
||||
|
|
|
@ -171,8 +171,8 @@ namespace geode::cocos {
|
|||
GEODE_DLL bool fileExistsInSearchPaths(const char* filename);
|
||||
|
||||
|
||||
template <class T>
|
||||
struct GEODE_DLL CCArrayIterator {
|
||||
template <typename T>
|
||||
struct CCArrayIterator {
|
||||
public:
|
||||
CCArrayIterator(T* p) : m_ptr(p) {}
|
||||
T* m_ptr;
|
||||
|
@ -416,69 +416,6 @@ namespace geode::cocos {
|
|||
return m_dict->allKeys(key)->count();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R, typename ...Args>
|
||||
class SelectorWrapperImpl : public cocos2d::CCObject {
|
||||
protected:
|
||||
std::function<R(Args...)> m_inner;
|
||||
public:
|
||||
static SelectorWrapperImpl<R, Args...>* create(std::function<R(Args...)> fn) {
|
||||
auto ret = new SelectorWrapperImpl<R, Args...>();
|
||||
ret->m_inner = fn;
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
|
||||
R invoke(Args... args) {
|
||||
return m_inner(args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename R, typename ...Args>
|
||||
class SelectorWrapper {
|
||||
protected:
|
||||
using Target = SelectorWrapperImpl<R, Args...>;
|
||||
bool m_tied;
|
||||
Target* m_impl;
|
||||
public:
|
||||
SelectorWrapper(std::function<R(Args...)> fn) {
|
||||
m_impl = Target::create(fn);
|
||||
m_impl->retain();
|
||||
}
|
||||
|
||||
~SelectorWrapper() {
|
||||
if (!m_tied)
|
||||
m_impl->release();
|
||||
}
|
||||
|
||||
Target* target() {
|
||||
return m_impl;
|
||||
}
|
||||
|
||||
auto selector() {
|
||||
return reinterpret_cast<R(cocos2d::CCObject::*)(Args...)>(&Target::invoke);
|
||||
}
|
||||
|
||||
SelectorWrapper<R, Args...>& leak() {
|
||||
m_impl->retain();
|
||||
return *this;
|
||||
}
|
||||
|
||||
SelectorWrapper<R, Args...> tieToNode(cocos2d::CCNode* node) {
|
||||
if (!m_tied) {
|
||||
node->addChild(m_impl);
|
||||
m_impl->release();
|
||||
m_tied = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
auto selectorFromFn(std::function<F> fn) {
|
||||
return SelectorWrapper(fn);
|
||||
}
|
||||
|
||||
// namespace for storing implementation stuff for
|
||||
// inline member functions
|
||||
|
@ -499,6 +436,9 @@ namespace geode::cocos {
|
|||
m_lambda.~F();
|
||||
}
|
||||
}
|
||||
LambdaHolder(F&& func) {
|
||||
this->assign(std::forward<F>(func));
|
||||
}
|
||||
Ret operator()(Args... args) {
|
||||
if (m_assigned) {
|
||||
return m_lambda(std::forward<Args>(args)...);
|
||||
|
@ -531,13 +471,18 @@ namespace geode::cocos {
|
|||
|
||||
template<class Base, class Func, class... Args>
|
||||
struct InlineMemberFunction<Base, Func, std::tuple<Args...>> : public Base {
|
||||
// this class isn't instantiated anywhere, and is
|
||||
// just used as a proxy to redirect the member function
|
||||
// to the lambda
|
||||
static inline LambdaHolder<Func, typename ExtractLambda<Func>::Ret, Args...> s_selector {};
|
||||
typename ExtractLambda<Func>::Ret onSelector(Args... args) {
|
||||
using Ret = typename ExtractLambda<Func>::Ret;
|
||||
using Selector = Ret(Base::*)(Args...);
|
||||
using Holder = LambdaHolder<Func, Ret, Args...>;
|
||||
|
||||
static inline Holder s_selector {};
|
||||
Ret selector(Args... args) {
|
||||
return s_selector(std::forward<Args>(args)...);
|
||||
}
|
||||
static Selector get(Func&& function) {
|
||||
s_selector.assign(std::move(function));
|
||||
return static_cast<Selector>(&InlineMemberFunction::selector);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -554,9 +499,14 @@ namespace geode::cocos {
|
|||
* same captured values.
|
||||
*/
|
||||
template<class Base, class Func>
|
||||
[[deprecated(
|
||||
"Due to too many implementation problems, "
|
||||
"makeMemberFunction will be removed in the future."
|
||||
)]]
|
||||
static auto makeMemberFunction(Func&& function) {
|
||||
InlineMemberFunction<Base, Func, typename ExtractLambda<Func>::Params>::s_selector.assign(std::move(function));
|
||||
return &InlineMemberFunction<Base, Func, typename ExtractLambda<Func>::Params>::onSelector;
|
||||
return InlineMemberFunction<
|
||||
Base, Func, typename ExtractLambda<Func>::Params
|
||||
>::get(std::move(function));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -566,16 +516,22 @@ namespace geode::cocos {
|
|||
* for even more concise code.
|
||||
*
|
||||
* Do note that due to implementation problems, captures may have
|
||||
* unexpected side-effects. In practice, lambda member functions with
|
||||
* captures do not work properly in loops. If you assign the same
|
||||
* member lambda to multiple different targets, they will share the
|
||||
* same captured values.
|
||||
* unexpected side-effects. In practice, **you should not expect to be able
|
||||
* to pass any more information than you can pass to a normal menu selector
|
||||
* through captures**. If you assign the same member lambda to multiple
|
||||
* different targets, they will share the same captured values.
|
||||
*/
|
||||
template<class Func>
|
||||
[[deprecated(
|
||||
"Due to too many implementation problems, "
|
||||
"makeMenuSelector will be removed in the future."
|
||||
)]]
|
||||
static cocos2d::SEL_MenuHandler makeMenuSelector(Func&& selector) {
|
||||
return (cocos2d::SEL_MenuHandler)(makeMemberFunction<cocos2d::CCObject, Func>(std::move(selector)));
|
||||
return reinterpret_cast<cocos2d::SEL_MenuHandler>(
|
||||
makeMemberFunction<cocos2d::CCObject, Func>(std::move(selector))
|
||||
);
|
||||
}
|
||||
|
||||
#define GEODE_MENU_SELECTOR(senderArg, ...) \
|
||||
makeMenuSelector([=](senderArg) { __VA_ARGS__; })
|
||||
makeMenuSelector([this](senderArg) { __VA_ARGS__; })
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#include "ModInfoLayer.hpp"
|
||||
#include "../dev/HookListLayer.hpp"
|
||||
#include <Geode/ui/BasedButton.hpp>
|
||||
#include <Geode/ui/MDTextArea.hpp>
|
||||
#include "../list/ModListView.hpp"
|
||||
#include <Geode/ui/Scrollbar.hpp>
|
||||
#include <Geode/utils/WackyGeodeMacros.hpp>
|
||||
#include <Geode/ui/IconButtonSprite.hpp>
|
||||
#include <Geode/ui/MDPopup.hpp>
|
||||
|
@ -69,6 +67,26 @@ void DownloadStatusNode::setStatus(std::string const& text) {
|
|||
m_label->limitLabelWidth(m_obContentSize.width - 30.f, .5f, .1f);
|
||||
}
|
||||
|
||||
void ModInfoLayer::onChangelog(CCObject* sender) {
|
||||
auto toggle = static_cast<CCMenuItemToggler*>(sender);
|
||||
auto winSize = CCDirector::get()->getWinSize();
|
||||
|
||||
m_detailsArea->setVisible(toggle->isToggled());
|
||||
// as it turns out, cocos2d is stupid and still passes touch
|
||||
// events to invisible nodes
|
||||
m_detailsArea->setPositionX(toggle->isToggled() ?
|
||||
winSize.width / 2 - m_detailsArea->getScaledContentSize().width / 2 :
|
||||
-5000.f
|
||||
);
|
||||
|
||||
m_changelogArea->setVisible(!toggle->isToggled());
|
||||
// as it turns out, cocos2d is stupid and still passes touch
|
||||
// events to invisible nodes
|
||||
m_changelogArea->setPositionX(!toggle->isToggled() ?
|
||||
winSize.width / 2 - m_changelogArea->getScaledContentSize().width / 2 :
|
||||
-5000.f
|
||||
);
|
||||
}
|
||||
|
||||
bool ModInfoLayer::init(ModObject* obj, ModListView* list) {
|
||||
m_noElasticity = true;
|
||||
|
@ -163,37 +181,37 @@ bool ModInfoLayer::init(ModObject* obj, ModListView* list) {
|
|||
CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
|
||||
this->registerWithTouchDispatcher();
|
||||
|
||||
auto details = MDTextArea::create(
|
||||
m_detailsArea = MDTextArea::create(
|
||||
m_info.m_details ?
|
||||
m_info.m_details.value() :
|
||||
"### No description provided.",
|
||||
{ 350.f, 137.5f }
|
||||
);
|
||||
details->setPosition(
|
||||
winSize.width / 2 - details->getScaledContentSize().width / 2,
|
||||
winSize.height / 2 - details->getScaledContentSize().height / 2 - 20.f
|
||||
m_detailsArea->setPosition(
|
||||
winSize.width / 2 - m_detailsArea->getScaledContentSize().width / 2,
|
||||
winSize.height / 2 - m_detailsArea->getScaledContentSize().height / 2 - 20.f
|
||||
);
|
||||
m_mainLayer->addChild(details);
|
||||
m_mainLayer->addChild(m_detailsArea);
|
||||
|
||||
auto detailsBar = Scrollbar::create(details->getScrollLayer());
|
||||
detailsBar->setPosition(
|
||||
winSize.width / 2 + details->getScaledContentSize().width / 2 + 20.f,
|
||||
m_scrollbar= Scrollbar::create(m_detailsArea->getScrollLayer());
|
||||
m_scrollbar->setPosition(
|
||||
winSize.width / 2 + m_detailsArea->getScaledContentSize().width / 2 + 20.f,
|
||||
winSize.height / 2 - 20.f
|
||||
);
|
||||
m_mainLayer->addChild(detailsBar);
|
||||
m_mainLayer->addChild(m_scrollbar);
|
||||
|
||||
// changelog
|
||||
if (m_info.m_changelog) {
|
||||
auto changelog = MDTextArea::create(
|
||||
m_changelogArea = MDTextArea::create(
|
||||
m_info.m_changelog.value(),
|
||||
{ 350.f, 137.5f }
|
||||
);
|
||||
changelog->setPosition(
|
||||
m_changelogArea->setPosition(
|
||||
-5000.f,
|
||||
winSize.height / 2 - changelog->getScaledContentSize().height / 2 - 20.f
|
||||
winSize.height / 2 - m_changelogArea->getScaledContentSize().height / 2 - 20.f
|
||||
);
|
||||
changelog->setVisible(false);
|
||||
m_mainLayer->addChild(changelog);
|
||||
m_changelogArea->setVisible(false);
|
||||
m_mainLayer->addChild(m_changelogArea);
|
||||
|
||||
auto changelogBtnOffSpr = ButtonSprite::create(
|
||||
CCSprite::createWithSpriteFrameName("changelog.png"_spr),
|
||||
|
@ -210,26 +228,7 @@ bool ModInfoLayer::init(ModObject* obj, ModListView* list) {
|
|||
auto changelogBtn = CCMenuItemToggler::create(
|
||||
changelogBtnOffSpr,
|
||||
changelogBtnOnSpr,
|
||||
this,
|
||||
makeMenuSelector([
|
||||
this, winSize, details, detailsBar, changelog
|
||||
](CCMenuItemToggler* toggle) {
|
||||
details->setVisible(toggle->isToggled());
|
||||
// as it turns out, cocos2d is stupid and still passes touch
|
||||
// events to invisible nodes
|
||||
details->setPositionX(toggle->isToggled() ?
|
||||
winSize.width / 2 - details->getScaledContentSize().width / 2 :
|
||||
-5000.f
|
||||
);
|
||||
|
||||
changelog->setVisible(!toggle->isToggled());
|
||||
// as it turns out, cocos2d is stupid and still passes touch
|
||||
// events to invisible nodes
|
||||
changelog->setPositionX(!toggle->isToggled() ?
|
||||
winSize.width / 2 - changelog->getScaledContentSize().width / 2 :
|
||||
-5000.f
|
||||
);
|
||||
})
|
||||
this, menu_selector(ModInfoLayer::onChangelog)
|
||||
);
|
||||
changelogBtn->setPosition(-size.width / 2 + 21.5f, .0f);
|
||||
m_buttonMenu->addChild(changelogBtn);
|
||||
|
@ -253,9 +252,7 @@ bool ModInfoLayer::init(ModObject* obj, ModListView* list) {
|
|||
issuesBtnSpr->setScale(.75f);
|
||||
|
||||
auto issuesBtn = CCMenuItemSpriteExtra::create(
|
||||
issuesBtnSpr, this, makeMenuSelector([this](CCObject*) {
|
||||
ModInfoLayer::showIssueReportPopup(m_info);
|
||||
})
|
||||
issuesBtnSpr, this, menu_selector(ModInfoLayer::onIssues)
|
||||
);
|
||||
issuesBtn->setPosition(0.f, -size.height / 2 + 25.f);
|
||||
m_buttonMenu->addChild(issuesBtn);
|
||||
|
@ -287,9 +284,7 @@ bool ModInfoLayer::init(ModObject* obj, ModListView* list) {
|
|||
if (m_mod->getModInfo().m_repository) {
|
||||
auto repoBtn = CCMenuItemSpriteExtra::create(
|
||||
CCSprite::createWithSpriteFrameName("github.png"_spr),
|
||||
this, makeMenuSelector([this](CCObject*) {
|
||||
web::openLinkInBrowser(m_mod->getModInfo().m_repository.value());
|
||||
})
|
||||
this, menu_selector(ModInfoLayer::onRepository)
|
||||
);
|
||||
repoBtn->setPosition(
|
||||
size.width / 2 - 25.f,
|
||||
|
@ -301,13 +296,7 @@ bool ModInfoLayer::init(ModObject* obj, ModListView* list) {
|
|||
if (m_mod->getModInfo().m_supportInfo) {
|
||||
auto supportBtn = CCMenuItemSpriteExtra::create(
|
||||
CCSprite::createWithSpriteFrameName("gift.png"_spr),
|
||||
this, makeMenuSelector([this](CCObject*) {
|
||||
MDPopup::create(
|
||||
"Support " + m_mod->getName(),
|
||||
m_mod->getModInfo().m_supportInfo.value(),
|
||||
"OK"
|
||||
)->show();
|
||||
})
|
||||
this, menu_selector(ModInfoLayer::onSupport)
|
||||
);
|
||||
supportBtn->setPosition(
|
||||
size.width / 2 - 60.f,
|
||||
|
@ -439,6 +428,18 @@ bool ModInfoLayer::init(ModObject* obj, ModListView* list) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ModInfoLayer::onIssues(CCObject*) {
|
||||
ModInfoLayer::showIssueReportPopup(m_info);
|
||||
}
|
||||
|
||||
void ModInfoLayer::onSupport(CCObject*) {
|
||||
MDPopup::create(
|
||||
"Support " + m_mod->getName(),
|
||||
m_mod->getModInfo().m_supportInfo.value(),
|
||||
"OK"
|
||||
)->show();
|
||||
}
|
||||
|
||||
void ModInfoLayer::onEnableMod(CCObject* pSender) {
|
||||
if (!InternalLoader::get()->shownInfoAlert("mod-disable-vs-unload")) {
|
||||
FLAlertLayer::create(
|
||||
|
@ -489,6 +490,10 @@ void ModInfoLayer::onEnableMod(CCObject* pSender) {
|
|||
as<CCMenuItemToggler*>(pSender)->toggle(m_mod->isEnabled());
|
||||
}
|
||||
|
||||
void ModInfoLayer::onRepository(CCObject*) {
|
||||
web::openLinkInBrowser(m_mod->getModInfo().m_repository.value());
|
||||
}
|
||||
|
||||
void ModInfoLayer::onInstallMod(CCObject*) {
|
||||
auto ticketRes = Index::get()->installItem(
|
||||
Index::get()->getKnownItem(m_info.m_id),
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <Geode/Geode.hpp>
|
||||
#include <Index.hpp>
|
||||
#include <Geode/ui/MDTextArea.hpp>
|
||||
#include <Geode/ui/Scrollbar.hpp>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
|
@ -36,6 +38,9 @@ protected:
|
|||
CCMenuItemSpriteExtra* m_installBtn;
|
||||
CCLabelBMFont* m_updateVersionLabel = nullptr;
|
||||
InstallTicket* m_ticket = nullptr;
|
||||
MDTextArea* m_detailsArea;
|
||||
MDTextArea* m_changelogArea;
|
||||
Scrollbar* m_scrollbar;
|
||||
|
||||
void onHooks(CCObject*);
|
||||
void onSettings(CCObject*);
|
||||
|
@ -46,6 +51,10 @@ protected:
|
|||
void onCancelInstall(CCObject*);
|
||||
void onUninstall(CCObject*);
|
||||
void onDisablingNotSupported(CCObject*);
|
||||
void onChangelog(CCObject*);
|
||||
void onIssues(CCObject*);
|
||||
void onRepository(CCObject*);
|
||||
void onSupport(CCObject*);
|
||||
void install();
|
||||
void uninstall();
|
||||
void updateInstallStatus(std::string const& status, uint8_t progress);
|
||||
|
|
|
@ -80,11 +80,7 @@ bool ModListLayer::init() {
|
|||
auto listDisplayType = CCMenuItemToggler::create(
|
||||
unextendedIconSpr,
|
||||
extendedIconSpr,
|
||||
this,
|
||||
makeMenuSelector([this](CCMenuItemToggler* toggle) {
|
||||
m_expandedList = !toggle->isToggled();
|
||||
this->reloadList();
|
||||
})
|
||||
this, menu_selector(ModListLayer::onExpand)
|
||||
);
|
||||
listDisplayType->setPosition(-210.f, .0f);
|
||||
m_topMenu->addChild(listDisplayType);
|
||||
|
@ -167,9 +163,7 @@ void ModListLayer::createSearchControl() {
|
|||
filterSpr->setScale(.7f);
|
||||
|
||||
m_filterBtn = CCMenuItemSpriteExtra::create(
|
||||
filterSpr, this, makeMenuSelector([this](CCObject*) {
|
||||
SearchFilterPopup::create(this, g_tab)->show();
|
||||
})
|
||||
filterSpr, this, menu_selector(ModListLayer::onFilters)
|
||||
);
|
||||
m_filterBtn->setPosition(-10.f, 0.f);
|
||||
menu->addChild(m_filterBtn);
|
||||
|
@ -411,6 +405,15 @@ void ModListLayer::onReload(CCObject*) {
|
|||
this->reloadList();
|
||||
}
|
||||
|
||||
void ModListLayer::onExpand(CCObject* sender) {
|
||||
m_expandedList = !static_cast<CCMenuItemToggler*>(sender)->isToggled();
|
||||
this->reloadList();
|
||||
}
|
||||
|
||||
void ModListLayer::onFilters(CCObject*) {
|
||||
SearchFilterPopup::create(this, g_tab)->show();
|
||||
}
|
||||
|
||||
void ModListLayer::onOpenFolder(CCObject*) {
|
||||
file::openFolder(
|
||||
ghc::filesystem::canonical(Loader::get()->getGeodeDirectory() / "mods")
|
||||
|
|
|
@ -37,8 +37,10 @@ protected:
|
|||
void onCheckForUpdates(CCObject*);
|
||||
void onOpenFolder(CCObject*);
|
||||
void onResetSearch(CCObject*);
|
||||
void keyDown(enumKeyCodes) override;
|
||||
void onExpand(CCObject*);
|
||||
void onTab(CCObject*);
|
||||
void onFilters(CCObject*);
|
||||
void keyDown(enumKeyCodes) override;
|
||||
void textChanged(CCTextInputNode*) override;
|
||||
void indexUpdateProgress(
|
||||
UpdateStatus status,
|
||||
|
|
|
@ -56,9 +56,7 @@ bool SearchFilterPopup::setup(ModListLayer* layer, ModListType type) {
|
|||
|
||||
this->addToggle(
|
||||
"Show Installed",
|
||||
makeMenuSelector([this](CCMenuItemToggler* sender) {
|
||||
m_modLayer->m_query.m_showInstalled = !sender->isToggled();
|
||||
}),
|
||||
menu_selector(SearchFilterPopup::onShowInstalled),
|
||||
layer->m_query.m_showInstalled,
|
||||
0,
|
||||
pos
|
||||
|
@ -85,23 +83,7 @@ bool SearchFilterPopup::setup(ModListLayer* layer, ModListType type) {
|
|||
|
||||
for (auto& category : Index::get()->getCategories()) {
|
||||
auto toggle = CCMenuItemToggler::createWithStandardSprites(
|
||||
this,
|
||||
makeMenuSelector([this](CCMenuItemToggler* toggle) {
|
||||
// due to implementation problems in makeMemberFunction,
|
||||
// category can't be passed through capture
|
||||
try {
|
||||
if (!toggle->isToggled()) {
|
||||
m_modLayer->m_query.m_categories.insert(
|
||||
static_cast<CCString*>(toggle->getUserObject())->getCString()
|
||||
);
|
||||
} else {
|
||||
m_modLayer->m_query.m_categories.erase(
|
||||
static_cast<CCString*>(toggle->getUserObject())->getCString()
|
||||
);
|
||||
}
|
||||
} catch(...) {}
|
||||
}),
|
||||
.5f
|
||||
this, menu_selector(SearchFilterPopup::onCategory), .5f
|
||||
);
|
||||
toggle->toggle(m_modLayer->m_query.m_categories.count(category));
|
||||
toggle->setPosition(pos - winSize / 2);
|
||||
|
@ -120,6 +102,23 @@ bool SearchFilterPopup::setup(ModListLayer* layer, ModListType type) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void SearchFilterPopup::onCategory(CCObject* sender) {
|
||||
try {
|
||||
auto toggle = static_cast<CCMenuItemToggler*>(sender);
|
||||
auto category = static_cast<CCString*>(toggle->getUserObject())->getCString();
|
||||
if (!toggle->isToggled()) {
|
||||
m_modLayer->m_query.m_categories.insert(category);
|
||||
} else {
|
||||
m_modLayer->m_query.m_categories.erase(category);
|
||||
}
|
||||
} catch(...) {}
|
||||
}
|
||||
|
||||
void SearchFilterPopup::onShowInstalled(CCObject* sender) {
|
||||
auto toggle = static_cast<CCMenuItemToggler*>(sender);
|
||||
m_modLayer->m_query.m_showInstalled = !toggle->isToggled();
|
||||
}
|
||||
|
||||
void SearchFilterPopup::enable(CCMenuItemToggler* toggle, ModListType type) {
|
||||
if (type == ModListType::Installed) {
|
||||
toggle->setEnabled(false);
|
||||
|
|
|
@ -21,6 +21,8 @@ protected:
|
|||
|
||||
void onSearchToggle(CCObject*);
|
||||
void onPlatformToggle(CCObject*);
|
||||
void onShowInstalled(CCObject*);
|
||||
void onCategory(CCObject*);
|
||||
|
||||
void enable(CCMenuItemToggler* toggle, ModListType type);
|
||||
|
||||
|
|
|
@ -111,6 +111,22 @@ void FileSettingNode::valueChanged(bool updateText) {
|
|||
this->updateLabel();
|
||||
}
|
||||
|
||||
void FileSettingNode::onPickFile(CCObject*) {
|
||||
auto setting = std::static_pointer_cast<FileSetting>(m_setting);
|
||||
if (auto path = file::pickFile(
|
||||
file::PickMode::OpenFile,
|
||||
{
|
||||
file::geodeRoot(),
|
||||
setting->getFileFilters().value_or(
|
||||
std::vector<file::FilePickOptions::Filter>()
|
||||
)
|
||||
}
|
||||
)) {
|
||||
m_uncommittedValue = path.value();
|
||||
this->valueChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSettingNode::setup(std::shared_ptr<FileSetting> setting, float width) {
|
||||
m_input = InputNode::create(width / 2 - 30.f, "Path to File", "chatFont.fnt");
|
||||
m_input->setPosition({ -(width / 2 - 80.f) / 2 - 15.f, .0f });
|
||||
|
@ -122,20 +138,7 @@ bool FileSettingNode::setup(std::shared_ptr<FileSetting> setting, float width) {
|
|||
fileBtnSpr->setScale(.5f);
|
||||
|
||||
auto fileBtn = CCMenuItemSpriteExtra::create(
|
||||
fileBtnSpr, this, makeMenuSelector([this, setting](CCObject*) {
|
||||
if (auto path = file::pickFile(
|
||||
file::PickMode::OpenFile,
|
||||
{
|
||||
file::geodeRoot(),
|
||||
setting->getFileFilters().value_or(
|
||||
std::vector<file::FilePickOptions::Filter>()
|
||||
)
|
||||
}
|
||||
)) {
|
||||
m_uncommittedValue = path.value();
|
||||
this->valueChanged(true);
|
||||
}
|
||||
})
|
||||
fileBtnSpr, this, menu_selector(FileSettingNode::onPickFile)
|
||||
);
|
||||
fileBtn->setPosition(.0f, .0f);
|
||||
m_menu->addChild(fileBtn);
|
||||
|
@ -155,18 +158,20 @@ void ColorSettingNode::updateColor(ccColor4B const& color) {
|
|||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
void ColorSettingNode::onSelectColor(CCObject*) {
|
||||
auto popup = ColorPickPopup::create(m_uncommittedValue);
|
||||
popup->setDelegate(this);
|
||||
popup->setColorTarget(m_colorSpr);
|
||||
popup->show();
|
||||
}
|
||||
|
||||
bool ColorSettingNode::setup(std::shared_ptr<ColorSetting> setting, float width) {
|
||||
m_colorSpr = ColorChannelSprite::create();
|
||||
m_colorSpr->setColor(m_uncommittedValue);
|
||||
m_colorSpr->setScale(.65f);
|
||||
|
||||
auto button = CCMenuItemSpriteExtra::create(
|
||||
m_colorSpr, this, makeMenuSelector([this](CCObject*) {
|
||||
auto popup = ColorPickPopup::create(m_uncommittedValue);
|
||||
popup->setDelegate(this);
|
||||
popup->setColorTarget(m_colorSpr);
|
||||
popup->show();
|
||||
})
|
||||
m_colorSpr, this, menu_selector(ColorSettingNode::onSelectColor)
|
||||
);
|
||||
button->setPositionX(-10.f);
|
||||
m_menu->addChild(button);
|
||||
|
@ -187,6 +192,13 @@ void ColorAlphaSettingNode::updateColor(ccColor4B const& color) {
|
|||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
void ColorAlphaSettingNode::onSelectColor(CCObject*) {
|
||||
auto popup = ColorPickPopup::create(m_uncommittedValue);
|
||||
popup->setDelegate(this);
|
||||
popup->setColorTarget(m_colorSpr);
|
||||
popup->show();
|
||||
}
|
||||
|
||||
bool ColorAlphaSettingNode::setup(std::shared_ptr<ColorAlphaSetting> setting, float width) {
|
||||
m_colorSpr = ColorChannelSprite::create();
|
||||
m_colorSpr->setColor(to3B(m_uncommittedValue));
|
||||
|
@ -194,12 +206,7 @@ bool ColorAlphaSettingNode::setup(std::shared_ptr<ColorAlphaSetting> setting, fl
|
|||
m_colorSpr->setScale(.65f);
|
||||
|
||||
auto button = CCMenuItemSpriteExtra::create(
|
||||
m_colorSpr, this, makeMenuSelector([this](CCObject*) {
|
||||
auto popup = ColorPickPopup::create(m_uncommittedValue);
|
||||
popup->setDelegate(this);
|
||||
popup->setColorTarget(m_colorSpr);
|
||||
popup->show();
|
||||
})
|
||||
m_colorSpr, this, menu_selector(ColorAlphaSettingNode::onSelectColor)
|
||||
);
|
||||
button->setPositionX(-10.f);
|
||||
m_menu->addChild(button);
|
||||
|
|
|
@ -54,9 +54,7 @@ namespace {
|
|||
|
||||
m_uncommittedValue = setting->getValue();
|
||||
|
||||
auto name = setting->getName() ?
|
||||
setting->getName().value() :
|
||||
setting->getKey();
|
||||
auto name = setting->getDisplayName();
|
||||
|
||||
m_nameLabel = CCLabelBMFont::create(name.c_str(), "bigFont.fnt");
|
||||
m_nameLabel->setAnchorPoint({ .0f, .5f });
|
||||
|
@ -94,13 +92,7 @@ namespace {
|
|||
infoSpr->setScale(.6f);
|
||||
|
||||
auto infoBtn = CCMenuItemSpriteExtra::create(
|
||||
infoSpr, this, makeMenuSelector([this, name, setting](CCObject*) {
|
||||
FLAlertLayer::create(
|
||||
name.c_str(),
|
||||
setting->getDescription().value(),
|
||||
"OK"
|
||||
)->show();
|
||||
})
|
||||
infoSpr, this, menu_selector(GeodeSettingNode::onDescription)
|
||||
);
|
||||
infoBtn->setPosition(
|
||||
-m_obContentSize.width + sidePad +
|
||||
|
@ -119,17 +111,7 @@ namespace {
|
|||
resetBtnSpr->setScale(.5f);
|
||||
|
||||
m_resetBtn = CCMenuItemSpriteExtra::create(
|
||||
resetBtnSpr, this, makeMenuSelector([name, this](CCObject*) {
|
||||
createQuickPopup(
|
||||
"Reset",
|
||||
"Are you sure you want to <cr>reset</c> <cl>" +
|
||||
name + "</c> to <cy>default</c>?",
|
||||
"Cancel", "Reset",
|
||||
[this](auto, bool btn2) {
|
||||
if (btn2) this->resetToDefault();
|
||||
}
|
||||
);
|
||||
})
|
||||
resetBtnSpr, this, menu_selector(GeodeSettingNode::onReset)
|
||||
);
|
||||
m_resetBtn->setPosition(
|
||||
-m_obContentSize.width + sidePad +
|
||||
|
@ -150,6 +132,29 @@ namespace {
|
|||
return true;
|
||||
}
|
||||
|
||||
void onDescription(CCObject*) {
|
||||
auto setting = std::static_pointer_cast<T>(m_setting);
|
||||
FLAlertLayer::create(
|
||||
setting->getDisplayName().c_str(),
|
||||
setting->getDescription().value(),
|
||||
"OK"
|
||||
)->show();
|
||||
}
|
||||
|
||||
void onReset(CCObject*) {
|
||||
auto setting = std::static_pointer_cast<T>(m_setting);
|
||||
createQuickPopup(
|
||||
"Reset",
|
||||
"Are you sure you want to <cr>reset</c> <cl>" +
|
||||
setting->getDisplayName() +
|
||||
"</c> to <cy>default</c>?",
|
||||
"Cancel", "Reset",
|
||||
[this](auto, bool btn2) {
|
||||
if (btn2) this->resetToDefault();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
virtual float setupHeight(std::shared_ptr<T> setting) const {
|
||||
return 40.f;
|
||||
}
|
||||
|
@ -292,10 +297,7 @@ namespace {
|
|||
decArrowSpr->setScale(.3f);
|
||||
|
||||
m_decArrow = CCMenuItemSpriteExtra::create(
|
||||
decArrowSpr, self(),
|
||||
makeMenuSelector([this](CCObject*){
|
||||
onDecrement(self());
|
||||
})
|
||||
decArrowSpr, self(), menu_selector(ImplArrows::onDecrement)
|
||||
);
|
||||
m_decArrow->setPosition(-width / 2 + 80.f, yPos);
|
||||
self()->m_menu->addChild(m_decArrow);
|
||||
|
@ -304,10 +306,7 @@ namespace {
|
|||
incArrowSpr->setScale(.3f);
|
||||
|
||||
m_incArrow = CCMenuItemSpriteExtra::create(
|
||||
incArrowSpr, self(),
|
||||
makeMenuSelector([this](CCObject*){
|
||||
onIncrement(self());
|
||||
})
|
||||
incArrowSpr, self(), menu_selector(ImplArrows::onIncrement)
|
||||
);
|
||||
m_incArrow->setPosition(-10.f, yPos);
|
||||
self()->m_menu->addChild(m_incArrow);
|
||||
|
@ -319,10 +318,7 @@ namespace {
|
|||
decArrowSpr->setScale(.3f);
|
||||
|
||||
m_bigDecArrow = CCMenuItemSpriteExtra::create(
|
||||
decArrowSpr, self(),
|
||||
makeMenuSelector([this](CCObject*){
|
||||
onBigDecrement(self());
|
||||
})
|
||||
decArrowSpr, self(), menu_selector(ImplArrows::onBigDecrement)
|
||||
);
|
||||
m_bigDecArrow->setPosition(-width / 2 + 65.f, yPos);
|
||||
self()->m_menu->addChild(m_bigDecArrow);
|
||||
|
@ -331,38 +327,45 @@ namespace {
|
|||
incArrowSpr->setScale(.3f);
|
||||
|
||||
m_bigIncArrow = CCMenuItemSpriteExtra::create(
|
||||
incArrowSpr, self(),
|
||||
makeMenuSelector([this](CCObject*){
|
||||
onBigIncrement(self());
|
||||
})
|
||||
incArrowSpr, self(), menu_selector(ImplArrows::onBigIncrement)
|
||||
);
|
||||
m_bigIncArrow->setPosition(5.f, yPos);
|
||||
self()->m_menu->addChild(m_bigIncArrow);
|
||||
}
|
||||
}
|
||||
|
||||
static void onIncrement(C* self) {
|
||||
void onIncrement(CCObject*) {
|
||||
// intentionally refcast to prevent warnings on clang and
|
||||
// not to offset this as it has already been offset to the
|
||||
// correct vtable when it's passed to CCMenuItemSpriteExtra
|
||||
auto self = reference_cast<C*>(this);
|
||||
self->m_uncommittedValue += std::static_pointer_cast<T>(
|
||||
self->m_setting
|
||||
)->getArrowStepSize();
|
||||
self->valueChanged(true);
|
||||
}
|
||||
|
||||
static void onDecrement(C* self) {
|
||||
void onDecrement(CCObject*) {
|
||||
// intentional, see ImplArrows::onIncrement
|
||||
auto self = reference_cast<C*>(this);
|
||||
self->m_uncommittedValue -= std::static_pointer_cast<T>(
|
||||
self->m_setting
|
||||
)->getArrowStepSize();
|
||||
self->valueChanged(true);
|
||||
}
|
||||
|
||||
static void onBigIncrement(C* self) {
|
||||
void onBigIncrement(CCObject*) {
|
||||
// intentional, see ImplArrows::onIncrement
|
||||
auto self = reference_cast<C*>(this);
|
||||
self->m_uncommittedValue += std::static_pointer_cast<T>(
|
||||
self->m_setting
|
||||
)->getBigArrowStepSize();
|
||||
self->valueChanged(true);
|
||||
}
|
||||
|
||||
static void onBigDecrement(C* self) {
|
||||
void onBigDecrement(CCObject*) {
|
||||
// intentional, see ImplArrows::onIncrement
|
||||
auto self = reference_cast<C*>(this);
|
||||
self->m_uncommittedValue -= std::static_pointer_cast<T>(
|
||||
self->m_setting
|
||||
)->getBigArrowStepSize();
|
||||
|
@ -410,9 +413,7 @@ namespace {
|
|||
void setupSlider(std::shared_ptr<T> setting, float width) {
|
||||
if (setting->hasSlider()) {
|
||||
m_slider = Slider::create(
|
||||
self(), makeMenuSelector([this](CCObject* slider){
|
||||
onSlider(self(), slider);
|
||||
}), .5f
|
||||
self(), menu_selector(ImplSlider::onSlider), .5f
|
||||
);
|
||||
m_slider->setPosition(-50.f, -15.f);
|
||||
self()->m_menu->addChild(m_slider);
|
||||
|
@ -429,7 +430,9 @@ namespace {
|
|||
m_slider->updateBar();
|
||||
}
|
||||
|
||||
static void onSlider(C* self, CCObject* slider) {
|
||||
void onSlider(CCObject* slider) {
|
||||
// intentional, see ImplArrows::onIncrement
|
||||
auto self = reference_cast<C*>(this);
|
||||
auto setting = std::static_pointer_cast<T>(self->m_setting);
|
||||
|
||||
self->m_uncommittedValue = valueFromSlider(
|
||||
|
@ -510,6 +513,8 @@ protected:
|
|||
void textChanged(CCTextInputNode* input) override;
|
||||
void valueChanged(bool updateText) override;
|
||||
void updateLabel();
|
||||
|
||||
void onPickFile(CCObject*);
|
||||
|
||||
bool setup(std::shared_ptr<FileSetting> setting, float width) override;
|
||||
};
|
||||
|
@ -524,6 +529,8 @@ protected:
|
|||
void valueChanged(bool updateText) override;
|
||||
void updateColor(ccColor4B const& color) override;
|
||||
|
||||
void onSelectColor(CCObject*);
|
||||
|
||||
bool setup(std::shared_ptr<ColorSetting> setting, float width) override;
|
||||
};
|
||||
|
||||
|
@ -537,5 +544,7 @@ protected:
|
|||
void valueChanged(bool updateText) override;
|
||||
void updateColor(ccColor4B const& color) override;
|
||||
|
||||
void onSelectColor(CCObject*);
|
||||
|
||||
bool setup(std::shared_ptr<ColorAlphaSetting> setting, float width) override;
|
||||
};
|
||||
|
|
|
@ -123,22 +123,7 @@ bool ModSettingsPopup::setup(Mod* mod) {
|
|||
m_applyBtnSpr->setScale(.7f);
|
||||
|
||||
m_applyBtn = CCMenuItemSpriteExtra::create(
|
||||
m_applyBtnSpr, this, makeMenuSelector([this](CCObject*) {
|
||||
bool someChangesMade = false;
|
||||
for (auto& sett : m_settings) {
|
||||
if (sett->hasUncommittedChanges()) {
|
||||
sett->commit();
|
||||
someChangesMade = true;
|
||||
}
|
||||
}
|
||||
if (!someChangesMade) {
|
||||
FLAlertLayer::create(
|
||||
"Info",
|
||||
"No changes have been made.",
|
||||
"OK"
|
||||
)->show();
|
||||
}
|
||||
})
|
||||
m_applyBtnSpr, this, menu_selector(ModSettingsPopup::onApply)
|
||||
);
|
||||
m_applyBtn->setPosition(.0f, -m_size.height / 2 + 20.f);
|
||||
m_buttonMenu->addChild(m_applyBtn);
|
||||
|
@ -152,21 +137,7 @@ bool ModSettingsPopup::setup(Mod* mod) {
|
|||
resetBtnSpr->setScale(.7f);
|
||||
|
||||
auto resetBtn = CCMenuItemSpriteExtra::create(
|
||||
resetBtnSpr, this, makeMenuSelector([this](CCObject*) {
|
||||
createQuickPopup(
|
||||
"Reset All",
|
||||
"Are you sure you want to <cr>reset</c> ALL settings "
|
||||
"to <cy>default</c>?",
|
||||
"Cancel", "Reset",
|
||||
[this](auto, bool btn2) {
|
||||
if (btn2) {
|
||||
for (auto& sett : m_settings) {
|
||||
sett->resetToDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
})
|
||||
resetBtnSpr, this, menu_selector(ModSettingsPopup::onResetAll)
|
||||
);
|
||||
resetBtn->setPosition(-m_size.width / 2 + 45.f, -m_size.height / 2 + 20.f);
|
||||
m_buttonMenu->addChild(resetBtn);
|
||||
|
@ -176,6 +147,39 @@ bool ModSettingsPopup::setup(Mod* mod) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ModSettingsPopup::onApply(CCObject*) {
|
||||
bool someChangesMade = false;
|
||||
for (auto& sett : m_settings) {
|
||||
if (sett->hasUncommittedChanges()) {
|
||||
sett->commit();
|
||||
someChangesMade = true;
|
||||
}
|
||||
}
|
||||
if (!someChangesMade) {
|
||||
FLAlertLayer::create(
|
||||
"Info",
|
||||
"No changes have been made.",
|
||||
"OK"
|
||||
)->show();
|
||||
}
|
||||
}
|
||||
|
||||
void ModSettingsPopup::onResetAll(CCObject*) {
|
||||
createQuickPopup(
|
||||
"Reset All",
|
||||
"Are you sure you want to <cr>reset</c> ALL settings "
|
||||
"to <cy>default</c>?",
|
||||
"Cancel", "Reset",
|
||||
[this](auto, bool btn2) {
|
||||
if (btn2) {
|
||||
for (auto& sett : m_settings) {
|
||||
sett->resetToDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void ModSettingsPopup::settingValueChanged(SettingNode*) {
|
||||
if (this->hasUncommitted()) {
|
||||
m_applyBtnSpr->setColor(cc3x(0xf));
|
||||
|
|
|
@ -18,6 +18,8 @@ protected:
|
|||
bool setup(Mod* mod) override;
|
||||
bool hasUncommitted() const;
|
||||
void onClose(CCObject*) override;
|
||||
void onApply(CCObject*);
|
||||
void onResetAll(CCObject*);
|
||||
|
||||
public:
|
||||
static ModSettingsPopup* create(Mod* mod);
|
||||
|
|
Loading…
Reference in a new issue