diff --git a/godot-core/src/registry/signal/typed_signal.rs b/godot-core/src/registry/signal/typed_signal.rs index 7e2f3a78a..aff386440 100644 --- a/godot-core/src/registry/signal/typed_signal.rs +++ b/godot-core/src/registry/signal/typed_signal.rs @@ -17,8 +17,6 @@ use crate::meta::{InParamTuple, ObjectToOwned, UniformObjectDeref}; use crate::obj::{Gd, GodotClass, WithSignals}; use crate::registry::signal::signal_receiver::{IndirectSignalReceiver, SignalReceiver}; -// ---------------------------------------------------------------------------------------------------------------------------------------------- - /// Type-safe version of a Godot signal. /// /// Short-lived type, only valid in the scope of its surrounding object type `C`, for lifetime `'c`. The generic argument `Ps` represents @@ -42,6 +40,7 @@ use crate::registry::signal::signal_receiver::{IndirectSignalReceiver, SignalRec /// - [`builder()`][Self::builder] for more complex setups (such as choosing [`ConnectFlags`] or making thread-safe connections). /// /// # Emitting a signal +// -------------------- /// Code-generated signal types provide a method `emit(...)`, which adopts the names and types of the `#[signal]` parameter list. /// In most cases, that's the method you are looking for. /// @@ -49,6 +48,57 @@ use crate::registry::signal::signal_receiver::{IndirectSignalReceiver, SignalRec /// /// # Generic programming and code reuse /// If you want to build higher-level abstractions that operate on `TypedSignal`, you will need the [`SignalReceiver`] trait. +/// +// Keep in sync with https://godot-rust.github.io/book/register/signals.html#admonition-availability-of-signal-api. +/// # Availability +/// For typed signals to be available, you need: +/// - A `#[godot_api] impl MyClass {}` block. +/// - This must be an inherent impl, the `I*` trait `impl` won't be enough. +/// - Leave the impl empty if necessary. +/// - A `Base` field. +/// +/// Signals, typed or not, cannot be declared in secondary impl blocks (those annotated with `#[godot_api(secondary)]` attribute). +/// # Examples +/// ```no_run +/// # use godot::prelude::*; +/// # use godot::classes::Button; +/// # #[derive(GodotClass)] +/// # #[class(init,base=Node)] +/// # pub struct ExampleClass { +/// # button: OnEditor>, +/// # other_button: OnEditor>, +/// # base: Base, +/// # } +/// #[godot_api] +/// impl ExampleClass { +/// #[signal] +/// fn signal(); +/// fn method(&mut self) { /* ... */ } +/// fn method_with_args(&mut self, value: bool) { /* ... */ } +/// } +/// impl ExampleClass { +/// fn example(&mut self) { +/// // Connect Self to Self (Self::method). +/// self.signals().signal().connect_self(Self::method); +/// // Connect Self to Self (closure). +/// self.signals() +/// .signal() +/// .connect_self(|s| s.method_with_args(true)); +/// // Connect other to Self (Self::method). +/// self.button +/// .signals() +/// .pressed() +/// .connect_other(self, Self::method); +/// // Connect other to other (closure). +/// self.button +/// .signals() +/// .toggled() +/// .connect_other(&*self.other_button, |other_button, toggled| { +/// other_button.set_pressed(toggled) +/// }); +/// } +/// } +/// ``` pub struct TypedSignal<'c, C: WithSignals, Ps> { /// In Godot, valid signals (unlike funcs) are _always_ declared in a class and become part of each instance. So there's always an object. object: C::__SignalObj<'c>, @@ -214,7 +264,6 @@ impl TypedSignal<'_, C, Ps> { /// - Any `&Gd` (e.g.: `&Gd`, `&Gd`). /// - `&OtherC`, as long as `OtherC` is a user class that contains a `base` field (it implements the /// [`WithBaseField`][crate::obj::WithBaseField] trait). - /// /// --- /// /// - To connect to methods on the object that owns this signal, use [`connect_self()`][Self::connect_self].