summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorA Thousand Ships <96648715+AThousandShips@users.noreply.github.com>2024-01-18 17:20:56 +0100
committerA Thousand Ships <96648715+AThousandShips@users.noreply.github.com>2024-09-20 16:39:09 +0200
commit203d3be200c9b607e5eaba82d9a267813a6700cd (patch)
treeced60a02eabb92aca3759a2f7165fb78352e852c
parent2be730a05b7ff221b89c967981f7caee6e164ef0 (diff)
downloadredot-engine-203d3be200c9b607e5eaba82d9a267813a6700cd.tar.gz
[Core] Add way to check if a signal has any connections
Added to `Object` and `Signal`
-rw-r--r--core/object/object.cpp19
-rw-r--r--core/object/object.h1
-rw-r--r--core/variant/callable.cpp7
-rw-r--r--core/variant/callable.h1
-rw-r--r--core/variant/variant_call.cpp1
-rw-r--r--doc/classes/Object.xml8
-rw-r--r--doc/classes/Signal.xml6
-rw-r--r--scene/main/node.cpp5
-rw-r--r--scene/main/node.h1
9 files changed, 49 insertions, 0 deletions
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 2d9d468d38..b3a4ec6e2e 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1457,6 +1457,24 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable
return s->slot_map.has(*p_callable.get_base_comparator());
}
+bool Object::has_connections(const StringName &p_signal) const {
+ const SignalData *s = signal_map.getptr(p_signal);
+ if (!s) {
+ bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
+ if (signal_is_valid) {
+ return false;
+ }
+
+ if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)) {
+ return false;
+ }
+
+ ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + ".");
+ }
+
+ return !s->slot_map.is_empty();
+}
+
void Object::disconnect(const StringName &p_signal, const Callable &p_callable) {
_disconnect(p_signal, p_callable);
}
@@ -1697,6 +1715,7 @@ void Object::_bind_methods() {
ClassDB::bind_method(D_METHOD("connect", "signal", "callable", "flags"), &Object::connect, DEFVAL(0));
ClassDB::bind_method(D_METHOD("disconnect", "signal", "callable"), &Object::disconnect);
ClassDB::bind_method(D_METHOD("is_connected", "signal", "callable"), &Object::is_connected);
+ ClassDB::bind_method(D_METHOD("has_connections", "signal"), &Object::has_connections);
ClassDB::bind_method(D_METHOD("set_block_signals", "enable"), &Object::set_block_signals);
ClassDB::bind_method(D_METHOD("is_blocking_signals"), &Object::is_blocking_signals);
diff --git a/core/object/object.h b/core/object/object.h
index 1274247d71..763e2974b9 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -932,6 +932,7 @@ public:
MTVIRTUAL Error connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags = 0);
MTVIRTUAL void disconnect(const StringName &p_signal, const Callable &p_callable);
MTVIRTUAL bool is_connected(const StringName &p_signal, const Callable &p_callable) const;
+ MTVIRTUAL bool has_connections(const StringName &p_signal) const;
template <typename... VarArgs>
void call_deferred(const StringName &p_name, VarArgs... p_args) {
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index 9dff5c1e91..bb2d0313f6 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -545,6 +545,13 @@ bool Signal::is_connected(const Callable &p_callable) const {
return obj->is_connected(name, p_callable);
}
+bool Signal::has_connections() const {
+ Object *obj = get_object();
+ ERR_FAIL_NULL_V(obj, false);
+
+ return obj->has_connections(name);
+}
+
Array Signal::get_connections() const {
Object *obj = get_object();
if (!obj) {
diff --git a/core/variant/callable.h b/core/variant/callable.h
index 63757d9d6e..e3c940a0e5 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -192,6 +192,7 @@ public:
Error connect(const Callable &p_callable, uint32_t p_flags = 0);
void disconnect(const Callable &p_callable);
bool is_connected(const Callable &p_callable) const;
+ bool has_connections() const;
Array get_connections() const;
Signal(const Object *p_object, const StringName &p_name);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 178c0bc4ec..63fb5e8d94 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -2121,6 +2121,7 @@ static void _register_variant_builtin_methods_misc() {
bind_method(Signal, disconnect, sarray("callable"), varray());
bind_method(Signal, is_connected, sarray("callable"), varray());
bind_method(Signal, get_connections, sarray(), varray());
+ bind_method(Signal, has_connections, sarray(), varray());
bind_custom(Signal, emit, _VariantCall::func_Signal_emit, false, Variant);
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index d0d0876108..2767a11e80 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -824,6 +824,14 @@
Returns the name of the translation domain used by [method tr] and [method tr_n]. See also [TranslationServer].
</description>
</method>
+ <method name="has_connections" qualifiers="const">
+ <return type="bool" />
+ <param index="0" name="signal" type="StringName" />
+ <description>
+ Returns [code]true[/code] if any connection exists on the given [param signal] name.
+ [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call.
+ </description>
+ </method>
<method name="has_meta" qualifiers="const">
<return type="bool" />
<param index="0" name="name" type="StringName" />
diff --git a/doc/classes/Signal.xml b/doc/classes/Signal.xml
index 7d6ff1e9b0..65168d6980 100644
--- a/doc/classes/Signal.xml
+++ b/doc/classes/Signal.xml
@@ -109,6 +109,12 @@
Returns the ID of the object emitting this signal (see [method Object.get_instance_id]).
</description>
</method>
+ <method name="has_connections" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if any [Callable] is connected to this signal.
+ </description>
+ </method>
<method name="is_connected" qualifiers="const">
<return type="bool" />
<param index="0" name="callable" type="Callable" />
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index eb3448e1a2..d921cc5b67 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -4019,4 +4019,9 @@ bool Node::is_connected(const StringName &p_signal, const Callable &p_callable)
return Object::is_connected(p_signal, p_callable);
}
+bool Node::has_connections(const StringName &p_signal) const {
+ ERR_THREAD_GUARD_V(false);
+ return Object::has_connections(p_signal);
+}
+
#endif
diff --git a/scene/main/node.h b/scene/main/node.h
index 4560ed085c..298cbc7e59 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -797,6 +797,7 @@ public:
virtual Error connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags = 0) override;
virtual void disconnect(const StringName &p_signal, const Callable &p_callable) override;
virtual bool is_connected(const StringName &p_signal, const Callable &p_callable) const override;
+ virtual bool has_connections(const StringName &p_signal) const override;
#endif
Node();
~Node();