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.

154 lines
4.9 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)
// Adapted from the Unity Test Tools project (MIT license)
// https://bitbucket.org/Unity-Technologies/unitytesttools/src/a30d562427e9/Assets/UnityTestTools/
using UnityEngine;
using MoonSharp.Interpreter;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;
namespace Fungus
{
/// <summary>
/// Executes Lua script defined in a string property or in an external file.
/// </summary>
public class LuaScript : MonoBehaviour, ILuaScript
{
/// <summary>
/// The Lua Environment to use when executing Lua script.
/// </summary>
[Tooltip("The Lua Environment to use when executing Lua script.")]
[SerializeField] protected LuaEnvironment luaEnvironment;
protected ILuaEnvironment LuaEnv { get; set; }
/// <summary>
/// Text file containing Lua script to be executed.
/// </summary>
[Tooltip("Text file containing Lua script to be executed.")]
[SerializeField] protected TextAsset luaFile;
/// <summary>
/// Lua script to execute.
/// </summary>
[Tooltip("A Lua string to execute, appended to the contents of Lua File (if one is specified).")]
[TextArea(5, 50)]
[SerializeField] protected string luaScript = "";
/// <summary>
/// Run the script as a Lua coroutine so execution can be yielded for asynchronous operations.
/// </summary>
[Tooltip("Run the script as a Lua coroutine so execution can be yielded for asynchronous operations.")]
[SerializeField] protected bool runAsCoroutine = true;
protected string friendlyName = "";
protected bool initialised;
// This is public so the editor code can force the component to reinitialise
public bool Initialised { set { initialised = value; } }
// Stores the compiled Lua code for fast execution later.
protected Closure luaFunction;
// Recursively build the full hierarchy path to this game object
private static string GetPath(Transform current)
{
if (current.parent == null)
{
return current.name;
}
return GetPath(current.parent) + "." + current.name;
}
protected virtual void Start()
{
InitLuaScript();
}
/// <summary>
/// Initialises the Lua environment and compiles the Lua string for execution later on.
/// </summary>
protected virtual void InitLuaScript()
{
if (initialised)
{
return;
}
if (LuaEnv == null &&
luaEnvironment != null)
{
LuaEnv = luaEnvironment as ILuaEnvironment;
}
if (LuaEnv == null)
{
// Create a Lua Environment if none exists yet
LuaEnv = LuaEnvironment.GetLua();
}
if (LuaEnv == null)
{
Debug.LogError("No Lua Environment found");
return;
}
// Ensure the LuaEnvironment is initialized before trying to execute code
LuaEnv.InitEnvironment();
// Cache a descriptive name to use in Lua error messages
friendlyName = GetPath(transform) + ".LuaScript";
string s = GetLuaString();
luaFunction = LuaEnv.LoadLuaFunction(s, friendlyName);
initialised = true;
}
/// <summary>
/// Returns the Lua string to be executed.
/// This is the contents of the Lua script appended to the contents of the Lua file.
/// </summary>
/// <returns>The lua string.</returns>
protected virtual string GetLuaString()
{
string s = "";
if (luaFile != null)
{
s = luaFile.text;
}
if (luaScript.Length > 0)
{
s += luaScript;
}
return s;
}
#region ILuaScript implementation
/// <summary>
/// Execute the Lua script.
/// This is the function to call if you want to trigger execution from an external script.
/// </summary>
public virtual void OnExecute()
{
// Make sure the script and Lua environment are initialised before executing
InitLuaScript();
if (LuaEnv == null)
{
Debug.LogWarning("No Lua Environment found");
}
else
{
LuaEnv.RunLuaFunction(luaFunction, runAsCoroutine);
}
}
#endregion
}
}