using System; using System.Collections.Generic; using System.Reflection; using UnityEngine; [Serializable] public class EventDelegate { public EventDelegate() { } public EventDelegate(EventDelegate.Callback call) { this.Set(call); } public EventDelegate(MonoBehaviour target, string methodName) { this.Set(target, methodName); } public MonoBehaviour target { get { return this.mTarget; } set { this.mTarget = value; this.mCachedCallback = null; this.mRawDelegate = false; this.mCached = false; this.mMethod = null; this.mParameterInfos = null; this.mParameters = null; } } public string methodName { get { return this.mMethodName; } set { this.mMethodName = value; this.mCachedCallback = null; this.mRawDelegate = false; this.mCached = false; this.mMethod = null; this.mParameterInfos = null; this.mParameters = null; } } public EventDelegate.Parameter[] parameters { get { if (!this.mCached) { this.Cache(); } return this.mParameters; } } public bool isValid { get { if (!this.mCached) { this.Cache(); } return (this.mRawDelegate && this.mCachedCallback != null) || (this.mTarget != null && !string.IsNullOrEmpty(this.mMethodName)); } } public bool isEnabled { get { if (!this.mCached) { this.Cache(); } if (this.mRawDelegate && this.mCachedCallback != null) { return true; } if (this.mTarget == null) { return false; } MonoBehaviour monoBehaviour = this.mTarget; return monoBehaviour == null || monoBehaviour.enabled; } } private static string GetMethodName(EventDelegate.Callback callback) { return callback.Method.Name; } private static bool IsValid(EventDelegate.Callback callback) { return callback != null && callback.Method != null; } public override bool Equals(object obj) { if (obj == null) { return !this.isValid; } if (obj is EventDelegate.Callback) { EventDelegate.Callback callback = obj as EventDelegate.Callback; if (callback.Equals(this.mCachedCallback)) { return true; } MonoBehaviour y = callback.Target as MonoBehaviour; return this.mTarget == y && string.Equals(this.mMethodName, EventDelegate.GetMethodName(callback)); } else { if (obj is EventDelegate) { EventDelegate eventDelegate = obj as EventDelegate; return this.mTarget == eventDelegate.mTarget && string.Equals(this.mMethodName, eventDelegate.mMethodName); } return false; } } public override int GetHashCode() { return EventDelegate.s_Hash; } private void Set(EventDelegate.Callback call) { this.Clear(); if (call != null && EventDelegate.IsValid(call)) { this.mTarget = (call.Target as MonoBehaviour); if (this.mTarget == null) { this.mRawDelegate = true; this.mCachedCallback = call; this.mMethodName = null; } else { this.mMethodName = EventDelegate.GetMethodName(call); this.mRawDelegate = false; } } } public void Set(MonoBehaviour target, string methodName) { this.Clear(); this.mTarget = target; this.mMethodName = methodName; } private void Cache() { this.mCached = true; if (this.mRawDelegate) { return; } if ((this.mCachedCallback == null || this.mCachedCallback.Target as MonoBehaviour != this.mTarget || EventDelegate.GetMethodName(this.mCachedCallback) != this.mMethodName) && this.mTarget != null && !string.IsNullOrEmpty(this.mMethodName)) { Type type = this.mTarget.GetType(); this.mMethod = null; while (type != null) { try { this.mMethod = type.GetMethod(this.mMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (this.mMethod != null) { break; } } catch (Exception) { } type = type.BaseType; } if (this.mMethod == null) { Debug.LogError(string.Concat(new object[] { "Could not find method '", this.mMethodName, "' on ", this.mTarget.GetType() }), this.mTarget); return; } if (this.mMethod.ReturnType != typeof(void)) { Debug.LogError(string.Concat(new object[] { this.mTarget.GetType(), ".", this.mMethodName, " must have a 'void' return type." }), this.mTarget); return; } this.mParameterInfos = this.mMethod.GetParameters(); if (this.mParameterInfos.Length == 0) { this.mCachedCallback = (EventDelegate.Callback)Delegate.CreateDelegate(typeof(EventDelegate.Callback), this.mTarget, this.mMethodName); this.mArgs = null; this.mParameters = null; return; } this.mCachedCallback = null; if (this.mParameters == null || this.mParameters.Length != this.mParameterInfos.Length) { this.mParameters = new EventDelegate.Parameter[this.mParameterInfos.Length]; int i = 0; int num = this.mParameters.Length; while (i < num) { this.mParameters[i] = new EventDelegate.Parameter(); i++; } } int j = 0; int num2 = this.mParameters.Length; while (j < num2) { this.mParameters[j].expectedType = this.mParameterInfos[j].ParameterType; j++; } } } public bool Execute() { if (!this.mCached) { this.Cache(); } if (this.mCachedCallback != null) { this.mCachedCallback(); return true; } if (this.mMethod != null) { if (this.mParameters == null || this.mParameters.Length == 0) { this.mMethod.Invoke(this.mTarget, null); } else { if (this.mArgs == null || this.mArgs.Length != this.mParameters.Length) { this.mArgs = new object[this.mParameters.Length]; } int i = 0; int num = this.mParameters.Length; while (i < num) { this.mArgs[i] = this.mParameters[i].value; i++; } try { this.mMethod.Invoke(this.mTarget, this.mArgs); } catch (ArgumentException ex) { string text = "Error calling "; if (this.mTarget == null) { text += this.mMethod.Name; } else { string text2 = text; text = string.Concat(new object[] { text2, this.mTarget.GetType(), ".", this.mMethod.Name }); } text = text + ": " + ex.Message; text += "\n Expected: "; if (this.mParameterInfos.Length == 0) { text += "no arguments"; } else { text += this.mParameterInfos[0]; for (int j = 1; j < this.mParameterInfos.Length; j++) { text = text + ", " + this.mParameterInfos[j].ParameterType; } } text += "\n Received: "; if (this.mParameters.Length == 0) { text += "no arguments"; } else { text += this.mParameters[0].type; for (int k = 1; k < this.mParameters.Length; k++) { text = text + ", " + this.mParameters[k].type; } } text += "\n"; Debug.LogError(text); } int l = 0; int num2 = this.mArgs.Length; while (l < num2) { if (this.mParameterInfos[l].IsIn || this.mParameterInfos[l].IsOut) { this.mParameters[l].value = this.mArgs[l]; } this.mArgs[l] = null; l++; } } return true; } return false; } public void Clear() { this.mTarget = null; this.mMethodName = null; this.mRawDelegate = false; this.mCachedCallback = null; this.mParameters = null; this.mCached = false; this.mMethod = null; this.mParameterInfos = null; this.mArgs = null; } public override string ToString() { if (!(this.mTarget != null)) { return (!this.mRawDelegate) ? null : "[delegate]"; } string text = this.mTarget.GetType().ToString(); int num = text.LastIndexOf('.'); if (num > 0) { text = text.Substring(num + 1); } if (!string.IsNullOrEmpty(this.methodName)) { return text + "/" + this.methodName; } return text + "/[delegate]"; } public static void Execute(List list) { if (list != null) { for (int i = 0; i < list.Count; i++) { EventDelegate eventDelegate = list[i]; if (eventDelegate != null) { try { eventDelegate.Execute(); } catch (Exception ex) { if (ex.InnerException != null) { Debug.LogError(ex.InnerException.Message); } else { Debug.LogError(ex.Message); } } if (i >= list.Count) { break; } if (list[i] != eventDelegate) { continue; } if (eventDelegate.oneShot) { list.RemoveAt(i); continue; } } } } } public static bool IsValid(List list) { if (list != null) { int i = 0; int count = list.Count; while (i < count) { EventDelegate eventDelegate = list[i]; if (eventDelegate != null && eventDelegate.isValid) { return true; } i++; } } return false; } public static EventDelegate Set(List list, EventDelegate.Callback callback) { if (list != null) { EventDelegate eventDelegate = new EventDelegate(callback); list.Clear(); list.Add(eventDelegate); return eventDelegate; } return null; } public static void Set(List list, EventDelegate del) { if (list != null) { list.Clear(); list.Add(del); } } public static EventDelegate Add(List list, EventDelegate.Callback callback) { return EventDelegate.Add(list, callback, false); } public static EventDelegate Add(List list, EventDelegate.Callback callback, bool oneShot) { if (list != null) { int i = 0; int count = list.Count; while (i < count) { EventDelegate eventDelegate = list[i]; if (eventDelegate != null && eventDelegate.Equals(callback)) { return eventDelegate; } i++; } EventDelegate eventDelegate2 = new EventDelegate(callback); eventDelegate2.oneShot = oneShot; list.Add(eventDelegate2); return eventDelegate2; } Debug.LogWarning("Attempting to add a callback to a list that's null"); return null; } public static void Add(List list, EventDelegate ev) { EventDelegate.Add(list, ev, ev.oneShot); } public static void Add(List list, EventDelegate ev, bool oneShot) { if (ev.mRawDelegate || ev.target == null || string.IsNullOrEmpty(ev.methodName)) { EventDelegate.Add(list, ev.mCachedCallback, oneShot); } else if (list != null) { int i = 0; int count = list.Count; while (i < count) { EventDelegate eventDelegate = list[i]; if (eventDelegate != null && eventDelegate.Equals(ev)) { return; } i++; } EventDelegate eventDelegate2 = new EventDelegate(ev.target, ev.methodName); eventDelegate2.oneShot = oneShot; if (ev.mParameters != null && ev.mParameters.Length > 0) { eventDelegate2.mParameters = new EventDelegate.Parameter[ev.mParameters.Length]; for (int j = 0; j < ev.mParameters.Length; j++) { eventDelegate2.mParameters[j] = ev.mParameters[j]; } } list.Add(eventDelegate2); } else { Debug.LogWarning("Attempting to add a callback to a list that's null"); } } public static bool Remove(List list, EventDelegate.Callback callback) { if (list != null) { int i = 0; int count = list.Count; while (i < count) { EventDelegate eventDelegate = list[i]; if (eventDelegate != null && eventDelegate.Equals(callback)) { list.RemoveAt(i); return true; } i++; } } return false; } public static bool Remove(List list, EventDelegate ev) { if (list != null) { int i = 0; int count = list.Count; while (i < count) { EventDelegate eventDelegate = list[i]; if (eventDelegate != null && eventDelegate.Equals(ev)) { list.RemoveAt(i); return true; } i++; } } return false; } [SerializeField] private MonoBehaviour mTarget; [SerializeField] private string mMethodName; [SerializeField] private EventDelegate.Parameter[] mParameters; public bool oneShot; [NonSerialized] private EventDelegate.Callback mCachedCallback; [NonSerialized] private bool mRawDelegate; [NonSerialized] private bool mCached; [NonSerialized] private MethodInfo mMethod; [NonSerialized] private ParameterInfo[] mParameterInfos; [NonSerialized] private object[] mArgs; private static int s_Hash = "EventDelegate".GetHashCode(); [Serializable] public class Parameter { public Parameter() { } public Parameter(UnityEngine.Object obj, string field) { this.obj = obj; this.field = field; } public Parameter(object val) { this.mValue = val; } public object value { get { if (this.mValue != null) { return this.mValue; } if (!this.cached) { this.cached = true; this.fieldInfo = null; this.propInfo = null; if (this.obj != null && !string.IsNullOrEmpty(this.field)) { Type type = this.obj.GetType(); this.propInfo = type.GetProperty(this.field); if (this.propInfo == null) { this.fieldInfo = type.GetField(this.field); } } } if (this.propInfo != null) { return this.propInfo.GetValue(this.obj, null); } if (this.fieldInfo != null) { return this.fieldInfo.GetValue(this.obj); } if (this.obj != null) { return this.obj; } if (this.expectedType != null && this.expectedType.IsValueType) { return null; } return Convert.ChangeType(null, this.expectedType); } set { this.mValue = value; } } public Type type { get { if (this.mValue != null) { return this.mValue.GetType(); } if (this.obj == null) { return typeof(void); } return this.obj.GetType(); } } public UnityEngine.Object obj; public string field; [NonSerialized] private object mValue; [NonSerialized] public Type expectedType = typeof(void); [NonSerialized] public bool cached; [NonSerialized] public PropertyInfo propInfo; [NonSerialized] public FieldInfo fieldInfo; } public delegate void Callback(); }