Skip to content

Commit

Permalink
feat: type safe signals for C#
Browse files Browse the repository at this point in the history
  • Loading branch information
derkork committed Aug 16, 2024
1 parent 7003db4 commit 077ef45
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 1 deletion.
3 changes: 3 additions & 0 deletions addons/godot_state_charts/csharp/StateChart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ namespace GodotStateCharts
/// </summary>
public class StateChart : NodeWrapper
{
public TypeSafeSignal<Action> EventReceived { get; private set; }

protected StateChart(Node wrapped) : base(wrapped)
{
EventReceived = new TypeSafeSignal<Action>(Wrapped, SignalName.EventReceived);
}

/// <summary>
Expand Down
27 changes: 26 additions & 1 deletion addons/godot_state_charts/csharp/StateChartState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,33 @@ namespace GodotStateCharts
/// </summary>
public class StateChartState : NodeWrapper
{
public TypeSafeSignal<Action> StateEntered { get; }
public TypeSafeSignal<Action> StateExited { get; }
public TypeSafeSignal<Action<StringName>> EventReceived { get; }

public TypeSafeSignal<Action<float>> StateProcessing { get; }
public TypeSafeSignal<Action<float>> StatePhysicsProcessing { get; }

public TypeSafeSignal<Action> StateStepped { get; }

public TypeSafeSignal<Action<InputEvent>> StateInput { get; }

public TypeSafeSignal<Action<InputEvent>> StateUnhandledInput { get; }

public TypeSafeSignal<Action<float,float>> TransitionPending { get; }

protected StateChartState(Node wrapped) : base(wrapped) { }
protected StateChartState(Node wrapped) : base(wrapped)
{
StateEntered = new TypeSafeSignal<Action>(Wrapped, SignalName.StateEntered);
StateExited = new TypeSafeSignal<Action>(Wrapped, SignalName.StateExited);
EventReceived = new TypeSafeSignal<Action<StringName>>(Wrapped, SignalName.EventReceived);
StateProcessing = new TypeSafeSignal<Action<float>>(Wrapped, SignalName.StateProcessing);
StatePhysicsProcessing = new TypeSafeSignal<Action<float>>(Wrapped, SignalName.StatePhysicsProcessing);
StateStepped = new TypeSafeSignal<Action>(Wrapped, SignalName.StateStepped);
StateInput = new TypeSafeSignal<Action<InputEvent>>(Wrapped, SignalName.StateInput);
StateUnhandledInput = new TypeSafeSignal<Action<InputEvent>>(Wrapped, SignalName.StateUnhandledInput);
TransitionPending = new TypeSafeSignal<Action<float,float>>(Wrapped, SignalName.TransitionPending);
}

/// <summary>
/// Creates a wrapper object around the given node and verifies that the node
Expand Down
83 changes: 83 additions & 0 deletions addons/godot_state_charts/csharp/TypeSafeSignal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using Godot;

namespace GodotStateCharts;

public class TypeSafeSignal<R>
{
private readonly Node _node;
private readonly StringName _signalName;

public TypeSafeSignal(Node node, StringName signalName)
{
_node = node;
_signalName = signalName;
}

public void Connect(TypeSafeReceiver<R> receiver)
{
_node.Connect(_signalName, receiver.Callable);
}

public void Disconnect(TypeSafeReceiver<R> receiver)
{
_node.Disconnect(_signalName, receiver.Callable);
}
}

public struct TypeSafeReceiver<TR>
{
internal TypeSafeReceiver(Callable callable)
{
Callable = callable;
}

public Callable Callable { get; }
}

public static class TypeSafeExtensions
{
public static void Connect(this TypeSafeSignal<Action> signal, Action action)
{
signal.Connect(new TypeSafeReceiver<Action>(Callable.From(action)));
}

public static void Disconnect(this TypeSafeSignal<Action> signal, Action action)
{
signal.Disconnect(new TypeSafeReceiver<Action>(Callable.From(action)));
}

public static void Connect<T>(this TypeSafeSignal<T> signal, Action<T> action)
{
signal.Connect(new TypeSafeReceiver<T>(Callable.From(action)));
}

public static void Disconnect<T>(this TypeSafeSignal<T> signal, Action<T> action)
{
signal.Disconnect(new TypeSafeReceiver<T>(Callable.From(action)));
}

// two args

public static void Connect<T1, T2>(this TypeSafeSignal<Action<T1, T2>> signal, Action<T1, T2> action)
{
signal.Connect(new TypeSafeReceiver<Action<T1, T2>>(Callable.From(action)));
}

public static void Disconnect<T1, T2>(this TypeSafeSignal<Action<T1, T2>> signal, Action<T1, T2> action)
{
signal.Disconnect(new TypeSafeReceiver<Action<T1, T2>>(Callable.From(action)));
}

// three args

public static void Connect<T1, T2, T3>(this TypeSafeSignal<Action<T1, T2, T3>> signal, Action<T1, T2, T3> action)
{
signal.Connect(new TypeSafeReceiver<Action<T1, T2, T3>>(Callable.From(action)));
}

public static void Disconnect<T1, T2, T3>(this TypeSafeSignal<Action<T1, T2, T3>> signal, Action<T1, T2, T3> action)
{
signal.Disconnect(new TypeSafeReceiver<Action<T1, T2, T3>>(Callable.From(action)));
}
}

0 comments on commit 077ef45

Please sign in to comment.