mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-23 16:07:52 -05:00
Merge branch 'main' into better-layouts
This commit is contained in:
commit
511938fe1c
13 changed files with 158 additions and 164 deletions
8
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
8
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
|
@ -12,6 +12,14 @@ body:
|
||||||
- "Windows"
|
- "Windows"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: commit
|
||||||
|
attributes:
|
||||||
|
label: SDK commit
|
||||||
|
description: The commit you used to compile your code with. If the bug is not related with your mod, you can leave this field empty.
|
||||||
|
placeholder: "Example: a674b97"
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
- type: input
|
- type: input
|
||||||
id: version
|
id: version
|
||||||
attributes:
|
attributes:
|
||||||
|
|
|
@ -54,6 +54,12 @@ include(cmake/GeodeFile.cmake)
|
||||||
include(cmake/Platform.cmake)
|
include(cmake/Platform.cmake)
|
||||||
include(cmake/CPM.cmake)
|
include(cmake/CPM.cmake)
|
||||||
|
|
||||||
|
# this is needed for cross compilation on linux,
|
||||||
|
# since fmtlib will fail to compile otherwise
|
||||||
|
if (GEODE_DISABLE_FMT_CONSTEVAL)
|
||||||
|
target_compile_definitions(${PROJECT_NAME} INTERFACE -DFMT_CONSTEVAL=)
|
||||||
|
endif()
|
||||||
|
|
||||||
CPMAddPackage("gh:geode-sdk/json#2b76460")
|
CPMAddPackage("gh:geode-sdk/json#2b76460")
|
||||||
CPMAddPackage("gh:fmtlib/fmt#9.1.0")
|
CPMAddPackage("gh:fmtlib/fmt#9.1.0")
|
||||||
CPMAddPackage("gh:gulrak/filesystem#3e5b930")
|
CPMAddPackage("gh:gulrak/filesystem#3e5b930")
|
||||||
|
@ -81,6 +87,7 @@ ExternalProject_Add(CodegenProject
|
||||||
# this should hopefully fix generator cache mismatch between different projects, however
|
# this should hopefully fix generator cache mismatch between different projects, however
|
||||||
# it causes a warning to be shown every time. if you know a better solution please tell us ok thx
|
# it causes a warning to be shown every time. if you know a better solution please tell us ok thx
|
||||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} ${GEODE_CODEGEN_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:STRING=${GEODE_CODEGEN_BINARY_OUT} -S <SOURCE_DIR> -B <BINARY_DIR>
|
CONFIGURE_COMMAND ${CMAKE_COMMAND} ${GEODE_CODEGEN_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:STRING=${GEODE_CODEGEN_BINARY_OUT} -S <SOURCE_DIR> -B <BINARY_DIR>
|
||||||
|
INSTALL_COMMAND ${CMAKE_COMMAND} --install <BINARY_DIR> --config $<CONFIGURATION>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -186,15 +186,13 @@ class ButtonSprite : cocos2d::CCSprite {
|
||||||
) = win 0x134b0, mac 0x4f1d0;
|
) = win 0x134b0, mac 0x4f1d0;
|
||||||
|
|
||||||
[[docs("
|
[[docs("
|
||||||
/**
|
Create a ButtonSprite with a top sprite and a texture.
|
||||||
* Create a ButtonSprite with a top sprite and a texture.
|
@param topSprite The top sprite to add on top of the sprite
|
||||||
* @param topSprite The top sprite to add on top of the sprite
|
@param width Sprite width; ignored if `absolute` is false
|
||||||
* @param width Sprite width; ignored if `absolute` is false
|
@param absolute Whether to use absolute width or not
|
||||||
* @param absolute Whether to use absolute width or not
|
@param texture The name of the background sprite file (can't be in a spritesheet)
|
||||||
* @param texture The name of the background sprite file (can't be in a spritesheet)
|
@param height The height of the button, leave 0 for automatic
|
||||||
* @param height The height of the button, leave 0 for automatic
|
@param scale Scale of top sprite
|
||||||
* @param scale Scale of top sprite
|
|
||||||
*/
|
|
||||||
")]]
|
")]]
|
||||||
static ButtonSprite* create(
|
static ButtonSprite* create(
|
||||||
cocos2d::CCSprite* topSprite,
|
cocos2d::CCSprite* topSprite,
|
||||||
|
@ -208,26 +206,27 @@ class ButtonSprite : cocos2d::CCSprite {
|
||||||
}
|
}
|
||||||
|
|
||||||
[[docs("
|
[[docs("
|
||||||
/**
|
Create a ButtonSprite with text, a font and a texture.
|
||||||
* Create a ButtonSprite with text, a font and a texture.
|
@param caption The text of the ButtonSprite
|
||||||
* @param caption The text of the ButtonSprite
|
@param width Sprite width; ignored if `absolute` is false
|
||||||
* @param width Sprite width; ignored if `absolute` is false
|
@param absolute Whether to use absolute width or not
|
||||||
* @param absolute Whether to use absolute width or not
|
@param font The name of the BM font file to use
|
||||||
* @param font The name of the BM font file to use
|
@param texture The name of the background sprite file (can't be in a spritesheet)
|
||||||
* @param texture The name of the background sprite file (can't be in a spritesheet)
|
@param height The height of the button, leave 0 for automatic
|
||||||
* @param height The height of the button, leave 0 for automatic
|
@param scale Scale of text
|
||||||
* @param scale Scale of text
|
@returns Pointer to the created ButtonSprite, or nullptr on error
|
||||||
* @returns Pointer to the created ButtonSprite, or nullptr on error
|
|
||||||
*/
|
|
||||||
")]]
|
")]]
|
||||||
static ButtonSprite* create(const char* caption, int width, bool absolute, const char* font, const char* texture, float height, float scale) {
|
static ButtonSprite* create(const char* caption, int width, bool absolute, const char* font, const char* texture, float height, float scale) {
|
||||||
return create(caption, width, 0, scale, absolute, font, texture, height);
|
return create(caption, width, 0, scale, absolute, font, texture, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static ButtonSprite* create(char const* caption) {
|
static ButtonSprite* create(char const* caption) {
|
||||||
return ButtonSprite::create(caption, 0, 0, "goldFont.fnt", "GJ_button_01.png", .0f, 1.f);
|
return ButtonSprite::create(caption, 0, 0, "goldFont.fnt", "GJ_button_01.png", .0f, 1.f);
|
||||||
}
|
}
|
||||||
inline static ButtonSprite* create(char const* caption, const char* font, const char* texture, float scale = 1.f) {
|
static ButtonSprite* create(char const* caption, const char* font, const char* texture) {
|
||||||
|
return ButtonSprite::create(caption, 0, 0, font, texture, .0f, 1.f);
|
||||||
|
}
|
||||||
|
static ButtonSprite* create(char const* caption, const char* font, const char* texture, float scale) {
|
||||||
return ButtonSprite::create(caption, 0, 0, font, texture, .0f, scale);
|
return ButtonSprite::create(caption, 0, 0, font, texture, .0f, scale);
|
||||||
}
|
}
|
||||||
static ButtonSprite* create(char const*, int, int, float, bool) = mac 0x4fa40;
|
static ButtonSprite* create(char const*, int, int, float, bool) = mac 0x4fa40;
|
||||||
|
@ -1268,6 +1267,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ
|
||||||
void onUngroupSticky(cocos2d::CCObject* sender) = mac 0xc1d0, win 0x87ac0;
|
void onUngroupSticky(cocos2d::CCObject* sender) = mac 0xc1d0, win 0x87ac0;
|
||||||
void onGoToLayer(cocos2d::CCObject* sender) = win 0x886b0;
|
void onGoToLayer(cocos2d::CCObject* sender) = win 0x886b0;
|
||||||
void onGoToBaseLayer(cocos2d::CCObject* sender) = win 0x88790;
|
void onGoToBaseLayer(cocos2d::CCObject* sender) = win 0x88790;
|
||||||
|
void onToggleGuide(cocos2d::CCObject* sender) = mac 0x19da0, win 0x79160;
|
||||||
void editColor(cocos2d::CCObject* sender) = mac 0x19190, win 0x8d3c0;
|
void editColor(cocos2d::CCObject* sender) = mac 0x19190, win 0x8d3c0;
|
||||||
void alignObjects(cocos2d::CCArray* objs, bool alignY) = mac 0x2cea0, win 0x8f320;
|
void alignObjects(cocos2d::CCArray* objs, bool alignY) = mac 0x2cea0, win 0x8f320;
|
||||||
virtual void scrollWheel(float vertical, float horizontal) = win 0x921d0, mac 0x31370, ios 0x2c4884;
|
virtual void scrollWheel(float vertical, float horizontal) = win 0x921d0, mac 0x31370, ios 0x2c4884;
|
||||||
|
|
|
@ -4,7 +4,7 @@ project(Codegen LANGUAGES C CXX)
|
||||||
include(../cmake/CPM.cmake)
|
include(../cmake/CPM.cmake)
|
||||||
|
|
||||||
CPMAddPackage("gh:fmtlib/fmt#9.1.0")
|
CPMAddPackage("gh:fmtlib/fmt#9.1.0")
|
||||||
CPMAddPackage("gh:camila314/Broma#1.0.0")
|
CPMAddPackage("gh:geode-sdk/Broma#eb45fab")
|
||||||
|
|
||||||
file(GLOB SOURCES
|
file(GLOB SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
|
||||||
|
|
|
@ -40,13 +40,18 @@ public:
|
||||||
char const* monostate_constructor_cutoff = R"GEN( GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF({class_name}, {first_base})
|
char const* monostate_constructor_cutoff = R"GEN( GEODE_MONOSTATE_CONSTRUCTOR_CUTOFF({class_name}, {first_base})
|
||||||
)GEN";
|
)GEN";
|
||||||
|
|
||||||
char const* function_definition = R"GEN({docs} {static}{virtual}{return_type} {function_name}({parameters}){const};
|
char const* function_definition = R"GEN(
|
||||||
|
/**
|
||||||
|
{docs}{docs_addresses} */
|
||||||
|
{static}{virtual}{return_type} {function_name}({parameters}){const};
|
||||||
)GEN";
|
)GEN";
|
||||||
|
|
||||||
char const* error_definition = R"GEN(
|
char const* error_definition = R"GEN(
|
||||||
#ifdef GEODE_WARN_INCORRECT_MEMBERS
|
#ifdef GEODE_WARN_INCORRECT_MEMBERS
|
||||||
[[deprecated("Function is not implemented - will throw at runtime!!!")]]
|
[[deprecated("Function is not implemented - will throw at runtime!!!")]]
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
{docs}{docs_addresses} */
|
||||||
{static}{return_type} {function_name}({parameters}){const}{{
|
{static}{return_type} {function_name}({parameters}){const}{{
|
||||||
throw std::runtime_error("Use of undefined function " + GEODE_PRETTY_FUNCTION);
|
throw std::runtime_error("Use of undefined function " + GEODE_PRETTY_FUNCTION);
|
||||||
}}
|
}}
|
||||||
|
@ -56,6 +61,8 @@ public:
|
||||||
#ifdef GEODE_WARN_INCORRECT_MEMBERS
|
#ifdef GEODE_WARN_INCORRECT_MEMBERS
|
||||||
[[deprecated("Use of undefined virtual function - will crash at runtime!!!")]]
|
[[deprecated("Use of undefined virtual function - will crash at runtime!!!")]]
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
{docs}{docs_addresses} */
|
||||||
{virtual}{return_type} {function_name}({parameters}){const}{{
|
{virtual}{return_type} {function_name}({parameters}){const}{{
|
||||||
#ifdef GEODE_NO_UNDEFINED_VIRTUALS
|
#ifdef GEODE_NO_UNDEFINED_VIRTUALS
|
||||||
static_assert(false, "Undefined virtual function - implement in GeometryDash.bro");
|
static_assert(false, "Undefined virtual function - implement in GeometryDash.bro");
|
||||||
|
@ -71,7 +78,10 @@ public:
|
||||||
)GEN";
|
)GEN";
|
||||||
|
|
||||||
char const* structor_definition = R"GEN(
|
char const* structor_definition = R"GEN(
|
||||||
{function_name}({parameters});)GEN";
|
/**
|
||||||
|
{docs}{docs_addresses} */
|
||||||
|
{function_name}({parameters});
|
||||||
|
)GEN";
|
||||||
|
|
||||||
// requires: type, member_name, array
|
// requires: type, member_name, array
|
||||||
char const* member_definition = R"GEN( {type} {member_name};
|
char const* member_definition = R"GEN( {type} {member_name};
|
||||||
|
@ -84,6 +94,52 @@ public:
|
||||||
)GEN";
|
)GEN";
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
inline std::string nameForPlatform(Platform platform) {
|
||||||
|
switch (platform) {
|
||||||
|
case Platform::Mac: return "MacOS";
|
||||||
|
case Platform::Windows: return "Windows";
|
||||||
|
case Platform::iOS: return "iOS";
|
||||||
|
case Platform::Android: return "Android";
|
||||||
|
default: // unreachable
|
||||||
|
return "Windows";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string generateAddressDocs(Field const& field, FunctionBindField* fn) {
|
||||||
|
std::string ret;
|
||||||
|
|
||||||
|
for (auto platform : {Platform::Mac, Platform::Windows, Platform::iOS, Platform::Android}) {
|
||||||
|
auto status = codegen::getStatusWithPlatform(platform, field);
|
||||||
|
|
||||||
|
if (status == BindStatus::NeedsBinding) {
|
||||||
|
ret += fmt::format(" * @note[short] {}: 0x{:x}\n",
|
||||||
|
nameForPlatform(platform),
|
||||||
|
codegen::platformNumberWithPlatform(platform, fn->binds)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (status == BindStatus::Binded) {
|
||||||
|
ret += fmt::format(" * @note[short] {}\n",
|
||||||
|
nameForPlatform(platform)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string generateDocs(std::string const& docs) {
|
||||||
|
if (docs.size() < 7) return "";
|
||||||
|
auto ret = docs.substr(1, docs.size() - 6); // i hate this but idk how to generalize
|
||||||
|
|
||||||
|
for (auto next = ret.find(" "); next != std::string::npos; next = ret.find(" ")) {
|
||||||
|
ret.replace(next, 8, " * ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singleFolder) {
|
std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singleFolder) {
|
||||||
std::string output;
|
std::string output;
|
||||||
|
|
||||||
|
@ -137,6 +193,8 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
|
||||||
FunctionBegin* fb;
|
FunctionBegin* fb;
|
||||||
char const* used_format = format_strings::function_definition;
|
char const* used_format = format_strings::function_definition;
|
||||||
|
|
||||||
|
std::string addressDocs;
|
||||||
|
|
||||||
if (auto i = field.get_as<InlineField>()) {
|
if (auto i = field.get_as<InlineField>()) {
|
||||||
single_output += "\t" + i->inner + "\n";
|
single_output += "\t" + i->inner + "\n";
|
||||||
continue;
|
continue;
|
||||||
|
@ -158,6 +216,8 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
|
||||||
continue;
|
continue;
|
||||||
} else if (auto fn = field.get_as<OutOfLineField>()) {
|
} else if (auto fn = field.get_as<OutOfLineField>()) {
|
||||||
fb = &fn->beginning;
|
fb = &fn->beginning;
|
||||||
|
addressDocs = " * @note[short] Out of line\n";
|
||||||
|
|
||||||
} else if (auto fn = field.get_as<FunctionBindField>()) {
|
} else if (auto fn = field.get_as<FunctionBindField>()) {
|
||||||
fb = &fn->beginning;
|
fb = &fn->beginning;
|
||||||
|
|
||||||
|
@ -170,8 +230,12 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
|
||||||
if (fb->type != FunctionType::Normal)
|
if (fb->type != FunctionType::Normal)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addressDocs = generateAddressDocs(field, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string docs = generateDocs(fb->docs);
|
||||||
|
|
||||||
single_output += fmt::format(used_format,
|
single_output += fmt::format(used_format,
|
||||||
fmt::arg("virtual", str_if("virtual ", fb->is_virtual)),
|
fmt::arg("virtual", str_if("virtual ", fb->is_virtual)),
|
||||||
fmt::arg("static", str_if("static ", fb->is_static)),
|
fmt::arg("static", str_if("static ", fb->is_static)),
|
||||||
|
@ -181,7 +245,8 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
|
||||||
fmt::arg("index", field.field_id),
|
fmt::arg("index", field.field_id),
|
||||||
fmt::arg("parameters", codegen::getParameters(*fb)),
|
fmt::arg("parameters", codegen::getParameters(*fb)),
|
||||||
fmt::arg("return_type", fb->ret.name),
|
fmt::arg("return_type", fb->ret.name),
|
||||||
fmt::arg("docs", fb->docs)
|
fmt::arg("docs_addresses", addressDocs),
|
||||||
|
fmt::arg("docs", docs)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ int main(int argc, char** argv) try {
|
||||||
writeFile(writeDir / "GeneratedAddress.cpp", generateAddressHeader(root));
|
writeFile(writeDir / "GeneratedAddress.cpp", generateAddressHeader(root));
|
||||||
writeFile(writeDir / "GeneratedModify.hpp", generateModifyHeader(root, writeDir / "modify"));
|
writeFile(writeDir / "GeneratedModify.hpp", generateModifyHeader(root, writeDir / "modify"));
|
||||||
// writeFile(writeDir / "GeneratedWrapper.hpp", generateWrapperHeader(root));
|
// writeFile(writeDir / "GeneratedWrapper.hpp", generateWrapperHeader(root));
|
||||||
writeFile(writeDir / "GeneratedType.hpp", generateTypeHeader(root));
|
// writeFile(writeDir / "GeneratedType.hpp", generateTypeHeader(root));
|
||||||
writeFile(writeDir / "GeneratedBinding.hpp", generateBindingHeader(root, writeDir / "binding"));
|
writeFile(writeDir / "GeneratedBinding.hpp", generateBindingHeader(root, writeDir / "binding"));
|
||||||
writeFile(writeDir / "GeneratedPredeclare.hpp", generatePredeclareHeader(root));
|
writeFile(writeDir / "GeneratedPredeclare.hpp", generatePredeclareHeader(root));
|
||||||
writeFile(writeDir / "GeneratedSource.cpp", generateBindingSource(root));
|
writeFile(writeDir / "GeneratedSource.cpp", generateBindingSource(root));
|
||||||
|
|
|
@ -70,22 +70,26 @@ namespace codegen {
|
||||||
|
|
||||||
inline Platform platform;
|
inline Platform platform;
|
||||||
|
|
||||||
inline uintptr_t platformNumber(PlatformNumber const& p) {
|
inline uintptr_t platformNumberWithPlatform(Platform p, PlatformNumber const& pn) {
|
||||||
switch (codegen::platform) {
|
switch (p) {
|
||||||
case Platform::Mac: return p.mac;
|
case Platform::Mac: return pn.mac;
|
||||||
case Platform::Windows: return p.win;
|
case Platform::Windows: return pn.win;
|
||||||
case Platform::iOS: return p.ios;
|
case Platform::iOS: return pn.ios;
|
||||||
case Platform::Android: return p.android;
|
case Platform::Android: return pn.android;
|
||||||
default: // unreachable
|
default: // unreachable
|
||||||
return p.win;
|
return pn.win;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BindStatus getStatus(Field const& field) {
|
inline uintptr_t platformNumber(PlatformNumber const& p) {
|
||||||
|
return platformNumberWithPlatform(codegen::platform, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BindStatus getStatusWithPlatform(Platform p, Field const& field) {
|
||||||
FunctionBegin const* fb;
|
FunctionBegin const* fb;
|
||||||
|
|
||||||
if (auto fn = field.get_as<FunctionBindField>()) {
|
if (auto fn = field.get_as<FunctionBindField>()) {
|
||||||
if (platformNumber(fn->binds)) return BindStatus::NeedsBinding;
|
if (platformNumberWithPlatform(p, fn->binds)) return BindStatus::NeedsBinding;
|
||||||
|
|
||||||
fb = &fn->beginning;
|
fb = &fn->beginning;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +100,7 @@ namespace codegen {
|
||||||
|
|
||||||
// if (field.parent.rfind("GDString", 0) == 0) return BindStatus::NeedsBinding;
|
// if (field.parent.rfind("GDString", 0) == 0) return BindStatus::NeedsBinding;
|
||||||
|
|
||||||
if (platform == Platform::Android) {
|
if (p == Platform::Android) {
|
||||||
for (auto& [type, name] : fb->args) {
|
for (auto& [type, name] : fb->args) {
|
||||||
if (type.name.find("gd::") != std::string::npos) return BindStatus::NeedsBinding;
|
if (type.name.find("gd::") != std::string::npos) return BindStatus::NeedsBinding;
|
||||||
}
|
}
|
||||||
|
@ -108,13 +112,17 @@ namespace codegen {
|
||||||
|
|
||||||
if (fb->type == FunctionType::Normal) {
|
if (fb->type == FunctionType::Normal) {
|
||||||
if (field.parent.rfind("fmod::", 0) == 0) return BindStatus::Binded;
|
if (field.parent.rfind("fmod::", 0) == 0) return BindStatus::Binded;
|
||||||
if (field.parent.rfind("cocos2d::", 0) == 0 && platform == Platform::Windows)
|
if (field.parent.rfind("cocos2d::", 0) == 0 && p == Platform::Windows)
|
||||||
return BindStatus::Binded;
|
return BindStatus::Binded;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BindStatus::Unbindable;
|
return BindStatus::Unbindable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline BindStatus getStatus(Field const& field) {
|
||||||
|
return getStatusWithPlatform(codegen::platform, field);
|
||||||
|
}
|
||||||
|
|
||||||
inline std::string getParameters(FunctionBegin const& f) { // int p0, float p1
|
inline std::string getParameters(FunctionBegin const& f) { // int p0, float p1
|
||||||
std::vector<std::string> parameters;
|
std::vector<std::string> parameters;
|
||||||
|
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
#include "Shared.hpp"
|
|
||||||
#include "TypeOpt.hpp"
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
std::string generateTypeHeader(Root& root) {
|
|
||||||
std::string output;
|
|
||||||
|
|
||||||
TypeBank bank;
|
|
||||||
bank.loadFrom(root);
|
|
||||||
|
|
||||||
std::map<std::string, int> used_returns;
|
|
||||||
std::map<std::string, int> used_funcs;
|
|
||||||
std::map<std::string, int> used_pures;
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (auto& f : bank.typeList()) {
|
|
||||||
|
|
||||||
char const* return_fmt = "using ret{index} = {return};";
|
|
||||||
char const* func_fmt;
|
|
||||||
char const* pure_fmt = "ret{ret_index}({parameter_types});";
|
|
||||||
char const* meta_fmt;
|
|
||||||
char const* member_fmt;
|
|
||||||
|
|
||||||
switch (f.type) {
|
|
||||||
case FuncType::Member:
|
|
||||||
func_fmt = "ret{ret_index}(*)( {const}{class_name}*{parameter_type_comma}{parameter_types});";
|
|
||||||
meta_fmt = "ret{ret_index}({const}{class_name}*{parameter_type_comma}{parameter_types});";
|
|
||||||
member_fmt = "ret{ret_index}({class_name}::*)({parameter_types}){const};";
|
|
||||||
break;
|
|
||||||
case FuncType::Static:
|
|
||||||
func_fmt = "ret{ret_index}(*)({parameter_types});";
|
|
||||||
meta_fmt = "ret{ret_index}({parameter_types});";
|
|
||||||
member_fmt = "func{index};";
|
|
||||||
break;
|
|
||||||
case FuncType::Structor:
|
|
||||||
func_fmt = "ret{ret_index}(*)({class_name}*{parameter_type_comma}{parameter_types});";
|
|
||||||
meta_fmt = "ret{ret_index}({const}{class_name}*{parameter_type_comma}{parameter_types});";
|
|
||||||
member_fmt = "func{index};";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (used_returns.count(f.return_type) == 0) {
|
|
||||||
output += fmt::format(return_fmt,
|
|
||||||
fmt::arg("index", i),
|
|
||||||
fmt::arg("return", f.return_type)
|
|
||||||
) + "\n";
|
|
||||||
used_returns[f.return_type] = i;
|
|
||||||
}
|
|
||||||
int ret_index = used_returns[f.return_type];
|
|
||||||
|
|
||||||
std::string pure_val = fmt::format(pure_fmt,
|
|
||||||
fmt::arg("ret_index", ret_index),
|
|
||||||
fmt::arg("parameter_types", fmt::join(f.parameter_types, ", "))
|
|
||||||
);
|
|
||||||
if (used_pures.count(pure_val) == 0) {
|
|
||||||
output += fmt::format("using pure{} = {}\n", i, pure_val);
|
|
||||||
used_pures[pure_val] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string func_val = fmt::format(func_fmt,
|
|
||||||
fmt::arg("ret_index", ret_index),
|
|
||||||
fmt::arg("parameter_types", fmt::join(f.parameter_types, ", ")),
|
|
||||||
fmt::arg("parameter_type_comma", str_if(", ", !f.parameter_types.empty())),
|
|
||||||
fmt::arg("class_name", f.class_name),
|
|
||||||
fmt::arg("const", str_if(" const ", f.is_const))
|
|
||||||
);
|
|
||||||
std::string meta_val = fmt::format(meta_fmt,
|
|
||||||
fmt::arg("ret_index", ret_index),
|
|
||||||
fmt::arg("parameter_types", fmt::join(f.parameter_types, ", ")),
|
|
||||||
fmt::arg("parameter_type_comma", str_if(", ", !f.parameter_types.empty())),
|
|
||||||
fmt::arg("class_name", f.class_name),
|
|
||||||
fmt::arg("const", str_if(" const ", f.is_const))
|
|
||||||
);
|
|
||||||
std::string member_val = fmt::format(member_fmt,
|
|
||||||
fmt::arg("ret_index", ret_index),
|
|
||||||
fmt::arg("parameter_types", fmt::join(f.parameter_types, ", ")),
|
|
||||||
fmt::arg("class_name", f.class_name),
|
|
||||||
fmt::arg("const", str_if(" const ", f.is_const)),
|
|
||||||
fmt::arg("index", i)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (used_funcs.count(func_val) == 0) {
|
|
||||||
output += fmt::format("using func{index} = {func}\nusing meta{index} = {meta}\nusing member{index} = {member}\n",
|
|
||||||
fmt::arg("index", i),
|
|
||||||
fmt::arg("func", func_val),
|
|
||||||
fmt::arg("meta", meta_val),
|
|
||||||
fmt::arg("member", member_val)
|
|
||||||
);
|
|
||||||
used_funcs[func_val] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
|
@ -219,9 +219,9 @@ namespace geode {
|
||||||
using ColorAlphaSettingValue = GeodeSettingValue<ColorAlphaSetting>;
|
using ColorAlphaSettingValue = GeodeSettingValue<ColorAlphaSetting>;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
struct SettingValueSetter {
|
struct GEODE_DLL SettingValueSetter {
|
||||||
static GEODE_DLL T get(SettingValue* setting);
|
static T get(SettingValue* setting);
|
||||||
static GEODE_DLL void set(SettingValue* setting, T const& value);
|
static void set(SettingValue* setting, T const& value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace geode::modifier {
|
||||||
class ModifyDerive {
|
class ModifyDerive {
|
||||||
public:
|
public:
|
||||||
ModifyDerive() {
|
ModifyDerive() {
|
||||||
static_assert(alwaysFalse<Derived>, "Custom Modify not implemented.");
|
static_assert(alwaysFalse<Derived>, "Modified class not recognized, please include <Geode/modify/ClassName.hpp> to be able to use it.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,18 +163,7 @@ namespace geode::addresser {
|
||||||
return addressOfNonVirtual(reinterpret_cast<R (T::*)(Ps...)>(func));
|
return addressOfNonVirtual(reinterpret_cast<R (T::*)(Ps...)>(func));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline intptr_t followThunkFunction(intptr_t address) {
|
static intptr_t followThunkFunction(intptr_t address);
|
||||||
#ifdef GEODE_IS_WINDOWS
|
|
||||||
// check if first instruction is a jmp dword ptr [....], i.e. if the func is a thunk
|
|
||||||
if (*reinterpret_cast<uint8_t*>(address) == 0xFF && *reinterpret_cast<uint8_t*>(address + 1) == 0x25) {
|
|
||||||
// read where the jmp reads from
|
|
||||||
address = *reinterpret_cast<uint32_t*>(address + 2);
|
|
||||||
// that then contains the actual address of the func
|
|
||||||
address = *reinterpret_cast<uintptr_t*>(address);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename R, typename T, typename... Ps>
|
template <typename R, typename T, typename... Ps>
|
||||||
static intptr_t addressOfNonVirtual(R (T::*func)(Ps...)) {
|
static intptr_t addressOfNonVirtual(R (T::*func)(Ps...)) {
|
||||||
|
|
|
@ -275,18 +275,6 @@ std::string SettingValue::getKey() const {
|
||||||
typename type_##Setting::ValueType const& value \
|
typename type_##Setting::ValueType const& value \
|
||||||
) const
|
) const
|
||||||
|
|
||||||
// instantiate value setters
|
|
||||||
|
|
||||||
namespace geode {
|
|
||||||
template struct SettingValueSetter<typename BoolSetting::ValueType>;
|
|
||||||
template struct SettingValueSetter<typename IntSetting::ValueType>;
|
|
||||||
template struct SettingValueSetter<typename FloatSetting::ValueType>;
|
|
||||||
template struct SettingValueSetter<typename StringSetting::ValueType>;
|
|
||||||
template struct SettingValueSetter<typename FileSetting::ValueType>;
|
|
||||||
template struct SettingValueSetter<typename ColorSetting::ValueType>;
|
|
||||||
template struct SettingValueSetter<typename ColorAlphaSetting::ValueType>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// instantiate values
|
// instantiate values
|
||||||
|
|
||||||
namespace geode {
|
namespace geode {
|
||||||
|
@ -370,6 +358,18 @@ IMPL_NODE_AND_SETTERS(File);
|
||||||
IMPL_NODE_AND_SETTERS(Color);
|
IMPL_NODE_AND_SETTERS(Color);
|
||||||
IMPL_NODE_AND_SETTERS(ColorAlpha);
|
IMPL_NODE_AND_SETTERS(ColorAlpha);
|
||||||
|
|
||||||
|
// instantiate value setters
|
||||||
|
|
||||||
|
namespace geode {
|
||||||
|
template struct SettingValueSetter<typename BoolSetting::ValueType>;
|
||||||
|
template struct SettingValueSetter<typename IntSetting::ValueType>;
|
||||||
|
template struct SettingValueSetter<typename FloatSetting::ValueType>;
|
||||||
|
template struct SettingValueSetter<typename StringSetting::ValueType>;
|
||||||
|
template struct SettingValueSetter<typename FileSetting::ValueType>;
|
||||||
|
template struct SettingValueSetter<typename ColorSetting::ValueType>;
|
||||||
|
template struct SettingValueSetter<typename ColorAlphaSetting::ValueType>;
|
||||||
|
}
|
||||||
|
|
||||||
// SettingChangedEvent
|
// SettingChangedEvent
|
||||||
|
|
||||||
SettingChangedEvent::SettingChangedEvent(Mod* mod, SettingValue* value)
|
SettingChangedEvent::SettingChangedEvent(Mod* mod, SettingValue* value)
|
||||||
|
|
|
@ -65,3 +65,16 @@ namespace {
|
||||||
Addresser::MultipleInheritance* Addresser::instance() {
|
Addresser::MultipleInheritance* Addresser::instance() {
|
||||||
return reinterpret_cast<Addresser::MultipleInheritance*>(&TableTable::table);
|
return reinterpret_cast<Addresser::MultipleInheritance*>(&TableTable::table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intptr_t Addresser::followThunkFunction(intptr_t address) {
|
||||||
|
#ifdef GEODE_IS_WINDOWS
|
||||||
|
// check if first instruction is a jmp dword ptr [....], i.e. if the func is a thunk
|
||||||
|
if (*reinterpret_cast<uint8_t*>(address) == 0xFF && *reinterpret_cast<uint8_t*>(address + 1) == 0x25) {
|
||||||
|
// read where the jmp reads from
|
||||||
|
address = *reinterpret_cast<uint32_t*>(address + 2);
|
||||||
|
// that then contains the actual address of the func
|
||||||
|
address = *reinterpret_cast<uintptr_t*>(address);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return address;
|
||||||
|
}
|
Loading…
Reference in a new issue