diff --git a/Editor/PropertyDrawer/SerializableFuncBasePropertyDrawer.cs b/Editor/PropertyDrawer/SerializableFuncBasePropertyDrawer.cs index 90af8c1..b1198e5 100644 --- a/Editor/PropertyDrawer/SerializableFuncBasePropertyDrawer.cs +++ b/Editor/PropertyDrawer/SerializableFuncBasePropertyDrawer.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; +using SerializableFunc.Runtime; using UnityEditor; using UnityEditor.UIElements; using UnityEditorInternal; @@ -12,11 +13,11 @@ using UnityEngine; using UnityEngine.UIElements; using Utilities.Extensions.SystemExtensions; using Utilities.Extensions.UIToolkit; -using UnityUtilities.SerializableDataHelpers; using Object = UnityEngine.Object; namespace UnityUtilities.SerializableDataHelpers.UnityEditorUtilities { + [CustomPropertyDrawer(typeof(SerializableAction), true)] [CustomPropertyDrawer(typeof(SerializableFuncBase<>), true)] public class SerializableFuncBasePropertyDrawer : PropertyDrawer { @@ -169,7 +170,11 @@ namespace UnityUtilities.SerializableDataHelpers.UnityEditorUtilities || string.IsNullOrWhiteSpace(targetMethodProperty.stringValue)) return false; Type[] funcArguments = GetFuncTypeArguments(funcProperty); - Type returnType = funcArguments.Last(); + Type returnType = typeof(void); + if (funcArguments.Length > 0) + { + returnType = funcArguments.Last(); + } MethodInfo targetMethod = targetObjectProperty.objectReferenceValue .GetType() @@ -561,8 +566,15 @@ namespace UnityUtilities.SerializableDataHelpers.UnityEditorUtilities { if (info.IsSpecialName) return false; - Type returnType = funcParameters.Last(); - if (info.ReturnType != returnType) return false; + if (funcParameters.Length > 0) + { + Type returnType = funcParameters.Last(); + if (info.ReturnType != returnType) return false; + } + else + { + if (info.ReturnType == typeof(void)) return true; + } ParameterInfo[] parameters = info.GetParameters(); if (parameters.Length != (funcParameters.Length - 1)) return false; diff --git a/Runtime/SerializableAction.cs b/Runtime/SerializableAction.cs new file mode 100644 index 0000000..661a5fa --- /dev/null +++ b/Runtime/SerializableAction.cs @@ -0,0 +1,83 @@ +using System; +using System.Linq; +using System.Reflection; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace SerializableFunc.Runtime +{ + [Serializable] + public class SerializableAction + { + [SerializeField] private Object targetObject; + [SerializeField] private string methodName; + + private Action cachedAction; + + private static readonly BindingFlags SuitableMethodsFlags = + BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance; + + public Object TargetObject + { + get => targetObject; + set => targetObject = value; + } + + public string MethodName + { + get => methodName; + set => methodName = value; + } + + private Action GetAction() + { + if (cachedAction == null) + { + if (targetObject == null) + throw new ArgumentNullException(nameof(targetObject), "Target Object is null!"); + + if (string.IsNullOrWhiteSpace(methodName)) + throw new ArgumentNullException(nameof(methodName), "Target Method is null!"); + + MethodInfo info = targetObject + .GetType() + .GetMethods(SuitableMethodsFlags) + .FirstOrDefault(IsTargetMethodInfo); + + if (info == null) + { + throw new MissingMethodException($"Object \"{targetObject.name}\" is missing target void method: {methodName}"); + } + + cachedAction = (Action)Delegate.CreateDelegate(typeof(Action), targetObject, methodName); + } + + return cachedAction; + } + + private bool IsTargetMethodInfo(MethodInfo methodInfo) + { + if (!string.Equals(methodInfo.Name, methodName, StringComparison.InvariantCulture)) + return false; + + if (methodInfo.ReturnType != typeof(void)) + return false; + + // Only allow parameterless void methods for this version + if (methodInfo.GetParameters().Length != 0) + return false; + + return true; + } + + public void Invoke() + { + GetAction()?.Invoke(); + } + + public static implicit operator Action(SerializableAction serializableAction) + { + return serializableAction?.GetAction(); + } + } +} \ No newline at end of file diff --git a/Runtime/SerializableAction.cs.meta b/Runtime/SerializableAction.cs.meta new file mode 100644 index 0000000..3a24d36 --- /dev/null +++ b/Runtime/SerializableAction.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 2ba5aa5c8f7c474fbaba429c733d8d7c +timeCreated: 1762160974 \ No newline at end of file diff --git a/Runtime/SerializableFunc.Runtime.asmdef b/Runtime/SerializableFunc.Runtime.asmdef index 64b57f5..39acda4 100644 --- a/Runtime/SerializableFunc.Runtime.asmdef +++ b/Runtime/SerializableFunc.Runtime.asmdef @@ -1,6 +1,6 @@ { "name": "SerializableFunc.Runtime", - "rootNamespace": "", + "rootNamespace": "SerializableFunc.Runtime", "references": [], "includePlatforms": [], "excludePlatforms": [], diff --git a/Runtime/SerializableFunc/Implementations/SerializableFunc.cs b/Runtime/SerializableFunc.cs similarity index 94% rename from Runtime/SerializableFunc/Implementations/SerializableFunc.cs rename to Runtime/SerializableFunc.cs index bc9598c..b7ffe43 100644 --- a/Runtime/SerializableFunc/Implementations/SerializableFunc.cs +++ b/Runtime/SerializableFunc.cs @@ -1,8 +1,8 @@ -namespace UnityUtilities.SerializableDataHelpers -{ - using System; +using System; - [System.Serializable] +namespace SerializableFunc.Runtime +{ + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke() @@ -12,7 +12,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0) @@ -22,7 +22,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1) @@ -32,7 +32,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2) @@ -42,7 +42,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3) @@ -52,7 +52,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) @@ -62,7 +62,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5) @@ -72,7 +72,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6) @@ -82,7 +82,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7) @@ -92,7 +92,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8) @@ -102,7 +102,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9) @@ -112,7 +112,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9, TArg10 arg10) @@ -122,7 +122,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { public TReturn Invoke(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9, TArg10 arg10, TArg11 arg11) @@ -132,7 +132,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { @@ -143,7 +143,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { @@ -154,7 +154,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { @@ -165,7 +165,7 @@ namespace UnityUtilities.SerializableDataHelpers } } - [System.Serializable] + [Serializable] public class SerializableFunc : SerializableFuncBase> { diff --git a/Runtime/SerializableFunc/Implementations/SerializableFunc.cs.meta b/Runtime/SerializableFunc.cs.meta similarity index 100% rename from Runtime/SerializableFunc/Implementations/SerializableFunc.cs.meta rename to Runtime/SerializableFunc.cs.meta diff --git a/Runtime/SerializableFunc.meta b/Runtime/SerializableFunc.meta deleted file mode 100644 index 8a35254..0000000 --- a/Runtime/SerializableFunc.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: fe4625ec820a55848834d700960d1a9f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/SerializableFunc/Base.meta b/Runtime/SerializableFunc/Base.meta deleted file mode 100644 index b0f4a36..0000000 --- a/Runtime/SerializableFunc/Base.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4bd647a4a04c7f947afa36dc0ab3e8bf -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/SerializableFunc/Implementations.meta b/Runtime/SerializableFunc/Implementations.meta deleted file mode 100644 index 0efafdc..0000000 --- a/Runtime/SerializableFunc/Implementations.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a05eff3308be0b2489425421e455c65f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/SerializableFunc/Base/SerializableFuncBase.cs b/Runtime/SerializableFuncBase.cs similarity index 97% rename from Runtime/SerializableFunc/Base/SerializableFuncBase.cs rename to Runtime/SerializableFuncBase.cs index 6c8becf..744b2f1 100644 --- a/Runtime/SerializableFunc/Base/SerializableFuncBase.cs +++ b/Runtime/SerializableFuncBase.cs @@ -4,9 +4,9 @@ using System.Reflection; using UnityEngine; using Object = UnityEngine.Object; -namespace UnityUtilities.SerializableDataHelpers +namespace SerializableFunc.Runtime { - [System.Serializable] + [Serializable] public abstract class SerializableFuncBase where TFuncType : Delegate { diff --git a/Runtime/SerializableFunc/Base/SerializableFuncBase.cs.meta b/Runtime/SerializableFuncBase.cs.meta similarity index 100% rename from Runtime/SerializableFunc/Base/SerializableFuncBase.cs.meta rename to Runtime/SerializableFuncBase.cs.meta