diff --git a/Assets/Fungus/Flowchart/Scripts/Flowchart.cs b/Assets/Fungus/Flowchart/Scripts/Flowchart.cs index 7c602897..370b5319 100644 --- a/Assets/Fungus/Flowchart/Scripts/Flowchart.cs +++ b/Assets/Fungus/Flowchart/Scripts/Flowchart.cs @@ -172,7 +172,7 @@ namespace Fungus /// </summary> [Tooltip("Lua Environment to be used by default for all Execute Lua commands in this Flowchart")] [SerializeField] protected LuaEnvironment luaEnvironment; - public virtual LuaEnvironment _LuaEnvironment { get { return luaEnvironment; } } + public virtual ILuaEnvironment LuaEnv { get { return luaEnvironment; } } /// <summary> /// The ExecuteLua command adds a global Lua variable with this name bound to the flowchart prior to executing. diff --git a/Assets/Fungus/Lua/Scripts/Commands/ExecuteLua.cs b/Assets/Fungus/Lua/Scripts/Commands/ExecuteLua.cs index 2807d3fe..ef0e3e93 100644 --- a/Assets/Fungus/Lua/Scripts/Commands/ExecuteLua.cs +++ b/Assets/Fungus/Lua/Scripts/Commands/ExecuteLua.cs @@ -17,6 +17,7 @@ namespace Fungus { [Tooltip("Lua Environment to use to execute this Lua script")] [SerializeField] protected LuaEnvironment luaEnvironment; + public ILuaEnvironment LuaEnv { set; get; } [Tooltip("A text file containing Lua script to execute.")] [SerializeField] protected TextAsset luaFile; @@ -65,22 +66,22 @@ namespace Fungus // See if a Lua Environment has been assigned to this Flowchart if (luaEnvironment == null) { - luaEnvironment = flowchart._LuaEnvironment; + LuaEnv = flowchart.LuaEnv; } // No Lua Environment specified so just use any available or create one. - if (luaEnvironment == null) + if (LuaEnv == null) { - luaEnvironment = LuaEnvironment.GetLua(); + LuaEnv = LuaEnvironment.GetLua(); } string s = GetLuaString(); - luaFunction = luaEnvironment.LoadLuaString(s, friendlyName); + luaFunction = LuaEnv.LoadLuaFunction(s, friendlyName); // Add a binding to the parent flowchart if (flowchart.LuaBindingName != "") { - Table globals = luaEnvironment.Interpreter.Globals; + Table globals = LuaEnv.Interpreter.Globals; if (globals != null) { globals[flowchart.LuaBindingName] = flowchart; @@ -115,7 +116,7 @@ namespace Fungus Continue(); } - luaEnvironment.RunLuaFunction(luaFunction, runAsCoroutine, (returnValue) => { + LuaEnv.RunLuaFunction(luaFunction, runAsCoroutine, (returnValue) => { StoreReturnVariable(returnValue); if (waitUntilFinished) { diff --git a/Assets/Fungus/Lua/Scripts/LuaExtensions.cs b/Assets/Fungus/Lua/Scripts/LuaExtensions.cs index 080208f7..61feba49 100644 --- a/Assets/Fungus/Lua/Scripts/LuaExtensions.cs +++ b/Assets/Fungus/Lua/Scripts/LuaExtensions.cs @@ -16,7 +16,7 @@ namespace Fungus /// <summary> /// Extension for MenuDialog that allows AddOption to call a Lua function when an option is selected. /// </summary> - public static bool AddOption(this MenuDialog menuDialog, string text, bool interactable, LuaEnvironment luaEnvironment, Closure callBack) + public static bool AddOption(this MenuDialog menuDialog, string text, bool interactable, ILuaEnvironment luaEnv, Closure callBack) { if (!menuDialog.gameObject.activeSelf) { @@ -46,7 +46,7 @@ namespace Fungus if (callBack != null) { - luaEnvironment.RunLuaFunction(callBack, true); + luaEnv.RunLuaFunction(callBack, true); } }); @@ -61,7 +61,7 @@ namespace Fungus /// <summary> /// Extension for MenuDialog that allows ShowTimer to call a Lua function when the timer expires. /// </summary> - public static IEnumerator ShowTimer(this MenuDialog menuDialog, float duration, LuaEnvironment luaEnvironment, Closure callBack) + public static IEnumerator ShowTimer(this MenuDialog menuDialog, float duration, ILuaEnvironment luaEnv, Closure callBack) { if (menuDialog.CachedSlider == null || duration <= 0f) @@ -94,7 +94,7 @@ namespace Fungus if (callBack != null) { - luaEnvironment.RunLuaFunction(callBack, true); + luaEnv.RunLuaFunction(callBack, true); } } } diff --git a/Assets/Fungus/Thirdparty/FungusLua/Scripts/ILuaEnvironment.cs b/Assets/Fungus/Thirdparty/FungusLua/Scripts/ILuaEnvironment.cs new file mode 100644 index 00000000..bfe8596e --- /dev/null +++ b/Assets/Fungus/Thirdparty/FungusLua/Scripts/ILuaEnvironment.cs @@ -0,0 +1,44 @@ +using MoonSharp.Interpreter; + +namespace Fungus +{ + /// <summary> + /// Wrapper for a MoonSharp Lua Script instance. + /// </summary> + public interface ILuaEnvironment + { + /// <summary> + /// Initialise the Lua interpreter so we can start running Lua code. + /// </summary> + void InitEnvironment(); + + /// <summary> + /// The MoonSharp interpreter instance used to run Lua code. + /// </summary> + Script Interpreter { get; } + + /// <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> + Closure LoadLuaFunction(string luaString, string friendlyName); + + /// <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> + void RunLuaFunction(Closure fn, bool runAsCoroutine, System.Action<DynValue> onComplete = null); + + /// <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> + void DoLuaString(string luaString, string friendlyName, bool runAsCoroutine, System.Action<DynValue> onComplete = null); + } +} \ No newline at end of file diff --git a/Assets/Fungus/Thirdparty/FungusLua/Scripts/ILuaEnvironment.cs.meta b/Assets/Fungus/Thirdparty/FungusLua/Scripts/ILuaEnvironment.cs.meta new file mode 100644 index 00000000..63099625 --- /dev/null +++ b/Assets/Fungus/Thirdparty/FungusLua/Scripts/ILuaEnvironment.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 73324073029d844479927d75293a9c38 +timeCreated: 1473436184 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaBindings.cs b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaBindings.cs index 7ac82803..c809a3f9 100644 --- a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaBindings.cs +++ b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaBindings.cs @@ -18,7 +18,7 @@ namespace Fungus /// <summary> /// Add all declared bindings to the globals table. /// </summary> - public abstract void AddBindings(LuaEnvironment luaEnvironment); + public abstract void AddBindings(ILuaEnvironment luaEnv); } /// <summary> @@ -43,6 +43,7 @@ namespace Fungus [Tooltip("The specific LuaEnvironment to register the bindings in.")] [SerializeField] protected LuaEnvironment luaEnvironment; + public ILuaEnvironment LuaEnv { get; set; } /// <summary> /// Name of global table variable to store bindings in. If left blank then each binding will be added as a global variable. @@ -81,16 +82,16 @@ namespace Fungus /// <summary> /// Add all declared bindings to the globals table. /// </summary> - public override void AddBindings(LuaEnvironment _luaEnvironment) + public override void AddBindings(ILuaEnvironment luaEnv) { if (!allEnvironments && - luaEnvironment != _luaEnvironment) + !luaEnvironment.Equals(luaEnv)) { // Don't add bindings to this environment return; } - MoonSharp.Interpreter.Script interpreter = _luaEnvironment.Interpreter; + MoonSharp.Interpreter.Script interpreter = luaEnv.Interpreter; Table globals = interpreter.Globals; Table bindingsTable = null; diff --git a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaEnvironment.cs b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaEnvironment.cs index 13af721d..b6e02a41 100644 --- a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaEnvironment.cs +++ b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaEnvironment.cs @@ -6,7 +6,6 @@ using System.Collections; using System.Collections.Generic; using System; using System.Linq; -using System.Diagnostics; using MoonSharp.Interpreter; using MoonSharp.Interpreter.Loaders; using MoonSharp.RemoteDebugger; @@ -16,7 +15,7 @@ namespace Fungus /// <summary> /// Wrapper for a MoonSharp Lua Script instance. /// </summary> - public class LuaEnvironment : MonoBehaviour + public class LuaEnvironment : MonoBehaviour, ILuaEnvironment { /// <summary> /// Helper class used to extend the initialization behavior of LuaEnvironment. @@ -86,29 +85,24 @@ namespace Fungus /// 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() + public static ILuaEnvironment GetLua() { - LuaEnvironment luaEnvironment = GameObject.FindObjectOfType<LuaEnvironment>(); - if (luaEnvironment == null) + 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"; - luaEnvironment = go.GetComponent<LuaEnvironment>(); + luaEnv = go.GetComponent<ILuaEnvironment>(); } } - return luaEnvironment; + return luaEnv; } protected Script interpreter; - /// <summary> - /// The MoonSharp interpreter instance used to run Lua code. - /// </summary> - public virtual Script Interpreter { get { return interpreter; } } - /// <summary> /// Launches the remote Lua debugger in your browser and breaks execution at the first executed Lua command. /// </summary> @@ -130,40 +124,6 @@ namespace Fungus InitEnvironment(); } - /// <summary> - /// Initialise the Lua interpreter so we can start running Lua code. - /// </summary> - public virtual void InitEnvironment() - { - if (initialised) - { - return; - } - - Script.DefaultOptions.DebugPrint = (s) => { UnityEngine.Debug.Log(s); }; - - // In some use cases (e.g. downloadable Lua files) some Lua modules can pose a potential security risk. - // You can restrict which core lua modules are available here if needed. See the MoonSharp documentation for details. - interpreter = new Script(CoreModules.Preset_Complete); - - // Load all Lua scripts in the project - InitLuaScriptFiles(); - - // Initialize any attached initializer components (e.g. LuaUtils) - Initializer[] initializers = GetComponents<Initializer>(); - foreach (Initializer initializer in initializers) - { - initializer.Initialize(); - } - - if (remoteDebugger) - { - ActivateRemoteDebugger(interpreter); - } - - initialised = true; - } - /// <summary> /// Register all Lua files in the project so they can be accessed at runtime. /// </summary> @@ -211,102 +171,6 @@ namespace Fungus } } - /// <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 LoadLuaString(string luaString, string friendlyName) - { - InitEnvironment(); - - string processedString; - Initializer initializer = GetComponent<Initializer>(); - if (initializer != null) - { - processedString = initializer.PreprocessScript(luaString); - } - else - { - processedString = luaString; - } - - // Load the Lua script - DynValue res = null; - try - { - res = interpreter.LoadString(processedString, null, friendlyName); - } - catch (InterpreterException ex) - { - LogException(ex.DecoratedMessage, luaString); - } - - if (res == null || - res.Type != DataType.Function) - { - UnityEngine.Debug.LogError("Failed to create Lua function from Lua string"); - return null; - } - - 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) - { - if (fn == null) - { - if (onComplete != null) - { - onComplete(null); - } - - return; - } - - // Execute the Lua script - if (runAsCoroutine) - { - StartCoroutine(RunLuaCoroutine(fn, onComplete)); - } - else - { - DynValue returnValue = null; - try - { - returnValue = fn.Call(); - } - catch (InterpreterException ex) - { - LogException(ex.DecoratedMessage, GetSourceCode()); - } - - if (onComplete != null) - { - onComplete(returnValue); - } - } - } - - /// <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) - { - Closure fn = LoadLuaString(luaString, friendlyName); - RunLuaFunction(fn, runAsCoroutine, onComplete); - } - /// <summary> /// A Unity coroutine method which updates a Lua coroutine each frame. /// <param name="closure">A MoonSharp closure object representing a function.</param> @@ -406,7 +270,7 @@ namespace Fungus /// </summary> /// <param name="decoratedMessage">Decorated message from a MoonSharp exception</param> /// <param name="debugInfo">Debug info, usually the Lua script that was running.</param> - public static void LogException(string decoratedMessage, string debugInfo) + protected static void LogException(string decoratedMessage, string debugInfo) { string output = decoratedMessage + "\n"; @@ -423,5 +287,120 @@ namespace Fungus UnityEngine.Debug.LogError(output); } + + #region ILuaEnvironment implementation + + public virtual void InitEnvironment() + { + if (initialised) + { + return; + } + + Script.DefaultOptions.DebugPrint = (s) => { UnityEngine.Debug.Log(s); }; + + // In some use cases (e.g. downloadable Lua files) some Lua modules can pose a potential security risk. + // You can restrict which core lua modules are available here if needed. See the MoonSharp documentation for details. + interpreter = new Script(CoreModules.Preset_Complete); + + // Load all Lua scripts in the project + InitLuaScriptFiles(); + + // Initialize any attached initializer components (e.g. LuaUtils) + Initializer[] initializers = GetComponents<Initializer>(); + foreach (Initializer initializer in initializers) + { + initializer.Initialize(); + } + + if (remoteDebugger) + { + ActivateRemoteDebugger(interpreter); + } + + initialised = true; + } + + public virtual Script Interpreter { get { return interpreter; } } + + public virtual Closure LoadLuaFunction(string luaString, string friendlyName) + { + InitEnvironment(); + + string processedString; + Initializer initializer = GetComponent<Initializer>(); + if (initializer != null) + { + processedString = initializer.PreprocessScript(luaString); + } + else + { + processedString = luaString; + } + + // Load the Lua script + DynValue res = null; + try + { + res = interpreter.LoadString(processedString, null, friendlyName); + } + catch (InterpreterException ex) + { + LogException(ex.DecoratedMessage, luaString); + } + + if (res == null || + res.Type != DataType.Function) + { + UnityEngine.Debug.LogError("Failed to create Lua function from Lua string"); + return null; + } + + return res.Function; + } + + public virtual void RunLuaFunction(Closure fn, bool runAsCoroutine, Action<DynValue> onComplete = null) + { + if (fn == null) + { + if (onComplete != null) + { + onComplete(null); + } + + return; + } + + // Execute the Lua script + if (runAsCoroutine) + { + StartCoroutine(RunLuaCoroutine(fn, onComplete)); + } + else + { + DynValue returnValue = null; + try + { + returnValue = fn.Call(); + } + catch (InterpreterException ex) + { + LogException(ex.DecoratedMessage, GetSourceCode()); + } + + if (onComplete != null) + { + onComplete(returnValue); + } + } + } + + public virtual void DoLuaString(string luaString, string friendlyName, bool runAsCoroutine, Action<DynValue> onComplete = null) + { + Closure fn = LoadLuaFunction(luaString, friendlyName); + RunLuaFunction(fn, runAsCoroutine, onComplete); + } + + #endregion } } \ No newline at end of file diff --git a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaScript.cs b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaScript.cs index a37cbb74..fa2ff7dd 100644 --- a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaScript.cs +++ b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaScript.cs @@ -21,6 +21,7 @@ namespace Fungus /// </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. @@ -76,26 +77,32 @@ namespace Fungus return; } - if (luaEnvironment == null) + if (LuaEnv == null && + luaEnvironment != null) + { + LuaEnv = luaEnvironment as ILuaEnvironment; + } + + if (LuaEnv == null) { // Create a Lua Environment if none exists yet - luaEnvironment = LuaEnvironment.GetLua(); + LuaEnv = LuaEnvironment.GetLua(); } - if (luaEnvironment == null) + if (LuaEnv == null) { Debug.LogError("No Lua Environment found"); return; } // Ensure the LuaEnvironment is initialized before trying to execute code - luaEnvironment.InitEnvironment(); + LuaEnv.InitEnvironment(); // Cache a descriptive name to use in Lua error messages friendlyName = GetPath(transform) + ".LuaScript"; string s = GetLuaString(); - luaFunction = luaEnvironment.LoadLuaString(s, friendlyName); + luaFunction = LuaEnv.LoadLuaFunction(s, friendlyName); initialised = true; } @@ -130,13 +137,13 @@ namespace Fungus // Make sure the script and Lua environment are initialised before executing InitLuaScript(); - if (luaEnvironment == null) + if (LuaEnv == null) { Debug.LogWarning("No Lua Environment found"); } else { - luaEnvironment.RunLuaFunction(luaFunction, runAsCoroutine); + LuaEnv.RunLuaFunction(luaFunction, runAsCoroutine); } } } diff --git a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaStore.cs b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaStore.cs index 21b1f59e..7a92855e 100644 --- a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaStore.cs +++ b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaStore.cs @@ -70,14 +70,14 @@ namespace Fungus /// <summary> /// Callback to bind this LuaStore component with the "unity" table in a LuaEnvironment component. /// </summary> - public override void AddBindings(LuaEnvironment luaEnvironment) + public override void AddBindings(ILuaEnvironment luaEnv) { if (!Init()) { return; } - MoonSharp.Interpreter.Script interpreter = luaEnvironment.Interpreter; + MoonSharp.Interpreter.Script interpreter = luaEnv.Interpreter; Table globals = interpreter.Globals; if (globals == null) diff --git a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaUtils.cs b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaUtils.cs index 49348aad..b63312c3 100644 --- a/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaUtils.cs +++ b/Assets/Fungus/Thirdparty/FungusLua/Scripts/LuaUtils.cs @@ -65,7 +65,7 @@ namespace Fungus /// <summary> /// Cached reference to the Lua Environment component. /// </summary> - protected LuaEnvironment luaEnvironment; + protected ILuaEnvironment LuaEnv { get; set; } protected StringSubstituter stringSubstituter; @@ -76,16 +76,16 @@ namespace Fungus /// </summary> public override void Initialize() { - luaEnvironment = GetComponent<LuaEnvironment>(); - if (luaEnvironment == null) + LuaEnv = GetComponent<ILuaEnvironment>(); + if (LuaEnv == null) { - UnityEngine.Debug.LogError("No Lua Environment found"); + Debug.LogError("No Lua Environment found"); return; } - if (luaEnvironment.Interpreter == null) + if (LuaEnv.Interpreter == null) { - UnityEngine.Debug.LogError("No Lua interpreter found"); + Debug.LogError("No Lua interpreter found"); return; } @@ -185,7 +185,7 @@ namespace Fungus LuaBindingsBase[] bindings = GameObject.FindObjectsOfType<LuaBindingsBase>(); foreach (LuaBindingsBase binding in bindings) { - binding.AddBindings(luaEnvironment); + binding.AddBindings(LuaEnv); } } @@ -201,7 +201,7 @@ namespace Fungus return; } - MoonSharp.Interpreter.Script interpreter = luaEnvironment.Interpreter; + MoonSharp.Interpreter.Script interpreter = LuaEnv.Interpreter; // Require the Fungus module and assign it to the global 'fungus' Table fungusTable = null; @@ -225,7 +225,7 @@ namespace Fungus fungusTable["factory"] = UserData.CreateStatic(typeof(PODTypeFactory)); // Lua Environment and Lua Utils components - fungusTable["luaenvironment"] = luaEnvironment; + fungusTable["luaenvironment"] = LuaEnv; fungusTable["luautils"] = this; // Provide access to the Unity Test Tools (if available). @@ -339,28 +339,28 @@ namespace Fungus { // This method could be called from the Start of another component, so // we need to ensure that the LuaEnvironment has been initialized. - if (luaEnvironment == null) + if (LuaEnv == null) { - luaEnvironment = GetComponent<LuaEnvironment>(); - if (luaEnvironment != null) + LuaEnv = GetComponent<ILuaEnvironment>(); + if (LuaEnv != null) { - luaEnvironment.InitEnvironment(); + LuaEnv.InitEnvironment(); } } - if (luaEnvironment == null) + if (LuaEnv == null) { UnityEngine.Debug.LogError("No Lua Environment found"); return false; } - if (luaEnvironment.Interpreter == null) + if (LuaEnv.Interpreter == null) { UnityEngine.Debug.LogError("No Lua interpreter found"); return false; } - MoonSharp.Interpreter.Script interpreter = luaEnvironment.Interpreter; + MoonSharp.Interpreter.Script interpreter = LuaEnv.Interpreter; // Instantiate the regular expression object. Regex r = new Regex("\\{\\$.*?\\}");