summaryrefslogtreecommitdiff
path: root/core/object
diff options
context:
space:
mode:
Diffstat (limited to 'core/object')
-rw-r--r--core/object/class_db.cpp21
-rw-r--r--core/object/class_db.h17
-rw-r--r--core/object/make_virtuals.py7
-rw-r--r--core/object/message_queue.cpp41
-rw-r--r--core/object/message_queue.h43
-rw-r--r--core/object/object.cpp60
-rw-r--r--core/object/object.h52
-rw-r--r--core/object/script_language.cpp14
-rw-r--r--core/object/script_language.h20
-rw-r--r--core/object/undo_redo.cpp55
-rw-r--r--core/object/undo_redo.h32
11 files changed, 189 insertions, 173 deletions
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index c29316c089..08e12dfcaa 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -557,6 +557,19 @@ bool ClassDB::can_instantiate(const StringName &p_class) {
return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance));
}
+bool ClassDB::is_virtual(const StringName &p_class) {
+ OBJTYPE_RLOCK;
+
+ ClassInfo *ti = classes.getptr(p_class);
+ ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
+#ifdef TOOLS_ENABLED
+ if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) {
+ return false;
+ }
+#endif
+ return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance) && ti->is_virtual);
+}
+
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
OBJTYPE_WLOCK;
@@ -1197,7 +1210,7 @@ bool ClassDB::set_property(Object *p_object, const StringName &p_property, const
if (psg->_setptr) {
psg->_setptr->call(p_object, arg, 2, ce);
} else {
- p_object->call(psg->setter, arg, 2, ce);
+ p_object->callp(psg->setter, arg, 2, ce);
}
} else {
@@ -1205,7 +1218,7 @@ bool ClassDB::set_property(Object *p_object, const StringName &p_property, const
if (psg->_setptr) {
psg->_setptr->call(p_object, arg, 1, ce);
} else {
- p_object->call(psg->setter, arg, 1, ce);
+ p_object->callp(psg->setter, arg, 1, ce);
}
}
@@ -1238,14 +1251,14 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia
Variant index = psg->index;
const Variant *arg[1] = { &index };
Callable::CallError ce;
- r_value = p_object->call(psg->getter, arg, 1, ce);
+ r_value = p_object->callp(psg->getter, arg, 1, ce);
} else {
Callable::CallError ce;
if (psg->_getptr) {
r_value = psg->_getptr->call(p_object, nullptr, 0, ce);
} else {
- r_value = p_object->call(psg->getter, nullptr, 0, ce);
+ r_value = p_object->callp(psg->getter, nullptr, 0, ce);
}
}
return true;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 5d258a29bf..580ae3582f 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -118,6 +118,7 @@ public:
StringName name;
bool disabled = false;
bool exposed = false;
+ bool is_virtual = false;
Object *(*creation_func)() = nullptr;
ClassInfo() {}
@@ -156,20 +157,21 @@ public:
}
template <class T>
- static void register_class() {
+ static void register_class(bool p_virtual = false) {
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->creation_func = &creator<T>;
t->exposed = true;
+ t->is_virtual = p_virtual;
t->class_ptr = T::get_class_ptr_static();
t->api = current_api;
T::register_custom_data_to_otdb();
}
template <class T>
- static void register_virtual_class() {
+ static void register_abstract_class() {
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
@@ -210,6 +212,7 @@ public:
static bool class_exists(const StringName &p_class);
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instantiate(const StringName &p_class);
+ static bool is_virtual(const StringName &p_class);
static Object *instantiate(const StringName &p_class);
static void set_object_extension_instance(Object *p_object, const StringName &p_class, GDExtensionClassInstancePtr p_instance);
@@ -436,9 +439,13 @@ _FORCE_INLINE_ Vector<Error> errarray(P... p_args) {
if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
::ClassDB::register_class<m_class>(); \
}
-#define GDREGISTER_VIRTUAL_CLASS(m_class) \
- if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
- ::ClassDB::register_virtual_class<m_class>(); \
+#define GDREGISTER_VIRTUAL_CLASS(m_class) \
+ if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
+ ::ClassDB::register_class<m_class>(true); \
+ }
+#define GDREGISTER_ABSTRACT_CLASS(m_class) \
+ if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
+ ::ClassDB::register_abstract_class<m_class>(); \
}
#include "core/disabled_classes.gen.h"
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 5de1b49026..2e909b8042 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -3,12 +3,13 @@ proto = """
StringName _gdvirtual_##m_name##_sn = #m_name;\\
mutable bool _gdvirtual_##m_name##_initialized = false;\\
mutable GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\
+template<bool required>\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
if (script_instance) {\\
Callable::CallError ce; \\
$CALLSIARGS\\
- $CALLSIBEGINscript_instance->call(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
+ $CALLSIBEGINscript_instance->callp(_gdvirtual_##m_name##_sn, $CALLSIARGPASS, ce);\\
if (ce.error == Callable::CallError::CALL_OK) {\\
$CALLSIRET\\
return true;\\
@@ -25,6 +26,10 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
$CALLPTRRET\\
return true;\\
}\\
+ \\
+ if (required) {\\
+ WARN_PRINT_ONCE("Required virtual method: "+get_class()+"::" + #m_name + " must be overriden before calling.");\\
+ }\\
\\
return false;\\
}\\
diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp
index 3c828eabd9..79c36ac81f 100644
--- a/core/object/message_queue.cpp
+++ b/core/object/message_queue.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/core_string_names.h"
+#include "core/object/class_db.h"
#include "core/object/script_language.h"
MessageQueue *MessageQueue::singleton = nullptr;
@@ -40,23 +41,8 @@ MessageQueue *MessageQueue::get_singleton() {
return singleton;
}
-Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {
- return push_callable(Callable(p_id, p_method), p_args, p_argcount, p_show_error);
-}
-
-Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
-
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- return push_call(p_id, p_method, argptr, argc, false);
+Error MessageQueue::push_callp(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {
+ return push_callablep(Callable(p_id, p_method), p_args, p_argcount, p_show_error);
}
Error MessageQueue::push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value) {
@@ -113,8 +99,8 @@ Error MessageQueue::push_notification(ObjectID p_id, int p_notification) {
return OK;
}
-Error MessageQueue::push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
- return push_call(p_object->get_instance_id(), p_method, VARIANT_ARG_PASS);
+Error MessageQueue::push_callp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) {
+ return push_callp(p_object->get_instance_id(), p_method, p_args, p_argcount, p_show_error);
}
Error MessageQueue::push_notification(Object *p_object, int p_notification) {
@@ -125,7 +111,7 @@ Error MessageQueue::push_set(Object *p_object, const StringName &p_prop, const V
return push_set(p_object->get_instance_id(), p_prop, p_value);
}
-Error MessageQueue::push_callable(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error) {
+Error MessageQueue::push_callablep(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error) {
_THREAD_SAFE_METHOD_
int room_needed = sizeof(Message) + sizeof(Variant) * p_argcount;
@@ -155,21 +141,6 @@ Error MessageQueue::push_callable(const Callable &p_callable, const Variant **p_
return OK;
}
-Error MessageQueue::push_callable(const Callable &p_callable, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
-
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- return push_callable(p_callable, argptr, argc);
-}
-
void MessageQueue::statistics() {
Map<StringName, int> set_count;
Map<int, int> notify_count;
diff --git a/core/object/message_queue.h b/core/object/message_queue.h
index a4449cf473..eaab01d0aa 100644
--- a/core/object/message_queue.h
+++ b/core/object/message_queue.h
@@ -31,8 +31,11 @@
#ifndef MESSAGE_QUEUE_H
#define MESSAGE_QUEUE_H
-#include "core/object/class_db.h"
+#include "core/object/object_id.h"
#include "core/os/thread_safe.h"
+#include "core/variant/variant.h"
+
+class Object;
class MessageQueue {
_THREAD_SAFE_CLASS_
@@ -73,14 +76,42 @@ class MessageQueue {
public:
static MessageQueue *get_singleton();
- Error push_call(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error = false);
- Error push_call(ObjectID p_id, const StringName &p_method, VARIANT_ARG_LIST);
+ Error push_callp(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error = false);
+ template <typename... VarArgs>
+ Error push_call(ObjectID p_id, const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ return push_callp(p_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+
Error push_notification(ObjectID p_id, int p_notification);
Error push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value);
- Error push_callable(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error = false);
- Error push_callable(const Callable &p_callable, VARIANT_ARG_LIST);
+ Error push_callablep(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error = false);
+
+ template <typename... VarArgs>
+ Error push_callable(const Callable &p_callable, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ return push_callablep(p_callable, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+
+ Error push_callp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error = false);
+ template <typename... VarArgs>
+ Error push_call(Object *p_object, const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ return push_callp(p_object, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
- Error push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
Error push_notification(Object *p_object, int p_notification);
Error push_set(Object *p_object, const StringName &p_prop, const Variant &p_value);
diff --git a/core/object/object.cpp b/core/object/object.cpp
index a8a49bd22e..096edd4e60 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -624,8 +624,12 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
}
if (_extension) {
- p_list->push_back(PropertyInfo(Variant::NIL, _extension->class_name, PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
- ClassDB::get_property_list(_extension->class_name, p_list, true, this);
+ const ObjectNativeExtension *current_extension = _extension;
+ while (current_extension) {
+ p_list->push_back(PropertyInfo(Variant::NIL, current_extension->class_name, PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY));
+ ClassDB::get_property_list(current_extension->class_name, p_list, true, this);
+ current_extension = current_extension->parent;
+ }
}
if (_extension && _extension->get_property_list) {
@@ -679,7 +683,7 @@ Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::Cal
StringName method = *p_args[0];
- return call(method, &p_args[1], p_argcount - 1, r_error);
+ return callp(method, &p_args[1], p_argcount - 1, r_error);
}
Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
@@ -700,7 +704,7 @@ Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Call
StringName method = *p_args[0];
- MessageQueue::get_singleton()->push_call(get_instance_id(), method, &p_args[1], p_argcount - 1, true);
+ MessageQueue::get_singleton()->push_callp(get_instance_id(), method, &p_args[1], p_argcount - 1, true);
return Variant();
}
@@ -750,31 +754,14 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) {
}
Callable::CallError ce;
- Variant ret = call(p_method, argptrs, p_args.size(), ce);
+ Variant ret = callp(p_method, argptrs, p_args.size(), ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(Variant(), "Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce) + ".");
}
return ret;
}
-Variant Object::call(const StringName &p_name, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- Callable::CallError error;
-
- Variant ret = call(p_name, argptr, argc, error);
- return ret;
-}
-
-Variant Object::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_OK;
if (p_method == CoreStringNames::get_singleton()->_free) {
@@ -808,7 +795,7 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a
OBJ_DEBUG_LOCK
if (script_instance) {
- ret = script_instance->call(p_method, p_args, p_argcount, r_error);
+ ret = script_instance->callp(p_method, p_args, p_argcount, r_error);
//force jumptable
switch (r_error.error) {
case Callable::CallError::CALL_OK:
@@ -1027,12 +1014,12 @@ Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::C
args = &p_args[1];
}
- emit_signal(signal, args, argc);
+ emit_signalp(signal, args, argc);
return Variant();
}
-Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount) {
+Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int p_argcount) {
if (_block_signals) {
return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked
}
@@ -1091,7 +1078,7 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
}
if (c.flags & CONNECT_DEFERRED) {
- MessageQueue::get_singleton()->push_callable(c.callable, args, argc, true);
+ MessageQueue::get_singleton()->push_callablep(c.callable, args, argc, true);
} else {
Callable::CallError ce;
_emitting = true;
@@ -1139,21 +1126,6 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int
return err;
}
-Error Object::emit_signal(const StringName &p_name, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
-
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- return emit_signal(p_name, argptr, argc);
-}
-
void Object::_add_user_signal(const String &p_name, const Array &p_args) {
// this version of add_user_signal is meant to be used from scripts or external apis
// without access to ADD_SIGNAL in bind_methods
@@ -1648,10 +1620,6 @@ void Object::_bind_methods() {
BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED);
}
-void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) {
- MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS);
-}
-
void Object::set_deferred(const StringName &p_property, const Variant &p_value) {
MessageQueue::get_singleton()->push_set(this, p_property, p_value);
}
diff --git a/core/object/object.h b/core/object/object.h
index b5be1cf0e7..3aa7e3f9f2 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -32,6 +32,7 @@
#define OBJECT_H
#include "core/extension/gdnative_interface.h"
+#include "core/object/message_queue.h"
#include "core/object/object_id.h"
#include "core/os/rw_lock.h"
#include "core/os/spin_lock.h"
@@ -44,14 +45,6 @@
#include "core/variant/callable_bind.h"
#include "core/variant/variant.h"
-#define VARIANT_ARG_LIST const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant()
-#define VARIANT_ARG_PASS p_arg1, p_arg2, p_arg3, p_arg4, p_arg5, p_arg6, p_arg7, p_arg8
-#define VARIANT_ARG_DECLARE const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5, const Variant &p_arg6, const Variant &p_arg7, const Variant &p_arg8
-#define VARIANT_ARG_MAX 8
-#define VARIANT_ARGPTRS const Variant *argptr[8] = { &p_arg1, &p_arg2, &p_arg3, &p_arg4, &p_arg5, &p_arg6, &p_arg7, &p_arg8 };
-#define VARIANT_ARGPTRS_PASS *argptr[0], *argptr[1], *argptr[2], *argptr[3], *argptr[4], *argptr[5], *argptr[6]], *argptr[7]
-#define VARIANT_ARGS_FROM_ARRAY(m_arr) m_arr[0], m_arr[1], m_arr[2], m_arr[3], m_arr[4], m_arr[5], m_arr[6], m_arr[7]
-
enum PropertyHint {
PROPERTY_HINT_NONE, ///< no hint provided.
PROPERTY_HINT_RANGE, ///< hint_text = "min,max[,step][,or_greater][,or_lesser][,noslider][,radians][,degrees][,exp][,suffix:<keyword>] range.
@@ -262,6 +255,7 @@ struct ObjectNativeExtension {
GDNativeExtensionClassToString to_string;
GDNativeExtensionClassReference reference;
GDNativeExtensionClassReference unreference;
+ GDNativeExtensionClassGetRID get_rid;
_FORCE_INLINE_ bool is_class(const String &p_class) const {
const ObjectNativeExtension *e = this;
@@ -280,8 +274,12 @@ struct ObjectNativeExtension {
GDNativeExtensionClassGetVirtual get_virtual;
};
-#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
-#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__)
+#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
+#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<false>(__VA_ARGS__)
+
+#define GDVIRTUAL_REQUIRED_CALL(m_name, ...) _gdvirtual_##m_name##_call<true>(__VA_ARGS__)
+#define GDVIRTUAL_REQUIRED_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<true>(__VA_ARGS__)
+
#ifdef DEBUG_METHODS_ENABLED
#define GDVIRTUAL_BIND(m_name, ...) ::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), true, sarray(__VA_ARGS__));
#else
@@ -734,8 +732,18 @@ public:
bool has_method(const StringName &p_method) const;
void get_method_list(List<MethodInfo> *p_list) const;
Variant callv(const StringName &p_method, const Array &p_args);
- virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- Variant call(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
+ virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+
+ template <typename... VarArgs>
+ Variant call(const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ Callable::CallError cerr;
+ return callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), cerr);
+ }
void notification(int p_notification, bool p_reversed = false);
virtual String to_string();
@@ -769,8 +777,18 @@ public:
void set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance);
void add_user_signal(const MethodInfo &p_signal);
- Error emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
- Error emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount);
+
+ template <typename... VarArgs>
+ Error emit_signal(const StringName &p_name, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ return emit_signalp(p_name, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+
+ Error emit_signalp(const StringName &p_name, const Variant **p_args, int p_argcount);
bool has_signal(const StringName &p_name) const;
void get_signal_list(List<MethodInfo> *p_signals) const;
void get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const;
@@ -782,7 +800,11 @@ public:
void disconnect(const StringName &p_signal, const Callable &p_callable);
bool is_connected(const StringName &p_signal, const Callable &p_callable) const;
- void call_deferred(const StringName &p_method, VARIANT_ARG_LIST);
+ template <typename... VarArgs>
+ void call_deferred(const StringName &p_name, VarArgs... p_args) {
+ MessageQueue::get_singleton()->push_call(this, p_name, p_args...);
+ }
+
void set_deferred(const StringName &p_property, const Variant &p_value);
void set_block_signals(bool p_block);
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index b14296b815..11440c37fe 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -310,20 +310,6 @@ void ScriptInstance::get_property_state(List<Pair<StringName, Variant>> &state)
}
}
-Variant ScriptInstance::call(const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
- int argc = 0;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- Callable::CallError error;
- return call(p_method, argptr, argc, error);
-}
-
void ScriptInstance::property_set_fallback(const StringName &, const Variant &, bool *r_valid) {
if (r_valid) {
*r_valid = false;
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 4b18d9a5e8..2122f785b6 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -176,8 +176,20 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
virtual bool has_method(const StringName &p_method) const = 0;
- virtual Variant call(const StringName &p_method, VARIANT_ARG_LIST);
- virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0;
+
+ virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) = 0;
+
+ template <typename... VarArgs>
+ Variant call(const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ Callable::CallError cerr;
+ return callp(p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args), cerr);
+ }
+
virtual void notification(int p_notification) = 0;
virtual String to_string(bool *r_valid) {
if (r_valid) {
@@ -419,8 +431,8 @@ public:
virtual void get_method_list(List<MethodInfo> *p_list) const;
virtual bool has_method(const StringName &p_method) const;
- virtual Variant call(const StringName &p_method, VARIANT_ARG_LIST) { return Variant(); }
- virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+
+ virtual Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return Variant();
}
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index b78328fb42..ee8eb97a93 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -126,8 +126,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) {
force_keep_in_merge_ends = false;
}
-void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS
+void UndoRedo::add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
ERR_FAIL_COND(p_object == nullptr);
ERR_FAIL_COND(action_level <= 0);
ERR_FAIL_COND((current_action + 1) >= actions.size());
@@ -140,14 +139,13 @@ void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIA
do_op.type = Operation::TYPE_METHOD;
do_op.name = p_method;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- do_op.args[i] = *argptr[i];
+ for (int i = 0; i < p_argcount; i++) {
+ do_op.args.push_back(*p_args[i]);
}
actions.write[current_action + 1].do_ops.push_back(do_op);
}
-void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS
+void UndoRedo::add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount) {
ERR_FAIL_COND(p_object == nullptr);
ERR_FAIL_COND(action_level <= 0);
ERR_FAIL_COND((current_action + 1) >= actions.size());
@@ -167,8 +165,8 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR
undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_method;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- undo_op.args[i] = *argptr[i];
+ for (int i = 0; i < p_argcount; i++) {
+ undo_op.args.push_back(*p_args[i]);
}
actions.write[current_action + 1].undo_ops.push_back(undo_op);
}
@@ -185,7 +183,7 @@ void UndoRedo::add_do_property(Object *p_object, const StringName &p_property, c
do_op.type = Operation::TYPE_PROPERTY;
do_op.name = p_property;
- do_op.args[0] = p_value;
+ do_op.args.push_back(p_value);
actions.write[current_action + 1].do_ops.push_back(do_op);
}
@@ -208,7 +206,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property,
undo_op.type = Operation::TYPE_PROPERTY;
undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends;
undo_op.name = p_property;
- undo_op.args[0] = p_value;
+ undo_op.args.push_back(p_value);
actions.write[current_action + 1].undo_ops.push_back(undo_op);
}
@@ -314,23 +312,18 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
switch (op.type) {
case Operation::TYPE_METHOD: {
+ int argc = op.args.size();
Vector<const Variant *> argptrs;
- argptrs.resize(VARIANT_ARG_MAX);
- int argc = 0;
+ argptrs.resize(argc);
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (op.args[i].get_type() == Variant::NIL) {
- break;
- }
+ for (int i = 0; i < argc; i++) {
argptrs.write[i] = &op.args[i];
- argc++;
}
- argptrs.resize(argc);
Callable::CallError ce;
- obj->call(op.name, (const Variant **)argptrs.ptr(), argc, ce);
+ obj->callp(op.name, (const Variant **)argptrs.ptr(), argc, ce);
if (ce.error != Callable::CallError::CALL_OK) {
- ERR_PRINT("Error calling method from signal '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, (const Variant **)argptrs.ptr(), argc, ce));
+ ERR_PRINT("Error calling UndoRedo method operation '" + String(op.name) + "': " + Variant::get_call_error_text(obj, op.name, (const Variant **)argptrs.ptr(), argc, ce));
}
#ifdef TOOLS_ENABLED
Resource *res = Object::cast_to<Resource>(obj);
@@ -341,7 +334,7 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
#endif
if (method_callback) {
- method_callback(method_callbck_ud, obj, op.name, VARIANT_ARGS_FROM_ARRAY(op.args));
+ method_callback(method_callback_ud, obj, op.name, (const Variant **)argptrs.ptr(), argc);
}
} break;
case Operation::TYPE_PROPERTY: {
@@ -439,7 +432,7 @@ void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback, void
void UndoRedo::set_method_notify_callback(MethodNotifyCallback p_method_callback, void *p_ud) {
method_callback = p_method_callback;
- method_callbck_ud = p_ud;
+ method_callback_ud = p_ud;
}
void UndoRedo::set_property_notify_callback(PropertyNotifyCallback p_property_callback, void *p_ud) {
@@ -477,14 +470,7 @@ Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callabl
Object *object = *p_args[0];
StringName method = *p_args[1];
- Variant v[VARIANT_ARG_MAX];
-
- for (int i = 0; i < MIN(VARIANT_ARG_MAX, p_argcount - 2); ++i) {
- v[i] = *p_args[i + 2];
- }
-
- static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
- add_do_method(object, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+ add_do_methodp(object, method, p_args + 2, p_argcount - 2);
return Variant();
}
@@ -514,14 +500,7 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla
Object *object = *p_args[0];
StringName method = *p_args[1];
- Variant v[VARIANT_ARG_MAX];
-
- for (int i = 0; i < MIN(VARIANT_ARG_MAX, p_argcount - 2); ++i) {
- v[i] = *p_args[i + 2];
- }
-
- static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
- add_undo_method(object, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+ add_undo_methodp(object, method, p_args + 2, p_argcount - 2);
return Variant();
}
diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h
index 5eede74e2d..ecd7a21167 100644
--- a/core/object/undo_redo.h
+++ b/core/object/undo_redo.h
@@ -49,7 +49,7 @@ public:
Variant _add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Variant _add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
- typedef void (*MethodNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_name, VARIANT_ARG_DECLARE);
+ typedef void (*MethodNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_name, const Variant **p_args, int p_argcount);
typedef void (*PropertyNotifyCallback)(void *p_ud, Object *p_base, const StringName &p_property, const Variant &p_value);
private:
@@ -65,7 +65,7 @@ private:
Ref<RefCounted> ref;
ObjectID object;
StringName name;
- Variant args[VARIANT_ARG_MAX];
+ Vector<Variant> args;
void delete_reference();
};
@@ -92,7 +92,7 @@ private:
CommitNotifyCallback callback = nullptr;
void *callback_ud = nullptr;
- void *method_callbck_ud = nullptr;
+ void *method_callback_ud = nullptr;
void *prop_callback_ud = nullptr;
MethodNotifyCallback method_callback = nullptr;
@@ -106,8 +106,30 @@ protected:
public:
void create_action(const String &p_name = "", MergeMode p_mode = MERGE_DISABLE);
- void add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
- void add_undo_method(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST);
+ void add_do_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
+ void add_undo_methodp(Object *p_object, const StringName &p_method, const Variant **p_args, int p_argcount);
+
+ template <typename... VarArgs>
+ void add_do_method(Object *p_object, const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+
+ add_do_methodp(p_object, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+ template <typename... VarArgs>
+ void add_undo_method(Object *p_object, const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+
+ add_undo_methodp(p_object, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+
void add_do_property(Object *p_object, const StringName &p_property, const Variant &p_value);
void add_undo_property(Object *p_object, const StringName &p_property, const Variant &p_value);
void add_do_reference(Object *p_object);