mirror of
https://github.com/godotengine/godot
synced 2024-09-04 22:28:26 +00:00
Merge pull request #87680 from AThousandShips/the_angry_count
Add methods to get argument count of methods
This commit is contained in:
commit
a1c476f9d7
|
@ -1434,6 +1434,10 @@ bool ClassDB::class_has_method(const StringName &p_class, const StringName &p_me
|
||||||
return ::ClassDB::has_method(p_class, p_method, p_no_inheritance);
|
return ::ClassDB::has_method(p_class, p_method, p_no_inheritance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ClassDB::class_get_method_argument_count(const StringName &p_class, const StringName &p_method, bool p_no_inheritance) const {
|
||||||
|
return ::ClassDB::get_method_argument_count(p_class, p_method, nullptr, p_no_inheritance);
|
||||||
|
}
|
||||||
|
|
||||||
TypedArray<Dictionary> ClassDB::class_get_method_list(const StringName &p_class, bool p_no_inheritance) const {
|
TypedArray<Dictionary> ClassDB::class_get_method_list(const StringName &p_class, bool p_no_inheritance) const {
|
||||||
List<MethodInfo> methods;
|
List<MethodInfo> methods;
|
||||||
::ClassDB::get_method_list(p_class, &methods, p_no_inheritance);
|
::ClassDB::get_method_list(p_class, &methods, p_no_inheritance);
|
||||||
|
@ -1562,6 +1566,8 @@ void ClassDB::_bind_methods() {
|
||||||
|
|
||||||
::ClassDB::bind_method(D_METHOD("class_has_method", "class", "method", "no_inheritance"), &ClassDB::class_has_method, DEFVAL(false));
|
::ClassDB::bind_method(D_METHOD("class_has_method", "class", "method", "no_inheritance"), &ClassDB::class_has_method, DEFVAL(false));
|
||||||
|
|
||||||
|
::ClassDB::bind_method(D_METHOD("class_get_method_argument_count", "class", "method", "no_inheritance"), &ClassDB::class_get_method_argument_count, DEFVAL(false));
|
||||||
|
|
||||||
::ClassDB::bind_method(D_METHOD("class_get_method_list", "class", "no_inheritance"), &ClassDB::class_get_method_list, DEFVAL(false));
|
::ClassDB::bind_method(D_METHOD("class_get_method_list", "class", "no_inheritance"), &ClassDB::class_get_method_list, DEFVAL(false));
|
||||||
|
|
||||||
::ClassDB::bind_method(D_METHOD("class_get_integer_constant_list", "class", "no_inheritance"), &ClassDB::class_get_integer_constant_list, DEFVAL(false));
|
::ClassDB::bind_method(D_METHOD("class_get_integer_constant_list", "class", "no_inheritance"), &ClassDB::class_get_integer_constant_list, DEFVAL(false));
|
||||||
|
|
|
@ -447,6 +447,8 @@ public:
|
||||||
|
|
||||||
bool class_has_method(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false) const;
|
bool class_has_method(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false) const;
|
||||||
|
|
||||||
|
int class_get_method_argument_count(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false) const;
|
||||||
|
|
||||||
TypedArray<Dictionary> class_get_method_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
TypedArray<Dictionary> class_get_method_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||||
|
|
||||||
PackedStringArray class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
PackedStringArray class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||||
|
|
|
@ -59,6 +59,8 @@ class CallableCustomExtension : public CallableCustom {
|
||||||
|
|
||||||
GDExtensionCallableCustomToString to_string_func;
|
GDExtensionCallableCustomToString to_string_func;
|
||||||
|
|
||||||
|
GDExtensionCallableCustomGetArgumentCount get_argument_count_func;
|
||||||
|
|
||||||
uint32_t _hash;
|
uint32_t _hash;
|
||||||
|
|
||||||
static bool default_compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) {
|
static bool default_compare_equal(const CallableCustom *p_a, const CallableCustom *p_b) {
|
||||||
|
@ -143,6 +145,21 @@ public:
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_argument_count(bool &r_is_valid) const override {
|
||||||
|
if (get_argument_count_func != nullptr) {
|
||||||
|
GDExtensionBool is_valid = false;
|
||||||
|
|
||||||
|
GDExtensionInt ret = get_argument_count_func(userdata, &is_valid);
|
||||||
|
|
||||||
|
if (is_valid) {
|
||||||
|
r_is_valid = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r_is_valid = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void *get_userdata(void *p_token) const {
|
void *get_userdata(void *p_token) const {
|
||||||
return (p_token == token) ? userdata : nullptr;
|
return (p_token == token) ? userdata : nullptr;
|
||||||
}
|
}
|
||||||
|
@ -157,6 +174,7 @@ public:
|
||||||
r_call_error.expected = error.expected;
|
r_call_error.expected = error.expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
CallableCustomExtension(GDExtensionCallableCustomInfo *p_info) {
|
CallableCustomExtension(GDExtensionCallableCustomInfo *p_info) {
|
||||||
userdata = p_info->callable_userdata;
|
userdata = p_info->callable_userdata;
|
||||||
token = p_info->token;
|
token = p_info->token;
|
||||||
|
@ -172,6 +190,35 @@ public:
|
||||||
|
|
||||||
to_string_func = p_info->to_string_func;
|
to_string_func = p_info->to_string_func;
|
||||||
|
|
||||||
|
get_argument_count_func = nullptr;
|
||||||
|
|
||||||
|
// Pre-calculate the hash.
|
||||||
|
if (p_info->hash_func != nullptr) {
|
||||||
|
_hash = p_info->hash_func(userdata);
|
||||||
|
} else {
|
||||||
|
_hash = hash_murmur3_one_64((uint64_t)call_func);
|
||||||
|
_hash = hash_murmur3_one_64((uint64_t)userdata, _hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CallableCustomExtension(GDExtensionCallableCustomInfo2 *p_info) {
|
||||||
|
userdata = p_info->callable_userdata;
|
||||||
|
token = p_info->token;
|
||||||
|
|
||||||
|
object = p_info->object_id;
|
||||||
|
|
||||||
|
call_func = p_info->call_func;
|
||||||
|
is_valid_func = p_info->is_valid_func;
|
||||||
|
free_func = p_info->free_func;
|
||||||
|
|
||||||
|
equal_func = p_info->equal_func;
|
||||||
|
less_than_func = p_info->less_than_func;
|
||||||
|
|
||||||
|
to_string_func = p_info->to_string_func;
|
||||||
|
|
||||||
|
get_argument_count_func = p_info->get_argument_count_func;
|
||||||
|
|
||||||
// Pre-calculate the hash.
|
// Pre-calculate the hash.
|
||||||
if (p_info->hash_func != nullptr) {
|
if (p_info->hash_func != nullptr) {
|
||||||
_hash = p_info->hash_func(userdata);
|
_hash = p_info->hash_func(userdata);
|
||||||
|
@ -1378,9 +1425,15 @@ static GDExtensionScriptInstancePtr gdextension_object_get_script_instance(GDExt
|
||||||
return script_instance_extension->instance;
|
return script_instance_extension->instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
static void gdextension_callable_custom_create(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo *p_custom_callable_info) {
|
static void gdextension_callable_custom_create(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo *p_custom_callable_info) {
|
||||||
memnew_placement(r_callable, Callable(memnew(CallableCustomExtension(p_custom_callable_info))));
|
memnew_placement(r_callable, Callable(memnew(CallableCustomExtension(p_custom_callable_info))));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void gdextension_callable_custom_create2(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo2 *p_custom_callable_info) {
|
||||||
|
memnew_placement(r_callable, Callable(memnew(CallableCustomExtension(p_custom_callable_info))));
|
||||||
|
}
|
||||||
|
|
||||||
static void *gdextension_callable_custom_get_userdata(GDExtensionTypePtr p_callable, void *p_token) {
|
static void *gdextension_callable_custom_get_userdata(GDExtensionTypePtr p_callable, void *p_token) {
|
||||||
const Callable &callable = *reinterpret_cast<const Callable *>(p_callable);
|
const Callable &callable = *reinterpret_cast<const Callable *>(p_callable);
|
||||||
|
@ -1595,7 +1648,10 @@ void gdextension_setup_interface() {
|
||||||
REGISTER_INTERFACE_FUNC(placeholder_script_instance_create);
|
REGISTER_INTERFACE_FUNC(placeholder_script_instance_create);
|
||||||
REGISTER_INTERFACE_FUNC(placeholder_script_instance_update);
|
REGISTER_INTERFACE_FUNC(placeholder_script_instance_update);
|
||||||
REGISTER_INTERFACE_FUNC(object_get_script_instance);
|
REGISTER_INTERFACE_FUNC(object_get_script_instance);
|
||||||
|
#ifndef DISABLE_DEPRECATED
|
||||||
REGISTER_INTERFACE_FUNC(callable_custom_create);
|
REGISTER_INTERFACE_FUNC(callable_custom_create);
|
||||||
|
#endif // DISABLE_DEPRECATED
|
||||||
|
REGISTER_INTERFACE_FUNC(callable_custom_create2);
|
||||||
REGISTER_INTERFACE_FUNC(callable_custom_get_userdata);
|
REGISTER_INTERFACE_FUNC(callable_custom_get_userdata);
|
||||||
REGISTER_INTERFACE_FUNC(classdb_construct_object);
|
REGISTER_INTERFACE_FUNC(classdb_construct_object);
|
||||||
REGISTER_INTERFACE_FUNC(classdb_get_method_bind);
|
REGISTER_INTERFACE_FUNC(classdb_get_method_bind);
|
||||||
|
|
|
@ -442,6 +442,8 @@ typedef GDExtensionBool (*GDExtensionCallableCustomLessThan)(void *callable_user
|
||||||
|
|
||||||
typedef void (*GDExtensionCallableCustomToString)(void *callable_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
|
typedef void (*GDExtensionCallableCustomToString)(void *callable_userdata, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
|
||||||
|
|
||||||
|
typedef GDExtensionInt (*GDExtensionCallableCustomGetArgumentCount)(void *callable_userdata, GDExtensionBool *r_is_valid);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Only `call_func` and `token` are strictly required, however, `object_id` should be passed if its not a static method.
|
/* Only `call_func` and `token` are strictly required, however, `object_id` should be passed if its not a static method.
|
||||||
*
|
*
|
||||||
|
@ -471,7 +473,40 @@ typedef struct {
|
||||||
GDExtensionCallableCustomLessThan less_than_func;
|
GDExtensionCallableCustomLessThan less_than_func;
|
||||||
|
|
||||||
GDExtensionCallableCustomToString to_string_func;
|
GDExtensionCallableCustomToString to_string_func;
|
||||||
} GDExtensionCallableCustomInfo;
|
} GDExtensionCallableCustomInfo; // Deprecated. Use GDExtensionCallableCustomInfo2 instead.
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* Only `call_func` and `token` are strictly required, however, `object_id` should be passed if its not a static method.
|
||||||
|
*
|
||||||
|
* `token` should point to an address that uniquely identifies the GDExtension (for example, the
|
||||||
|
* `GDExtensionClassLibraryPtr` passed to the entry symbol function.
|
||||||
|
*
|
||||||
|
* `hash_func`, `equal_func`, and `less_than_func` are optional. If not provided both `call_func` and
|
||||||
|
* `callable_userdata` together are used as the identity of the callable for hashing and comparison purposes.
|
||||||
|
*
|
||||||
|
* The hash returned by `hash_func` is cached, `hash_func` will not be called more than once per callable.
|
||||||
|
*
|
||||||
|
* `is_valid_func` is necessary if the validity of the callable can change before destruction.
|
||||||
|
*
|
||||||
|
* `free_func` is necessary if `callable_userdata` needs to be cleaned up when the callable is freed.
|
||||||
|
*/
|
||||||
|
void *callable_userdata;
|
||||||
|
void *token;
|
||||||
|
|
||||||
|
GDObjectInstanceID object_id;
|
||||||
|
|
||||||
|
GDExtensionCallableCustomCall call_func;
|
||||||
|
GDExtensionCallableCustomIsValid is_valid_func;
|
||||||
|
GDExtensionCallableCustomFree free_func;
|
||||||
|
|
||||||
|
GDExtensionCallableCustomHash hash_func;
|
||||||
|
GDExtensionCallableCustomEqual equal_func;
|
||||||
|
GDExtensionCallableCustomLessThan less_than_func;
|
||||||
|
|
||||||
|
GDExtensionCallableCustomToString to_string_func;
|
||||||
|
|
||||||
|
GDExtensionCallableCustomGetArgumentCount get_argument_count_func;
|
||||||
|
} GDExtensionCallableCustomInfo2;
|
||||||
|
|
||||||
/* SCRIPT INSTANCE EXTENSION */
|
/* SCRIPT INSTANCE EXTENSION */
|
||||||
|
|
||||||
|
@ -2510,6 +2545,7 @@ typedef GDExtensionScriptInstanceDataPtr (*GDExtensionInterfaceObjectGetScriptIn
|
||||||
/**
|
/**
|
||||||
* @name callable_custom_create
|
* @name callable_custom_create
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
|
* @deprecated in Godot 4.3. Use `callable_custom_create2` instead.
|
||||||
*
|
*
|
||||||
* Creates a custom Callable object from a function pointer.
|
* Creates a custom Callable object from a function pointer.
|
||||||
*
|
*
|
||||||
|
@ -2520,6 +2556,19 @@ typedef GDExtensionScriptInstanceDataPtr (*GDExtensionInterfaceObjectGetScriptIn
|
||||||
*/
|
*/
|
||||||
typedef void (*GDExtensionInterfaceCallableCustomCreate)(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo *p_callable_custom_info);
|
typedef void (*GDExtensionInterfaceCallableCustomCreate)(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo *p_callable_custom_info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name callable_custom_create2
|
||||||
|
* @since 4.3
|
||||||
|
*
|
||||||
|
* Creates a custom Callable object from a function pointer.
|
||||||
|
*
|
||||||
|
* Provided struct can be safely freed once the function returns.
|
||||||
|
*
|
||||||
|
* @param r_callable A pointer that will receive the new Callable.
|
||||||
|
* @param p_callable_custom_info The info required to construct a Callable.
|
||||||
|
*/
|
||||||
|
typedef void (*GDExtensionInterfaceCallableCustomCreate2)(GDExtensionUninitializedTypePtr r_callable, GDExtensionCallableCustomInfo2 *p_callable_custom_info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name callable_custom_get_userdata
|
* @name callable_custom_get_userdata
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
|
|
|
@ -93,6 +93,11 @@ public:
|
||||||
return data.instance->get_instance_id();
|
return data.instance->get_instance_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int get_argument_count(bool &r_is_valid) const {
|
||||||
|
r_is_valid = true;
|
||||||
|
return sizeof...(P);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||||
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
||||||
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
|
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
|
||||||
|
@ -140,6 +145,11 @@ public:
|
||||||
return data.instance->get_instance_id();
|
return data.instance->get_instance_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int get_argument_count(bool &r_is_valid) const {
|
||||||
|
r_is_valid = true;
|
||||||
|
return sizeof...(P);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||||
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
||||||
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
|
@ -187,6 +197,11 @@ public:
|
||||||
return data.instance->get_instance_id();
|
return data.instance->get_instance_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||||
|
r_is_valid = true;
|
||||||
|
return sizeof...(P);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
||||||
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
||||||
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
|
@ -238,6 +253,11 @@ public:
|
||||||
return ObjectID();
|
return ObjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||||
|
r_is_valid = true;
|
||||||
|
return sizeof...(P);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
||||||
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
r_return_value = Variant();
|
r_return_value = Variant();
|
||||||
|
@ -280,6 +300,11 @@ public:
|
||||||
return ObjectID();
|
return ObjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||||
|
r_is_valid = true;
|
||||||
|
return sizeof...(P);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
||||||
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1666,6 +1666,31 @@ bool ClassDB::has_method(const StringName &p_class, const StringName &p_method,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ClassDB::get_method_argument_count(const StringName &p_class, const StringName &p_method, bool *r_is_valid, bool p_no_inheritance) {
|
||||||
|
OBJTYPE_RLOCK;
|
||||||
|
|
||||||
|
ClassInfo *type = classes.getptr(p_class);
|
||||||
|
|
||||||
|
while (type) {
|
||||||
|
MethodBind **method = type->method_map.getptr(p_method);
|
||||||
|
if (method && *method) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return (*method)->get_argument_count();
|
||||||
|
}
|
||||||
|
if (p_no_inheritance) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
type = type->inherits_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method) {
|
void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method) {
|
||||||
_bind_method_custom(p_class, p_method, false);
|
_bind_method_custom(p_class, p_method, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -430,6 +430,7 @@ public:
|
||||||
static void get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
|
static void get_method_list(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
|
||||||
static void get_method_list_with_compatibility(const StringName &p_class, List<Pair<MethodInfo, uint32_t>> *p_methods_with_hash, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
|
static void get_method_list_with_compatibility(const StringName &p_class, List<Pair<MethodInfo, uint32_t>> *p_methods_with_hash, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
|
||||||
static bool get_method_info(const StringName &p_class, const StringName &p_method, MethodInfo *r_info, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
|
static bool get_method_info(const StringName &p_class, const StringName &p_method, MethodInfo *r_info, bool p_no_inheritance = false, bool p_exclude_from_properties = false);
|
||||||
|
static int get_method_argument_count(const StringName &p_class, const StringName &p_method, bool *r_is_valid = nullptr, bool p_no_inheritance = false);
|
||||||
static MethodBind *get_method(const StringName &p_class, const StringName &p_name);
|
static MethodBind *get_method(const StringName &p_class, const StringName &p_name);
|
||||||
static MethodBind *get_method_with_compatibility(const StringName &p_class, const StringName &p_name, uint64_t p_hash, bool *r_method_exists = nullptr, bool *r_is_deprecated = nullptr);
|
static MethodBind *get_method_with_compatibility(const StringName &p_class, const StringName &p_name, uint64_t p_hash, bool *r_method_exists = nullptr, bool *r_is_deprecated = nullptr);
|
||||||
static Vector<uint32_t> get_method_compatibility_hashes(const StringName &p_class, const StringName &p_name);
|
static Vector<uint32_t> get_method_compatibility_hashes(const StringName &p_class, const StringName &p_name);
|
||||||
|
|
|
@ -688,6 +688,59 @@ bool Object::has_method(const StringName &p_method) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Object::_get_method_argument_count_bind(const StringName &p_method) const {
|
||||||
|
return get_method_argument_count(p_method);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Object::get_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
|
||||||
|
if (p_method == CoreStringNames::get_singleton()->_free) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script_instance) {
|
||||||
|
bool valid = false;
|
||||||
|
int ret = script_instance->get_method_argument_count(p_method, &valid);
|
||||||
|
if (valid) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
int ret = ClassDB::get_method_argument_count(get_class_name(), p_method, &valid);
|
||||||
|
if (valid) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Script *scr = Object::cast_to<Script>(this);
|
||||||
|
while (scr != nullptr) {
|
||||||
|
bool valid = false;
|
||||||
|
int ret = scr->get_script_method_argument_count(p_method, &valid);
|
||||||
|
if (valid) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
scr = scr->get_base_script().ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Variant Object::getvar(const Variant &p_key, bool *r_valid) const {
|
Variant Object::getvar(const Variant &p_key, bool *r_valid) const {
|
||||||
if (r_valid) {
|
if (r_valid) {
|
||||||
*r_valid = false;
|
*r_valid = false;
|
||||||
|
@ -1644,6 +1697,8 @@ void Object::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method);
|
ClassDB::bind_method(D_METHOD("has_method", "method"), &Object::has_method);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("get_method_argument_count", "method"), &Object::_get_method_argument_count_bind);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("has_signal", "signal"), &Object::has_signal);
|
ClassDB::bind_method(D_METHOD("has_signal", "signal"), &Object::has_signal);
|
||||||
ClassDB::bind_method(D_METHOD("get_signal_list"), &Object::_get_signal_list);
|
ClassDB::bind_method(D_METHOD("get_signal_list"), &Object::_get_signal_list);
|
||||||
ClassDB::bind_method(D_METHOD("get_signal_connection_list", "signal"), &Object::_get_signal_connection_list);
|
ClassDB::bind_method(D_METHOD("get_signal_connection_list", "signal"), &Object::_get_signal_connection_list);
|
||||||
|
|
|
@ -654,6 +654,7 @@ private:
|
||||||
Variant _get_bind(const StringName &p_name) const;
|
Variant _get_bind(const StringName &p_name) const;
|
||||||
void _set_indexed_bind(const NodePath &p_name, const Variant &p_value);
|
void _set_indexed_bind(const NodePath &p_name, const Variant &p_value);
|
||||||
Variant _get_indexed_bind(const NodePath &p_name) const;
|
Variant _get_indexed_bind(const NodePath &p_name) const;
|
||||||
|
int _get_method_argument_count_bind(const StringName &p_name) const;
|
||||||
|
|
||||||
_FORCE_INLINE_ void _construct_object(bool p_reference);
|
_FORCE_INLINE_ void _construct_object(bool p_reference);
|
||||||
|
|
||||||
|
@ -865,6 +866,7 @@ public:
|
||||||
Variant property_get_revert(const StringName &p_name) const;
|
Variant property_get_revert(const StringName &p_name) const;
|
||||||
|
|
||||||
bool has_method(const StringName &p_method) const;
|
bool has_method(const StringName &p_method) const;
|
||||||
|
int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const;
|
||||||
void get_method_list(List<MethodInfo> *p_list) const;
|
void get_method_list(List<MethodInfo> *p_list) const;
|
||||||
Variant callv(const StringName &p_method, const Array &p_args);
|
Variant callv(const StringName &p_method, const Array &p_args);
|
||||||
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||||
|
|
|
@ -32,6 +32,28 @@
|
||||||
|
|
||||||
#include "core/object/script_language.h"
|
#include "core/object/script_language.h"
|
||||||
|
|
||||||
|
int ScriptInstance::get_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
|
||||||
|
// Default implementation simply traverses hierarchy.
|
||||||
|
Ref<Script> script = get_script();
|
||||||
|
while (script.is_valid()) {
|
||||||
|
bool valid = false;
|
||||||
|
int ret = script->get_script_method_argument_count(p_method, &valid);
|
||||||
|
if (valid) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
script = script->get_base_script();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Variant ScriptInstance::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
Variant ScriptInstance::call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
||||||
return callp(p_method, p_args, p_argcount, r_error);
|
return callp(p_method, p_args, p_argcount, r_error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ public:
|
||||||
virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
|
virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
|
||||||
virtual bool has_method(const StringName &p_method) const = 0;
|
virtual bool has_method(const StringName &p_method) const = 0;
|
||||||
|
|
||||||
|
virtual int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const;
|
||||||
|
|
||||||
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0;
|
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0;
|
||||||
|
|
||||||
template <typename... VarArgs>
|
template <typename... VarArgs>
|
||||||
|
|
|
@ -102,6 +102,22 @@ Dictionary Script::_get_script_constant_map() {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Script::get_script_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
|
||||||
|
MethodInfo mi = get_method_info(p_method);
|
||||||
|
|
||||||
|
if (mi == MethodInfo()) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return mi.arguments.size();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
PropertyInfo Script::get_class_category() const {
|
PropertyInfo Script::get_class_category() const {
|
||||||
|
|
|
@ -151,6 +151,8 @@ public:
|
||||||
virtual bool has_method(const StringName &p_method) const = 0;
|
virtual bool has_method(const StringName &p_method) const = 0;
|
||||||
virtual bool has_static_method(const StringName &p_method) const { return false; }
|
virtual bool has_static_method(const StringName &p_method) const { return false; }
|
||||||
|
|
||||||
|
virtual int get_script_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const;
|
||||||
|
|
||||||
virtual MethodInfo get_method_info(const StringName &p_method) const = 0;
|
virtual MethodInfo get_method_info(const StringName &p_method) const = 0;
|
||||||
|
|
||||||
virtual bool is_tool() const = 0;
|
virtual bool is_tool() const = 0;
|
||||||
|
@ -442,6 +444,13 @@ public:
|
||||||
virtual void get_method_list(List<MethodInfo> *p_list) const override;
|
virtual void get_method_list(List<MethodInfo> *p_list) const override;
|
||||||
virtual bool has_method(const StringName &p_method) const override;
|
virtual bool has_method(const StringName &p_method) const override;
|
||||||
|
|
||||||
|
virtual int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
|
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
|
||||||
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
|
||||||
return Variant();
|
return Variant();
|
||||||
|
|
|
@ -56,6 +56,9 @@ void ScriptExtension::_bind_methods() {
|
||||||
|
|
||||||
GDVIRTUAL_BIND(_has_method, "method");
|
GDVIRTUAL_BIND(_has_method, "method");
|
||||||
GDVIRTUAL_BIND(_has_static_method, "method");
|
GDVIRTUAL_BIND(_has_static_method, "method");
|
||||||
|
|
||||||
|
GDVIRTUAL_BIND(_get_script_method_argument_count, "method");
|
||||||
|
|
||||||
GDVIRTUAL_BIND(_get_method_info, "method");
|
GDVIRTUAL_BIND(_get_method_info, "method");
|
||||||
|
|
||||||
GDVIRTUAL_BIND(_is_tool);
|
GDVIRTUAL_BIND(_is_tool);
|
||||||
|
|
|
@ -101,6 +101,19 @@ public:
|
||||||
EXBIND1RC(bool, has_method, const StringName &)
|
EXBIND1RC(bool, has_method, const StringName &)
|
||||||
EXBIND1RC(bool, has_static_method, const StringName &)
|
EXBIND1RC(bool, has_static_method, const StringName &)
|
||||||
|
|
||||||
|
GDVIRTUAL1RC(Variant, _get_script_method_argument_count, const StringName &)
|
||||||
|
virtual int get_script_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override {
|
||||||
|
Variant ret;
|
||||||
|
if (GDVIRTUAL_CALL(_get_script_method_argument_count, p_method, ret) && ret.get_type() == Variant::INT) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return ret.operator int();
|
||||||
|
}
|
||||||
|
// Fallback to default.
|
||||||
|
return Script::get_script_method_argument_count(p_method, r_is_valid);
|
||||||
|
}
|
||||||
|
|
||||||
GDVIRTUAL1RC(Dictionary, _get_method_info, const StringName &)
|
GDVIRTUAL1RC(Dictionary, _get_method_info, const StringName &)
|
||||||
virtual MethodInfo get_method_info(const StringName &p_method) const override {
|
virtual MethodInfo get_method_info(const StringName &p_method) const override {
|
||||||
Dictionary mi;
|
Dictionary mi;
|
||||||
|
@ -807,6 +820,11 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override {
|
||||||
|
// Fallback to default.
|
||||||
|
return ScriptInstance::get_method_argument_count(p_method, r_is_valid);
|
||||||
|
}
|
||||||
|
|
||||||
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
|
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
|
||||||
Variant ret;
|
Variant ret;
|
||||||
if (native_info->call_func) {
|
if (native_info->call_func) {
|
||||||
|
|
|
@ -184,6 +184,20 @@ StringName Callable::get_method() const {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Callable::get_argument_count(bool *r_is_valid) const {
|
||||||
|
if (is_custom()) {
|
||||||
|
bool valid = false;
|
||||||
|
return custom->get_argument_count(r_is_valid ? *r_is_valid : valid);
|
||||||
|
} else if (!is_null()) {
|
||||||
|
return get_object()->get_method_argument_count(method, r_is_valid);
|
||||||
|
} else {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int Callable::get_bound_arguments_count() const {
|
int Callable::get_bound_arguments_count() const {
|
||||||
if (!is_null() && is_custom()) {
|
if (!is_null() && is_custom()) {
|
||||||
return custom->get_bound_arguments_count();
|
return custom->get_bound_arguments_count();
|
||||||
|
@ -438,6 +452,11 @@ const Callable *CallableCustom::get_base_comparator() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CallableCustom::get_argument_count(bool &r_is_valid) const {
|
||||||
|
r_is_valid = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int CallableCustom::get_bound_arguments_count() const {
|
int CallableCustom::get_bound_arguments_count() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ public:
|
||||||
ObjectID get_object_id() const;
|
ObjectID get_object_id() const;
|
||||||
StringName get_method() const;
|
StringName get_method() const;
|
||||||
CallableCustom *get_custom() const;
|
CallableCustom *get_custom() const;
|
||||||
|
int get_argument_count(bool *r_is_valid = nullptr) const;
|
||||||
int get_bound_arguments_count() const;
|
int get_bound_arguments_count() const;
|
||||||
void get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const; // Internal engine use, the exposed one is below.
|
void get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const; // Internal engine use, the exposed one is below.
|
||||||
Array get_bound_arguments() const;
|
Array get_bound_arguments() const;
|
||||||
|
@ -155,6 +156,7 @@ public:
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
|
||||||
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
|
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
|
||||||
virtual const Callable *get_base_comparator() const;
|
virtual const Callable *get_base_comparator() const;
|
||||||
|
virtual int get_argument_count(bool &r_is_valid) const;
|
||||||
virtual int get_bound_arguments_count() const;
|
virtual int get_bound_arguments_count() const;
|
||||||
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const;
|
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const;
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,14 @@ const Callable *CallableCustomBind::get_base_comparator() const {
|
||||||
return callable.get_base_comparator();
|
return callable.get_base_comparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CallableCustomBind::get_argument_count(bool &r_is_valid) const {
|
||||||
|
int ret = callable.get_argument_count(&r_is_valid);
|
||||||
|
if (r_is_valid) {
|
||||||
|
return ret - binds.size();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int CallableCustomBind::get_bound_arguments_count() const {
|
int CallableCustomBind::get_bound_arguments_count() const {
|
||||||
return callable.get_bound_arguments_count() + binds.size();
|
return callable.get_bound_arguments_count() + binds.size();
|
||||||
}
|
}
|
||||||
|
@ -225,6 +233,14 @@ const Callable *CallableCustomUnbind::get_base_comparator() const {
|
||||||
return callable.get_base_comparator();
|
return callable.get_base_comparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CallableCustomUnbind::get_argument_count(bool &r_is_valid) const {
|
||||||
|
int ret = callable.get_argument_count(&r_is_valid);
|
||||||
|
if (r_is_valid) {
|
||||||
|
return ret + argcount;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int CallableCustomUnbind::get_bound_arguments_count() const {
|
int CallableCustomUnbind::get_bound_arguments_count() const {
|
||||||
return callable.get_bound_arguments_count() - argcount;
|
return callable.get_bound_arguments_count() - argcount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||||
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
|
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
|
||||||
virtual const Callable *get_base_comparator() const override;
|
virtual const Callable *get_base_comparator() const override;
|
||||||
|
virtual int get_argument_count(bool &r_is_valid) const override;
|
||||||
virtual int get_bound_arguments_count() const override;
|
virtual int get_bound_arguments_count() const override;
|
||||||
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
|
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
|
||||||
Callable get_callable() { return callable; }
|
Callable get_callable() { return callable; }
|
||||||
|
@ -81,6 +82,7 @@ public:
|
||||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||||
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
|
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
|
||||||
virtual const Callable *get_base_comparator() const override;
|
virtual const Callable *get_base_comparator() const override;
|
||||||
|
virtual int get_argument_count(bool &r_is_valid) const override;
|
||||||
virtual int get_bound_arguments_count() const override;
|
virtual int get_bound_arguments_count() const override;
|
||||||
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
|
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
|
||||||
|
|
||||||
|
|
|
@ -1053,6 +1053,10 @@ struct _VariantCall {
|
||||||
r_ret = callable->bindp(p_args, p_argcount);
|
r_ret = callable->bindp(p_args, p_argcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int func_Callable_get_argument_count(Callable *p_callable) {
|
||||||
|
return p_callable->get_argument_count();
|
||||||
|
}
|
||||||
|
|
||||||
static void func_Signal_emit(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
|
static void func_Signal_emit(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
|
||||||
Signal *signal = VariantGetInternalPtr<Signal>::get_ptr(v);
|
Signal *signal = VariantGetInternalPtr<Signal>::get_ptr(v);
|
||||||
signal->emit(p_args, p_argcount);
|
signal->emit(p_args, p_argcount);
|
||||||
|
@ -2048,6 +2052,7 @@ static void _register_variant_builtin_methods() {
|
||||||
bind_method(Callable, get_object, sarray(), varray());
|
bind_method(Callable, get_object, sarray(), varray());
|
||||||
bind_method(Callable, get_object_id, sarray(), varray());
|
bind_method(Callable, get_object_id, sarray(), varray());
|
||||||
bind_method(Callable, get_method, sarray(), varray());
|
bind_method(Callable, get_method, sarray(), varray());
|
||||||
|
bind_function(Callable, get_argument_count, _VariantCall::func_Callable_get_argument_count, sarray(), varray());
|
||||||
bind_method(Callable, get_bound_arguments_count, sarray(), varray());
|
bind_method(Callable, get_bound_arguments_count, sarray(), varray());
|
||||||
bind_method(Callable, get_bound_arguments, sarray(), varray());
|
bind_method(Callable, get_bound_arguments, sarray(), varray());
|
||||||
bind_method(Callable, hash, sarray(), varray());
|
bind_method(Callable, hash, sarray(), varray());
|
||||||
|
|
|
@ -68,6 +68,15 @@ ObjectID VariantCallable::get_object() const {
|
||||||
return ObjectID();
|
return ObjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VariantCallable::get_argument_count(bool &r_is_valid) const {
|
||||||
|
if (!Variant::has_builtin_method(variant.get_type(), method)) {
|
||||||
|
r_is_valid = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
r_is_valid = true;
|
||||||
|
return Variant::get_builtin_method_argument_count(variant.get_type(), method);
|
||||||
|
}
|
||||||
|
|
||||||
void VariantCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
void VariantCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||||
Variant v = variant;
|
Variant v = variant;
|
||||||
v.callp(method, p_arguments, p_argcount, r_return_value, r_call_error);
|
v.callp(method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
bool is_valid() const override;
|
bool is_valid() const override;
|
||||||
StringName get_method() const override;
|
StringName get_method() const override;
|
||||||
ObjectID get_object() const override;
|
ObjectID get_object() const override;
|
||||||
|
int get_argument_count(bool &r_is_valid) const override;
|
||||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||||
|
|
||||||
VariantCallable(const Variant &p_variant, const StringName &p_method);
|
VariantCallable(const Variant &p_variant, const StringName &p_method);
|
||||||
|
|
|
@ -147,6 +147,12 @@
|
||||||
[b]Note:[/b] This method is always necessary for the [Dictionary] type, as property syntax is used to access its entries. You may also use this method when [param variant]'s type is not known in advance (for polymorphism).
|
[b]Note:[/b] This method is always necessary for the [Dictionary] type, as property syntax is used to access its entries. You may also use this method when [param variant]'s type is not known in advance (for polymorphism).
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="get_argument_count" qualifiers="const">
|
||||||
|
<return type="int" />
|
||||||
|
<description>
|
||||||
|
Returns the total number of arguments this [Callable] should take, including optional arguments. This means that any arguments bound with [method bind] are [i]subtracted[/i] from the result, and any arguments unbound with [method unbind] are [i]added[/i] to the result.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="get_bound_arguments" qualifiers="const">
|
<method name="get_bound_arguments" qualifiers="const">
|
||||||
<return type="Array" />
|
<return type="Array" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -65,6 +65,15 @@
|
||||||
Returns an array with the names all the integer constants of [param class] or its ancestry.
|
Returns an array with the names all the integer constants of [param class] or its ancestry.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="class_get_method_argument_count" qualifiers="const">
|
||||||
|
<return type="int" />
|
||||||
|
<param index="0" name="class" type="StringName" />
|
||||||
|
<param index="1" name="method" type="StringName" />
|
||||||
|
<param index="2" name="no_inheritance" type="bool" default="false" />
|
||||||
|
<description>
|
||||||
|
Returns the number of arguments of the method [param method] of [param class] or its ancestry if [param no_inheritance] is [code]false[/code].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="class_get_method_list" qualifiers="const">
|
<method name="class_get_method_list" qualifiers="const">
|
||||||
<return type="Dictionary[]" />
|
<return type="Dictionary[]" />
|
||||||
<param index="0" name="class" type="StringName" />
|
<param index="0" name="class" type="StringName" />
|
||||||
|
|
|
@ -711,6 +711,14 @@
|
||||||
Returns the object's metadata entry names as a [PackedStringArray].
|
Returns the object's metadata entry names as a [PackedStringArray].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="get_method_argument_count" qualifiers="const">
|
||||||
|
<return type="int" />
|
||||||
|
<param index="0" name="method" type="StringName" />
|
||||||
|
<description>
|
||||||
|
Returns the number of arguments of the given [param method] by name.
|
||||||
|
[b]Note:[/b] In C#, [param method] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]MethodName[/code] class to avoid allocating a new [StringName] on each call.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="get_method_list" qualifiers="const">
|
<method name="get_method_list" qualifiers="const">
|
||||||
<return type="Dictionary[]" />
|
<return type="Dictionary[]" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -80,6 +80,12 @@
|
||||||
<description>
|
<description>
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="_get_script_method_argument_count" qualifiers="virtual const">
|
||||||
|
<return type="Variant" />
|
||||||
|
<param index="0" name="method" type="StringName" />
|
||||||
|
<description>
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="_get_script_method_list" qualifiers="virtual const">
|
<method name="_get_script_method_list" qualifiers="virtual const">
|
||||||
<return type="Dictionary[]" />
|
<return type="Dictionary[]" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -354,6 +354,21 @@ bool GDScript::has_static_method(const StringName &p_method) const {
|
||||||
return member_functions.has(p_method) && member_functions[p_method]->is_static();
|
return member_functions.has(p_method) && member_functions[p_method]->is_static();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GDScript::get_script_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
|
||||||
|
HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method);
|
||||||
|
if (!E) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return E->value->get_argument_count();
|
||||||
|
}
|
||||||
|
|
||||||
MethodInfo GDScript::get_method_info(const StringName &p_method) const {
|
MethodInfo GDScript::get_method_info(const StringName &p_method) const {
|
||||||
HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method);
|
HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method);
|
||||||
if (!E) {
|
if (!E) {
|
||||||
|
@ -1916,6 +1931,25 @@ bool GDScriptInstance::has_method(const StringName &p_method) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GDScriptInstance::get_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
|
||||||
|
const GDScript *sptr = script.ptr();
|
||||||
|
while (sptr) {
|
||||||
|
HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_method);
|
||||||
|
if (E) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return E->value->get_argument_count();
|
||||||
|
}
|
||||||
|
sptr = sptr->_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
||||||
GDScript *sptr = script.ptr();
|
GDScript *sptr = script.ptr();
|
||||||
if (unlikely(p_method == SNAME("_ready"))) {
|
if (unlikely(p_method == SNAME("_ready"))) {
|
||||||
|
|
|
@ -312,6 +312,9 @@ public:
|
||||||
virtual void get_script_method_list(List<MethodInfo> *p_list) const override;
|
virtual void get_script_method_list(List<MethodInfo> *p_list) const override;
|
||||||
virtual bool has_method(const StringName &p_method) const override;
|
virtual bool has_method(const StringName &p_method) const override;
|
||||||
virtual bool has_static_method(const StringName &p_method) const override;
|
virtual bool has_static_method(const StringName &p_method) const override;
|
||||||
|
|
||||||
|
virtual int get_script_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override;
|
||||||
|
|
||||||
virtual MethodInfo get_method_info(const StringName &p_method) const override;
|
virtual MethodInfo get_method_info(const StringName &p_method) const override;
|
||||||
|
|
||||||
virtual void get_script_property_list(List<PropertyInfo> *p_list) const override;
|
virtual void get_script_property_list(List<PropertyInfo> *p_list) const override;
|
||||||
|
@ -376,6 +379,9 @@ public:
|
||||||
|
|
||||||
virtual void get_method_list(List<MethodInfo> *p_list) const;
|
virtual void get_method_list(List<MethodInfo> *p_list) const;
|
||||||
virtual bool has_method(const StringName &p_method) const;
|
virtual bool has_method(const StringName &p_method) const;
|
||||||
|
|
||||||
|
virtual int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const;
|
||||||
|
|
||||||
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||||
|
|
||||||
Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }
|
Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }
|
||||||
|
|
|
@ -511,6 +511,7 @@ public:
|
||||||
_FORCE_INLINE_ GDScript *get_script() const { return _script; }
|
_FORCE_INLINE_ GDScript *get_script() const { return _script; }
|
||||||
_FORCE_INLINE_ bool is_static() const { return _static; }
|
_FORCE_INLINE_ bool is_static() const { return _static; }
|
||||||
_FORCE_INLINE_ MethodInfo get_method_info() const { return method_info; }
|
_FORCE_INLINE_ MethodInfo get_method_info() const { return method_info; }
|
||||||
|
_FORCE_INLINE_ int get_argument_count() const { return _argument_count; }
|
||||||
_FORCE_INLINE_ Variant get_rpc_config() const { return rpc_config; }
|
_FORCE_INLINE_ Variant get_rpc_config() const { return rpc_config; }
|
||||||
_FORCE_INLINE_ int get_max_stack_size() const { return _stack_size; }
|
_FORCE_INLINE_ int get_max_stack_size() const { return _stack_size; }
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,15 @@ StringName GDScriptLambdaCallable::get_method() const {
|
||||||
return function->get_name();
|
return function->get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GDScriptLambdaCallable::get_argument_count(bool &r_is_valid) const {
|
||||||
|
if (function == nullptr) {
|
||||||
|
r_is_valid = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
r_is_valid = true;
|
||||||
|
return function->get_argument_count();
|
||||||
|
}
|
||||||
|
|
||||||
void GDScriptLambdaCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
void GDScriptLambdaCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||||
int captures_amount = captures.size();
|
int captures_amount = captures.size();
|
||||||
|
|
||||||
|
@ -189,6 +198,15 @@ ObjectID GDScriptLambdaSelfCallable::get_object() const {
|
||||||
return object->get_instance_id();
|
return object->get_instance_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GDScriptLambdaSelfCallable::get_argument_count(bool &r_is_valid) const {
|
||||||
|
if (function == nullptr) {
|
||||||
|
r_is_valid = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
r_is_valid = true;
|
||||||
|
return function->get_argument_count();
|
||||||
|
}
|
||||||
|
|
||||||
void GDScriptLambdaSelfCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
void GDScriptLambdaSelfCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (object->get_script_instance() == nullptr || object->get_script_instance()->get_language() != GDScriptLanguage::get_singleton()) {
|
if (object->get_script_instance() == nullptr || object->get_script_instance()->get_language() != GDScriptLanguage::get_singleton()) {
|
||||||
|
|
|
@ -59,6 +59,7 @@ public:
|
||||||
CompareLessFunc get_compare_less_func() const override;
|
CompareLessFunc get_compare_less_func() const override;
|
||||||
ObjectID get_object() const override;
|
ObjectID get_object() const override;
|
||||||
StringName get_method() const override;
|
StringName get_method() const override;
|
||||||
|
int get_argument_count(bool &r_is_valid) const override;
|
||||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||||
|
|
||||||
GDScriptLambdaCallable(GDScriptLambdaCallable &) = delete;
|
GDScriptLambdaCallable(GDScriptLambdaCallable &) = delete;
|
||||||
|
@ -86,6 +87,7 @@ public:
|
||||||
CompareEqualFunc get_compare_equal_func() const override;
|
CompareEqualFunc get_compare_equal_func() const override;
|
||||||
CompareLessFunc get_compare_less_func() const override;
|
CompareLessFunc get_compare_less_func() const override;
|
||||||
ObjectID get_object() const override;
|
ObjectID get_object() const override;
|
||||||
|
int get_argument_count(bool &r_is_valid) const override;
|
||||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||||
|
|
||||||
GDScriptLambdaSelfCallable(GDScriptLambdaSelfCallable &) = delete;
|
GDScriptLambdaSelfCallable(GDScriptLambdaSelfCallable &) = delete;
|
||||||
|
|
|
@ -68,6 +68,10 @@ StringName GDScriptRPCCallable::get_method() const {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GDScriptRPCCallable::get_argument_count(bool &r_is_valid) const {
|
||||||
|
return object->get_method_argument_count(method, &r_is_valid);
|
||||||
|
}
|
||||||
|
|
||||||
void GDScriptRPCCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
void GDScriptRPCCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||||
r_return_value = object->callp(method, p_arguments, p_argcount, r_call_error);
|
r_return_value = object->callp(method, p_arguments, p_argcount, r_call_error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
CompareLessFunc get_compare_less_func() const override;
|
CompareLessFunc get_compare_less_func() const override;
|
||||||
ObjectID get_object() const override;
|
ObjectID get_object() const override;
|
||||||
StringName get_method() const override;
|
StringName get_method() const override;
|
||||||
|
int get_argument_count(bool &r_is_valid) const override;
|
||||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||||
Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
|
Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const override;
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,21 @@ ObjectID GDScriptUtilityCallable::get_object() const {
|
||||||
return ObjectID();
|
return ObjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GDScriptUtilityCallable::get_argument_count(bool &r_is_valid) const {
|
||||||
|
switch (type) {
|
||||||
|
case TYPE_INVALID:
|
||||||
|
r_is_valid = false;
|
||||||
|
return 0;
|
||||||
|
case TYPE_GLOBAL:
|
||||||
|
r_is_valid = true;
|
||||||
|
return Variant::get_utility_function_argument_count(function_name);
|
||||||
|
case TYPE_GDSCRIPT:
|
||||||
|
r_is_valid = true;
|
||||||
|
return GDScriptUtilityFunctions::get_function_argument_count(function_name);
|
||||||
|
}
|
||||||
|
ERR_FAIL_V_MSG(0, "Invalid type.");
|
||||||
|
}
|
||||||
|
|
||||||
void GDScriptUtilityCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
void GDScriptUtilityCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_INVALID:
|
case TYPE_INVALID:
|
||||||
|
|
|
@ -57,6 +57,7 @@ public:
|
||||||
bool is_valid() const override;
|
bool is_valid() const override;
|
||||||
StringName get_method() const override;
|
StringName get_method() const override;
|
||||||
ObjectID get_object() const override;
|
ObjectID get_object() const override;
|
||||||
|
int get_argument_count(bool &r_is_valid) const override;
|
||||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||||
|
|
||||||
GDScriptUtilityCallable(const StringName &p_function_name);
|
GDScriptUtilityCallable(const StringName &p_function_name);
|
||||||
|
|
|
@ -759,7 +759,7 @@ Variant::Type GDScriptUtilityFunctions::get_function_argument_type(const StringN
|
||||||
return info->info.arguments[p_arg].type;
|
return info->info.arguments[p_arg].type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GDScriptUtilityFunctions::get_function_argument_count(const StringName &p_function, int p_arg) {
|
int GDScriptUtilityFunctions::get_function_argument_count(const StringName &p_function) {
|
||||||
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
GDScriptUtilityFunctionInfo *info = utility_function_table.lookup_ptr(p_function);
|
||||||
ERR_FAIL_NULL_V(info, 0);
|
ERR_FAIL_NULL_V(info, 0);
|
||||||
return info->info.arguments.size();
|
return info->info.arguments.size();
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
static Variant::Type get_function_return_type(const StringName &p_function);
|
static Variant::Type get_function_return_type(const StringName &p_function);
|
||||||
static StringName get_function_return_class(const StringName &p_function);
|
static StringName get_function_return_class(const StringName &p_function);
|
||||||
static Variant::Type get_function_argument_type(const StringName &p_function, int p_arg);
|
static Variant::Type get_function_argument_type(const StringName &p_function, int p_arg);
|
||||||
static int get_function_argument_count(const StringName &p_function, int p_arg);
|
static int get_function_argument_count(const StringName &p_function);
|
||||||
static bool is_function_vararg(const StringName &p_function);
|
static bool is_function_vararg(const StringName &p_function);
|
||||||
static bool is_function_constant(const StringName &p_function);
|
static bool is_function_constant(const StringName &p_function);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
func my_func_1(_foo, _bar):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func my_func_2(_foo, _bar, _baz):
|
||||||
|
pass
|
||||||
|
|
||||||
|
static func my_static_func_1(_foo, _bar):
|
||||||
|
pass
|
||||||
|
|
||||||
|
static func my_static_func_2(_foo, _bar, _baz):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@rpc
|
||||||
|
func my_rpc_func_1(_foo, _bar):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@rpc
|
||||||
|
func my_rpc_func_2(_foo, _bar, _baz):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func test():
|
||||||
|
# Test built-in methods.
|
||||||
|
var builtin_callable_1 : Callable = add_to_group
|
||||||
|
print(builtin_callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var builtin_callable_2 : Callable = find_child
|
||||||
|
print(builtin_callable_2.get_argument_count()) # Should print 3.
|
||||||
|
|
||||||
|
# Test built-in vararg methods.
|
||||||
|
var builtin_vararg_callable_1 : Callable = call_thread_safe
|
||||||
|
print(builtin_vararg_callable_1.get_argument_count()) # Should print 1.
|
||||||
|
var builtin_vararg_callable_2 : Callable = rpc_id
|
||||||
|
print(builtin_vararg_callable_2.get_argument_count()) # Should print 2.
|
||||||
|
|
||||||
|
# Test plain methods.
|
||||||
|
var callable_1 : Callable = my_func_1
|
||||||
|
print(callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var callable_2 : Callable = my_func_2
|
||||||
|
print(callable_2.get_argument_count()) # Should print 3.
|
||||||
|
|
||||||
|
# Test static methods.
|
||||||
|
var static_callable_1 : Callable = my_static_func_1
|
||||||
|
print(static_callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var static_callable_2 : Callable = my_static_func_2
|
||||||
|
print(static_callable_2.get_argument_count()) # Should print 3.
|
||||||
|
|
||||||
|
# Test rpc methods.
|
||||||
|
var rpc_callable_1 : Callable = my_rpc_func_1
|
||||||
|
print(rpc_callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var rpc_callable_2 : Callable = my_rpc_func_2
|
||||||
|
print(rpc_callable_2.get_argument_count()) # Should print 3.
|
||||||
|
|
||||||
|
# Test lambdas.
|
||||||
|
var lambda_callable_1 : Callable = func(_foo, _bar): pass
|
||||||
|
print(lambda_callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var lambda_callable_2 : Callable = func(_foo, _bar, _baz): pass
|
||||||
|
print(lambda_callable_2.get_argument_count()) # Should print 3.
|
||||||
|
|
||||||
|
# Test lambas with self.
|
||||||
|
var lambda_self_callable_1 : Callable = func(_foo, _bar): return self
|
||||||
|
print(lambda_self_callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var lambda_self_callable_2 : Callable = func(_foo, _bar, _baz): return self
|
||||||
|
print(lambda_self_callable_2.get_argument_count()) # Should print 3.
|
||||||
|
|
||||||
|
# Test bind.
|
||||||
|
var bind_callable_1 : Callable = my_func_2.bind(1)
|
||||||
|
print(bind_callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var bind_callable_2 : Callable = my_func_2.bind(1, 2)
|
||||||
|
print(bind_callable_2.get_argument_count()) # Should print 1.
|
||||||
|
|
||||||
|
# Test unbind.
|
||||||
|
var unbind_callable_1 : Callable = my_func_2.unbind(1)
|
||||||
|
print(unbind_callable_1.get_argument_count()) # Should print 4.
|
||||||
|
var unbind_callable_2 : Callable = my_func_2.unbind(2)
|
||||||
|
print(unbind_callable_2.get_argument_count()) # Should print 5.
|
||||||
|
|
||||||
|
# Test variant callables.
|
||||||
|
var string_tmp := String()
|
||||||
|
var variant_callable_1 : Callable = string_tmp.replace
|
||||||
|
print(variant_callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var variant_callable_2 : Callable = string_tmp.rsplit
|
||||||
|
print(variant_callable_2.get_argument_count()) # Should print 3.
|
||||||
|
|
||||||
|
# Test variant vararg callables.
|
||||||
|
var callable_tmp := Callable()
|
||||||
|
var variant_vararg_callable_1 : Callable = callable_tmp.call
|
||||||
|
print(variant_vararg_callable_1.get_argument_count()) # Should print 0.
|
||||||
|
var variant_vararg_callable_2 : Callable = callable_tmp.rpc_id
|
||||||
|
print(variant_vararg_callable_2.get_argument_count()) # Should print 1.
|
||||||
|
|
||||||
|
# Test global methods.
|
||||||
|
var global_callable_1 = is_equal_approx
|
||||||
|
print(global_callable_1.get_argument_count()) # Should print 2.
|
||||||
|
var global_callable_2 = inverse_lerp
|
||||||
|
print(global_callable_2.get_argument_count()) # Should print 3.
|
||||||
|
|
||||||
|
# Test GDScript methods.
|
||||||
|
var gdscript_callable_1 = char
|
||||||
|
print(gdscript_callable_1.get_argument_count()) # Should print 1.
|
||||||
|
var gdscript_callable_2 = is_instance_of
|
||||||
|
print(gdscript_callable_2.get_argument_count()) # Should print 2.
|
|
@ -0,0 +1,27 @@
|
||||||
|
GDTEST_OK
|
||||||
|
2
|
||||||
|
3
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
4
|
||||||
|
5
|
||||||
|
2
|
||||||
|
3
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
1
|
||||||
|
2
|
|
@ -1735,6 +1735,34 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
|
||||||
gchandle.get_intptr(), &p_method);
|
gchandle.get_intptr(), &p_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CSharpInstance::get_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
|
||||||
|
if (!script->is_valid() || !script->valid) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSharpScript *top = script.ptr();
|
||||||
|
while (top != nullptr) {
|
||||||
|
for (const CSharpScript::CSharpMethodInfo &E : top->methods) {
|
||||||
|
if (E.name == p_method) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return E.method_info.arguments.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top->base_script.ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Variant CSharpInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
Variant CSharpInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
||||||
ERR_FAIL_COND_V(!script.is_valid(), Variant());
|
ERR_FAIL_COND_V(!script.is_valid(), Variant());
|
||||||
|
|
||||||
|
@ -2579,6 +2607,29 @@ bool CSharpScript::has_method(const StringName &p_method) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CSharpScript::get_script_method_argument_count(const StringName &p_method, bool *r_is_valid) const {
|
||||||
|
if (!valid) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const CSharpMethodInfo &E : methods) {
|
||||||
|
if (E.name == p_method) {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = true;
|
||||||
|
}
|
||||||
|
return E.method_info.arguments.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
|
MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return MethodInfo();
|
return MethodInfo();
|
||||||
|
|
|
@ -278,6 +278,7 @@ public:
|
||||||
|
|
||||||
void get_script_method_list(List<MethodInfo> *p_list) const override;
|
void get_script_method_list(List<MethodInfo> *p_list) const override;
|
||||||
bool has_method(const StringName &p_method) const override;
|
bool has_method(const StringName &p_method) const override;
|
||||||
|
virtual int get_script_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override;
|
||||||
MethodInfo get_method_info(const StringName &p_method) const override;
|
MethodInfo get_method_info(const StringName &p_method) const override;
|
||||||
Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
||||||
|
|
||||||
|
@ -346,6 +347,7 @@ public:
|
||||||
|
|
||||||
void get_method_list(List<MethodInfo> *p_list) const override;
|
void get_method_list(List<MethodInfo> *p_list) const override;
|
||||||
bool has_method(const StringName &p_method) const override;
|
bool has_method(const StringName &p_method) const override;
|
||||||
|
virtual int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override;
|
||||||
Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
||||||
|
|
||||||
void mono_object_disposed(GCHandleIntPtr p_gchandle_to_free);
|
void mono_object_disposed(GCHandleIntPtr p_gchandle_to_free);
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Godot.Bridge
|
||||||
public delegate* unmanaged<IntPtr, void*, godot_variant**, int, godot_variant*, void> DelegateUtils_InvokeWithVariantArgs;
|
public delegate* unmanaged<IntPtr, void*, godot_variant**, int, godot_variant*, void> DelegateUtils_InvokeWithVariantArgs;
|
||||||
public delegate* unmanaged<IntPtr, IntPtr, godot_bool> DelegateUtils_DelegateEquals;
|
public delegate* unmanaged<IntPtr, IntPtr, godot_bool> DelegateUtils_DelegateEquals;
|
||||||
public delegate* unmanaged<IntPtr, int> DelegateUtils_DelegateHash;
|
public delegate* unmanaged<IntPtr, int> DelegateUtils_DelegateHash;
|
||||||
|
public delegate* unmanaged<IntPtr, godot_bool*, int> DelegateUtils_GetArgumentCount;
|
||||||
public delegate* unmanaged<IntPtr, godot_array*, godot_bool> DelegateUtils_TrySerializeDelegateWithGCHandle;
|
public delegate* unmanaged<IntPtr, godot_array*, godot_bool> DelegateUtils_TrySerializeDelegateWithGCHandle;
|
||||||
public delegate* unmanaged<godot_array*, IntPtr*, godot_bool> DelegateUtils_TryDeserializeDelegateWithGCHandle;
|
public delegate* unmanaged<godot_array*, IntPtr*, godot_bool> DelegateUtils_TryDeserializeDelegateWithGCHandle;
|
||||||
public delegate* unmanaged<void> ScriptManagerBridge_FrameCallback;
|
public delegate* unmanaged<void> ScriptManagerBridge_FrameCallback;
|
||||||
|
@ -55,6 +56,7 @@ namespace Godot.Bridge
|
||||||
DelegateUtils_InvokeWithVariantArgs = &DelegateUtils.InvokeWithVariantArgs,
|
DelegateUtils_InvokeWithVariantArgs = &DelegateUtils.InvokeWithVariantArgs,
|
||||||
DelegateUtils_DelegateEquals = &DelegateUtils.DelegateEquals,
|
DelegateUtils_DelegateEquals = &DelegateUtils.DelegateEquals,
|
||||||
DelegateUtils_DelegateHash = &DelegateUtils.DelegateHash,
|
DelegateUtils_DelegateHash = &DelegateUtils.DelegateHash,
|
||||||
|
DelegateUtils_GetArgumentCount = &DelegateUtils.GetArgumentCount,
|
||||||
DelegateUtils_TrySerializeDelegateWithGCHandle = &DelegateUtils.TrySerializeDelegateWithGCHandle,
|
DelegateUtils_TrySerializeDelegateWithGCHandle = &DelegateUtils.TrySerializeDelegateWithGCHandle,
|
||||||
DelegateUtils_TryDeserializeDelegateWithGCHandle = &DelegateUtils.TryDeserializeDelegateWithGCHandle,
|
DelegateUtils_TryDeserializeDelegateWithGCHandle = &DelegateUtils.TryDeserializeDelegateWithGCHandle,
|
||||||
ScriptManagerBridge_FrameCallback = &ScriptManagerBridge.FrameCallback,
|
ScriptManagerBridge_FrameCallback = &ScriptManagerBridge.FrameCallback,
|
||||||
|
|
|
@ -45,6 +45,29 @@ namespace Godot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly]
|
||||||
|
internal static unsafe int GetArgumentCount(IntPtr delegateGCHandle, godot_bool* outIsValid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var @delegate = (Delegate?)GCHandle.FromIntPtr(delegateGCHandle).Target;
|
||||||
|
int? argCount = @delegate?.Method?.GetParameters().Length;
|
||||||
|
if (argCount is null)
|
||||||
|
{
|
||||||
|
*outIsValid = godot_bool.False;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*outIsValid = godot_bool.True;
|
||||||
|
return argCount.Value;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExceptionUtils.LogException(e);
|
||||||
|
*outIsValid = godot_bool.False;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
internal static unsafe void InvokeWithVariantArgs(IntPtr delegateGCHandle, void* trampoline,
|
internal static unsafe void InvokeWithVariantArgs(IntPtr delegateGCHandle, void* trampoline,
|
||||||
godot_variant** args, int argc, godot_variant* outRet)
|
godot_variant** args, int argc, godot_variant* outRet)
|
||||||
|
|
|
@ -85,6 +85,10 @@ ObjectID ManagedCallable::get_object() const {
|
||||||
return CSharpLanguage::get_singleton()->get_managed_callable_middleman()->get_instance_id();
|
return CSharpLanguage::get_singleton()->get_managed_callable_middleman()->get_instance_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ManagedCallable::get_argument_count(bool &r_is_valid) const {
|
||||||
|
return GDMonoCache::managed_callbacks.DelegateUtils_GetArgumentCount(delegate_handle, &r_is_valid);
|
||||||
|
}
|
||||||
|
|
||||||
void ManagedCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
void ManagedCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||||
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; // Can't find anything better
|
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; // Can't find anything better
|
||||||
r_return_value = Variant();
|
r_return_value = Variant();
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
CompareEqualFunc get_compare_equal_func() const override;
|
CompareEqualFunc get_compare_equal_func() const override;
|
||||||
CompareLessFunc get_compare_less_func() const override;
|
CompareLessFunc get_compare_less_func() const override;
|
||||||
ObjectID get_object() const override;
|
ObjectID get_object() const override;
|
||||||
|
int get_argument_count(bool &r_is_valid) const override;
|
||||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||||
|
|
||||||
_FORCE_INLINE_ GCHandleIntPtr get_delegate() const { return delegate_handle; }
|
_FORCE_INLINE_ GCHandleIntPtr get_delegate() const { return delegate_handle; }
|
||||||
|
|
|
@ -53,6 +53,7 @@ void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) {
|
||||||
CHECK_CALLBACK_NOT_NULL(DelegateUtils, InvokeWithVariantArgs);
|
CHECK_CALLBACK_NOT_NULL(DelegateUtils, InvokeWithVariantArgs);
|
||||||
CHECK_CALLBACK_NOT_NULL(DelegateUtils, DelegateEquals);
|
CHECK_CALLBACK_NOT_NULL(DelegateUtils, DelegateEquals);
|
||||||
CHECK_CALLBACK_NOT_NULL(DelegateUtils, DelegateHash);
|
CHECK_CALLBACK_NOT_NULL(DelegateUtils, DelegateHash);
|
||||||
|
CHECK_CALLBACK_NOT_NULL(DelegateUtils, GetArgumentCount);
|
||||||
CHECK_CALLBACK_NOT_NULL(DelegateUtils, TrySerializeDelegateWithGCHandle);
|
CHECK_CALLBACK_NOT_NULL(DelegateUtils, TrySerializeDelegateWithGCHandle);
|
||||||
CHECK_CALLBACK_NOT_NULL(DelegateUtils, TryDeserializeDelegateWithGCHandle);
|
CHECK_CALLBACK_NOT_NULL(DelegateUtils, TryDeserializeDelegateWithGCHandle);
|
||||||
CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, FrameCallback);
|
CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, FrameCallback);
|
||||||
|
|
|
@ -78,6 +78,7 @@ struct ManagedCallbacks {
|
||||||
using FuncDelegateUtils_InvokeWithVariantArgs = void(GD_CLR_STDCALL *)(GCHandleIntPtr, void *, const Variant **, int32_t, const Variant *);
|
using FuncDelegateUtils_InvokeWithVariantArgs = void(GD_CLR_STDCALL *)(GCHandleIntPtr, void *, const Variant **, int32_t, const Variant *);
|
||||||
using FuncDelegateUtils_DelegateEquals = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, GCHandleIntPtr);
|
using FuncDelegateUtils_DelegateEquals = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, GCHandleIntPtr);
|
||||||
using FuncDelegateUtils_DelegateHash = int32_t(GD_CLR_STDCALL *)(GCHandleIntPtr);
|
using FuncDelegateUtils_DelegateHash = int32_t(GD_CLR_STDCALL *)(GCHandleIntPtr);
|
||||||
|
using FuncDelegateUtils_GetArgumentCount = int32_t(GD_CLR_STDCALL *)(GCHandleIntPtr, bool *);
|
||||||
using FuncDelegateUtils_TrySerializeDelegateWithGCHandle = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const Array *);
|
using FuncDelegateUtils_TrySerializeDelegateWithGCHandle = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const Array *);
|
||||||
using FuncDelegateUtils_TryDeserializeDelegateWithGCHandle = bool(GD_CLR_STDCALL *)(const Array *, GCHandleIntPtr *);
|
using FuncDelegateUtils_TryDeserializeDelegateWithGCHandle = bool(GD_CLR_STDCALL *)(const Array *, GCHandleIntPtr *);
|
||||||
using FuncScriptManagerBridge_FrameCallback = void(GD_CLR_STDCALL *)();
|
using FuncScriptManagerBridge_FrameCallback = void(GD_CLR_STDCALL *)();
|
||||||
|
@ -115,6 +116,7 @@ struct ManagedCallbacks {
|
||||||
FuncDelegateUtils_InvokeWithVariantArgs DelegateUtils_InvokeWithVariantArgs;
|
FuncDelegateUtils_InvokeWithVariantArgs DelegateUtils_InvokeWithVariantArgs;
|
||||||
FuncDelegateUtils_DelegateEquals DelegateUtils_DelegateEquals;
|
FuncDelegateUtils_DelegateEquals DelegateUtils_DelegateEquals;
|
||||||
FuncDelegateUtils_DelegateHash DelegateUtils_DelegateHash;
|
FuncDelegateUtils_DelegateHash DelegateUtils_DelegateHash;
|
||||||
|
FuncDelegateUtils_GetArgumentCount DelegateUtils_GetArgumentCount;
|
||||||
FuncDelegateUtils_TrySerializeDelegateWithGCHandle DelegateUtils_TrySerializeDelegateWithGCHandle;
|
FuncDelegateUtils_TrySerializeDelegateWithGCHandle DelegateUtils_TrySerializeDelegateWithGCHandle;
|
||||||
FuncDelegateUtils_TryDeserializeDelegateWithGCHandle DelegateUtils_TryDeserializeDelegateWithGCHandle;
|
FuncDelegateUtils_TryDeserializeDelegateWithGCHandle DelegateUtils_TryDeserializeDelegateWithGCHandle;
|
||||||
FuncScriptManagerBridge_FrameCallback ScriptManagerBridge_FrameCallback;
|
FuncScriptManagerBridge_FrameCallback ScriptManagerBridge_FrameCallback;
|
||||||
|
|
|
@ -95,6 +95,12 @@ public:
|
||||||
bool has_method(const StringName &p_method) const override {
|
bool has_method(const StringName &p_method) const override {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override {
|
||||||
|
if (r_is_valid) {
|
||||||
|
*r_is_valid = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
|
Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
|
||||||
return Variant();
|
return Variant();
|
||||||
}
|
}
|
||||||
|
|
140
tests/core/variant/test_callable.h
Normal file
140
tests/core/variant/test_callable.h
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* test_callable.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TEST_CALLABLE_H
|
||||||
|
#define TEST_CALLABLE_H
|
||||||
|
|
||||||
|
#include "core/object/class_db.h"
|
||||||
|
#include "core/object/object.h"
|
||||||
|
|
||||||
|
#include "tests/test_macros.h"
|
||||||
|
|
||||||
|
namespace TestCallable {
|
||||||
|
|
||||||
|
class TestClass : public Object {
|
||||||
|
GDCLASS(TestClass, Object);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods() {
|
||||||
|
ClassDB::bind_method(D_METHOD("test_func_1", "foo", "bar"), &TestClass::test_func_1);
|
||||||
|
ClassDB::bind_method(D_METHOD("test_func_2", "foo", "bar", "baz"), &TestClass::test_func_2);
|
||||||
|
ClassDB::bind_static_method("TestClass", D_METHOD("test_func_5", "foo", "bar"), &TestClass::test_func_5);
|
||||||
|
ClassDB::bind_static_method("TestClass", D_METHOD("test_func_6", "foo", "bar", "baz"), &TestClass::test_func_6);
|
||||||
|
|
||||||
|
{
|
||||||
|
MethodInfo mi;
|
||||||
|
mi.name = "test_func_7";
|
||||||
|
mi.arguments.push_back(PropertyInfo(Variant::INT, "foo"));
|
||||||
|
mi.arguments.push_back(PropertyInfo(Variant::INT, "bar"));
|
||||||
|
|
||||||
|
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "test_func_7", &TestClass::test_func_7, mi, varray(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MethodInfo mi;
|
||||||
|
mi.name = "test_func_8";
|
||||||
|
mi.arguments.push_back(PropertyInfo(Variant::INT, "foo"));
|
||||||
|
mi.arguments.push_back(PropertyInfo(Variant::INT, "bar"));
|
||||||
|
mi.arguments.push_back(PropertyInfo(Variant::INT, "baz"));
|
||||||
|
|
||||||
|
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "test_func_8", &TestClass::test_func_8, mi, varray(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void test_func_1(int p_foo, int p_bar) {}
|
||||||
|
void test_func_2(int p_foo, int p_bar, int p_baz) {}
|
||||||
|
|
||||||
|
int test_func_3(int p_foo, int p_bar) const { return 0; }
|
||||||
|
int test_func_4(int p_foo, int p_bar, int p_baz) const { return 0; }
|
||||||
|
|
||||||
|
static void test_func_5(int p_foo, int p_bar) {}
|
||||||
|
static void test_func_6(int p_foo, int p_bar, int p_baz) {}
|
||||||
|
|
||||||
|
void test_func_7(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {}
|
||||||
|
void test_func_8(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_CASE("[Callable] Argument count") {
|
||||||
|
TestClass *my_test = memnew(TestClass);
|
||||||
|
|
||||||
|
// Bound methods tests.
|
||||||
|
|
||||||
|
// Test simple methods.
|
||||||
|
Callable callable_1 = Callable(my_test, "test_func_1");
|
||||||
|
CHECK_EQ(callable_1.get_argument_count(), 2);
|
||||||
|
Callable callable_2 = Callable(my_test, "test_func_2");
|
||||||
|
CHECK_EQ(callable_2.get_argument_count(), 3);
|
||||||
|
Callable callable_3 = Callable(my_test, "test_func_5");
|
||||||
|
CHECK_EQ(callable_3.get_argument_count(), 2);
|
||||||
|
Callable callable_4 = Callable(my_test, "test_func_6");
|
||||||
|
CHECK_EQ(callable_4.get_argument_count(), 3);
|
||||||
|
|
||||||
|
// Test vararg methods.
|
||||||
|
Callable callable_vararg_1 = Callable(my_test, "test_func_7");
|
||||||
|
CHECK_MESSAGE(callable_vararg_1.get_argument_count() == 2, "vararg Callable should return the number of declared arguments");
|
||||||
|
Callable callable_vararg_2 = Callable(my_test, "test_func_8");
|
||||||
|
CHECK_MESSAGE(callable_vararg_2.get_argument_count() == 3, "vararg Callable should return the number of declared arguments");
|
||||||
|
|
||||||
|
// Callable MP tests.
|
||||||
|
|
||||||
|
// Test simple methods.
|
||||||
|
Callable callable_mp_1 = callable_mp(my_test, &TestClass::test_func_1);
|
||||||
|
CHECK_EQ(callable_mp_1.get_argument_count(), 2);
|
||||||
|
Callable callable_mp_2 = callable_mp(my_test, &TestClass::test_func_2);
|
||||||
|
CHECK_EQ(callable_mp_2.get_argument_count(), 3);
|
||||||
|
Callable callable_mp_3 = callable_mp(my_test, &TestClass::test_func_3);
|
||||||
|
CHECK_EQ(callable_mp_3.get_argument_count(), 2);
|
||||||
|
Callable callable_mp_4 = callable_mp(my_test, &TestClass::test_func_4);
|
||||||
|
CHECK_EQ(callable_mp_4.get_argument_count(), 3);
|
||||||
|
|
||||||
|
// Test static methods.
|
||||||
|
Callable callable_mp_static_1 = callable_mp_static(&TestClass::test_func_5);
|
||||||
|
CHECK_EQ(callable_mp_static_1.get_argument_count(), 2);
|
||||||
|
Callable callable_mp_static_2 = callable_mp_static(&TestClass::test_func_6);
|
||||||
|
CHECK_EQ(callable_mp_static_2.get_argument_count(), 3);
|
||||||
|
|
||||||
|
// Test bind.
|
||||||
|
Callable callable_mp_bind_1 = callable_mp_2.bind(1);
|
||||||
|
CHECK_MESSAGE(callable_mp_bind_1.get_argument_count() == 2, "bind should subtract from the argument count");
|
||||||
|
Callable callable_mp_bind_2 = callable_mp_2.bind(1, 2);
|
||||||
|
CHECK_MESSAGE(callable_mp_bind_2.get_argument_count() == 1, "bind should subtract from the argument count");
|
||||||
|
|
||||||
|
// Test unbind.
|
||||||
|
Callable callable_mp_unbind_1 = callable_mp_2.unbind(1);
|
||||||
|
CHECK_MESSAGE(callable_mp_unbind_1.get_argument_count() == 4, "unbind should add to the argument count");
|
||||||
|
Callable callable_mp_unbind_2 = callable_mp_2.unbind(2);
|
||||||
|
CHECK_MESSAGE(callable_mp_unbind_2.get_argument_count() == 5, "unbind should add to the argument count");
|
||||||
|
|
||||||
|
memdelete(my_test);
|
||||||
|
}
|
||||||
|
} // namespace TestCallable
|
||||||
|
|
||||||
|
#endif // TEST_CALLABLE_H
|
|
@ -93,6 +93,7 @@
|
||||||
#include "tests/core/test_time.h"
|
#include "tests/core/test_time.h"
|
||||||
#include "tests/core/threads/test_worker_thread_pool.h"
|
#include "tests/core/threads/test_worker_thread_pool.h"
|
||||||
#include "tests/core/variant/test_array.h"
|
#include "tests/core/variant/test_array.h"
|
||||||
|
#include "tests/core/variant/test_callable.h"
|
||||||
#include "tests/core/variant/test_dictionary.h"
|
#include "tests/core/variant/test_dictionary.h"
|
||||||
#include "tests/core/variant/test_variant.h"
|
#include "tests/core/variant/test_variant.h"
|
||||||
#include "tests/core/variant/test_variant_utility.h"
|
#include "tests/core/variant/test_variant_utility.h"
|
||||||
|
|
Loading…
Reference in a new issue