Merge branch 'main' of https://github.com/geode-sdk/geode into main

This commit is contained in:
HJfod 2022-10-09 21:02:48 +03:00
commit e7f82381a1
15 changed files with 283 additions and 280 deletions

View file

@ -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 }}

View file

@ -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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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__; })
}

View file

@ -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),

View file

@ -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);

View file

@ -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")

View file

@ -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,

View file

@ -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);

View file

@ -21,6 +21,8 @@ protected:
void onSearchToggle(CCObject*);
void onPlatformToggle(CCObject*);
void onShowInstalled(CCObject*);
void onCategory(CCObject*);
void enable(CCMenuItemToggler* toggle, ModListType type);

View file

@ -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);

View file

@ -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;
};

View file

@ -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));

View file

@ -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);