From 077ef45c24e8bb8d9cbbc336775d8cd14aa187a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Thom=C3=A4?= Date: Sun, 23 Jun 2024 09:50:46 +0200 Subject: [PATCH] feat: type safe signals for C# --- .../godot_state_charts/csharp/StateChart.cs | 3 + .../csharp/StateChartState.cs | 27 +++++- .../csharp/TypeSafeSignal.cs | 83 +++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 addons/godot_state_charts/csharp/TypeSafeSignal.cs diff --git a/addons/godot_state_charts/csharp/StateChart.cs b/addons/godot_state_charts/csharp/StateChart.cs index 5a6d1e4..8af76b5 100644 --- a/addons/godot_state_charts/csharp/StateChart.cs +++ b/addons/godot_state_charts/csharp/StateChart.cs @@ -10,8 +10,11 @@ namespace GodotStateCharts /// public class StateChart : NodeWrapper { + public TypeSafeSignal EventReceived { get; private set; } + protected StateChart(Node wrapped) : base(wrapped) { + EventReceived = new TypeSafeSignal(Wrapped, SignalName.EventReceived); } /// diff --git a/addons/godot_state_charts/csharp/StateChartState.cs b/addons/godot_state_charts/csharp/StateChartState.cs index df32834..a9bdc26 100644 --- a/addons/godot_state_charts/csharp/StateChartState.cs +++ b/addons/godot_state_charts/csharp/StateChartState.cs @@ -10,8 +10,33 @@ namespace GodotStateCharts /// public class StateChartState : NodeWrapper { + public TypeSafeSignal StateEntered { get; } + public TypeSafeSignal StateExited { get; } + public TypeSafeSignal> EventReceived { get; } + + public TypeSafeSignal> StateProcessing { get; } + public TypeSafeSignal> StatePhysicsProcessing { get; } + + public TypeSafeSignal StateStepped { get; } + + public TypeSafeSignal> StateInput { get; } + + public TypeSafeSignal> StateUnhandledInput { get; } + + public TypeSafeSignal> TransitionPending { get; } - protected StateChartState(Node wrapped) : base(wrapped) { } + protected StateChartState(Node wrapped) : base(wrapped) + { + StateEntered = new TypeSafeSignal(Wrapped, SignalName.StateEntered); + StateExited = new TypeSafeSignal(Wrapped, SignalName.StateExited); + EventReceived = new TypeSafeSignal>(Wrapped, SignalName.EventReceived); + StateProcessing = new TypeSafeSignal>(Wrapped, SignalName.StateProcessing); + StatePhysicsProcessing = new TypeSafeSignal>(Wrapped, SignalName.StatePhysicsProcessing); + StateStepped = new TypeSafeSignal(Wrapped, SignalName.StateStepped); + StateInput = new TypeSafeSignal>(Wrapped, SignalName.StateInput); + StateUnhandledInput = new TypeSafeSignal>(Wrapped, SignalName.StateUnhandledInput); + TransitionPending = new TypeSafeSignal>(Wrapped, SignalName.TransitionPending); + } /// /// Creates a wrapper object around the given node and verifies that the node diff --git a/addons/godot_state_charts/csharp/TypeSafeSignal.cs b/addons/godot_state_charts/csharp/TypeSafeSignal.cs new file mode 100644 index 0000000..81b1ffd --- /dev/null +++ b/addons/godot_state_charts/csharp/TypeSafeSignal.cs @@ -0,0 +1,83 @@ +using System; +using Godot; + +namespace GodotStateCharts; + +public class TypeSafeSignal +{ + private readonly Node _node; + private readonly StringName _signalName; + + public TypeSafeSignal(Node node, StringName signalName) + { + _node = node; + _signalName = signalName; + } + + public void Connect(TypeSafeReceiver receiver) + { + _node.Connect(_signalName, receiver.Callable); + } + + public void Disconnect(TypeSafeReceiver receiver) + { + _node.Disconnect(_signalName, receiver.Callable); + } +} + +public struct TypeSafeReceiver +{ + internal TypeSafeReceiver(Callable callable) + { + Callable = callable; + } + + public Callable Callable { get; } +} + +public static class TypeSafeExtensions +{ + public static void Connect(this TypeSafeSignal signal, Action action) + { + signal.Connect(new TypeSafeReceiver(Callable.From(action))); + } + + public static void Disconnect(this TypeSafeSignal signal, Action action) + { + signal.Disconnect(new TypeSafeReceiver(Callable.From(action))); + } + + public static void Connect(this TypeSafeSignal signal, Action action) + { + signal.Connect(new TypeSafeReceiver(Callable.From(action))); + } + + public static void Disconnect(this TypeSafeSignal signal, Action action) + { + signal.Disconnect(new TypeSafeReceiver(Callable.From(action))); + } + +// two args + + public static void Connect(this TypeSafeSignal> signal, Action action) + { + signal.Connect(new TypeSafeReceiver>(Callable.From(action))); + } + + public static void Disconnect(this TypeSafeSignal> signal, Action action) + { + signal.Disconnect(new TypeSafeReceiver>(Callable.From(action))); + } + +// three args + + public static void Connect(this TypeSafeSignal> signal, Action action) + { + signal.Connect(new TypeSafeReceiver>(Callable.From(action))); + } + + public static void Disconnect(this TypeSafeSignal> signal, Action action) + { + signal.Disconnect(new TypeSafeReceiver>(Callable.From(action))); + } +}