Browse Source

Merge pull request #8812 from 31/dev/31/signal-connect

Elaborate on C# Connect/Disconnect
Matthew 1 year ago
parent
commit
829619ecf8

+ 42 - 4
tutorials/scripting/c_sharp/c_sharp_signals.rst

@@ -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
 --------------------
@@ -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
 ---------------------------
@@ -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 - 0
tutorials/scripting/cross_language_scripting.rst

@@ -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())
 
@@ -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;
@@ -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);
@@ -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
@@ -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
 -----------