Skip to content

Commit

Permalink
Merge pull request #8812 from 31/dev/31/signal-connect
Browse files Browse the repository at this point in the history
Elaborate on C# Connect/Disconnect
  • Loading branch information
skyace65 authored Jan 22, 2024
2 parents d847e27 + 6a6cdf9 commit 829619e
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 4 deletions.
46 changes: 42 additions & 4 deletions tutorials/scripting/c_sharp/c_sharp_signals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ C# signals
For a detailed explanation of signals in general, see the :ref:`doc_signals` section in the step
by step tutorial.

While it is still possible to use signals through the ``Connect``/``Disconnect`` API, C# gives us
a more idiomatic way to implement the :ref:`observer pattern<doc_key_concepts_signals>`.
Signals are implemented using C# events, the idiomatic way to represent
:ref:`the observer pattern<doc_key_concepts_signals>` in C#. This is the
recommended way to use signals in C# and the focus of this page.

In some cases it's necessary to use the older
:ref:`Connect()<class_object_method_connect>` and
:ref:`Disconnect()<class_object_method_disconnect>` APIs.
See :ref:`using_connect_and_disconnect` for more details.

Signals as C# events
--------------------
Expand All @@ -30,8 +36,11 @@ In addition, you can always access signal names associated with a node type thro
.. warning::

While all engine signals connected as events are automatically disconnected when nodes are freed, custom
signals aren't. Meaning that: you will need to manually disconnect (using ``-=``) all the custom signals you
connected as C# events (using ``+=``).
signals connected using ``+=`` aren't. This means you will need to manually disconnect (using ``-=``)
all the custom signals you connected as C# events (using ``+=``).

An alternative to manually disconnecting using ``-=`` is to
:ref:`use Connect <using_connect_and_disconnect>` rather than ``+=``.

Custom signals as C# events
---------------------------
Expand Down Expand Up @@ -146,3 +155,32 @@ connecting to them or emitting them). Also, note that signals created this way w
AddUserSignal("MyCustomSignal");
EmitSignal("MyCustomSignal");
}
.. _using_connect_and_disconnect:

Using Connect and Disconnect
----------------------------

In general, it isn't recommended to use
:ref:`Connect()<class_object_method_connect>` and
:ref:`Disconnect()<class_object_method_disconnect>`. These APIs don't provide as
much type safety as the events. However, they're necessary for
:ref:`connecting to signals defined by GDScript <connecting_to_signals_cross_language>`
and passing :ref:`ConnectFlags<enum_Object_ConnectFlags>`.

In the following example, pressing the button for the first time prints
``Greetings!``. ``OneShot`` disconnects the signal, so pressing the button again
does nothing.

.. code-block:: csharp
public override void _Ready()
{
Button button = GetNode<Button>("GreetButton");
button.Connect(Button.SignalName.Pressed, Callable.From(OnButtonPressed), (uint)GodotObject.ConnectFlags.OneShot);
}
public void OnButtonPressed()
{
GD.Print("Greetings!");
}
37 changes: 37 additions & 0 deletions tutorials/scripting/cross_language_scripting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ The following two scripts will be used as references throughout this page.

var my_field: String = "foo"

signal my_signal

func print_node_name(node: Node) -> void:
print(node.get_name())

Expand All @@ -29,6 +31,9 @@ The following two scripts will be used as references throughout this page.
for i in range(n):
print(msg)

func my_signal_handler():
print("The signal handler was called!")

.. code-tab:: csharp

using Godot;
Expand All @@ -37,6 +42,8 @@ The following two scripts will be used as references throughout this page.
{
public string myField = "bar";

[Signal] public delegate void MySignalEventHandler();

public void PrintNodeName(Node node)
{
GD.Print(node.Name);
Expand All @@ -57,6 +64,11 @@ The following two scripts will be used as references throughout this page.
GD.Print(msg);
}
}

public void MySignalHandler()
{
GD.Print("The signal handler was called!");
}
}

Instantiating nodes
Expand Down Expand Up @@ -186,6 +198,31 @@ to said method.
Otherwise, each element of your array will be treated as a single argument
and the function signature won't match.

.. _connecting_to_signals_cross_language:

Connecting to signals
---------------------

Connecting to C# signals from GDScript
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Connecting to a C# signal from GDScript is the same as connecting to a signal
defined in GDScript:

.. code-block:: gdscript
my_csharp_node.MySignal.connect(my_signal_handler)
Connecting to GDScript signals from C#
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Connecting to a GDScript signal from C# only works with the ``Connect`` method
because no C# static types exist for signals defined by GDScript:

.. code-block:: csharp
myGDScriptNode.Connect("my_signal", Callable.From(mySignalHandler));
Inheritance
-----------

Expand Down

0 comments on commit 829619e

Please sign in to comment.