I am converting part of my project from gdscript to C# for performance reasons. In the original, a gdscript client can define a signal and call a signal registration method in server class that looks like this:
func add_input_signal(port: int, s: Signal) -> void:
var signal_receiver = func(value: int) -> void: _insert_new_event(
port, value
)
s.connect(signal_receiver)
# Utility function to add an input event to the queue
func _insert_new_event(port: int, value: int) -> void:
... # the registration automatically connects a port to any incoming signal.
The gdscript client has a signal defined thus: signal input_100(value: int)
followed by: server.add_input_signal(100, input_100)
to connect the signal to a particular server port. Then to emit the signal the client does something like: input_100.emit(666)
The example is a little over-complicated because it uses a Lambda to hide the port parameter. All Iām really doing is trying to pass a signal object to the server and as a function argument, and let the server connect. Now I am rewriting the server in C#, which I am not very familiar with. My naive translation of the server registration method is:
public void AddInputSignal(int port, Godot.Signal s)
{
var signal_receiver = (int value) => _InsertNewEvent(port, value);
s.Connect(signal_receiver);
}
Unfortunately, the Godot.Signal parameter s has no Connect method.
I have read the page on C# signals in the documentation, but it doesnāt seem like my particular use case is represented. Or, if it is, I am lacking the C# sophistication to recognize it
Any tips for me? TIA
Edit: this probably isnāt a huge issue; I think I can just put a gdscript interface around the C# code and keep the C# simple.
I thought this was going to work, but it does not. The Action return type makes the handler not recognizable by gdscript. It fails with āInvalid call. Nonexistent function āGetInputSignalā in baseā¦ā. Now that Iāve spent some more time thinking about this, I may come up with an alternative.
It looks like the C# integration makes it impossible(?) to dynamically create event handler delegates using lambdas, as I was attempting.
This ended up being a little convoluted, but I was able to retain the original API by adding a helper class that can be instantiated on a per-signal basis, and which will associate the port with the user-supplied signal:
using Godot;
[GlobalClass]
public partial class AMCForthInput : Godot.RefCounted
{
private AMCForth Forth;
private int Port;
private void Emit(int value)
{
Forth.InputEvent(Port, value);
}
public void Initialize(AMCForth forth, int port, Signal s)
{
Forth = forth;
Port = port;
Callable handler = new(this, MethodName.Emit);
s.Owner.Connect(s.Name, handler);
}
}
Now the original API for connecting a user-supplied signal to an input port is a one-liner:
public void AddInputSignal(int port, Signal s)
{
new AMCForthInput().Initialize(this, port, s);
}
...
// this will send an input value to a specific port
public void InputEvent(int port, int value)
{
...
And the whole thing is called from gdscript, thus:
signal input_100(value: int)
...
func _ready() -> void:
forth.AddInputSignal(100, input_100)
...
# and when it's time to emit the signal, 666 goes to port 100
input_100.emit(666)