summaryrefslogtreecommitdiffstats
path: root/core/object
diff options
context:
space:
mode:
Diffstat (limited to 'core/object')
-rw-r--r--core/object/callable_method_pointer.h45
-rw-r--r--core/object/class_db.cpp25
-rw-r--r--core/object/class_db.h33
-rw-r--r--core/object/method_bind.h42
-rw-r--r--core/object/object.cpp55
-rw-r--r--core/object/object.h6
-rw-r--r--core/object/ref_counted.h20
-rw-r--r--core/object/script_instance.cpp22
-rw-r--r--core/object/script_instance.h2
-rw-r--r--core/object/script_language.cpp16
-rw-r--r--core/object/script_language.h9
-rw-r--r--core/object/script_language_extension.cpp3
-rw-r--r--core/object/script_language_extension.h27
-rw-r--r--core/object/worker_thread_pool.h8
14 files changed, 249 insertions, 64 deletions
diff --git a/core/object/callable_method_pointer.h b/core/object/callable_method_pointer.h
index f8e8c4d7e9..1b29e1778a 100644
--- a/core/object/callable_method_pointer.h
+++ b/core/object/callable_method_pointer.h
@@ -77,7 +77,7 @@ public:
virtual uint32_t hash() const;
};
-template <class T, class... P>
+template <typename T, typename... P>
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@@ -93,6 +93,11 @@ public:
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 {
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);
@@ -107,7 +112,7 @@ public:
}
};
-template <class T, class... P>
+template <typename T, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
@@ -123,7 +128,7 @@ Callable create_custom_callable_function_pointer(T *p_instance,
// VERSION WITH RETURN
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@@ -140,6 +145,11 @@ public:
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 {
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);
@@ -154,7 +164,7 @@ public:
}
};
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
@@ -170,7 +180,7 @@ Callable create_custom_callable_function_pointer(T *p_instance,
// CONST VERSION WITH RETURN
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
@@ -187,6 +197,11 @@ public:
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 {
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);
@@ -201,7 +216,7 @@ public:
}
};
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
Callable create_custom_callable_function_pointer(T *p_instance,
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
@@ -223,7 +238,7 @@ Callable create_custom_callable_function_pointer(T *p_instance,
// STATIC VERSIONS
-template <class... P>
+template <typename... P>
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
struct Data {
void (*method)(P...);
@@ -238,6 +253,11 @@ public:
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 {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
r_return_value = Variant();
@@ -250,7 +270,7 @@ public:
}
};
-template <class T, class... P>
+template <typename T, typename... P>
Callable create_custom_callable_static_function_pointer(
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
@@ -264,7 +284,7 @@ Callable create_custom_callable_static_function_pointer(
return Callable(ccmp);
}
-template <class R, class... P>
+template <typename R, typename... P>
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
R(*method)
@@ -280,6 +300,11 @@ public:
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 {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
@@ -291,7 +316,7 @@ public:
}
};
-template <class R, class... P>
+template <typename R, typename... P>
Callable create_custom_callable_static_function_pointer(
#ifdef DEBUG_METHODS_ENABLED
const char *p_func_text,
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 231a8e4d68..80a2703c2f 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -1666,6 +1666,31 @@ bool ClassDB::has_method(const StringName &p_class, const StringName &p_method,
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) {
_bind_method_custom(p_class, p_method, false);
}
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 7f117b4a9b..adb525cbe8 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -140,7 +140,7 @@ public:
~ClassInfo() {}
};
- template <class T>
+ template <typename T>
static Object *creator() {
return memnew(T);
}
@@ -187,12 +187,12 @@ private:
public:
// DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!!
- template <class T>
+ template <typename T>
static void _add_class() {
_add_class2(T::get_class_static(), T::get_parent_class_static());
}
- template <class T>
+ template <typename T>
static void register_class(bool p_virtual = false) {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -207,7 +207,7 @@ public:
T::register_custom_data_to_otdb();
}
- template <class T>
+ template <typename T>
static void register_abstract_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -220,7 +220,7 @@ public:
//nothing
}
- template <class T>
+ template <typename T>
static void register_internal_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -235,7 +235,7 @@ public:
T::register_custom_data_to_otdb();
}
- template <class T>
+ template <typename T>
static void register_runtime_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -255,12 +255,12 @@ public:
static void register_extension_class(ObjectGDExtension *p_extension);
static void unregister_extension_class(const StringName &p_class, bool p_free_method_binds = true);
- template <class T>
+ template <typename T>
static Object *_create_ptr_func() {
return T::create();
}
- template <class T>
+ template <typename T>
static void register_custom_instance_class() {
GLOBAL_LOCK_FUNCTION;
static_assert(types_are_same_v<typename T::self_type, T>, "Class not declared properly, please use GDCLASS.");
@@ -314,7 +314,7 @@ public:
using return_type = R;
};
- template <class N, class M, typename... VarArgs>
+ template <typename N, typename M, typename... VarArgs>
static MethodBind *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];
@@ -328,7 +328,7 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, false, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class N, class M, typename... VarArgs>
+ template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_static_method(const StringName &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];
@@ -343,7 +343,7 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, false, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class N, class M, typename... VarArgs>
+ template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_compatibility_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];
@@ -357,7 +357,7 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, true, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class N, class M, typename... VarArgs>
+ template <typename N, typename M, typename... VarArgs>
static MethodBind *bind_compatibility_static_method(const StringName &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];
@@ -372,7 +372,7 @@ public:
return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, true, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
}
- template <class M>
+ template <typename M>
static MethodBind *bind_vararg_method(uint32_t p_flags, const StringName &p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
GLOBAL_LOCK_FUNCTION;
@@ -385,7 +385,7 @@ public:
return _bind_vararg_method(bind, p_name, p_default_args, false);
}
- template <class M>
+ template <typename M>
static MethodBind *bind_compatibility_vararg_method(uint32_t p_flags, const StringName &p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) {
GLOBAL_LOCK_FUNCTION;
@@ -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_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 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_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);
@@ -497,13 +498,13 @@ _FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr, const Error &p_err) {
arr.push_back(p_err);
}
-template <class... P>
+template <typename... P>
_FORCE_INLINE_ void errarray_add_str(Vector<Error> &arr, const Error &p_err, P... p_args) {
arr.push_back(p_err);
errarray_add_str(arr, p_args...);
}
-template <class... P>
+template <typename... P>
_FORCE_INLINE_ Vector<Error> errarray(P... p_args) {
Vector<Error> arr;
errarray_add_str(arr, p_args...);
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index 88b867a1ca..e97f4abc6a 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -140,7 +140,7 @@ public:
};
// MethodBindVarArg base CRTP
-template <class Derived, class T, class R, bool should_returns>
+template <typename Derived, typename T, typename R, bool should_returns>
class MethodBindVarArgBase : public MethodBind {
protected:
R(T::*method)
@@ -219,7 +219,7 @@ private:
};
// variadic, no return
-template <class T>
+template <typename T>
class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> {
friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>;
@@ -245,7 +245,7 @@ private:
}
};
-template <class T>
+template <typename T>
MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static());
@@ -253,7 +253,7 @@ MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, int,
}
// variadic, return
-template <class T, class R>
+template <typename T, typename R>
class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> {
friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>;
@@ -287,7 +287,7 @@ private:
}
};
-template <class T, class R>
+template <typename T, typename R>
MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) {
MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant));
a->set_instance_class(T::get_class_static());
@@ -305,9 +305,9 @@ class __UnexistingClass;
// no return, not const
#ifdef TYPED_METHOD_BIND
-template <class T, class... P>
+template <typename T, typename... P>
#else
-template <class... P>
+template <typename... P>
#endif
class MethodBindT : public MethodBind {
void (MB_T::*method)(P...);
@@ -375,7 +375,7 @@ public:
}
};
-template <class T, class... P>
+template <typename T, typename... P>
MethodBind *create_method_bind(void (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindT<T, P...>)(p_method));
@@ -389,9 +389,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...)) {
// no return, const
#ifdef TYPED_METHOD_BIND
-template <class T, class... P>
+template <typename T, typename... P>
#else
-template <class... P>
+template <typename... P>
#endif
class MethodBindTC : public MethodBind {
void (MB_T::*method)(P...) const;
@@ -460,7 +460,7 @@ public:
}
};
-template <class T, class... P>
+template <typename T, typename... P>
MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method));
@@ -474,9 +474,9 @@ MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
// return, not const
#ifdef TYPED_METHOD_BIND
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
#else
-template <class R, class... P>
+template <typename R, typename... P>
#endif
class MethodBindTR : public MethodBind {
R(MB_T::*method)
@@ -555,7 +555,7 @@ public:
}
};
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
MethodBind *create_method_bind(R (T::*p_method)(P...)) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method));
@@ -570,9 +570,9 @@ MethodBind *create_method_bind(R (T::*p_method)(P...)) {
// return, const
#ifdef TYPED_METHOD_BIND
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
#else
-template <class R, class... P>
+template <typename R, typename... P>
#endif
class MethodBindTRC : public MethodBind {
R(MB_T::*method)
@@ -652,7 +652,7 @@ public:
}
};
-template <class T, class R, class... P>
+template <typename T, typename R, typename... P>
MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
#ifdef TYPED_METHOD_BIND
MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method));
@@ -667,7 +667,7 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
// no return
-template <class... P>
+template <typename... P>
class MethodBindTS : public MethodBind {
void (*function)(P...);
@@ -717,7 +717,7 @@ public:
}
};
-template <class... P>
+template <typename... P>
MethodBind *create_static_method_bind(void (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
return a;
@@ -725,7 +725,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) {
// return
-template <class R, class... P>
+template <typename R, typename... P>
class MethodBindTRS : public MethodBind {
R(*function)
(P...);
@@ -784,7 +784,7 @@ public:
}
};
-template <class R, class... P>
+template <typename R, typename... P>
MethodBind *create_static_method_bind(R (*p_method)(P...)) {
MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
return a;
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 6a5a9efefa..e5d771844b 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -688,6 +688,59 @@ bool Object::has_method(const StringName &p_method) const {
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 {
if (r_valid) {
*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("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("get_signal_list"), &Object::_get_signal_list);
ClassDB::bind_method(D_METHOD("get_signal_connection_list", "signal"), &Object::_get_signal_connection_list);
diff --git a/core/object/object.h b/core/object/object.h
index cb1495296d..d9551ecd01 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -654,6 +654,7 @@ private:
Variant _get_bind(const StringName &p_name) const;
void _set_indexed_bind(const NodePath &p_name, const Variant &p_value);
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);
@@ -796,12 +797,12 @@ public:
void detach_from_objectdb();
_FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; }
- template <class T>
+ template <typename T>
static T *cast_to(Object *p_object) {
return p_object ? dynamic_cast<T *>(p_object) : nullptr;
}
- template <class T>
+ template <typename T>
static const T *cast_to(const Object *p_object) {
return p_object ? dynamic_cast<const T *>(p_object) : nullptr;
}
@@ -865,6 +866,7 @@ public:
Variant property_get_revert(const StringName &p_name) 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;
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);
diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h
index 10be27b879..5b358135c4 100644
--- a/core/object/ref_counted.h
+++ b/core/object/ref_counted.h
@@ -53,7 +53,7 @@ public:
~RefCounted() {}
};
-template <class T>
+template <typename T>
class Ref {
T *reference = nullptr;
@@ -117,7 +117,7 @@ public:
ref(p_from);
}
- template <class T_Other>
+ template <typename T_Other>
void operator=(const Ref<T_Other> &p_from) {
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
if (!refb) {
@@ -149,7 +149,7 @@ public:
}
}
- template <class T_Other>
+ template <typename T_Other>
void reference_ptr(T_Other *p_ptr) {
if (reference == p_ptr) {
return;
@@ -166,7 +166,7 @@ public:
ref(p_from);
}
- template <class T_Other>
+ template <typename T_Other>
Ref(const Ref<T_Other> &p_from) {
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
if (!refb) {
@@ -240,7 +240,7 @@ public:
WeakRef() {}
};
-template <class T>
+template <typename T>
struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
if (p_ptr == nullptr) {
@@ -258,7 +258,7 @@ struct PtrToArg<Ref<T>> {
}
};
-template <class T>
+template <typename T>
struct PtrToArg<const Ref<T> &> {
typedef Ref<T> EncodeT;
@@ -271,7 +271,7 @@ struct PtrToArg<const Ref<T> &> {
}
};
-template <class T>
+template <typename T>
struct GetTypeInfo<Ref<T>> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
@@ -281,7 +281,7 @@ struct GetTypeInfo<Ref<T>> {
}
};
-template <class T>
+template <typename T>
struct GetTypeInfo<const Ref<T> &> {
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
@@ -291,13 +291,13 @@ struct GetTypeInfo<const Ref<T> &> {
}
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor<Ref<T>> {
static _FORCE_INLINE_ Ref<T> get(const Variant *v) { return Ref<T>(*VariantInternal::get_object(v)); }
static _FORCE_INLINE_ void set(Variant *v, const Ref<T> &p_ref) { VariantInternal::refcounted_object_assign(v, p_ref.ptr()); }
};
-template <class T>
+template <typename T>
struct VariantInternalAccessor<const Ref<T> &> {
static _FORCE_INLINE_ Ref<T> get(const Variant *v) { return Ref<T>(*VariantInternal::get_object(v)); }
static _FORCE_INLINE_ void set(Variant *v, const Ref<T> &p_ref) { VariantInternal::refcounted_object_assign(v, p_ref.ptr()); }
diff --git a/core/object/script_instance.cpp b/core/object/script_instance.cpp
index 303b127db1..65f44e8a6b 100644
--- a/core/object/script_instance.cpp
+++ b/core/object/script_instance.cpp
@@ -32,6 +32,28 @@
#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) {
return callp(p_method, p_args, p_argcount, r_error);
}
diff --git a/core/object/script_instance.h b/core/object/script_instance.h
index 45d51534fc..2c8132ec1f 100644
--- a/core/object/script_instance.h
+++ b/core/object/script_instance.h
@@ -53,6 +53,8 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) 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;
template <typename... VarArgs>
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 14894e1710..1196c2f787 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -102,6 +102,22 @@ Dictionary Script::_get_script_constant_map() {
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
PropertyInfo Script::get_class_category() const {
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 95e9d2b4af..be50e58d79 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -151,6 +151,8 @@ public:
virtual bool has_method(const StringName &p_method) const = 0;
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 bool is_tool() const = 0;
@@ -442,6 +444,13 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) 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 {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index ec99c7cf4e..a18ef8d4d7 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -56,6 +56,9 @@ void ScriptExtension::_bind_methods() {
GDVIRTUAL_BIND(_has_method, "method");
GDVIRTUAL_BIND(_has_static_method, "method");
+
+ GDVIRTUAL_BIND(_get_script_method_argument_count, "method");
+
GDVIRTUAL_BIND(_get_method_info, "method");
GDVIRTUAL_BIND(_is_tool);
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index 18105ec8cd..1db322526d 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -101,6 +101,19 @@ public:
EXBIND1RC(bool, has_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 &)
virtual MethodInfo get_method_info(const StringName &p_method) const override {
Dictionary mi;
@@ -807,6 +820,19 @@ public:
return false;
}
+ virtual int get_method_argument_count(const StringName &p_method, bool *r_is_valid = nullptr) const override {
+ if (native_info->get_method_argument_count_func) {
+ GDExtensionBool is_valid = 0;
+ GDExtensionInt ret = native_info->get_method_argument_count_func(instance, (GDExtensionStringNamePtr)&p_method, &is_valid);
+ if (r_is_valid) {
+ *r_is_valid = is_valid != 0;
+ }
+ return ret;
+ }
+ // 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 {
Variant ret;
if (native_info->call_func) {
@@ -894,7 +920,6 @@ public:
return reinterpret_cast<ScriptLanguage *>(lang);
}
return nullptr;
- ;
}
virtual ~ScriptInstanceExtension() {
if (native_info->free_func) {
diff --git a/core/object/worker_thread_pool.h b/core/object/worker_thread_pool.h
index c9921c808d..fdddc9a647 100644
--- a/core/object/worker_thread_pool.h
+++ b/core/object/worker_thread_pool.h
@@ -157,7 +157,7 @@ private:
TaskID _add_task(const Callable &p_callable, void (*p_func)(void *), void *p_userdata, BaseTemplateUserdata *p_template_userdata, bool p_high_priority, const String &p_description);
GroupID _add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description);
- template <class C, class M, class U>
+ template <typename C, typename M, typename U>
struct TaskUserData : public BaseTemplateUserdata {
C *instance;
M method;
@@ -167,7 +167,7 @@ private:
}
};
- template <class C, class M, class U>
+ template <typename C, typename M, typename U>
struct GroupUserData : public BaseTemplateUserdata {
C *instance;
M method;
@@ -181,7 +181,7 @@ protected:
static void _bind_methods();
public:
- template <class C, class M, class U>
+ template <typename C, typename M, typename U>
TaskID add_template_task(C *p_instance, M p_method, U p_userdata, bool p_high_priority = false, const String &p_description = String()) {
typedef TaskUserData<C, M, U> TUD;
TUD *ud = memnew(TUD);
@@ -196,7 +196,7 @@ public:
bool is_task_completed(TaskID p_task_id) const;
Error wait_for_task_completion(TaskID p_task_id);
- template <class C, class M, class U>
+ template <typename C, typename M, typename U>
GroupID add_template_group_task(C *p_instance, M p_method, U p_userdata, int p_elements, int p_tasks = -1, bool p_high_priority = false, const String &p_description = String()) {
typedef GroupUserData<C, M, U> GroupUD;
GroupUD *ud = memnew(GroupUD);