Skip to content

Commit b568129

Browse files
authored
Merge pull request #1068 from Yarwin/test-signal-is-connected-to-callable
Regression test for checking if `RustCallable` is connected to signal.
2 parents 489b1f1 + e8c6f93 commit b568129

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

godot-core/src/builtin/callable.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,9 @@ mod custom_callable {
540540
///
541541
/// Since callables can be invoked from anywhere, they must be self-contained (`'static`) and thread-safe (`Send + Sync`).
542542
/// They also should implement `Display` for the Godot string representation.
543-
/// Furthermore, `PartialEq` and `Hash` are required for equality checks and usage as a key in a `Dictionary`.
543+
/// Furthermore, `Hash` is required for usage as a key in a `Dictionary` and for checking signal connections –
544+
/// Godot considers a custom callable to be connected to a signal if a callable with the same hash is already connected to that signal.
545+
/// Finally, `PartialEq` is necessary for equality checks.
544546
pub trait RustCallable: 'static + PartialEq + Hash + fmt::Display + Send + Sync {
545547
/// Invokes the callable with the given arguments as `Variant` references.
546548
///

itest/rust/src/builtin_tests/containers/callable_test.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ pub mod custom_callable {
384384
use super::*;
385385
use crate::framework::{assert_eq_self, quick_thread, ThreadCrosser};
386386
use godot::builtin::{Dictionary, RustCallable};
387+
use godot::prelude::Signal;
387388
use godot::sys;
388389
use godot::sys::GdextBuild;
389390
use std::fmt;
@@ -613,6 +614,41 @@ pub mod custom_callable {
613614
assert_eq!(1, received.load(Ordering::SeqCst));
614615
}
615616

617+
#[itest]
618+
fn callable_is_connected() {
619+
let tracker = Tracker::new();
620+
let tracker2 = Tracker::new();
621+
622+
// Adder hash depends on its sum.
623+
let some_callable = Callable::from_custom(Adder::new_tracked(3, tracker));
624+
let identical_callable = Callable::from_custom(Adder::new_tracked(3, tracker2));
625+
626+
let obj = RefCounted::new_gd();
627+
let signal = Signal::from_object_signal(&obj, "script_changed");
628+
signal.connect(&some_callable, 0);
629+
630+
// Given Custom Callable is connected to signal
631+
// if callable with the very same hash is already connected.
632+
assert!(signal.is_connected(&some_callable));
633+
assert!(signal.is_connected(&identical_callable));
634+
635+
let change = [2.to_variant()];
636+
637+
// Change the hash.
638+
signal.emit(&change);
639+
640+
// The hash, dependent on `Adder.sum` has been changed.
641+
// `identical_callable` is considered NOT connected.
642+
assert!(signal.is_connected(&some_callable));
643+
assert!(!signal.is_connected(&identical_callable));
644+
645+
identical_callable.call(&change);
646+
647+
// The hashes are, once again, identical.
648+
assert!(signal.is_connected(&some_callable));
649+
assert!(signal.is_connected(&identical_callable));
650+
}
651+
616652
// ------------------------------------------------------------------------------------------------------------------------------------------
617653
// Helper structs and functions for custom callables
618654

0 commit comments

Comments
 (0)