summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2023-01-18 22:04:09 +0100
committerPedro J. Estébanez <pedrojrulez@gmail.com>2023-04-12 18:12:19 +0200
commit33f674d0f7e94b768cd957a920fed8a215760ee2 (patch)
tree6168ce65a1292dcdf1790a8e13d83b185b04f0f9
parentd4dad2b2f88968ff329145f3dab5290478bae886 (diff)
downloadredot-engine-33f674d0f7e94b768cd957a920fed8a215760ee2.tar.gz
Complete support of callables of static methods
-rw-r--r--core/object/callable_method_pointer.h20
-rw-r--r--core/object/message_queue.cpp67
-rw-r--r--core/object/message_queue.h3
-rw-r--r--core/variant/callable.cpp11
-rw-r--r--core/variant/callable.h3
-rw-r--r--core/variant/callable_bind.cpp8
-rw-r--r--core/variant/callable_bind.h6
7 files changed, 76 insertions, 42 deletions
diff --git a/core/object/callable_method_pointer.h b/core/object/callable_method_pointer.h
index 1584906710..2dbb7e468e 100644
--- a/core/object/callable_method_pointer.h
+++ b/core/object/callable_method_pointer.h
@@ -198,7 +198,7 @@ class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
} data;
public:
- virtual ObjectID get_object() const {
+ virtual ObjectID get_object() const override {
#ifdef DEBUG_ENABLED
if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
return ObjectID();
@@ -207,7 +207,7 @@ public:
return data.instance->get_instance_id();
}
- virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
#endif
@@ -254,11 +254,15 @@ class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase
} data;
public:
- virtual ObjectID get_object() const {
+ virtual bool is_valid() const override {
+ return true;
+ }
+
+ virtual ObjectID get_object() const override {
return ObjectID();
}
- virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
r_return_value = Variant();
}
@@ -292,11 +296,15 @@ class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerB
} data;
public:
- virtual ObjectID get_object() const {
+ virtual bool is_valid() const override {
+ return true;
+ }
+
+ virtual ObjectID get_object() const override {
return ObjectID();
}
- virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
+ virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
}
diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp
index 7a8dae2341..83e0c4aea1 100644
--- a/core/object/message_queue.cpp
+++ b/core/object/message_queue.cpp
@@ -90,6 +90,10 @@ Error CallQueue::push_callablep(const Callable &p_callable, const Variant **p_ar
if (p_show_error) {
msg->type |= FLAG_SHOW_ERROR;
}
+ // Support callables of static methods.
+ if (p_callable.get_object_id().is_null() && p_callable.is_valid()) {
+ msg->type |= FLAG_NULL_IS_OK;
+ }
buffer_end += sizeof(Message);
@@ -238,28 +242,24 @@ Error CallQueue::flush() {
mutex.unlock();
- if (target != nullptr) {
- switch (message->type & FLAG_MASK) {
- case TYPE_CALL: {
+ switch (message->type & FLAG_MASK) {
+ case TYPE_CALL: {
+ if (target || (message->type & FLAG_NULL_IS_OK)) {
Variant *args = (Variant *)(message + 1);
-
- // messages don't expect a return value
-
_call_function(message->callable, args, message->args, message->type & FLAG_SHOW_ERROR);
-
- } break;
- case TYPE_NOTIFICATION: {
- // messages don't expect a return value
+ }
+ } break;
+ case TYPE_NOTIFICATION: {
+ if (target) {
target->notification(message->notification);
-
- } break;
- case TYPE_SET: {
+ }
+ } break;
+ case TYPE_SET: {
+ if (target) {
Variant *arg = (Variant *)(message + 1);
- // messages don't expect a return value
target->set(message->callable.get_method(), *arg);
-
- } break;
- }
+ }
+ } break;
}
if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) {
@@ -355,36 +355,41 @@ void CallQueue::statistics() {
Object *target = message->callable.get_object();
- if (target != nullptr) {
- switch (message->type & FLAG_MASK) {
- case TYPE_CALL: {
+ bool null_target = true;
+ switch (message->type & FLAG_MASK) {
+ case TYPE_CALL: {
+ if (target || (message->type & FLAG_NULL_IS_OK)) {
if (!call_count.has(message->callable)) {
call_count[message->callable] = 0;
}
call_count[message->callable]++;
-
- } break;
- case TYPE_NOTIFICATION: {
+ null_target = false;
+ }
+ } break;
+ case TYPE_NOTIFICATION: {
+ if (target) {
if (!notify_count.has(message->notification)) {
notify_count[message->notification] = 0;
}
notify_count[message->notification]++;
-
- } break;
- case TYPE_SET: {
+ null_target = false;
+ }
+ } break;
+ case TYPE_SET: {
+ if (target) {
StringName t = message->callable.get_method();
if (!set_count.has(t)) {
set_count[t] = 0;
}
set_count[t]++;
-
- } break;
- }
-
- } else {
+ null_target = false;
+ }
+ } break;
+ }
+ if (null_target) {
//object was deleted
print_line("Object was deleted while awaiting a callback");
diff --git a/core/object/message_queue.h b/core/object/message_queue.h
index 525285e061..68969dfd39 100644
--- a/core/object/message_queue.h
+++ b/core/object/message_queue.h
@@ -51,8 +51,9 @@ private:
TYPE_NOTIFICATION,
TYPE_SET,
TYPE_END, // End marker.
+ FLAG_NULL_IS_OK = 1 << 13,
FLAG_SHOW_ERROR = 1 << 14,
- FLAG_MASK = FLAG_SHOW_ERROR - 1,
+ FLAG_MASK = FLAG_NULL_IS_OK - 1,
};
struct Page {
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index 2f2acc55a6..630873ec2e 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -122,7 +122,11 @@ Callable Callable::unbind(int p_argcount) const {
}
bool Callable::is_valid() const {
- return get_object() && (is_custom() || get_object()->has_method(get_method()));
+ if (is_custom()) {
+ return get_custom()->is_valid();
+ } else {
+ return get_object() && get_object()->has_method(get_method());
+ }
}
Object *Callable::get_object() const {
@@ -373,6 +377,11 @@ Callable::~Callable() {
}
}
+bool CallableCustom::is_valid() const {
+ // Sensible default implementation so most custom callables don't need their own.
+ return ObjectDB::get_instance(get_object());
+}
+
StringName CallableCustom::get_method() const {
ERR_FAIL_V_MSG(StringName(), vformat("Can't get method on CallableCustom \"%s\".", get_as_text()));
}
diff --git a/core/variant/callable.h b/core/variant/callable.h
index 0abbb64c0b..086e5d2a00 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -145,8 +145,9 @@ public:
virtual String get_as_text() const = 0;
virtual CompareEqualFunc get_compare_equal_func() const = 0;
virtual CompareLessFunc get_compare_less_func() const = 0;
+ virtual bool is_valid() const;
virtual StringName get_method() const;
- virtual ObjectID get_object() const = 0; //must always be able to provide an object
+ virtual ObjectID get_object() const = 0;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const;
diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp
index 5be91c6e11..378d1ff618 100644
--- a/core/variant/callable_bind.cpp
+++ b/core/variant/callable_bind.cpp
@@ -75,6 +75,10 @@ CallableCustom::CompareLessFunc CallableCustomBind::get_compare_less_func() cons
return _less_func;
}
+bool CallableCustomBind::is_valid() const {
+ return callable.is_valid();
+}
+
StringName CallableCustomBind::get_method() const {
return callable.get_method();
}
@@ -193,6 +197,10 @@ CallableCustom::CompareLessFunc CallableCustomUnbind::get_compare_less_func() co
return _less_func;
}
+bool CallableCustomUnbind::is_valid() const {
+ return callable.is_valid();
+}
+
StringName CallableCustomUnbind::get_method() const {
return callable.get_method();
}
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h
index 278ed335d0..b51076ad0f 100644
--- a/core/variant/callable_bind.h
+++ b/core/variant/callable_bind.h
@@ -47,8 +47,9 @@ public:
virtual String get_as_text() const override;
virtual CompareEqualFunc get_compare_equal_func() const override;
virtual CompareLessFunc get_compare_less_func() const override;
+ virtual bool is_valid() const override;
virtual StringName get_method() const override;
- virtual ObjectID get_object() const override; //must always be able to provide an object
+ virtual ObjectID get_object() const override;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
virtual int get_bound_arguments_count() const override;
@@ -73,8 +74,9 @@ public:
virtual String get_as_text() const override;
virtual CompareEqualFunc get_compare_equal_func() const override;
virtual CompareLessFunc get_compare_less_func() const override;
+ virtual bool is_valid() const override;
virtual StringName get_method() const override;
- virtual ObjectID get_object() const override; //must always be able to provide an object
+ virtual ObjectID get_object() const override;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
virtual int get_bound_arguments_count() const override;