From ee814fa61d418428bcf92c381feb33cc361fd147 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 8 Nov 2022 15:02:08 +0800 Subject: [PATCH] Added support for parameter-less CallbackActions and CallbackEvents --- SHADE_CSharp/src/Events/CallbackAction.cs | 93 ++++++++++++++++ SHADE_CSharp/src/Events/CallbackAction.tt | 8 +- SHADE_CSharp/src/Events/CallbackEvent.cs | 126 ++++++++++++++++++---- SHADE_CSharp/src/Events/CallbackEvent.tt | 24 ++--- TempScriptsFolder/RaccoonSpin.cs | 4 + 5 files changed, 219 insertions(+), 36 deletions(-) diff --git a/SHADE_CSharp/src/Events/CallbackAction.cs b/SHADE_CSharp/src/Events/CallbackAction.cs index 623e4f59..b6082c0c 100644 --- a/SHADE_CSharp/src/Events/CallbackAction.cs +++ b/SHADE_CSharp/src/Events/CallbackAction.cs @@ -34,6 +34,99 @@ namespace SHADE Object TargetObject { get; } } + /// + /// Represents a function call that can be serialised and put togetheer with scripts. + /// This variant accepts functions with 0 parameter. + /// + public class CallbackAction : ICallbackAction + { + #region Properties ------------------------------------------------------------ + /// + public Object TargetObject { get; private set; } + /// + public string TargetMethodName => targetMethod == null ? "" : targetMethod.Name; + /// + public bool IsRuntimeAction => targetAction != null; + #endregion + + #region Fields ------------------------------------------------------------------ + private MethodInfo targetMethod; + private Action targetAction; + private Object[] parameters; + #endregion + + #region Constructors ------------------------------------------------------------ + /// + /// Constructs an empty Callback action. + /// + public CallbackAction() {} + /// + /// Constructs a CallbackAction that represents a call to the specified static + /// method. + /// + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(MethodInfo method) + { + // No errors, assign + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[0]; + } + /// + /// Constructs a CallbackAction that represents a call to a specified member + /// method on the specified target. + /// + /// Object to call the method on. + /// Method to call. + /// + /// Thrown if a method that is not compatible with the target is specified. The method's + /// source type must match the target's type. + /// + public CallbackAction(Object target, MethodInfo method) + { + // Error Checks + if (method.DeclaringType != target.GetType()) + throw new ArgumentException("[CallbackAction] Attempted register an action using an incompatible target object and method."); + + // No errors, assign + TargetObject = target; + targetMethod = method; + + // Create storage for parameters for calling + parameters = new Object[0]; + } + /// + /// Constructs a Callback action based on an action. + /// + /// Action that wraps a function to be called. + public CallbackAction(Action action) + { + targetAction = action; + } + #endregion + + #region Usage Functions --------------------------------------------------------- + /// + /// Invokes the CallbackAction's stored method/action with the specified parameters. + /// + public void Invoke() + { + if (targetAction != null) + { + targetAction.Invoke(); + } + else if (targetMethod != null) + { + _ = targetMethod.Invoke(TargetObject, parameters); + } + } + #endregion + } /// /// Represents a function call that can be serialised and put togetheer with scripts. /// This variant accepts functions with 1 parameter. diff --git a/SHADE_CSharp/src/Events/CallbackAction.tt b/SHADE_CSharp/src/Events/CallbackAction.tt index 34789b67..3fbb7617 100644 --- a/SHADE_CSharp/src/Events/CallbackAction.tt +++ b/SHADE_CSharp/src/Events/CallbackAction.tt @@ -50,12 +50,12 @@ namespace SHADE Object TargetObject { get; } } -<# for (int i = 1; i <= max; ++i) { #> +<# for (int i = 0; i <= max; ++i) { #> /// /// Represents a function call that can be serialised and put togetheer with scripts. /// This variant accepts functions with <#=i#> parameter<# if (i > 1) {#>s<#} #>. /// - public class CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> : ICallbackAction + public class CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> : ICallbackAction { #region Properties ------------------------------------------------------------ /// @@ -68,7 +68,7 @@ namespace SHADE #region Fields ------------------------------------------------------------------ private MethodInfo targetMethod; - private Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> targetAction; + private Action<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> targetAction; private Object[] parameters; #endregion @@ -121,7 +121,7 @@ namespace SHADE /// Constructs a Callback action based on an action. /// /// Action that wraps a function to be called. - public CallbackAction(Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action) + public CallbackAction(Action<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> action) { targetAction = action; } diff --git a/SHADE_CSharp/src/Events/CallbackEvent.cs b/SHADE_CSharp/src/Events/CallbackEvent.cs index ec464ba9..2c3cc388 100644 --- a/SHADE_CSharp/src/Events/CallbackEvent.cs +++ b/SHADE_CSharp/src/Events/CallbackEvent.cs @@ -45,6 +45,92 @@ namespace SHADE IEnumerable Actions { get; } } + /// + /// A container of CallbackActions that is correlated to a specific scenario as + /// specified by the user of this class. + /// This variant accepts CallbackEvents with 1 generic parameter. + /// + public class CallbackEvent : ICallbackEvent + { + #region Properties -------------------------------------------------------------- + /// + public IEnumerable Actions => actions; + #endregion + + #region Fields ------------------------------------------------------------------ + private List actions = new List(); + #endregion + + #region Usage Functions --------------------------------------------------------- + /// + public void RegisterAction() + { + actions.Add(new CallbackAction()); + } + /// + public void RegisterAction(ICallbackAction action) + { + // Check if valid action + if (action.GetType() != typeof(CallbackAction)) + { + Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this); + return; + } + + actions.Add(action); + } + /// + /// Adds a CallbackAction into the event. + /// + /// CallbackAction to add. + public void RegisterAction(CallbackAction action) + { + actions.Add(action); + } + /// + /// Constructs and adds a CallbackAction into the event. + /// + /// System.Action to add as a CallbackAction. + public void RegisterAction(Action action) + { + actions.Add(new CallbackAction(action)); + } + /// + /// Constructs and adds a CallbackAction into the event. + /// + /// Object to call the method on. + /// Method to call. + public void RegisterAction(Object target, MethodInfo method) + { + actions.Add(new CallbackAction(target, method)); + } + /// + public void DeregisterAction(ICallbackAction action) + { + if (!actions.Remove(action)) + { + Debug.LogWarning("Attempted to deregister invalid action. Ignored.", this); + } + } + /// + /// Invokes all stored CallbackActions with the specified parameters. + /// + public void Invoke() + { + foreach (CallbackAction action in actions) + { + try + { + action.Invoke(); + } + catch (Exception e) + { + Debug.LogException(e, this); + } + } + } + #endregion + } /// /// A container of CallbackActions that is correlated to a specific scenario as /// specified by the user of this class. @@ -88,7 +174,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -96,7 +182,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -174,7 +260,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -182,7 +268,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -260,7 +346,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -268,7 +354,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -346,7 +432,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -354,7 +440,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -432,7 +518,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -440,7 +526,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -518,7 +604,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -526,7 +612,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -604,7 +690,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -612,7 +698,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -690,7 +776,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -698,7 +784,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -776,7 +862,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -784,7 +870,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. @@ -862,7 +948,7 @@ namespace SHADE actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. public void RegisterAction(Action action) @@ -870,7 +956,7 @@ namespace SHADE actions.Add(new CallbackAction(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. diff --git a/SHADE_CSharp/src/Events/CallbackEvent.tt b/SHADE_CSharp/src/Events/CallbackEvent.tt index 6a545601..66a8b6d9 100644 --- a/SHADE_CSharp/src/Events/CallbackEvent.tt +++ b/SHADE_CSharp/src/Events/CallbackEvent.tt @@ -61,13 +61,13 @@ namespace SHADE IEnumerable Actions { get; } } -<# for (int i = 1; i <= max; ++i) { #> +<# for (int i = 0; i <= max; ++i) { #> /// /// A container of CallbackActions that is correlated to a specific scenario as /// specified by the user of this class. /// This variant accepts CallbackEvents with 1 generic parameter. /// - public class CallbackEvent<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> : ICallbackEvent + public class CallbackEvent<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> : ICallbackEvent { #region Properties -------------------------------------------------------------- /// @@ -82,13 +82,13 @@ namespace SHADE /// public void RegisterAction() { - actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>()); + actions.Add(new CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #>()); } /// public void RegisterAction(ICallbackAction action) { // Check if valid action - if (action.GetType() != typeof(CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>)) + if (action.GetType() != typeof(CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #>)) { Debug.LogWarning("Attempted to register an invalid CallbackAction type. Ignoring.", this); return; @@ -100,26 +100,26 @@ namespace SHADE /// Adds a CallbackAction into the event. /// /// CallbackAction to add. - public void RegisterAction(CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action) + public void RegisterAction(CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> action) { actions.Add(action); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// System.Action to add as a CallbackAction. - public void RegisterAction(Action<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action) + public void RegisterAction(Action<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> action) { - actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>(action)); + actions.Add(new CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #>(action)); } /// - /// Constructs and adds a CallbackACtion into the event. + /// Constructs and adds a CallbackAction into the event. /// /// Object to call the method on. /// Method to call. public void RegisterAction(Object target, MethodInfo method) { - actions.Add(new CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>>(target, method)); + actions.Add(new CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #>(target, method)); } /// public void DeregisterAction(ICallbackAction action) @@ -132,9 +132,9 @@ namespace SHADE /// /// Invokes all stored CallbackActions with the specified parameters. /// - public void Invoke(<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#> t<#=t#><# if (t != i) { #>, <# } #><# } #>) + public void Invoke(<# if (i != 0) { for (int t = 1; t < i + 1; ++t) { #>T<#=t#> t<#=t#><# if (t != i) { #>, <# } #><# } } #>) { - foreach (CallbackAction<<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>> action in actions) + foreach (CallbackAction<# if (i != 0) { #><<# for (int t = 1; t < i + 1; ++t) { #>T<#=t#><# if (t != i) { #>, <# } #><# } #>><# } #> action in actions) { try { diff --git a/TempScriptsFolder/RaccoonSpin.cs b/TempScriptsFolder/RaccoonSpin.cs index 06b3c163..efdfadeb 100644 --- a/TempScriptsFolder/RaccoonSpin.cs +++ b/TempScriptsFolder/RaccoonSpin.cs @@ -8,6 +8,8 @@ public class RaccoonSpin : Script private float RotateSpeed = 1.0f; private float rotation = 0.0f; [SerializeField] + private CallbackEvent emptyEvent; + [SerializeField] private CallbackEvent testEvent; [SerializeField] private CallbackEvent testEvent3 = new CallbackEvent(); @@ -17,6 +19,8 @@ public class RaccoonSpin : Script protected override void awake() { + emptyEvent = new CallbackEvent(); + emptyEvent.RegisterAction(() => Debug.Log("Empty event action!")); testEvent = new CallbackEvent(); Action action = (x) => Debug.Log($"{x}"); testEvent.RegisterAction(action);