Files
2026-02-21 16:45:37 +08:00

679 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
[Serializable]
public class KGFEvent : KGFEventBase, KGFIValidator
{
public delegate bool KGFEventFilterMethod(MethodInfo theMethod);
[Serializable]
public class KGFEventData
{
public bool itsRuntimeObjectSearch;
public string itsRuntimeObjectSearchType = string.Empty;
public string itsRuntimeObjectSearchFilter = string.Empty;
public GameObject itsObject;
public string itsComponentName = string.Empty;
public string itsMethodName = string.Empty;
public string itsMethodNameShort = string.Empty;
public EventParameter[] itsParameters = new EventParameter[0];
public EventParameterType[] itsParameterTypes = new EventParameterType[0];
public bool itsPassthroughMode;
private KGFEventFilterMethod itsFilterMethod;
public KGFEventData()
{
}
public KGFEventData(bool thePassThroughMode, params EventParameterType[] theParameterTypes)
{
itsParameterTypes = theParameterTypes;
itsPassthroughMode = thePassThroughMode;
}
public Type GetRuntimeType()
{
return Type.GetType(itsRuntimeObjectSearchType);
}
public bool GetDirectPassThroughMode()
{
return itsPassthroughMode;
}
public void SetDirectPassThroughMode(bool thePassThroughMode)
{
itsPassthroughMode = thePassThroughMode;
}
public void SetRuntimeParameterInfos(params EventParameterType[] theParameterTypes)
{
if (theParameterTypes == null)
{
itsParameterTypes = new EventParameterType[0];
}
else
{
itsParameterTypes = theParameterTypes;
}
}
public EventParameterType[] GetParameterLinkTypes()
{
return itsParameterTypes;
}
public bool GetSupportsRuntimeParameterInfos()
{
return itsParameterTypes.Length > 0;
}
public bool GetIsParameterLinked(int theParameterIndex)
{
if (!GetSupportsRuntimeParameterInfos())
{
return false;
}
if (theParameterIndex >= itsParameters.Length)
{
return false;
}
return itsParameters[theParameterIndex].itsLinked;
}
public void SetIsParameterLinked(int theParameterIndex, bool theLinkState)
{
if (theParameterIndex < itsParameters.Length)
{
itsParameters[theParameterIndex].itsLinked = theLinkState;
}
}
public int GetParameterLink(int theParameterIndex)
{
if (theParameterIndex >= itsParameters.Length)
{
return 0;
}
return itsParameters[theParameterIndex].itsLink;
}
public void SetParameterLink(int theParameterIndex, int theLink)
{
if (theParameterIndex < itsParameters.Length)
{
itsParameters[theParameterIndex].itsLink = theLink;
}
}
public EventParameter[] GetParameters()
{
return itsParameters;
}
public void SetParameters(EventParameter[] theParameters)
{
itsParameters = theParameters;
}
public GameObject GetGameObject()
{
return itsObject;
}
private object GetFieldValueByReflection(MonoBehaviour theCaller, string theMemberName)
{
Type type = theCaller.GetType();
FieldInfo field = type.GetField(theMemberName);
if (field != null)
{
return field.GetValue(theCaller);
}
return null;
}
public void Trigger(MonoBehaviour theCaller, params object[] theParameters)
{
List<object> list = new List<object>(theParameters);
EventParameterType[] array = itsParameterTypes;
foreach (EventParameterType eventParameterType in array)
{
if (eventParameterType.GetCopyFromSourceObject())
{
list.Add(GetFieldValueByReflection(theCaller, eventParameterType.itsName));
}
}
if (itsRuntimeObjectSearch)
{
TriggerRuntimeSearch(theCaller, list.ToArray());
}
else
{
TriggerDefault(theCaller, list.ToArray());
}
}
private int GetParameterIndexWithType(int theIndex, string theType)
{
int num = 0;
for (int i = 0; i < itsParameterTypes.Length; i++)
{
EventParameterType eventParameterType = itsParameterTypes[i];
if (eventParameterType.itsTypeName == theType)
{
if (num == theIndex)
{
return i;
}
num++;
}
}
return 0;
}
private bool CheckRuntimeObjectName(MonoBehaviour theMonobehaviour)
{
if (itsRuntimeObjectSearchFilter.Trim() == string.Empty)
{
return true;
}
if (itsRuntimeObjectSearchFilter == theMonobehaviour.name)
{
return true;
}
return false;
}
private void TriggerRuntimeSearch(MonoBehaviour theCaller, object[] theRuntimeParameters)
{
Type runtimeType = GetRuntimeType();
if (runtimeType == null)
{
LogError("could not find type", "KGFEventSystem", theCaller);
return;
}
if (itsMethodName == null)
{
LogError("event has no selected method", "KGFEventSystem", theCaller);
return;
}
MethodInfo theMethod;
MonoBehaviour theComponent;
if (!FindMethod(this, out theMethod, out theComponent))
{
LogError("Could not find method on object.", "KGFEventSystem", theCaller);
return;
}
object[] array = null;
if (GetDirectPassThroughMode())
{
array = theRuntimeParameters;
}
else
{
ParameterInfo[] parameters = theMethod.GetParameters();
array = ConvertParameters(parameters, itsParameters);
for (int i = 0; i < itsParameters.Length; i++)
{
if (GetIsParameterLinked(i))
{
int parameterIndexWithType = GetParameterIndexWithType(GetParameterLink(i), parameters[i].ParameterType.FullName);
if (parameterIndexWithType < theRuntimeParameters.Length)
{
array[i] = theRuntimeParameters[parameterIndexWithType];
}
else
{
Debug.LogError("you did not give enough parameters");
}
}
}
}
List<MonoBehaviour> list = new List<MonoBehaviour>();
try
{
if (runtimeType.IsInterface || typeof(KGFObject).IsAssignableFrom(runtimeType))
{
foreach (object @object in KGFAccessor.GetObjects(runtimeType))
{
MonoBehaviour monoBehaviour = @object as MonoBehaviour;
if (monoBehaviour != null && CheckRuntimeObjectName(monoBehaviour))
{
theMethod.Invoke(@object, array);
list.Add(monoBehaviour);
}
}
}
else if (!runtimeType.IsInterface)
{
UnityEngine.Object[] array2 = UnityEngine.Object.FindObjectsOfType(runtimeType);
foreach (object obj in array2)
{
MonoBehaviour monoBehaviour2 = obj as MonoBehaviour;
if (monoBehaviour2 != null && CheckRuntimeObjectName(monoBehaviour2))
{
theMethod.Invoke(obj, array);
list.Add(monoBehaviour2);
}
}
}
}
catch (Exception ex)
{
LogError("invoked method caused exception in event_generic:" + ex, "KGFEventSystem", theCaller);
}
List<string> list2 = new List<string>();
if (array != null)
{
object[] array3 = array;
foreach (object obj2 in array3)
{
list2.Add(string.Empty + obj2);
}
}
foreach (MonoBehaviour item in list)
{
string theMessage = string.Format("{0}({1}): {2} ({3})", item.name, itsRuntimeObjectSearchType, theMethod.Name, string.Join(",", list2.ToArray()));
LogDebug(theMessage, "KGFEventSystem", theCaller);
}
}
private void TriggerDefault(MonoBehaviour theCaller, params object[] theRuntimeParameters)
{
if (itsObject == null)
{
LogError("event has null object", "KGFEventSystem", theCaller);
return;
}
if (itsComponentName == null)
{
LogError("event has no selected component", "KGFEventSystem", theCaller);
return;
}
if (itsMethodName == null)
{
LogError("event has no selected method", "KGFEventSystem", theCaller);
return;
}
MethodInfo theMethod;
MonoBehaviour theComponent;
if (!FindMethod(this, out theMethod, out theComponent))
{
LogError("Could not find method on object.", "KGFEventSystem", theCaller);
return;
}
object[] array = null;
if (GetDirectPassThroughMode())
{
array = theRuntimeParameters;
}
else
{
ParameterInfo[] parameters = theMethod.GetParameters();
array = ConvertParameters(parameters, itsParameters);
for (int i = 0; i < itsParameters.Length; i++)
{
if (GetIsParameterLinked(i))
{
int parameterIndexWithType = GetParameterIndexWithType(GetParameterLink(i), parameters[i].ParameterType.FullName);
if (parameterIndexWithType < theRuntimeParameters.Length)
{
array[i] = theRuntimeParameters[parameterIndexWithType];
}
else
{
Debug.LogError("you did not give enough parameters");
}
}
}
}
try
{
theMethod.Invoke(theComponent, array);
}
catch (Exception ex)
{
LogError("invoked method caused exception in event_generic:" + ex, "KGFEventSystem", theCaller);
}
List<string> list = new List<string>();
if (array != null)
{
object[] array2 = array;
foreach (object obj in array2)
{
list.Add(string.Empty + obj);
}
}
string theMessage = string.Format("{0}({1}): {2} ({3})", itsObject.name, theComponent.GetType().Name, theMethod.Name, string.Join(",", list.ToArray()));
LogDebug(theMessage, "KGFEventSystem", theCaller);
}
public void SetMethodFilter(KGFEventFilterMethod theFilter)
{
itsFilterMethod = theFilter;
}
public void ClearMethodFilter()
{
itsFilterMethod = null;
}
private KGFEventFilterMethod GetFilterMethod()
{
return itsFilterMethod;
}
public bool CheckMethod(MethodInfo theMethod)
{
if (itsFilterMethod != null && !GetFilterMethod()(theMethod))
{
return false;
}
if (GetSupportsRuntimeParameterInfos() && GetDirectPassThroughMode())
{
ParameterInfo[] parameters = theMethod.GetParameters();
if (parameters.Length != itsParameterTypes.Length)
{
return false;
}
for (int i = 0; i < parameters.Length; i++)
{
if (!itsParameterTypes[i].GetIsMatchingType(parameters[i].ParameterType))
{
return false;
}
}
}
return true;
}
public KGFMessageList GetErrors()
{
KGFMessageList kGFMessageList = new KGFMessageList();
if (string.IsNullOrEmpty(itsMethodName))
{
kGFMessageList.AddError("Empty method name");
}
if (itsRuntimeObjectSearch && string.IsNullOrEmpty(itsRuntimeObjectSearchType))
{
kGFMessageList.AddError("Empty type field");
}
MethodInfo theMethod;
MonoBehaviour theComponent;
if (!FindMethod(this, out theMethod, out theComponent))
{
kGFMessageList.AddError("Could not find method on object.");
}
else
{
ParameterInfo[] parameters = theMethod.GetParameters();
for (int i = 0; i < itsParameters.Length; i++)
{
if (!GetIsParameterLinked(i) && typeof(UnityEngine.Object).IsAssignableFrom(parameters[i].ParameterType) && itsParameters[i].itsValueUnityObject == null)
{
kGFMessageList.AddError("Empty unity object in parameters");
}
}
}
return kGFMessageList;
}
}
[Serializable]
public class EventParameterType
{
public string itsName;
public string itsTypeName;
public bool itsCopyFromSourceObject;
public EventParameterType()
{
}
public EventParameterType(string theName, Type theType)
{
itsName = theName;
itsTypeName = theType.FullName;
}
public void SetCopyFromSourceObject(bool theCopy)
{
itsCopyFromSourceObject = theCopy;
}
public bool GetCopyFromSourceObject()
{
return itsCopyFromSourceObject;
}
public bool GetIsMatchingType(Type theOtherParameterType)
{
return itsTypeName == theOtherParameterType.FullName;
}
}
[Serializable]
public class EventParameter
{
public int itsValueInt32;
public string itsValueString;
public float itsValueSingle;
public double itsValueDouble;
public Color itsValueColor;
public Rect itsValueRect;
public Vector2 itsValueVector2;
public Vector3 itsValueVector3;
public Vector4 itsValueVector4;
public bool itsValueBoolean;
public UnityEngine.Object itsValueUnityObject;
public bool itsLinked;
public int itsLink;
public EventParameter()
{
itsValueUnityObject = null;
}
}
public KGFEventData itsEventData = new KGFEventData();
private const string itsEventCategory = "KGFEventSystem";
public void SetDestination(GameObject theGameObject, string theComponentName, string theMethodString)
{
itsEventData.itsObject = theGameObject;
itsEventData.itsComponentName = theComponentName;
itsEventData.itsMethodName = theMethodString;
}
private static bool FindMethod(KGFEventData theEventData, out MethodInfo theMethod, out MonoBehaviour theComponent)
{
theMethod = null;
theComponent = null;
if (theEventData.itsRuntimeObjectSearch)
{
MethodInfo[] methods = GetMethods(theEventData.GetRuntimeType(), theEventData);
foreach (MethodInfo methodInfo in methods)
{
string methodString = GetMethodString(methodInfo);
if (methodString == theEventData.itsMethodName)
{
theMethod = methodInfo;
return true;
}
}
}
else if (theEventData.itsObject != null)
{
MonoBehaviour[] components = theEventData.itsObject.GetComponents<MonoBehaviour>();
MonoBehaviour[] array = components;
foreach (MonoBehaviour monoBehaviour in array)
{
if (!(monoBehaviour.GetType().Name == theEventData.itsComponentName))
{
continue;
}
theComponent = monoBehaviour;
MethodInfo[] methods2 = GetMethods(monoBehaviour.GetType(), theEventData);
foreach (MethodInfo methodInfo2 in methods2)
{
string methodString2 = GetMethodString(methodInfo2);
if (methodString2 == theEventData.itsMethodName)
{
theMethod = methodInfo2;
return true;
}
}
}
}
return false;
}
public override void Trigger()
{
itsEventData.Trigger(this);
}
private static bool SearchInstanceForVariable(Type theType, object theInstance, string theName, ref object theValue)
{
FieldInfo field = theType.GetField(theName);
if (field != null)
{
theValue = field.GetValue(theInstance);
return true;
}
return false;
}
private static object[] ConvertParameters(ParameterInfo[] theMethodParametersList, EventParameter[] theParametersList)
{
object[] array = new object[theMethodParametersList.Length];
for (int i = 0; i < theMethodParametersList.Length; i++)
{
if (typeof(UnityEngine.Object).IsAssignableFrom(theMethodParametersList[i].ParameterType))
{
array[i] = theParametersList[i].itsValueUnityObject;
}
else if (!SearchInstanceForVariable(typeof(EventParameter), theParametersList[i], "itsValue" + theMethodParametersList[i].ParameterType.Name, ref array[i]))
{
Debug.LogError("could not find variable for type:" + theMethodParametersList[i].ParameterType.Name);
}
}
return array;
}
public static MethodInfo[] GetMethods(Type theType, KGFEventData theData)
{
List<MethodInfo> list = new List<MethodInfo>();
for (Type type = theType; type != null; type = type.BaseType)
{
MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
MethodInfo[] array = methods;
foreach (MethodInfo methodInfo in array)
{
if (methodInfo.GetCustomAttributes(typeof(KGFEventExpose), true).Length > 0 && theData.CheckMethod(methodInfo))
{
list.Add(methodInfo);
}
}
}
return list.ToArray();
}
public static string GetMethodString(MethodInfo theMethod)
{
return theMethod.ToString();
}
public static void LogError(string theMessage, string theCategory, MonoBehaviour theCaller)
{
Debug.LogError(theMessage);
}
public static void LogDebug(string theMessage, string theCategory, MonoBehaviour theCaller)
{
Debug.Log(theMessage);
}
public static void LogWarning(string theMessage, string theCategory, MonoBehaviour theCaller)
{
Debug.LogWarning(theMessage);
}
public override KGFMessageList Validate()
{
KGFMessageList kGFMessageList = new KGFMessageList();
if ((string.Empty + itsEventData.itsMethodName).Trim() == string.Empty)
{
kGFMessageList.AddError("itsMethod is empty");
}
if (!itsEventData.itsRuntimeObjectSearch)
{
if (itsEventData.itsObject == null)
{
kGFMessageList.AddError("itsObject == null");
}
if ((string.Empty + itsEventData.itsComponentName).Trim() == string.Empty)
{
kGFMessageList.AddError("itsScript is empty");
}
MethodInfo theMethod;
MonoBehaviour theComponent;
if (itsEventData.itsObject != null && !FindMethod(itsEventData, out theMethod, out theComponent))
{
kGFMessageList.AddError("method could not be found");
}
}
if (itsEventData.itsRuntimeObjectSearch)
{
Type runtimeType = itsEventData.GetRuntimeType();
if (runtimeType == null)
{
kGFMessageList.AddError("could not find type");
}
else if (runtimeType.IsInterface)
{
kGFMessageList.AddWarning("you used an interface, please ensure that the objects you want to call the method on are derrived from KGFObject");
}
else
{
if (!typeof(MonoBehaviour).IsAssignableFrom(runtimeType))
{
kGFMessageList.AddError("type must be derrived from Monobehaviour");
}
if (!typeof(KGFObject).IsAssignableFrom(runtimeType))
{
kGFMessageList.AddWarning("please derrive from KGFObject because it will be faster to search");
}
}
}
return kGFMessageList;
}
}