From 501cb34247e59c77fcbdaa4b679cf38ad1dc1f96 Mon Sep 17 00:00:00 2001 From: Christopher Date: Mon, 12 Sep 2016 10:11:27 +0100 Subject: [PATCH] Refactored LuaEnvironment to use ILuaEnvironment interface --- Assets/Fungus/Flowchart/Scripts/Flowchart.cs | 2 +- .../Fungus/Lua/Scripts/Commands/ExecuteLua.cs | 13 +- Assets/Fungus/Lua/Scripts/LuaExtensions.cs | 8 +- .../FungusLua/Scripts/ILuaEnvironment.cs | 44 +++ .../FungusLua/Scripts/ILuaEnvironment.cs.meta | 12 + .../FungusLua/Scripts/LuaBindings.cs | 9 +- .../FungusLua/Scripts/LuaEnvironment.cs | 265 ++++++++---------- .../Thirdparty/FungusLua/Scripts/LuaScript.cs | 21 +- .../Thirdparty/FungusLua/Scripts/LuaStore.cs | 4 +- .../Thirdparty/FungusLua/Scripts/LuaUtils.cs | 32 +-- 10 files changed, 227 insertions(+), 183 deletions(-) create mode 100644 Assets/Fungus/Thirdparty/FungusLua/Scripts/ILuaEnvironment.cs create mode 100644 Assets/Fungus/Thirdparty/FungusLua/Scripts/ILuaEnvironment.cs.meta 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 /// [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; } } /// /// 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 /// /// Extension for MenuDialog that allows AddOption to call a Lua function when an option is selected. /// - 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 /// /// Extension for MenuDialog that allows ShowTimer to call a Lua function when the timer expires. /// - 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 +{ + /// + /// Wrapper for a MoonSharp Lua Script instance. + /// + public interface ILuaEnvironment + { + /// + /// Initialise the Lua interpreter so we can start running Lua code. + /// + void InitEnvironment(); + + /// + /// The MoonSharp interpreter instance used to run Lua code. + /// + Script Interpreter { get; } + + /// + /// Loads and compiles a string containing Lua script, returning a closure (Lua function) which can be executed later. + /// The Lua code to be run. + /// A descriptive name to be used in error reports. + /// + Closure LoadLuaFunction(string luaString, string friendlyName); + + /// + /// Load and run a previously compiled Lua script. May be run as a coroutine. + /// A previously compiled Lua function. + /// Run the Lua code as a coroutine to support asynchronous operations. + /// Method to callback when the Lua code finishes exection. Supports return parameters. + /// + void RunLuaFunction(Closure fn, bool runAsCoroutine, System.Action onComplete = null); + + /// + /// Load and run a string containing Lua script. May be run as a coroutine. + /// The Lua code to be run. + /// A descriptive name to be used in error reports. + /// Run the Lua code as a coroutine to support asynchronous operations. + /// Method to callback when the Lua code finishes exection. Supports return parameters. + /// + void DoLuaString(string luaString, string friendlyName, bool runAsCoroutine, System.Action 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 /// /// Add all declared bindings to the globals table. /// - public abstract void AddBindings(LuaEnvironment luaEnvironment); + public abstract void AddBindings(ILuaEnvironment luaEnv); } /// @@ -43,6 +43,7 @@ namespace Fungus [Tooltip("The specific LuaEnvironment to register the bindings in.")] [SerializeField] protected LuaEnvironment luaEnvironment; + public ILuaEnvironment LuaEnv { get; set; } /// /// 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 /// /// Add all declared bindings to the globals table. /// - 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 /// /// Wrapper for a MoonSharp Lua Script instance. /// - public class LuaEnvironment : MonoBehaviour + public class LuaEnvironment : MonoBehaviour, ILuaEnvironment { /// /// 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. /// - public static LuaEnvironment GetLua() + public static ILuaEnvironment GetLua() { - LuaEnvironment luaEnvironment = GameObject.FindObjectOfType(); - if (luaEnvironment == null) + ILuaEnvironment luaEnv = GameObject.FindObjectOfType(); + if (luaEnv == null) { GameObject prefab = Resources.Load("Prefabs/LuaEnvironment"); if (prefab != null) { GameObject go = Instantiate(prefab) as GameObject; go.name = "LuaEnvironment"; - luaEnvironment = go.GetComponent(); + luaEnv = go.GetComponent(); } } - return luaEnvironment; + return luaEnv; } protected Script interpreter; - /// - /// The MoonSharp interpreter instance used to run Lua code. - /// - public virtual Script Interpreter { get { return interpreter; } } - /// /// Launches the remote Lua debugger in your browser and breaks execution at the first executed Lua command. /// @@ -130,40 +124,6 @@ namespace Fungus InitEnvironment(); } - /// - /// Initialise the Lua interpreter so we can start running Lua code. - /// - 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(); - foreach (Initializer initializer in initializers) - { - initializer.Initialize(); - } - - if (remoteDebugger) - { - ActivateRemoteDebugger(interpreter); - } - - initialised = true; - } - /// /// Register all Lua files in the project so they can be accessed at runtime. /// @@ -211,102 +171,6 @@ namespace Fungus } } - /// - /// Loads and compiles a string containing Lua script, returning a closure (Lua function) which can be executed later. - /// The Lua code to be run. - /// A descriptive name to be used in error reports. - /// - public virtual Closure LoadLuaString(string luaString, string friendlyName) - { - InitEnvironment(); - - string processedString; - Initializer initializer = GetComponent(); - 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; - } - - /// - /// Load and run a previously compiled Lua script. May be run as a coroutine. - /// A previously compiled Lua function. - /// Run the Lua code as a coroutine to support asynchronous operations. - /// Method to callback when the Lua code finishes exection. Supports return parameters. - /// - public virtual void RunLuaFunction(Closure fn, bool runAsCoroutine, Action 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); - } - } - } - - /// - /// Load and run a string containing Lua script. May be run as a coroutine. - /// The Lua code to be run. - /// A descriptive name to be used in error reports. - /// Run the Lua code as a coroutine to support asynchronous operations. - /// Method to callback when the Lua code finishes exection. Supports return parameters. - /// - public virtual void DoLuaString(string luaString, string friendlyName, bool runAsCoroutine, Action onComplete = null) - { - Closure fn = LoadLuaString(luaString, friendlyName); - RunLuaFunction(fn, runAsCoroutine, onComplete); - } - /// /// A Unity coroutine method which updates a Lua coroutine each frame. /// A MoonSharp closure object representing a function. @@ -406,7 +270,7 @@ namespace Fungus /// /// Decorated message from a MoonSharp exception /// Debug info, usually the Lua script that was running. - 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(); + 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(); + 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 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 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 /// [Tooltip("The Lua Environment to use when executing Lua script.")] [SerializeField] protected LuaEnvironment luaEnvironment; + protected ILuaEnvironment LuaEnv { get; set; } /// /// 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 /// /// Callback to bind this LuaStore component with the "unity" table in a LuaEnvironment component. /// - 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 /// /// Cached reference to the Lua Environment component. /// - protected LuaEnvironment luaEnvironment; + protected ILuaEnvironment LuaEnv { get; set; } protected StringSubstituter stringSubstituter; @@ -76,16 +76,16 @@ namespace Fungus /// public override void Initialize() { - luaEnvironment = GetComponent(); - if (luaEnvironment == null) + LuaEnv = GetComponent(); + 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(); 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(); - if (luaEnvironment != null) + LuaEnv = GetComponent(); + 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("\\{\\$.*?\\}");