[Method Bind] Add support for default argument values and static method binding. Sync headers.

pull/752/head
bruvzg 2022-05-04 14:27:08 +03:00
parent 24e4aeb2c6
commit 031a83b0ea
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
11 changed files with 794 additions and 115 deletions

View File

@ -8290,7 +8290,7 @@
"hash": 3, "hash": 3,
"arguments": [ "arguments": [
{ {
"name": "phi", "name": "angle",
"type": "float" "type": "float"
} }
] ]
@ -9779,11 +9779,11 @@
"hash": 3, "hash": 3,
"arguments": [ "arguments": [
{ {
"name": "by_axis", "name": "axis",
"type": "Vector3" "type": "Vector3"
}, },
{ {
"name": "phi", "name": "angle",
"type": "float" "type": "float"
} }
] ]
@ -10557,7 +10557,7 @@
"hash": 3, "hash": 3,
"arguments": [ "arguments": [
{ {
"name": "phi", "name": "angle",
"type": "float" "type": "float"
} }
] ]
@ -11997,7 +11997,7 @@
"type": "Vector3" "type": "Vector3"
}, },
{ {
"name": "phi", "name": "angle",
"type": "float" "type": "float"
} }
] ]
@ -12212,7 +12212,7 @@
"type": "Vector3" "type": "Vector3"
}, },
{ {
"name": "phi", "name": "angle",
"type": "float" "type": "float"
} }
] ]
@ -12372,7 +12372,7 @@
"type": "Vector3" "type": "Vector3"
}, },
{ {
"name": "phi", "name": "angle",
"type": "float" "type": "float"
} }
] ]
@ -30002,56 +30002,6 @@
} }
] ]
}, },
{
"name": "set_start_node",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "name",
"type": "StringName"
}
]
},
{
"name": "get_start_node",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "String"
}
},
{
"name": "set_end_node",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "name",
"type": "StringName"
}
]
},
{
"name": "get_end_node",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "String"
}
},
{ {
"name": "set_graph_offset", "name": "set_graph_offset",
"is_const": false, "is_const": false,
@ -120220,6 +120170,156 @@
} }
] ]
}, },
{
"name": "MissingNode",
"is_refcounted": false,
"is_instantiable": true,
"inherits": "Node",
"api_type": "core",
"methods": [
{
"name": "set_original_class",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "name",
"type": "String"
}
]
},
{
"name": "get_original_class",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "String"
}
},
{
"name": "set_recording_properties",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "enable",
"type": "bool"
}
]
},
{
"name": "is_recording_properties",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "bool"
}
}
],
"properties": [
{
"type": "String",
"name": "original_class",
"setter": "set_original_class",
"getter": "get_original_class",
"index": -1
},
{
"type": "bool",
"name": "recording_properties",
"setter": "set_recording_properties",
"getter": "is_recording_properties",
"index": -1
}
]
},
{
"name": "MissingResource",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "Resource",
"api_type": "core",
"methods": [
{
"name": "set_original_class",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "name",
"type": "String"
}
]
},
{
"name": "get_original_class",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "String"
}
},
{
"name": "set_recording_properties",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "enable",
"type": "bool"
}
]
},
{
"name": "is_recording_properties",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "bool"
}
}
],
"properties": [
{
"type": "String",
"name": "original_class",
"setter": "set_original_class",
"getter": "get_original_class",
"index": -1
},
{
"type": "bool",
"name": "recording_properties",
"setter": "set_recording_properties",
"getter": "is_recording_properties",
"index": -1
}
]
},
{ {
"name": "MobileVRInterface", "name": "MobileVRInterface",
"is_refcounted": true, "is_refcounted": true,
@ -124876,7 +124976,14 @@
"is_vararg": false, "is_vararg": false,
"is_static": false, "is_static": false,
"is_virtual": false, "is_virtual": false,
"hash": 134152229 "hash": 133279208,
"arguments": [
{
"name": "on_thread",
"type": "bool",
"default_value": "true"
}
]
} }
], ],
"signals": [ "signals": [
@ -130865,6 +130972,24 @@
} }
] ]
}, },
{
"name": "is_process_running",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135374120,
"return_value": {
"type": "bool"
},
"arguments": [
{
"name": "pid",
"type": "int",
"meta": "int32"
}
]
},
{ {
"name": "get_process_id", "name": "get_process_id",
"is_const": true, "is_const": true,
@ -151227,6 +151352,206 @@
} }
] ]
}, },
{
"name": "PlaceholderCubemap",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "PlaceholderTextureLayered",
"api_type": "core"
},
{
"name": "PlaceholderCubemapArray",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "PlaceholderTextureLayered",
"api_type": "core"
},
{
"name": "PlaceholderMaterial",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "Material",
"api_type": "core"
},
{
"name": "PlaceholderMesh",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "Mesh",
"api_type": "core",
"methods": [
{
"name": "set_aabb",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "aabb",
"type": "AABB"
}
]
}
],
"properties": [
{
"type": "AABB",
"name": "aabb",
"setter": "set_aabb",
"getter": "get_aabb",
"index": -1
}
]
},
{
"name": "PlaceholderTexture2D",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "Texture2D",
"api_type": "core",
"methods": [
{
"name": "set_size",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "size",
"type": "Vector2"
}
]
}
],
"properties": [
{
"type": "Vector2i",
"name": "size",
"setter": "set_size",
"getter": "get_size",
"index": -1
}
]
},
{
"name": "PlaceholderTexture2DArray",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "PlaceholderTextureLayered",
"api_type": "core"
},
{
"name": "PlaceholderTexture3D",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "Texture3D",
"api_type": "core",
"methods": [
{
"name": "set_size",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "size",
"type": "Vector3i"
}
]
},
{
"name": "get_size",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "Vector3i"
}
}
],
"properties": [
{
"type": "Vector3i",
"name": "size",
"setter": "set_size",
"getter": "get_size",
"index": -1
}
]
},
{
"name": "PlaceholderTextureLayered",
"is_refcounted": true,
"is_instantiable": false,
"inherits": "TextureLayered",
"api_type": "core",
"methods": [
{
"name": "set_size",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "size",
"type": "Vector2i"
}
]
},
{
"name": "get_size",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "Vector2i"
}
},
{
"name": "set_layers",
"is_const": false,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 134188166,
"arguments": [
{
"name": "layers",
"type": "int",
"meta": "int32"
}
]
}
],
"properties": [
{
"type": "Vector2i",
"name": "size",
"setter": "set_size",
"getter": "get_size",
"index": -1
},
{
"type": "int",
"name": "layers",
"setter": "set_layers",
"getter": "get_layers",
"index": -1
}
]
},
{ {
"name": "PlaneMesh", "name": "PlaneMesh",
"is_refcounted": true, "is_refcounted": true,
@ -176586,6 +176911,17 @@
"type": "enum::RenderingDevice.DeviceType" "type": "enum::RenderingDevice.DeviceType"
} }
}, },
{
"name": "get_video_adapter_api_version",
"is_const": true,
"is_vararg": false,
"is_static": false,
"is_virtual": false,
"hash": 135338183,
"return_value": {
"type": "String"
}
},
{ {
"name": "make_sphere_mesh", "name": "make_sphere_mesh",
"is_const": false, "is_const": false,
@ -215014,6 +215350,13 @@
} }
] ]
}, },
{
"name": "TextServerFallback",
"is_refcounted": true,
"is_instantiable": true,
"inherits": "TextServerExtension",
"api_type": "core"
},
{ {
"name": "TextServerManager", "name": "TextServerManager",
"is_refcounted": false, "is_refcounted": false,
@ -223084,7 +223427,7 @@
] ]
}, },
{ {
"name": "get_datetime_dict_from_string", "name": "get_datetime_dict_from_datetime_string",
"is_const": true, "is_const": true,
"is_vararg": false, "is_vararg": false,
"is_static": false, "is_static": false,
@ -223105,7 +223448,7 @@
] ]
}, },
{ {
"name": "get_datetime_string_from_dict", "name": "get_datetime_string_from_datetime_dict",
"is_const": true, "is_const": true,
"is_vararg": false, "is_vararg": false,
"is_static": false, "is_static": false,

View File

@ -440,6 +440,118 @@ GDNativeExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_ar
return md; return md;
} }
template <class... P, size_t... Is>
void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, GDNativeCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDNATIVE_CALL_OK;
#ifdef DEBUG_METHODS_ENABLED
(p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
#else
(p_method)(VariantCaster<P>::cast(*p_args[Is])...);
#endif
}
template <class... P>
void call_with_variant_args_static_dv(void (*p_method)(P...), const GDNativeVariantPtr *p_args, int p_argcount, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = sizeof...(P);
return;
}
#endif
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
int32_t dvs = default_values.size();
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = sizeof...(P);
return;
}
#endif
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
std::array<const Variant *, sizeof...(P)> argsp;
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
if (i < p_argcount) {
args[i] = Variant(p_args[i]);
} else {
args[i] = default_values[i - p_argcount + (dvs - missing)];
}
argsp[i] = &args[i];
}
call_with_variant_args_static(p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class... P, size_t... Is>
void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const GDNativeTypePtr *p_args, IndexSequence<Is...>) {
p_method(PtrToArg<P>::convert(p_args[Is])...);
}
template <class... P>
void call_with_ptr_args_static_method(void (*p_method)(P...), const GDNativeTypePtr *p_args) {
call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
}
template <class R, class... P, size_t... Is>
void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, GDNativeCallError &r_error, IndexSequence<Is...>) {
r_error.error = GDNATIVE_CALL_OK;
#ifdef DEBUG_METHODS_ENABLED
r_ret = (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
#else
r_ret = (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
#endif
}
template <class R, class... P>
void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDNativeVariantPtr *p_args, int p_argcount, Variant &r_ret, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
#ifdef DEBUG_ENABLED
if ((size_t)p_argcount > sizeof...(P)) {
r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
r_error.argument = sizeof...(P);
return;
}
#endif
int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
int32_t dvs = default_values.size();
#ifdef DEBUG_ENABLED
if (missing > dvs) {
r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = sizeof...(P);
return;
}
#endif
Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
std::array<const Variant *, sizeof...(P)> argsp;
for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
if (i < p_argcount) {
args[i] = Variant(p_args[i]);
} else {
args[i] = default_values[i - p_argcount + (dvs - missing)];
}
argsp[i] = &args[i];
}
call_with_variant_args_static_ret(p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
}
template <class R, class... P, size_t... Is>
void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const GDNativeTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret);
}
template <class R, class... P>
void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const GDNativeTypePtr *p_args, void *r_ret) {
call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
}
#if defined(__GNUC__) && !defined(__clang__) #if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif

View File

@ -46,6 +46,8 @@
namespace godot { namespace godot {
#define DEFVAL(m_defval) (m_defval)
struct MethodDefinition { struct MethodDefinition {
const char *name = nullptr; const char *name = nullptr;
std::list<std::string> args; std::list<std::string> args;
@ -101,10 +103,15 @@ public:
template <class T> template <class T>
static void register_class(); static void register_class();
template <class N, class M> template <class N, class M, typename... VarArgs>
static MethodBind *bind_method(N p_method_name, M p_method); static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
template <class N, class M, typename... VarArgs>
static MethodBind *bind_static_method(const char *p_class, N p_method_name, M p_method, VarArgs... p_args);
template <class M> template <class M>
static MethodBind *bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true); static MethodBind *bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
static void add_property_group(const char *p_class, const char *p_name, const char *p_prefix); static void add_property_group(const char *p_class, const char *p_name, const char *p_prefix);
static void add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix); static void add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix);
static void add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index = -1); static void add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index = -1);
@ -172,11 +179,27 @@ void ClassDB::register_class() {
initialize_class(classes[cl.name]); initialize_class(classes[cl.name]);
} }
template <class N, class M> template <class N, class M, typename... VarArgs>
MethodBind *ClassDB::bind_method(N p_method_name, M p_method) { MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
for (uint32_t i = 0; i < sizeof...(p_args); i++) {
argptrs[i] = &args[i];
}
MethodBind *bind = create_method_bind(p_method); MethodBind *bind = create_method_bind(p_method);
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args));
}
return bind_methodfi(0, bind, p_method_name, nullptr, 0); template <class N, class M, typename... VarArgs>
MethodBind *ClassDB::bind_static_method(const char *p_class, N p_method_name, M p_method, VarArgs... p_args) {
Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
const Variant *argptrs[sizeof...(p_args) + 1];
for (uint32_t i = 0; i < sizeof...(p_args); i++) {
argptrs[i] = &args[i];
}
MethodBind *bind = create_static_method_bind(p_method);
bind->set_instance_class(p_class);
return bind_methodfi(0, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args));
} }
template <class M> template <class M>

View File

@ -53,8 +53,10 @@ class MethodBind {
int argument_count = 0; int argument_count = 0;
uint32_t hint_flags = METHOD_FLAGS_DEFAULT; uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
bool _static = false;
bool _is_const = false; bool _is_const = false;
bool _has_return = false; bool _has_return = false;
bool _vararg = false;
std::vector<std::string> argument_names; std::vector<std::string> argument_names;
GDNativeVariantType *argument_types = nullptr; GDNativeVariantType *argument_types = nullptr;
@ -66,6 +68,8 @@ protected:
void generate_argument_types(int p_count); void generate_argument_types(int p_count);
void set_const(bool p_const); void set_const(bool p_const);
void set_return(bool p_return); void set_return(bool p_return);
void set_static(bool p_static);
void set_vararg(bool p_vararg);
void set_argument_count(int p_count); void set_argument_count(int p_count);
public: public:
@ -96,8 +100,10 @@ public:
_FORCE_INLINE_ int get_argument_count() const { return argument_count; }; _FORCE_INLINE_ int get_argument_count() const { return argument_count; };
_FORCE_INLINE_ bool is_const() const { return _is_const; } _FORCE_INLINE_ bool is_const() const { return _is_const; }
_FORCE_INLINE_ bool is_static() const { return _static; }
_FORCE_INLINE_ bool is_vararg() const { return _vararg; }
_FORCE_INLINE_ bool has_return() const { return _has_return; } _FORCE_INLINE_ bool has_return() const { return _has_return; }
_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags; } _FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDNATIVE_EXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDNATIVE_EXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDNATIVE_EXTENSION_METHOD_FLAG_STATIC : 0); }
_FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; } _FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
void set_argument_names(const std::vector<std::string> &p_names); void set_argument_names(const std::vector<std::string> &p_names);
std::vector<std::string> get_argument_names() const; std::vector<std::string> get_argument_names() const;
@ -155,15 +161,13 @@ public:
ERR_FAIL(); // Can't call. ERR_FAIL(); // Can't call.
} }
virtual bool is_const() const { return false; }
virtual bool is_vararg() const { return true; }
MethodBindVarArgBase( MethodBindVarArgBase(
R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &), R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
const MethodInfo &p_method_info, const MethodInfo &p_method_info,
bool p_return_nil_is_variant) : bool p_return_nil_is_variant) :
method(p_method), method_info(p_method_info) { method(p_method), method_info(p_method_info) {
set_vararg(true);
set_const(true);
set_argument_count(method_info.arguments.size()); set_argument_count(method_info.arguments.size());
if (method_info.arguments.size()) { if (method_info.arguments.size()) {
std::vector<std::string> names; std::vector<std::string> names;
@ -572,6 +576,138 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
return a; return a;
} }
// STATIC BINDS
// no return
template <class... P>
class MethodBindTS : public MethodBind {
void (*function)(P...);
protected:
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
#endif
virtual GDNativeVariantType gen_argument_type(int p_arg) const {
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
return call_get_argument_type<P...>(p_arg);
} else {
return GDNATIVE_VARIANT_TYPE_NIL;
}
}
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
GDNativePropertyInfo pi;
call_get_argument_type_info<P...>(p_arg, pi);
return pi;
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
public:
virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_arg) const {
return call_get_argument_metadata<P...>(p_arg);
}
virtual Variant call(GDExtensionClassInstancePtr p_object, const GDNativeVariantPtr *p_args, const GDNativeInt p_arg_count, GDNativeCallError &r_error) const {
(void)p_object; // unused
call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments());
return Variant();
}
virtual void ptrcall(GDExtensionClassInstancePtr p_object, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
(void)p_object;
(void)r_ret;
call_with_ptr_args_static_method(function, p_args);
}
MethodBindTS(void (*p_function)(P...)) {
function = p_function;
generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
set_static(true);
}
};
template <class... P>
MethodBind *create_static_method_bind(void (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
return a;
}
// return
template <class R, class... P>
class MethodBindTRS : public MethodBind {
R(*function)
(P...);
protected:
// GCC raises warnings in the case P = {} as the comparison is always false...
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
#endif
virtual GDNativeVariantType gen_argument_type(int p_arg) const {
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
return call_get_argument_type<P...>(p_arg);
} else {
return GetTypeInfo<R>::VARIANT_TYPE;
}
}
virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
GDNativePropertyInfo pi;
call_get_argument_type_info<P...>(p_arg, pi);
return pi;
} else {
return GetTypeInfo<R>::get_class_info();
}
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
public:
virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_arg) const {
if (p_arg >= 0) {
return call_get_argument_metadata<P...>(p_arg);
} else {
return GetTypeInfo<R>::METADATA;
}
}
virtual Variant call(GDExtensionClassInstancePtr p_object, const GDNativeVariantPtr *p_args, const GDNativeInt p_arg_count, GDNativeCallError &r_error) const {
Variant ret;
call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments());
return ret;
}
virtual void ptrcall(GDExtensionClassInstancePtr p_object, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
(void)p_object;
call_with_ptr_args_static_method_ret(function, p_args, r_ret);
}
MethodBindTRS(R (*p_function)(P...)) {
function = p_function;
generate_argument_types(sizeof...(P));
set_argument_count(sizeof...(P));
set_static(true);
set_return(true);
}
};
template <class R, class... P>
MethodBind *create_static_method_bind(R (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
return a;
}
} // namespace godot } // namespace godot
#endif // ! GODOT_CPP_METHOD_BIND_HPP #endif // ! GODOT_CPP_METHOD_BIND_HPP

View File

@ -117,20 +117,20 @@ struct MethodInfo {
template <class... Args> template <class... Args>
MethodInfo::MethodInfo(const char *p_name, const Args &...args) : MethodInfo::MethodInfo(const char *p_name, const Args &...args) :
name(p_name), flags(METHOD_FLAG_NORMAL) { name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
arguments = { args... }; arguments = { args... };
} }
template <class... Args> template <class... Args>
MethodInfo::MethodInfo(Variant::Type ret, const char *p_name, const Args &...args) : MethodInfo::MethodInfo(Variant::Type ret, const char *p_name, const Args &...args) :
name(p_name), flags(METHOD_FLAG_NORMAL) { name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
return_val.type = ret; return_val.type = ret;
arguments = { args... }; arguments = { args... };
} }
template <class... Args> template <class... Args>
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...args) : MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...args) :
name(p_name), return_val(p_ret), flags(METHOD_FLAG_NORMAL) { name(p_name), return_val(p_ret), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
arguments = { args... }; arguments = { args... };
} }

View File

@ -95,9 +95,9 @@ void ClassDB::add_property(const char *p_class, const PropertyInfo &p_pinfo, con
// register with Godot // register with Godot
GDNativePropertyInfo prop_info = { GDNativePropertyInfo prop_info = {
(uint32_t)p_pinfo.type, //uint32_t type; (uint32_t)p_pinfo.type, // uint32_t type;
p_pinfo.name, //const char *name; p_pinfo.name, // const char *name;
p_pinfo.class_name, //const char *class_name; p_pinfo.class_name, // const char *class_name;
p_pinfo.hint, // NONE //uint32_t hint; p_pinfo.hint, // NONE //uint32_t hint;
p_pinfo.hint_string, // const char *hint_string; p_pinfo.hint_string, // const char *hint_string;
p_pinfo.usage, // DEFAULT //uint32_t usage; p_pinfo.usage, // DEFAULT //uint32_t usage;
@ -169,6 +169,16 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const M
p_bind->set_argument_names(args); p_bind->set_argument_names(args);
std::vector<Variant> defvals;
defvals.resize(p_defcount);
for (int i = 0; i < p_defcount; i++) {
defvals[i] = *static_cast<const Variant *>(p_defs[i]);
}
p_bind->set_default_arguments(defvals);
p_bind->set_hint_flags(p_flags);
// register our method bind within our plugin // register our method bind within our plugin
type.method_map[method_name.name] = p_bind; type.method_map[method_name.name] = p_bind;
@ -179,19 +189,27 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const M
} }
void ClassDB::bind_method_godot(const char *p_class_name, MethodBind *p_method) { void ClassDB::bind_method_godot(const char *p_class_name, MethodBind *p_method) {
std::vector<GDNativeVariantPtr> def_args;
const std::vector<Variant> &def_args_val = p_method->get_default_arguments();
def_args.resize(def_args_val.size());
for (int i = 0; i < def_args_val.size(); i++) {
def_args[i] = (GDNativeVariantPtr)&def_args_val[i];
}
GDNativeExtensionClassMethodInfo method_info = { GDNativeExtensionClassMethodInfo method_info = {
p_method->get_name(), //const char *name; p_method->get_name(), // const char *name;
p_method, //void *method_userdata; p_method, // void *method_userdata;
MethodBind::bind_call, //GDNativeExtensionClassMethodCall call_func; MethodBind::bind_call, // GDNativeExtensionClassMethodCall call_func;
MethodBind::bind_ptrcall, //GDNativeExtensionClassMethodPtrCall ptrcall_func; MethodBind::bind_ptrcall, // GDNativeExtensionClassMethodPtrCall ptrcall_func;
GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT, //uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */ p_method->get_hint_flags(), // uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */
(uint32_t)p_method->get_argument_count(), //uint32_t argument_count; (uint32_t)p_method->get_argument_count(), // uint32_t argument_count;
(GDNativeBool)p_method->has_return(), //GDNativeBool has_return_value; (GDNativeBool)p_method->has_return(), // GDNativeBool has_return_value;
MethodBind::bind_get_argument_type, //(GDNativeExtensionClassMethodGetArgumentType) get_argument_type_func; MethodBind::bind_get_argument_type, //(GDNativeExtensionClassMethodGetArgumentType) get_argument_type_func;
MethodBind::bind_get_argument_info, //GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */ MethodBind::bind_get_argument_info, // GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
MethodBind::bind_get_argument_metadata, //GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func; MethodBind::bind_get_argument_metadata, // GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
p_method->get_hint_flags(), //uint32_t default_argument_count; (uint32_t)p_method->get_default_argument_count(), // uint32_t default_argument_count;
nullptr, //GDNativeVariantPtr *default_arguments; def_args.data(), // GDNativeVariantPtr *default_arguments;
}; };
internal::gdn_interface->classdb_register_extension_class_method(internal::library, p_class_name, &method_info); internal::gdn_interface->classdb_register_extension_class_method(internal::library, p_class_name, &method_info);
} }

View File

@ -52,6 +52,14 @@ void MethodBind::set_return(bool p_return) {
_has_return = p_return; _has_return = p_return;
} }
void MethodBind::set_static(bool p_static) {
_static = p_static;
}
void MethodBind::set_vararg(bool p_vararg) {
_vararg = p_vararg;
}
void MethodBind::set_argument_names(const std::vector<std::string> &p_names) { void MethodBind::set_argument_names(const std::vector<std::string> &p_names) {
argument_names = p_names; argument_names = p_names;
} }

View File

@ -33,22 +33,22 @@
namespace godot { namespace godot {
MethodInfo::MethodInfo() : MethodInfo::MethodInfo() :
flags(METHOD_FLAG_NORMAL) {} flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {}
MethodInfo::MethodInfo(const char *p_name) : MethodInfo::MethodInfo(const char *p_name) :
name(p_name), flags(METHOD_FLAG_NORMAL) {} name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {}
MethodInfo::MethodInfo(Variant::Type ret) : MethodInfo::MethodInfo(Variant::Type ret) :
flags(METHOD_FLAG_NORMAL) { flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
return_val.type = ret; return_val.type = ret;
} }
MethodInfo::MethodInfo(Variant::Type ret, const char *p_name) : MethodInfo::MethodInfo(Variant::Type ret, const char *p_name) :
name(p_name), flags(METHOD_FLAG_NORMAL) { name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
return_val.type = ret; return_val.type = ret;
} }
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name) : MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name) :
name(p_name), return_val(p_ret), flags(METHOD_FLAG_NORMAL) {} name(p_name), return_val(p_ret), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {}
} // namespace godot } // namespace godot

View File

@ -2,32 +2,49 @@ extends Node
func _ready(): func _ready():
# Bind signals # Bind signals
prints("Signal bind")
$Button.button_up.connect($Example.emit_custom_signal.bind("Button", 42)) $Button.button_up.connect($Example.emit_custom_signal.bind("Button", 42))
prints("")
# Call static methods.
prints("Static method calls")
prints(" static (109)", Example.test_static(9, 100));
Example.test_static2();
# Call methods. # Call methods.
prints("Instance method calls")
$Example.simple_func() $Example.simple_func()
($Example as Example).simple_const_func() # Force use of ptrcall ($Example as Example).simple_const_func() # Force use of ptrcall
prints("returned", $Example.return_something("some string")) prints(" returned", $Example.return_something("some string"))
prints("returned const", $Example.return_something_const()) prints(" returned const", $Example.return_something_const())
prints("returned ref", $Example.return_extended_ref()) prints(" returned ref", $Example.return_extended_ref())
prints("VarArg method calls")
var ref = ExampleRef.new() var ref = ExampleRef.new()
prints("sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id()) prints(" sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id())
prints("vararg args", $Example.varargs_func("some", "arguments", "to", "test")) prints(" vararg args", $Example.varargs_func("some", "arguments", "to", "test"))
prints("vararg_nv ret", $Example.varargs_func_nv("some", "arguments", "to", "test")) prints(" vararg_nv ret", $Example.varargs_func_nv("some", "arguments", "to", "test"))
$Example.varargs_func_void("some", "arguments", "to", "test") $Example.varargs_func_void("some", "arguments", "to", "test")
prints("test array", $Example.test_array()) prints("Method calls with default values")
prints("test dictionary", $Example.test_dictionary()) prints(" defval (300)", $Example.def_args())
prints(" defval (250)", $Example.def_args(50))
prints(" defval (150)", $Example.def_args(50, 100))
# Use properties. prints("Array and Dictionary")
prints("custom position is", $Example.group_subgroup_custom_position) prints(" test array", $Example.test_array())
prints(" test dictionary", $Example.test_dictionary())
prints("Properties")
prints(" custom position is", $Example.group_subgroup_custom_position)
$Example.group_subgroup_custom_position = Vector2(50, 50) $Example.group_subgroup_custom_position = Vector2(50, 50)
prints("custom position now is", $Example.group_subgroup_custom_position) prints(" custom position now is", $Example.group_subgroup_custom_position)
# Get constants prints("Constnts")
prints("FIRST", $Example.FIRST) prints(" FIRST", $Example.FIRST)
prints("ANSWER_TO_EVERYTHING", $Example.ANSWER_TO_EVERYTHING) prints(" ANSWER_TO_EVERYTHING", $Example.ANSWER_TO_EVERYTHING)
prints("CONSTANT_WITHOUT_ENUM", $Example.CONSTANT_WITHOUT_ENUM) prints(" CONSTANT_WITHOUT_ENUM", $Example.CONSTANT_WITHOUT_ENUM)
func _on_Example_custom_signal(name, value): func _on_Example_custom_signal(name, value):
prints("Example emitted:", name, value) prints("Example emitted:", name, value)

View File

@ -46,6 +46,18 @@ ExampleRef::~ExampleRef() {
UtilityFunctions::print("ExampleRef destroyed."); UtilityFunctions::print("ExampleRef destroyed.");
} }
int Example::test_static(int p_a, int p_b) {
return p_a + p_b;
}
void Example::test_static2() {
UtilityFunctions::print(" void static");
}
int Example::def_args(int p_a, int p_b) {
return p_a + p_b;
}
void Example::_bind_methods() { void Example::_bind_methods() {
// Methods. // Methods.
ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func); ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
@ -58,6 +70,11 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array); ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array);
ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary); ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary);
ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
{ {
MethodInfo mi; MethodInfo mi;
mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument")); mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument"));
@ -108,20 +125,20 @@ Example::~Example() {
// Methods. // Methods.
void Example::simple_func() { void Example::simple_func() {
UtilityFunctions::print("Simple func called."); UtilityFunctions::print(" Simple func called.");
} }
void Example::simple_const_func() const { void Example::simple_const_func() const {
UtilityFunctions::print("Simple const func called."); UtilityFunctions::print(" Simple const func called.");
} }
String Example::return_something(const String &base) { String Example::return_something(const String &base) {
UtilityFunctions::print("Return something called."); UtilityFunctions::print(" Return something called.");
return base; return base;
} }
Viewport *Example::return_something_const() const { Viewport *Example::return_something_const() const {
UtilityFunctions::print("Return something const called."); UtilityFunctions::print(" Return something const called.");
if (is_inside_tree()) { if (is_inside_tree()) {
Viewport *result = get_viewport(); Viewport *result = get_viewport();
return result; return result;
@ -138,22 +155,22 @@ Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
ref.instantiate(); ref.instantiate();
// TODO the returned value gets dereferenced too early and return a null object otherwise. // TODO the returned value gets dereferenced too early and return a null object otherwise.
ref->reference(); ref->reference();
UtilityFunctions::print("Example ref checks called with value: ", p_ref->get_instance_id(), ", returning value: ", ref->get_instance_id()); UtilityFunctions::print(" Example ref checks called with value: ", p_ref->get_instance_id(), ", returning value: ", ref->get_instance_id());
return ref; return ref;
} }
Variant Example::varargs_func(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) { Variant Example::varargs_func(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
UtilityFunctions::print("Varargs (Variant return) called with ", String::num((double)arg_count), " arguments"); UtilityFunctions::print(" Varargs (Variant return) called with ", String::num((double)arg_count), " arguments");
return arg_count; return arg_count;
} }
int Example::varargs_func_nv(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) { int Example::varargs_func_nv(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
UtilityFunctions::print("Varargs (int return) called with ", String::num((double)arg_count), " arguments"); UtilityFunctions::print(" Varargs (int return) called with ", String::num((double)arg_count), " arguments");
return 42; return 42;
} }
void Example::varargs_func_void(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) { void Example::varargs_func_void(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
UtilityFunctions::print("Varargs (no return) called with ", String::num((double)arg_count), " arguments"); UtilityFunctions::print(" Varargs (no return) called with ", String::num((double)arg_count), " arguments");
} }
void Example::emit_custom_signal(const String &name, int value) { void Example::emit_custom_signal(const String &name, int value) {

View File

@ -90,6 +90,7 @@ public:
int varargs_func_nv(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error); int varargs_func_nv(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error);
void varargs_func_void(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error); void varargs_func_void(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error);
void emit_custom_signal(const String &name, int value); void emit_custom_signal(const String &name, int value);
int def_args(int p_a = 100, int p_b = 200);
Array test_array() const; Array test_array() const;
Dictionary test_dictionary() const; Dictionary test_dictionary() const;
@ -98,6 +99,10 @@ public:
void set_custom_position(const Vector2 &pos); void set_custom_position(const Vector2 &pos);
Vector2 get_custom_position() const; Vector2 get_custom_position() const;
// Static method.
static int test_static(int p_a, int p_b);
static void test_static2();
// Virtual function override (no need to bind manually). // Virtual function override (no need to bind manually).
virtual bool _has_point(const Vector2 &point) const override; virtual bool _has_point(const Vector2 &point) const override;
}; };