using System; using System.Linq; using UnityEngine; using Object = UnityEngine.Object; namespace SerializableCallback { /// /// https://github.com/Siccity/SerializableCallback /// /// public abstract class SerializableCallbackBase : SerializableCallbackBase { /// /// https://github.com/Siccity/SerializableCallback /// public InvokableCallbackBase func; /// /// https://github.com/Siccity/SerializableCallback /// public override void ClearCache() { base.ClearCache(); func = null; } /// /// https://github.com/Siccity/SerializableCallback /// /// protected InvokableCallbackBase GetPersistentMethod() { Type[] types = new Type[ArgTypes.Length + 1]; Array.Copy(ArgTypes, types, ArgTypes.Length); types[types.Length - 1] = typeof(TReturn); Type genericType = null; switch (types.Length) { case 1: genericType = typeof(InvokableCallback<>).MakeGenericType(types); break; case 2: genericType = typeof(InvokableCallback<,>).MakeGenericType(types); break; case 3: genericType = typeof(InvokableCallback<, ,>).MakeGenericType(types); break; case 4: genericType = typeof(InvokableCallback<, , ,>).MakeGenericType(types); break; case 5: genericType = typeof(InvokableCallback<, , , ,>).MakeGenericType(types); break; default: throw new ArgumentException(types.Length + "args"); } return Activator.CreateInstance(genericType, new object[] { target, methodName }) as InvokableCallbackBase; } } /// An inspector-friendly serializable function [System.Serializable] public abstract class SerializableCallbackBase : ISerializationCallbackReceiver { /// Target object public Object target { get { return _target; } set { _target = value; ClearCache(); } } /// Target method name public string methodName { get { return _methodName; } set { _methodName = value; ClearCache(); } } /// /// https://github.com/Siccity/SerializableCallback /// public object[] Args { get { return args != null ? args : args = _args.Select(x => x.GetValue()).ToArray(); } } /// /// https://github.com/Siccity/SerializableCallback /// public object[] args; /// /// https://github.com/Siccity/SerializableCallback /// public Type[] ArgTypes { get { return argTypes != null ? argTypes : argTypes = _args.Select(x => Arg.RealType(x.argType)).ToArray(); } } /// /// https://github.com/Siccity/SerializableCallback /// public Type[] argTypes; /// /// https://github.com/Siccity/SerializableCallback /// public bool dynamic { get { return _dynamic; } set { _dynamic = value; ClearCache(); } } /// /// https://github.com/Siccity/SerializableCallback /// [SerializeField] protected Object _target; /// /// https://github.com/Siccity/SerializableCallback /// [SerializeField] protected string _methodName; /// /// https://github.com/Siccity/SerializableCallback /// [SerializeField] protected Arg[] _args; /// /// https://github.com/Siccity/SerializableCallback /// [SerializeField] protected bool _dynamic; #pragma warning disable 0414 [SerializeField] private string _typeName; #pragma warning restore 0414 [SerializeField] private bool dirty; #if UNITY_EDITOR /// /// https://github.com/Siccity/SerializableCallback /// protected SerializableCallbackBase() { _typeName = base.GetType().AssemblyQualifiedName; } #endif /// /// https://github.com/Siccity/SerializableCallback /// public virtual void ClearCache() { argTypes = null; args = null; } /// /// https://github.com/Siccity/SerializableCallback /// /// /// /// /// public void SetMethod(Object target, string methodName, bool dynamic, params Arg[] args) { _target = target; _methodName = methodName; _dynamic = dynamic; _args = args; ClearCache(); } /// /// https://github.com/Siccity/SerializableCallback /// protected abstract void Cache(); /// /// https://github.com/Siccity/SerializableCallback /// public void OnBeforeSerialize() { #if UNITY_EDITOR if (dirty) { ClearCache(); dirty = false; } #endif } /// /// https://github.com/Siccity/SerializableCallback /// public void OnAfterDeserialize() { #if UNITY_EDITOR _typeName = base.GetType().AssemblyQualifiedName; #endif } } /// /// https://github.com/Siccity/SerializableCallback /// [System.Serializable] public struct Arg { /// /// https://github.com/Siccity/SerializableCallback /// public enum ArgType { /// /// https://github.com/Siccity/SerializableCallback /// Unsupported, /// /// https://github.com/Siccity/SerializableCallback /// Bool, /// /// https://github.com/Siccity/SerializableCallback /// Int, /// /// https://github.com/Siccity/SerializableCallback /// Float, /// /// https://github.com/Siccity/SerializableCallback /// String, /// /// https://github.com/Siccity/SerializableCallback /// Object } /// /// https://github.com/Siccity/SerializableCallback /// public bool boolValue; /// /// https://github.com/Siccity/SerializableCallback /// public int intValue; /// /// https://github.com/Siccity/SerializableCallback /// public float floatValue; /// /// https://github.com/Siccity/SerializableCallback /// public string stringValue; /// /// https://github.com/Siccity/SerializableCallback /// public Object objectValue; /// /// https://github.com/Siccity/SerializableCallback /// public ArgType argType; /// /// https://github.com/Siccity/SerializableCallback /// /// public object GetValue() { return GetValue(argType); } /// /// https://github.com/Siccity/SerializableCallback /// /// /// public object GetValue(ArgType type) { switch (type) { case ArgType.Bool: return boolValue; case ArgType.Int: return intValue; case ArgType.Float: return floatValue; case ArgType.String: return stringValue; case ArgType.Object: return objectValue; default: return null; } } /// /// https://github.com/Siccity/SerializableCallback /// /// /// public static Type RealType(ArgType type) { switch (type) { case ArgType.Bool: return typeof(bool); case ArgType.Int: return typeof(int); case ArgType.Float: return typeof(float); case ArgType.String: return typeof(string); case ArgType.Object: return typeof(Object); default: return null; } } /// /// https://github.com/Siccity/SerializableCallback /// /// /// public static ArgType FromRealType(Type type) { if (type == typeof(bool)) return ArgType.Bool; else if (type == typeof(int)) return ArgType.Int; else if (type == typeof(float)) return ArgType.Float; else if (type == typeof(String)) return ArgType.String; else if (type == typeof(Object)) return ArgType.Object; else return ArgType.Unsupported; } /// /// https://github.com/Siccity/SerializableCallback /// /// /// public static bool IsSupported(Type type) { return FromRealType(type) != ArgType.Unsupported; } } }