Remove VARIANT_ARG* macros

* Very old macros from the time Godot was created.
* Limited arguments to 5 (then later changed to 8) in many places.
* They were replaced by C++11 Variadic Templates.
* Renamed methods that take argument pointers to have a "p" suffix. This was used in some places and not in others, so made it standard.
* Also added a dereference check for Variant*. Helped catch a couple of bugs.
This commit is contained in:
reduz 2022-03-09 14:58:40 +01:00
parent 922348f4c0
commit 21637dfc25
59 changed files with 417 additions and 467 deletions

View File

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

View File

@ -1440,7 +1440,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
} }
Callable::CallError ce; 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) { if (ce.error != Callable::CallError::CALL_OK) {
r_error_str = vformat(RTR("On call to '%s':"), String(call->method)); r_error_str = vformat(RTR("On call to '%s':"), String(call->method));

View File

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

View File

@ -8,7 +8,7 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
if (script_instance) {\\ if (script_instance) {\\
Callable::CallError ce; \\ Callable::CallError ce; \\
$CALLSIARGS\\ $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) {\\ if (ce.error == Callable::CallError::CALL_OK) {\\
$CALLSIRET\\ $CALLSIRET\\
return true;\\ return true;\\

View File

@ -32,6 +32,7 @@
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/core_string_names.h" #include "core/core_string_names.h"
#include "core/object/class_db.h"
#include "core/object/script_language.h" #include "core/object/script_language.h"
MessageQueue *MessageQueue::singleton = nullptr; MessageQueue *MessageQueue::singleton = nullptr;
@ -40,23 +41,8 @@ MessageQueue *MessageQueue::get_singleton() {
return 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) { Error MessageQueue::push_callp(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); return push_callablep(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_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value) { 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; return OK;
} }
Error MessageQueue::push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) { Error MessageQueue::push_callp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {
return push_call(p_object->get_instance_id(), p_method, VARIANT_ARG_PASS); 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) { 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); 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_ _THREAD_SAFE_METHOD_
int room_needed = sizeof(Message) + sizeof(Variant) * p_argcount; 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; 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() { void MessageQueue::statistics() {
Map<StringName, int> set_count; Map<StringName, int> set_count;
Map<int, int> notify_count; Map<int, int> notify_count;

View File

@ -31,8 +31,11 @@
#ifndef MESSAGE_QUEUE_H #ifndef MESSAGE_QUEUE_H
#define 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/os/thread_safe.h"
#include "core/variant/variant.h"
class Object;
class MessageQueue { class MessageQueue {
_THREAD_SAFE_CLASS_ _THREAD_SAFE_CLASS_
@ -73,14 +76,42 @@ class MessageQueue {
public: public:
static MessageQueue *get_singleton(); 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_callp(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); 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_notification(ObjectID p_id, int p_notification);
Error push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value); 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_callablep(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);
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_notification(Object *p_object, int p_notification);
Error push_set(Object *p_object, const StringName &p_prop, const Variant &p_value); Error push_set(Object *p_object, const StringName &p_prop, const Variant &p_value);

View File

@ -679,7 +679,7 @@ Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::Cal
StringName method = *p_args[0]; 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) { 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]; 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(); return Variant();
} }
@ -750,31 +750,14 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) {
} }
Callable::CallError ce; 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) { 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) + "."); 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; return ret;
} }
Variant Object::call(const StringName &p_name, VARIANT_ARG_DECLARE) { Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
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) {
r_error.error = Callable::CallError::CALL_OK; r_error.error = Callable::CallError::CALL_OK;
if (p_method == CoreStringNames::get_singleton()->_free) { 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 OBJ_DEBUG_LOCK
if (script_instance) { 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 //force jumptable
switch (r_error.error) { switch (r_error.error) {
case Callable::CallError::CALL_OK: 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]; args = &p_args[1];
} }
emit_signal(signal, args, argc); emit_signalp(signal, args, argc);
return Variant(); 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) { if (_block_signals) {
return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked 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) { 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 { } else {
Callable::CallError ce; Callable::CallError ce;
_emitting = true; _emitting = true;
@ -1139,21 +1122,6 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
return err; 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) { 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 // this version of add_user_signal is meant to be used from scripts or external apis
// without access to ADD_SIGNAL in bind_methods // without access to ADD_SIGNAL in bind_methods
@ -1648,10 +1616,6 @@ void Object::_bind_methods() {
BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED); 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) { void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
MessageQueue::get_singleton()->push_set(this, p_property, p_value); MessageQueue::get_singleton()->push_set(this, p_property, p_value);
} }

View File

@ -32,6 +32,7 @@
#define OBJECT_H #define OBJECT_H
#include "core/extension/gdnative_interface.h" #include "core/extension/gdnative_interface.h"
#include "core/object/message_queue.h"
#include "core/object/object_id.h" #include "core/object/object_id.h"
#include "core/os/rw_lock.h" #include "core/os/rw_lock.h"
#include "core/os/spin_lock.h" #include "core/os/spin_lock.h"
@ -44,14 +45,6 @@
#include "core/variant/callable_bind.h" #include "core/variant/callable_bind.h"
#include "core/variant/variant.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 { enum PropertyHint {
PROPERTY_HINT_NONE, ///< no hint provided. 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. 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; bool has_method(const StringName &p_method) const;
void get_method_list(List<MethodInfo> *p_list) const; void get_method_list(List<MethodInfo> *p_list) const;
Variant callv(const StringName &p_method, const Array &p_args); Variant callv(const StringName &p_method, const Array &p_args);
virtual Variant 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 call(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
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); void notification(int p_notification, bool p_reversed = false);
virtual String to_string(); virtual String to_string();
@ -769,8 +772,18 @@ public:
void set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance); void set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance);
void add_user_signal(const MethodInfo &p_signal); 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; bool has_signal(const StringName &p_name) const;
void get_signal_list(List<MethodInfo> *p_signals) const; void get_signal_list(List<MethodInfo> *p_signals) const;
void get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) 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); void disconnect(const StringName &p_signal, const Callable &p_callable);
bool is_connected(const StringName &p_signal, const Callable &p_callable) const; 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_deferred(const StringName &p_property, const Variant &p_value);
void set_block_signals(bool p_block); void set_block_signals(bool p_block);

View File

@ -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) { void ScriptInstance::property_set_fallback(const StringName &, const Variant &, bool *r_valid) {
if (r_valid) { if (r_valid) {
*r_valid = false; *r_valid = false;

View File

@ -176,8 +176,20 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) const = 0; virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
virtual bool has_method(const StringName &p_method) const = 0; virtual bool has_method(const StringName &p_method) const = 0;
virtual 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 void notification(int p_notification) = 0;
virtual String to_string(bool *r_valid) { virtual String to_string(bool *r_valid) {
if (r_valid) { if (r_valid) {
@ -419,8 +431,8 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) const; virtual void get_method_list(List<MethodInfo> *p_list) const;
virtual bool has_method(const StringName &p_method) const; virtual bool has_method(const StringName &p_method) const;
virtual 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; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant(); return Variant();
} }

View File

@ -126,8 +126,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
force_keep_in_merge_ends = false; force_keep_in_merge_ends = false;
} }
void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) { void UndoRedo::add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
VARIANT_ARGPTRS
ERR_FAIL_COND(p_object == nullptr); ERR_FAIL_COND(p_object == nullptr);
ERR_FAIL_COND(action_level <= 0); ERR_FAIL_COND(action_level <= 0);
ERR_FAIL_COND((current_action + 1) >= actions.size()); 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.type = Operation::TYPE_METHOD;
do_op.name = p_method; do_op.name = p_method;
for (int i = 0; i < VARIANT_ARG_MAX; i++) { for (int i = 0; i < p_argcount; i++) {
do_op.args[i] = *argptr[i]; do_op.args.push_back(*p_args[i]);
} }
actions.write[current_action + 1].do_ops.push_back(do_op); 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) { void UndoRedo::add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
VARIANT_ARGPTRS
ERR_FAIL_COND(p_object == nullptr); ERR_FAIL_COND(p_object == nullptr);
ERR_FAIL_COND(action_level <= 0); ERR_FAIL_COND(action_level <= 0);
ERR_FAIL_COND((current_action + 1) >= actions.size()); 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.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_method; undo_op.name = p_method;
for (int i = 0; i < VARIANT_ARG_MAX; i++) { for (int i = 0; i < p_argcount; i++) {
undo_op.args[i] = *argptr[i]; undo_op.args.push_back(*p_args[i]);
} }
actions.write[current_action + 1].undo_ops.push_back(undo_op); 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.type = Operation::TYPE_PROPERTY;
do_op.name = p_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); 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.type = Operation::TYPE_PROPERTY;
undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends; undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_property; 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); 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) { switch (op.type) {
case Operation::TYPE_METHOD: { case Operation::TYPE_METHOD: {
Vector<const Variant *> argptrs; Vector<const Variant *> argptrs;
argptrs.resize(VARIANT_ARG_MAX); argptrs.resize(op.args.size());
int argc = 0; int argc = 0;
for (int i = 0; i < VARIANT_ARG_MAX; i++) { for (int i = 0; i < op.args.size(); i++) {
if (op.args[i].get_type() == Variant::NIL) {
break;
}
argptrs.write[i] = &op.args[i]; argptrs.write[i] = &op.args[i];
argc++;
} }
argptrs.resize(argc);
Callable::CallError ce; 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) { 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)); 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 #endif
if (method_callback) { 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; } break;
case Operation::TYPE_PROPERTY: { 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]; Object *object = *p_args[0];
StringName method = *p_args[1]; StringName method = *p_args[1];
Variant v[VARIANT_ARG_MAX]; add_do_methodp(object, method, p_args + 2, p_argcount - 2);
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]);
return Variant(); return Variant();
} }
@ -514,14 +500,7 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla
Object *object = *p_args[0]; Object *object = *p_args[0];
StringName method = *p_args[1]; StringName method = *p_args[1];
Variant v[VARIANT_ARG_MAX]; add_undo_methodp(object, method, p_args + 2, p_argcount - 2);
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]);
return Variant(); return Variant();
} }

View File

@ -49,7 +49,7 @@ public:
Variant _add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error); 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); 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); typedef void (*PropertyNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
private: private:
@ -65,7 +65,7 @@ private:
Ref<RefCounted> ref; Ref<RefCounted> ref;
ObjectID object; ObjectID object;
StringName name; StringName name;
Variant args[VARIANT_ARG_MAX]; Vector<Variant> args;
void delete_reference(); void delete_reference();
}; };
@ -106,8 +106,30 @@ protected:
public: public:
void create_action(const String &p_name = "", MergeMode p_mode = MERGE_DISABLE); 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_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
void add_undo_method(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST); 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_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_undo_property(Object *p_object, const StringName &p_property, const Variant &p_value);
void add_do_reference(Object *p_object); void add_do_reference(Object *p_object);

View File

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

View File

@ -37,7 +37,7 @@
#include "core/object/script_language.h" #include "core/object/script_language.h"
void Callable::call_deferred(const Variant **p_arguments, int p_argcount) const { 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 { 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; return;
} }
#endif #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 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) { Error Signal::connect(const Callable &p_callable, uint32_t p_flags) {

View File

@ -1972,7 +1972,7 @@ Variant::operator ::RID() const {
} }
#endif #endif
Callable::CallError ce; 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) { if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::RID) {
return ret; return ret;
} }
@ -3309,21 +3309,7 @@ bool Variant::is_shared() const {
return false; return false;
} }
Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) { void Variant::_variant_call_error(const String &p_method, Callable::CallError &error) {
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);
switch (error.error) { switch (error.error) {
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { 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)) + "'."; 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: { default: {
} }
} }
return ret;
} }
void Variant::construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct, void *p_construct_ud) { void Variant::construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct, void *p_construct_ud) {

View File

@ -282,6 +282,14 @@ private:
static void _register_variant_utility_functions(); static void _register_variant_utility_functions();
static void _unregister_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: public:
_FORCE_INLINE_ Type get_type() const { _FORCE_INLINE_ Type get_type() const {
return type; return type;
@ -527,8 +535,23 @@ public:
static int get_builtin_method_count(Variant::Type p_type); 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); 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); void callp(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());
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); 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);

View File

@ -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); 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) { if (type == Variant::OBJECT) {
//call object //call object
Object *obj = _get_obj().obj; Object *obj = _get_obj().obj;
@ -1018,7 +1018,7 @@ void Variant::call(const StringName &p_method, const Variant **p_args, int p_arg
} }
#endif #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 if (type==Variant::METHOD) {
} else { } else {

View File

@ -1277,7 +1277,7 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
ref.push_back(r_iter); ref.push_back(r_iter);
Variant vref = ref; Variant vref = ref;
const Variant *refp[] = { &vref }; 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) { if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
valid = false; valid = false;
@ -1504,7 +1504,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
ref.push_back(r_iter); ref.push_back(r_iter);
Variant vref = ref; Variant vref = ref;
const Variant *refp[] = { &vref }; 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) { if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) {
valid = false; valid = false;
@ -1686,7 +1686,7 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
Callable::CallError ce; Callable::CallError ce;
ce.error = Callable::CallError::CALL_OK; ce.error = Callable::CallError::CALL_OK;
const Variant *refp[] = { &r_iter }; 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) { if (ce.error != Callable::CallError::CALL_OK) {
r_valid = false; r_valid = false;

View File

@ -606,8 +606,7 @@ public:
} break; } break;
case Animation::TYPE_METHOD: { case Animation::TYPE_METHOD: {
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "name")); 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,32,1,or_greater"));
p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,8,1"));
Dictionary d = animation->track_get_key_value(track, key); Dictionary d = animation->track_get_key_value(track, key);
ERR_FAIL_COND(!d.has("args")); ERR_FAIL_COND(!d.has("args"));
@ -1287,8 +1286,8 @@ public:
} break; } break;
case Animation::TYPE_METHOD: { case Animation::TYPE_METHOD: {
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "name")); 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); Dictionary d = animation->track_get_key_value(first_track, first_key);
ERR_FAIL_COND(!d.has("args")); ERR_FAIL_COND(!d.has("args"));
@ -3189,7 +3188,7 @@ AnimationTrackEdit *AnimationTrackEditPlugin::create_value_track_edit(Object *p_
}; };
Callable::CallError ce; 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; return nullptr;
} }

View File

@ -180,9 +180,6 @@ void ConnectDialog::_unbind_count_changed(double p_count) {
* Adds a new parameter bind to connection. * Adds a new parameter bind to connection.
*/ */
void ConnectDialog::_add_bind() { 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::Type vt = (Variant::Type)type_list->get_item_id(type_list->get_selected());
Variant value; Variant value;

View File

@ -610,12 +610,12 @@ void EditorDebuggerNode::_save_node_requested(ObjectID p_id, const String &p_fil
} }
// Remote inspector/edit. // 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) { if (!singleton) {
return; return;
} }
_for_all(singleton->tabs, [&](ScriptEditorDebugger *dbg) { _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);
}); });
} }

View File

@ -171,7 +171,7 @@ public:
// Remote inspector/edit. // Remote inspector/edit.
void request_remote_tree(); 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); static void _property_changeds(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
// LiveDebug // LiveDebug

View File

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

View File

@ -187,7 +187,7 @@ private:
void _live_edit_set(); void _live_edit_set();
void _live_edit_clear(); 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 _property_changed(Object *p_base, const StringName &p_property, const Variant &p_value);
void _error_activated(); void _error_activated();

View File

@ -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] }; const Variant *argptrs[4] = { &args[0], &args[1], &args[2], &args[3] };
cache[p_property] = p_value; 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) { 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. // 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 args[3] = { p_path, object->get(p_path), p_advance };
const Variant *argp[3] = { &args[0], &args[1], &args[2] }; 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) { 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. // 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 args[3] = { p_path, p_value, p_advance };
const Variant *argp[3] = { &args[0], &args[1], &args[2] }; 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) { void EditorInspector::_property_checked(const String &p_path, bool p_checked) {

View File

@ -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. // 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 args[3] = { String(get_edited_property()) + ":" + p_property, p_value, p_advance };
const Variant *argp[3] = { &args[0], &args[1], &args[2] }; 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) { void EditorPropertyResource::_sub_inspector_resource_selected(const RES &p_resource, const String &p_property) {

View File

@ -938,7 +938,7 @@ const Vector<Multiplayer::RPCConfig> GDScript::get_rpc_methods() const {
return rpc_functions; 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; GDScript *top = this;
while (top) { while (top) {
Map<StringName, GDScriptFunction *>::Element *E = top->member_functions.find(p_method); 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 //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 { 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) { if (member->setter) {
const Variant *val = &p_value; const Variant *val = &p_value;
Callable::CallError err; Callable::CallError err;
call(member->setter, &val, 1, err); callp(member->setter, &val, 1, err);
if (err.error == Callable::CallError::CALL_OK) { if (err.error == Callable::CallError::CALL_OK) {
return true; //function exists, call was successful return true; //function exists, call was successful
} else { } else {
@ -1335,7 +1335,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
if (E) { if (E) {
if (E->get().getter) { if (E->get().getter) {
Callable::CallError err; 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) { if (err.error == Callable::CallError::CALL_OK) {
return true; return true;
} }
@ -1520,7 +1520,7 @@ bool GDScriptInstance::has_method(const StringName &p_method) const {
return false; 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(); GDScript *sptr = script.ptr();
while (sptr) { while (sptr) {
Map<StringName, GDScriptFunction *>::Element *E = sptr->member_functions.find(p_method); 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) { String GDScriptInstance::to_string(bool *r_valid) {
if (has_method(CoreStringNames::get_singleton()->_to_string)) { if (has_method(CoreStringNames::get_singleton()->_to_string)) {
Callable::CallError ce; 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 (ce.error == Callable::CallError::CALL_OK) {
if (ret.get_type() != Variant::STRING) { if (ret.get_type() != Variant::STRING) {
if (r_valid) { if (r_valid) {

View File

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

View File

@ -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 { 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) { GDScriptRPCCallable::GDScriptRPCCallable(Object *p_object, const StringName &p_method) {

View File

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

View File

@ -573,7 +573,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
// Call test function. // Call test function.
Callable::CallError call_err; 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. // Tear down output handlers.
remove_print_handler(&_print_handler); remove_print_handler(&_print_handler);

View File

@ -1893,7 +1893,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const {
return false; 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()); ERR_FAIL_COND_V(!script.is_valid(), Variant());
GD_MONO_SCOPE_THREAD_ATTACH; GD_MONO_SCOPE_THREAD_ATTACH;
@ -2908,7 +2908,7 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage
} }
#endif #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)) { if (unlikely(GDMono::get_singleton() == nullptr)) {
// Probably not the best error but eh. // Probably not the best error but eh.
r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; 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 // 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() { void CSharpScript::_resource_path_changed() {

View File

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

View File

@ -199,7 +199,7 @@ MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoStrin
} }
Callable::CallError error; 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); *r_result = GDMonoMarshal::variant_to_mono_object(result);

View File

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

View File

@ -1621,7 +1621,7 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) {
conn_map.get_key_list(&keys); conn_map.get_key_list(&keys);
for (const int &E : keys) { for (const int &E : keys) {
for (const Set<int>::Element *F = conn_map[E].front(); F; F = F->next()) { 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());
} }
} }

View File

@ -1705,7 +1705,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p
return return_value; 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 r_error.error = Callable::CallError::CALL_OK; //ok by default
Map<StringName, Function>::Element *F = functions.find(p_method); Map<StringName, Function>::Element *F = functions.find(p_method);
@ -1798,13 +1798,13 @@ void VisualScriptInstance::notification(int p_notification) {
Variant what = p_notification; Variant what = p_notification;
const Variant *whatp = &what; const Variant *whatp = &what;
Callable::CallError ce; 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) { String VisualScriptInstance::to_string(bool *r_valid) {
if (has_method(CoreStringNames::get_singleton()->_to_string)) { if (has_method(CoreStringNames::get_singleton()->_to_string)) {
Callable::CallError ce; 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 (ce.error == Callable::CallError::CALL_OK) {
if (ret.get_type() != Variant::STRING) { if (ret.get_type() != Variant::STRING) {
if (r_valid) { if (r_valid) {

View File

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

View File

@ -1500,7 +1500,7 @@ public:
argp.write[i] = &arr[i]; 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) { if (ce.error != Callable::CallError::CALL_OK) {
r_error_str = "On call to '" + String(call->method) + "':"; r_error_str = "On call to '" + String(call->method) + "':";

View File

@ -772,9 +772,9 @@ public:
if (rpc_mode) { if (rpc_mode) {
call_rpc(object, p_inputs, input_args); call_rpc(object, p_inputs, input_args);
} else if (returns) { } 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 { } else {
object->call(function, p_inputs, input_args, r_error); object->callp(function, p_inputs, input_args, r_error);
} }
} break; } break;
case VisualScriptFunctionCall::CALL_MODE_NODE_PATH: { case VisualScriptFunctionCall::CALL_MODE_NODE_PATH: {
@ -795,9 +795,9 @@ public:
if (rpc_mode) { if (rpc_mode) {
call_rpc(node, p_inputs, input_args); call_rpc(node, p_inputs, input_args);
} else if (returns) { } 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 { } else {
another->call(function, p_inputs, input_args, r_error); another->callp(function, p_inputs, input_args, r_error);
} }
} break; } break;
@ -813,21 +813,21 @@ public:
} else if (returns) { } else if (returns) {
if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) { if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
if (returns >= 2) { 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) { } else if (returns == 1) {
Variant ret; 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 { } else {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE"; r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE";
return 0; return 0;
} }
} else { } 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 { } else {
Variant ret; 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) { if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
@ -846,9 +846,9 @@ public:
if (rpc_mode) { if (rpc_mode) {
call_rpc(object, p_inputs, input_args); call_rpc(object, p_inputs, input_args);
} else if (returns) { } 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 { } else {
object->call(function, p_inputs, input_args, r_error); object->callp(function, p_inputs, input_args, r_error);
} }
} break; } 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) { 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(); Object *obj = instance->get_owner_ptr();
obj->emit_signal(name, p_inputs, argcount); obj->emit_signalp(name, p_inputs, argcount);
return 0; return 0;
} }

View File

@ -3174,7 +3174,7 @@ public:
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return 0; 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; return 0;
} }
}; };

View File

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

View File

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

View File

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

View File

@ -485,14 +485,14 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
return success; 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; Variant ret;
bool found = _call_method(nullptr, p_method, p_args, p_argcount, r_error, ret); bool found = _call_method(nullptr, p_method, p_args, p_argcount, r_error, ret);
if (found) { if (found) {
return ret; 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() { 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(); return Variant();
} }

View File

@ -446,7 +446,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_callobject(JNIEnv *en
} }
Callable::CallError err; Callable::CallError err;
obj->call(str_method, (const Variant **)vptr, count, err); obj->callp(str_method, (const Variant **)vptr, count, err);
// something // something
env->PopLocalFrame(nullptr); 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); String str_method = jstring_to_string(method, env);
int count = env->GetArrayLength(params); 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); jobject obj = env->GetObjectArrayElement(params, i);
if (obj) { if (obj) {
args[i] = _jobject_to_variant(env, obj); args[i] = _jobject_to_variant(env, obj);
} }
env->DeleteLocalRef(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"); MessageQueue::get_singleton()->push_callp(obj, str_method, (const Variant **)argptrs, count);
obj->call_deferred(str_method, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
// something // something
env->PopLocalFrame(nullptr); env->PopLocalFrame(nullptr);
} }

View File

@ -114,10 +114,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS
String signal_name = jstring_to_string(j_signal_name, env); String signal_name = jstring_to_string(j_signal_name, env);
int count = env->GetArrayLength(j_signal_params); 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]; Variant *variant_params = (Variant *)alloca(sizeof(Variant) * count);
const Variant *args[VARIANT_ARG_MAX]; const Variant **args = (const Variant **)alloca(sizeof(Variant *) * count);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
jobject j_param = env->GetObjectArrayElement(j_signal_params, 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); 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) { JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths) {

View File

@ -81,7 +81,7 @@ protected:
public: public:
Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const override; 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; 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() {}
JavaScriptObjectImpl(int p_id) { _js_id = p_id; } JavaScriptObjectImpl(int p_id) { _js_id = p_id; }
~JavaScriptObjectImpl() { ~JavaScriptObjectImpl() {
@ -231,7 +231,7 @@ int JavaScriptObjectImpl::_variant2js(const void **p_args, int p_pos, godot_js_w
return type; 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; godot_js_wrapper_ex exchange;
const String method = p_method; const String method = p_method;
void *lock = nullptr; void *lock = nullptr;

View File

@ -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) { 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); _ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); 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); StringName method = a->method_track_get_name(i, E);
Vector<Variant> params = a->method_track_get_params(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 #ifdef DEBUG_ENABLED
if (!nc->node->has_method(method)) { if (!nc->node->has_method(method)) {
ERR_PRINT("Invalid method call '" + method + "'. '" + a->get_name() + "' at node '" + get_path() + "'."); ERR_PRINT("Invalid method call '" + method + "'. '" + a->get_name() + "' at node '" + get_path() + "'.");
} }
#endif #endif
static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
if (can_call) { if (can_call) {
if (method_call_mode == ANIMATION_METHOD_CALL_DEFERRED) { _call_object(nc->node, method, params, 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());
}
} }
} }
@ -754,7 +743,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx); Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) { if (!stream.is_valid()) {
nc->node->call("stop"); nc->node->call(SNAME("stop"));
nc->audio_playing = false; nc->audio_playing = false;
playing_caches.erase(nc); playing_caches.erase(nc);
} else { } else {
@ -764,14 +753,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
float len = stream->get_length(); float len = stream->get_length();
if (start_ofs > len - end_ofs) { if (start_ofs > len - end_ofs) {
nc->node->call("stop"); nc->node->call(SNAME("stop"));
nc->audio_playing = false; nc->audio_playing = false;
playing_caches.erase(nc); playing_caches.erase(nc);
continue; continue;
} }
nc->node->call("set_stream", stream); nc->node->call(SNAME("set_stream"), stream);
nc->node->call("play", start_ofs); nc->node->call(SNAME("play"), start_ofs);
nc->audio_playing = true; nc->audio_playing = true;
playing_caches.insert(nc); 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); Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) { if (!stream.is_valid()) {
nc->node->call("stop"); nc->node->call(SNAME("stop"));
nc->audio_playing = false; nc->audio_playing = false;
playing_caches.erase(nc); playing_caches.erase(nc);
} else { } 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 end_ofs = a->audio_track_get_key_end_offset(i, idx);
float len = stream->get_length(); float len = stream->get_length();
nc->node->call("set_stream", stream); nc->node->call(SNAME("set_stream"), stream);
nc->node->call("play", start_ofs); nc->node->call(SNAME("play"), start_ofs);
nc->audio_playing = true; nc->audio_playing = true;
playing_caches.insert(nc); playing_caches.insert(nc);
@ -833,7 +822,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (stop) { if (stop) {
//time to stop //time to stop
nc->node->call("stop"); nc->node->call(SNAME("stop"));
nc->audio_playing = false; nc->audio_playing = false;
playing_caches.erase(nc); playing_caches.erase(nc);
} }
@ -1544,7 +1533,7 @@ void AnimationPlayer::_animation_changed() {
void AnimationPlayer::_stop_playing_caches() { void AnimationPlayer::_stop_playing_caches() {
for (Set<TrackNodeCache *>::Element *E = playing_caches.front(); E; E = E->next()) { for (Set<TrackNodeCache *>::Element *E = playing_caches.front(); E; E = E->next()) {
if (E->get()->node && E->get()->audio_playing) { 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) { if (E->get()->node && E->get()->animation_playing) {
AnimationPlayer *player = Object::cast_to<AnimationPlayer>(E->get()->node); AnimationPlayer *player = Object::cast_to<AnimationPlayer>(E->get()->node);

View File

@ -490,7 +490,7 @@ void AnimationTree::set_active(bool p_active) {
if (!active && is_inside_tree()) { if (!active && is_inside_tree()) {
for (Set<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) { for (Set<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) {
if (ObjectDB::get_instance(E->get()->object_id)) { 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; 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) { void AnimationTree::_process_graph(double p_delta) {
_update_properties(); //if properties need updating, update them _update_properties(); //if properties need updating, update them
@ -1286,25 +1301,10 @@ void AnimationTree::_process_graph(double p_delta) {
for (int &F : indices) { for (int &F : indices) {
StringName method = a->method_track_get_name(i, F); StringName method = a->method_track_get_name(i, F);
Vector<Variant> params = a->method_track_get_params(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) { if (can_call) {
t->object->call_deferred( _call_object(t->object, method, params, true);
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());
} }
} }
} break; } break;
case Animation::TYPE_BEZIER: { case Animation::TYPE_BEZIER: {
TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track); 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); Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) { if (!stream.is_valid()) {
t->object->call("stop"); t->object->call(SNAME("stop"));
t->playing = false; t->playing = false;
playing_caches.erase(t); playing_caches.erase(t);
} else { } else {
@ -1341,14 +1341,14 @@ void AnimationTree::_process_graph(double p_delta) {
double len = stream->get_length(); double len = stream->get_length();
if (start_ofs > len - end_ofs) { if (start_ofs > len - end_ofs) {
t->object->call("stop"); t->object->call(SNAME("stop"));
t->playing = false; t->playing = false;
playing_caches.erase(t); playing_caches.erase(t);
continue; continue;
} }
t->object->call("set_stream", stream); t->object->call(SNAME("set_stream"), stream);
t->object->call("play", start_ofs); t->object->call(SNAME("play"), start_ofs);
t->playing = true; t->playing = true;
playing_caches.insert(t); 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); Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) { if (!stream.is_valid()) {
t->object->call("stop"); t->object->call(SNAME("stop"));
t->playing = false; t->playing = false;
playing_caches.erase(t); playing_caches.erase(t);
} else { } 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 end_ofs = a->audio_track_get_key_end_offset(i, idx);
double len = stream->get_length(); double len = stream->get_length();
t->object->call("set_stream", stream); t->object->call(SNAME("set_stream"), stream);
t->object->call("play", start_ofs); t->object->call(SNAME("play"), start_ofs);
t->playing = true; t->playing = true;
playing_caches.insert(t); playing_caches.insert(t);
@ -1416,7 +1416,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (stop) { if (stop) {
//time to stop //time to stop
t->object->call("stop"); t->object->call(SNAME("stop"));
t->playing = false; t->playing = false;
playing_caches.erase(t); playing_caches.erase(t);
} }
@ -1424,10 +1424,10 @@ void AnimationTree::_process_graph(double p_delta) {
} }
real_t db = Math::linear2db(MAX(blend, 0.00001)); real_t db = Math::linear2db(MAX(blend, 0.00001));
if (t->object->has_method("set_unit_db")) { if (t->object->has_method(SNAME("set_unit_db"))) {
t->object->call("set_unit_db", db); t->object->call(SNAME("set_unit_db"), db);
} else { } else {
t->object->call("set_volume_db", db); t->object->call(SNAME("set_volume_db"), db);
} }
} break; } break;
case Animation::TYPE_ANIMATION: { case Animation::TYPE_ANIMATION: {

View File

@ -34,6 +34,7 @@
#include "core/debugger/engine_profiler.h" #include "core/debugger/engine_profiler.h"
#include "core/io/marshalls.h" #include "core/io/marshalls.h"
#include "core/object/script_language.h" #include "core/object/script_language.h"
#include "core/templates/local_vector.h"
#include "scene/main/scene_tree.h" #include "scene/main/scene_tree.h"
#include "scene/main/window.h" #include "scene/main/window.h"
#include "scene/resources/packed_scene.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]); live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]);
} else if (p_msg == "live_node_call") { } else if (p_msg == "live_node_call") {
ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA); LocalVector<Variant> args;
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 *> 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") { } else if (p_msg == "live_res_call") {
ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA); 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") { } else if (p_msg == "live_create_node") {
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA); 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); _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(); SceneTree *scene_tree = SceneTree::get_singleton();
if (!scene_tree) { if (!scene_tree) {
return; 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); 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); _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)) { if (!live_edit_resource_cache.has(p_id)) {
return; return;
} }
@ -715,7 +733,8 @@ void LiveEditor::_res_call_func(int p_id, const StringName &p_method, VARIANT_AR
return; 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) { void LiveEditor::_root_func(const NodePath &p_scene_path, const String &p_scene_from) {

View File

@ -148,10 +148,10 @@ private:
void _node_set_func(int p_id, const StringName &p_prop, const Variant &p_value); 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_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_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_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 _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); void _create_node_func(const NodePath &p_parent, const String &p_type, const String &p_name);

View File

@ -1186,7 +1186,7 @@ void recursive_call_aux(TreeItem *p_item, const StringName &p_method, const Vari
if (!p_item) { if (!p_item) {
return; 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(); TreeItem *c = p_item->get_first_child();
while (c) { while (c) {
recursive_call_aux(c, p_method, p_args, p_argcount, r_error); recursive_call_aux(c, p_method, p_args, p_argcount, r_error);

View File

@ -211,7 +211,7 @@ void Node::_propagate_enter_tree() {
if (data.parent) { if (data.parent) {
Variant c = this; Variant c = this;
const Variant *cptr = &c; 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++; data.blocked++;
@ -287,7 +287,7 @@ void Node::_propagate_exit_tree() {
if (data.parent) { if (data.parent) {
Variant c = this; Variant c = this;
const Variant *cptr = &c; 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 // exit groups
@ -582,34 +582,6 @@ uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc
/***** RPC FUNCTIONS ********/ /***** 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) { Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 1) { if (p_argcount < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; 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 { bool Node::has_node_and_resource(const NodePath &p_path) const {
if (!has_node(p_path)) { if (!has_node(p_path)) {
return false; return false;

View File

@ -420,7 +420,11 @@ public:
void set_scene_instance_load_placeholder(bool p_enable); void set_scene_instance_load_placeholder(bool p_enable);
bool get_scene_instance_load_placeholder() const; 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); 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 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; Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const;
void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel template <typename... VarArgs>
void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel 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); void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
Ref<MultiplayerAPI> get_multiplayer() const; Ref<MultiplayerAPI> get_multiplayer() const;

View File

@ -175,13 +175,13 @@ void SceneTree::_flush_ugc() {
while (unique_group_calls.size()) { while (unique_group_calls.size()) {
Map<UGCall, Vector<Variant>>::Element *E = unique_group_calls.front(); 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++) { 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_flagsp(GROUP_CALL_REALTIME, E->key().group, E->key().call, argptrs, E->get().size());
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]);
unique_group_calls.erase(E); unique_group_calls.erase(E);
} }
@ -210,7 +210,7 @@ void SceneTree::_update_group_order(Group &g, bool p_use_priority) {
g.changed = false; 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); Map<StringName, Group>::Element *E = group_map.find(p_group);
if (!E) { if (!E) {
return; return;
@ -231,14 +231,9 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
return; return;
} }
VARIANT_ARGPTRS;
Vector<Variant> args; Vector<Variant> args;
for (int i = 0; i < VARIANT_ARG_MAX; i++) { for (int i = 0; i < p_argcount; i++) {
if (argptr[i]->get_type() == Variant::NIL) { args.push_back(*p_args[i]);
break;
}
args.push_back(*argptr[i]);
} }
unique_group_calls[ug] = args; 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) { 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 { } 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) { 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 { } 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) { void SceneTree::notify_group(const StringName &p_group, int p_notification) {
notify_group_flags(0, p_group, 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]; int flags = *p_args[0];
StringName group = *p_args[1]; StringName group = *p_args[1];
StringName method = *p_args[2]; StringName method = *p_args[2];
Variant v[VARIANT_ARG_MAX];
for (int i = 0; i < MIN(p_argcount - 3, 5); i++) { call_group_flagsp(flags, group, method, p_args + 3, p_argcount - 3);
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]);
return Variant(); return Variant();
} }
@ -950,14 +937,8 @@ Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable:
StringName group = *p_args[0]; StringName group = *p_args[0];
StringName method = *p_args[1]; StringName method = *p_args[1];
Variant v[VARIANT_ARG_MAX];
for (int i = 0; i < MIN(p_argcount - 2, 5); i++) { call_group_flagsp(0, group, method, p_args + 2, p_argcount - 2);
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]);
return Variant(); return Variant();
} }

View File

@ -229,14 +229,33 @@ public:
_FORCE_INLINE_ Window *get_root() const { return root; } _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 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 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 notify_group(const StringName &p_group, int p_notification);
void set_group(const StringName &p_group, const String &p_name, const Variant &p_value); 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(); void flush_transform_notifications();
virtual void initialize() override; virtual void initialize() override;

View File

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

View File

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