mirror of
https://github.com/geode-sdk/geode.git
synced 2025-04-24 05:14:40 -04:00
replace modify checking implementation
i got distracted
This commit is contained in:
parent
e47a5b4e27
commit
a1be695aab
15 changed files with 334 additions and 156 deletions
|
@ -32,7 +32,7 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "MacOS")
|
|||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE curl "-framework Cocoa")
|
||||
target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions -Wno-deprecated -Wno-ignored-attributes -Os #[[-flto]] -fvisibility=internal)
|
||||
target_compile_options(${PROJECT_NAME} INTERFACE -fms-extensions #[[-Wno-deprecated]] -Wno-ignored-attributes -Os #[[-flto]] -fvisibility=internal)
|
||||
|
||||
set(GEODE_PLATFORM_BINARY "Geode.dylib")
|
||||
|
||||
|
|
|
@ -41,14 +41,17 @@ public:
|
|||
char const* function_definition = R"GEN({docs} {static}{virtual}{return_type} {function_name}({parameters}){const};
|
||||
)GEN";
|
||||
|
||||
char const* error_definition = R"GEN( template <bool T=false>
|
||||
char const* error_definition = R"GEN(
|
||||
#ifdef GEODE_WARN_INCORRECT_MEMBERS
|
||||
[[deprecated("Function is not implemented - will throw at runtime!!!")]]
|
||||
#endif
|
||||
{static}{return_type} {function_name}({parameters}){const}{{
|
||||
static_assert(T, "Implement {class_name}::{function_name}");
|
||||
throw std::runtime_error("Use of undefined function " + GEODE_PRETTY_FUNCTION);
|
||||
}}
|
||||
)GEN";
|
||||
|
||||
char const* error_definition_virtual = R"GEN(
|
||||
#ifndef GEODE_DONT_WARN_INCORRECT_MEMBERS
|
||||
#ifdef GEODE_WARN_INCORRECT_MEMBERS
|
||||
[[deprecated("Use of undefined virtual function - will crash at runtime!!!")]]
|
||||
#endif
|
||||
{virtual}{return_type} {function_name}({parameters}){const}{{
|
||||
|
@ -60,7 +63,7 @@ public:
|
|||
)GEN";
|
||||
|
||||
char const* warn_offset_member = R"GEN(
|
||||
#ifndef GEODE_DONT_WARN_INCORRECT_MEMBERS
|
||||
#ifdef GEODE_WARN_INCORRECT_MEMBERS
|
||||
[[deprecated("Member placed incorrectly - will crash at runtime!!!")]]
|
||||
#endif
|
||||
)GEN";
|
||||
|
|
|
@ -33,7 +33,7 @@ int main(int argc, char** argv) try {
|
|||
|
||||
writeFile(writeDir / "GeneratedAddress.hpp", generateAddressHeader(root));
|
||||
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 / "GeneratedBinding.hpp", generateBindingHeader(root, writeDir / "binding"));
|
||||
writeFile(writeDir / "GeneratedPredeclare.hpp", generatePredeclareHeader(root));
|
||||
|
|
|
@ -6,29 +6,16 @@
|
|||
|
||||
namespace {
|
||||
namespace format_strings {
|
||||
char const* wrap_start = R"GEN(
|
||||
namespace wrap {
|
||||
)GEN";
|
||||
|
||||
char const* wrap_declare_identifier = R"GEN(
|
||||
#ifndef GEODE_WRAP_{function_name}
|
||||
#define GEODE_WRAP_{function_name}
|
||||
GEODE_WRAPPER_FOR_IDENTIFIER({function_name})
|
||||
#endif
|
||||
)GEN";
|
||||
|
||||
char const* wrap_end = R"GEN(
|
||||
}
|
||||
)GEN";
|
||||
// requires: class_name
|
||||
// requires: class_name, class_include
|
||||
char const* modify_start = R"GEN(#pragma once
|
||||
#include <Geode/modify/Modify.hpp>
|
||||
#include <Geode/modify/Field.hpp>
|
||||
#include <Geode/modify/InternalMacros.hpp>
|
||||
{class_include}
|
||||
using namespace geode::modifier;
|
||||
|
||||
namespace geode::modifier {{
|
||||
{wrap}
|
||||
{statics}
|
||||
|
||||
template<class Der>
|
||||
struct ModifyDerive<Der, {class_name}> : ModifyBase<ModifyDerive<Der, {class_name}>> {{
|
||||
using BaseModify = ModifyBase<ModifyDerive<Der, {class_name}>>;
|
||||
|
@ -38,11 +25,24 @@ namespace geode::modifier {{
|
|||
void apply() override {{
|
||||
using namespace geode::core::meta;
|
||||
|
||||
)GEN";
|
||||
|
||||
char const* statics_declare_identifier = R"GEN(
|
||||
#ifndef GEODE_STATICS_{function_name}
|
||||
#define GEODE_STATICS_{function_name}
|
||||
GEODE_AS_STATIC_FUNCTION({function_name})
|
||||
#endif
|
||||
)GEN";
|
||||
|
||||
// requires: index, class_name, arg_types, function_name, raw_arg_types, non_virtual
|
||||
char const* apply_function = R"GEN(
|
||||
GEODE_APPLY_MODIFY_FOR_FUNCTION({addr_index}, {pure_index}, {function_convention}, {class_name}, {function_name}))GEN";
|
||||
GEODE_APPLY_MODIFY_FOR_FUNCTION({addr_index}, {function_convention}, {class_name}, {function_name}, {parameter_types}))GEN";
|
||||
|
||||
char const* apply_constructor = R"GEN(
|
||||
GEODE_APPLY_MODIFY_FOR_CONSTRUCTOR({addr_index}, {function_convention}, {class_name}, {parameter_types}))GEN";
|
||||
|
||||
char const* apply_destructor = R"GEN(
|
||||
GEODE_APPLY_MODIFY_FOR_DESTRUCTOR({addr_index}, {function_convention}, {class_name}))GEN";
|
||||
|
||||
char const* modify_end = R"GEN(
|
||||
}
|
||||
|
@ -68,45 +68,70 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single
|
|||
output += fmt::format(format_strings::modify_include, fmt::arg("file_name", filename));
|
||||
|
||||
std::string single_output;
|
||||
std::string wrap;
|
||||
|
||||
// wrap
|
||||
wrap += format_strings::wrap_start;
|
||||
std::string class_include;
|
||||
|
||||
if (c.name.find("cocos2d::extension") != std::string::npos) {
|
||||
class_include = "#include <cocos-ext.h>";
|
||||
}
|
||||
else if (c.name.find("cocos2d") != std::string::npos) {
|
||||
class_include = "#include <cocos2d.h>";
|
||||
}
|
||||
else {
|
||||
class_include = fmt::format(
|
||||
"#include <Geode/binding/{class_name}.hpp>",
|
||||
fmt::arg("class_name", codegen::getUnqualifiedClassName(c.name))
|
||||
);
|
||||
}
|
||||
|
||||
std::string statics;
|
||||
std::set<std::string> used;
|
||||
for (auto& f : c.fields) {
|
||||
if (auto fn = f.get_fn()) {
|
||||
if (fn->type == FunctionType::Normal && !used.count(fn->name)) {
|
||||
used.insert(fn->name);
|
||||
wrap += fmt::format(
|
||||
format_strings::wrap_declare_identifier, fmt::arg("function_name", fn->name)
|
||||
statics += fmt::format(
|
||||
format_strings::statics_declare_identifier, fmt::arg("function_name", fn->name)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
wrap += format_strings::wrap_end;
|
||||
|
||||
single_output += fmt::format(
|
||||
format_strings::modify_start, fmt::arg("class_name", c.name), fmt::arg("wrap", wrap)
|
||||
format_strings::modify_start,
|
||||
fmt::arg("statics", statics),
|
||||
fmt::arg("class_name", c.name),
|
||||
fmt::arg("class_include", class_include)
|
||||
);
|
||||
|
||||
// modify
|
||||
for (auto& f : c.fields) {
|
||||
if (codegen::getStatus(f) != BindStatus::Unbindable) {
|
||||
auto begin = f.get_fn();
|
||||
auto func = TypeBank::makeFunc(*begin, c.name);
|
||||
|
||||
std::string function_name;
|
||||
std::string format_string;
|
||||
|
||||
switch (begin->type) {
|
||||
case FunctionType::Normal: function_name = begin->name; break;
|
||||
case FunctionType::Ctor: function_name = "constructor"; break;
|
||||
case FunctionType::Dtor: function_name = "destructor"; break;
|
||||
case FunctionType::Normal:
|
||||
format_string = format_strings::apply_function;
|
||||
break;
|
||||
case FunctionType::Ctor:
|
||||
format_string = format_strings::apply_constructor;
|
||||
break;
|
||||
case FunctionType::Dtor:
|
||||
format_string = format_strings::apply_destructor;
|
||||
break;
|
||||
}
|
||||
|
||||
single_output += fmt::format(
|
||||
format_strings::apply_function, fmt::arg("addr_index", f.field_id),
|
||||
format_string,
|
||||
fmt::arg("addr_index", f.field_id),
|
||||
fmt::arg("pure_index", bank.getPure(*begin, c.name)),
|
||||
fmt::arg("class_name", c.name), fmt::arg("function_name", function_name),
|
||||
fmt::arg("function_convention", codegen::getModifyConvention(f))
|
||||
fmt::arg("class_name", c.name),
|
||||
fmt::arg("function_name", begin->name),
|
||||
fmt::arg("function_convention", codegen::getModifyConvention(f)),
|
||||
fmt::arg("parameter_types", fmt::join(func.parameter_types, ", "))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,14 +18,14 @@ using namespace geode::modifier; // types
|
|||
)CAC";
|
||||
|
||||
char const* declare_member = R"GEN(
|
||||
types::ret{ret_index} {class_name}::{function_name}({parameters}){const} {{
|
||||
auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{
|
||||
auto func = Function<types::meta{meta_index}, {convention}>({{addresses::address{addr_index}()}});
|
||||
return func(this{parameter_comma}{arguments});
|
||||
}}
|
||||
)GEN";
|
||||
|
||||
char const* declare_virtual = R"GEN(
|
||||
types::ret{ret_index} {class_name}::{function_name}({parameters}){const} {{
|
||||
auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{
|
||||
auto self = addresser::thunkAdjust((types::member{member_index})(&{class_name}::{function_name}), this);
|
||||
auto func = Function<types::meta{meta_index}, {convention}>({{addresses::address{addr_index}()}});
|
||||
return func(self{parameter_comma}{arguments});
|
||||
|
@ -33,7 +33,7 @@ types::ret{ret_index} {class_name}::{function_name}({parameters}){const} {{
|
|||
)GEN";
|
||||
|
||||
char const* declare_static = R"GEN(
|
||||
types::ret{ret_index} {class_name}::{function_name}({parameters}){const} {{
|
||||
auto {class_name}::{function_name}({parameters}){const} -> decltype({function_name}({arguments})) {{
|
||||
auto func = Function<types::meta{meta_index}, {convention}>({{addresses::address{addr_index}()}});
|
||||
return func({arguments});
|
||||
}}
|
||||
|
|
|
@ -146,7 +146,6 @@ if (NOT GEODE_DISABLE_PRECOMPILED_HEADERS)
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Loader.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/UI.hpp"
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Bindings.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/Modify.hpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/include/cocos2d.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/Geode/cocos/extensions/cocos-ext.h"
|
||||
)
|
||||
|
|
|
@ -57,7 +57,6 @@ NS_CC_BEGIN
|
|||
|
||||
class CC_DLL CCLabelTTF : public CCSprite, public CCLabelProtocol
|
||||
{
|
||||
GEODE_FRIEND_MODIFY
|
||||
GEODE_FRIEND_MODIFY
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -113,20 +113,25 @@ It's new in cocos2d-x since v0.99.5
|
|||
* macro.
|
||||
*/
|
||||
class GeodeNodeMetadata;
|
||||
namespace geode {
|
||||
struct modify;
|
||||
namespace modifier {
|
||||
struct addresses;
|
||||
struct types;
|
||||
|
||||
namespace geode {
|
||||
struct modify;
|
||||
|
||||
namespace modifier {
|
||||
struct types;
|
||||
class FieldContainer;
|
||||
}
|
||||
|
||||
template <class Derived, class Base>
|
||||
class ModifyDerive;
|
||||
}
|
||||
}
|
||||
#define GEODE_FRIEND_MODIFY GEODE_ADD(\
|
||||
friend struct ::geode::modify;\
|
||||
friend struct ::geode::modifier::addresses;\
|
||||
friend struct ::geode::modifier::types;\
|
||||
friend class ::GeodeNodeMetadata;\
|
||||
)
|
||||
|
||||
#define GEODE_FRIEND_MODIFY \
|
||||
friend struct ::geode::modify; \
|
||||
template <class Derived, class Base> \
|
||||
friend class ::geode::modifier::ModifyDerive; \
|
||||
friend struct ::geode::modifier::types; \
|
||||
friend class ::GeodeNodeMetadata;
|
||||
#define GEODE_ADD(...) __VA_ARGS__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
37
loader/include/Geode/modify/AsStaticFunction.hpp
Normal file
37
loader/include/Geode/modify/AsStaticFunction.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
#include "../utils/addresser.hpp"
|
||||
#include "Traits.hpp"
|
||||
|
||||
namespace geode::modifier {
|
||||
/**
|
||||
* A helper struct that generates a static function that calls the given function.
|
||||
*/
|
||||
#define GEODE_AS_STATIC_FUNCTION(FunctionName_) \
|
||||
template <class Class2, auto Function> \
|
||||
struct AsStaticFunction_##FunctionName_ { \
|
||||
template <class FunctionType2> \
|
||||
struct Impl {}; \
|
||||
template <class Return, class... Params> \
|
||||
struct Impl<Return (*)(Params...)> { \
|
||||
static Return function(Params... params) { return Class2::FunctionName_(params...); } \
|
||||
}; \
|
||||
template <class Return, class Class, class... Params> \
|
||||
struct Impl<Return (Class::*)(Params...)> { \
|
||||
static Return function(Class* self, Params... params) { \
|
||||
auto self2 = addresser::rthunkAdjust(Function, self); \
|
||||
return self2->Class2::FunctionName_(params...); \
|
||||
} \
|
||||
}; \
|
||||
template <class Return, class Class, class... Params> \
|
||||
struct Impl<Return (Class::*)(Params...) const> { \
|
||||
static Return function(Class const* self, Params... params) { \
|
||||
auto self2 = addresser::rthunkAdjust(Function, self); \
|
||||
return self2->Class2::FunctionName_(params...); \
|
||||
} \
|
||||
}; \
|
||||
static constexpr auto value = &Impl<decltype(Function)>::function; \
|
||||
};
|
||||
|
||||
GEODE_AS_STATIC_FUNCTION(constructor)
|
||||
GEODE_AS_STATIC_FUNCTION(destructor)
|
||||
}
|
|
@ -1,29 +1,57 @@
|
|||
#pragma once
|
||||
#include "../meta/meta.hpp"
|
||||
#include "Addresses.hpp"
|
||||
#include "AsStaticFunction.hpp"
|
||||
#include "Field.hpp"
|
||||
#include "IDManager.hpp"
|
||||
#include "Types.hpp"
|
||||
#include "Wrapper.hpp"
|
||||
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <iostream>
|
||||
#include <tulip/TulipHook.hpp>
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_FUNCTION(addr_index, pure_index, convention, className, functionName) \
|
||||
do { \
|
||||
using DerivedWrap = wrap::functionName<Derived, types::pure##pure_index>; \
|
||||
using BaseWrap = wrap::functionName<Base, types::pure##pure_index>; \
|
||||
if constexpr (DerivedWrap::uuid != nullptr && (void*)BaseWrap::uuid != (void*)DerivedWrap::uuid) { \
|
||||
auto hook = Hook::create<convention>( \
|
||||
Mod::get(), \
|
||||
reinterpret_cast<void*>(addresses::address##addr_index()), \
|
||||
DerivedWrap::value, \
|
||||
#className "::" #functionName \
|
||||
); \
|
||||
this->m_hooks[#className "::" #functionName] = hook; \
|
||||
} \
|
||||
#define GEODE_APPLY_MODIFY_FOR_FUNCTION(AddressIndex_, Convention_, ClassName_, FunctionName_, ...) \
|
||||
do { \
|
||||
constexpr auto b = Resolve<__VA_ARGS__>::func(&Base::FunctionName_); \
|
||||
constexpr auto d = Resolve<__VA_ARGS__>::func(&Derived::FunctionName_); \
|
||||
if constexpr (Unique::different<b, d>()) { \
|
||||
auto hook = Hook::create<Convention_>( \
|
||||
Mod::get(), \
|
||||
reinterpret_cast<void*>(addresses::address##AddressIndex_()), \
|
||||
AsStaticFunction_##FunctionName_<Derived, d>::value, \
|
||||
#ClassName_ "::" #FunctionName_ \
|
||||
); \
|
||||
this->m_hooks[#ClassName_ "::" #FunctionName_] = hook; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_CONSTRUCTOR(AddressIndex_, Convention_, ClassName_, ...) \
|
||||
do { \
|
||||
if constexpr (HasConstructor<Derived>) { \
|
||||
constexpr auto d = Resolve<__VA_ARGS__>::func(&Derived::constructor); \
|
||||
auto hook = Hook::create<Convention_>( \
|
||||
Mod::get(), \
|
||||
reinterpret_cast<void*>(addresses::address##AddressIndex_()), \
|
||||
AsStaticFunction_##constructor<Derived, d>::value, \
|
||||
#ClassName_ "::" #ClassName_ \
|
||||
); \
|
||||
this->m_hooks[#ClassName_ "::" #ClassName_] = hook; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_DESTRUCTOR(AddressIndex_, Convention_, ClassName_) \
|
||||
do { \
|
||||
if constexpr (HasDestructor<Derived>) { \
|
||||
constexpr auto d = Resolve<>::func(&Derived::destructor); \
|
||||
auto hook = Hook::create<Convention_>( \
|
||||
Mod::get(), \
|
||||
reinterpret_cast<void*>(addresses::address##AddressIndex_()), \
|
||||
AsStaticFunction_##destructor<Derived, d>::value, \
|
||||
#ClassName_ "::" #ClassName_ \
|
||||
); \
|
||||
this->m_hooks[#ClassName_ "::" #ClassName_] = hook; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
namespace geode::modifier {
|
||||
|
@ -87,11 +115,15 @@ namespace geode {
|
|||
// we already have utilities for these, which are ccdestructor
|
||||
// and the monostate constructor
|
||||
Modify() : Base(std::monostate(), sizeof(Base)) {}
|
||||
|
||||
~Modify() {
|
||||
cocos2d::CCDestructor::lock(this) = true;
|
||||
}
|
||||
|
||||
Modify(Modify const&) = delete;
|
||||
Modify(Modify&&) = delete;
|
||||
Modify& operator=(Modify const&) = delete;
|
||||
Modify& operator=(Modify&&) = delete;
|
||||
|
||||
modifier::FieldIntermediate<Derived, Base> m_fields;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
#include <Geode/meta/common.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace geode::modifier {
|
||||
|
@ -28,8 +27,6 @@ namespace geode::modifier {
|
|||
using type = FunctionType*;
|
||||
};
|
||||
|
||||
using ::geode::core::meta::always_false;
|
||||
|
||||
/**
|
||||
* The ~unevaluated~ function that gets the appropriate
|
||||
* version of a function type from its return, parameters, and classes.
|
||||
|
@ -65,4 +62,144 @@ namespace geode::modifier {
|
|||
public:
|
||||
constexpr static inline void (*value)() = &FunctionUUID::function;
|
||||
};
|
||||
|
||||
/**
|
||||
* A type trait that removes the class from a member function pointer.
|
||||
*/
|
||||
template <class Func>
|
||||
struct RemoveClass {
|
||||
using type = Func;
|
||||
};
|
||||
|
||||
template <class Return, class Class, class... Params>
|
||||
struct RemoveClass<Return(Class::*)(Params...)> {
|
||||
using type = Return(Params...);
|
||||
};
|
||||
|
||||
template <class Return, class Class, class... Params>
|
||||
struct RemoveClass<Return(Class::*)(Params...) const> {
|
||||
using type = Return(Params...);
|
||||
};
|
||||
|
||||
template <class Func>
|
||||
using RemoveClassType = typename RemoveClass<Func>::type;
|
||||
|
||||
/**
|
||||
* A helper struct that allows for checking if two function pointers
|
||||
* are the same or different.
|
||||
*/
|
||||
struct Unique {
|
||||
using ValueType = void(*)(...);
|
||||
static constexpr auto nvalue = static_cast<void(*)(...)>(nullptr);
|
||||
|
||||
template <auto Value>
|
||||
struct Impl {
|
||||
static void unique(...) {};
|
||||
|
||||
static constexpr auto value = &unique;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Impl<nvalue> {
|
||||
static constexpr auto value = nvalue;
|
||||
};
|
||||
|
||||
template <auto Value>
|
||||
static constexpr auto value = Impl<Value>::value;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if two function pointers are the same. If their types are
|
||||
* different, returns false.
|
||||
*/
|
||||
template <auto p1, auto p2>
|
||||
static constexpr auto same() {
|
||||
if (!std::is_same_v<RemoveClassType<decltype(p1)>, RemoveClassType<decltype(p2)>>) return false;
|
||||
auto v1 = value<p1>;
|
||||
auto v2 = value<p2>;
|
||||
if (v1 == nvalue) return false;
|
||||
if (v2 == nvalue) return false;
|
||||
return v1 == v2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if two function pointers are different. If their types are
|
||||
* different, returns false.
|
||||
*/
|
||||
template <auto p1, auto p2>
|
||||
static constexpr auto different() {
|
||||
if (!std::is_same_v<RemoveClassType<decltype(p1)>, RemoveClassType<decltype(p2)>>) return false;
|
||||
auto v1 = value<p1>;
|
||||
auto v2 = value<p2>;
|
||||
if (v1 == nvalue) return false;
|
||||
if (v2 == nvalue) return false;
|
||||
return v1 != v2;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helps resolving an overloaded function pointer to a specific function using
|
||||
* its parameter types as the hint.
|
||||
*/
|
||||
template <class... Params>
|
||||
struct Resolve {
|
||||
template <class Return>
|
||||
static constexpr auto func(Return(*ptr)(std::type_identity_t<Params>...)) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class Return, class Class>
|
||||
static constexpr auto func(Return(Class::*ptr)(std::type_identity_t<Params>...)) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class Return, class Class>
|
||||
static constexpr auto func(Return(Class::*ptr)(std::type_identity_t<Params>...) const) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static constexpr auto func(...) {
|
||||
return Unique::nvalue;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A specialization for giving the variadic types as a single type with the
|
||||
* function type. The return type is ignored.
|
||||
*/
|
||||
template <class... Params>
|
||||
struct Resolve<void(Params...)> : Resolve<Params...> {
|
||||
using Resolve<Params...>::func;
|
||||
};
|
||||
|
||||
/**
|
||||
* A type trait that checks if a class has a function called "constructor".
|
||||
*/
|
||||
template <class Class>
|
||||
concept HasConstructor = requires {
|
||||
&Class::constructor;
|
||||
};
|
||||
|
||||
/**
|
||||
* A type trait that checks if a class has a function called "destructor".
|
||||
*/
|
||||
template <class Class>
|
||||
concept HasDestructor = requires {
|
||||
&Class::destructor;
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct AsStaticType {
|
||||
using type = FunctionType;
|
||||
};
|
||||
|
||||
template <class Return, class Class, class... Params>
|
||||
struct AsStaticType<Return(Class::*)(Params...)> {
|
||||
using type = Return(*)(Class*, Params...);
|
||||
};
|
||||
|
||||
template <class Return, class Class, class... Params>
|
||||
struct AsStaticType<Return(Class::*)(Params...) const> {
|
||||
using type = Return(*)(Class const*, Params...);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
#pragma once
|
||||
#include "../utils/addresser.hpp"
|
||||
#include "Traits.hpp"
|
||||
|
||||
#define GEODE_WRAPPER_FOR_IDENTIFIER(identifier) \
|
||||
/* Default - function Return Class::identifier(Parameters...) does not exist */ \
|
||||
template <class Class, class FunctionType, class = void> \
|
||||
struct identifier { \
|
||||
public: \
|
||||
constexpr static inline auto value = nullptr; \
|
||||
constexpr static inline auto uuid = nullptr; \
|
||||
}; \
|
||||
/* Specialization - function Return Class::identifier(Parameters...) is a member function */ \
|
||||
template <class Class, class Return, class... Parameters> \
|
||||
struct identifier< \
|
||||
Class, Return(Parameters...), \
|
||||
std::enable_if_t<std::is_member_function_pointer_v< \
|
||||
decltype(substitute<Return(Parameters...)>(&Class::identifier))>>> { \
|
||||
private: \
|
||||
static Return wrapperImpl(Class* self, Parameters... ps) { \
|
||||
self = addresser::rthunkAdjust( \
|
||||
substitute<Return(Parameters...)>(&Class::identifier), self \
|
||||
); \
|
||||
return self->Class::identifier(ps...); \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
constexpr static inline auto value = &wrapperImpl; \
|
||||
constexpr static inline auto uuid = \
|
||||
FunctionUUID<substitute<Return(Parameters...)>(&Class::identifier)>::value; \
|
||||
}; \
|
||||
/* Specialization - function Return Class::identifier(Parameters...) is a static function */ \
|
||||
template <class Class, class Return, class... Parameters> \
|
||||
struct identifier< \
|
||||
Class, Return(Parameters...), \
|
||||
std::enable_if_t< \
|
||||
std::is_pointer_v<decltype(substitute<Return(Parameters...)>(&Class::identifier))>>> { \
|
||||
private: \
|
||||
static Return wrapperImpl(Parameters... ps) { \
|
||||
return Class::identifier(ps...); \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
constexpr static inline auto value = &wrapperImpl; \
|
||||
constexpr static inline auto uuid = \
|
||||
FunctionUUID<substitute<Return(Parameters...)>(&Class::identifier)>::value; \
|
||||
};
|
||||
|
||||
namespace geode::modifier {
|
||||
namespace wrap {
|
||||
GEODE_WRAPPER_FOR_IDENTIFIER(constructor)
|
||||
GEODE_WRAPPER_FOR_IDENTIFIER(destructor)
|
||||
};
|
||||
|
||||
// template <template<class, class, class=void> class Identifier, class Base, class Derived,
|
||||
// class ...Types> struct PotentiallyWrongIdentifier {
|
||||
|
||||
// template <typename D>
|
||||
// static std::true_type existsImpl(...);
|
||||
|
||||
// template <typename D, typename = std::enable_if_t<
|
||||
// (... && (
|
||||
// Identifier<D, Types>::uuid == nullptr ||
|
||||
// Identifier<Base, Types>::uuid == Identifier<D, Types>::uuid
|
||||
// ))
|
||||
// >>
|
||||
// static std::false_type existsImpl(char);
|
||||
|
||||
// template <typename D, typename = std::enable_if_t<
|
||||
// (... || (
|
||||
// Identifier<D, Types>::uuid != nullptr &&
|
||||
// Identifier<Base, Types>::uuid == Identifier<D, Types>::uuid
|
||||
// ))
|
||||
// >>
|
||||
// static std::false_type existsImpl(int);
|
||||
|
||||
// static constexpr bool value = decltype(existsImpl<Derived>(0))::value;
|
||||
|
||||
// };
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#include "AddIDs.hpp"
|
||||
|
||||
#include <Geode/Bindings.hpp>
|
||||
#include <Geode/Modify.hpp>
|
||||
#include <Geode/modify/CreatorLayer.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "AddIDs.hpp"
|
||||
|
||||
#include <Geode/Bindings.hpp>
|
||||
#include <Geode/Modify.hpp>
|
||||
#include <Geode/modify/LevelBrowserLayer.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "AddIDs.hpp"
|
||||
|
||||
#include <Geode/Bindings.hpp>
|
||||
#include <Geode/Modify.hpp>
|
||||
#include <Geode/modify/LevelSettingsLayer.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
@ -205,3 +205,25 @@ struct LevelSettingsLayerIDs : Modify<LevelSettingsLayerIDs, LevelSettingsLayer>
|
|||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class... Params>
|
||||
struct Resolve2 {
|
||||
template <class Return>
|
||||
static constexpr auto func(Return(*ptr)(float)) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class Return, class Class>
|
||||
static constexpr auto func(Return(Class::*ptr)(float)) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class Return, class Class>
|
||||
static constexpr auto func(Return(Class::*ptr)(float) const) {
|
||||
return ptr;
|
||||
}
|
||||
};
|
||||
|
||||
#include <Geode/modify/PlayerObject.hpp>
|
||||
constexpr auto b = Resolve2<float>::func(&PlayerObject::runBallRotation);
|
Loading…
Add table
Add a link
Reference in a new issue