Ver Fonte

Complete support of callables of static methods

Pedro J. Estébanez há 2 anos atrás
pai
commit
33f674d0f7

+ 14 - 6
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);
 	}
 

+ 36 - 31
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");
 

+ 2 - 1
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 {

+ 10 - 1
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()));
 }

+ 2 - 1
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;

+ 8 - 0
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();
 }

+ 4 - 2
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;