|
|
@ -16,84 +16,19 @@ namespace Fungus |
|
|
|
/// <summary> |
|
|
|
/// <summary> |
|
|
|
/// Wrapper for a MoonSharp Lua Script instance. |
|
|
|
/// Wrapper for a MoonSharp Lua Script instance. |
|
|
|
/// </summary> |
|
|
|
/// </summary> |
|
|
|
public class LuaEnvironment : MonoBehaviour, ILuaEnvironment |
|
|
|
public class LuaEnvironment : MonoBehaviour |
|
|
|
{ |
|
|
|
{ |
|
|
|
/// <summary> |
|
|
|
/// <summary> |
|
|
|
/// Custom file loader for MoonSharp that loads in all Lua scripts in the project. |
|
|
|
/// Launches the remote Lua debugger in your browser and breaks execution at the first executed Lua command. |
|
|
|
/// Scripts must be placed in a Resources/Lua directory. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
protected class LuaScriptLoader : ScriptLoaderBase |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Give the script loader access to the list of accessible Lua Modules. |
|
|
|
|
|
|
|
private IEnumerable<TextAsset> luaScripts; |
|
|
|
|
|
|
|
public LuaScriptLoader(IEnumerable<TextAsset> luaScripts) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.luaScripts = luaScripts; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
// Bypasses the standard path resolution logic for require. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
/// </summary> |
|
|
|
protected override string ResolveModuleName(string modname, string[] paths) |
|
|
|
[Tooltip("Launches the remote Lua debugger in your browser and breaks execution at the first executed Lua command. Standalone platform only.")] |
|
|
|
{ |
|
|
|
[SerializeField] protected bool remoteDebugger = false; |
|
|
|
return modname; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override object LoadFile(string file, Table globalContext) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
foreach (TextAsset luaScript in luaScripts) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Case insensitive string compare to allow standard Lua naming conventions in code |
|
|
|
|
|
|
|
if (String.Compare(luaScript.name, file, true) == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return luaScript.text; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return ""; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool ScriptFileExists(string name) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
foreach (TextAsset luaScript in luaScripts) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Case insensitive string compare to allow standard Lua naming conventions in code |
|
|
|
|
|
|
|
if (String.Compare(luaScript.name, name, true) == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// <summary> |
|
|
|
/// Returns the first Lua Environment found in the scene, or creates one if none exists. |
|
|
|
/// The MoonSharp interpreter instance. |
|
|
|
/// This is a slow operation, call it once at startup and cache the returned value. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
/// </summary> |
|
|
|
public static ILuaEnvironment GetLua() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ILuaEnvironment luaEnv = GameObject.FindObjectOfType<LuaEnvironment>(); |
|
|
|
|
|
|
|
if (luaEnv == null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
GameObject prefab = Resources.Load<GameObject>("Prefabs/LuaEnvironment"); |
|
|
|
|
|
|
|
if (prefab != null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
GameObject go = Instantiate(prefab) as GameObject; |
|
|
|
|
|
|
|
go.name = "LuaEnvironment"; |
|
|
|
|
|
|
|
luaEnv = go.GetComponent<ILuaEnvironment>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return luaEnv; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected Script interpreter; |
|
|
|
protected Script interpreter; |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Launches the remote Lua debugger in your browser and breaks execution at the first executed Lua command. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
[Tooltip("Launches the remote Lua debugger in your browser and breaks execution at the first executed Lua command. Standalone platform only.")] |
|
|
|
|
|
|
|
[SerializeField] protected bool remoteDebugger = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// <summary> |
|
|
|
/// Instance of remote debugging service when debugging option is enabled. |
|
|
|
/// Instance of remote debugging service when debugging option is enabled. |
|
|
|
/// </summary> |
|
|
|
/// </summary> |
|
|
@ -118,44 +53,6 @@ namespace Fungus |
|
|
|
interpreter.Options.ScriptLoader = new LuaScriptLoader(result.OfType<TextAsset>()); |
|
|
|
interpreter.Options.ScriptLoader = new LuaScriptLoader(result.OfType<TextAsset>()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Register a type given it's assembly qualified name. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
public static void RegisterType(string typeName, bool extensionType = false) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
System.Type t = System.Type.GetType(typeName); |
|
|
|
|
|
|
|
if (t == null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
UnityEngine.Debug.LogWarning("Type not found: " + typeName); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Registering System.Object breaks MoonSharp's automated conversion of Lists and Dictionaries to Lua tables. |
|
|
|
|
|
|
|
if (t == typeof(System.Object)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!UserData.IsTypeRegistered(t)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (extensionType) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
UserData.RegisterExtensionType(t); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
UserData.RegisterType(t); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (ArgumentException ex) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
UnityEngine.Debug.LogWarning(ex.Message); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// <summary> |
|
|
|
/// A Unity coroutine method which updates a Lua coroutine each frame. |
|
|
|
/// A Unity coroutine method which updates a Lua coroutine each frame. |
|
|
|
/// <param name="closure">A MoonSharp closure object representing a function.</param> |
|
|
|
/// <param name="closure">A MoonSharp closure object representing a function.</param> |
|
|
@ -201,21 +98,6 @@ namespace Fungus |
|
|
|
return sourceCode; |
|
|
|
return sourceCode; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Start a Unity coroutine from a Lua call. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
public virtual Task RunUnityCoroutine(IEnumerator coroutine) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (coroutine == null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We use the Task class so we can poll the coroutine to check if it has finished. |
|
|
|
|
|
|
|
// Standard Unity coroutines don't support this check. |
|
|
|
|
|
|
|
return new Task(RunUnityCoroutineImpl(coroutine)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// <summary> |
|
|
|
/// Starts a standard Unity coroutine. |
|
|
|
/// Starts a standard Unity coroutine. |
|
|
|
/// The coroutine is managed by the LuaEnvironment monobehavior, so you can call StopAllCoroutines to |
|
|
|
/// The coroutine is managed by the LuaEnvironment monobehavior, so you can call StopAllCoroutines to |
|
|
@ -273,8 +155,84 @@ namespace Fungus |
|
|
|
UnityEngine.Debug.LogError(output); |
|
|
|
UnityEngine.Debug.LogError(output); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#region ILuaEnvironment implementation |
|
|
|
#region Public members |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Returns the first Lua Environment found in the scene, or creates one if none exists. |
|
|
|
|
|
|
|
/// This is a slow operation, call it once at startup and cache the returned value. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
public static LuaEnvironment GetLua() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var luaEnv = GameObject.FindObjectOfType<LuaEnvironment>(); |
|
|
|
|
|
|
|
if (luaEnv == null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
GameObject prefab = Resources.Load<GameObject>("Prefabs/LuaEnvironment"); |
|
|
|
|
|
|
|
if (prefab != null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
GameObject go = Instantiate(prefab) as GameObject; |
|
|
|
|
|
|
|
go.name = "LuaEnvironment"; |
|
|
|
|
|
|
|
luaEnv = go.GetComponent<LuaEnvironment>(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return luaEnv; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Register a type given it's assembly qualified name. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
public static void RegisterType(string typeName, bool extensionType = false) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
System.Type t = System.Type.GetType(typeName); |
|
|
|
|
|
|
|
if (t == null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
UnityEngine.Debug.LogWarning("Type not found: " + typeName); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Registering System.Object breaks MoonSharp's automated conversion of Lists and Dictionaries to Lua tables. |
|
|
|
|
|
|
|
if (t == typeof(System.Object)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!UserData.IsTypeRegistered(t)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (extensionType) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
UserData.RegisterExtensionType(t); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
UserData.RegisterType(t); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (ArgumentException ex) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
UnityEngine.Debug.LogWarning(ex.Message); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Start a Unity coroutine from a Lua call. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
|
|
|
|
public virtual Task RunUnityCoroutine(IEnumerator coroutine) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (coroutine == null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We use the Task class so we can poll the coroutine to check if it has finished. |
|
|
|
|
|
|
|
// Standard Unity coroutines don't support this check. |
|
|
|
|
|
|
|
return new Task(RunUnityCoroutineImpl(coroutine)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Initialise the Lua interpreter so we can start running Lua code. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
public virtual void InitEnvironment() |
|
|
|
public virtual void InitEnvironment() |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (initialised) |
|
|
|
if (initialised) |
|
|
@ -306,8 +264,16 @@ namespace Fungus |
|
|
|
initialised = true; |
|
|
|
initialised = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// The MoonSharp interpreter instance used to run Lua code. |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
public virtual Script Interpreter { get { return interpreter; } } |
|
|
|
public virtual Script Interpreter { get { return interpreter; } } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Loads and compiles a string containing Lua script, returning a closure (Lua function) which can be executed later. |
|
|
|
|
|
|
|
/// <param name="luaString">The Lua code to be run.</param> |
|
|
|
|
|
|
|
/// <param name="friendlyName">A descriptive name to be used in error reports.</param> |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
public virtual Closure LoadLuaFunction(string luaString, string friendlyName) |
|
|
|
public virtual Closure LoadLuaFunction(string luaString, string friendlyName) |
|
|
|
{ |
|
|
|
{ |
|
|
|
InitEnvironment(); |
|
|
|
InitEnvironment(); |
|
|
@ -344,6 +310,12 @@ namespace Fungus |
|
|
|
return res.Function; |
|
|
|
return res.Function; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Load and run a previously compiled Lua script. May be run as a coroutine. |
|
|
|
|
|
|
|
/// <param name="fn">A previously compiled Lua function.</param> |
|
|
|
|
|
|
|
/// <param name="runAsCoroutine">Run the Lua code as a coroutine to support asynchronous operations.</param> |
|
|
|
|
|
|
|
/// <param name="onComplete">Method to callback when the Lua code finishes exection. Supports return parameters.</param> |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
public virtual void RunLuaFunction(Closure fn, bool runAsCoroutine, Action<DynValue> onComplete = null) |
|
|
|
public virtual void RunLuaFunction(Closure fn, bool runAsCoroutine, Action<DynValue> onComplete = null) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fn == null) |
|
|
|
if (fn == null) |
|
|
@ -380,6 +352,13 @@ namespace Fungus |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
|
|
|
/// Load and run a string containing Lua script. May be run as a coroutine. |
|
|
|
|
|
|
|
/// <param name="luaString">The Lua code to be run.</param> |
|
|
|
|
|
|
|
/// <param name="friendlyName">A descriptive name to be used in error reports.</param> |
|
|
|
|
|
|
|
/// <param name="runAsCoroutine">Run the Lua code as a coroutine to support asynchronous operations.</param> |
|
|
|
|
|
|
|
/// <param name="onComplete">Method to callback when the Lua code finishes exection. Supports return parameters.</param> |
|
|
|
|
|
|
|
/// </summary> |
|
|
|
public virtual void DoLuaString(string luaString, string friendlyName, bool runAsCoroutine, Action<DynValue> onComplete = null) |
|
|
|
public virtual void DoLuaString(string luaString, string friendlyName, bool runAsCoroutine, Action<DynValue> onComplete = null) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Closure fn = LoadLuaFunction(luaString, friendlyName); |
|
|
|
Closure fn = LoadLuaFunction(luaString, friendlyName); |
|
|
|