using System; using System.Reflection; using UnityEngine; namespace Passer { /// /// A function which can be called /// [Serializable] public partial class FunctionCall { /// /// The target GameObject on which the function should be called. /// public GameObject targetGameObject; /// /// The name of the method to call on the GameObject /// /// The format of this string is <fully qualified component type>.<function name> public string methodName; public FunctionCall() { } /// /// Creates a new FunctionCall /// /// The GameObject on which the functioncall is executed /// The full method name: component/methodName public FunctionCall(GameObject targetGameObject, string methodName) { this.targetGameObject = targetGameObject; this.methodName = methodName; } protected INetworkObject networkObject; protected Delegate targetDelegate; protected delegate void Method(); protected delegate void MethodBool(bool value); protected delegate void MethodFloat(float value); protected delegate void MethodInt(int value); protected delegate void MethodVector3(Vector3 value); protected delegate void MethodGameObject(GameObject value); protected delegate void MethodRigidbody(Rigidbody value); // For animation parameter calls protected delegate void MethodStringBool(string s, bool value); protected delegate void MethodStringFloat(string s, float value); protected delegate void MethodStringInt(string s, int value); public enum ParameterType { Void, Float, Int, Bool, Vector3, GameObject, Rigidbody, String, } public static Type ToSystemType(ParameterType parameterType) { switch (parameterType) { default: case ParameterType.Void: return typeof(void); case ParameterType.Bool: return typeof(bool); case ParameterType.Int: return typeof(int); case ParameterType.Float: return typeof(float); case ParameterType.Vector3: return typeof(Vector3); case ParameterType.GameObject: return typeof(GameObject); case ParameterType.Rigidbody: return typeof(Rigidbody); case ParameterType.String: return typeof(string); } } /// /// Function Parameter /// [Serializable] public class Parameter { /// /// The parameter value comes from the event /// /// When false one of the constant values is used, based on the type of the parameter public bool fromEvent = false; /// /// For future use... /// public string localProperty; /// /// The type of the parameter /// /// May be converted to a System.Type later... public ParameterType type; /// /// The constant float value when the parameter type is float and fromEvent is false. /// public float floatConstant; /// /// The constant integer value when the parameter type is int and fromEvent is false. /// public int intConstant; /// /// The constant boolean value when the parameter type is bool and fromEvent is false. /// public bool boolConstant; /// /// The constant string value when the parameter type is string and fromEvent is false. /// public string stringConstant; /// /// The constant Vector3 value when the parameter type is Vector3 and fromEvent is false. /// public Vector3 vector3Constant; /// /// The constant GameObject value when the parameter type is GameObject and fromEvent is false. /// public GameObject gameObjectConstant; /// /// The constant Rigidbody value when the parameter type is Rigidbody and fromEvent is false. /// public Rigidbody rigidbodyConstant; } /// /// For future use... /// public Parameter[] parameters; /// /// Adds a new Parameter to the function call /// /// The new Parameter public Parameter AddParameter() { if (parameters == null || parameters.Length == 0) parameters = new Parameter[1]; parameters[parameters.Length - 1] = new Parameter(); return parameters[parameters.Length - 1]; } public static void Execute(GameObject target, string methodName) { UnityEngine.Object component = GetComponent(target, methodName); Method method = CreateMethod(component, methodName); method(); } /// /// For future use... /// public enum Networking { No, Yes } /// /// Execute the void function call /// /// For future use... public virtual void Execute(Networking networking = Networking.No) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } if (targetDelegate is Method) { ((Method)targetDelegate)(); ExecuteRemote(); } else if (targetDelegate is MethodBool) { ((MethodBool)targetDelegate)(parameters[0].boolConstant); ExecuteRemote(parameters[0].boolConstant); } else if (targetDelegate is MethodInt) ((MethodInt)targetDelegate)(parameters[0].intConstant); else if (targetDelegate is MethodFloat) ((MethodFloat)targetDelegate)(parameters[0].floatConstant); else if (targetDelegate is MethodGameObject) { ((MethodGameObject)targetDelegate)(parameters[0].gameObjectConstant); } else if (targetDelegate is MethodVector3) ((MethodVector3)targetDelegate)(parameters[0].vector3Constant); else if (targetDelegate is MethodRigidbody) ((MethodRigidbody)targetDelegate)(parameters[0].rigidbodyConstant); } private void ExecuteRemote() { if (NetworkObject.connected == false) return; if (networkObject == null) networkObject = NetworkObject.GetINetworkObject(this); if (networkObject != null) networkObject.RPC(this); } private void ExecuteRemote(bool value) { if (NetworkObject.connected == false) return; if (networkObject == null) networkObject = NetworkObject.GetINetworkObject(this); if (networkObject != null) networkObject.RPC(this, value); } private void ExecuteRemote(float value) { if (NetworkObject.connected == false) return; if (networkObject == null) networkObject = NetworkObject.GetINetworkObject(this); if (networkObject != null) networkObject.RPC(this, value); } public static void Execute(GameObject target, string methodName, bool boolValue) { UnityEngine.Object component = GetComponent(target, methodName); MethodBool method = CreateMethodBool(component, methodName); method(boolValue); } public static void Execute(GameObject target, string methodName, float floatValue) { UnityEngine.Object component = GetComponent(target, methodName); MethodFloat method = CreateMethodFloat(component, methodName); method(floatValue); } /// /// Execute a function call with a boolean parameter /// /// The boolean value to pass to the function /// For future use... public void Execute(bool value, Networking networking = Networking.No) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodBool)targetDelegate)(value); ExecuteRemote(value); } /// /// Call the function with an integer parameter /// /// The integer value to pass to the function public void Execute(int value) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodInt)targetDelegate)(value); } /// /// Call the function with a float parameter /// /// The float value to pass to the function public virtual void Execute(float value) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodFloat)targetDelegate)(value); } /// /// Call the function with a Vector3 parameter /// /// The Vector3 value to pass to the function public void Execute(Vector3 value) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodVector3)targetDelegate)(value); } /// /// Call the funtion with a GameObject parameter /// /// The GameObject value to pass to the function public void Execute(GameObject value) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodGameObject)targetDelegate)(value); } /// /// Call the function with a Rigidbody parameter /// /// The Rigidbody value to pass to the function protected void Execute(Rigidbody value) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodRigidbody)targetDelegate)(value); } /// /// Call the function with a string and a boolean parameter /// /// The string value to pass to the function as the first parameter /// The boolean value to pass to the function as the second parameter public void ExecuteString(string s, bool value) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodStringBool)targetDelegate)(s, value); } /// /// Call the function with a string and a float parameter /// /// The string value to pass to the function as the first parameter /// The float value to pass to the function as the second parameter public void ExecuteString(string s, float value) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodStringFloat)targetDelegate)(s, value); } /// /// Call the function with a string and a integer parameter /// /// The string value to pass to the function as the first parameter /// The integer value to pass to the function as the second parameter public void ExecuteString(string s, int value) { if (targetDelegate == null) { GetTargetMethod(); if (targetDelegate == null) return; } ((MethodStringInt)targetDelegate)(s, value); } protected virtual void GetTargetMethod() { if (targetGameObject == null) return; string localMethodName; if (methodName != null && methodName.Length > 21 && methodName.Substring(0, 21).Equals("SetAnimatorParameter/")) { CreateAnimationParameterMethod(targetGameObject, methodName); if (targetDelegate != null) return; } UnityEngine.Object targetComponent = GetComponent(targetGameObject, methodName, out localMethodName); if (targetComponent == null) return; if (targetComponent is Script) { Script script = (Script)targetComponent; targetDelegate = (Method)(() => script.Execute()); return; } if (parameters == null || parameters.Length == 0) { targetDelegate = CreateMethod(targetGameObject, methodName); return; } switch (parameters[0].type) { case ParameterType.Void: targetDelegate = CreateMethod(targetGameObject, methodName); break; case ParameterType.Bool: CreateTargetMethod(targetComponent, localMethodName, parameters[0].fromEvent, parameters[0].boolConstant); break; case ParameterType.Int: CreateTargetMethod(targetComponent, localMethodName, parameters[0].fromEvent, parameters[0].intConstant); break; case ParameterType.Float: CreateTargetMethod(targetComponent, localMethodName, parameters[0].fromEvent, parameters[0].floatConstant); break; case ParameterType.String: CreateTargetMethodString(targetComponent, localMethodName, parameters[0].fromEvent, parameters[0].stringConstant); break; case ParameterType.Vector3: CreateTargetMethod(targetComponent, localMethodName, parameters[0].fromEvent, parameters[0].vector3Constant); break; case ParameterType.GameObject: CreateTargetMethod(targetComponent, localMethodName, parameters[0].fromEvent, parameters[0].gameObjectConstant); break; case ParameterType.Rigidbody: CreateTargetMethod(targetComponent, localMethodName, parameters[0].fromEvent, parameters[0].rigidbodyConstant); break; default: return; } } protected static UnityEngine.Object GetComponent(GameObject target, string fullMethodName) { string methodName; return GetComponent(target, fullMethodName, out methodName); } protected static UnityEngine.Object GetComponent(GameObject target, string fullMethodName, out string methodName) { methodName = fullMethodName; string componentName = ""; int slashPos = methodName.LastIndexOf("/"); if (slashPos >= 0) { methodName = methodName.Substring(slashPos + 1); componentName = fullMethodName.Substring(0, slashPos); } if (componentName == "") return null; if (componentName == "UnityEngine.GameObject") return target; if (componentName == "Script") { Script[] scriptComponents = target.GetComponents