Merge branch 'main' into bi-additions

This commit is contained in:
alk 2023-07-30 20:50:30 +03:00 committed by GitHub
commit 4c8c0ae7b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 685 additions and 262 deletions

View file

@ -112,6 +112,19 @@ jobs:
with:
name: geode-v${{ env.VERSION_TRIM }}-${{ matrix.config.os_identifier }}
path: ./out
- name: Package MacOS
run: |
cp -R ./bin/nightly/resources ./out/resources
./installer/mac/package.sh ./out ./out/geode-installer-v${{ env.VERSION_TRIM }}-${{ matrix.config.os_identifier }}.pkg
if: matrix.config.os_identifier == 'mac'
- name: Publish MacOS Installer
uses: actions/upload-artifact@v2
with:
name: geode-installer-v${{ env.VERSION_TRIM }}-${{ matrix.config.os_identifier }}
path: ./out/geode-installer-v${{ env.VERSION_TRIM }}-${{ matrix.config.os_identifier }}.pkg
if: matrix.config.os_identifier == 'mac'
publish:
runs-on: ubuntu-latest
@ -145,7 +158,7 @@ jobs:
dest: geode-nightly-win.zip
- name: Update release
uses: IsaacShelton/update-existing-release@v1.3.1
uses: IsaacShelton/update-existing-release@v1.3.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
files: ./geode-nightly-mac.zip ./geode-nightly-win.zip

1
.gitignore vendored
View file

@ -54,6 +54,7 @@ loader/resources/version
loader/resources/blanks/rename.js
loader/resources/changelog.md
fods-catgirl-hideout.txt
test-docs.bat
# krita files too because alk is funny
**/*.kra

View file

@ -122,6 +122,10 @@ file(GLOB CODEGEN_DEPENDS CONFIGURE_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/codegen/src/*.hpp
)
if (NOT GEODE_BINDINGS_PATH)
set(GEODE_BINDINGS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bindings)
endif()
file(GLOB CODEGEN_OUTPUTS CONFIGURE_DEPENDS
${GEODE_CODEGEN_PATH}/Geode/binding/*.hpp
)
@ -129,7 +133,7 @@ file(GLOB CODEGEN_OUTPUTS CONFIGURE_DEPENDS
add_custom_command(
DEPENDS ${CODEGEN_DEPENDS}
DEPENDS CodegenProject
COMMAND ${GEODE_CODEGEN_BINARY_OUT}/Codegen ${GEODE_TARGET_PLATFORM} bindings ${GEODE_CODEGEN_PATH}
COMMAND ${GEODE_CODEGEN_BINARY_OUT}/Codegen ${GEODE_TARGET_PLATFORM} ${GEODE_BINDINGS_PATH} ${GEODE_CODEGEN_PATH}
COMMAND echo codegen > ${GEODE_CODEGEN_PATH}/.stamp
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Run Codegen"

View file

@ -1 +1 @@
1.0.0
1.0.0

View file

@ -737,6 +737,7 @@ class cocos2d::CCRenderTexture {
static cocos2d::CCRenderTexture* create(int, int, cocos2d::CCTexture2DPixelFormat) = mac 0x35c720;
auto newCCImage(bool) = mac 0x35d7d0;
auto saveToFile(char const*) = mac 0x35dab0;
auto beginWithClear(float r, float g, float b, float a) = mac 0x35d010;
}
class cocos2d::CCRepeat {

View file

@ -1020,11 +1020,13 @@ class CustomSongWidget : cocos2d::CCNode, MusicDownloadDelegate, FLAlertLayerPro
class CustomizeObjectLayer : FLAlertLayer, TextInputDelegate, HSVWidgetPopupDelegate, ColorSelectDelegate, ColorSetupDelegate {
void onNextColorChannel(cocos2d::CCObject* sender) = win 0x56c80;
void onSelectColor(cocos2d::CCObject* sender) = win 0x577b0;
void onSelectMode(cocos2d::CCObject* sender) = mac 0xdf820, win 0x56db0;
int getActiveMode(bool unknown) = win 0x57210;
void onClose(cocos2d::CCObject*) = mac 0xdf660, win 0x57ac0;
void updateSelected(int channelID) = win 0x57850;
bool init(GameObject* target, cocos2d::CCArray* targets) = mac 0xdd560, win 0x53e00;
void onHSV(cocos2d::CCObject* sender) = win 0x567c0;
void toggleVisible() = mac 0xe1140, win 0x56fb0;
virtual void hsvPopupClosed(HSVWidgetPopup* popup, cocos2d::ccHSVValue value) = win 0x56990;
inline CustomizeObjectLayer() {}
~CustomizeObjectLayer() = win 0x53c30;
@ -1032,10 +1034,10 @@ class CustomizeObjectLayer : FLAlertLayer, TextInputDelegate, HSVWidgetPopupDele
GameObject* m_targetObject;
cocos2d::CCArray* m_targetObjects;
cocos2d::CCArray* m_colorButtons;
cocos2d::CCArray* m_colorNodes;
cocos2d::CCArray* m_textInputNodes;
cocos2d::CCArray* m_colorTabNodes;
cocos2d::CCArray* m_textTabNodes;
PAD = win 0x4;
cocos2d::CCArray* m_detailColorButtons;
cocos2d::CCArray* m_detailTabNodes;
int m_selectedMode;
int m_customColorChannel;
bool m_unk0x200;
@ -1964,8 +1966,8 @@ class GJBaseGameLayer : cocos2d::CCLayer, TriggerEffectDelegate {
int m_activeEnterEffect;
bool m_activeDualTouch;
int m_attemptClickCount;
int m_lastVisibleSection;
int m_firstVisibleSection;
int m_lastVisibleSection;
bool m_objectsAreDisabled;
bool m_blending;
PAD = mac 0x8, win 0x8;
@ -2094,7 +2096,7 @@ class GJEffectManager : cocos2d::CCNode {
}
virtual bool init() = mac 0x180230, win 0x11c1b0;
void activeColorForIndex(int) = mac 0x180cb0, win 0x11c6e0;
cocos2d::_ccColor3B activeColorForIndex(int) = mac 0x180cb0, win 0x11c6e0;
void activeOpacityForIndex(int) = mac 0x180e10;
void addAllInheritedColorActions(cocos2d::CCArray*) = mac 0x1817a0;
void addGroupPulseEffect(PulseEffectAction*) = mac 0x184c10;
@ -2124,7 +2126,7 @@ class GJEffectManager : cocos2d::CCNode {
const cocos2d::_ccColor3B& getColorSprite(int) = mac 0x180d00, win 0x11ce20;
void getCurrentStateString() = mac 0x1867e0, win 0x11fac0;
void getLoadedMoveOffset() = mac 0x184390;
void getMixedColor(cocos2d::_ccColor3B, cocos2d::_ccColor3B, float) = mac 0x185d30;
static cocos2d::_ccColor3B getMixedColor(cocos2d::_ccColor3B, cocos2d::_ccColor3B, float) = mac 0x185d30, win 0x11f610;
uint8_t getOpacityActionForGroup(int) = mac 0x1845b0;
gd::string getSaveString() = mac 0x185e90;
void handleObjectCollision(bool, int, int) = mac 0x1828f0, win 0x11d2a0;
@ -2260,7 +2262,7 @@ class GJGameLevel : cocos2d::CCNode {
void getNormalPercent() = mac 0x2b8b20;
void levelWasAltered() = mac 0x2db530, win 0xbd550;
void savePercentage(int, bool, int, int, bool) = mac 0x2db700;
void dataLoaded(DS_Dictionary* dict) = mac 0x2922f0, win 0xbded0, ios 0x6fca4;
void dataLoaded(DS_Dictionary* dict) = mac 0x2dc0e0, win 0xbded0, ios 0x6fca4;
GJDifficulty getAverageDifficulty() = win 0xbd9b0;
gd::string getUnpackedLevelDescription() = win 0xbf890;
gd::string lengthKeyToString(int key) = win 0xbd910;
@ -2314,7 +2316,7 @@ class GJGameLevel : cocos2d::CCNode {
int m_chk;
bool m_isChkValid;
bool m_isCompletionLegitimate;
geode::SeedValueVSR m_normalPercent;
geode::SeedValueVRS m_normalPercent;
geode::SeedValueRSV m_orbCompletion;
geode::SeedValueRSV m_newNormalPercent2;
int m_practicePercent;
@ -2589,7 +2591,7 @@ class GJSearchObject : cocos2d::CCNode {
}
static GJSearchObject* create(SearchType nID) = win 0xc2b90;
static GJSearchObject* create(SearchType nID, gd::string str) = win 0xc2c80;
static GJSearchObject* create(SearchType nID, gd::string str) = win 0xc2c80, mac 0x2df310;
static GJSearchObject* createFromKey(const char* key) = win 0xC2760;
const char* getKey() = win 0xC30A0;
const char* getNextPageKey() = win 0xC31F0;
@ -3222,14 +3224,15 @@ class GameObject : CCSpritePlus {
void addToTempOffset(float, float) = mac 0x335700;
void calculateOrientedBox() = mac 0x342b20, win 0xef1a0;
void canChangeCustomColor() = mac 0x342db0;
void colorForMode(int, bool) = mac 0x343460;
cocos2d::_ccColor3B& colorForMode(int, bool) = mac 0x343460, win 0xef8d0;
float groupOpacityMod() = win 0xebda0;
void commonSetup() = mac 0x2f5570, win 0xcfac0;
void copyGroups(GameObject*) = mac 0x33ae30, win 0xeb9d0;
static GameObject* createWithFrame(const char*) = mac 0x2f5490, win 0xcf8f0;
static GameObject* createWithKey(int) = mac 0x2f4ce0, win 0xcf4f0;
void destroyObject() = mac 0x336a00;
void determineSlopeDirection() = mac 0x33a9e0, win 0xeb670;
void getActiveColorForMode(int, bool) = mac 0x343860, win 0xefb10;
cocos2d::_ccColor3B& getActiveColorForMode(int, bool) = mac 0x343860, win 0xefb10;
void getBallFrame(int) = mac 0x341bf0;
cocos2d::CCPoint getBoxOffset() = mac 0x3353d0, win 0xef350;
const cocos2d::_ccColor3B& getColorIndex() = mac 0x343b90;
@ -3363,7 +3366,7 @@ class GameObject : CCSpritePlus {
bool m_unknownVisibility347;
cocos2d::CCSprite* m_baseSprite;
cocos2d::CCSprite* m_detailSprite;
PAD = mac 0x4, win 0x4;
bool m_unk2e8;
float m_objectRadius;
bool m_isRotatedSide;
float m_unk2F4;
@ -3391,7 +3394,10 @@ class GameObject : CCSpritePlus {
int m_targetColorID;
float m_scale;
int m_objectID;
int m_unknown3c8;
bool m_unk364;
bool m_unk365;
bool m_unk366;
bool m_ignoreFade;
bool m_unk368;
bool m_unk369;
bool m_unk36A;
@ -3401,10 +3407,10 @@ class GameObject : CCSpritePlus {
int m_defaultZOrder;
bool m_useSecondSheet;
bool m_isPortal;
bool m_lockColourAsChild;
bool m_customAudioScale;
int m_minAudioScale;
int m_maxAudioScale;
bool m_lockColourAsChild;
float m_minAudioScale;
float m_maxAudioScale;
bool m_unkParticleSystem2;
int m_secretCoinID;
int m_unkUnusedSaveStringKey53;
@ -3420,7 +3426,7 @@ class GameObject : CCSpritePlus {
float m_realOpacity;
GJSpriteColor* m_baseColor;
GJSpriteColor* m_detailColor;
int m_unknown420;
bool m_unk3b0;
ZLayer m_defaultZLayer;
ZLayer m_zLayer;
int m_gameZOrder;
@ -3480,7 +3486,7 @@ class GameRateDelegate {}
class GameSoundManager : cocos2d::CCNode {
void disableMetering() = mac 0x362d80, win 0x257D0;
void enableMetering() = mac 0x362d00, win 0x256F0;
void getMeteringValue() = mac 0x362db0, win 0x258f0;
float getMeteringValue() = mac 0x362db0, win 0x258f0;
void playBackgroundMusic(gd::string, bool, bool) = mac 0x362070, win 0x252B0;
void playEffect(gd::string, float, float, float) = mac 0x3623d0, win 0x25450;
void stopBackgroundMusic() = mac 0x362130, win 0x253A0;
@ -3712,8 +3718,7 @@ class LevelBrowserLayer : cocos2d::CCLayer, LevelManagerDelegate, FLAlertLayerPr
void updateLevelsLabel() = win 0x15c350;
static LevelBrowserLayer* create(GJSearchObject* search) = mac 0x251210, win 0x159fa0, ios 0x2d0a00;
PAD = win 0x4;
int m_unk0;
PAD = win 0x4, mac 0x8;
TextArea* m_noInternet;
GJListLayer* m_list;
CCMenuItemSpriteExtra* m_rightArrow;
@ -3975,14 +3980,14 @@ class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDeleg
void setupProgressBars() = win 0x177fc0;
void downloadLevel() = win 0x177d90;
PAD = win 0x4;
PAD = win 0x4, mac 0x8;
cocos2d::CCMenu* m_playBtnMenu;
GJGameLevel* m_level;
cocos2d::CCArray* m_unknown;
CCMenuItemSpriteExtra* m_likeBtn;
CCMenuItemSpriteExtra* m_starRateBtn;
CCMenuItemSpriteExtra* m_demonRateBtn;
PAD = win 0x4;
PAD = win 0x4, mac 0x8;
CCMenuItemToggler* m_toggler;
cocos2d::CCLabelBMFont* m_label0;
cocos2d::CCLabelBMFont* m_label1;
@ -3991,7 +3996,7 @@ class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDeleg
cocos2d::CCLabelBMFont* m_label4;
cocos2d::CCLabelBMFont* m_label5;
CCMenuItemSpriteExtra* m_cloneBtn;
PAD = win 0x4;
PAD = win 0x4, mac 0x8;
}
class LevelLeaderboard : FLAlertLayer {
@ -4005,7 +4010,11 @@ class LevelLeaderboard : FLAlertLayer {
LevelLeaderboardType m_type;
}
class LevelManagerDelegate {}
class LevelManagerDelegate {
virtual void loadLevelsFailed(char const*) {}
virtual void loadLevelsFinished(cocos2d::CCArray *,char const*) {}
virtual void setupPageInfo(std::string,char const*) {}
}
class LevelPage {
PAD = win 0x124;
@ -4206,7 +4215,7 @@ class LocalLevelManager : GManager {
cocos2d::CCDictionary* getAllLevelsInDict() = mac 0x35e3d0, win 0x18d7c0;
PAD = mac 0x10, win 0x1C;
PAD = mac 0x4, win 0x1C;
cocos2d::CCDictionary* m_loadData;
cocos2d::CCDictionary* m_levelData;
cocos2d::CCArray* m_localLevels;
@ -4650,7 +4659,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate,
bool unk350;
cocos2d::CCArray* unk354;
cocos2d::CCArray* unk358;
cocos2d::CCArray* unk35C;
cocos2d::CCArray* m_objectsToUpdate;
cocos2d::CCArray* unk360;
bool m_isMute;
bool unk365;
@ -4713,14 +4722,14 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate,
bool unk42C;
bool m_isPlayer2Frozen;
gd::string m_previousRecords;
void* unknown6a8;
double unknown6a8;
double m_time;
int unknown6b8;
int unknown6bc;
bool unk460;
bool m_isAudioMeteringSupported;
cocos2d::CCDictionary* unk464;
gd::map<short, bool> unk468;
gd::map<short, bool> m_hasColors;
bool m_collisionDisabled;
bool unknown701;
GameObject* m_latestVehicle;
@ -4957,8 +4966,8 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
PAD = mac 0x30, win 0x1c;
bool m_unk4B0;
cocos2d::CCSprite* m_unk4B4;
int m_unk4B8;
int m_unk4BC;
int m_collidedGroundObjectUniqueID;
int m_collidedCeilObjectUniqueID;
PAD = mac 0x14, win 0x14;
bool m_unk4D4;
cocos2d::CCArray* m_particleSystems;
@ -5047,7 +5056,7 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
bool m_isRobot;
bool m_isSpider;
bool m_isUpsideDown;
bool m_unk63F;
bool m_isDead;
bool m_isOnGround;
bool m_isDashing;
float m_vehicleSize;
@ -5069,7 +5078,8 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
bool m_unk684;
bool m_unk685;
double m_unk688;
PAD = win 0x8;
PAD = win 0x4;
float m_meteringValue;
float m_groundHeight;
float m_unk69C;
PAD = win 0x4;

View file

@ -122,65 +122,67 @@ std::string generateAddressHeader(Root& root) {
}
}
output += format_strings::declare_metadata_begin;
// TODO: this eats too much of compile time make it opt in maybe
for (auto& c : root.classes) {
for (auto& field : c.fields) {
std::string address_str;
// output += format_strings::declare_metadata_begin;
auto fn = field.get_as<FunctionBindField>();
// for (auto& c : root.classes) {
// for (auto& field : c.fields) {
// std::string address_str;
if (!fn) {
continue;
}
// auto fn = field.get_as<FunctionBindField>();
if (codegen::getStatus(field) == BindStatus::Binded) {
address_str = fmt::format(
"addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))",
str_if("Non", !fn->beginning.is_virtual),
codegen::getParameterTypes(fn->beginning),
field.parent,
fn->beginning.name
);
}
else if (codegen::getStatus(field) == BindStatus::NeedsBinding) {
address_str = fmt::format("base::get() + 0x{:x}", codegen::platformNumber(fn->binds));
}
else {
continue;
}
// if (!fn) {
// continue;
// }
char const* used_declare_format;
// if (codegen::getStatus(field) == BindStatus::Binded) {
// address_str = fmt::format(
// "addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))",
// str_if("Non", !fn->beginning.is_virtual),
// codegen::getParameterTypes(fn->beginning),
// field.parent,
// fn->beginning.name
// );
// }
// else if (codegen::getStatus(field) == BindStatus::NeedsBinding) {
// address_str = fmt::format("base::get() + 0x{:x}", codegen::platformNumber(fn->binds));
// }
// else {
// continue;
// }
switch (fn->beginning.type) {
case FunctionType::Normal:
used_declare_format = format_strings::declare_metadata;
break;
case FunctionType::Ctor:
case FunctionType::Dtor:
used_declare_format = format_strings::declare_metadata_structor;
break;
}
// char const* used_declare_format;
if (fn->beginning.is_static)
used_declare_format = format_strings::declare_metadata_static;
// switch (fn->beginning.type) {
// case FunctionType::Normal:
// used_declare_format = format_strings::declare_metadata;
// break;
// case FunctionType::Ctor:
// case FunctionType::Dtor:
// used_declare_format = format_strings::declare_metadata_structor;
// break;
// }
output += fmt::format(
used_declare_format,
fmt::arg("address", address_str),
fmt::arg("class_name", c.name),
fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
fmt::arg("convention", codegen::getModifyConventionName(field)),
fmt::arg("return", bank.getReturn(fn->beginning, c.name)),
fmt::arg("parameters", codegen::getParameters(fn->beginning)),
fmt::arg("parameter_types", codegen::getParameterTypes(fn->beginning)),
fmt::arg("arguments", codegen::getParameterNames(fn->beginning)),
fmt::arg("parameter_comma", str_if(", ", !fn->beginning.args.empty())),
fmt::arg("index", field.field_id)
);
}
}
// if (fn->beginning.is_static)
// used_declare_format = format_strings::declare_metadata_static;
output += format_strings::declare_metadata_end;
// output += fmt::format(
// used_declare_format,
// fmt::arg("address", address_str),
// fmt::arg("class_name", c.name),
// fmt::arg("const", str_if(" const ", fn->beginning.is_const)),
// fmt::arg("convention", codegen::getModifyConventionName(field)),
// fmt::arg("return", bank.getReturn(fn->beginning, c.name)),
// fmt::arg("parameters", codegen::getParameters(fn->beginning)),
// fmt::arg("parameter_types", codegen::getParameterTypes(fn->beginning)),
// fmt::arg("arguments", codegen::getParameterNames(fn->beginning)),
// fmt::arg("parameter_comma", str_if(", ", !fn->beginning.args.empty())),
// fmt::arg("index", field.field_id)
// );
// }
// }
// output += format_strings::declare_metadata_end;
return output;
}

View file

@ -0,0 +1,67 @@
#!/usr/bin/env osascript
set tmpPath to POSIX path of "/tmp/"
set binPath to POSIX path of (tmpPath & "geode-install/")
on ExitWithMessage(message)
display dialog message
do shell script "rm -rf " & binPath
error number -128
end ExitWithMessage
try
set gdPath to (the POSIX path of (choose file with prompt "Please choose the Geometry Dash application to install Geode to:" of type {"app"}))
on error
ExitWithMessage ("Prompt cancelled.")
end try
set execPath to (gdPath & "Contents/MacOS/Geometry Dash")
set frameworkPath to POSIX path of (gdPath & "Contents/Frameworks/")
set fmodPath to "libfmod.dylib"
set fmodOriginalPath to "libfmod-original.dylib"
set geodePath to "Geode.dylib"
set bootstrapperPath to "GeodeBootstrapper.dylib"
set resourcesPath to "resources/"
set newGeodePath to "Contents/geode/"
set newResourcesPath to (newGeodePath & "resources/geode.loader/")
try
tell application "System Events"
if not exists file execPath then
ExitWithMessage ("Not a valid Geometry Dash installation (executable missing): " & gdPath)
end if
if not exists file (frameworkPath & fmodPath) then
ExitWithMessage ("Not a valid Geometry Dash installation (fmod missing): " & gdPath)
end if
end tell
on error
ExitWithMessage ("Not a valid Geometry Dash installation: " & gdPath)
end try
try
do shell script "mv -n " & (frameworkPath & fmodPath) & " " & (frameworkPath & fmodOriginalPath)
on error
ExitWithMessage ("Moving original fmod failed: " & (frameworkPath & fmodPath))
end try
try
do shell script "mv " & (binPath & geodePath) & " " & (frameworkPath & geodePath)
do shell script "mv " & (binPath & bootstrapperPath) & " " & (frameworkPath & bootstrapperPath)
do shell script "mv " & (binPath & fmodPath) & " " & (frameworkPath & fmodPath)
do shell script "INSTALLER_USER=$(stat -f '%Su' $HOME) && sudo chown -R $INSTALLER_USER " & frameworkPath
on error
ExitWithMessage ("Moving libraries failed: " & frameworkPath)
end try
try
do shell script "mkdir -p " & (gdPath & newResourcesPath)
do shell script "mv " & (binPath & resourcesPath) & "* " & (gdPath & newResourcesPath)
do shell script "INSTALLER_USER=$(stat -f '%Su' $HOME) && sudo chown -R $INSTALLER_USER " & (gdPath & newGeodePath)
on error
ExitWithMessage ("Moving resources failed: " & (gdPath & newResourcesPath))
end try
do shell script "rm -rf " & binPath

3
installer/mac/package.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/bash
pkgbuild --root "$1" --identifier com.geode-sdk.geode --scripts "installer/mac/Scripts" --install-location "/tmp/geode-install" $2

View file

@ -53,7 +53,7 @@ namespace geode {
template<class T, class N>
concept InheritsEnterLayer = std::is_base_of_v<EnterLayerEvent<N>, T>;
template<class N, InheritsEnterLayer<N> T>
template<class N, InheritsEnterLayer<N> T = EnterLayerEvent<N>>
class EnterLayerFilter : public EventFilter<EnterLayerEvent<N>> {
public:
using Callback = void(T*);

View file

@ -33,8 +33,7 @@ namespace geode {
m_buttonMenu->setZOrder(100);
m_mainLayer->addChild(m_buttonMenu);
cocos2d::CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
this->registerWithTouchDispatcher();
this->setTouchEnabled(true);
auto closeSpr = cocos2d::CCSprite::createWithSpriteFrameName("GJ_closeBtn_001.png");
closeSpr->setScale(.8f);

View file

@ -51,8 +51,7 @@ namespace geode {
this->updateLabel();
cocos2d::CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
this->registerWithTouchDispatcher();
this->setTouchEnabled(true);
return true;
}

View file

@ -1,77 +1,4 @@
#include <ghc/filesystem.hpp>
#include <mach-o/dyld.h>
#include <unistd.h>
#include <dlfcn.h>
#include <array>
#include <iostream>
#include <CoreFoundation/CoreFoundation.h>
void displayError(std::string alertMessage) {
CFStringRef cfTitle = CFStringCreateWithCString(NULL, "Geode Bootstrapper", kCFStringEncodingUTF8);
CFStringRef cfMessage = CFStringCreateWithCString(NULL, alertMessage.c_str(), kCFStringEncodingUTF8);
CFUserNotificationDisplayNotice(0, kCFUserNotificationCautionAlertLevel, NULL, NULL, NULL, cfTitle, cfMessage, NULL);
}
void loadGeode() {
auto dylib = dlopen("Geode.dylib", RTLD_NOW);
if (!dylib) {
displayError(std::string("Couldn't load Geode: ") + dlerror());
return;
}
auto trigger = dlsym(dylib, "dynamicTrigger");
if (!trigger) {
displayError(std::string("Couldn't start Geode: ") + dlerror());
return;
}
reinterpret_cast<void(*)()>(trigger)();
return;
}
extern "C" void fake();
__attribute__((constructor)) void _entry() {
std::array<char, PATH_MAX> gddir;
uint32_t out = PATH_MAX;
_NSGetExecutablePath(gddir.data(), &out);
ghc::filesystem::path gdpath = gddir.data();
auto workingDir = gdpath.parent_path().parent_path();
auto updatesDir = workingDir / "geode" / "update";
auto libDir = workingDir / "Frameworks";
auto resourcesDir = workingDir / "geode" / "resources";
auto error = std::error_code();
if (ghc::filesystem::exists(updatesDir / "Geode.dylib", error) && !error) {
ghc::filesystem::rename(
updatesDir / "Geode.dylib",
libDir / "Geode.dylib", error
);
if (error) {
displayError(std::string("Couldn't update Geode: ") + error.message());
return loadGeode();
}
}
if (ghc::filesystem::exists(updatesDir / "resources", error) && !error) {
ghc::filesystem::remove_all(resourcesDir / "geode.loader", error);
if (error) {
displayError(std::string("Couldn't update Geode resources: ") + error.message());
return loadGeode();
}
ghc::filesystem::rename(
updatesDir / "resources",
resourcesDir / "geode.loader", error
);
if (error) {
displayError(std::string("Couldn't update Geode resources: ") + error.message());
return loadGeode();
}
}
return loadGeode();
fake();
}

View file

@ -10,4 +10,13 @@ set_target_properties(Bootstrapper PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${GEODE_BIN_PATH}/nightly"
)
target_link_libraries(Bootstrapper PRIVATE "-framework CoreFoundation" ghc_filesystem)
target_link_libraries(Bootstrapper PRIVATE)
add_library(FakeGeode SHARED FakeGeode.cpp)
target_compile_features(FakeGeode PUBLIC cxx_std_17)
set_target_properties(FakeGeode PROPERTIES
PREFIX ""
OUTPUT_NAME "Geode"
)
target_link_libraries(Bootstrapper PRIVATE geode-loader)

View file

@ -0,0 +1 @@
extern "C" void fake() {}

View file

View file

@ -70,6 +70,12 @@
"default": true,
"name": "Auto-Update Mods",
"description": "Automatically update <cp>mods</c> on startup"
},
"disable-last-crashed-popup": {
"type": "bool",
"default": false,
"name": "Disable Crash Popup",
"description": "Disables the popup at startup asking if you'd like to send a bug report; intended for developers"
}
},
"issues": {

View file

@ -221,9 +221,6 @@ static AxisPosition nodeAxis(CCNode* node, Axis axis, float scale) {
if (auto toggle = typeinfo_cast<CCMenuItemToggler*>(node)) {
scaledSize = toggle->m_offButton->getScaledContentSize();
}
if (auto spacer = typeinfo_cast<SpacerNode*>(node)) {
scaledSize = CCSizeZero;
}
auto anchor = node->getAnchorPoint();
if (axis == Axis::Row) {
return AxisPosition {
@ -492,6 +489,13 @@ void AxisLayout::tryFitLayout(
float crossScaleDownFactor = 0.f;
float crossSquishFactor = 0.f;
// make spacers have zero size so they don't affect spacing calculations
for (auto& node : CCArrayExt<CCNode>(nodes)) {
if (auto spacer = typeinfo_cast<SpacerNode*>(node)) {
spacer->setContentSize(CCSizeZero);
}
}
// fit everything into rows while possible
size_t ix = 0;
auto newNodes = nodes->shallowCopy();

View file

@ -139,7 +139,11 @@ struct CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> {
// show crash info
static bool shownLastCrash = false;
if (Loader::get()->didLastLaunchCrash() && !shownLastCrash) {
if (
Loader::get()->didLastLaunchCrash() &&
!shownLastCrash &&
!Mod::get()->template getSettingValue<bool>("disable-last-crashed-popup")
) {
shownLastCrash = true;
auto popup = createQuickPopup(
"Crashed",
@ -198,12 +202,7 @@ struct CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> {
}
void onMissingTextures(CCObject*) {
static bool shownInfoPopup = false;
if (shownInfoPopup) {
return this->onGeode(nullptr);
}
shownInfoPopup = true;
#ifdef GEODE_IS_DESKTOP
try {
@ -218,7 +217,7 @@ struct CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> {
"and <cy>unzip its contents</c> into <cb>geode/update/resources</c>.\n"
"Afterwards, <cg>restart the game</c>.\n"
"You may also continue without installing resources, but be aware that "
"the game <cr>will crash</c>.",
"you won't be able to open <cr>the Geode menu</c>.",
"Dismiss", "Open Github",
[](auto, bool btn2) {
if (btn2) {

View file

@ -35,7 +35,9 @@ void setIDs(CCNode* node, int startIndex, Args... args) {
static void switchToMenu(CCNode* node, CCMenu* menu) {
if (!node || !menu) return;
auto worldPos = node->getParent()->convertToWorldSpace(node->getPosition());
auto worldPos = node->getParent() ?
node->getParent()->convertToWorldSpace(node->getPosition()) :
node->getPosition();
node->retain();
node->removeFromParent();

View file

@ -0,0 +1,321 @@
#include "AddIDs.hpp"
#include <Geode/modify/CustomizeObjectLayer.hpp>
using namespace geode::prelude;
$register_ids(CustomizeObjectLayer) {
auto winSize = CCDirector::get()->getWinSize();
setIDs(
m_mainLayer, 0,
"alert-bg",
"title-label",
"button-menu",
"selected-channel-label",
"channel-input-bg",
"channel-input",
"text-input-bg",
"text-input",
"glow-label"
);
m_buttonMenu->setID("ok-menu");
setIDs(
m_buttonMenu,
0,
"ok-button",
"info-button",
"base-tab-button",
"detail-tab-button",
"base-hsv-button",
"detail-hsv-button",
"text-tab-button",
"player-color-1-button",
"player-color-2-button",
"light-bg-button",
"default-button",
"channel-1-button",
"channel-2-button",
"channel-3-button",
"channel-4-button",
"channel-5-button",
"channel-6-button",
"channel-7-button",
"channel-8-button",
"channel-9-button",
"channel-custom-button",
"select-channel-up-button",
"select-channel-down-button",
"select-channel-button",
"split-text-button",
"clear-text-button",
"next-free-button",
"copy-button",
"paste-button",
"browse-button",
"glow-toggle"
);
auto tabsLayout = RowLayout::create()
->setAxisAlignment(AxisAlignment::Center)
->setCrossAxisAlignment(AxisAlignment::Center);
tabsLayout->ignoreInvisibleChildren(true);
auto tabsMenu = detachAndCreateMenu(
m_mainLayer,
"tabs-menu",
tabsLayout,
m_buttonMenu->getChildByID("base-tab-button"),
m_buttonMenu->getChildByID("detail-tab-button"),
SpacerNode::create(),
m_buttonMenu->getChildByID("text-tab-button")
);
tabsMenu->setContentSize({ 360.f, 50.f });
tabsMenu->setPositionX(winSize.width / 2);
tabsMenu->updateLayout();
auto specialChannelsMenu = detachAndCreateMenu(
m_mainLayer,
"special-channels-menu",
RowLayout::create()
->setCrossAxisOverflow(false)
->setGrowCrossAxis(true)
->setAxisAlignment(AxisAlignment::Center)
->setCrossAxisAlignment(AxisAlignment::Center)
->setGap(14.f),
m_buttonMenu->getChildByID("player-color-1-button"),
m_buttonMenu->getChildByID("player-color-2-button"),
m_buttonMenu->getChildByID("light-bg-button"),
m_buttonMenu->getChildByID("default-button")
);
specialChannelsMenu->setContentSize({ 350.f, 50.f });
specialChannelsMenu->setPositionX(winSize.width / 2);
specialChannelsMenu->updateLayout();
auto channelsMenu = detachAndCreateMenu(
m_mainLayer,
"channels-menu",
RowLayout::create()
->setCrossAxisOverflow(false)
->setGrowCrossAxis(true)
->setAxisAlignment(AxisAlignment::Center)
->setCrossAxisAlignment(AxisAlignment::Center)
->setGap(20.f),
m_buttonMenu->getChildByID("channel-1-button"),
m_buttonMenu->getChildByID("channel-2-button"),
m_buttonMenu->getChildByID("channel-3-button"),
m_buttonMenu->getChildByID("channel-4-button"),
m_buttonMenu->getChildByID("channel-5-button"),
m_buttonMenu->getChildByID("channel-6-button"),
m_buttonMenu->getChildByID("channel-7-button"),
m_buttonMenu->getChildByID("channel-8-button"),
m_buttonMenu->getChildByID("channel-9-button"),
m_buttonMenu->getChildByID("channel-custom-button")
);
channelsMenu->setContentSize({ 350.f, 100.f });
channelsMenu->setPosition(winSize.width / 2, winSize.height / 2 - 25.f);
channelsMenu->updateLayout();
auto selectedChannelMenu = detachAndCreateMenu(
m_mainLayer,
"selected-channel-menu",
nullptr,
m_buttonMenu->getChildByID("select-channel-button"),
m_mainLayer->getChildByID("selected-channel-label")
);
selectedChannelMenu->setContentSize({ 120.f, 40.f });
selectedChannelMenu->setPosition(
winSize.width / 2 + 110.f,
winSize.height / 2 - 90.f
);
if (auto label = selectedChannelMenu->getChildByID("selected-channel-label")) {
label->setPosition(75.f, 20.f);
}
if (auto button = selectedChannelMenu->getChildByID("select-channel-button")) {
button->setPosition(100.f, 20.f);
}
auto togglesMenu = detachAndCreateMenu(
m_mainLayer,
"toggles-menu",
nullptr,
m_mainLayer->getChildByID("glow-label"),
m_buttonMenu->getChildByID("glow-toggle")
);
togglesMenu->setContentSize({ 75.f, 120.f });
togglesMenu->setPosition(55.f, 90.f);
if (auto label = togglesMenu->getChildByID("glow-label")) {
label->setPosition(57.f, 20.f);
}
if (auto toggle = togglesMenu->getChildByID("glow-toggle")) {
toggle->setPosition(57.f, 5.f);
}
auto baseHSVMenu = detachAndCreateMenu(
m_mainLayer,
"base-hsv-menu",
RowLayout::create()
->setAxisAlignment(AxisAlignment::Start),
m_buttonMenu->getChildByID("base-hsv-button")
);
baseHSVMenu->setContentSize({ 80.f, 60.f });
baseHSVMenu->setPositionX(winSize.width / 2 - 132.5f);
baseHSVMenu->updateLayout();
auto detailHSVMenu = detachAndCreateMenu(
m_mainLayer,
"detail-hsv-menu",
RowLayout::create()
->setAxisAlignment(AxisAlignment::Start),
m_buttonMenu->getChildByID("detail-hsv-button")
);
detailHSVMenu->setContentSize({ 80.f, 60.f });
detailHSVMenu->setPositionX(baseHSVMenu->getPositionX());
detailHSVMenu->updateLayout();
auto nextFreeMenu = detachAndCreateMenu(
m_mainLayer,
"next-free-menu",
RowLayout::create()
->setAxisAlignment(AxisAlignment::Start),
m_buttonMenu->getChildByID("next-free-button")
);
nextFreeMenu->setContentSize({ 120.f, 60.f });
nextFreeMenu->setPositionX(winSize.width / 2 - 110.f);
nextFreeMenu->updateLayout();
auto textActionsMenu = detachAndCreateMenu(
m_mainLayer,
"text-actions-menu",
RowLayout::create()
->setAxisAlignment(AxisAlignment::End)
->setAxisReverse(true),
m_buttonMenu->getChildByID("split-text-button")
);
textActionsMenu->setContentSize({ 120.f, 60.f });
textActionsMenu->setPositionX(winSize.width / 2 + 110.f);
textActionsMenu->updateLayout();
auto clearTextMenu = detachAndCreateMenu(
m_mainLayer,
"clear-text-menu",
nullptr,
m_buttonMenu->getChildByID("clear-text-button")
);
auto infoMenu = detachAndCreateMenu(
m_mainLayer,
"info-menu",
RowLayout::create()
->setAxisAlignment(AxisAlignment::End)
->setAxisReverse(true),
m_buttonMenu->getChildByID("info-button")
);
infoMenu->setContentSize({ 80.f, 60.f });
infoMenu->setPosition(winSize.width / 2 + 132.5f, baseHSVMenu->getPositionY());
infoMenu->updateLayout();
auto browseMenu = detachAndCreateMenu(
m_mainLayer,
"browse-menu",
ColumnLayout::create()
->setAxisAlignment(AxisAlignment::Start)
->setAxisReverse(true),
m_buttonMenu->getChildByID("browse-button")
);
browseMenu->setContentSize({ 100.f, 140.f });
browseMenu->setPositionY(winSize.height / 2 - 70.f);
browseMenu->updateLayout();
auto copyPasteMenu = detachAndCreateMenu(
m_mainLayer,
"copy-paste-menu",
ColumnLayout::create()
->setAxisAlignment(AxisAlignment::End)
->setAxisReverse(true),
m_buttonMenu->getChildByID("copy-button"),
m_buttonMenu->getChildByID("paste-button")
);
copyPasteMenu->setContentSize({ 100.f, 140.f });
copyPasteMenu->setPositionY(winSize.height / 2 + 100.f);
copyPasteMenu->updateLayout();
auto selectChannelMenu = detachAndCreateMenu(
m_mainLayer,
"select-channel-menu",
nullptr,
m_mainLayer->getChildByID("channel-input-bg"),
m_mainLayer->getChildByID("channel-input"),
m_buttonMenu->getChildByID("select-channel-up-button"),
m_buttonMenu->getChildByID("select-channel-down-button")
);
selectChannelMenu->setContentSize({ 60.f, 140.f });
if (auto bg = selectChannelMenu->getChildByID("channel-input-bg")) {
bg->setPosition({ 30.f, 70.f });
}
if (auto input = selectChannelMenu->getChildByID("channel-input")) {
input->setPosition({ 30.f, 70.f });
}
if (auto btn = selectChannelMenu->getChildByID("select-channel-up-button")) {
btn->setPosition({ 30.f, 110.f });
}
if (auto btn = selectChannelMenu->getChildByID("select-channel-down-button")) {
btn->setPosition({ 30.f, 30.f });
}
}
struct CustomizeObjectLayerIDs : Modify<CustomizeObjectLayerIDs, CustomizeObjectLayer> {
static void onModify(auto& self) {
if (!self.setHookPriority("CustomizeObjectLayer::init", GEODE_ID_PRIORITY)) {
log::warn("Failed to set CustomizeObjectLayer::init hook priority, node IDs may not work properly");
}
}
void toggleMenuIf(const char* id, int mode) {
if (auto menu = m_mainLayer->getChildByID(id)) {
menu->setVisible(m_selectedMode == mode);
}
}
void toggleMenuIfNot(const char* id, int mode) {
if (auto menu = m_mainLayer->getChildByID(id)) {
menu->setVisible(m_selectedMode != mode);
}
}
void toggleVisible() {
CustomizeObjectLayer::toggleVisible();
// have to manually toggle menu visibility to allow touches being correctly passed
this->toggleMenuIf("base-hsv-menu", 1);
this->toggleMenuIf("detail-hsv-menu", 2);
this->toggleMenuIf("text-actions-menu", 3);
this->toggleMenuIf("clear-text-menu", 3);
this->toggleMenuIfNot("next-free-menu", 3);
this->toggleMenuIfNot("toggles-menu", 3);
this->toggleMenuIfNot("channels-menu", 3);
this->toggleMenuIfNot("special-channels-menu", 3);
this->toggleMenuIfNot("selected-channel-menu", 3);
this->toggleMenuIfNot("browse-menu", 3);
this->toggleMenuIfNot("copy-paste-menu", 3);
this->toggleMenuIfNot("select-channel-menu", 3);
}
bool init(GameObject* obj, CCArray* objs) {
if (!CustomizeObjectLayer::init(obj, objs))
return false;
NodeIDs::get()->provide(this);
this->toggleVisible();
return true;
}
};

View file

@ -5,6 +5,7 @@ using namespace geode::prelude;
#if defined(GEODE_IS_MACOS)
#include "mac/main.mm"
#include "mac/crashlog.mm"
#include "mac/FileWatcher.mm"
#include "mac/util.mm"

View file

@ -1,47 +0,0 @@
#include <Geode/DefaultInclude.hpp>
#if defined(GEODE_IS_MACOS)
#include "../load.hpp"
#include <dlfcn.h>
#include <mach-o/dyld.h>
#include <unistd.h>
#include <thread>
using namespace geode::prelude;
std::length_error::~length_error() _NOEXCEPT {} // do not ask...
// camila has an old ass macos and this function turned
// from dynamic to static thats why she needs to define it
// this is what old versions does to a silly girl
void dynamicEntry() {
auto dylib = dlopen("GeodeBootstrapper.dylib", RTLD_NOLOAD);
dlclose(dylib);
auto workingDir = dirs::getGameDir();
auto libDir = workingDir / "Frameworks";
auto updatesDir = workingDir / "geode" / "update";
auto error = std::error_code();
if (ghc::filesystem::exists(updatesDir / "GeodeBootstrapper.dylib", error) && !error) {
ghc::filesystem::rename(
updatesDir / "GeodeBootstrapper.dylib", libDir / "GeodeBootstrapper.dylib", error
);
if (error) return;
}
geodeEntry(nullptr);
}
extern "C" __attribute__((visibility("default"))) void dynamicTrigger() {
std::thread(&dynamicEntry).detach();
}
// remove when we can figure out how to not remove it
auto dynamicTriggerRef = &dynamicTrigger;
#endif

View file

@ -0,0 +1,66 @@
#include <Geode/DefaultInclude.hpp>
#if defined(GEODE_IS_MACOS)
#import <Cocoa/Cocoa.h>
#include "../load.hpp"
#include <dlfcn.h>
#include <mach-o/dyld.h>
#include <unistd.h>
#include <tulip/TulipHook.hpp>
#include <array>
#include <thread>
using namespace geode::prelude;
std::length_error::~length_error() _NOEXCEPT {} // do not ask...
// camila has an old ass macos and this function turned
// from dynamic to static thats why she needs to define it
// this is what old versions does to a silly girl
extern "C" void fake() {}
void applicationDidFinishLaunchingHook(void* self, SEL sel, NSNotification* notification) {
// updateGeode();
std::array<uint8_t, 6> patchBytes = {
0x55,
0x48, 0x89, 0xe5,
0x41, 0x57
};
auto res = tulip::hook::writeMemory((void*)(base::get() + 0x69a0), patchBytes.data(), 6);
if (!res)
return;
int exitCode = geodeEntry(nullptr);
if (exitCode != 0)
return;
return reinterpret_cast<void(*)(void*, SEL, NSNotification*)>(geode::base::get() + 0x69a0)(self, sel, notification);
}
bool loadGeode() {
auto detourAddr = reinterpret_cast<uintptr_t>(&applicationDidFinishLaunchingHook) - geode::base::get() - 0x69a5;
auto detourAddrPtr = reinterpret_cast<uint8_t*>(&detourAddr);
std::array<uint8_t, 5> patchBytes = {
0xe9, detourAddrPtr[0], detourAddrPtr[1], detourAddrPtr[2], detourAddrPtr[3]
};
auto res = tulip::hook::writeMemory((void*)(base::get() + 0x69a0), patchBytes.data(), 5);
if (!res)
return false;
return true;
}
__attribute__((constructor)) void _entry() {
if (!loadGeode())
return;
}
#endif

View file

@ -75,25 +75,14 @@ void utils::web::openLinkInBrowser(std::string const& url) {
@implementation FileDialog
+(Result<std::vector<ghc::filesystem::path>>) filePickerWithMode:(file::PickMode)mode options:(file::FilePickOptions const&)options multiple:(bool)mult {
NSOpenPanel* panel = [NSOpenPanel openPanel];
NSSavePanel* panel;
if (mode == file::PickMode::SaveFile)
panel = [NSSavePanel savePanel];
else
panel = [NSOpenPanel openPanel];
// allowed files
NSMutableArray* allowed = [NSMutableArray array];
[panel setCanCreateDirectories: TRUE];
for (auto& f : options.filters) {
for (auto& i : f.files) {
auto nsstr = [NSString stringWithUTF8String: i.c_str()];
if (![allowed containsObject: nsstr])
[allowed addObject: nsstr];
}
}
if (options.filters.size())
[panel setAllowedFileTypes: allowed];
// multiple
[panel setAllowsMultipleSelection: mult];
// default path
if (options.defaultPath) {
@ -102,8 +91,36 @@ void utils::web::openLinkInBrowser(std::string const& url) {
}
// other
[panel setCanChooseDirectories: NO];
[panel setCanChooseFiles: YES];
if (mode != file::PickMode::SaveFile) {
auto openPanel = (NSOpenPanel*)panel;
if (mode == file::PickMode::OpenFile){
[openPanel setCanChooseDirectories: NO];
[openPanel setCanChooseFiles: YES];
}
else {
[openPanel setCanChooseDirectories: YES];
[openPanel setCanChooseFiles: NO];
}
[openPanel setAllowsMultipleSelection: mult];
// allowed files
// TODO: allowed files using the NSOpenSavePanelDelegate xd
// NSMutableArray* allowed = [NSMutableArray array];
// for (auto& f : options.filters) {
// for (auto& i : f.files) {
// auto nsstr = [NSString stringWithUTF8String: i.c_str()];
// if (![allowed containsObject: nsstr])
// [allowed addObject: nsstr];
// }
// }
// if (options.filters.size())
// [panel setAllowedFileTypes: allowed];
}
// run thing
@ -111,11 +128,16 @@ void utils::web::openLinkInBrowser(std::string const& url) {
if (result == NSModalResponseOK) {
std::vector<ghc::filesystem::path> fileURLs;
for (NSURL* i in panel.URLs) {
fileURLs.push_back(std::string(i.path.UTF8String));
if (mode == file::PickMode::SaveFile) {
fileURLs.push_back(std::string([[[panel URL] path] UTF8String]));
}
else {
auto openPanel = (NSOpenPanel*)panel;
for (NSURL* i in openPanel.URLs) {
fileURLs.push_back(std::string(i.path.UTF8String));
}
}
return Ok(fileURLs);
} else {
return Err("File picker cancelled");
@ -143,10 +165,11 @@ Result<std::vector<ghc::filesystem::path>> utils::file::pickFiles(
}
CCPoint cocos::getMousePos() {
auto frame = NSApp.mainWindow.frame;
auto scaleFactor = CCPoint(CCDirector::get()->getWinSize()) / ccp(frame.size.width, frame.size.height);
auto windowFrame = NSApp.mainWindow.frame;
auto viewFrame = NSApp.mainWindow.contentView.frame;
auto scaleFactor = CCPoint(CCDirector::get()->getWinSize()) / ccp(viewFrame.size.width, viewFrame.size.height);
auto mouse = [NSEvent mouseLocation];
return ccp(mouse.x - frame.origin.x, mouse.y - frame.origin.y) * scaleFactor;
return ccp(mouse.x - windowFrame.origin.x, mouse.y - windowFrame.origin.y) * scaleFactor;
}
ghc::filesystem::path dirs::getGameDir() {

View file

@ -91,8 +91,7 @@ bool ModInfoPopup::init(ModInfo const& info, ModListLayer* list) {
versionLabel->setColor({0, 255, 0});
m_mainLayer->addChild(versionLabel);
CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
this->registerWithTouchDispatcher();
this->setTouchEnabled(true);
m_detailsArea = MDTextArea::create(
(info.details() ? info.details().value() : "### No description provided."),

View file

@ -107,8 +107,7 @@ protected:
);
m_menu->addChild(m_resetBtn);
CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
m_menu->registerWithTouchDispatcher();
m_menu->setTouchEnabled(true);
if (!this->setup(setting, width)) return false;

View file

@ -25,9 +25,7 @@ bool ModSettingsPopup::setup(Mod* mod) {
auto layer = ScrollLayer::create(layerSize);
layer->setPosition(winSize / 2 - layerSize / 2);
CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
layer->registerWithTouchDispatcher();
layer->setTouchEnabled(true);
float totalHeight = .0f;
std::vector<CCNode*> rendered;

View file

@ -128,8 +128,7 @@ bool MDTextArea::init(std::string const& str, CCSize const& size) {
m_content->setZOrder(2);
m_scrollLayer->m_contentLayer->addChild(m_content);
CCDirector::sharedDirector()->getTouchDispatcher()->incrementForcePrio(2);
m_scrollLayer->registerWithTouchDispatcher();
m_scrollLayer->setTouchEnabled(true);
this->addChild(m_scrollLayer);

View file

@ -7,7 +7,7 @@ using namespace geode::prelude;
constexpr auto NOTIFICATION_FADEIN = .3f;
constexpr auto NOTIFICATION_FADEOUT = 1.f;
Ref<CCArray> Notification::s_queue = CCArray::create();
Ref<CCArray> Notification::s_queue = nullptr;
bool Notification::init(std::string const& text, CCSprite* icon, float time) {
if (!CCNodeRGBA::init()) return false;
@ -55,6 +55,9 @@ void Notification::updateLayout() {
void Notification::showNextNotification() {
m_showing = false;
if (!s_queue) {
s_queue = CCArray::create();
}
SceneManager::get()->forget(this);
// remove self from front of queue
s_queue->removeFirstObject();
@ -156,6 +159,9 @@ void Notification::waitAndHide() {
}
void Notification::show() {
if (!s_queue) {
s_queue = CCArray::create();
}
if (!m_showing) {
if (!s_queue->containsObject(this)) {
s_queue->addObject(this);

View file

@ -177,7 +177,7 @@ bool Scrollbar::init(CCScrollLayerExt* target) {
this->addChild(m_track);
this->addChild(m_thumb);
this->registerWithTouchDispatcher();
this->setTouchEnabled(true);
return true;
}

View file

@ -64,4 +64,15 @@ GEODE_MEMBER_CHECK(SetupPulsePopup, m_pulseMode, 0x38c);
// ColorSelectPopup
GEODE_MEMBER_CHECK(ColorSelectPopup, m_copyColor, 0x372);
// LevelInfoLayer
GEODE_MEMBER_CHECK(LevelInfoLayer, m_level, 0x1c0);
// LevelBrowserLayer
GEODE_MEMBER_CHECK(LevelBrowserLayer, m_leftArrow, 0x1a8);
GEODE_MEMBER_CHECK(LevelBrowserLayer, m_searchObject, 0x1d8);
GEODE_MEMBER_CHECK(LevelBrowserLayer, m_itemCount, 0x208);
// LocalLevelManager
GEODE_MEMBER_CHECK(LocalLevelManager, m_localLevels, 0x140);
#endif