Browse Source

Merge pull request #58929 from reduz/remove-variant-arg-macros

Remove VARIANT_ARG* macros
Rémi Verschelde 3 years ago
parent
commit
33c907f9f5
59 changed files with 417 additions and 467 deletions
  1. 2 2
      core/extension/gdnative_interface.cpp
  2. 1 1
      core/math/expression.cpp
  3. 4 4
      core/object/class_db.cpp
  4. 1 1
      core/object/make_virtuals.py
  5. 6 35
      core/object/message_queue.cpp
  6. 37 6
      core/object/message_queue.h
  7. 8 44
      core/object/object.cpp
  8. 30 13
      core/object/object.h
  9. 0 14
      core/object/script_language.cpp
  10. 16 4
      core/object/script_language.h
  11. 14 35
      core/object/undo_redo.cpp
  12. 26 4
      core/object/undo_redo.h
  13. 3 3
      core/variant/binder_common.h
  14. 3 3
      core/variant/callable.cpp
  15. 2 18
      core/variant/variant.cpp
  16. 25 2
      core/variant/variant.h
  17. 2 2
      core/variant/variant_call.cpp
  18. 3 3
      core/variant/variant_setget.cpp
  19. 4 5
      editor/animation_track_editor.cpp
  20. 0 3
      editor/connections_dialog.cpp
  21. 2 2
      editor/debugger/editor_debugger_node.cpp
  22. 1 1
      editor/debugger/editor_debugger_node.h
  23. 7 9
      editor/debugger/script_editor_debugger.cpp
  24. 1 1
      editor/debugger/script_editor_debugger.h
  25. 3 3
      editor/editor_inspector.cpp
  26. 1 1
      editor/editor_properties.cpp
  27. 6 6
      modules/gdscript/gdscript.cpp
  28. 2 2
      modules/gdscript/gdscript.h
  29. 1 1
      modules/gdscript/gdscript_rpc_callable.cpp
  30. 8 8
      modules/gdscript/gdscript_vm.cpp
  31. 1 1
      modules/gdscript/tests/gdscript_test_runner.cpp
  32. 3 3
      modules/mono/csharp_script.cpp
  33. 2 2
      modules/mono/csharp_script.h
  34. 1 1
      modules/mono/glue/base_object_glue.cpp
  35. 1 1
      modules/navigation/rvo_agent.cpp
  36. 1 1
      modules/visual_script/editor/visual_script_editor.cpp
  37. 3 3
      modules/visual_script/visual_script.cpp
  38. 1 1
      modules/visual_script/visual_script.h
  39. 1 1
      modules/visual_script/visual_script_expression.cpp
  40. 11 11
      modules/visual_script/visual_script_func_nodes.cpp
  41. 1 1
      modules/visual_script/visual_script_nodes.cpp
  42. 2 2
      platform/android/api/api.cpp
  43. 2 2
      platform/android/api/java_class_wrapper.h
  44. 3 3
      platform/android/api/jni_singleton.h
  45. 3 3
      platform/android/java_class_wrapper.cpp
  46. 7 5
      platform/android/java_godot_lib_jni.cpp
  47. 3 4
      platform/android/plugin/godot_plugin_jni.cpp
  48. 2 2
      platform/javascript/javascript_singleton.cpp
  49. 26 37
      scene/animation/animation_player.cpp
  50. 28 28
      scene/animation/animation_tree.cpp
  51. 26 7
      scene/debugger/scene_debugger.cpp
  52. 2 2
      scene/debugger/scene_debugger.h
  53. 1 1
      scene/gui/tree.cpp
  54. 2 66
      scene/main/node.cpp
  55. 25 3
      scene/main/node.h
  56. 15 34
      scene/main/scene_tree.cpp
  57. 21 2
      scene/main/scene_tree.h
  58. 3 3
      scene/multiplayer/scene_rpc_interface.cpp
  59. 1 1
      tests/core/object/test_object.h

+ 2 - 2
core/extension/gdnative_interface.cpp

@@ -80,7 +80,7 @@ static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStrin
 	const Variant **args = (const Variant **)p_args;
 	Variant ret;
 	Callable::CallError error;
-	self->call(*method, args, p_argcount, ret, error);
+	self->callp(*method, args, p_argcount, ret, error);
 	memnew_placement(r_return, Variant(ret));
 
 	if (r_error) {
@@ -152,7 +152,7 @@ static void gdnative_variant_set_indexed(GDNativeVariantPtr p_self, GDNativeInt
 
 	bool valid;
 	bool oob;
-	self->set_indexed(p_index, value, valid, oob);
+	self->set_indexed(p_index, *value, valid, oob);
 	*r_valid = valid;
 	*r_oob = oob;
 }

+ 1 - 1
core/math/expression.cpp

@@ -1440,7 +1440,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
 			}
 
 			Callable::CallError ce;
-			base.call(call->method, (const Variant **)argp.ptr(), argp.size(), r_ret, ce);
+			base.callp(call->method, (const Variant **)argp.ptr(), argp.size(), r_ret, ce);
 
 			if (ce.error != Callable::CallError::CALL_OK) {
 				r_error_str = vformat(RTR("On call to '%s':"), String(call->method));

+ 4 - 4
core/object/class_db.cpp

@@ -1197,7 +1197,7 @@ bool ClassDB::set_property(Object *p_object, const StringName &p_property, const
 				if (psg->_setptr) {
 					psg->_setptr->call(p_object, arg, 2, ce);
 				} else {
-					p_object->call(psg->setter, arg, 2, ce);
+					p_object->callp(psg->setter, arg, 2, ce);
 				}
 
 			} else {
@@ -1205,7 +1205,7 @@ bool ClassDB::set_property(Object *p_object, const StringName &p_property, const
 				if (psg->_setptr) {
 					psg->_setptr->call(p_object, arg, 1, ce);
 				} else {
-					p_object->call(psg->setter, arg, 1, ce);
+					p_object->callp(psg->setter, arg, 1, ce);
 				}
 			}
 
@@ -1238,14 +1238,14 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia
 				Variant index = psg->index;
 				const Variant *arg[1] = { &index };
 				Callable::CallError ce;
-				r_value = p_object->call(psg->getter, arg, 1, ce);
+				r_value = p_object->callp(psg->getter, arg, 1, ce);
 
 			} else {
 				Callable::CallError ce;
 				if (psg->_getptr) {
 					r_value = psg->_getptr->call(p_object, nullptr, 0, ce);
 				} else {
-					r_value = p_object->call(psg->getter, nullptr, 0, ce);
+					r_value = p_object->callp(psg->getter, nullptr, 0, ce);
 				}
 			}
 			return true;

+ 1 - 1
core/object/make_virtuals.py

@@ -8,7 +8,7 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
 	if (script_instance) {\\
 		Callable::CallError ce; \\
 		$CALLSIARGS\\
-		$CALLSIBEGINscript_instance->call(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
+		$CALLSIBEGINscript_instance->callp(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
 		if (ce.error == Callable::CallError::CALL_OK) {\\
 			$CALLSIRET\\
 			return true;\\

+ 6 - 35
core/object/message_queue.cpp

@@ -32,6 +32,7 @@
 
 #include "core/config/project_settings.h"
 #include "core/core_string_names.h"
+#include "core/object/class_db.h"
 #include "core/object/script_language.h"
 
 MessageQueue *MessageQueue::singleton = nullptr;
@@ -40,23 +41,8 @@ MessageQueue *MessageQueue::get_singleton() {
 	return singleton;
 }
 
-Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {
-	return push_callable(Callable(p_id, p_method), p_args, p_argcount, p_show_error);
-}
-
-Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS;
-
-	int argc = 0;
-
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		if (argptr[i]->get_type() == Variant::NIL) {
-			break;
-		}
-		argc++;
-	}
-
-	return push_call(p_id, p_method, argptr, argc, false);
+Error MessageQueue::push_callp(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {
+	return push_callablep(Callable(p_id, p_method), p_args, p_argcount, p_show_error);
 }
 
 Error MessageQueue::push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value) {
@@ -113,8 +99,8 @@ Error MessageQueue::push_notification(ObjectID p_id, int p_notification) {
 	return OK;
 }
 
-Error MessageQueue::push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
-	return push_call(p_object->get_instance_id(), p_method, VARIANT_ARG_PASS);
+Error MessageQueue::push_callp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {
+	return push_callp(p_object->get_instance_id(), p_method, p_args, p_argcount, p_show_error);
 }
 
 Error MessageQueue::push_notification(Object *p_object, int p_notification) {
@@ -125,7 +111,7 @@ Error MessageQueue::push_set(Object *p_object, const StringName &p_prop, const V
 	return push_set(p_object->get_instance_id(), p_prop, p_value);
 }
 
-Error MessageQueue::push_callable(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error) {
+Error MessageQueue::push_callablep(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error) {
 	_THREAD_SAFE_METHOD_
 
 	int room_needed = sizeof(Message) + sizeof(Variant) * p_argcount;
@@ -155,21 +141,6 @@ Error MessageQueue::push_callable(const Callable &p_callable, const Variant **p_
 	return OK;
 }
 
-Error MessageQueue::push_callable(const Callable &p_callable, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS;
-
-	int argc = 0;
-
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		if (argptr[i]->get_type() == Variant::NIL) {
-			break;
-		}
-		argc++;
-	}
-
-	return push_callable(p_callable, argptr, argc);
-}
-
 void MessageQueue::statistics() {
 	Map<StringName, int> set_count;
 	Map<int, int> notify_count;

+ 37 - 6
core/object/message_queue.h

@@ -31,8 +31,11 @@
 #ifndef MESSAGE_QUEUE_H
 #define MESSAGE_QUEUE_H
 
-#include "core/object/class_db.h"
+#include "core/object/object_id.h"
 #include "core/os/thread_safe.h"
+#include "core/variant/variant.h"
+
+class Object;
 
 class MessageQueue {
 	_THREAD_SAFE_CLASS_
@@ -73,14 +76,42 @@ class MessageQueue {
 public:
 	static MessageQueue *get_singleton();
 
-	Error push_call(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error = false);
-	Error push_call(ObjectID p_id, const StringName &p_method, VARIANT_ARG_LIST);
+	Error push_callp(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error = false);
+	template <typename... VarArgs>
+	Error push_call(ObjectID p_id, const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		return push_callp(p_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+
 	Error push_notification(ObjectID p_id, int p_notification);
 	Error push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value);
-	Error push_callable(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error = false);
-	Error push_callable(const Callable &p_callable, VARIANT_ARG_LIST);
+	Error push_callablep(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error = false);
+
+	template <typename... VarArgs>
+	Error push_callable(const Callable &p_callable, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		return push_callablep(p_callable, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+
+	Error push_callp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error = false);
+	template <typename... VarArgs>
+	Error push_call(Object *p_object, const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		return push_callp(p_object, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
 
-	Error push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
 	Error push_notification(Object *p_object, int p_notification);
 	Error push_set(Object *p_object, const StringName &p_prop, const Variant &p_value);
 

+ 8 - 44
core/object/object.cpp

@@ -679,7 +679,7 @@ Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::Cal
 
 	StringName method = *p_args[0];
 
-	return call(method, &p_args[1], p_argcount - 1, r_error);
+	return callp(method, &p_args[1], p_argcount - 1, r_error);
 }
 
 Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
@@ -700,7 +700,7 @@ Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Call
 
 	StringName method = *p_args[0];
 
-	MessageQueue::get_singleton()->push_call(get_instance_id(), method, &p_args[1], p_argcount - 1, true);
+	MessageQueue::get_singleton()->push_callp(get_instance_id(), method, &p_args[1], p_argcount - 1, true);
 
 	return Variant();
 }
@@ -750,31 +750,14 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) {
 	}
 
 	Callable::CallError ce;
-	Variant ret = call(p_method, argptrs, p_args.size(), ce);
+	Variant ret = callp(p_method, argptrs, p_args.size(), ce);
 	if (ce.error != Callable::CallError::CALL_OK) {
 		ERR_FAIL_V_MSG(Variant(), "Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce) + ".");
 	}
 	return ret;
 }
 
-Variant Object::call(const StringName &p_name, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS;
-
-	int argc = 0;
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		if (argptr[i]->get_type() == Variant::NIL) {
-			break;
-		}
-		argc++;
-	}
-
-	Callable::CallError error;
-
-	Variant ret = call(p_name, argptr, argc, error);
-	return ret;
-}
-
-Variant Object::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
 	r_error.error = Callable::CallError::CALL_OK;
 
 	if (p_method == CoreStringNames::get_singleton()->_free) {
@@ -808,7 +791,7 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a
 	OBJ_DEBUG_LOCK
 
 	if (script_instance) {
-		ret = script_instance->call(p_method, p_args, p_argcount, r_error);
+		ret = script_instance->callp(p_method, p_args, p_argcount, r_error);
 		//force jumptable
 		switch (r_error.error) {
 			case Callable::CallError::CALL_OK:
@@ -1027,12 +1010,12 @@ Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::C
 		args = &p_args[1];
 	}
 
-	emit_signal(signal, args, argc);
+	emit_signalp(signal, args, argc);
 
 	return Variant();
 }
 
-Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount) {
+Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int p_argcount) {
 	if (_block_signals) {
 		return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked
 	}
@@ -1091,7 +1074,7 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
 		}
 
 		if (c.flags & CONNECT_DEFERRED) {
-			MessageQueue::get_singleton()->push_callable(c.callable, args, argc, true);
+			MessageQueue::get_singleton()->push_callablep(c.callable, args, argc, true);
 		} else {
 			Callable::CallError ce;
 			_emitting = true;
@@ -1139,21 +1122,6 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
 	return err;
 }
 
-Error Object::emit_signal(const StringName &p_name, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS;
-
-	int argc = 0;
-
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		if (argptr[i]->get_type() == Variant::NIL) {
-			break;
-		}
-		argc++;
-	}
-
-	return emit_signal(p_name, argptr, argc);
-}
-
 void Object::_add_user_signal(const String &p_name, const Array &p_args) {
 	// this version of add_user_signal is meant to be used from scripts or external apis
 	// without access to ADD_SIGNAL in bind_methods
@@ -1648,10 +1616,6 @@ void Object::_bind_methods() {
 	BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED);
 }
 
-void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) {
-	MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS);
-}
-
 void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
 	MessageQueue::get_singleton()->push_set(this, p_property, p_value);
 }

+ 30 - 13
core/object/object.h

@@ -32,6 +32,7 @@
 #define OBJECT_H
 
 #include "core/extension/gdnative_interface.h"
+#include "core/object/message_queue.h"
 #include "core/object/object_id.h"
 #include "core/os/rw_lock.h"
 #include "core/os/spin_lock.h"
@@ -44,14 +45,6 @@
 #include "core/variant/callable_bind.h"
 #include "core/variant/variant.h"
 
-#define VARIANT_ARG_LIST const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant()
-#define VARIANT_ARG_PASS p_arg1, p_arg2, p_arg3, p_arg4, p_arg5, p_arg6, p_arg7, p_arg8
-#define VARIANT_ARG_DECLARE const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5, const Variant &p_arg6, const Variant &p_arg7, const Variant &p_arg8
-#define VARIANT_ARG_MAX 8
-#define VARIANT_ARGPTRS const Variant *argptr[8] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4, &p_arg5, &p_arg6, &p_arg7, &p_arg8 };
-#define VARIANT_ARGPTRS_PASS *argptr[0], *argptr[1], *argptr[2], *argptr[3], *argptr[4], *argptr[5], *argptr[6]], *argptr[7]
-#define VARIANT_ARGS_FROM_ARRAY(m_arr) m_arr[0], m_arr[1], m_arr[2], m_arr[3], m_arr[4], m_arr[5], m_arr[6], m_arr[7]
-
 enum PropertyHint {
 	PROPERTY_HINT_NONE, ///< no hint provided.
 	PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,noslider][,radians][,degrees][,exp][,suffix:<keyword>] range.
@@ -734,8 +727,18 @@ public:
 	bool has_method(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 call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
-	Variant call(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
+	virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+
+	template <typename... VarArgs>
+	Variant call(const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		Callable::CallError cerr;
+		return callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), cerr);
+	}
 
 	void notification(int p_notification, bool p_reversed = false);
 	virtual String to_string();
@@ -769,8 +772,18 @@ public:
 	void set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance);
 
 	void add_user_signal(const MethodInfo &p_signal);
-	Error emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
-	Error emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount);
+
+	template <typename... VarArgs>
+	Error emit_signal(const StringName &p_name, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		return emit_signalp(p_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+
+	Error emit_signalp(const StringName &p_name, const Variant **p_args, int p_argcount);
 	bool has_signal(const StringName &p_name) const;
 	void get_signal_list(List<MethodInfo> *p_signals) const;
 	void get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const;
@@ -782,7 +795,11 @@ public:
 	void disconnect(const StringName &p_signal, const Callable &p_callable);
 	bool is_connected(const StringName &p_signal, const Callable &p_callable) const;
 
-	void call_deferred(const StringName &p_method, VARIANT_ARG_LIST);
+	template <typename... VarArgs>
+	void call_deferred(const StringName &p_name, VarArgs... p_args) {
+		MessageQueue::get_singleton()->push_call(this, p_name, p_args...);
+	}
+
 	void set_deferred(const StringName &p_property, const Variant &p_value);
 
 	void set_block_signals(bool p_block);

+ 0 - 14
core/object/script_language.cpp

@@ -310,20 +310,6 @@ void ScriptInstance::get_property_state(List<Pair<StringName, Variant>> &state)
 	}
 }
 
-Variant ScriptInstance::call(const StringName &p_method, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS;
-	int argc = 0;
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		if (argptr[i]->get_type() == Variant::NIL) {
-			break;
-		}
-		argc++;
-	}
-
-	Callable::CallError error;
-	return call(p_method, argptr, argc, error);
-}
-
 void ScriptInstance::property_set_fallback(const StringName &, const Variant &, bool *r_valid) {
 	if (r_valid) {
 		*r_valid = false;

+ 16 - 4
core/object/script_language.h

@@ -176,8 +176,20 @@ public:
 
 	virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
 	virtual bool has_method(const StringName &p_method) const = 0;
-	virtual Variant call(const StringName &p_method, VARIANT_ARG_LIST);
-	virtual Variant call(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>
+	Variant call(const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		Callable::CallError cerr;
+		return callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), cerr);
+	}
+
 	virtual void notification(int p_notification) = 0;
 	virtual String to_string(bool *r_valid) {
 		if (r_valid) {
@@ -419,8 +431,8 @@ public:
 
 	virtual void get_method_list(List<MethodInfo> *p_list) const;
 	virtual bool has_method(const StringName &p_method) const;
-	virtual Variant call(const StringName &p_method, VARIANT_ARG_LIST) { return Variant(); }
-	virtual Variant call(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) {
 		r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
 		return Variant();
 	}

+ 14 - 35
core/object/undo_redo.cpp

@@ -126,8 +126,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
 	force_keep_in_merge_ends = false;
 }
 
-void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS
+void UndoRedo::add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
 	ERR_FAIL_COND(p_object == nullptr);
 	ERR_FAIL_COND(action_level <= 0);
 	ERR_FAIL_COND((current_action + 1) >= actions.size());
@@ -140,14 +139,13 @@ void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIA
 	do_op.type = Operation::TYPE_METHOD;
 	do_op.name = p_method;
 
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		do_op.args[i] = *argptr[i];
+	for (int i = 0; i < p_argcount; i++) {
+		do_op.args.push_back(*p_args[i]);
 	}
 	actions.write[current_action + 1].do_ops.push_back(do_op);
 }
 
-void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS
+void UndoRedo::add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
 	ERR_FAIL_COND(p_object == nullptr);
 	ERR_FAIL_COND(action_level <= 0);
 	ERR_FAIL_COND((current_action + 1) >= actions.size());
@@ -167,8 +165,8 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR
 	undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
 	undo_op.name = p_method;
 
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		undo_op.args[i] = *argptr[i];
+	for (int i = 0; i < p_argcount; i++) {
+		undo_op.args.push_back(*p_args[i]);
 	}
 	actions.write[current_action + 1].undo_ops.push_back(undo_op);
 }
@@ -185,7 +183,7 @@ void UndoRedo::add_do_property(Object *p_object, const StringName &p_property, c
 
 	do_op.type = Operation::TYPE_PROPERTY;
 	do_op.name = p_property;
-	do_op.args[0] = p_value;
+	do_op.args.push_back(p_value);
 	actions.write[current_action + 1].do_ops.push_back(do_op);
 }
 
@@ -208,7 +206,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property,
 	undo_op.type = Operation::TYPE_PROPERTY;
 	undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
 	undo_op.name = p_property;
-	undo_op.args[0] = p_value;
+	undo_op.args.push_back(p_value);
 	actions.write[current_action + 1].undo_ops.push_back(undo_op);
 }
 
@@ -315,20 +313,15 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
 		switch (op.type) {
 			case Operation::TYPE_METHOD: {
 				Vector<const Variant *> argptrs;
-				argptrs.resize(VARIANT_ARG_MAX);
+				argptrs.resize(op.args.size());
 				int argc = 0;
 
-				for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-					if (op.args[i].get_type() == Variant::NIL) {
-						break;
-					}
+				for (int i = 0; i < op.args.size(); i++) {
 					argptrs.write[i] = &op.args[i];
-					argc++;
 				}
-				argptrs.resize(argc);
 
 				Callable::CallError ce;
-				obj->call(op.name, (const Variant **)argptrs.ptr(), argc, ce);
+				obj->callp(op.name, (const Variant **)argptrs.ptr(), argc, ce);
 				if (ce.error != Callable::CallError::CALL_OK) {
 					ERR_PRINT("Error calling method from signal '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, (const Variant **)argptrs.ptr(), argc, ce));
 				}
@@ -341,7 +334,7 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
 #endif
 
 				if (method_callback) {
-					method_callback(method_callbck_ud, obj, op.name, VARIANT_ARGS_FROM_ARRAY(op.args));
+					method_callback(method_callbck_ud, obj, op.name, (const Variant **)argptrs.ptr(), argc);
 				}
 			} break;
 			case Operation::TYPE_PROPERTY: {
@@ -477,14 +470,7 @@ Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callabl
 	Object *object = *p_args[0];
 	StringName method = *p_args[1];
 
-	Variant v[VARIANT_ARG_MAX];
-
-	for (int i = 0; i < MIN(VARIANT_ARG_MAX, p_argcount - 2); ++i) {
-		v[i] = *p_args[i + 2];
-	}
-
-	static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
-	add_do_method(object, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+	add_do_methodp(object, method, p_args + 2, p_argcount - 2);
 	return Variant();
 }
 
@@ -514,14 +500,7 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla
 	Object *object = *p_args[0];
 	StringName method = *p_args[1];
 
-	Variant v[VARIANT_ARG_MAX];
-
-	for (int i = 0; i < MIN(VARIANT_ARG_MAX, p_argcount - 2); ++i) {
-		v[i] = *p_args[i + 2];
-	}
-
-	static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
-	add_undo_method(object, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+	add_undo_methodp(object, method, p_args + 2, p_argcount - 2);
 	return Variant();
 }
 

+ 26 - 4
core/object/undo_redo.h

@@ -49,7 +49,7 @@ public:
 	Variant _add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
 	Variant _add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
 
-	typedef void (*MethodNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE);
+	typedef void (*MethodNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount);
 	typedef void (*PropertyNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
 
 private:
@@ -65,7 +65,7 @@ private:
 		Ref<RefCounted> ref;
 		ObjectID object;
 		StringName name;
-		Variant args[VARIANT_ARG_MAX];
+		Vector<Variant> args;
 
 		void delete_reference();
 	};
@@ -106,8 +106,30 @@ protected:
 public:
 	void create_action(const String &p_name = "", MergeMode p_mode = MERGE_DISABLE);
 
-	void add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
-	void add_undo_method(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
+	void add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
+	void add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
+
+	template <typename... VarArgs>
+	void add_do_method(Object *p_object, const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+
+		add_do_methodp(p_object, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+	template <typename... VarArgs>
+	void add_undo_method(Object *p_object, const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+
+		add_undo_methodp(p_object, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+
 	void add_do_property(Object *p_object, const StringName &p_property, const Variant &p_value);
 	void add_undo_property(Object *p_object, const StringName &p_property, const Variant &p_value);
 	void add_do_reference(Object *p_object);

+ 3 - 3
core/variant/binder_common.h

@@ -182,7 +182,7 @@ struct VariantCasterAndValidate {
 	static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
 		Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
 		if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
-				!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+				!VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
 			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
 			r_error.argument = p_arg_idx;
 			r_error.expected = argtype;
@@ -197,7 +197,7 @@ struct VariantCasterAndValidate<T &> {
 	static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
 		Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
 		if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
-				!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+				!VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
 			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
 			r_error.argument = p_arg_idx;
 			r_error.expected = argtype;
@@ -212,7 +212,7 @@ struct VariantCasterAndValidate<const T &> {
 	static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
 		Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
 		if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
-				!VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) {
+				!VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
 			r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
 			r_error.argument = p_arg_idx;
 			r_error.expected = argtype;

+ 3 - 3
core/variant/callable.cpp

@@ -37,7 +37,7 @@
 #include "core/object/script_language.h"
 
 void Callable::call_deferred(const Variant **p_arguments, int p_argcount) const {
-	MessageQueue::get_singleton()->push_callable(*this, p_arguments, p_argcount);
+	MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount);
 }
 
 void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const {
@@ -59,7 +59,7 @@ void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_retu
 			return;
 		}
 #endif
-		r_return_value = obj->call(method, p_arguments, p_argcount, r_call_error);
+		r_return_value = obj->callp(method, p_arguments, p_argcount, r_call_error);
 	}
 }
 
@@ -379,7 +379,7 @@ Error Signal::emit(const Variant **p_arguments, int p_argcount) const {
 		return ERR_INVALID_DATA;
 	}
 
-	return obj->emit_signal(name, p_arguments, p_argcount);
+	return obj->emit_signalp(name, p_arguments, p_argcount);
 }
 
 Error Signal::connect(const Callable &p_callable, uint32_t p_flags) {

+ 2 - 18
core/variant/variant.cpp

@@ -1972,7 +1972,7 @@ Variant::operator ::RID() const {
 		}
 #endif
 		Callable::CallError ce;
-		Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce);
+		Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce);
 		if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::RID) {
 			return ret;
 		}
@@ -3309,21 +3309,7 @@ bool Variant::is_shared() const {
 	return false;
 }
 
-Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS;
-	int argc = 0;
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		if (argptr[i]->get_type() == Variant::NIL) {
-			break;
-		}
-		argc++;
-	}
-
-	Callable::CallError error;
-
-	Variant ret;
-	call(p_method, argptr, argc, ret, error);
-
+void Variant::_variant_call_error(const String &p_method, Callable::CallError &error) {
 	switch (error.error) {
 		case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
 			String err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(Variant::Type(error.expected)) + "'.";
@@ -3341,8 +3327,6 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) {
 		default: {
 		}
 	}
-
-	return ret;
 }
 
 void Variant::construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct, void *p_construct_ud) {

+ 25 - 2
core/variant/variant.h

@@ -282,6 +282,14 @@ private:
 	static void _register_variant_utility_functions();
 	static void _unregister_variant_utility_functions();
 
+	void _variant_call_error(const String &p_method, Callable::CallError &error);
+
+	// Avoid accidental conversion. If you reached this point, it's because you most likely forgot to dereference
+	// a Variant pointer (so add * like this: *variant_pointer).
+
+	Variant(const Variant *) {}
+	Variant(const Variant **) {}
+
 public:
 	_FORCE_INLINE_ Type get_type() const {
 		return type;
@@ -527,8 +535,23 @@ public:
 	static int get_builtin_method_count(Variant::Type p_type);
 	static uint32_t get_builtin_method_hash(Variant::Type p_type, const StringName &p_method);
 
-	void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
-	Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant());
+	void callp(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
+
+	template <typename... VarArgs>
+	Variant call(const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		Callable::CallError cerr;
+		Variant ret;
+		callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), ret, cerr);
+		if (cerr.error != Callable::CallError::CALL_OK) {
+			_variant_call_error(p_method, cerr);
+		}
+		return ret;
+	}
 
 	static void call_static(Variant::Type p_type, const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
 

+ 2 - 2
core/variant/variant_call.cpp

@@ -1003,7 +1003,7 @@ static void register_builtin_method(const Vector<String> &p_argnames, const Vect
 	builtin_method_names[T::get_base_type()].push_back(name);
 }
 
-void Variant::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
+void Variant::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
 	if (type == Variant::OBJECT) {
 		//call object
 		Object *obj = _get_obj().obj;
@@ -1018,7 +1018,7 @@ void Variant::call(const StringName &p_method, const Variant **p_args, int p_arg
 		}
 
 #endif
-		r_ret = _get_obj().obj->call(p_method, p_args, p_argcount, r_error);
+		r_ret = _get_obj().obj->callp(p_method, p_args, p_argcount, r_error);
 
 		//else if (type==Variant::METHOD) {
 	} else {

+ 3 - 3
core/variant/variant_setget.cpp

@@ -1277,7 +1277,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
 			ref.push_back(r_iter);
 			Variant vref = ref;
 			const Variant *refp[] = { &vref };
-			Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce);
+			Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce);
 
 			if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
 				valid = false;
@@ -1504,7 +1504,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
 			ref.push_back(r_iter);
 			Variant vref = ref;
 			const Variant *refp[] = { &vref };
-			Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce);
+			Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce);
 
 			if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
 				valid = false;
@@ -1686,7 +1686,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
 			Callable::CallError ce;
 			ce.error = Callable::CallError::CALL_OK;
 			const Variant *refp[] = { &r_iter };
-			Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce);
+			Variant ret = _get_obj().obj->callp(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce);
 
 			if (ce.error != Callable::CallError::CALL_OK) {
 				r_valid = false;

+ 4 - 5
editor/animation_track_editor.cpp

@@ -606,8 +606,7 @@ public:
 			} break;
 			case Animation::TYPE_METHOD: {
 				p_list->push_back(PropertyInfo(Variant::STRING_NAME, "name"));
-				static_assert(VARIANT_ARG_MAX == 8, "PROPERTY_HINT_RANGE needs to be updated if VARIANT_ARG_MAX != 8");
-				p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,8,1"));
+				p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,32,1,or_greater"));
 
 				Dictionary d = animation->track_get_key_value(track, key);
 				ERR_FAIL_COND(!d.has("args"));
@@ -1287,8 +1286,8 @@ public:
 				} break;
 				case Animation::TYPE_METHOD: {
 					p_list->push_back(PropertyInfo(Variant::STRING_NAME, "name"));
-					static_assert(VARIANT_ARG_MAX == 8, "PROPERTY_HINT_RANGE needs to be updated if VARIANT_ARG_MAX != 8");
-					p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,8,1"));
+
+					p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,32,1,or_greater"));
 
 					Dictionary d = animation->track_get_key_value(first_track, first_key);
 					ERR_FAIL_COND(!d.has("args"));
@@ -3189,7 +3188,7 @@ AnimationTrackEdit *AnimationTrackEditPlugin::create_value_track_edit(Object *p_
 		};
 
 		Callable::CallError ce;
-		return Object::cast_to<AnimationTrackEdit>(get_script_instance()->call("create_value_track_edit", (const Variant **)&argptrs, 6, ce).operator Object *());
+		return Object::cast_to<AnimationTrackEdit>(get_script_instance()->callp("create_value_track_edit", (const Variant **)&argptrs, 6, ce).operator Object *());
 	}
 	return nullptr;
 }

+ 0 - 3
editor/connections_dialog.cpp

@@ -180,9 +180,6 @@ void ConnectDialog::_unbind_count_changed(double p_count) {
  * Adds a new parameter bind to connection.
  */
 void ConnectDialog::_add_bind() {
-	if (cdbinds->params.size() >= VARIANT_ARG_MAX) {
-		return;
-	}
 	Variant::Type vt = (Variant::Type)type_list->get_item_id(type_list->get_selected());
 
 	Variant value;

+ 2 - 2
editor/debugger/editor_debugger_node.cpp

@@ -610,12 +610,12 @@ void EditorDebuggerNode::_save_node_requested(ObjectID p_id, const String &p_fil
 }
 
 // Remote inspector/edit.
-void EditorDebuggerNode::_method_changeds(void *p_ud, Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE) {
+void EditorDebuggerNode::_method_changeds(void *p_ud, Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount) {
 	if (!singleton) {
 		return;
 	}
 	_for_all(singleton->tabs, [&](ScriptEditorDebugger *dbg) {
-		dbg->_method_changed(p_base, p_name, VARIANT_ARG_PASS);
+		dbg->_method_changed(p_base, p_name, p_args, p_argcount);
 	});
 }
 

+ 1 - 1
editor/debugger/editor_debugger_node.h

@@ -171,7 +171,7 @@ public:
 
 	// Remote inspector/edit.
 	void request_remote_tree();
-	static void _method_changeds(void *p_ud, Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE);
+	static void _method_changeds(void *p_ud, Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount);
 	static void _property_changeds(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
 
 	// LiveDebug

+ 7 - 9
editor/debugger/script_editor_debugger.cpp

@@ -1064,18 +1064,16 @@ int ScriptEditorDebugger::_get_res_path_cache(const String &p_path) {
 	return last_path_id;
 }
 
-void ScriptEditorDebugger::_method_changed(Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE) {
+void ScriptEditorDebugger::_method_changed(Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount) {
 	if (!p_base || !live_debug || !is_session_active() || !EditorNode::get_singleton()->get_edited_scene()) {
 		return;
 	}
 
 	Node *node = Object::cast_to<Node>(p_base);
 
-	VARIANT_ARGPTRS
-
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
+	for (int i = 0; i < p_argcount; i++) {
 		//no pointers, sorry
-		if (argptr[i] && (argptr[i]->get_type() == Variant::OBJECT || argptr[i]->get_type() == Variant::RID)) {
+		if (p_args[i]->get_type() == Variant::OBJECT || p_args[i]->get_type() == Variant::RID) {
 			return;
 		}
 	}
@@ -1087,9 +1085,9 @@ void ScriptEditorDebugger::_method_changed(Object *p_base, const StringName &p_n
 		Array msg;
 		msg.push_back(pathid);
 		msg.push_back(p_name);
-		for (int i = 0; i < VARIANT_ARG_MAX; i++) {
+		for (int i = 0; i < p_argcount; i++) {
 			//no pointers, sorry
-			msg.push_back(*argptr[i]);
+			msg.push_back(*p_args[i]);
 		}
 		_put_msg("scene:live_node_call", msg);
 
@@ -1105,9 +1103,9 @@ void ScriptEditorDebugger::_method_changed(Object *p_base, const StringName &p_n
 		Array msg;
 		msg.push_back(pathid);
 		msg.push_back(p_name);
-		for (int i = 0; i < VARIANT_ARG_MAX; i++) {
+		for (int i = 0; i < p_argcount; i++) {
 			//no pointers, sorry
-			msg.push_back(*argptr[i]);
+			msg.push_back(*p_args[i]);
 		}
 		_put_msg("scene:live_res_call", msg);
 

+ 1 - 1
editor/debugger/script_editor_debugger.h

@@ -187,7 +187,7 @@ private:
 	void _live_edit_set();
 	void _live_edit_clear();
 
-	void _method_changed(Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE);
+	void _method_changed(Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount);
 	void _property_changed(Object *p_base, const StringName &p_property, const Variant &p_value);
 
 	void _error_activated();

+ 3 - 3
editor/editor_inspector.cpp

@@ -99,7 +99,7 @@ void EditorProperty::emit_changed(const StringName &p_property, const Variant &p
 	const Variant *argptrs[4] = { &args[0], &args[1], &args[2], &args[3] };
 
 	cache[p_property] = p_value;
-	emit_signal(SNAME("property_changed"), (const Variant **)argptrs, 4);
+	emit_signalp(SNAME("property_changed"), (const Variant **)argptrs, 4);
 }
 
 void EditorProperty::_notification(int p_what) {
@@ -3314,7 +3314,7 @@ void EditorInspector::_property_keyed(const String &p_path, bool p_advance) {
 	// The second parameter could be null, causing the event to fire with less arguments, so use the pointer call which preserves it.
 	const Variant args[3] = { p_path, object->get(p_path), p_advance };
 	const Variant *argp[3] = { &args[0], &args[1], &args[2] };
-	emit_signal(SNAME("property_keyed"), argp, 3);
+	emit_signalp(SNAME("property_keyed"), argp, 3);
 }
 
 void EditorInspector::_property_deleted(const String &p_path) {
@@ -3333,7 +3333,7 @@ void EditorInspector::_property_keyed_with_value(const String &p_path, const Var
 	// The second parameter could be null, causing the event to fire with less arguments, so use the pointer call which preserves it.
 	const Variant args[3] = { p_path, p_value, p_advance };
 	const Variant *argp[3] = { &args[0], &args[1], &args[2] };
-	emit_signal(SNAME("property_keyed"), argp, 3);
+	emit_signalp(SNAME("property_keyed"), argp, 3);
 }
 
 void EditorInspector::_property_checked(const String &p_path, bool p_checked) {

+ 1 - 1
editor/editor_properties.cpp

@@ -3059,7 +3059,7 @@ void EditorPropertyResource::_sub_inspector_property_keyed(const String &p_prope
 	// The second parameter could be null, causing the event to fire with less arguments, so use the pointer call which preserves it.
 	const Variant args[3] = { String(get_edited_property()) + ":" + p_property, p_value, p_advance };
 	const Variant *argp[3] = { &args[0], &args[1], &args[2] };
-	emit_signal(SNAME("property_keyed_with_value"), argp, 3);
+	emit_signalp(SNAME("property_keyed_with_value"), argp, 3);
 }
 
 void EditorPropertyResource::_sub_inspector_resource_selected(const RES &p_resource, const String &p_property) {

+ 6 - 6
modules/gdscript/gdscript.cpp

@@ -938,7 +938,7 @@ const Vector<Multiplayer::RPCConfig> GDScript::get_rpc_methods() const {
 	return rpc_functions;
 }
 
-Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant GDScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
 	GDScript *top = this;
 	while (top) {
 		Map<StringName, GDScriptFunction *>::Element *E = top->member_functions.find(p_method);
@@ -952,7 +952,7 @@ Variant GDScript::call(const StringName &p_method, const Variant **p_args, int p
 
 	//none found, regular
 
-	return Script::call(p_method, p_args, p_argcount, r_error);
+	return Script::callp(p_method, p_args, p_argcount, r_error);
 }
 
 bool GDScript::_get(const StringName &p_name, Variant &r_ret) const {
@@ -1273,7 +1273,7 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
 			if (member->setter) {
 				const Variant *val = &p_value;
 				Callable::CallError err;
-				call(member->setter, &val, 1, err);
+				callp(member->setter, &val, 1, err);
 				if (err.error == Callable::CallError::CALL_OK) {
 					return true; //function exists, call was successful
 				} else {
@@ -1335,7 +1335,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
 			if (E) {
 				if (E->get().getter) {
 					Callable::CallError err;
-					r_ret = const_cast<GDScriptInstance *>(this)->call(E->get().getter, nullptr, 0, err);
+					r_ret = const_cast<GDScriptInstance *>(this)->callp(E->get().getter, nullptr, 0, err);
 					if (err.error == Callable::CallError::CALL_OK) {
 						return true;
 					}
@@ -1520,7 +1520,7 @@ bool GDScriptInstance::has_method(const StringName &p_method) const {
 	return false;
 }
 
-Variant GDScriptInstance::call(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();
 	while (sptr) {
 		Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method);
@@ -1555,7 +1555,7 @@ void GDScriptInstance::notification(int p_notification) {
 String GDScriptInstance::to_string(bool *r_valid) {
 	if (has_method(CoreStringNames::get_singleton()->_to_string)) {
 		Callable::CallError ce;
-		Variant ret = call(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce);
+		Variant ret = callp(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce);
 		if (ce.error == Callable::CallError::CALL_OK) {
 			if (ret.get_type() != Variant::STRING) {
 				if (r_valid) {

+ 2 - 2
modules/gdscript/gdscript.h

@@ -166,7 +166,7 @@ protected:
 	bool _set(const StringName &p_name, const Variant &p_value);
 	void _get_property_list(List<PropertyInfo> *p_properties) const;
 
-	Variant call(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;
 
 	static void _bind_methods();
 
@@ -285,7 +285,7 @@ public:
 
 	virtual void get_method_list(List<MethodInfo> *p_list) const;
 	virtual bool has_method(const StringName &p_method) const;
-	virtual Variant call(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]; }
 

+ 1 - 1
modules/gdscript/gdscript_rpc_callable.cpp

@@ -64,7 +64,7 @@ ObjectID GDScriptRPCCallable::get_object() 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->call(method, p_arguments, p_argcount, r_call_error);
+	r_return_value = object->callp(method, p_arguments, p_argcount, r_call_error);
 }
 
 GDScriptRPCCallable::GDScriptRPCCallable(Object *p_object, const StringName &p_method) {

+ 8 - 8
modules/gdscript/gdscript_vm.cpp

@@ -1447,7 +1447,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				const StringName native_type = _global_names_ptr[native_type_idx];
 
 				Array array;
-				array.set_typed(builtin_type, native_type, script_type);
+				array.set_typed(builtin_type, native_type, *script_type);
 				array.resize(argc);
 
 				for (int i = 0; i < argc; i++) {
@@ -1517,7 +1517,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				Callable::CallError err;
 				if (call_ret) {
 					GET_INSTRUCTION_ARG(ret, argc + 1);
-					base->call(*methodname, (const Variant **)argptrs, argc, *ret, err);
+					base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
 #ifdef DEBUG_ENABLED
 					if (!call_async && ret->get_type() == Variant::OBJECT) {
 						// Check if getting a function state without await.
@@ -1536,7 +1536,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 #endif
 				} else {
 					Variant ret;
-					base->call(*methodname, (const Variant **)argptrs, argc, ret, err);
+					base->callp(*methodname, (const Variant **)argptrs, argc, ret, err);
 				}
 #ifdef DEBUG_ENABLED
 				if (GDScriptLanguage::get_singleton()->profiling) {
@@ -2340,7 +2340,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				}
 
 				Array array;
-				array.set_typed(builtin_type, native_type, script_type);
+				array.set_typed(builtin_type, native_type, *script_type);
 
 #ifdef DEBUG_ENABLED
 				bool valid = array.typed_assign(*VariantInternal::get_array(r));
@@ -2810,7 +2810,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				args[0] = &vref;
 
 				Callable::CallError ce;
-				Variant has_next = obj->call(CoreStringNames::get_singleton()->_iter_init, (const Variant **)args, 1, ce);
+				Variant has_next = obj->callp(CoreStringNames::get_singleton()->_iter_init, (const Variant **)args, 1, ce);
 
 #ifdef DEBUG_ENABLED
 				if (ce.error != Callable::CallError::CALL_OK) {
@@ -2824,7 +2824,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 					ip = jumpto;
 				} else {
 					GET_INSTRUCTION_ARG(iterator, 2);
-					*iterator = obj->call(CoreStringNames::get_singleton()->_iter_get, (const Variant **)args, 1, ce);
+					*iterator = obj->callp(CoreStringNames::get_singleton()->_iter_get, (const Variant **)args, 1, ce);
 #ifdef DEBUG_ENABLED
 					if (ce.error != Callable::CallError::CALL_OK) {
 						err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
@@ -3141,7 +3141,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				args[0] = &vref;
 
 				Callable::CallError ce;
-				Variant has_next = obj->call(CoreStringNames::get_singleton()->_iter_next, (const Variant **)args, 1, ce);
+				Variant has_next = obj->callp(CoreStringNames::get_singleton()->_iter_next, (const Variant **)args, 1, ce);
 
 #ifdef DEBUG_ENABLED
 				if (ce.error != Callable::CallError::CALL_OK) {
@@ -3155,7 +3155,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 					ip = jumpto;
 				} else {
 					GET_INSTRUCTION_ARG(iterator, 2);
-					*iterator = obj->call(CoreStringNames::get_singleton()->_iter_get, (const Variant **)args, 1, ce);
+					*iterator = obj->callp(CoreStringNames::get_singleton()->_iter_get, (const Variant **)args, 1, ce);
 #ifdef DEBUG_ENABLED
 					if (ce.error != Callable::CallError::CALL_OK) {
 						err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);

+ 1 - 1
modules/gdscript/tests/gdscript_test_runner.cpp

@@ -573,7 +573,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
 
 	// Call test function.
 	Callable::CallError call_err;
-	instance->call(GDScriptTestRunner::test_function_name, nullptr, 0, call_err);
+	instance->callp(GDScriptTestRunner::test_function_name, nullptr, 0, call_err);
 
 	// Tear down output handlers.
 	remove_print_handler(&_print_handler);

+ 3 - 3
modules/mono/csharp_script.cpp

@@ -1893,7 +1893,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
 	return false;
 }
 
-Variant CSharpInstance::call(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());
 
 	GD_MONO_SCOPE_THREAD_ATTACH;
@@ -2908,7 +2908,7 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
 }
 #endif
 
-Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant CSharpScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
 	if (unlikely(GDMono::get_singleton() == nullptr)) {
 		// Probably not the best error but eh.
 		r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
@@ -2936,7 +2936,7 @@ Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, i
 	}
 
 	// No static method found. Try regular instance calls
-	return Script::call(p_method, p_args, p_argcount, r_error);
+	return Script::callp(p_method, p_args, p_argcount, r_error);
 }
 
 void CSharpScript::_resource_path_changed() {

+ 2 - 2
modules/mono/csharp_script.h

@@ -184,7 +184,7 @@ private:
 protected:
 	static void _bind_methods();
 
-	Variant call(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 _resource_path_changed() override;
 	bool _get(const StringName &p_name, Variant &r_ret) const;
 	bool _set(const StringName &p_name, const Variant &p_value);
@@ -295,7 +295,7 @@ public:
 
 	void get_method_list(List<MethodInfo> *p_list) const override;
 	bool has_method(const StringName &p_method) const override;
-	Variant call(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(MonoObject *p_obj);
 

+ 1 - 1
modules/mono/glue/base_object_glue.cpp

@@ -199,7 +199,7 @@ MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoStrin
 	}
 
 	Callable::CallError error;
-	Variant result = p_ptr->call(StringName(name), args.ptr(), argc, error);
+	Variant result = p_ptr->callp(StringName(name), args.ptr(), argc, error);
 
 	*r_result = GDMonoMarshal::variant_to_mono_object(result);
 

+ 1 - 1
modules/navigation/rvo_agent.cpp

@@ -75,5 +75,5 @@ void RvoAgent::dispatch_callback() {
 
 	const Variant *vp[2] = { &callback.new_velocity, &callback.udata };
 	int argc = (callback.udata.get_type() == Variant::NIL) ? 1 : 2;
-	obj->call(callback.method, vp, argc, responseCallError);
+	obj->callp(callback.method, vp, argc, responseCallError);
 }

+ 1 - 1
modules/visual_script/editor/visual_script_editor.cpp

@@ -1621,7 +1621,7 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) {
 	conn_map.get_key_list(&keys);
 	for (const int &E : keys) {
 		for (const Set<int>::Element *F = conn_map[E].front(); F; F = F->next()) {
-			undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E, F);
+			undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E, F->get());
 		}
 	}
 

+ 3 - 3
modules/visual_script/visual_script.cpp

@@ -1705,7 +1705,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p
 	return return_value;
 }
 
-Variant VisualScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant VisualScriptInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
 	r_error.error = Callable::CallError::CALL_OK; //ok by default
 
 	Map<StringName, Function>::Element *F = functions.find(p_method);
@@ -1798,13 +1798,13 @@ void VisualScriptInstance::notification(int p_notification) {
 	Variant what = p_notification;
 	const Variant *whatp = &what;
 	Callable::CallError ce;
-	call(VisualScriptLanguage::singleton->notification, &whatp, 1, ce); // Do as call.
+	callp(VisualScriptLanguage::singleton->notification, &whatp, 1, ce); // Do as call.
 }
 
 String VisualScriptInstance::to_string(bool *r_valid) {
 	if (has_method(CoreStringNames::get_singleton()->_to_string)) {
 		Callable::CallError ce;
-		Variant ret = call(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce);
+		Variant ret = callp(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce);
 		if (ce.error == Callable::CallError::CALL_OK) {
 			if (ret.get_type() != Variant::STRING) {
 				if (r_valid) {

+ 1 - 1
modules/visual_script/visual_script.h

@@ -410,7 +410,7 @@ public:
 
 	virtual void get_method_list(List<MethodInfo> *p_list) const;
 	virtual bool has_method(const StringName &p_method) const;
-	virtual Variant call(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);
 	virtual void notification(int p_notification);
 	String to_string(bool *r_valid);
 

+ 1 - 1
modules/visual_script/visual_script_expression.cpp

@@ -1500,7 +1500,7 @@ public:
 					argp.write[i] = &arr[i];
 				}
 
-				base.call(call->method, (const Variant **)argp.ptr(), argp.size(), r_ret, ce);
+				base.callp(call->method, (const Variant **)argp.ptr(), argp.size(), r_ret, ce);
 
 				if (ce.error != Callable::CallError::CALL_OK) {
 					r_error_str = "On call to '" + String(call->method) + "':";

+ 11 - 11
modules/visual_script/visual_script_func_nodes.cpp

@@ -772,9 +772,9 @@ public:
 				if (rpc_mode) {
 					call_rpc(object, p_inputs, input_args);
 				} else if (returns) {
-					*p_outputs[0] = object->call(function, p_inputs, input_args, r_error);
+					*p_outputs[0] = object->callp(function, p_inputs, input_args, r_error);
 				} else {
-					object->call(function, p_inputs, input_args, r_error);
+					object->callp(function, p_inputs, input_args, r_error);
 				}
 			} break;
 			case VisualScriptFunctionCall::CALL_MODE_NODE_PATH: {
@@ -795,9 +795,9 @@ public:
 				if (rpc_mode) {
 					call_rpc(node, p_inputs, input_args);
 				} else if (returns) {
-					*p_outputs[0] = another->call(function, p_inputs, input_args, r_error);
+					*p_outputs[0] = another->callp(function, p_inputs, input_args, r_error);
 				} else {
-					another->call(function, p_inputs, input_args, r_error);
+					another->callp(function, p_inputs, input_args, r_error);
 				}
 
 			} break;
@@ -813,21 +813,21 @@ public:
 				} else if (returns) {
 					if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
 						if (returns >= 2) {
-							v.call(function, p_inputs + 1, input_args, *p_outputs[1], r_error);
+							v.callp(function, p_inputs + 1, input_args, *p_outputs[1], r_error);
 						} else if (returns == 1) {
 							Variant ret;
-							v.call(function, p_inputs + 1, input_args, ret, r_error);
+							v.callp(function, p_inputs + 1, input_args, ret, r_error);
 						} else {
 							r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
 							r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE";
 							return 0;
 						}
 					} else {
-						v.call(function, p_inputs + 1, input_args, *p_outputs[0], r_error);
+						v.callp(function, p_inputs + 1, input_args, *p_outputs[0], r_error);
 					}
 				} else {
 					Variant ret;
-					v.call(function, p_inputs + 1, input_args, ret, r_error);
+					v.callp(function, p_inputs + 1, input_args, ret, r_error);
 				}
 
 				if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
@@ -846,9 +846,9 @@ public:
 				if (rpc_mode) {
 					call_rpc(object, p_inputs, input_args);
 				} else if (returns) {
-					*p_outputs[0] = object->call(function, p_inputs, input_args, r_error);
+					*p_outputs[0] = object->callp(function, p_inputs, input_args, r_error);
 				} else {
-					object->call(function, p_inputs, input_args, r_error);
+					object->callp(function, p_inputs, input_args, r_error);
 				}
 			} break;
 		}
@@ -2373,7 +2373,7 @@ public:
 	virtual int step(const Variant **p_inputs, Variant **p_outputs, StartMode p_start_mode, Variant *p_working_mem, Callable::CallError &r_error, String &r_error_str) {
 		Object *obj = instance->get_owner_ptr();
 
-		obj->emit_signal(name, p_inputs, argcount);
+		obj->emit_signalp(name, p_inputs, argcount);
 
 		return 0;
 	}

+ 1 - 1
modules/visual_script/visual_script_nodes.cpp

@@ -3174,7 +3174,7 @@ public:
 			r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
 			return 0;
 		}
-		*p_outputs[0] = subcall->call(VisualScriptLanguage::singleton->_subcall, p_inputs, input_args, r_error);
+		*p_outputs[0] = subcall->callp(VisualScriptLanguage::singleton->_subcall, p_inputs, input_args, r_error);
 		return 0;
 	}
 };

+ 2 - 2
platform/android/api/api.cpp

@@ -64,14 +64,14 @@ void JavaClassWrapper::_bind_methods() {
 
 #if !defined(ANDROID_ENABLED)
 
-Variant JavaClass::call(const StringName &, const Variant **, int, Callable::CallError &) {
+Variant JavaClass::callp(const StringName &, const Variant **, int, Callable::CallError &) {
 	return Variant();
 }
 
 JavaClass::JavaClass() {
 }
 
-Variant JavaObject::call(const StringName &, const Variant **, int, Callable::CallError &) {
+Variant JavaObject::callp(const StringName &, const Variant **, int, Callable::CallError &) {
 	return Variant();
 }
 

+ 2 - 2
platform/android/api/java_class_wrapper.h

@@ -179,7 +179,7 @@ class JavaClass : public RefCounted {
 #endif
 
 public:
-	virtual Variant call(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;
 
 	JavaClass();
 };
@@ -195,7 +195,7 @@ class JavaObject : public RefCounted {
 #endif
 
 public:
-	virtual Variant call(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;
 
 #ifdef ANDROID_ENABLED
 	JavaObject(const Ref<JavaClass> &p_base, jobject *p_instance);

+ 3 - 3
platform/android/api/jni_singleton.h

@@ -52,7 +52,7 @@ class JNISingleton : public Object {
 #endif
 
 public:
-	virtual Variant call(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 {
 #ifdef ANDROID_ENABLED
 		Map<StringName, MethodData>::Element *E = method_map.find(p_method);
 
@@ -70,7 +70,7 @@ public:
 
 		if (call_error) {
 			// The method is not in this map, defaulting to the regular instance calls.
-			return Object::call(p_method, p_args, p_argcount, r_error);
+			return Object::callp(p_method, p_args, p_argcount, r_error);
 		}
 
 		ERR_FAIL_COND_V(!instance, Variant());
@@ -176,7 +176,7 @@ public:
 #else // ANDROID_ENABLED
 
 		// Defaulting to the regular instance calls.
-		return Object::call(p_method, p_args, p_argcount, r_error);
+		return Object::callp(p_method, p_args, p_argcount, r_error);
 #endif
 	}
 

+ 3 - 3
platform/android/java_class_wrapper.cpp

@@ -485,14 +485,14 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
 	return success;
 }
 
-Variant JavaClass::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant JavaClass::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
 	Variant ret;
 	bool found = _call_method(nullptr, p_method, p_args, p_argcount, r_error, ret);
 	if (found) {
 		return ret;
 	}
 
-	return RefCounted::call(p_method, p_args, p_argcount, r_error);
+	return RefCounted::callp(p_method, p_args, p_argcount, r_error);
 }
 
 JavaClass::JavaClass() {
@@ -500,7 +500,7 @@ JavaClass::JavaClass() {
 
 /////////////////////
 
-Variant JavaObject::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant JavaObject::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
 	return Variant();
 }
 

+ 7 - 5
platform/android/java_godot_lib_jni.cpp

@@ -446,7 +446,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en
 	}
 
 	Callable::CallError err;
-	obj->call(str_method, (const Variant **)vptr, count, err);
+	obj->callp(str_method, (const Variant **)vptr, count, err);
 	// something
 
 	env->PopLocalFrame(nullptr);
@@ -462,18 +462,20 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *
 	String str_method = jstring_to_string(method, env);
 
 	int count = env->GetArrayLength(params);
-	Variant args[VARIANT_ARG_MAX];
 
-	for (int i = 0; i < MIN(count, VARIANT_ARG_MAX); i++) {
+	Variant *args = (Variant *)alloca(sizeof(Variant) * count);
+	const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * count);
+
+	for (int i = 0; i < count; i++) {
 		jobject obj = env->GetObjectArrayElement(params, i);
 		if (obj) {
 			args[i] = _jobject_to_variant(env, obj);
 		}
 		env->DeleteLocalRef(obj);
+		argptrs[i] = &args[i];
 	}
 
-	static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
-	obj->call_deferred(str_method, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+	MessageQueue::get_singleton()->push_callp(obj, str_method, (const Variant **)argptrs, count);
 	// something
 	env->PopLocalFrame(nullptr);
 }

+ 3 - 4
platform/android/plugin/godot_plugin_jni.cpp

@@ -114,10 +114,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
 	String signal_name = jstring_to_string(j_signal_name, env);
 
 	int count = env->GetArrayLength(j_signal_params);
-	ERR_FAIL_COND_MSG(count > VARIANT_ARG_MAX, "Maximum argument count exceeded!");
 
-	Variant variant_params[VARIANT_ARG_MAX];
-	const Variant *args[VARIANT_ARG_MAX];
+	Variant *variant_params = (Variant *)alloca(sizeof(Variant) * count);
+	const Variant **args = (const Variant **)alloca(sizeof(Variant *) * count);
 
 	for (int i = 0; i < count; i++) {
 		jobject j_param = env->GetObjectArrayElement(j_signal_params, i);
@@ -126,7 +125,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
 		env->DeleteLocalRef(j_param);
 	};
 
-	singleton->emit_signal(StringName(signal_name), args, count);
+	singleton->emit_signalp(StringName(signal_name), args, count);
 }
 
 JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths) {

+ 2 - 2
platform/javascript/javascript_singleton.cpp

@@ -81,7 +81,7 @@ protected:
 public:
 	Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const override;
 	void setvar(const Variant &p_key, const Variant &p_value, bool *r_valid = nullptr) override;
-	Variant call(const StringName &p_method, const Variant **p_args, int p_argc, Callable::CallError &r_error) override;
+	Variant callp(const StringName &p_method, const Variant **p_args, int p_argc, Callable::CallError &r_error) override;
 	JavaScriptObjectImpl() {}
 	JavaScriptObjectImpl(int p_id) { _js_id = p_id; }
 	~JavaScriptObjectImpl() {
@@ -231,7 +231,7 @@ int JavaScriptObjectImpl::_variant2js(const void **p_args, int p_pos, godot_js_w
 	return type;
 }
 
-Variant JavaScriptObjectImpl::call(const StringName &p_method, const Variant **p_args, int p_argc, Callable::CallError &r_error) {
+Variant JavaScriptObjectImpl::callp(const StringName &p_method, const Variant **p_args, int p_argc, Callable::CallError &r_error) {
 	godot_js_wrapper_ex exchange;
 	const String method = p_method;
 	void *lock = nullptr;

+ 26 - 37
scene/animation/animation_player.cpp

@@ -401,6 +401,22 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
 	}
 }
 
+static void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) {
+	// Separate function to use alloca() more efficiently
+	const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size());
+	const Variant *args = p_params.ptr();
+	uint32_t argcount = p_params.size();
+	for (uint32_t i = 0; i < argcount; i++) {
+		argptrs[i] = &args[i];
+	}
+	if (p_deferred) {
+		MessageQueue::get_singleton()->push_callp(p_object, p_method, argptrs, argcount);
+	} else {
+		Callable::CallError ce;
+		p_object->callp(p_method, argptrs, argcount, ce);
+	}
+}
+
 void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) {
 	_ensure_node_caches(p_anim);
 	ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
@@ -677,41 +693,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
 					StringName method = a->method_track_get_name(i, E);
 					Vector<Variant> params = a->method_track_get_params(i, E);
 
-					int s = params.size();
-
-					ERR_CONTINUE(s > VARIANT_ARG_MAX);
 #ifdef DEBUG_ENABLED
 					if (!nc->node->has_method(method)) {
 						ERR_PRINT("Invalid method call '" + method + "'. '" + a->get_name() + "' at node '" + get_path() + "'.");
 					}
 #endif
 
-					static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
 					if (can_call) {
-						if (method_call_mode == ANIMATION_METHOD_CALL_DEFERRED) {
-							MessageQueue::get_singleton()->push_call(
-									nc->node,
-									method,
-									s >= 1 ? params[0] : Variant(),
-									s >= 2 ? params[1] : Variant(),
-									s >= 3 ? params[2] : Variant(),
-									s >= 4 ? params[3] : Variant(),
-									s >= 5 ? params[4] : Variant(),
-									s >= 6 ? params[5] : Variant(),
-									s >= 7 ? params[6] : Variant(),
-									s >= 8 ? params[7] : Variant());
-						} else {
-							nc->node->call(
-									method,
-									s >= 1 ? params[0] : Variant(),
-									s >= 2 ? params[1] : Variant(),
-									s >= 3 ? params[2] : Variant(),
-									s >= 4 ? params[3] : Variant(),
-									s >= 5 ? params[4] : Variant(),
-									s >= 6 ? params[5] : Variant(),
-									s >= 7 ? params[6] : Variant(),
-									s >= 8 ? params[7] : Variant());
-						}
+						_call_object(nc->node, method, params, method_call_mode == ANIMATION_METHOD_CALL_DEFERRED);
 					}
 				}
 
@@ -754,7 +743,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
 
 					Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
 					if (!stream.is_valid()) {
-						nc->node->call("stop");
+						nc->node->call(SNAME("stop"));
 						nc->audio_playing = false;
 						playing_caches.erase(nc);
 					} else {
@@ -764,14 +753,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
 						float len = stream->get_length();
 
 						if (start_ofs > len - end_ofs) {
-							nc->node->call("stop");
+							nc->node->call(SNAME("stop"));
 							nc->audio_playing = false;
 							playing_caches.erase(nc);
 							continue;
 						}
 
-						nc->node->call("set_stream", stream);
-						nc->node->call("play", start_ofs);
+						nc->node->call(SNAME("set_stream"), stream);
+						nc->node->call(SNAME("play"), start_ofs);
 
 						nc->audio_playing = true;
 						playing_caches.insert(nc);
@@ -793,7 +782,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
 
 						Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
 						if (!stream.is_valid()) {
-							nc->node->call("stop");
+							nc->node->call(SNAME("stop"));
 							nc->audio_playing = false;
 							playing_caches.erase(nc);
 						} else {
@@ -801,8 +790,8 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
 							float end_ofs = a->audio_track_get_key_end_offset(i, idx);
 							float len = stream->get_length();
 
-							nc->node->call("set_stream", stream);
-							nc->node->call("play", start_ofs);
+							nc->node->call(SNAME("set_stream"), stream);
+							nc->node->call(SNAME("play"), start_ofs);
 
 							nc->audio_playing = true;
 							playing_caches.insert(nc);
@@ -833,7 +822,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
 
 						if (stop) {
 							//time to stop
-							nc->node->call("stop");
+							nc->node->call(SNAME("stop"));
 							nc->audio_playing = false;
 							playing_caches.erase(nc);
 						}
@@ -1544,7 +1533,7 @@ void AnimationPlayer::_animation_changed() {
 void AnimationPlayer::_stop_playing_caches() {
 	for (Set<TrackNodeCache *>::Element *E = playing_caches.front(); E; E = E->next()) {
 		if (E->get()->node && E->get()->audio_playing) {
-			E->get()->node->call("stop");
+			E->get()->node->call(SNAME("stop"));
 		}
 		if (E->get()->node && E->get()->animation_playing) {
 			AnimationPlayer *player = Object::cast_to<AnimationPlayer>(E->get()->node);

+ 28 - 28
scene/animation/animation_tree.cpp

@@ -490,7 +490,7 @@ void AnimationTree::set_active(bool p_active) {
 	if (!active && is_inside_tree()) {
 		for (Set<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) {
 			if (ObjectDB::get_instance(E->get()->object_id)) {
-				E->get()->object->call("stop");
+				E->get()->object->call(SNAME("stop"));
 			}
 		}
 
@@ -796,6 +796,21 @@ void AnimationTree::_clear_caches() {
 	cache_valid = false;
 }
 
+static void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) {
+	// Separate function to use alloca() more efficiently
+	const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size());
+	const Variant *args = p_params.ptr();
+	uint32_t argcount = p_params.size();
+	for (uint32_t i = 0; i < argcount; i++) {
+		argptrs[i] = &args[i];
+	}
+	if (p_deferred) {
+		MessageQueue::get_singleton()->push_callp(p_object, p_method, argptrs, argcount);
+	} else {
+		Callable::CallError ce;
+		p_object->callp(p_method, argptrs, argcount, ce);
+	}
+}
 void AnimationTree::_process_graph(double p_delta) {
 	_update_properties(); //if properties need updating, update them
 
@@ -1286,25 +1301,10 @@ void AnimationTree::_process_graph(double p_delta) {
 						for (int &F : indices) {
 							StringName method = a->method_track_get_name(i, F);
 							Vector<Variant> params = a->method_track_get_params(i, F);
-
-							int s = params.size();
-
-							static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
-							ERR_CONTINUE(s > VARIANT_ARG_MAX);
 							if (can_call) {
-								t->object->call_deferred(
-										method,
-										s >= 1 ? params[0] : Variant(),
-										s >= 2 ? params[1] : Variant(),
-										s >= 3 ? params[2] : Variant(),
-										s >= 4 ? params[3] : Variant(),
-										s >= 5 ? params[4] : Variant(),
-										s >= 6 ? params[5] : Variant(),
-										s >= 7 ? params[6] : Variant(),
-										s >= 8 ? params[7] : Variant());
+								_call_object(t->object, method, params, true);
 							}
 						}
-
 					} break;
 					case Animation::TYPE_BEZIER: {
 						TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);
@@ -1331,7 +1331,7 @@ void AnimationTree::_process_graph(double p_delta) {
 
 							Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
 							if (!stream.is_valid()) {
-								t->object->call("stop");
+								t->object->call(SNAME("stop"));
 								t->playing = false;
 								playing_caches.erase(t);
 							} else {
@@ -1341,14 +1341,14 @@ void AnimationTree::_process_graph(double p_delta) {
 								double len = stream->get_length();
 
 								if (start_ofs > len - end_ofs) {
-									t->object->call("stop");
+									t->object->call(SNAME("stop"));
 									t->playing = false;
 									playing_caches.erase(t);
 									continue;
 								}
 
-								t->object->call("set_stream", stream);
-								t->object->call("play", start_ofs);
+								t->object->call(SNAME("set_stream"), stream);
+								t->object->call(SNAME("play"), start_ofs);
 
 								t->playing = true;
 								playing_caches.insert(t);
@@ -1370,7 +1370,7 @@ void AnimationTree::_process_graph(double p_delta) {
 
 								Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
 								if (!stream.is_valid()) {
-									t->object->call("stop");
+									t->object->call(SNAME("stop"));
 									t->playing = false;
 									playing_caches.erase(t);
 								} else {
@@ -1378,8 +1378,8 @@ void AnimationTree::_process_graph(double p_delta) {
 									double end_ofs = a->audio_track_get_key_end_offset(i, idx);
 									double len = stream->get_length();
 
-									t->object->call("set_stream", stream);
-									t->object->call("play", start_ofs);
+									t->object->call(SNAME("set_stream"), stream);
+									t->object->call(SNAME("play"), start_ofs);
 
 									t->playing = true;
 									playing_caches.insert(t);
@@ -1416,7 +1416,7 @@ void AnimationTree::_process_graph(double p_delta) {
 
 								if (stop) {
 									//time to stop
-									t->object->call("stop");
+									t->object->call(SNAME("stop"));
 									t->playing = false;
 									playing_caches.erase(t);
 								}
@@ -1424,10 +1424,10 @@ void AnimationTree::_process_graph(double p_delta) {
 						}
 
 						real_t db = Math::linear2db(MAX(blend, 0.00001));
-						if (t->object->has_method("set_unit_db")) {
-							t->object->call("set_unit_db", db);
+						if (t->object->has_method(SNAME("set_unit_db"))) {
+							t->object->call(SNAME("set_unit_db"), db);
 						} else {
-							t->object->call("set_volume_db", db);
+							t->object->call(SNAME("set_volume_db"), db);
 						}
 					} break;
 					case Animation::TYPE_ANIMATION: {

+ 26 - 7
scene/debugger/scene_debugger.cpp

@@ -34,6 +34,7 @@
 #include "core/debugger/engine_profiler.h"
 #include "core/io/marshalls.h"
 #include "core/object/script_language.h"
+#include "core/templates/local_vector.h"
 #include "scene/main/scene_tree.h"
 #include "scene/main/window.h"
 #include "scene/resources/packed_scene.h"
@@ -236,12 +237,28 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
 		live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]);
 
 	} else if (p_msg == "live_node_call") {
-		ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA);
-		live_editor->_node_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6], p_args[7], p_args[8], p_args[9]);
+		LocalVector<Variant> args;
+		LocalVector<Variant *> argptrs;
+		args.resize(p_args.size() - 2);
+		argptrs.resize(args.size());
+		for (uint32_t i = 0; i < args.size(); i++) {
+			args[i] = p_args[i + 2];
+			argptrs[i] = &args[i];
+		}
+		live_editor->_node_call_func(p_args[0], p_args[1], (const Variant **)argptrs.ptr(), argptrs.size());
 
 	} else if (p_msg == "live_res_call") {
 		ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA);
-		live_editor->_res_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6], p_args[7], p_args[8], p_args[9]);
+
+		LocalVector<Variant> args;
+		LocalVector<Variant *> argptrs;
+		args.resize(p_args.size() - 2);
+		argptrs.resize(args.size());
+		for (uint32_t i = 0; i < args.size(); i++) {
+			args[i] = p_args[i + 2];
+			argptrs[i] = &args[i];
+		}
+		live_editor->_res_call_func(p_args[0], p_args[1], (const Variant **)argptrs.ptr(), argptrs.size());
 
 	} else if (p_msg == "live_create_node") {
 		ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);
@@ -636,7 +653,7 @@ void LiveEditor::_node_set_res_func(int p_id, const StringName &p_prop, const St
 	_node_set_func(p_id, p_prop, r);
 }
 
-void LiveEditor::_node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
+void LiveEditor::_node_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount) {
 	SceneTree *scene_tree = SceneTree::get_singleton();
 	if (!scene_tree) {
 		return;
@@ -668,7 +685,8 @@ void LiveEditor::_node_call_func(int p_id, const StringName &p_method, VARIANT_A
 		}
 		Node *n2 = n->get_node(np);
 
-		n2->call(p_method, VARIANT_ARG_PASS);
+		Callable::CallError ce;
+		n2->callp(p_method, p_args, p_argcount, ce);
 	}
 }
 
@@ -699,7 +717,7 @@ void LiveEditor::_res_set_res_func(int p_id, const StringName &p_prop, const Str
 	_res_set_func(p_id, p_prop, r);
 }
 
-void LiveEditor::_res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
+void LiveEditor::_res_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount) {
 	if (!live_edit_resource_cache.has(p_id)) {
 		return;
 	}
@@ -715,7 +733,8 @@ void LiveEditor::_res_call_func(int p_id, const StringName &p_method, VARIANT_AR
 		return;
 	}
 
-	r->call(p_method, VARIANT_ARG_PASS);
+	Callable::CallError ce;
+	r->callp(p_method, p_args, p_argcount, ce);
 }
 
 void LiveEditor::_root_func(const NodePath &p_scene_path, const String &p_scene_from) {

+ 2 - 2
scene/debugger/scene_debugger.h

@@ -148,10 +148,10 @@ private:
 
 	void _node_set_func(int p_id, const StringName &p_prop, const Variant &p_value);
 	void _node_set_res_func(int p_id, const StringName &p_prop, const String &p_value);
-	void _node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE);
+	void _node_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount);
 	void _res_set_func(int p_id, const StringName &p_prop, const Variant &p_value);
 	void _res_set_res_func(int p_id, const StringName &p_prop, const String &p_value);
-	void _res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE);
+	void _res_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount);
 	void _root_func(const NodePath &p_scene_path, const String &p_scene_from);
 
 	void _create_node_func(const NodePath &p_parent, const String &p_type, const String &p_name);

+ 1 - 1
scene/gui/tree.cpp

@@ -1186,7 +1186,7 @@ void recursive_call_aux(TreeItem *p_item, const StringName &p_method, const Vari
 	if (!p_item) {
 		return;
 	}
-	p_item->call(p_method, p_args, p_argcount, r_error);
+	p_item->callp(p_method, p_args, p_argcount, r_error);
 	TreeItem *c = p_item->get_first_child();
 	while (c) {
 		recursive_call_aux(c, p_method, p_args, p_argcount, r_error);

+ 2 - 66
scene/main/node.cpp

@@ -211,7 +211,7 @@ void Node::_propagate_enter_tree() {
 	if (data.parent) {
 		Variant c = this;
 		const Variant *cptr = &c;
-		data.parent->emit_signal(SNAME("child_entered_tree"), &cptr, 1);
+		data.parent->emit_signalp(SNAME("child_entered_tree"), &cptr, 1);
 	}
 
 	data.blocked++;
@@ -287,7 +287,7 @@ void Node::_propagate_exit_tree() {
 	if (data.parent) {
 		Variant c = this;
 		const Variant *cptr = &c;
-		data.parent->emit_signal(SNAME("child_exited_tree"), &cptr, 1);
+		data.parent->emit_signalp(SNAME("child_exited_tree"), &cptr, 1);
 	}
 
 	// exit groups
@@ -582,34 +582,6 @@ uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc
 
 /***** RPC FUNCTIONS ********/
 
-void Node::rpc(const StringName &p_method, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS;
-
-	int argc = 0;
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		if (argptr[i]->get_type() == Variant::NIL) {
-			break;
-		}
-		argc++;
-	}
-
-	rpcp(0, p_method, argptr, argc);
-}
-
-void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
-	VARIANT_ARGPTRS;
-
-	int argc = 0;
-	for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-		if (argptr[i]->get_type() == Variant::NIL) {
-			break;
-		}
-		argc++;
-	}
-
-	rpcp(p_peer_id, p_method, argptr, argc);
-}
-
 Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
 	if (p_argcount < 1) {
 		r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
@@ -2389,42 +2361,6 @@ void Node::_replace_connections_target(Node *p_new_target) {
 	}
 }
 
-Vector<Variant> Node::make_binds(VARIANT_ARG_DECLARE) {
-	Vector<Variant> ret;
-
-	if (p_arg1.get_type() == Variant::NIL) {
-		return ret;
-	} else {
-		ret.push_back(p_arg1);
-	}
-
-	if (p_arg2.get_type() == Variant::NIL) {
-		return ret;
-	} else {
-		ret.push_back(p_arg2);
-	}
-
-	if (p_arg3.get_type() == Variant::NIL) {
-		return ret;
-	} else {
-		ret.push_back(p_arg3);
-	}
-
-	if (p_arg4.get_type() == Variant::NIL) {
-		return ret;
-	} else {
-		ret.push_back(p_arg4);
-	}
-
-	if (p_arg5.get_type() == Variant::NIL) {
-		return ret;
-	} else {
-		ret.push_back(p_arg5);
-	}
-
-	return ret;
-}
-
 bool Node::has_node_and_resource(const NodePath &p_path) const {
 	if (!has_node(p_path)) {
 		return false;

+ 25 - 3
scene/main/node.h

@@ -420,7 +420,11 @@ public:
 	void set_scene_instance_load_placeholder(bool p_enable);
 	bool get_scene_instance_load_placeholder() const;
 
-	static Vector<Variant> make_binds(VARIANT_ARG_LIST);
+	template <typename... VarArgs>
+	Vector<Variant> make_binds(VarArgs... p_args) {
+		Vector<Variant> binds = { p_args... };
+		return binds;
+	}
 
 	void replace_by(Node *p_node, bool p_keep_data = false);
 
@@ -472,8 +476,26 @@ public:
 	uint16_t rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local = false, Multiplayer::TransferMode p_transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0); // config a local method for RPC
 	Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const;
 
-	void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel
-	void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel
+	template <typename... VarArgs>
+	void rpc(const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		rpcp(0, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+
+	template <typename... VarArgs>
+	void rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+
 	void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
 
 	Ref<MultiplayerAPI> get_multiplayer() const;

+ 15 - 34
scene/main/scene_tree.cpp

@@ -175,13 +175,13 @@ void SceneTree::_flush_ugc() {
 	while (unique_group_calls.size()) {
 		Map<UGCall, Vector<Variant>>::Element *E = unique_group_calls.front();
 
-		Variant v[VARIANT_ARG_MAX];
+		const Variant **argptrs = (const Variant **)alloca(E->get().size() * sizeof(Variant *));
+
 		for (int i = 0; i < E->get().size(); i++) {
-			v[i] = E->get()[i];
+			argptrs[i] = &E->get()[i];
 		}
 
-		static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
-		call_group_flags(GROUP_CALL_REALTIME, E->key().group, E->key().call, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+		call_group_flagsp(GROUP_CALL_REALTIME, E->key().group, E->key().call, argptrs, E->get().size());
 
 		unique_group_calls.erase(E);
 	}
@@ -210,7 +210,7 @@ void SceneTree::_update_group_order(Group &g, bool p_use_priority) {
 	g.changed = false;
 }
 
-void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) {
+void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount) {
 	Map<StringName, Group>::Element *E = group_map.find(p_group);
 	if (!E) {
 		return;
@@ -231,14 +231,9 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
 			return;
 		}
 
-		VARIANT_ARGPTRS;
-
 		Vector<Variant> args;
-		for (int i = 0; i < VARIANT_ARG_MAX; i++) {
-			if (argptr[i]->get_type() == Variant::NIL) {
-				break;
-			}
-			args.push_back(*argptr[i]);
+		for (int i = 0; i < p_argcount; i++) {
+			args.push_back(*p_args[i]);
 		}
 
 		unique_group_calls[ug] = args;
@@ -260,9 +255,10 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
 			}
 
 			if (p_call_flags & GROUP_CALL_REALTIME) {
-				nodes[i]->call(p_function, VARIANT_ARG_PASS);
+				Callable::CallError ce;
+				nodes[i]->callp(p_function, p_args, p_argcount, ce);
 			} else {
-				MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS);
+				MessageQueue::get_singleton()->push_callp(nodes[i], p_function, p_args, p_argcount);
 			}
 		}
 
@@ -273,9 +269,10 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
 			}
 
 			if (p_call_flags & GROUP_CALL_REALTIME) {
-				nodes[i]->call(p_function, VARIANT_ARG_PASS);
+				Callable::CallError ce;
+				nodes[i]->callp(p_function, p_args, p_argcount, ce);
 			} else {
-				MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS);
+				MessageQueue::get_singleton()->push_callp(nodes[i], p_function, p_args, p_argcount);
 			}
 		}
 	}
@@ -388,10 +385,6 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group
 	}
 }
 
-void SceneTree::call_group(const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) {
-	call_group_flags(0, p_group, p_function, VARIANT_ARG_PASS);
-}
-
 void SceneTree::notify_group(const StringName &p_group, int p_notification) {
 	notify_group_flags(0, p_group, p_notification);
 }
@@ -930,14 +923,8 @@ Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Cal
 	int flags = *p_args[0];
 	StringName group = *p_args[1];
 	StringName method = *p_args[2];
-	Variant v[VARIANT_ARG_MAX];
-
-	for (int i = 0; i < MIN(p_argcount - 3, 5); i++) {
-		v[i] = *p_args[i + 3];
-	}
 
-	static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
-	call_group_flags(flags, group, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+	call_group_flagsp(flags, group, method, p_args + 3, p_argcount - 3);
 	return Variant();
 }
 
@@ -950,14 +937,8 @@ Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable:
 
 	StringName group = *p_args[0];
 	StringName method = *p_args[1];
-	Variant v[VARIANT_ARG_MAX];
-
-	for (int i = 0; i < MIN(p_argcount - 2, 5); i++) {
-		v[i] = *p_args[i + 2];
-	}
 
-	static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
-	call_group_flags(0, group, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+	call_group_flagsp(0, group, method, p_args + 2, p_argcount - 2);
 	return Variant();
 }
 

+ 21 - 2
scene/main/scene_tree.h

@@ -229,14 +229,33 @@ public:
 
 	_FORCE_INLINE_ Window *get_root() const { return root; }
 
-	void call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST);
+	void call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount);
 	void notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification);
 	void set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value);
 
-	void call_group(const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST);
 	void notify_group(const StringName &p_group, int p_notification);
 	void set_group(const StringName &p_group, const String &p_name, const Variant &p_value);
 
+	template <typename... VarArgs>
+	void call_group(const StringName &p_group, const StringName &p_function, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		call_group_flagsp(0, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+
+	template <typename... VarArgs>
+	void call_group_flags(uint32_t p_flags, const StringName &p_group, const StringName &p_function, VarArgs... p_args) {
+		Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+		const Variant *argptrs[sizeof...(p_args) + 1];
+		for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+			argptrs[i] = &args[i];
+		}
+		call_group_flagsp(p_flags, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+	}
+
 	void flush_transform_notifications();
 
 	virtual void initialize() override;

+ 3 - 3
scene/multiplayer/scene_rpc_interface.cpp

@@ -278,7 +278,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
 
 	Callable::CallError ce;
 
-	p_node->call(config.name, (const Variant **)argp.ptr(), argc, ce);
+	p_node->callp(config.name, (const Variant **)argp.ptr(), argc, ce);
 	if (ce.error != Callable::CallError::CALL_OK) {
 		String error = Variant::get_call_error_text(p_node, config.name, (const Variant **)argp.ptr(), argc, ce);
 		error = "RPC - " + error;
@@ -480,7 +480,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
 		Callable::CallError ce;
 
 		multiplayer->set_remote_sender_override(peer->get_unique_id());
-		node->call(p_method, p_arg, p_argcount, ce);
+		node->callp(p_method, p_arg, p_argcount, ce);
 		multiplayer->set_remote_sender_override(0);
 
 		if (ce.error != Callable::CallError::CALL_OK) {
@@ -496,7 +496,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
 		ce.error = Callable::CallError::CALL_OK;
 
 		multiplayer->set_remote_sender_override(peer->get_unique_id());
-		node->get_script_instance()->call(p_method, p_arg, p_argcount, ce);
+		node->get_script_instance()->callp(p_method, p_arg, p_argcount, ce);
 		multiplayer->set_remote_sender_override(0);
 
 		if (ce.error != Callable::CallError::CALL_OK) {

+ 1 - 1
tests/core/object/test_object.h

@@ -87,7 +87,7 @@ public:
 	bool has_method(const StringName &p_method) const override {
 		return false;
 	}
-	Variant call(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();
 	}
 	void notification(int p_notification) override {