Skip to content

Commit

Permalink
[Core] Add methods to get argument count of Callables
Browse files Browse the repository at this point in the history
  • Loading branch information
AThousandShips committed Jan 28, 2024
1 parent 17e7f85 commit 5b48574
Show file tree
Hide file tree
Showing 32 changed files with 199 additions and 0 deletions.
5 changes: 5 additions & 0 deletions core/extension/gdextension_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ class CallableCustomExtension : public CallableCustom {
return object;
}

int get_argument_count() const override {
// TODO
return 0;
}

void *get_userdata(void *p_token) const {
return (p_token == token) ? userdata : nullptr;
}
Expand Down
20 changes: 20 additions & 0 deletions core/object/callable_method_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
return data.instance->get_instance_id();
}

virtual int get_argument_count() const {
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);
Expand Down Expand Up @@ -140,6 +144,10 @@ class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
return data.instance->get_instance_id();
}

virtual int get_argument_count() const {
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);
Expand Down Expand Up @@ -187,6 +195,10 @@ class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
return data.instance->get_instance_id();
}

virtual int get_argument_count() const override {
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);
Expand Down Expand Up @@ -238,6 +250,10 @@ class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase
return ObjectID();
}

virtual int get_argument_count() const override {
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();
Expand Down Expand Up @@ -280,6 +296,10 @@ class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerB
return ObjectID();
}

virtual int get_argument_count() const override {
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);
}
Expand Down
24 changes: 24 additions & 0 deletions core/object/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,28 @@ bool Object::has_method(const StringName &p_method) const {
return false;
}

int Object::get_method_argument_count(const StringName &p_method) const {
if (p_method == CoreStringNames::get_singleton()->_free) {
return 0;
}

if (script_instance && script_instance->has_method(p_method)) {
return script_instance->get_method_argument_count(p_method);
}

MethodBind *method = ClassDB::get_method(get_class_name(), p_method);
if (method != nullptr) {
return method->get_argument_count();
}

const Script *scr = Object::cast_to<Script>(this);
if (scr != nullptr && scr->has_static_method(p_method)) {
return scr->get_method_argument_count(p_method);
}

return 0;
}

Variant Object::getvar(const Variant &p_key, bool *r_valid) const {
if (r_valid) {
*r_valid = false;
Expand Down Expand Up @@ -1624,6 +1646,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);

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);
Expand Down
1 change: 1 addition & 0 deletions core/object/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,7 @@ class Object {
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) 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);
Expand Down
2 changes: 2 additions & 0 deletions core/object/script_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class ScriptInstance {
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) const = 0;

virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0;

template <typename... VarArgs>
Expand Down
4 changes: 4 additions & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ class Script : public Resource {
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_method_argument_count(const StringName &p_method) const = 0;

virtual MethodInfo get_method_info(const StringName &p_method) const = 0;

virtual bool is_tool() const = 0;
Expand Down Expand Up @@ -426,6 +428,8 @@ class PlaceHolderScriptInstance : public ScriptInstance {
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) const override { 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();
Expand Down
3 changes: 3 additions & 0 deletions core/object/script_language_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ void ScriptExtension::_bind_methods() {

GDVIRTUAL_BIND(_has_method, "method");
GDVIRTUAL_BIND(_has_static_method, "method");

GDVIRTUAL_BIND(_get_method_argument_count, "method");

GDVIRTUAL_BIND(_get_method_info, "method");

GDVIRTUAL_BIND(_is_tool);
Expand Down
7 changes: 7 additions & 0 deletions core/object/script_language_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class ScriptExtension : public Script {
EXBIND1RC(bool, has_method, const StringName &)
EXBIND1RC(bool, has_static_method, const StringName &)

EXBIND1RC(int, get_method_argument_count, const StringName &)

GDVIRTUAL1RC(Dictionary, _get_method_info, const StringName &)
virtual MethodInfo get_method_info(const StringName &p_method) const override {
Dictionary mi;
Expand Down Expand Up @@ -791,6 +793,11 @@ class ScriptInstanceExtension : public ScriptInstance {
return false;
}

virtual int get_method_argument_count(const StringName &p_method) const override {
// TODO
return 0;
}

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) {
Expand Down
10 changes: 10 additions & 0 deletions core/variant/callable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ StringName Callable::get_method() const {
return method;
}

int Callable::get_argument_count() const {
if (is_null()) {
return 0;
} else if (is_custom()) {
return custom->get_argument_count();
} else {
return get_object()->get_method_argument_count(method);
}
}

int Callable::get_bound_arguments_count() const {
if (!is_null() && is_custom()) {
return custom->get_bound_arguments_count();
Expand Down
2 changes: 2 additions & 0 deletions core/variant/callable.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class Callable {
ObjectID get_object_id() const;
StringName get_method() const;
CallableCustom *get_custom() const;
int get_argument_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.
Array get_bound_arguments() const;
Expand Down Expand Up @@ -153,6 +154,7 @@ class CallableCustom {
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 const Callable *get_base_comparator() const;
virtual int get_argument_count() const = 0;
virtual int get_bound_arguments_count() const;
virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const;

Expand Down
8 changes: 8 additions & 0 deletions core/variant/callable_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ const Callable *CallableCustomBind::get_base_comparator() const {
return callable.get_base_comparator();
}

int CallableCustomBind::get_argument_count() const {
return callable.get_argument_count() - binds.size();
}

int CallableCustomBind::get_bound_arguments_count() const {
return callable.get_bound_arguments_count() + binds.size();
}
Expand Down Expand Up @@ -225,6 +229,10 @@ const Callable *CallableCustomUnbind::get_base_comparator() const {
return callable.get_base_comparator();
}

int CallableCustomUnbind::get_argument_count() const {
return callable.get_argument_count() + argcount;
}

int CallableCustomUnbind::get_bound_arguments_count() const {
return callable.get_bound_arguments_count() - argcount;
}
Expand Down
2 changes: 2 additions & 0 deletions core/variant/callable_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class CallableCustomBind : public CallableCustom {
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 const Callable *get_base_comparator() const override;
virtual int get_argument_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;
Callable get_callable() { return callable; }
Expand Down Expand Up @@ -81,6 +82,7 @@ class CallableCustomUnbind : public CallableCustom {
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 const Callable *get_base_comparator() const override;
virtual int get_argument_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;

Expand Down
1 change: 1 addition & 0 deletions core/variant/variant_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2046,6 +2046,7 @@ static void _register_variant_builtin_methods() {
bind_method(Callable, get_object, sarray(), varray());
bind_method(Callable, get_object_id, sarray(), varray());
bind_method(Callable, get_method, sarray(), varray());
bind_method(Callable, get_argument_count, sarray(), varray());
bind_method(Callable, get_bound_arguments_count, sarray(), varray());
bind_method(Callable, get_bound_arguments, sarray(), varray());
bind_method(Callable, hash, sarray(), varray());
Expand Down
4 changes: 4 additions & 0 deletions core/variant/variant_callable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ ObjectID VariantCallable::get_object() const {
return ObjectID();
}

int VariantCallable::get_argument_count() const {
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 {
Variant v = variant;
v.callp(method, p_arguments, p_argcount, r_return_value, r_call_error);
Expand Down
1 change: 1 addition & 0 deletions core/variant/variant_callable.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class VariantCallable : public CallableCustom {
bool is_valid() const override;
StringName get_method() const override;
ObjectID get_object() const override;
int get_argument_count() 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);
Expand Down
6 changes: 6 additions & 0 deletions doc/classes/Callable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@
Calls the method represented by this [Callable]. Unlike [method call], this method expects all arguments to be contained inside the [param arguments] [Array].
</description>
</method>
<method name="get_argument_count" qualifiers="const">
<return type="int" />
<description>
Returns the total number of arguments of this [Callable], accounting for any bound (or unbound) arguments. The number of bound arguments is subtracted from the total, and the number of unbound arguments are added.
</description>
</method>
<method name="get_bound_arguments" qualifiers="const">
<return type="Array" />
<description>
Expand Down
8 changes: 8 additions & 0 deletions doc/classes/Object.xml
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,14 @@
Returns the object's metadata entry names as a [PackedStringArray].
</description>
</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].
[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">
<return type="Dictionary[]" />
<description>
Expand Down
6 changes: 6 additions & 0 deletions doc/classes/ScriptExtension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
<description>
</description>
</method>
<method name="_get_method_argument_count" qualifiers="virtual const">
<return type="int" />
<param index="0" name="method" type="StringName" />
<description>
</description>
</method>
<method name="_get_method_info" qualifiers="virtual const">
<return type="Dictionary" />
<param index="0" name="method" type="StringName" />
Expand Down
22 changes: 22 additions & 0 deletions modules/gdscript/gdscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,15 @@ bool GDScript::has_static_method(const StringName &p_method) const {
return member_functions.has(p_method) && member_functions[p_method]->is_static();
}

int GDScript::get_method_argument_count(const StringName &p_method) const {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method);
if (!E) {
return 0;
}

return E->value->get_argument_count();
}

MethodInfo GDScript::get_method_info(const StringName &p_method) const {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = member_functions.find(p_method);
if (!E) {
Expand Down Expand Up @@ -1916,6 +1925,19 @@ bool GDScriptInstance::has_method(const StringName &p_method) const {
return false;
}

int GDScriptInstance::get_method_argument_count(const StringName &p_method) const {
const GDScript *sptr = script.ptr();
while (sptr) {
HashMap<StringName, GDScriptFunction *>::ConstIterator E = sptr->member_functions.find(p_method);
if (E) {
return E->value->get_argument_count();
}
sptr = sptr->_base;
}

return 0;
}

Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
GDScript *sptr = script.ptr();
if (unlikely(p_method == SNAME("_ready"))) {
Expand Down
6 changes: 6 additions & 0 deletions modules/gdscript/gdscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,9 @@ class GDScript : public Script {
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_static_method(const StringName &p_method) const override;

virtual int get_method_argument_count(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;
Expand Down Expand Up @@ -369,6 +372,9 @@ class GDScriptInstance : public ScriptInstance {

virtual void get_method_list(List<MethodInfo> *p_list) const;
virtual bool has_method(const StringName &p_method) const;

virtual int get_method_argument_count(const StringName &p_method) const;

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]; }
Expand Down
1 change: 1 addition & 0 deletions modules/gdscript/gdscript_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ class GDScriptFunction {
_FORCE_INLINE_ GDScript *get_script() const { return _script; }
_FORCE_INLINE_ bool is_static() const { return _static; }
_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_ int get_max_stack_size() const { return _stack_size; }

Expand Down

0 comments on commit 5b48574

Please sign in to comment.