You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
404 lines
12 KiB
404 lines
12 KiB
9 years ago
|
using UnityEngine;
|
||
|
using System.Collections;
|
||
|
using System.Reflection;
|
||
|
using System.Linq;
|
||
|
using System.Collections.Generic;
|
||
|
using System;
|
||
|
using UnityEngine.Events;
|
||
|
|
||
|
namespace Fungus
|
||
|
{
|
||
|
|
||
|
[CommandInfo("Scripting",
|
||
|
"Invoke Method",
|
||
|
"Invokes a method of a component via reflection. Supports passing multiple parameters and storing returned values in a Fungus variable.")]
|
||
|
public class InvokeMethod : Command
|
||
|
{
|
||
|
[Tooltip("Delay before invoking method")]
|
||
|
public float delay;
|
||
|
|
||
|
[Tooltip("GameObject containing the component method to be invoked")]
|
||
|
public GameObject targetObject;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("Name of assembly containing the target component")]
|
||
|
public string targetComponentAssemblyName;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("Full name of the target component")]
|
||
|
public string targetComponentFullname;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("Display name of the target component")]
|
||
|
public string targetComponentText;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("Name of target method to invoke on the target component")]
|
||
|
public string targetMethod;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("Display name of target method to invoke on the target component")]
|
||
|
public string targetMethodText;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("List of parameters to pass to the invoked method")]
|
||
|
public InvokeMethodParameter[] methodParameters;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("If true, store the return value in a flowchart variable of the same type.")]
|
||
|
public bool saveReturnValue;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("Name of Fungus variable to store the return value in")]
|
||
|
public string returnValueVariableKey;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("The type of the return value")]
|
||
|
public string returnValueType;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("If true, list all inherited methods for the component")]
|
||
|
public bool showInherited;
|
||
|
|
||
|
[HideInInspector]
|
||
|
[Tooltip("The coroutine call behavior for methods that return IEnumerator")]
|
||
|
public Fungus.Call.CallMode callMode;
|
||
|
|
||
|
protected Type componentType;
|
||
|
protected Component objComponent;
|
||
|
protected Type[] parameterTypes = null;
|
||
|
protected MethodInfo objMethod;
|
||
|
|
||
|
protected virtual void Awake()
|
||
|
{
|
||
|
if (componentType == null)
|
||
|
{
|
||
|
componentType = ReflectionHelper.GetType(targetComponentAssemblyName);
|
||
|
}
|
||
|
|
||
|
if (objComponent == null)
|
||
|
{
|
||
|
objComponent = targetObject.GetComponent(componentType);
|
||
|
}
|
||
|
|
||
|
if (parameterTypes == null)
|
||
|
{
|
||
|
parameterTypes = GetParameterTypes();
|
||
|
}
|
||
|
|
||
|
if (objMethod == null)
|
||
|
{
|
||
|
objMethod = UnityEvent.GetValidMethodInfo(objComponent, targetMethod, parameterTypes);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void OnEnter()
|
||
|
{
|
||
|
if (delay <= 0)
|
||
|
{
|
||
|
DoInvokeMethod();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Invoke("DoInvokeMethod", delay);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected virtual void DoInvokeMethod()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
if (targetObject == null || string.IsNullOrEmpty(targetComponentAssemblyName) || string.IsNullOrEmpty(targetMethod))
|
||
|
{
|
||
|
Continue();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (returnValueType != "System.Collections.IEnumerator")
|
||
|
{
|
||
|
var objReturnValue = objMethod.Invoke(objComponent, GetParameterValues());
|
||
|
|
||
|
if (saveReturnValue)
|
||
|
{
|
||
|
SetVariable(returnValueVariableKey, objReturnValue, returnValueType);
|
||
|
}
|
||
|
|
||
|
Continue();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StartCoroutine(ExecuteCoroutine());
|
||
|
|
||
|
if(callMode == Call.CallMode.Continue)
|
||
|
{
|
||
|
Continue();
|
||
|
}
|
||
|
else if(callMode == Call.CallMode.Stop)
|
||
|
{
|
||
|
Stop();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (System.Exception ex)
|
||
|
{
|
||
|
Debug.LogError("Error: " + ex.Message);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected virtual IEnumerator ExecuteCoroutine()
|
||
|
{
|
||
|
yield return StartCoroutine((IEnumerator)objMethod.Invoke(objComponent, GetParameterValues()));
|
||
|
|
||
|
if (callMode == Call.CallMode.WaitUntilFinished)
|
||
|
{
|
||
|
Continue();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override Color GetButtonColor()
|
||
|
{
|
||
|
return new Color32(235, 191, 217, 255);
|
||
|
}
|
||
|
|
||
|
public override string GetSummary()
|
||
|
{
|
||
|
if (targetObject == null)
|
||
|
{
|
||
|
return "Error: targetObject is not assigned";
|
||
|
}
|
||
|
|
||
|
return targetObject.name + "." + targetComponentText + "." + targetMethodText;
|
||
|
}
|
||
|
|
||
|
protected System.Type[] GetParameterTypes()
|
||
|
{
|
||
|
System.Type[] types = new System.Type[methodParameters.Length];
|
||
|
|
||
|
for (int i = 0; i < methodParameters.Length; i++)
|
||
|
{
|
||
|
var item = methodParameters[i];
|
||
|
var objType = ReflectionHelper.GetType(item.objValue.typeAssemblyname);
|
||
|
|
||
|
types[i] = objType;
|
||
|
}
|
||
|
|
||
|
return types;
|
||
|
}
|
||
|
|
||
|
protected object[] GetParameterValues()
|
||
|
{
|
||
|
object[] values = new object[methodParameters.Length];
|
||
|
var flowChart = GetFlowchart();
|
||
|
|
||
|
for (int i = 0; i < methodParameters.Length; i++)
|
||
|
{
|
||
|
var item = methodParameters[i];
|
||
|
|
||
|
if (string.IsNullOrEmpty(item.variableKey))
|
||
|
{
|
||
|
values[i] = item.objValue.GetValue();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
object objValue = null;
|
||
|
|
||
|
switch (item.objValue.typeFullname)
|
||
|
{
|
||
|
case "System.Int32":
|
||
|
objValue = flowChart.GetIntegerVariable(item.variableKey);
|
||
|
break;
|
||
|
case "System.Boolean":
|
||
|
objValue = flowChart.GetBooleanVariable(item.variableKey);
|
||
|
break;
|
||
|
case "System.Single":
|
||
|
objValue = flowChart.GetFloatVariable(item.variableKey);
|
||
|
break;
|
||
|
case "System.String":
|
||
|
objValue = flowChart.GetStringVariable(item.variableKey);
|
||
|
break;
|
||
|
case "UnityEngine.Color":
|
||
|
var color = flowChart.GetVariable<ColorVariable>(item.variableKey);
|
||
|
if (color != null)
|
||
|
objValue = color.value;
|
||
|
break;
|
||
|
case "UnityEngine.GameObject":
|
||
|
var gameObject = flowChart.GetVariable<GameObjectVariable>(item.variableKey);
|
||
|
if (gameObject != null)
|
||
|
objValue = gameObject.value;
|
||
|
break;
|
||
|
case "UnityEngine.Material":
|
||
|
var material = flowChart.GetVariable<MaterialVariable>(item.variableKey);
|
||
|
if (material != null)
|
||
|
objValue = material.value;
|
||
|
break;
|
||
|
case "UnityEngine.Sprite":
|
||
|
var sprite = flowChart.GetVariable<SpriteVariable>(item.variableKey);
|
||
|
if (sprite != null)
|
||
|
objValue = sprite.value;
|
||
|
break;
|
||
|
case "UnityEngine.Texture":
|
||
|
var texture = flowChart.GetVariable<TextureVariable>(item.variableKey);
|
||
|
if (texture != null)
|
||
|
objValue = texture.value;
|
||
|
break;
|
||
|
case "UnityEngine.Vector2":
|
||
|
var vector2 = flowChart.GetVariable<Vector2Variable>(item.variableKey);
|
||
|
if (vector2 != null)
|
||
|
objValue = vector2.value;
|
||
|
break;
|
||
|
case "UnityEngine.Vector3":
|
||
|
var vector3 = flowChart.GetVariable<Vector3Variable>(item.variableKey);
|
||
|
if (vector3 != null)
|
||
|
objValue = vector3.value;
|
||
|
break;
|
||
|
default:
|
||
|
var obj = flowChart.GetVariable<ObjectVariable>(item.variableKey);
|
||
|
if (obj != null)
|
||
|
objValue = obj.value;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
values[i] = objValue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return values;
|
||
|
}
|
||
|
|
||
|
protected void SetVariable(string key, object value, string returnType)
|
||
|
{
|
||
|
var flowChart = GetFlowchart();
|
||
|
|
||
|
switch (returnType)
|
||
|
{
|
||
|
case "System.Int32":
|
||
|
flowChart.SetIntegerVariable(key, (int)value);
|
||
|
break;
|
||
|
case "System.Boolean":
|
||
|
flowChart.SetBooleanVariable(key, (bool)value);
|
||
|
break;
|
||
|
case "System.Single":
|
||
|
flowChart.SetFloatVariable(key, (float)value);
|
||
|
break;
|
||
|
case "System.String":
|
||
|
flowChart.SetStringVariable(key, (string)value);
|
||
|
break;
|
||
|
case "UnityEngine.Color":
|
||
|
flowChart.GetVariable<ColorVariable>(key).value = (UnityEngine.Color)value;
|
||
|
break;
|
||
|
case "UnityEngine.GameObject":
|
||
|
flowChart.GetVariable<GameObjectVariable>(key).value = (UnityEngine.GameObject)value;
|
||
|
break;
|
||
|
case "UnityEngine.Material":
|
||
|
flowChart.GetVariable<MaterialVariable>(key).value = (UnityEngine.Material)value;
|
||
|
break;
|
||
|
case "UnityEngine.Sprite":
|
||
|
flowChart.GetVariable<SpriteVariable>(key).value = (UnityEngine.Sprite)value;
|
||
|
break;
|
||
|
case "UnityEngine.Texture":
|
||
|
flowChart.GetVariable<TextureVariable>(key).value = (UnityEngine.Texture)value;
|
||
|
break;
|
||
|
case "UnityEngine.Vector2":
|
||
|
flowChart.GetVariable<Vector2Variable>(key).value = (UnityEngine.Vector2)value;
|
||
|
break;
|
||
|
case "UnityEngine.Vector3":
|
||
|
flowChart.GetVariable<Vector3Variable>(key).value = (UnityEngine.Vector3)value;
|
||
|
break;
|
||
|
default:
|
||
|
flowChart.GetVariable<ObjectVariable>(key).value = (UnityEngine.Object)value;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class InvokeMethodParameter
|
||
|
{
|
||
|
[SerializeField]
|
||
|
public ObjectValue objValue;
|
||
|
|
||
|
|
||
|
[SerializeField]
|
||
|
public string variableKey;
|
||
|
}
|
||
|
|
||
|
[System.Serializable]
|
||
|
public class ObjectValue
|
||
|
{
|
||
|
public string typeAssemblyname;
|
||
|
public string typeFullname;
|
||
|
|
||
|
public int intValue;
|
||
|
public bool boolValue;
|
||
|
public float floatValue;
|
||
|
public string stringValue;
|
||
|
|
||
|
public Color colorValue;
|
||
|
public GameObject gameObjectValue;
|
||
|
public Material materialValue;
|
||
|
public UnityEngine.Object objectValue;
|
||
|
public Sprite spriteValue;
|
||
|
public Texture textureValue;
|
||
|
public Vector2 vector2Value;
|
||
|
public Vector3 vector3Value;
|
||
|
|
||
|
public object GetValue()
|
||
|
{
|
||
|
switch (typeFullname)
|
||
|
{
|
||
|
case "System.Int32":
|
||
|
return intValue;
|
||
|
case "System.Boolean":
|
||
|
return boolValue;
|
||
|
case "System.Single":
|
||
|
return floatValue;
|
||
|
case "System.String":
|
||
|
return stringValue;
|
||
|
case "UnityEngine.Color":
|
||
|
return colorValue;
|
||
|
case "UnityEngine.GameObject":
|
||
|
return gameObjectValue;
|
||
|
case "UnityEngine.Material":
|
||
|
return materialValue;
|
||
|
case "UnityEngine.Sprite":
|
||
|
return spriteValue;
|
||
|
case "UnityEngine.Texture":
|
||
|
return textureValue;
|
||
|
case "UnityEngine.Vector2":
|
||
|
return vector2Value;
|
||
|
case "UnityEngine.Vector3":
|
||
|
return vector3Value;
|
||
|
default:
|
||
|
var objType = ReflectionHelper.GetType(typeAssemblyname);
|
||
|
|
||
|
if (objType.IsSubclassOf(typeof(UnityEngine.Object)))
|
||
|
{
|
||
|
return objectValue;
|
||
|
}
|
||
|
else if (objType.IsEnum)
|
||
|
return System.Enum.ToObject(objType, intValue);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static class ReflectionHelper
|
||
|
{
|
||
|
static Dictionary<string, System.Type> types = new Dictionary<string, System.Type>();
|
||
|
|
||
|
public static System.Type GetType(string typeName)
|
||
|
{
|
||
|
if (types.ContainsKey(typeName))
|
||
|
return types[typeName];
|
||
|
|
||
|
types[typeName] = System.Type.GetType(typeName);
|
||
|
|
||
|
return types[typeName];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|