This commit is contained in:
hjfod 2023-03-08 08:38:25 +02:00
commit b88eda0fde
50 changed files with 310 additions and 232 deletions

View file

@ -17,7 +17,7 @@ jobs:
os_identifier: "win" os_identifier: "win"
os: windows-2019 os: windows-2019
prefixes: '' prefixes: ''
extra_flags: '-G "Visual Studio 16 2019" -T host=x86 -A win32 -DGEODE_DEBUG=On' extra_flags: '-T host=x86 -A win32 -DGEODE_DEBUG=On'
out_paths: './bin/nightly/Geode.dll ./bin/nightly/GeodeBootstrapper.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'
cli_cmd: '' cli_cmd: ''
@ -141,5 +141,6 @@ jobs:
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
files: ./geode-nightly-mac.zip ./geode-nightly-win.zip files: ./geode-nightly-mac.zip ./geode-nightly-win.zip
release: Nightly release: nightly
tag: nightly
prerelease: true prerelease: true

View file

@ -1,9 +1,16 @@
# Geode Changelog # Geode Changelog
## v1.0.0-beta.9
* Fix multiple modifiers not being able to have fields on same class due to having same field index (7710fa9)
* Add `Result::ok` and `Result::err` for converting the `Result` into `std::optional` (4a15afc)
## v1.0.0-beta.8 ## v1.0.0-beta.8
* Unload the mod even when first time warning pops up (63b4774) * Unload the mod even when first time warning pops up (63b4774)
* Make log not throw, but warn on invalid format (6aba7cf)
* Error when address of a function returns nullptr when hooking (724a9d3) * Error when address of a function returns nullptr when hooking (724a9d3)
* Add support for Geode CLI v2.0.0 (which has not been released yet) (088ac7b, deadb58)
* Logging no longer causes a crash on invalid formats, but instead just warns (6aba7cf)
* `file::pickFile` now uses the last item in the default path as the default filename to save/open (5c9ee08)
* Fix `EditorPauseLayer` crashing constantly due to some members being accidentally set to `nullptr` (33a91d6)
## v1.0.0-beta.7 ## v1.0.0-beta.7
* Add `Mod::getResourcesDir` for getting the mod resources directory (0055032) * Add `Mod::getResourcesDir` for getting the mod resources directory (0055032)

View file

@ -866,7 +866,7 @@ class CreatorLayer : cocos2d::CCLayer {
void onFameLevels(cocos2d::CCObject*) = win 0x4ee70; void onFameLevels(cocos2d::CCObject*) = win 0x4ee70;
void onMapPacks(cocos2d::CCObject*) = win 0x4efb0; void onMapPacks(cocos2d::CCObject*) = win 0x4efb0;
void onOnlineLevels(cocos2d::CCObject*) = win 0x4ef60; void onOnlineLevels(cocos2d::CCObject*) = win 0x4ef60;
void onGauntlets(cocos2d::CCObject*) = win 0x4f0a0; void onGauntlets(cocos2d::CCObject*) = mac 0x142b20, win 0x4f0a0;
void onSecretVault(cocos2d::CCObject*) = win 0x4f1d0; void onSecretVault(cocos2d::CCObject*) = win 0x4f1d0;
void onTreasureRoom(cocos2d::CCObject*) = win 0x4f540; void onTreasureRoom(cocos2d::CCObject*) = win 0x4f540;
virtual void sceneWillResume() = win 0x4fb50; virtual void sceneWillResume() = win 0x4fb50;
@ -878,6 +878,13 @@ class CurrencyRewardLayer : cocos2d::CCLayer {
inline CurrencyRewardLayer() {} inline CurrencyRewardLayer() {}
~CurrencyRewardLayer() = mac 0x447950, win 0x4ffb0; ~CurrencyRewardLayer() = mac 0x447950, win 0x4ffb0;
virtual void update(float) = mac 0x44a5c0, win 0x52350; virtual void update(float) = mac 0x44a5c0, win 0x52350;
static CurrencyRewardLayer* create(
int, int, int,
CurrencySpriteType, int,
CurrencySpriteType, int,
cocos2d::CCPoint, CurrencyRewardType, float
) = win 0x50050;
} }
class CurrencyRewardDelegate { class CurrencyRewardDelegate {
@ -3476,7 +3483,7 @@ class LeaderboardManagerDelegate {}
class LeaderboardsLayer : cocos2d::CCLayer { class LeaderboardsLayer : cocos2d::CCLayer {
static LeaderboardsLayer* create(LeaderboardState state) = win 0x158710; static LeaderboardsLayer* create(LeaderboardState state) = win 0x158710;
bool init(LeaderboardState state) = win 0x1587b0; bool init(LeaderboardState state) = mac 0x29f6d0, win 0x1587b0;
} }
class LevelBrowserLayer : cocos2d::CCLayer { class LevelBrowserLayer : cocos2d::CCLayer {
@ -3763,7 +3770,7 @@ class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDeleg
class LevelLeaderboard : FLAlertLayer { class LevelLeaderboard : FLAlertLayer {
void onChangeType(cocos2d::CCObject* sender) = win 0x17d090; void onChangeType(cocos2d::CCObject* sender) = win 0x17d090;
void onGarage(cocos2d::CCObject* sender) = win 0x17d1b0; void onGarage(cocos2d::CCObject* sender) = win 0x17d1b0;
bool init(GJGameLevel* level, int type) = win 0x17c4f0; bool init(GJGameLevel* level, int type) = mac 0x20d710, win 0x17c4f0;
static LevelLeaderboard* create(GJGameLevel* level, LevelLeaderboardType leaderboardType) = win 0x17c440; static LevelLeaderboard* create(GJGameLevel* level, LevelLeaderboardType leaderboardType) = win 0x17c440;
} }
@ -3929,6 +3936,7 @@ class LocalLevelManager : cocos2d::CCNode {
inline static LocalLevelManager* get() { inline static LocalLevelManager* get() {
return LocalLevelManager::sharedState(); return LocalLevelManager::sharedState();
} }
bool init() = mac 0x2384e0;
PAD = mac 0x10, win 0x1C; PAD = mac 0x10, win 0x1C;
cocos2d::CCDictionary* m_loadData; cocos2d::CCDictionary* m_loadData;
@ -4284,7 +4292,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate,
void shouldBlend(int) = mac 0x771b0; void shouldBlend(int) = mac 0x771b0;
void showCompleteEffect() = mac 0x738e0, win 0x1fe060; void showCompleteEffect() = mac 0x738e0, win 0x1fe060;
void showCompleteText() = mac 0x73be0, win 0x1fda90; void showCompleteText() = mac 0x73be0, win 0x1fda90;
void showEndLayer() = mac 0x74450; void showEndLayer() = mac 0x74450, win 0x1ffd00;
void showHint() = mac 0x7deb0; void showHint() = mac 0x7deb0;
void showNewBest(bool, int, int, bool, bool, bool) = mac 0x74580, win 0x1fe3a0; void showNewBest(bool, int, int, bool, bool, bool) = mac 0x74580, win 0x1fe3a0;
void showRetryLayer() = mac 0x75ba0; void showRetryLayer() = mac 0x75ba0;
@ -5406,11 +5414,15 @@ class VideoOptionsLayer : FLAlertLayer {
} }
class LevelTools { class LevelTools {
static gd::string base64EncodeString(gd::string) = win 0x18b310; static gd::string base64EncodeString(gd::string) = mac 0x294470, win 0x18b310;
static gd::string base64DecodeString(gd::string) = mac 0x294510, win 0x18b3b0; static gd::string base64DecodeString(gd::string) = mac 0x294510, win 0x18b3b0;
static GJGameLevel *getLevel(int, bool) = win 0x189370; static GJGameLevel* getLevel(int, bool) = mac 0x2908c0, win 0x189370;
static bool verifyLevelIntegrity(gd::string, int) = win 0x18b180; static bool verifyLevelIntegrity(gd::string, int) = mac 0x294360, win 0x18b180;
static float xPosForTime(float, cocos2d::CCArray*, int) = win 0x18acd0; static float xPosForTime(float, cocos2d::CCArray*, int) = mac 0x293d90, win 0x18acd0;
static float timeForXPos(float, cocos2d::CCArray*, int) = win 0x18ae70; static float timeForXPos(float, cocos2d::CCArray*, int) = mac 0x293eb0, win 0x18ae70;
static gd::string getAudioFilename(int) = mac 0x292840;
static gd::string getAudioTitle(int) = mac 0x2922f0;
static gd::string getArtistForAudio(int) = mac 0x292d90;
static gd::string getURLForAudio(int) = mac 0x292f10;
} }
// clang-format on // clang-format on

View file

@ -34,10 +34,10 @@ public:
static constexpr auto CLASS_NAME = "{class_name}"; static constexpr auto CLASS_NAME = "{class_name}";
)GEN"; )GEN";
char const* monostate_constructor = R"GEN( GEODE_MONOSTATE_CONSTRUCTOR_GD({class_name}, {first_base}) char const* custom_constructor = R"GEN( GEODE_CUSTOM_CONSTRUCTOR_GD({class_name}, {first_base})
)GEN"; )GEN";
char const* monostate_constructor_cutoff = R"GEN( GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF({class_name}, {first_base}) char const* custom_constructor_cutoff = R"GEN( GEODE_CUSTOM_CONSTRUCTOR_CUTOFF({class_name}, {first_base})
)GEN"; )GEN";
char const* function_definition = R"GEN( char const* function_definition = R"GEN(
@ -181,8 +181,8 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
if (!cls.superclasses.empty()) { if (!cls.superclasses.empty()) {
single_output += fmt::format( single_output += fmt::format(
can_find(cls.superclasses[0], "cocos2d") can_find(cls.superclasses[0], "cocos2d")
? format_strings::monostate_constructor_cutoff ? format_strings::custom_constructor_cutoff
: format_strings::monostate_constructor, : format_strings::custom_constructor,
fmt::arg("class_name", cls.name), fmt::arg("class_name", cls.name),
fmt::arg("first_base", cls.superclasses[0]) fmt::arg("first_base", cls.superclasses[0])
); );

View file

@ -85,13 +85,13 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments}); reinterpret_cast<FunctionType>(func)(this{parameter_comma}{arguments});
// we need to construct it back so that it uhhh ummm doesnt crash // we need to construct it back so that it uhhh ummm doesnt crash
// while going to the child destructors // while going to the child destructors
auto thing = new (this) {class_name}(std::monostate(), sizeof({class_name})); auto thing = new (this) {class_name}(geode::CutoffConstructor, sizeof({class_name}));
CCDestructor::lock(this) = true; CCDestructor::lock(this) = true;
}} }}
)GEN"; )GEN";
char const* declare_constructor = R"GEN( char const* declare_constructor = R"GEN(
{class_name}::{function_name}({parameters}) : {class_name}(std::monostate(), sizeof({class_name})) {{ {class_name}::{function_name}({parameters}) : {class_name}(geode::CutoffConstructor, sizeof({class_name})) {{
// here we construct it as normal as we can, then destruct it // here we construct it as normal as we can, then destruct it
// using the generated functions. this ensures no memory gets leaked // using the generated functions. this ensures no memory gets leaked
// no crashes :pray: // no crashes :pray:

View file

@ -69,28 +69,74 @@ namespace cocos2d::extension {}
#define GEODE_EXPAND(x) x #define GEODE_EXPAND(x) x
#define GEODE_INVOKE(macro, ...) GEODE_EXPAND(macro(__VA_ARGS__)) #define GEODE_INVOKE(macro, ...) GEODE_EXPAND(macro(__VA_ARGS__))
#define GEODE_FILL_CONSTRUCTOR(Class_, Offset_) \ namespace geode {
Class_(std::monostate, size_t fill) : \ struct ZeroConstructorType {};
Class_({}, std::memset(reinterpret_cast<std::byte*>(this) + Offset_, 0, fill - Offset_)) {} \
Class_(std::monostate, void*)
#define GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(Class_) \ static constexpr auto ZeroConstructor = ZeroConstructorType();
struct CutoffConstructorType {};
static constexpr auto CutoffConstructor = CutoffConstructorType();
}
#define GEODE_CUSTOM_CONSTRUCTOR_BEGIN(Class_) \
GEODE_ZERO_CONSTRUCTOR_BEGIN(Class_) \
GEODE_CUTOFF_CONSTRUCTOR_BEGIN(Class_)
#define GEODE_CUSTOM_CONSTRUCTOR_COCOS(Class_, Base_) \
GEODE_ZERO_CONSTRUCTOR(Class_, Base_) \
GEODE_CUTOFF_CONSTRUCTOR_COCOS(Class_, Base_)
#define GEODE_CUSTOM_CONSTRUCTOR_GD(Class_, Base_) \
GEODE_ZERO_CONSTRUCTOR(Class_, Base_) \
GEODE_CUTOFF_CONSTRUCTOR_GD(Class_, Base_)
#define GEODE_CUSTOM_CONSTRUCTOR_CUTOFF(Class_, Base_) \
GEODE_ZERO_CONSTRUCTOR(Class_, Base_) \
GEODE_CUTOFF_CONSTRUCTOR_CUTOFF(Class_, Base_)
#define GEODE_ZERO_CONSTRUCTOR_BEGIN(Class_) \
Class_(geode::ZeroConstructorType, void*) {} \
Class_(geode::ZeroConstructorType, size_t fill) : \
Class_(geode::ZeroConstructor, std::memset(static_cast<void*>(this), 0, fill)) {} \
Class_(geode::ZeroConstructorType) : Class_(geode::ZeroConstructor, nullptr) {}
#define GEODE_ZERO_CONSTRUCTOR(Class_, Base_) \
Class_(geode::ZeroConstructorType, size_t fill) : Base_(geode::ZeroConstructor, fill) {} \
Class_(geode::ZeroConstructorType) : Base_(geode::ZeroConstructor, sizeof(Class_)) {}
#define GEODE_FILL_CONSTRUCTOR(Class_, Offset_) \
Class_(geode::CutoffConstructorType, size_t fill) : \
Class_( \
geode::CutoffConstructor, \
std::memset(reinterpret_cast<std::byte*>(this) + Offset_, 0, fill - Offset_) \
) {} \
Class_(geode::CutoffConstructorType, void*)
#define GEODE_CUTOFF_CONSTRUCTOR_BEGIN(Class_) \
GEODE_MACOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){}) \ GEODE_MACOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){}) \
GEODE_IOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){}) GEODE_IOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){})
#define GEODE_MONOSTATE_CONSTRUCTOR_COCOS(Class_, Base_) \ #define GEODE_CUTOFF_CONSTRUCTOR_COCOS(Class_, Base_) \
GEODE_MACOS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) \ GEODE_MACOS(Class_(geode::CutoffConstructorType, size_t fill) \
GEODE_IOS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) : Base_(geode::CutoffConstructor, fill){}) \
GEODE_IOS(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){})
#define GEODE_MONOSTATE_CONSTRUCTOR_GD(Class_, Base_) \ #define GEODE_CUTOFF_CONSTRUCTOR_GD(Class_, Base_) \
GEODE_WINDOWS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) \ GEODE_WINDOWS(Class_(geode::CutoffConstructorType, size_t fill) \
GEODE_MACOS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) \ : Base_(geode::CutoffConstructor, fill){}) \
GEODE_IOS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) GEODE_MACOS(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){}) \
GEODE_IOS(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){})
#define GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF(Class_, Base_) \ #define GEODE_CUTOFF_CONSTRUCTOR_CUTOFF(Class_, Base_) \
GEODE_WINDOWS(GEODE_FILL_CONSTRUCTOR(Class_, sizeof(Base_)) : Base_(){}) \ GEODE_WINDOWS(GEODE_FILL_CONSTRUCTOR(Class_, sizeof(Base_)) : Base_(){}) \
GEODE_MACOS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) \ GEODE_MACOS(Class_(geode::CutoffConstructorType, size_t fill) \
GEODE_IOS(Class_(std::monostate, size_t fill) : Base_({}, fill){}) : Base_(geode::CutoffConstructor, fill){}) \
GEODE_IOS(Class_(geode::CutoffConstructorType, size_t fill) \
: Base_(geode::CutoffConstructor, fill){})
#define GEODE_NUMBER_OF_ARGS(...) \ #define GEODE_NUMBER_OF_ARGS(...) \
GEODE_EXPAND(GEODE_NUMBER_OF_ARGS_(__VA_ARGS__, GEODE_NUMBER_SEQUENCE(), )) GEODE_EXPAND(GEODE_NUMBER_OF_ARGS_(__VA_ARGS__, GEODE_NUMBER_SEQUENCE(), ))

View file

@ -122,6 +122,14 @@ enum class BoomListType {
Artist = 0x14, Artist = 0x14,
}; };
enum class CurrencySpriteType {
// todo
};
enum class CurrencyRewardType {
// todo
};
enum class MenuAnimationType { enum class MenuAnimationType {
Scale = 0, Scale = 0,
Move = 1, Move = 1,

View file

@ -121,6 +121,7 @@ public:
* @js ctor * @js ctor
*/ */
CCDirector(void); CCDirector(void);
GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCDirector, CCObject)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -146,7 +147,7 @@ public:
/** Get the FPS value */ /** Get the FPS value */
inline double getAnimationInterval(void) { return m_dAnimationInterval; } inline double getAnimationInterval(void) { return m_dAnimationInterval; }
/** Set the FPS value. */ /** Set the FPS value. */
virtual void setAnimationInterval(double dValue) = 0; virtual void setAnimationInterval(double dValue) {}
/** Whether or not to display the FPS on the bottom-left corner */ /** Whether or not to display the FPS on the bottom-left corner */
inline bool isDisplayStats(void) { return m_bDisplayStats; } inline bool isDisplayStats(void) { return m_bDisplayStats; }
@ -308,13 +309,13 @@ protected:
/** Stops the animation. Nothing will be drawn. The main loop won't be triggered anymore. /** Stops the animation. Nothing will be drawn. The main loop won't be triggered anymore.
If you don't want to pause your animation call [pause] instead. If you don't want to pause your animation call [pause] instead.
*/ */
virtual void stopAnimation(void) = 0; virtual void stopAnimation(void) {}
/** The main loop is triggered again. /** The main loop is triggered again.
Call this function only if [stopAnimation] was called earlier Call this function only if [stopAnimation] was called earlier
@warning Don't call this function to start the main loop. To run the main loop call runWithScene @warning Don't call this function to start the main loop. To run the main loop call runWithScene
*/ */
virtual void startAnimation(void) = 0; virtual void startAnimation(void) {}
public: public:
/** Draw the scene. /** Draw the scene.
@ -345,7 +346,7 @@ public:
void setDepthTest(bool bOn); void setDepthTest(bool bOn);
protected: protected:
virtual void mainLoop(void) = 0; virtual void mainLoop(void) {}
/** The size in pixels of the surface. It could be different than the screen size. /** The size in pixels of the surface. It could be different than the screen size.
High-res devices might have a higher surface size than the screen size. High-res devices might have a higher surface size than the screen size.

View file

@ -141,6 +141,7 @@ class CC_DLL CCScheduler : public CCObject
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
CCScheduler(); CCScheduler();
GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCScheduler, CCObject)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -140,7 +140,7 @@ public:
* @js ctor * @js ctor
*/ */
CCNode(void); CCNode(void);
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCNode, CCObject) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCNode, CCObject)
/** /**
* Default destructor * Default destructor
@ -1638,7 +1638,7 @@ public:
* @js ctor * @js ctor
*/ */
CCNodeRGBA(); CCNodeRGBA();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCNodeRGBA, CCNode) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCNodeRGBA, CCNode)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -234,7 +234,8 @@ protected:
CCNode* on, CCArray* nodes, CCNode* on, CCArray* nodes,
std::pair<int, int> const& minMaxPrios, std::pair<int, int> const& minMaxPrios,
bool doAutoScale, bool doAutoScale,
float scale, float squish, int prio float scale, float squish, int prio,
size_t depth
) const; ) const;
AxisLayout(Axis); AxisLayout(Axis);

View file

@ -112,7 +112,7 @@ protected:
int m_nUnknown; int m_nUnknown;
) )
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(CCObject) GEODE_CUSTOM_CONSTRUCTOR_BEGIN(CCObject)
CCObject(void); CCObject(void);
/** /**
* @lua NA * @lua NA

View file

@ -46,7 +46,7 @@ public:
* @lua NA * @lua NA
*/ */
CCSet(void); CCSet(void);
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCSet, CCObject) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCSet, CCObject)
/** /**
* @lua NA * @lua NA
*/ */

View file

@ -47,6 +47,7 @@ class CC_DLL CCString : public CCObject
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCString, CCObject)
/** /**
* @lua NA * @lua NA
*/ */

View file

@ -94,7 +94,7 @@ public:
void setBlendFunc(const ccBlendFunc &blendFunc); void setBlendFunc(const ccBlendFunc &blendFunc);
CCDrawNode(); CCDrawNode();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCDrawNode, CCNodeRGBA) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCDrawNode, CCNodeRGBA)
/** listen the event that coming to foreground on Android /** listen the event that coming to foreground on Android
* @js NA * @js NA

View file

@ -139,7 +139,7 @@ public:
* @js ctor * @js ctor
*/ */
CCControl(); CCControl();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCControl, CCLayerRGBA) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCControl, CCLayerRGBA)
virtual bool init(void); virtual bool init(void);
/** /**

View file

@ -58,7 +58,7 @@ public:
virtual void setColorValue(ccColor3B const&); virtual void setColorValue(ccColor3B const&);
) )
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCControlColourPicker, CCControl) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCControlColourPicker, CCControl)
CCControlColourPicker(); CCControlColourPicker();
virtual ~CCControlColourPicker(); virtual ~CCControlColourPicker();

View file

@ -54,7 +54,7 @@ class CC_DLL CCScale9Sprite : public CCNodeRGBA
{ {
public: public:
CCScale9Sprite(); CCScale9Sprite();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCScale9Sprite, CCNodeRGBA) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCScale9Sprite, CCNodeRGBA)
virtual ~CCScale9Sprite(); virtual ~CCScale9Sprite();
public: public:

View file

@ -69,7 +69,7 @@ public:
* @js ctor * @js ctor
*/ */
CCScrollView(); CCScrollView();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCScrollView, CCLayer) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCScrollView, CCLayer)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -59,7 +59,7 @@ class CC_DLL CCKeypadHandler : public CCObject
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCKeypadHandler, CCObject) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCKeypadHandler, CCObject)
inline CCKeypadHandler() = default; inline CCKeypadHandler() = default;
virtual ~CCKeypadHandler(void); virtual ~CCKeypadHandler(void);

View file

@ -198,7 +198,7 @@ public:
* @js ctor * @js ctor
*/ */
CCLabelBMFont(); CCLabelBMFont();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLabelBMFont, CCSpriteBatchNode) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCLabelBMFont, CCSpriteBatchNode)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -63,6 +63,7 @@ public:
* @js ctor * @js ctor
*/ */
CCLabelTTF(); CCLabelTTF();
GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCLabelTTF, CCSprite)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -75,7 +75,7 @@ public:
* @js ctor * @js ctor
*/ */
CCLayer(); CCLayer();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLayer, CCNode) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCLayer, CCNode)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -233,7 +233,7 @@ public:
* @js ctor * @js ctor
*/ */
CCLayerRGBA(); CCLayerRGBA();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLayerRGBA, CCLayer) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCLayerRGBA, CCLayer)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -290,7 +290,7 @@ public:
* @js ctor * @js ctor
*/ */
CCLayerColor(); CCLayerColor();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCLayerColor, CCLayerRGBA) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCLayerColor, CCLayerRGBA)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -63,7 +63,7 @@ public:
* @js ctor * @js ctor
*/ */
CCScene(); CCScene();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCScene, CCNode) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCScene, CCNode)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -64,7 +64,7 @@ public:
* @js ctor * @js ctor
*/ */
CCMenu() : m_pSelectedItem(NULL) {} CCMenu() : m_pSelectedItem(NULL) {}
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenu, CCLayerRGBA) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCMenu, CCLayerRGBA)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -71,7 +71,7 @@ public:
, m_pfnSelector(NULL) , m_pfnSelector(NULL)
, m_nScriptTapHandler(0) , m_nScriptTapHandler(0)
{} {}
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenuItem, CCNodeRGBA) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCMenuItem, CCNodeRGBA)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -139,7 +139,7 @@ public:
: m_pLabel(NULL) : m_pLabel(NULL)
, m_fOriginalScale(0.0) , m_fOriginalScale(0.0)
{} {}
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenuItemLabel, CCMenuItem) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCMenuItemLabel, CCMenuItem)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA
@ -292,7 +292,7 @@ public:
,m_pSelectedImage(NULL) ,m_pSelectedImage(NULL)
,m_pDisabledImage(NULL) ,m_pDisabledImage(NULL)
{} {}
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenuItemSprite, CCMenuItem) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCMenuItemSprite, CCMenuItem)
/** creates a menu item with a normal, selected and disabled image*/ /** creates a menu item with a normal, selected and disabled image*/
static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite = NULL); static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite = NULL);
@ -337,7 +337,7 @@ public:
* @lua NA * @lua NA
*/ */
CCMenuItemImage(){} CCMenuItemImage(){}
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMenuItemImage, CCMenuItemSprite) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCMenuItemImage, CCMenuItemSprite)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -62,24 +62,24 @@ public:
@return true Initialize success, app continue. @return true Initialize success, app continue.
@return false Initialize failed, app terminate. @return false Initialize failed, app terminate.
*/ */
virtual bool applicationDidFinishLaunching() = 0; virtual bool applicationDidFinishLaunching() { return true; }
/** /**
@brief The function be called when the application enter background @brief The function be called when the application enter background
@param the pointer of the application @param the pointer of the application
*/ */
virtual void applicationDidEnterBackground() = 0; virtual void applicationDidEnterBackground() {}
/** /**
@brief The function be called when the application enter foreground @brief The function be called when the application enter foreground
@param the pointer of the application @param the pointer of the application
*/ */
virtual void applicationWillEnterForeground() = 0; virtual void applicationWillEnterForeground() {}
RT_ADD( RT_ADD(
virtual void applicationWillBecomeActive() {} virtual void applicationWillBecomeActive() {}
virtual void applicationWillResignActive() {} virtual void applicationWillResignActive() {}
virtual void trySaveGame() = 0; virtual void trySaveGame() {}
virtual void gameDidSave() {} virtual void gameDidSave() {}
) )
@ -87,18 +87,18 @@ public:
@brief Callback by CCDirector for limit FPS. @brief Callback by CCDirector for limit FPS.
@interval The time, expressed in seconds, between current frame and next. @interval The time, expressed in seconds, between current frame and next.
*/ */
virtual void setAnimationInterval(double interval) = 0; virtual void setAnimationInterval(double interval) {}
/** /**
@brief Get current language config @brief Get current language config
@return Current language config @return Current language config
*/ */
virtual ccLanguageType getCurrentLanguage() = 0; virtual ccLanguageType getCurrentLanguage() { return kLanguageEnglish; }
/** /**
@brief Get target platform @brief Get target platform
*/ */
virtual TargetPlatform getTargetPlatform() = 0; virtual TargetPlatform getTargetPlatform() { return kTargetWindows; }
RT_ADD( virtual void openURL(const char* url) {} ) RT_ADD( virtual void openURL(const char* url) {} )
}; };

View file

@ -52,6 +52,8 @@ class CC_DLL CCFileUtils : public TypeInfo
friend class CCArray; friend class CCArray;
friend class CCDictionary; friend class CCDictionary;
public: public:
GEODE_CUSTOM_CONSTRUCTOR_BEGIN(CCFileUtils)
/** /**
* Returns an unique ID for this class. * Returns an unique ID for this class.
* @note It's only used for JSBindings now. * @note It's only used for JSBindings now.
@ -339,7 +341,7 @@ public:
* @return The path that can be write/read a file in * @return The path that can be write/read a file in
* @lua NA * @lua NA
*/ */
virtual gd::string getWritablePath() = 0; virtual gd::string getWritablePath() { return ""; }
RT_ADD(virtual gd::string getWritablePath2();) RT_ADD(virtual gd::string getWritablePath2();)
@ -351,7 +353,7 @@ public:
* @return true if the file exists, otherwise it will return false. * @return true if the file exists, otherwise it will return false.
* @lua NA * @lua NA
*/ */
virtual bool isFileExist(const gd::string& strFilePath) = 0; virtual bool isFileExist(const gd::string& strFilePath) { return false; }
/** /**
* Checks whether the path is an absolute path. * Checks whether the path is an absolute path.

View file

@ -46,7 +46,7 @@ public:
@js ctor @js ctor
*/ */
CCImage(); CCImage();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCImage, CCObject) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCImage, CCObject)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -36,7 +36,7 @@ class CC_DLL CCApplication : public CCApplicationProtocol
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(CCApplication) GEODE_CUSTOM_CONSTRUCTOR_BEGIN(CCApplication)
CCApplication(); CCApplication();
/** /**
* @js NA * @js NA

View file

@ -35,7 +35,7 @@ class CC_DLL CCApplication : public CCApplicationProtocol
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(CCApplication) GEODE_CUSTOM_CONSTRUCTOR_BEGIN(CCApplication)
CCApplication(); CCApplication();
virtual ~CCApplication(); virtual ~CCApplication();

View file

@ -15,7 +15,7 @@ class CC_DLL CCApplication : public CCApplicationProtocol
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_BEGIN(CCApplication) GEODE_CUSTOM_CONSTRUCTOR_BEGIN(CCApplication)
CCApplication(); CCApplication();
virtual ~CCApplication(); virtual ~CCApplication();

View file

@ -45,6 +45,7 @@ protected:
RT_ADD( virtual ~CCEGLView(); ) RT_ADD( virtual ~CCEGLView(); )
public: public:
CCEGLView(); CCEGLView();
GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCEGLView, CCObject)
RT_REMOVE( virtual ~CCEGLView(); ) RT_REMOVE( virtual ~CCEGLView(); )
/* override functions */ /* override functions */

View file

@ -207,7 +207,7 @@ RT_ADD(
class CC_DLL CCKeyboardHandler : public CCObject class CC_DLL CCKeyboardHandler : public CCObject
{ {
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCKeyboardHandler, CCObject) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCKeyboardHandler, CCObject)
inline CCKeyboardHandler() = default; inline CCKeyboardHandler() = default;
virtual ~CCKeyboardHandler(); virtual ~CCKeyboardHandler();

View file

@ -22,7 +22,7 @@ RT_ADD(
class CC_DLL CCMouseHandler : public CCObject class CC_DLL CCMouseHandler : public CCObject
{ {
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCMouseHandler, CCObject) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCMouseHandler, CCObject)
inline CCMouseHandler() = default; inline CCMouseHandler() = default;
virtual ~CCMouseHandler(); virtual ~CCMouseHandler();

View file

@ -168,7 +168,7 @@ public:
* @js ctor * @js ctor
*/ */
CCSprite(void); CCSprite(void);
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCSprite, CCNodeRGBA) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCSprite, CCNodeRGBA)
/** /**
* Default destructor * Default destructor

View file

@ -68,7 +68,7 @@ public:
* @js ctor * @js ctor
*/ */
CCSpriteBatchNode(); CCSpriteBatchNode();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCSpriteBatchNode, CCNode) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCSpriteBatchNode, CCNode)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -50,6 +50,7 @@ class CC_DLL CCIMEDelegate
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_CUSTOM_CONSTRUCTOR_BEGIN(CCIMEDelegate)
virtual ~CCIMEDelegate(); virtual ~CCIMEDelegate();
virtual bool attachWithIME(); virtual bool attachWithIME();

View file

@ -117,7 +117,7 @@ public:
* @js ctor * @js ctor
*/ */
CCTexture2D(); CCTexture2D();
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCTexture2D, CCObject) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCTexture2D, CCObject)
/** /**
* @js NA * @js NA
* @lua NA * @lua NA

View file

@ -48,7 +48,7 @@ class CC_DLL CCTouchHandler : public CCObject
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCTouchHandler, CCObject) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCTouchHandler, CCObject)
inline CCTouchHandler() = default; inline CCTouchHandler() = default;
virtual ~CCTouchHandler(void); virtual ~CCTouchHandler(void);
@ -86,7 +86,7 @@ class CC_DLL CCStandardTouchHandler : public CCTouchHandler
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCStandardTouchHandler, CCTouchHandler) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCStandardTouchHandler, CCTouchHandler)
inline CCStandardTouchHandler() = default; inline CCStandardTouchHandler() = default;
~CCStandardTouchHandler(void); ~CCStandardTouchHandler(void);
@ -110,7 +110,7 @@ class CC_DLL CCTargetedTouchHandler : public CCTouchHandler
{ {
GEODE_FRIEND_MODIFY GEODE_FRIEND_MODIFY
public: public:
GEODE_MONOSTATE_CONSTRUCTOR_COCOS(CCTargetedTouchHandler, CCTouchHandler) GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCTargetedTouchHandler, CCTouchHandler)
inline CCTargetedTouchHandler() = default; inline CCTargetedTouchHandler() = default;
~CCTargetedTouchHandler(void); ~CCTargetedTouchHandler(void);

View file

@ -32,8 +32,8 @@ namespace geode::modifier {
void* getField(size_t index) { void* getField(size_t index) {
if (m_containedFields.size() <= index) { if (m_containedFields.size() <= index) {
m_containedFields.resize(index + 1); m_containedFields.push_back(nullptr);
m_destructorFunctions.resize(index + 1); m_destructorFunctions.push_back(nullptr);
} }
return m_containedFields.at(index); return m_containedFields.at(index);
} }
@ -49,7 +49,9 @@ namespace geode::modifier {
} }
}; };
[[deprecated("Will be removed in 1.0.0")]]
GEODE_DLL size_t getFieldIndexForClass(size_t hash); GEODE_DLL size_t getFieldIndexForClass(size_t hash);
GEODE_DLL size_t getFieldIndexForClass(char const* name);
template <class Parent, class Base> template <class Parent, class Base>
class FieldIntermediate { class FieldIntermediate {
@ -89,8 +91,7 @@ namespace geode::modifier {
static_cast<Parent*>(parent)->Parent::~Parent(); static_cast<Parent*>(parent)->Parent::~Parent();
} }
template <class = std::enable_if_t<true>> operator Parent*() {
Parent* operator->() {
// get the this pointer of the base // get the this pointer of the base
// field intermediate is the first member of Modify // field intermediate is the first member of Modify
// meaning we canget the base from ourself // meaning we canget the base from ourself
@ -102,7 +103,7 @@ namespace geode::modifier {
// the index is global across all mods, so the // the index is global across all mods, so the
// function is defined in the loader source // function is defined in the loader source
static size_t index = getFieldIndexForClass(typeid(Base).hash_code()); static size_t index = getFieldIndexForClass(typeid(Base).name());
// the fields are actually offset from their original // the fields are actually offset from their original
// offset, this is done to save on allocation and space // offset, this is done to save on allocation and space
@ -119,6 +120,14 @@ namespace geode::modifier {
reinterpret_cast<std::byte*>(offsetField) - sizeof(Intermediate) reinterpret_cast<std::byte*>(offsetField) - sizeof(Intermediate)
); );
} }
Parent* self() {
return this->operator Parent*();
}
Parent* operator->() {
return this->operator Parent*();
}
}; };
} }

View file

@ -134,8 +134,8 @@ namespace geode {
// abusing the internal stuff // abusing the internal stuff
// basically we dont want modify to invoke base ctors and dtors // basically we dont want modify to invoke base ctors and dtors
// we already have utilities for these, which are ccdestructor // we already have utilities for these, which are ccdestructor
// and the monostate constructor // and the cutoff constructor
Modify() : Base(std::monostate(), sizeof(Base)) {} Modify() : Base(CutoffConstructor, sizeof(Base)) {}
~Modify() { ~Modify() {
cocos2d::CCDestructor::lock(this) = true; cocos2d::CCDestructor::lock(this) = true;

View file

@ -8,6 +8,7 @@
#include <string_view> #include <string_view>
#include <type_traits> #include <type_traits>
#include <variant> #include <variant>
#include <optional>
namespace geode { namespace geode {
namespace impl { namespace impl {

View file

@ -56,8 +56,8 @@ namespace geode {
constexpr bool operator>(VersionTag const& other) const { constexpr bool operator>(VersionTag const& other) const {
if (value == other.value) { if (value == other.value) {
if (number && other.number) return number > other.number; if (number && other.number) return number > other.number;
if (number) return true; if (number) return false;
if (other.number) return false; if (other.number) return true;
return false; return false;
} }
return value > other.value; return value > other.value;
@ -65,8 +65,8 @@ namespace geode {
constexpr bool operator>=(VersionTag const& other) const { constexpr bool operator>=(VersionTag const& other) const {
if (value == other.value) { if (value == other.value) {
if (number && other.number) return number >= other.number; if (number && other.number) return number >= other.number;
if (number) return true; if (number) return false;
if (other.number) return false; if (other.number) return true;
return true; return true;
} }
return value >= other.value; return value >= other.value;
@ -77,6 +77,34 @@ namespace geode {
std::string toString() const; std::string toString() const;
}; };
constexpr bool operator<(std::optional<VersionTag> const& a, std::optional<VersionTag> const& b) {
if (a && b) return *a < *b;
if (a) return true;
if (b) return false;
return false;
}
constexpr bool operator<=(std::optional<VersionTag> const& a, std::optional<VersionTag> const& b) {
if (a && b) return *a <= *b;
if (a) return true;
if (b) return false;
return true;
}
constexpr bool operator>(std::optional<VersionTag> const& a, std::optional<VersionTag> const& b) {
if (a && b) return *a > *b;
if (a) return false;
if (b) return true;
return false;
}
constexpr bool operator>=(std::optional<VersionTag> const& a, std::optional<VersionTag> const& b) {
if (a && b) return *a >= *b;
if (a) return false;
if (b) return true;
return true;
}
/** /**
* Class representing version information. Uses a limited subset of SemVer; * Class representing version information. Uses a limited subset of SemVer;
* identifiers are restricted to a few predefined ones, and only one * identifiers are restricted to a few predefined ones, and only one

View file

@ -9,36 +9,24 @@
#include <Geode/DefaultInclude.hpp> #include <Geode/DefaultInclude.hpp>
#include <cocos-ext.h> #include <cocos-ext.h>
#include <concepts>
#include <cstdlib> #include <cstdlib>
#include <stddef.h> #include <stddef.h>
#include <type_traits> #include <type_traits>
#include <concepts>
namespace geode::addresser { namespace geode::addresser {
template <typename T> template <class Function>
inline intptr_t getVirtual(T func); intptr_t getVirtual(Function func);
template <typename T> template <class Function>
inline intptr_t getNonVirtual(T func); intptr_t getNonVirtual(Function func);
template <typename T, typename F> template <class Function, class Class>
inline F thunkAdjust(T func, F self); Class thunkAdjust(Function func, Class self);
template <typename T, typename F> template <class Function, class Class>
inline F rthunkAdjust(T func, F self); Class rthunkAdjust(Function func, Class self);
template <class Class>
Class* friendCreate(typename std::void_t<decltype(static_cast<Class* (*)()>(&Class::create))>*) {
auto ret = Class::create();
ret->retain();
return ret;
}
template <class Class>
concept HasCreate = requires() {
{ friendCreate<Class>(nullptr) } -> std::same_as<Class*>;
};
class GEODE_DLL Addresser final { class GEODE_DLL Addresser final {
template <char C> template <char C>
@ -76,57 +64,20 @@ namespace geode::addresser {
return thunk; return thunk;
} }
// I gave up
// template <HasCreate Class>
// static Class* generateInstance(Class*) {
// return friendCreate<Class>(nullptr);
// }
// I extra gave up
template <class = void>
static cocos2d::extension::CCScrollView* generateInstance(cocos2d::extension::CCScrollView*) {
return cocos2d::extension::CCScrollView::create({0.0f, 0.0f}, cocos2d::CCLayer::create());
}
template <class = void>
static cocos2d::CCFileUtils* generateInstance(cocos2d::CCFileUtils*) {
return cocos2d::CCFileUtils::sharedFileUtils();
}
template <class Class>
static Class* generateInstance(Class*) {
if constexpr (std::is_abstract_v<Class>) {
// Cant construct abstract classes, so fail early
return nullptr;
} else {
// Create a random memory block with the size of Class
// Assign a pointer to that block and cast it to type Class*
uint8_t dum[sizeof(Class)]{};
auto ptr = reinterpret_cast<Class*>(dum);
// Now you have a object of Class that actually isn't an object of Class and is just a
// random memory But C++ doesn't know that of course So now you can copy an object
// that wasn't there in the first place
// ((oh also get the offsets of the virtual tables))
auto ins = new Class(*ptr);
// this is how the first human was made
return ins;
}
}
template <class Class> template <class Class>
static Class* cachedInstance() { static Class* cachedInstance() {
static auto ret = generateInstance(static_cast<Class*>(nullptr)); static auto ret = new Class(ZeroConstructor);
return ret; return ret;
} }
/** /**
* Specialized functionss * Specialized functionss
*/ */
template <typename R, typename T, typename... Ps> template <class Return, class Class, class... Parameters>
static intptr_t addressOfVirtual(R (T::*func)(Ps...)) { static intptr_t addressOfVirtual(Return (Class::*func)(Parameters...)) {
using geode::cast::reference_cast; using geode::cast::reference_cast;
auto ins = cachedInstance<T>(); auto ins = cachedInstance<Class>();
// generateInstance will return nullptr on most abstract classes, // generateInstance will return nullptr on most abstract classes,
// so dont bother getting the address // so dont bother getting the address
if (ins == nullptr) { if (ins == nullptr) {
@ -136,97 +87,87 @@ namespace geode::addresser {
auto thunk = thunkOf(func); auto thunk = thunkOf(func);
// [[this + thunk] + offset] is the function we want // [[this + thunk] + offset] is the function we want
auto address = *reinterpret_cast<intptr_t*>(*reinterpret_cast<intptr_t*>(reinterpret_cast<intptr_t>(ins) + thunk) + index); auto address = *reinterpret_cast<intptr_t*>(
*reinterpret_cast<intptr_t*>(reinterpret_cast<intptr_t>(ins) + thunk) + index
);
address = followThunkFunction(address); address = followThunkFunction(address);
return address; return address;
} }
template <typename R, typename T, typename... Ps> template <class Return, class Class, class... Parameters>
static intptr_t addressOfVirtual(R (T::*func)(Ps...) const) { static intptr_t addressOfVirtual(Return (Class::*func)(Parameters...) const) {
return addressOfVirtual(reinterpret_cast<R (T::*)(Ps...)>(func)); return addressOfVirtual(reinterpret_cast<Return (Class::*)(Parameters...)>(func));
} }
template <typename R, typename T, typename... Ps> template <class Return, class Class, class... Parameters>
static intptr_t addressOfNonVirtual(R (T::*func)(Ps...) const) { static intptr_t addressOfNonVirtual(Return (Class::*func)(Parameters...) const) {
return addressOfNonVirtual(reinterpret_cast<R (T::*)(Ps...)>(func)); return addressOfNonVirtual(reinterpret_cast<Return (Class::*)(Parameters...)>(func));
} }
static intptr_t followThunkFunction(intptr_t address); static intptr_t followThunkFunction(intptr_t address);
template <typename R, typename T, typename... Ps> template <class Return, class Class, class... Parameters>
static intptr_t addressOfNonVirtual(R (T::*func)(Ps...)) { static intptr_t addressOfNonVirtual(Return (Class::*func)(Parameters...)) {
return followThunkFunction(geode::cast::reference_cast<intptr_t>(func)); return followThunkFunction(geode::cast::reference_cast<intptr_t>(func));
} }
template <typename R, typename... Ps> template <class Return, class... Parameters>
static intptr_t addressOfNonVirtual(R (*func)(Ps...)) { static intptr_t addressOfNonVirtual(Return (*func)(Parameters...)) {
return followThunkFunction(geode::cast::reference_cast<intptr_t>(func)); return followThunkFunction(geode::cast::reference_cast<intptr_t>(func));
} }
template <typename T> template <class Function>
friend intptr_t getVirtual(T func); friend intptr_t getVirtual(Function func);
template <typename T> template <class Function>
friend intptr_t getNonVirtual(T func); friend intptr_t getNonVirtual(Function func);
template <typename T, typename F> template <class Function, class Class>
friend F thunkAdjust(T func, F self); friend Class thunkAdjust(Function func, Class self);
template <typename T, typename F> template <class Function, class Class>
friend F rthunkAdjust(T func, F self); friend Class rthunkAdjust(Function func, Class self);
}; };
#ifdef GEODE_ADDRESSER_TEST /**
template <typename T> * Gets the real address of a virtual function
inline intptr_t getVirtual(T func) { */
template <class Function>
inline intptr_t getVirtual(Function func) {
return Addresser::addressOfVirtual(func); return Addresser::addressOfVirtual(func);
} }
template <typename T> /**
inline intptr_t getNonVirtual(T func) { * Gets the real address of a non-virtual function
*/
template <class Function>
inline intptr_t getNonVirtual(Function func) {
return Addresser::addressOfNonVirtual(func); return Addresser::addressOfNonVirtual(func);
} }
#else
template <typename T>
inline intptr_t getVirtual(T func) {
// log::debug(
// "Get virtual function address from {}",
// utils::intToHex(geode::cast::reference_cast<intptr_t>(func))
// );
auto addr = Addresser::addressOfVirtual(func);
// log::debug("The address is: {}", utils::intToHex(addr));
return addr;
}
template <typename T> /**
inline intptr_t getNonVirtual(T func) { * Adjusts a class instance to its appropriate base for the given virtual function
// log::debug( */
// "Get non-virtual function address from {}", template <class Function, class Class>
// utils::intToHex(geode::cast::reference_cast<intptr_t>(func)) inline Class thunkAdjust(Function func, Class self) {
// );
auto addr = Addresser::addressOfNonVirtual(func);
// log::debug("The address is: {}", utils::intToHex(addr));
return addr;
}
template <typename T, typename F>
inline F thunkAdjust(T func, F self) {
// do NOT delete the line below. // do NOT delete the line below.
// doing so breaks thunk adjusting on windows. // doing so breaks thunk adjusting on windows.
// why? bruh idk // why? bruh idk
auto _ = *geode::cast::template union_cast<ptrdiff_t*>(&func); auto _ = *geode::cast::template union_cast<ptrdiff_t*>(&func);
return (F)((intptr_t)self + Addresser::thunkOf(func)); return (Class)((intptr_t)self + Addresser::thunkOf(func));
} }
template <typename T, typename F> /**
inline F rthunkAdjust(T func, F self) { * Adjusts a class instance back from its appropriate base for the given virtual function to the original base
*/
template <class Function, class Class>
inline Class rthunkAdjust(Function func, Class self) {
// do NOT delete the line below. // do NOT delete the line below.
// doing so breaks thunk adjusting on windows. // doing so breaks thunk adjusting on windows.
// why? bruh idk // why? bruh idk
auto _ = *geode::cast::template union_cast<ptrdiff_t*>(&func); auto _ = *geode::cast::template union_cast<ptrdiff_t*>(&func);
return (F)((intptr_t)self - Addresser::thunkOf(func)); return (Class)((intptr_t)self - Addresser::thunkOf(func));
} }
#endif
} }

Binary file not shown.

View file

@ -9,6 +9,9 @@ USE_GEODE_NAMESPACE();
#pragma warning(disable: 4273) #pragma warning(disable: 4273)
// if 5k iterations isn't enough to fit the layout, then something is wrong
static size_t RECURSION_DEPTH_LIMIT = 5000;
void CCNode::swapChildIndices(CCNode* first, CCNode* second) { void CCNode::swapChildIndices(CCNode* first, CCNode* second) {
m_pChildren->exchangeObject(first, second); m_pChildren->exchangeObject(first, second);
std::swap(first->m_nZOrder, second->m_nZOrder); std::swap(first->m_nZOrder, second->m_nZOrder);
@ -277,11 +280,10 @@ AxisLayout::Row* AxisLayout::fitInRow(
// also force at least one object to be added to this row, because if // also force at least one object to be added to this row, because if
// it's too large for this row it's gonna be too large for all rows // it's too large for this row it's gonna be too large for all rows
if ( if (
m_growCrossAxis && (( m_growCrossAxis && (
(nextAxisScalableLength + nextAxisUnscalableLength > available.axisLength) && (nextAxisScalableLength + nextAxisUnscalableLength > available.axisLength) &&
ix != 0 && ix != 0 && !isOptsSameLine(opts)
!isOptsSameLine(opts) )
))
) { ) {
break; break;
} }
@ -323,16 +325,17 @@ AxisLayout::Row* AxisLayout::fitInRow(
nodes->removeFirstObject(); nodes->removeFirstObject();
} }
auto scaleDownFactor = scale - .025f; // todo: make this calculation more smart to avoid so much unnecessary recursion
auto scaleDownFactor = scale - .0125f;
auto squishFactor = available.axisLength / (axisUnsquishedLength + .01f) * squish; auto squishFactor = available.axisLength / (axisUnsquishedLength + .01f) * squish;
// calculate row scale, squish, and prio // calculate row scale, squish, and prio
int tries = 1000; int tries = 1000;
while (axisLength > available.axisLength) { while (axisLength > available.axisLength) {
if (this->canTryScalingDown( if (this->canTryScalingDown(
res, prio, scale, scale - .025f, minMaxPrios res, prio, scale, scale - .0125f, minMaxPrios
)) { )) {
scale -= .025f; scale -= .0125f;
} }
else { else {
squish = available.axisLength / (axisUnsquishedLength + .01f) * squish; squish = available.axisLength / (axisUnsquishedLength + .01f) * squish;
@ -366,7 +369,6 @@ AxisLayout::Row* AxisLayout::fitInRow(
// the .01f is because floating point arithmetic is imprecise and you // the .01f is because floating point arithmetic is imprecise and you
// end up in a situation where it confidently tells you that // end up in a situation where it confidently tells you that
// 241 > 241 == true // 241 > 241 == true
// todo: make this calculation more smart to avoid so much unnecessary recursion
scaleDownFactor, scaleDownFactor,
// how much should the nodes be squished to fit the next item in this // how much should the nodes be squished to fit the next item in this
// row // row
@ -389,9 +391,9 @@ bool AxisLayout::canTryScalingDown(
// if the scale is less than the lowest min scale allowed, then // if the scale is less than the lowest min scale allowed, then
// trying to scale will have no effect and not help anywmore // trying to scale will have no effect and not help anywmore
crossScaleDownFactor < minScaleForPrio || crossScaleDownFactor < minScaleForPrio ||
// if the scale down factor is the same as before, then we've // if the scale down factor is really close to the same as before,
// entered an infinite loop // then we've entered an infinite loop (float == float is unreliable)
crossScaleDownFactor == scale (fabsf(crossScaleDownFactor - scale) < .001f)
) { ) {
// is there still some lower priority nodes we could try scaling? // is there still some lower priority nodes we could try scaling?
if (prio > minMaxPrios.first) { if (prio > minMaxPrios.first) {
@ -414,6 +416,7 @@ bool AxisLayout::canTryScalingDown(
// otherwise scale as usual // otherwise scale as usual
else { else {
attemptRescale = true; attemptRescale = true;
scale = crossScaleDownFactor;
} }
return attemptRescale; return attemptRescale;
} }
@ -422,7 +425,8 @@ void AxisLayout::tryFitLayout(
CCNode* on, CCArray* nodes, CCNode* on, CCArray* nodes,
std::pair<int, int> const& minMaxPrios, std::pair<int, int> const& minMaxPrios,
bool doAutoScale, bool doAutoScale,
float scale, float squish, int prio float scale, float squish, int prio,
size_t depth
) const { ) const {
// where do all of these magical calculations come from? // where do all of these magical calculations come from?
// idk i got tired of doing the math but they work so ¯\_(ツ)_/¯ // idk i got tired of doing the math but they work so ¯\_(ツ)_/¯
@ -447,13 +451,13 @@ void AxisLayout::tryFitLayout(
rows->addObject(row); rows->addObject(row);
if ( if (
row->nextOverflowScaleDownFactor > crossScaleDownFactor && row->nextOverflowScaleDownFactor > crossScaleDownFactor &&
row->nextOverflowScaleDownFactor <= scale row->nextOverflowScaleDownFactor < scale
) { ) {
crossScaleDownFactor = row->nextOverflowScaleDownFactor; crossScaleDownFactor = row->nextOverflowScaleDownFactor;
} }
if ( if (
row->nextOverflowSquishFactor > crossSquishFactor && row->nextOverflowSquishFactor > crossSquishFactor &&
row->nextOverflowSquishFactor <= squish row->nextOverflowSquishFactor < squish
) { ) {
crossSquishFactor = row->nextOverflowSquishFactor; crossSquishFactor = row->nextOverflowSquishFactor;
} }
@ -484,7 +488,8 @@ void AxisLayout::tryFitLayout(
if ( if (
!m_allowCrossAxisOverflow && !m_allowCrossAxisOverflow &&
doAutoScale && doAutoScale &&
totalRowCrossLength > available.crossLength totalRowCrossLength > available.crossLength &&
depth < RECURSION_DEPTH_LIMIT
) { ) {
if (this->canTryScalingDown( if (this->canTryScalingDown(
nodes, prio, scale, crossScaleDownFactor, minMaxPrios nodes, prio, scale, crossScaleDownFactor, minMaxPrios
@ -493,7 +498,8 @@ void AxisLayout::tryFitLayout(
return this->tryFitLayout( return this->tryFitLayout(
on, nodes, on, nodes,
minMaxPrios, doAutoScale, minMaxPrios, doAutoScale,
scale, squish, prio scale, squish, prio,
depth + 1
); );
} }
} }
@ -501,7 +507,8 @@ void AxisLayout::tryFitLayout(
// if we're still overflowing, squeeze nodes closer together // if we're still overflowing, squeeze nodes closer together
if ( if (
!m_allowCrossAxisOverflow && !m_allowCrossAxisOverflow &&
totalRowCrossLength > available.crossLength totalRowCrossLength > available.crossLength &&
depth < RECURSION_DEPTH_LIMIT
) { ) {
// if squishing rows would take less squishing that squishing columns, // if squishing rows would take less squishing that squishing columns,
// then squish rows // then squish rows
@ -513,7 +520,8 @@ void AxisLayout::tryFitLayout(
return this->tryFitLayout( return this->tryFitLayout(
on, nodes, on, nodes,
minMaxPrios, doAutoScale, minMaxPrios, doAutoScale,
scale, crossSquishFactor, prio scale, crossSquishFactor, prio,
depth + 1
); );
} }
} }
@ -719,7 +727,8 @@ void AxisLayout::apply(CCNode* on) {
this->tryFitLayout( this->tryFitLayout(
on, nodes, on, nodes,
minMaxPrio, doAutoScale, minMaxPrio, doAutoScale,
this->maxScaleForPrio(nodes, minMaxPrio.second), 1.f, minMaxPrio.second this->maxScaleForPrio(nodes, minMaxPrio.second), 1.f, minMaxPrio.second,
0
); );
} }

View file

@ -79,9 +79,13 @@ struct ProxyCCNode : Modify<ProxyCCNode, CCNode> {
} }
}; };
static inline std::unordered_map<size_t, size_t> s_nextIndex; static inline std::unordered_map<std::string, size_t> s_nextIndex;
size_t modifier::getFieldIndexForClass(char const* name) {
return s_nextIndex[name]++;
}
size_t modifier::getFieldIndexForClass(size_t hash) { size_t modifier::getFieldIndexForClass(size_t hash) {
return s_nextIndex[hash]++; return s_nextIndex[std::to_string(hash)]++;
} }
// not const because might modify contents // not const because might modify contents

View file

@ -237,6 +237,7 @@ $register_ids(EditorPauseLayer) {
->setAxisAlignment(AxisAlignment::End) ->setAxisAlignment(AxisAlignment::End)
->setAxisReverse(true) ->setAxisReverse(true)
->setCrossAxisOverflow(false) ->setCrossAxisOverflow(false)
->setCrossAxisAlignment(AxisAlignment::Start)
->setCrossAxisLineAlignment(AxisAlignment::Start), ->setCrossAxisLineAlignment(AxisAlignment::Start),
this->getChildByID("object-count-label"), this->getChildByID("object-count-label"),
this->getChildByID("length-label"), this->getChildByID("length-label"),
@ -250,8 +251,8 @@ $register_ids(EditorPauseLayer) {
->setBreakLine(true) ->setBreakLine(true)
); );
} }
menu->setContentSize({ 165.f, 100.f }); menu->setContentSize({ 180.f, 100.f });
menu->setPosition(75.f, winSize.height - 55.f); menu->setPosition(100.f, winSize.height - 55.f);
menu->updateLayout(); menu->updateLayout();
} }
} }

View file

@ -356,8 +356,10 @@ Result<> Mod::Impl::enable() {
} }
for (auto const& hook : m_hooks) { for (auto const& hook : m_hooks) {
if (hook->getAutoEnable()) {
GEODE_UNWRAP(this->enableHook(hook)); GEODE_UNWRAP(this->enableHook(hook));
} }
}
for (auto const& patch : m_patches) { for (auto const& patch : m_patches) {
if (!patch->apply()) { if (!patch->apply()) {