//============= Copyright (c) Ludic GmbH, All rights reserved. ============== // // Purpose: Part of the My Behaviour Tree Code // //============================================================================= using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using UnityEngine; namespace MyBT { [System.Serializable] public class MethodImplementation : ScriptableObject { bool debug = false; // CANNOT BE SERIALIZED! public MemberInfo memberInfo; [SerializeField] public object implementation; [SerializeField] public TaskParameterGroup parameters; [SerializeField] public string fullName; [SerializeField] public string namespaceName; [SerializeField] public string className; [SerializeField] public string memberName; public void Init (MemberInfo _memberInfo, Component component) { // https://stackoverflow.com/questions/607178/how-enumerate-all-classes-with-custom-class-attribute memberInfo = _memberInfo; System.Type classType = memberInfo.DeclaringType; string namespaceClassMemberName = classType.FullName + "." + memberInfo.Name; switch (memberInfo.MemberType) { case MemberTypes.Method: //MethodInfo methodInfo = (MethodInfo)memberInfo; fullName = namespaceClassMemberName; namespaceName = classType.Namespace; className = classType.Name; memberName = memberInfo.Name; parameters = ScriptableObject.CreateInstance(); parameters.Init(memberInfo); implementation = component; break; default: //Debug.LogWarning("TaskImplementation.TaskImplementation: Unknown MemberType " + memberInfo.MemberType); break; } } public bool HasImplementation() { return (implementation != null); } public override string ToString() { return "name='" + this.fullName + "' : implementation " + (this.implementation != null); // + ", task " + (this.task != null); } public bool GetAction(TaskParameterGroup taskParameterGroup, out Action returnAction) { returnAction = null; if (memberInfo == null) { Debug.LogError("undefined memberInfo in MethodImplementation"); return false; } returnAction = null; List executionTaskParameters = taskParameterGroup.GetAll(); if (executionTaskParameters.Count != parameters.Count) { Debug.LogWarning("TaskImplementation.ExecuteTask: invalid parameter count: " + this.fullName + " " + executionTaskParameters.Count + " " + parameters.Count); return false; } // verify and convert parameters List parametersList = new List(); for (int i = 0; i < parameters.Count; i++) { if (executionTaskParameters[i].valType == parameters[i].valType) { try { parametersList.Add(executionTaskParameters[i].valValue); } catch (Exception e) { Debug.LogError("TaskImplementation.ExecuteTask: cannot convert parameter: " + i + " " + executionTaskParameters[i] + " : " + e.ToString()); return false; } } else { //Debug.LogWarning("TaskImplementation.ExecuteTask: trying conversion of parameter: " + i + " " + executionTaskParameters[i] + " " + executionTaskParameters[i].valType + " " + parameterTypesNew[i].valType); object convertedValue = Convert.ChangeType(executionTaskParameters[i].valValue, parameters[i].valType); parametersList.Add(convertedValue); } } object[] executionParameters = parametersList.ToArray(); if (debug) Debug.Log("MethodImplementation.GetAction: member "+memberInfo.Name+" parameters "+taskParameterGroup); // call a method MethodInfo methodInfo = (MethodInfo)memberInfo; if (methodInfo.ReturnType == typeof(void)) { if (this.parameters.Count > 0) { returnAction = () => methodInfo.Invoke(implementation, executionParameters); } else { returnAction = System.Delegate.CreateDelegate(typeof(System.Action), implementation, methodInfo) as System.Action; } } else { // for the moment dont handle methods with return value differently then the ones without return value if (this.parameters.Count > 0) { returnAction = () => methodInfo.Invoke(implementation, executionParameters); } else { returnAction = System.Delegate.CreateDelegate(typeof(System.Action), implementation, methodInfo) as System.Action; } } return true; } } }