From a66c1a3f3d4fe275ad6ff467619294c395f4a004 Mon Sep 17 00:00:00 2001 From: chrisgregan Date: Tue, 5 Apr 2016 13:59:38 +0100 Subject: [PATCH] Improved how fungus lua module is initialized --- Assets/Fungus/Lua/Resources/Lua/fungus.txt | 9 ---- .../Lua/Resources/Types/RegisterTypes.txt | 1 + .../Fungus/Lua/Scripts/Commands/ExecuteLua.cs | 14 +----- .../Lua/Scripts/Editor/LuaScriptEditor.cs | 3 -- Assets/Fungus/Lua/Scripts/LuaEnvironment.cs | 6 +-- Assets/Fungus/Lua/Scripts/LuaScript.cs | 22 ++++---- Assets/Fungus/Lua/Scripts/LuaStore.cs | 4 +- Assets/Fungus/Lua/Scripts/LuaUtils.cs | 50 +++++++++++++++---- Assets/Tests/Lua/FungusTests.unity | 36 +++---------- Assets/Tests/Lua/LuaEnvironmentTests.unity | 19 ++----- 10 files changed, 68 insertions(+), 96 deletions(-) diff --git a/Assets/Fungus/Lua/Resources/Lua/fungus.txt b/Assets/Fungus/Lua/Resources/Lua/fungus.txt index 3a54d438..4e730709 100644 --- a/Assets/Fungus/Lua/Resources/Lua/fungus.txt +++ b/Assets/Fungus/Lua/Resources/Lua/fungus.txt @@ -3,15 +3,6 @@ local inspect = require('inspect') -- Utility functions for working with Lua in Fungus local M = {} --- Merge everything in the temp _fungus table into this module -local function mergefungustable() - for k,v in pairs(_fungus) do - M[k] = v - end - _fungus = nil -end -mergefungustable() - ------------ -- Debugging ------------ diff --git a/Assets/Fungus/Lua/Resources/Types/RegisterTypes.txt b/Assets/Fungus/Lua/Resources/Types/RegisterTypes.txt index 26b49036..1478c827 100644 --- a/Assets/Fungus/Lua/Resources/Types/RegisterTypes.txt +++ b/Assets/Fungus/Lua/Resources/Types/RegisterTypes.txt @@ -26,6 +26,7 @@ Fungus.Label Fungus.MaterialVariable Fungus.MenuDialog Fungus.ObjectVariable +Fungus.PODTypeFactory Fungus.PortraitState Fungus.SayDialog Fungus.SpriteVariable diff --git a/Assets/Fungus/Lua/Scripts/Commands/ExecuteLua.cs b/Assets/Fungus/Lua/Scripts/Commands/ExecuteLua.cs index 8cda5a53..3e1c447c 100644 --- a/Assets/Fungus/Lua/Scripts/Commands/ExecuteLua.cs +++ b/Assets/Fungus/Lua/Scripts/Commands/ExecuteLua.cs @@ -18,12 +18,6 @@ namespace Fungus [Tooltip("Lua script to execute. Use {$VarName} to insert a Flowchart variable in the Lua script.")] public string luaScript; - /// - /// Require the fungus Lua module at the start of the script. Equivalent to 'local fungus = require('fungus') - /// - [Tooltip("Require the fungus Lua module at the start of the script. Equivalent to 'local fungus = require('fungus')")] - public bool useFungusModule = true; - [Tooltip("Execute this Lua script as a Lua coroutine")] public bool runAsCoroutine = true; @@ -63,13 +57,7 @@ namespace Fungus return; } - string s = ""; - if (useFungusModule) - { - s = "fungus = require('fungus')\n"; - } - - string subbed = s + GetFlowchart().SubstituteVariables(luaScript); + string subbed = GetFlowchart().SubstituteVariables(luaScript); luaEnvironment.DoLuaString(subbed, friendlyName, runAsCoroutine, (returnValue) => { StoreReturnVariable(returnValue); diff --git a/Assets/Fungus/Lua/Scripts/Editor/LuaScriptEditor.cs b/Assets/Fungus/Lua/Scripts/Editor/LuaScriptEditor.cs index ab112e11..6423e4aa 100644 --- a/Assets/Fungus/Lua/Scripts/Editor/LuaScriptEditor.cs +++ b/Assets/Fungus/Lua/Scripts/Editor/LuaScriptEditor.cs @@ -28,7 +28,6 @@ namespace Fungus protected SerializedProperty runAsCoroutineProp; protected SerializedProperty luaFileProp; protected SerializedProperty luaScriptProp; - protected SerializedProperty useFungusModuleProp; protected List luaFiles = new List(); @@ -46,7 +45,6 @@ namespace Fungus runAsCoroutineProp = serializedObject.FindProperty("runAsCoroutine"); luaFileProp = serializedObject.FindProperty("luaFile"); luaScriptProp = serializedObject.FindProperty("luaScript"); - useFungusModuleProp = serializedObject.FindProperty("useFungusModule"); // Make a note of all Lua files in the project resources object[] result = Resources.LoadAll("Lua", typeof(TextAsset)); @@ -105,7 +103,6 @@ namespace Fungus EditorGUILayout.PropertyField(luaEnvironmentProp); EditorGUILayout.PropertyField(runAsCoroutineProp); - EditorGUILayout.PropertyField(useFungusModuleProp); int selected = 0; List options = new List(); diff --git a/Assets/Fungus/Lua/Scripts/LuaEnvironment.cs b/Assets/Fungus/Lua/Scripts/LuaEnvironment.cs index 2a12877c..185dc665 100644 --- a/Assets/Fungus/Lua/Scripts/LuaEnvironment.cs +++ b/Assets/Fungus/Lua/Scripts/LuaEnvironment.cs @@ -118,13 +118,13 @@ namespace Fungus protected virtual void Start() { - InitInterpreter(); + InitEnvironment(); } /// /// Initialise the Lua interpreter so we can start running Lua code. /// - public virtual void InitInterpreter() + public virtual void InitEnvironment() { if (initialised) { @@ -212,7 +212,7 @@ namespace Fungus /// public void DoLuaString(string luaString, string friendlyName, bool runAsCoroutine, Action onComplete = null) { - InitInterpreter(); + InitEnvironment(); // Load the Lua script DynValue res = null; diff --git a/Assets/Fungus/Lua/Scripts/LuaScript.cs b/Assets/Fungus/Lua/Scripts/LuaScript.cs index 5c69ab3d..2d739878 100644 --- a/Assets/Fungus/Lua/Scripts/LuaScript.cs +++ b/Assets/Fungus/Lua/Scripts/LuaScript.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using UnityEngine; +using MoonSharp.Interpreter; using Debug = UnityEngine.Debug; using Object = UnityEngine.Object; @@ -81,12 +82,6 @@ namespace Fungus [Tooltip("Run the script as a Lua coroutine so execution can be yielded for asynchronous operations.")] public bool runAsCoroutine = true; - /// - /// Require the fungus Lua module at the start of the script. Equivalent to 'local fungus = require('fungus') - /// - [Tooltip("Require the fungus Lua module at the start of the script. Equivalent to 'local fungus = require('fungus')")] - public bool useFungusModule = true; - private int m_ExecuteOnFrame; protected string friendlyName = ""; @@ -114,6 +109,9 @@ namespace Fungus Debug.LogError("No Lua Environment found"); return; } + + // Ensure the LuaEnvironment is initialized before trying to execute code + luaEnvironment.InitEnvironment(); // Cache a descriptive name to use in Lua error messages friendlyName = GetPath(transform) + ".LuaScript"; @@ -297,19 +295,17 @@ namespace Fungus } else { + // Ensure the Lua Environment is initialised first. + luaEnvironment.InitEnvironment(); + string s = ""; - if (useFungusModule) - { - s = "fungus = require('fungus')\n"; - } - if (luaFile != null) { - s += luaFile.text; + s = luaFile.text; } else if (luaScript.Length > 0) { - s += luaScript; + s = luaScript; } luaEnvironment.DoLuaString(s, friendlyName, runAsCoroutine); diff --git a/Assets/Fungus/Lua/Scripts/LuaStore.cs b/Assets/Fungus/Lua/Scripts/LuaStore.cs index b0572a48..a538d342 100644 --- a/Assets/Fungus/Lua/Scripts/LuaStore.cs +++ b/Assets/Fungus/Lua/Scripts/LuaStore.cs @@ -82,10 +82,10 @@ namespace Fungus return; } - Table fungusTable = globals.Get("_fungus").Table; + Table fungusTable = globals.Get("fungus").Table; if (fungusTable == null) { - Debug.LogError("_fungus table not found"); + Debug.LogError("fungus table not found"); return; } diff --git a/Assets/Fungus/Lua/Scripts/LuaUtils.cs b/Assets/Fungus/Lua/Scripts/LuaUtils.cs index 62ced355..fb64e81a 100644 --- a/Assets/Fungus/Lua/Scripts/LuaUtils.cs +++ b/Assets/Fungus/Lua/Scripts/LuaUtils.cs @@ -15,6 +15,13 @@ namespace Fungus public class LuaUtils : LuaEnvironment.Initializer, StringSubstituter.ISubstitutionHandler { + /// + /// Create an instance of the 'fungus' utility Lua module. + /// This module provides useful utilities that can be accessed via the 'fungus' global table. + /// + [Tooltip("Create an instance of the 'fungus' utility Lua module.")] + public bool useFungusModule = true; + /// /// Lua script file which defines the global string table used for localisation. /// @@ -78,7 +85,7 @@ namespace Fungus } InitTypes(); - InitCustomObjects(); + InitFungusModule(); InitBindings(); InitStringTable(); } @@ -130,21 +137,33 @@ namespace Fungus /// To register more class objects externally to this class, register them in the Awake method of any /// monobehavior in your scene. /// - protected virtual void InitCustomObjects() + protected virtual void InitFungusModule() { - MoonSharp.Interpreter.Script interpreter = luaEnvironment.Interpreter; + if (!useFungusModule) + { + return; + } - // Add the CLR class objects to a temp unity table called _fungus. - // When the fungus module is required, all the entries from _fungus are copied over. + MoonSharp.Interpreter.Script interpreter = luaEnvironment.Interpreter; - Table fungusTable = new Table(interpreter); - interpreter.Globals["_fungus"] = fungusTable; + // Require the Fungus module and assign it to the global 'fungus' + Table fungusTable = null; + MoonSharp.Interpreter.DynValue value = interpreter.RequireModule("fungus"); + if (value != null && + value.Type == DataType.Function) + { + fungusTable = value.Function.Call().Table; + } + if (fungusTable == null) + { + UnityEngine.Debug.LogError("Failed to create Fungus table"); + return; + } + interpreter.Globals["fungus"] = fungusTable; // Static classes fungusTable["time"] = UserData.CreateStatic(typeof(Time)); fungusTable["prefs"] = UserData.CreateStatic(typeof(FungusPrefs)); - - UserData.RegisterType(typeof(PODTypeFactory)); fungusTable["factory"] = UserData.CreateStatic(typeof(PODTypeFactory)); // Lua Environment and Lua Utils components @@ -179,7 +198,7 @@ namespace Fungus if (stringTableRes.Type == DataType.Table) { stringTableCached = stringTableRes.Table; - Table fungusTable = interpreter.Globals.Get("_fungus").Table; + Table fungusTable = interpreter.Globals.Get("fungus").Table; if (fungusTable != null) { fungusTable["stringtable"] = stringTableCached; @@ -230,8 +249,19 @@ namespace Fungus [MoonSharpHidden] public virtual string SubstituteStrings(string input) { + // 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) { + luaEnvironment = GetComponent(); + if (luaEnvironment != null) + { + luaEnvironment.InitEnvironment(); + } + } + + if (luaEnvironment == null) + { UnityEngine.Debug.LogError("No Lua Environment found"); return input; } diff --git a/Assets/Tests/Lua/FungusTests.unity b/Assets/Tests/Lua/FungusTests.unity index a2fe6d10..b7ed76e0 100644 --- a/Assets/Tests/Lua/FungusTests.unity +++ b/Assets/Tests/Lua/FungusTests.unity @@ -822,7 +822,6 @@ MonoBehaviour: fungus.pass()' - useFungusModule: 1 runAsCoroutine: 1 waitUntilFinished: 1 returnVariable: {fileID: 0} @@ -880,7 +879,7 @@ MonoBehaviour: variablesScrollPos: {x: 0, y: 0} variablesExpanded: 1 blockViewHeight: 400 - zoom: 0.8889934 + zoom: 0.9199953 scrollViewRect: serializedVersion: 2 x: -343 @@ -1229,7 +1228,6 @@ MonoBehaviour: fungus.pass()' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1001 &130678264 Prefab: m_ObjectHideFlags: 0 @@ -2275,6 +2273,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c10f0b861365b42b0928858f7b086ff3, type: 3} m_Name: m_EditorClassIdentifier: + useFungusModule: 1 stringTable: {fileID: 0} activeLanguage: en timeScale: -1 @@ -2751,7 +2750,6 @@ MonoBehaviour: fungus.pass()' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &465829169 GameObject: m_ObjectHideFlags: 0 @@ -3070,7 +3068,6 @@ MonoBehaviour: 1\", option1)\n\nfungus.assert(optionbutton0.activeSelf)\nfungus.clearmenu()\nfungus.assert(not optionbutton0.activeSelf)\n\nfungus.pass()" runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &511430244 GameObject: m_ObjectHideFlags: 0 @@ -3127,7 +3124,6 @@ MonoBehaviour: menu option with a timer\nfungus.menu(\"Option 1\", option1)\nfungus.menutimer(1, timeout)\n" runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &560555132 GameObject: m_ObjectHideFlags: 0 @@ -3290,7 +3286,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 25fb867d2049d41f597aefdd6b19f598, type: 3} m_Name: m_EditorClassIdentifier: - nameText: John [$score] + nameText: John {$score} nameColor: {r: 0.034482718, g: 1, b: 0, a: 1} soundEffect: {fileID: 0} profileSprite: {fileID: 21300000, guid: ea8f56c43254d41728f5ac4e8299b6c9, type: 3} @@ -4409,7 +4405,6 @@ MonoBehaviour: go = fungus.luautils.find(\"OptionButton0\")\nfungus.assert(go != nil)\n\nlocal button = go.GetComponent(\"Button\")\nfungus.assert(button != nil)\n\nbutton.onClick.Invoke()" runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &851680338 GameObject: m_ObjectHideFlags: 0 @@ -4554,7 +4549,6 @@ MonoBehaviour: fungus.pass()' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &863130402 GameObject: m_ObjectHideFlags: 0 @@ -5343,7 +5337,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return true - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227029} @@ -5460,7 +5453,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return 1.0 - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227035} @@ -5480,7 +5472,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return 2 - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227034} @@ -5500,7 +5491,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return "a string" - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227033} @@ -5579,7 +5569,6 @@ MonoBehaviour: return c' - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227037} @@ -5599,7 +5588,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return testgameobject - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227040} @@ -5647,7 +5635,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return testmaterial - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227042} @@ -5681,7 +5668,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return testgameobject - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227044} @@ -5715,7 +5701,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return mushroom - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227046} @@ -5752,7 +5737,6 @@ MonoBehaviour: return v' - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227050} @@ -5786,7 +5770,6 @@ MonoBehaviour: indentLevel: 0 luaEnvironment: {fileID: 0} luaScript: return mousepointer - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227048} @@ -5822,7 +5805,6 @@ MonoBehaviour: luaScript: 'local v = fungus.factory.vector3(1,1,1) return v' - useFungusModule: 1 runAsCoroutine: 0 waitUntilFinished: 1 returnVariable: {fileID: 942227052} @@ -6449,7 +6431,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!114 &1109996700 MonoBehaviour: m_ObjectHideFlags: 0 @@ -7630,7 +7612,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!114 &1641285457 MonoBehaviour: m_ObjectHideFlags: 0 @@ -7819,7 +7801,6 @@ MonoBehaviour: \ fungus.pass()\nend\n\n-- Display a menu option with a timer\nfungus.menu(\"Option 1\", option1)\n\noptionbutton0.onClick.Invoke()\n" runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &1667495163 GameObject: m_ObjectHideFlags: 0 @@ -8827,7 +8808,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 61dddfdc5e0e44ca298d8f46f7f5a915, type: 3} m_Name: m_EditorClassIdentifier: - selectedFlowchart: {fileID: 942227028} + selectedFlowchart: {fileID: 56584893} --- !u!4 &1791050794 Transform: m_ObjectHideFlags: 1 @@ -8912,7 +8893,7 @@ MonoBehaviour: -- Test say command with a tag and global variable substitution - fungus.say "Alrighty{w=1} how do [$score]?" + fungus.say "Alrighty{w=1} how do {$score}?" fungus.assert(nametext.text == "John 10") @@ -8924,7 +8905,6 @@ MonoBehaviour: ' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &1880266302 GameObject: m_ObjectHideFlags: 0 @@ -9583,7 +9563,6 @@ MonoBehaviour: fungus.pass()' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &2087053783 GameObject: m_ObjectHideFlags: 0 @@ -9903,7 +9882,6 @@ MonoBehaviour: luaFile: {fileID: 0} luaScript: runAsCoroutine: 1 - useFungusModule: 1 --- !u!1001 &2092185197 Prefab: m_ObjectHideFlags: 0 diff --git a/Assets/Tests/Lua/LuaEnvironmentTests.unity b/Assets/Tests/Lua/LuaEnvironmentTests.unity index 91e8d493..19c99b1a 100644 --- a/Assets/Tests/Lua/LuaEnvironmentTests.unity +++ b/Assets/Tests/Lua/LuaEnvironmentTests.unity @@ -242,7 +242,6 @@ MonoBehaviour: ' runAsCoroutine: 1 - useFungusModule: 1 --- !u!4 &236999594 stripped Transform: m_PrefabParentObject: {fileID: 495584, guid: 49031c561e16d4fcf91c12153f8e0b25, type: 2} @@ -415,7 +414,6 @@ MonoBehaviour: returns true\n-- If this doesn't work the test will timeout and fail\nvalue = true\nfungus.waitfor(fn, 1)\n\nfungus.pass()" runAsCoroutine: 1 - useFungusModule: 1 --- !u!1001 &364012152 Prefab: m_ObjectHideFlags: 0 @@ -556,6 +554,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c10f0b861365b42b0928858f7b086ff3, type: 3} m_Name: m_EditorClassIdentifier: + useFungusModule: 1 stringTable: {fileID: 0} activeLanguage: en timeScale: -1 @@ -736,7 +735,6 @@ MonoBehaviour: ' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &715881501 GameObject: m_ObjectHideFlags: 0 @@ -1001,7 +999,6 @@ MonoBehaviour: fungus.pass()' runAsCoroutine: 1 - useFungusModule: 1 --- !u!4 &1167396341 stripped Transform: m_PrefabParentObject: {fileID: 495584, guid: 49031c561e16d4fcf91c12153f8e0b25, type: 2} @@ -1158,7 +1155,6 @@ MonoBehaviour: f.pass()' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &1394431693 GameObject: m_ObjectHideFlags: 0 @@ -1286,6 +1282,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c10f0b861365b42b0928858f7b086ff3, type: 3} m_Name: m_EditorClassIdentifier: + useFungusModule: 1 stringTable: {fileID: 0} activeLanguage: en timeScale: -1 @@ -1622,8 +1619,6 @@ MonoBehaviour: luaFile: {fileID: 0} luaScript: '-- Test string table localisation system - print (fungus.stringtable) - fungus.assert(fungus.stringtable != nil) @@ -1645,14 +1640,14 @@ MonoBehaviour: t = 3 - local s = fungus.sub("should be [$t]") + local s = fungus.sub("should be {$t}") fungus.assert(s == "should be 3") -- Test substituting a string table value (en) - s = fungus.sub("say [$hello]") + s = fungus.sub("say {$hello}") fungus.assert(s == "say Hi there") @@ -1661,14 +1656,13 @@ MonoBehaviour: fungus.setlanguage("fr") - s = fungus.sub("say [$hello]") + s = fungus.sub("say {$hello}") fungus.assert(s == "say Bonjour") fungus.pass()' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &1818482578 GameObject: m_ObjectHideFlags: 0 @@ -1726,7 +1720,6 @@ MonoBehaviour: ' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &1828947831 GameObject: m_ObjectHideFlags: 0 @@ -1805,7 +1798,6 @@ MonoBehaviour: fungus.pass()' - useFungusModule: 1 runAsCoroutine: 1 waitUntilFinished: 1 returnVariable: {fileID: 0} @@ -2047,7 +2039,6 @@ MonoBehaviour: fungus.pass()' runAsCoroutine: 1 - useFungusModule: 1 --- !u!1 &1960220030 GameObject: m_ObjectHideFlags: 0