Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elaborate on C# Connect/Disconnect #8812

Merged
merged 3 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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