//============= Copyright (c) Ludic GmbH, All rights reserved. ============== // // Purpose: Part of the My Behaviour Tree Code // //============================================================================= using System; using System.Reflection; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace MyBT { [System.Serializable] public class MethodScanner { public static bool debugActive = false; public static readonly BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.GetField; private static bool IsGenerated (DictionaryOfStringAndDictionaryOfStringAndMethodImplementation methods) { if (methods != null) { int count = 0; foreach (KeyValuePair fileKvp in methods) { if (fileKvp.Value != null) { foreach (KeyValuePair functionKvp in fileKvp.Value) { count += 1; } } } return (count > 0); } return false; } public static void Reset(ref DictionaryOfStringAndDictionaryOfStringAndMethodImplementation methods) { if (methods != null) { foreach (KeyValuePair fileKvp in methods) { if (fileKvp.Value != null) { foreach (KeyValuePair functionKvp in fileKvp.Value) { #if UNITY_EDITOR UnityEngine.Object.DestroyImmediate(functionKvp.Value); #else UnityEngine.Object.Destroy(functionKvp.Value); #endif } } } methods = null; } } public static bool CheckComponents(GameObject checkObject, bool readAllComponents, ref DictionaryOfStringAndDictionaryOfStringAndMethodImplementation methods) { bool success = true; methods = new DictionaryOfStringAndDictionaryOfStringAndMethodImplementation(); foreach (Component component in checkObject.GetComponents()) { if (debugActive) Debug.Log("MethodScanner.CheckComponents: Checking Component "+component.GetType().Name+" on "+component.gameObject.name); if (component != null) { MemberInfo[] members = component.GetType().GetMembers(bindingFlags); foreach (MemberInfo memberInfo in members) { if (memberInfo.IsDefined(typeof(Task), true)) { MethodImplementation methodImplementation = ScriptableObject.CreateInstance(); methodImplementation.Init(memberInfo, component); if (debugActive) Debug.Log("MethodScanner.CheckComponents: Method found with name "+methodImplementation.fullName + " " + methodImplementation.parameters); if (methodImplementation.HasImplementation()) { success &= AddTaskImplementation(methodImplementation, ref methods); } } else { if (readAllComponents) { MethodImplementation methodImplementation = ScriptableObject.CreateInstance(); methodImplementation.Init(memberInfo, component); if (debugActive) Debug.Log("MethodScanner.CheckComponents: Method found with name "+methodImplementation.fullName + " " + methodImplementation.parameters); if (methodImplementation.HasImplementation()) { success &= AddTaskImplementation(methodImplementation, ref methods); } } } } } } return IsGenerated(methods) && success; } public static bool AddTaskImplementation(MethodImplementation methodImplementation, ref DictionaryOfStringAndDictionaryOfStringAndMethodImplementation methods) { string taskName = methodImplementation.fullName; string paramtersAsString = methodImplementation.parameters.ToString(); // generate unique key dictionarys if (!methods.ContainsKey(taskName)) { methods[taskName] = new DictionaryOfStringAndMethodImplementation(); //Dictionary(); } // add the list if (!methods[taskName].ContainsKey(paramtersAsString)) { methods[taskName][paramtersAsString] = methodImplementation; } // we have this exact implementation already in the dict, should normally not happen, maybe if you have 2 scripts of the same type on the object? else { Debug.LogWarning("Duplicate function: " + taskName + " with parms: " + paramtersAsString); return false; } return true; } } }