Files
beyond/Assets/ThirdParty/PlayMaker/Actions/ScriptControl/CallStaticMethod.cs
2024-11-20 15:21:28 +01:00

170 lines
5.2 KiB
C#

// (c) copyright Hutong Games, LLC 2010-2012. All rights reserved.
using System;
using System.Reflection;
using UnityEngine;
using System.Collections.Generic;
namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.ScriptControl)]
[Tooltip("Call a static method in a class.")]
public class CallStaticMethod : FsmStateAction
{
[Tooltip("Full path to the class that contains the static method.")]
public FsmString className;
[Tooltip("The static method to call.")]
public FsmString methodName;
[Tooltip("Method parameters. NOTE: these must match the method's signature!")]
public FsmVar[] parameters;
[ActionSection("Store Result")]
[UIHint(UIHint.Variable)]
[Tooltip("Store the result of the method call.")]
public FsmVar storeResult;
[Tooltip("Repeat every frame.")]
public bool everyFrame;
private Type cachedType;
private string cachedClassName;
private string cachedMethodName;
private MethodInfo cachedMethodInfo;
private ParameterInfo[] cachedParameterInfo;
private object[] parametersArray;
private string errorString;
public override void OnEnter()
{
parametersArray = new object[parameters.Length];
DoMethodCall();
if (!everyFrame)
{
Finish();
}
}
public override void OnUpdate()
{
DoMethodCall();
}
private void DoMethodCall()
{
if (className == null || string.IsNullOrEmpty(className.Value))
{
Finish();
return;
}
if (cachedClassName != className.Value || cachedMethodName != methodName.Value)
{
errorString = string.Empty;
if(!DoCache())
{
Debug.LogError(errorString);
Finish();
return;
}
}
object result = null;
if (cachedParameterInfo.Length == 0)
{
result = cachedMethodInfo.Invoke(null, null);
}
else
{
for (var i = 0; i < parameters.Length; i++)
{
var parameter = parameters[i];
parameter.UpdateValue();
parametersArray[i] = parameter.GetValue();
}
result = cachedMethodInfo.Invoke(null, parametersArray);
}
storeResult.SetValue(result);
}
private bool DoCache()
{
cachedType = ReflectionUtils.GetGlobalType(className.Value);
if (cachedType == null)
{
errorString += "Class is invalid: " + className.Value + "\n";
Finish();
return false;
}
cachedClassName = className.Value;
#if NETFX_CORE
cachedMethodInfo = cachedType.GetTypeInfo().GetDeclaredMethod(methodName.Value);
#else
var types = new List<Type>( capacity: parameters.Length );
foreach ( var each in parameters ) {
types.Add( each.RealType );
}
cachedMethodInfo = cachedType.GetMethod(methodName.Value, types.ToArray());
#endif
if (cachedMethodInfo == null)
{
errorString += "Invalid Method Name or Parameters: " + methodName.Value +"\n";
Finish();
return false;
}
cachedMethodName = methodName.Value;
cachedParameterInfo = cachedMethodInfo.GetParameters();
return true;
}
public override string ErrorCheck()
{
errorString = string.Empty;
DoCache();
if (!string.IsNullOrEmpty(errorString))
{
return errorString;
}
if (parameters.Length != cachedParameterInfo.Length)
{
return "Parameter count does not match method.\nMethod has " + cachedParameterInfo.Length + " parameters.\nYou specified " +parameters.Length + " paramaters.";
}
for (var i = 0; i < parameters.Length; i++)
{
var p = parameters[i];
var paramType = p.RealType;
var paramInfoType = cachedParameterInfo[i].ParameterType;
if (!ReferenceEquals(paramType, paramInfoType ))
{
return "Parameters do not match method signature.\nParameter " + (i + 1) + " (" + paramType + ") should be of type: " + paramInfoType;
}
}
if (ReferenceEquals(cachedMethodInfo.ReturnType, typeof(void)))
{
if (!string.IsNullOrEmpty(storeResult.variableName))
{
return "Method does not have return.\nSpecify 'none' in Store Result.";
}
}
else if (!ReferenceEquals(cachedMethodInfo.ReturnType,storeResult.RealType))
{
return "Store Result is of the wrong type.\nIt should be of type: " + cachedMethodInfo.ReturnType;
}
return string.Empty;
}
}
}