An easy to use Unity 3D library for creating illustrated Interactive Fiction games and more.
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.

417 lines
15 KiB

// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
using UnityEngine;
using System.Collections;
using System.Reflection;
using System.Collections.Generic;
using System;
using UnityEngine.Events;
using MarkerMetro.Unity.WinLegacy.Reflection;
namespace Fungus
{
/// <summary>
/// Invokes a method of a component via reflection. Supports passing multiple parameters and storing returned values in a Fungus variable.
/// </summary>
[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("A description of what this command does. Appears in the command summary.")]
[SerializeField] protected string description = "";
[Tooltip("GameObject containing the component method to be invoked")]
[SerializeField] protected GameObject targetObject;
[HideInInspector]
[Tooltip("Name of assembly containing the target component")]
[SerializeField] protected string targetComponentAssemblyName;
[HideInInspector]
[Tooltip("Full name of the target component")]
[SerializeField] protected string targetComponentFullname;
[HideInInspector]
[Tooltip("Display name of the target component")]
[SerializeField] protected string targetComponentText;
[HideInInspector]
[Tooltip("Name of target method to invoke on the target component")]
[SerializeField] protected string targetMethod;
[HideInInspector]
[Tooltip("Display name of target method to invoke on the target component")]
[SerializeField] protected string targetMethodText;
[HideInInspector]
[Tooltip("List of parameters to pass to the invoked method")]
[SerializeField] protected InvokeMethodParameter[] methodParameters;
[HideInInspector]
[Tooltip("If true, store the return value in a flowchart variable of the same type.")]
[SerializeField] protected bool saveReturnValue;
[HideInInspector]
[Tooltip("Name of Fungus variable to store the return value in")]
[SerializeField] protected string returnValueVariableKey;
[HideInInspector]
[Tooltip("The type of the return value")]
[SerializeField] protected string returnValueType;
[HideInInspector]
[Tooltip("If true, list all inherited methods for the component")]
[SerializeField] protected bool showInherited;
[HideInInspector]
[Tooltip("The coroutine call behavior for methods that return IEnumerator")]
[SerializeField] protected 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);
}
}
protected virtual IEnumerator ExecuteCoroutine()
{
yield return StartCoroutine((IEnumerator)objMethod.Invoke(objComponent, GetParameterValues()));
if (callMode == CallMode.WaitUntilFinished)
{
Continue();
}
}
protected virtual 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 virtual 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":
var intvalue = flowChart.GetVariable<IntegerVariable>(item.variableKey);
if (intvalue != null)
objValue = intvalue.Value;
break;
case "System.Boolean":
var boolean = flowChart.GetVariable<BooleanVariable>(item.variableKey);
if (boolean != null)
objValue = boolean.Value;
break;
case "System.Single":
var floatvalue = flowChart.GetVariable<FloatVariable>(item.variableKey);
if (floatvalue != null)
objValue = floatvalue.Value;
break;
case "System.String":
var stringvalue = flowChart.GetVariable<StringVariable>(item.variableKey);
if (stringvalue != null)
objValue = stringvalue.Value;
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 virtual void SetVariable(string key, object value, string returnType)
{
var flowChart = GetFlowchart();
switch (returnType)
{
case "System.Int32":
flowChart.GetVariable<IntegerVariable>(key).Value = (int)value;
break;
case "System.Boolean":
flowChart.GetVariable<BooleanVariable>(key).Value = (bool)value;
break;
case "System.Single":
flowChart.GetVariable<FloatVariable>(key).Value = (float)value;
break;
case "System.String":
flowChart.GetVariable<StringVariable>(key).Value = (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;
}
}
#region Public members
/// <summary>
/// GameObject containing the component method to be invoked.
/// </summary>
public virtual GameObject TargetObject { get { return targetObject; } }
public override void OnEnter()
{
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 == CallMode.Continue)
{
Continue();
}
else if(callMode == CallMode.Stop)
{
StopParentBlock();
}
}
}
catch (System.Exception ex)
{
Debug.LogError("Error: " + ex.Message);
}
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
public override string GetSummary()
{
if (targetObject == null)
{
return "Error: targetObject is not assigned";
}
if (!string.IsNullOrEmpty(description))
{
return description;
}
return targetObject.name + "." + targetComponentText + "." + targetMethodText;
}
#endregion
}
[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];
}
}
}