summaryrefslogtreecommitdiffstats
path: root/core/variant/callable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/variant/callable.cpp')
-rw-r--r--core/variant/callable.cpp83
1 files changed, 68 insertions, 15 deletions
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index 0b1174c873..c6fbfd93a1 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -30,14 +30,14 @@
#include "callable.h"
-#include "callable_bind.h"
-#include "core/object/message_queue.h"
#include "core/object/object.h"
#include "core/object/ref_counted.h"
#include "core/object/script_language.h"
+#include "core/variant/callable_bind.h"
+#include "core/variant/variant_callable.h"
void Callable::call_deferredp(const Variant **p_arguments, int p_argcount) const {
- MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount);
+ MessageQueue::get_singleton()->push_callablep(*this, p_arguments, p_argcount, true);
}
void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const {
@@ -92,10 +92,31 @@ Error Callable::rpcp(int p_id, const Variant **p_arguments, int p_argcount, Call
r_call_error.expected = 0;
return ERR_UNCONFIGURED;
} else if (!is_custom()) {
- r_call_error.error = CallError::CALL_ERROR_INVALID_METHOD;
- r_call_error.argument = 0;
- r_call_error.expected = 0;
- return ERR_UNCONFIGURED;
+ Object *obj = ObjectDB::get_instance(ObjectID(object));
+#ifdef DEBUG_ENABLED
+ if (!obj || !obj->is_class("Node")) {
+ r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ r_call_error.argument = 0;
+ r_call_error.expected = 0;
+ return ERR_UNCONFIGURED;
+ }
+#endif
+
+ int argcount = p_argcount + 2;
+ const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * argcount);
+ const Variant args[2] = { p_id, method };
+
+ argptrs[0] = &args[0];
+ argptrs[1] = &args[1];
+ for (int i = 0; i < p_argcount; ++i) {
+ argptrs[i + 2] = p_arguments[i];
+ }
+
+ CallError tmp;
+ Error err = (Error)obj->callp(SNAME("rpc_id"), argptrs, argcount, tmp).operator int64_t();
+
+ r_call_error.error = Callable::CallError::CALL_OK;
+ return err;
} else {
return custom->rpc(p_id, p_arguments, p_argcount, r_call_error);
}
@@ -163,6 +184,20 @@ StringName Callable::get_method() const {
return method;
}
+int Callable::get_argument_count(bool *r_is_valid) const {
+ if (is_custom()) {
+ bool valid = false;
+ return custom->get_argument_count(r_is_valid ? *r_is_valid : valid);
+ } else if (!is_null()) {
+ return get_object()->get_method_argument_count(method, r_is_valid);
+ } else {
+ if (r_is_valid) {
+ *r_is_valid = false;
+ }
+ return 0;
+ }
+}
+
int Callable::get_bound_arguments_count() const {
if (!is_null() && is_custom()) {
return custom->get_bound_arguments_count();
@@ -328,14 +363,27 @@ Callable::operator String() const {
}
}
+Callable Callable::create(const Variant &p_variant, const StringName &p_method) {
+ ERR_FAIL_COND_V_MSG(p_method == StringName(), Callable(), "Method argument to Callable::create method must be a non-empty string.");
+
+ switch (p_variant.get_type()) {
+ case Variant::NIL:
+ return Callable(ObjectID(), p_method);
+ case Variant::OBJECT:
+ return Callable(p_variant.operator ObjectID(), p_method);
+ default:
+ return Callable(memnew(VariantCallable(p_variant, p_method)));
+ }
+}
+
Callable::Callable(const Object *p_object, const StringName &p_method) {
- if (p_method == StringName()) {
+ if (unlikely(p_method == StringName())) {
object = 0;
- ERR_FAIL_MSG("Method argument to Callable constructor must be a non-empty string");
+ ERR_FAIL_MSG("Method argument to Callable constructor must be a non-empty string.");
}
- if (p_object == nullptr) {
+ if (unlikely(p_object == nullptr)) {
object = 0;
- ERR_FAIL_MSG("Object argument to Callable constructor must be non-null");
+ ERR_FAIL_MSG("Object argument to Callable constructor must be non-null.");
}
object = p_object->get_instance_id();
@@ -343,9 +391,9 @@ Callable::Callable(const Object *p_object, const StringName &p_method) {
}
Callable::Callable(ObjectID p_object, const StringName &p_method) {
- if (p_method == StringName()) {
+ if (unlikely(p_method == StringName())) {
object = 0;
- ERR_FAIL_MSG("Method argument to Callable constructor must be a non-empty string");
+ ERR_FAIL_MSG("Method argument to Callable constructor must be a non-empty string.");
}
object = p_object;
@@ -353,9 +401,9 @@ Callable::Callable(ObjectID p_object, const StringName &p_method) {
}
Callable::Callable(CallableCustom *p_custom) {
- if (p_custom->referenced) {
+ if (unlikely(p_custom->referenced)) {
object = 0;
- ERR_FAIL_MSG("Callable custom is already referenced");
+ ERR_FAIL_MSG("Callable custom is already referenced.");
}
p_custom->referenced = true;
object = 0; //ensure object is all zero, since pointer may be 32 bits
@@ -404,6 +452,11 @@ const Callable *CallableCustom::get_base_comparator() const {
return nullptr;
}
+int CallableCustom::get_argument_count(bool &r_is_valid) const {
+ r_is_valid = false;
+ return 0;
+}
+
int CallableCustom::get_bound_arguments_count() const {
return 0;
}