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

Update C# signal documentation and remove bind array #64930

Merged
merged 1 commit into from
Jan 24, 2023
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
10 changes: 6 additions & 4 deletions doc/classes/Callable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@
callable.call("invalid") # Invalid call, should have at least 2 arguments.
[/gdscript]
[csharp]
public void PrintArgs(object arg1, object arg2, object arg3 = null)
// Default parameter values are not supported.
public void PrintArgs(Variant arg1, Variant arg2, Variant arg3 = default)
{
GD.PrintS(arg1, arg2, arg3);
}

public void Test()
{
Callable callable = new Callable(this, nameof(PrintArgs));
callable.Call("hello", "world"); // Prints "hello world null".
// Invalid calls fail silently.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because of #59830.

Callable callable = new Callable(this, MethodName.PrintArgs);
callable.Call("hello", "world"); // Default parameter values are not supported, should have 3 arguments.
callable.Call(Vector2.Up, 42, callable); // Prints "(0, -1) 42 Node(Node.cs)::PrintArgs".
callable.Call("invalid"); // Invalid call, should have at least 2 arguments.
callable.Call("invalid"); // Invalid call, should have 3 arguments.
}
[/csharp]
[/codeblocks]
Expand Down
2 changes: 1 addition & 1 deletion doc/classes/EditorCommandPalette.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
[csharp]
EditorCommandPalette commandPalette = GetEditorInterface().GetCommandPalette();
// ExternalCommand is a function that will be called with the command is executed.
Callable commandCallable = new Callable(this, nameof(ExternalCommand));
Callable commandCallable = new Callable(this, MethodName.ExternalCommand);
commandPalette.AddCommand("command", "test/command", commandCallable)
[/csharp]
[/codeblocks]
Expand Down
2 changes: 1 addition & 1 deletion doc/classes/Expression.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

public override void _Ready()
{
GetNode("LineEdit").TextSubmitted += OnTextEntered;
GetNode<LineEdit>("LineEdit").TextSubmitted += OnTextEntered;
}

private void OnTextEntered(string command)
Expand Down
4 changes: 2 additions & 2 deletions doc/classes/HTTPRequest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
}

// Called when the HTTP request is completed.
private void HttpRequestCompleted(int result, int response_code, string[] headers, byte[] body)
private void HttpRequestCompleted(int result, int responseCode, string[] headers, byte[] body)
{
var json = new JSON();
json.Parse(body.GetStringFromUTF8());
Expand Down Expand Up @@ -128,7 +128,7 @@
}

// Called when the HTTP request is completed.
private void HttpRequestCompleted(int result, int response_code, string[] headers, byte[] body)
private void HttpRequestCompleted(int result, int responseCode, string[] headers, byte[] body)
{
if (result != (int)HTTPRequest.Result.Success)
{
Expand Down
46 changes: 21 additions & 25 deletions doc/classes/Object.xml
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@
[/gdscript]
[csharp]
var node = new Node3D();
node.Call("rotate", new Vector3(1f, 0f, 0f), 1.571f);
node.Call(Node3D.MethodName.Rotate, new Vector3(1f, 0f, 0f), 1.571f);
[/csharp]
[/codeblocks]
[b]Note:[/b] In C#, [param method] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]MethodName[/code] class to avoid allocating a new [StringName] on each call.
Expand All @@ -323,7 +323,7 @@
[/gdscript]
[csharp]
var node = new Node3D();
node.CallDeferred("rotate", new Vector3(1f, 0f, 0f), 1.571f);
node.CallDeferred(Node3D.MethodName.Rotate, new Vector3(1f, 0f, 0f), 1.571f);
[/csharp]
[/codeblocks]
[b]Note:[/b] In C#, [param method] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]MethodName[/code] class to avoid allocating a new [StringName] on each call.
Expand All @@ -342,7 +342,7 @@
[/gdscript]
[csharp]
var node = new Node3D();
node.Callv("rotate", new Godot.Collections.Array { new Vector3(1f, 0f, 0f), 1.571f });
node.Callv(Node3D.MethodName.Rotate, new Godot.Collections.Array { new Vector3(1f, 0f, 0f), 1.571f });
[/csharp]
[/codeblocks]
[b]Note:[/b] In C#, [param method] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]MethodName[/code] class to avoid allocating a new [StringName] on each call
Expand Down Expand Up @@ -394,8 +394,8 @@

// This assumes that a `Player` class exists, which defines a `Hit` signal.
var player = new Player();
// Signals as events (`player.Hit += OnPlayerHit;`) do not support argument binding. You have to use:
player.Hit.Connect(OnPlayerHit, new Godot.Collections.Array {"sword", 100 });
// We can use lambdas when we need to bind additional parameters.
player.Hit += () => OnPlayerHit("sword", 100);
}

private void OnButtonDown()
Expand All @@ -405,7 +405,7 @@

private void OnPlayerHit(string weaponType, int damage)
{
GD.Print(String.Format("Hit with weapon {0} for {1} damage.", weaponType, damage));
GD.Print($"Hit with weapon {weaponType} for {damage} damage.");
}
[/csharp]
[/codeblocks]
Expand All @@ -431,16 +431,12 @@
public override void _Ready()
{
var button = new Button();
// Option 1: Object.Connect() with an implicit Callable for the defined function.
button.Connect("button_down", OnButtonDown);
// Option 2: Object.connect() with a constructed Callable using a target object and method name.
button.Connect("button_down", new Callable(self, nameof(OnButtonDown)));
// Option 3: Signal.connect() with an implicit Callable for the defined function.
button.ButtonDown.Connect(OnButtonDown);
// Option 3b: In C#, we can use signals as events and connect with this more idiomatic syntax:
// Option 1: In C#, we can use signals as events and connect with this idiomatic syntax:
button.ButtonDown += OnButtonDown;
// Option 4: Signal.connect() with a constructed Callable using a target object and method name.
button.ButtonDown.Connect(new Callable(self, nameof(OnButtonDown)));
// Option 2: Object.Connect() with a constructed Callable from a method group.
button.Connect(Button.SignalName.ButtonDown, Callable.From(OnButtonDown));
// Option 3: Object.Connect() with a constructed Callable using a target object and method name.
button.Connect(Button.SignalName.ButtonDown, new Callable(this, MethodName.OnButtonDown));
}

private void OnButtonDown()
Expand All @@ -458,6 +454,7 @@
func _ready():
# This assumes that a `Player` class exists, which defines a `hit` signal.
var player = Player.new()
# Using Callable.bind().
player.hit.connect(_on_player_hit.bind("sword", 100))

# Parameters added when emitting the signal are passed first.
Expand All @@ -473,20 +470,19 @@
{
// This assumes that a `Player` class exists, which defines a `Hit` signal.
var player = new Player();
// Option 1: Using Callable.Bind(). This way we can still use signals as events.
player.Hit += OnPlayerHit.Bind("sword", 100);
// Option 2: Using a `binds` Array in Signal.Connect().
player.Hit.Connect(OnPlayerHit, new Godot.Collections.Array{ "sword", 100 });
// Using lambda expressions that create a closure that captures the additional parameters.
// The lambda only receives the parameters defined by the signal's delegate.
player.Hit += (hitBy, level) => OnPlayerHit(hitBy, level, "sword", 100);

// Parameters added when emitting the signal are passed first.
player.EmitSignal("hit", "Dark lord", 5);
player.EmitSignal(SignalName.Hit, "Dark lord", 5);
}

// We pass two arguments when emitting (`hit_by`, `level`),
// and bind two more arguments when connecting (`weapon_type`, `damage`).
private void OnPlayerHit(string hitBy, int level, string weaponType, int damage)
{
GD.Print(String.Format("Hit by {0} (level {1}) with weapon {2} for {3} damage.", hitBy, level, weaponType, damage));
GD.Print($"Hit by {hitBy} (level {level}) with weapon {weaponType} for {damage} damage.");
}
[/csharp]
[/codeblocks]
Expand All @@ -512,8 +508,8 @@
emit_signal("game_over")
[/gdscript]
[csharp]
EmitSignal("Hit", "sword", 100);
EmitSignal("GameOver");
EmitSignal(SignalName.Hit, "sword", 100);
EmitSignal(SignalName.GameOver);
[/csharp]
[/codeblocks]
[b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot signals. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call.
Expand Down Expand Up @@ -581,7 +577,7 @@
var b = node.GetIndexed("position:y"); // b is -10
[/csharp]
[/codeblocks]
[b]Note:[/b] In C#, [param property_path] must be in snake_case when referring to built-in Godot properties.
[b]Note:[/b] In C#, [param property_path] must be in snake_case when referring to built-in Godot properties. Prefer using the names exposed in the [code]PropertyName[/code] class to avoid allocating a new [StringName] on each call.
[b]Note:[/b] This method does not support actual paths to nodes in the [SceneTree], only sub-property paths. In the context of nodes, use [method Node.get_node_and_resource] instead.
</description>
</method>
Expand Down Expand Up @@ -868,7 +864,7 @@
GD.Print(node.Position); // Prints (42, -10)
[/csharp]
[/codeblocks]
[b]Note:[/b] In C#, [param property_path] must be in snake_case when referring to built-in Godot properties.
[b]Note:[/b] In C#, [param property_path] must be in snake_case when referring to built-in Godot properties. Prefer using the names exposed in the [code]PropertyName[/code] class to avoid allocating a new [StringName] on each call.
</description>
</method>
<method name="set_message_translation">
Expand Down
2 changes: 1 addition & 1 deletion doc/classes/Performance.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
[csharp]
public override void _Ready()
{
var monitorValue = new Callable(this, nameof(GetMonitorValue));
var monitorValue = new Callable(this, MethodName.GetMonitorValue);

// Adds monitor with name "MyName" to category "MyCategory".
Performance.AddCustomMonitor("MyCategory/MyMonitor", monitorValue);
Expand Down
4 changes: 2 additions & 2 deletions doc/classes/Signal.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
[/gdscript]
[csharp]
[Signal]
delegate void Attacked();
delegate void AttackedEventHandler();

// Additional arguments may be declared.
// These arguments must be passed when the signal is emitted.
[Signal]
delegate void ItemDropped(itemName: string, amount: int);
delegate void ItemDroppedEventHandler(string itemName, int amount);
[/csharp]
[/codeblocks]
</description>
Expand Down
20 changes: 10 additions & 10 deletions doc/classes/Tween.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
Tween tween = GetTree().CreateTween();
tween.TweenProperty(GetNode("Sprite"), "modulate", Colors.Red, 1.0f);
tween.TweenProperty(GetNode("Sprite"), "scale", Vector2.Zero, 1.0f);
tween.TweenCallback(new Callable(GetNode("Sprite").QueueFree));
tween.TweenCallback(Callable.From(GetNode("Sprite").QueueFree));
[/csharp]
[/codeblocks]
This sequence will make the [code]$Sprite[/code] node turn red, then shrink, before finally calling [method Node.queue_free] to free the sprite. [Tweener]s are executed one after another by default. This behavior can be changed using [method parallel] and [method set_parallel].
Expand All @@ -35,7 +35,7 @@
Tween tween = GetTree().CreateTween();
tween.TweenProperty(GetNode("Sprite"), "modulate", Colors.Red, 1.0f).SetTrans(Tween.TransitionType.Sine);
tween.TweenProperty(GetNode("Sprite"), "scale", Vector2.Zero, 1.0f).SetTrans(Tween.TransitionType.Bounce);
tween.TweenCallback(new Callable(GetNode("Sprite").QueueFree));
tween.TweenCallback(Callable.From(GetNode("Sprite").QueueFree));
[/csharp]
[/codeblocks]
Most of the [Tween] methods can be chained this way too. In the following example the [Tween] is bound to the running script's node and a default transition is set for its [Tweener]s:
Expand All @@ -50,7 +50,7 @@
var tween = GetTree().CreateTween().BindNode(this).SetTrans(Tween.TransitionType.Elastic);
tween.TweenProperty(GetNode("Sprite"), "modulate", Colors.Red, 1.0f);
tween.TweenProperty(GetNode("Sprite"), "scale", Vector2.Zero, 1.0f);
tween.TweenCallback(new Callable(GetNode("Sprite").QueueFree));
tween.TweenCallback(Callable.From(GetNode("Sprite").QueueFree));
[/csharp]
[/codeblocks]
Another interesting use for [Tween]s is animating arbitrary sets of objects:
Expand Down Expand Up @@ -281,7 +281,7 @@
[/gdscript]
[csharp]
Tween tween = GetTree().CreateTween().SetLoops();
tween.TweenCallback(new Callable(Shoot)).SetDelay(1.0f);
tween.TweenCallback(Callable.From(Shoot)).SetDelay(1.0f);
[/csharp]
[/codeblocks]
[b]Example:[/b] Turning a sprite red and then blue, with 2 second delay:
Expand All @@ -294,8 +294,8 @@
[csharp]
Tween tween = GetTree().CreateTween();
Sprite2D sprite = GetNode&lt;Sprite2D&gt;("Sprite");
tween.TweenCallback(new Callable(() =&gt; sprite.Modulate = Colors.Red)).SetDelay(2.0f);
tween.TweenCallback(new Callable(() =&gt; sprite.Modulate = Colors.Blue)).SetDelay(2.0f);
tween.TweenCallback(Callable.From(() =&gt; sprite.Modulate = Colors.Red)).SetDelay(2.0f);
tween.TweenCallback(Callable.From(() =&gt; sprite.Modulate = Colors.Blue)).SetDelay(2.0f);
[/csharp]
[/codeblocks]
</description>
Expand Down Expand Up @@ -332,10 +332,10 @@
[csharp]
Tween tween = CreateTween().SetLoops();
tween.TweenProperty(GetNode("Sprite"), "position:x", 200.0f, 1.0f).AsRelative();
tween.TweenCallback(new Callable(Jump));
tween.TweenCallback(Callable.From(Jump));
tween.TweenInterval(2.0f);
tween.TweenProperty(GetNode("Sprite"), "position:x", -200.0f, 1.0f).AsRelative();
tween.TweenCallback(new Callable(Jump));
tween.TweenCallback(Callable.From(Jump));
tween.TweenInterval(2.0f);
[/csharp]
[/codeblocks]
Expand All @@ -357,7 +357,7 @@
[/gdscript]
[csharp]
Tween tween = CreateTween();
tween.TweenMethod(new Callable(() =&gt; LookAt(Vector3.Up)), new Vector3(-1.0f, 0.0f, -1.0f), new Vector3(1.0f, 0.0f, -1.0f), 1.0f); // The LookAt() method takes up vector as second argument.
tween.TweenMethod(Callable.From(() =&gt; LookAt(Vector3.Up)), new Vector3(-1.0f, 0.0f, -1.0f), new Vector3(1.0f, 0.0f, -1.0f), 1.0f); // The LookAt() method takes up vector as second argument.
[/csharp]
[/codeblocks]
[b]Example:[/b] Setting the text of a [Label], using an intermediate method and after a delay:
Expand All @@ -376,7 +376,7 @@
base._Ready();

Tween tween = CreateTween();
tween.TweenMethod(new Callable(SetLabelText), 0.0f, 10.0f, 1.0f).SetDelay(1.0f);
tween.TweenMethod(Callable.From&lt;int&gt;(SetLabelText), 0.0f, 10.0f, 1.0f).SetDelay(1.0f);
}

private void SetLabelText(int value)
Expand Down
8 changes: 4 additions & 4 deletions doc/classes/UndoRedo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@
{
var node = GetNode&lt;Node2D&gt;("MyNode2D");
UndoRedo.CreateAction("Move the node");
UndoRedo.AddDoMethod(this, nameof(DoSomething));
UndoRedo.AddUndoMethod(this, nameof(UndoSomething));
UndoRedo.AddDoProperty(node, "position", new Vector2(100, 100));
UndoRedo.AddUndoProperty(node, "position", node.Position);
UndoRedo.AddDoMethod(this, MethodName.DoSomething);
UndoRedo.AddUndoMethod(this, MethodName.UndoSomething);
UndoRedo.AddDoProperty(node, Node2D.PropertyName.Position, new Vector2(100, 100));
UndoRedo.AddUndoProperty(node, Node2D.PropertyName.Position, node.Position);
UndoRedo.CommitAction();
}
[/csharp]
Expand Down