From a17cfe2aacdd7d91349349bfdc698b665a2fb72c Mon Sep 17 00:00:00 2001 From: Conrad Kreyling Date: Mon, 24 Apr 2017 20:00:24 -0400 Subject: [PATCH] break conditionals out to allow for reused code in LuaIf --- Assets/Fungus/Scripts/Commands/Condition.cs | 156 ++++++++++++++- Assets/Fungus/Scripts/Commands/ElseIf.cs | 49 +---- Assets/Fungus/Scripts/Commands/If.cs | 183 +----------------- .../Fungus/Scripts/Commands/LuaCondition.cs | 126 ++++++++++++ .../Scripts/Commands/LuaCondition.cs.meta | 12 ++ Assets/Fungus/Scripts/Commands/LuaElseIf.cs | 38 ++++ .../Fungus/Scripts/Commands/LuaElseIf.cs.meta | 12 ++ Assets/Fungus/Scripts/Commands/LuaIf.cs | 26 +++ Assets/Fungus/Scripts/Commands/LuaIf.cs.meta | 12 ++ .../Scripts/Commands/VariableCondition.cs | 110 +++++++++++ .../Commands/VariableCondition.cs.meta | 12 ++ 11 files changed, 504 insertions(+), 232 deletions(-) create mode 100644 Assets/Fungus/Scripts/Commands/LuaCondition.cs create mode 100644 Assets/Fungus/Scripts/Commands/LuaCondition.cs.meta create mode 100644 Assets/Fungus/Scripts/Commands/LuaElseIf.cs create mode 100644 Assets/Fungus/Scripts/Commands/LuaElseIf.cs.meta create mode 100644 Assets/Fungus/Scripts/Commands/LuaIf.cs create mode 100644 Assets/Fungus/Scripts/Commands/LuaIf.cs.meta create mode 100644 Assets/Fungus/Scripts/Commands/VariableCondition.cs create mode 100644 Assets/Fungus/Scripts/Commands/VariableCondition.cs.meta diff --git a/Assets/Fungus/Scripts/Commands/Condition.cs b/Assets/Fungus/Scripts/Commands/Condition.cs index d0c4e38f..a8dacb34 100644 --- a/Assets/Fungus/Scripts/Commands/Condition.cs +++ b/Assets/Fungus/Scripts/Commands/Condition.cs @@ -8,11 +8,6 @@ namespace Fungus [AddComponentMenu("")] public abstract class Condition : Command { - [Tooltip("The type of comparison to be performed")] - [SerializeField] protected CompareOperator compareOperator; - - #region Public members - public static string GetOperatorDescription(CompareOperator compareOperator) { string summary = ""; @@ -41,6 +36,157 @@ namespace Fungus return summary; } + #region Public members + + public override void OnEnter() + { + + if (ParentBlock == null) + { + return; + } + + if( !HasNeededProperties() ) + { + Continue(); + return; + } + + if( !this.IsElseIf ) + { + EvaluateAndContinue(); + } + else + { + System.Type previousCommandType = ParentBlock.GetPreviousActiveCommandType(); + + if (previousCommandType.IsSubclassOf(typeof(Condition))) + { + // Else If behaves the same as an If command + EvaluateAndContinue(); + } + else + { + // Else If behaves mostly like an Else command, + // but will also jump to a following Else command. + + // Stop if this is the last command in the list + if (CommandIndex >= ParentBlock.CommandList.Count - 1) + { + StopParentBlock(); + return; + } + + // Find the next End command at the same indent level as this Else If command + int indent = indentLevel; + for (int i = CommandIndex + 1; i < ParentBlock.CommandList.Count; ++i) + { + var command = ParentBlock.CommandList[i]; + + if (command.IndentLevel == indent) + { + System.Type type = command.GetType(); + if (type == typeof(End)) + { + // Execute command immediately after the Else or End command + Continue(command.CommandIndex + 1); + return; + } + } + } + + // No End command found + StopParentBlock(); + } + } + } + + public override bool OpenBlock() + { + return true; + } + #endregion + + protected virtual void EvaluateAndContinue() + { + if (EvaluateCondition()) + { + OnTrue(); + } + else + { + OnFalse(); + } + } + + protected virtual void OnTrue() + { + Continue(); + } + + protected virtual void OnFalse() + { + // Last command in block + if (CommandIndex >= ParentBlock.CommandList.Count) + { + StopParentBlock(); + return; + } + + // Find the next Else, ElseIf or End command at the same indent level as this If command + for (int i = CommandIndex + 1; i < ParentBlock.CommandList.Count; ++i) + { + Command nextCommand = ParentBlock.CommandList[i]; + + if (nextCommand == null) + { + continue; + } + + // Find next command at same indent level as this If command + // Skip disabled commands, comments & labels + if (!((Command)nextCommand).enabled || + nextCommand.GetType() == typeof(Comment) || + nextCommand.GetType() == typeof(Label) || + nextCommand.IndentLevel != indentLevel) + { + continue; + } + + System.Type type = nextCommand.GetType(); + if (type == typeof(Else) || + type == typeof(End)) + { + if (i >= ParentBlock.CommandList.Count - 1) + { + // Last command in Block, so stop + StopParentBlock(); + } + else + { + // Execute command immediately after the Else or End command + Continue(nextCommand.CommandIndex + 1); + return; + } + } + else if (type.IsSubclassOf(typeof(Condition)) && (nextCommand as Condition).IsElseIf) + { + // Execute the Else If command + Continue(i); + + return; + } + } + + // No matching End command found, so just stop the block + StopParentBlock(); + } + + protected abstract bool EvaluateCondition(); + + protected abstract bool HasNeededProperties(); + + protected virtual bool IsElseIf { get { return false; } } } } \ No newline at end of file diff --git a/Assets/Fungus/Scripts/Commands/ElseIf.cs b/Assets/Fungus/Scripts/Commands/ElseIf.cs index e6cabf71..eee6ab14 100644 --- a/Assets/Fungus/Scripts/Commands/ElseIf.cs +++ b/Assets/Fungus/Scripts/Commands/ElseIf.cs @@ -12,54 +12,11 @@ namespace Fungus "Else If", "Marks the start of a command block to be executed when the preceding If statement is False and the test expression is true.")] [AddComponentMenu("")] - public class ElseIf : If + public class ElseIf : VariableCondition { - #region Public members - - public override void OnEnter() - { - System.Type previousCommandType = ParentBlock.GetPreviousActiveCommandType(); - - if (previousCommandType == typeof(If) || - previousCommandType == typeof(ElseIf) ) - { - // Else If behaves the same as an If command - EvaluateAndContinue(); - } - else - { - // Else If behaves mostly like an Else command, - // but will also jump to a following Else command. - - // Stop if this is the last command in the list - if (CommandIndex >= ParentBlock.CommandList.Count - 1) - { - StopParentBlock(); - return; - } + protected override bool IsElseIf { get { return true; } } - // Find the next End command at the same indent level as this Else If command - int indent = indentLevel; - for (int i = CommandIndex + 1; i < ParentBlock.CommandList.Count; ++i) - { - var command = ParentBlock.CommandList[i]; - - if (command.IndentLevel == indent) - { - System.Type type = command.GetType(); - if (type == typeof(End)) - { - // Execute command immediately after the Else or End command - Continue(command.CommandIndex + 1); - return; - } - } - } - - // No End command found - StopParentBlock(); - } - } + #region Public members public override bool OpenBlock() { diff --git a/Assets/Fungus/Scripts/Commands/If.cs b/Assets/Fungus/Scripts/Commands/If.cs index 680c17f8..c8d15fb0 100644 --- a/Assets/Fungus/Scripts/Commands/If.cs +++ b/Assets/Fungus/Scripts/Commands/If.cs @@ -12,189 +12,10 @@ namespace Fungus "If", "If the test expression is true, execute the following command block.")] [AddComponentMenu("")] - public class If : Condition + public class If : VariableCondition { - [Tooltip("Variable to use in expression")] - [VariableProperty(typeof(BooleanVariable), - typeof(IntegerVariable), - typeof(FloatVariable), - typeof(StringVariable))] - [SerializeField] protected Variable variable; - - [Tooltip("Boolean value to compare against")] - [SerializeField] protected BooleanData booleanData; - - [Tooltip("Integer value to compare against")] - [SerializeField] protected IntegerData integerData; - - [Tooltip("Float value to compare against")] - [SerializeField] protected FloatData floatData; - - [Tooltip("String value to compare against")] - [SerializeField] protected StringDataMulti stringData; - - protected virtual void EvaluateAndContinue() - { - if (EvaluateCondition()) - { - OnTrue(); - } - else - { - OnFalse(); - } - } - - protected virtual void OnTrue() - { - Continue(); - } - - protected virtual void OnFalse() - { - // Last command in block - if (CommandIndex >= ParentBlock.CommandList.Count) - { - StopParentBlock(); - return; - } - - // Find the next Else, ElseIf or End command at the same indent level as this If command - for (int i = CommandIndex + 1; i < ParentBlock.CommandList.Count; ++i) - { - Command nextCommand = ParentBlock.CommandList[i]; - - if (nextCommand == null) - { - continue; - } - - // Find next command at same indent level as this If command - // Skip disabled commands, comments & labels - if (!((Command)nextCommand).enabled || - nextCommand.GetType() == typeof(Comment) || - nextCommand.GetType() == typeof(Label) || - nextCommand.IndentLevel != indentLevel) - { - continue; - } - - System.Type type = nextCommand.GetType(); - if (type == typeof(Else) || - type == typeof(End)) - { - if (i >= ParentBlock.CommandList.Count - 1) - { - // Last command in Block, so stop - StopParentBlock(); - } - else - { - // Execute command immediately after the Else or End command - Continue(nextCommand.CommandIndex + 1); - return; - } - } - else if (type == typeof(ElseIf)) - { - // Execute the Else If command - Continue(i); - - return; - } - } - - // No matching End command found, so just stop the block - StopParentBlock(); - } - - protected virtual bool EvaluateCondition() - { - BooleanVariable booleanVariable = variable as BooleanVariable; - IntegerVariable integerVariable = variable as IntegerVariable; - FloatVariable floatVariable = variable as FloatVariable; - StringVariable stringVariable = variable as StringVariable; - - bool condition = false; - - if (booleanVariable != null) - { - condition = booleanVariable.Evaluate(compareOperator, booleanData.Value); - } - else if (integerVariable != null) - { - condition = integerVariable.Evaluate(compareOperator, integerData.Value); - } - else if (floatVariable != null) - { - condition = floatVariable.Evaluate(compareOperator, floatData.Value); - } - else if (stringVariable != null) - { - condition = stringVariable.Evaluate(compareOperator, stringData.Value); - } - - return condition; - } - #region Public members - - public override void OnEnter() - { - if (ParentBlock == null) - { - return; - } - - if (variable == null) - { - Continue(); - return; - } - - EvaluateAndContinue(); - } - - public override string GetSummary() - { - if (variable == null) - { - return "Error: No variable selected"; - } - - string summary = variable.Key + " "; - summary += Condition.GetOperatorDescription(compareOperator) + " "; - - if (variable.GetType() == typeof(BooleanVariable)) - { - summary += booleanData.GetDescription(); - } - else if (variable.GetType() == typeof(IntegerVariable)) - { - summary += integerData.GetDescription(); - } - else if (variable.GetType() == typeof(FloatVariable)) - { - summary += floatData.GetDescription(); - } - else if (variable.GetType() == typeof(StringVariable)) - { - summary += stringData.GetDescription(); - } - - return summary; - } - - public override bool HasReference(Variable variable) - { - return (variable == this.variable); - } - - public override bool OpenBlock() - { - return true; - } - + public override Color GetButtonColor() { return new Color32(253, 253, 150, 255); diff --git a/Assets/Fungus/Scripts/Commands/LuaCondition.cs b/Assets/Fungus/Scripts/Commands/LuaCondition.cs new file mode 100644 index 00000000..7bd7d81d --- /dev/null +++ b/Assets/Fungus/Scripts/Commands/LuaCondition.cs @@ -0,0 +1,126 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using Fungus; +using MoonSharp.Interpreter; + +namespace Fungus +{ + public class LuaCondition : Condition + { + [Tooltip("Lua Environment to use to execute this Lua script (null for global)")] + [SerializeField] protected LuaEnvironment luaEnvironment; + + [Tooltip("The lua comparison string to run; implicitly prepends 'return' onto this")] + [TextArea] + public string luaCompareString; + protected bool initialised; + protected string friendlyName = ""; + protected Closure luaFunction; + + protected override bool EvaluateCondition() + { + bool condition = false; + luaEnvironment.RunLuaFunction(luaFunction, false, (returnValue) => { + if( returnValue != null ) + { + condition = returnValue.Boolean; + } + else + { + Debug.LogWarning("No return value from " + friendlyName); + } + }); + return condition; + } + + protected override bool HasNeededProperties() + { + return !string.IsNullOrEmpty(luaCompareString); + } + + protected virtual void Start() + { + InitExecuteLua(); + } + + protected virtual string GetLuaString() + { + return "return not not (" + luaCompareString + ")"; + } + + /// + /// Initialises the Lua environment and compiles the Lua string for execution later on. + /// + protected virtual void InitExecuteLua() + { + if (initialised) + { + return; + } + + // Cache a descriptive name to use in Lua error messages + friendlyName = gameObject.name + "." + ParentBlock.BlockName + "." + this.GetType().ToString() + " #" + CommandIndex.ToString(); + + Flowchart flowchart = GetFlowchart(); + + // See if a Lua Environment has been assigned to this Flowchart + if (luaEnvironment == null) + { + luaEnvironment = flowchart.LuaEnv; + } + + // No Lua Environment specified so just use any available or create one. + if (luaEnvironment == null) + { + luaEnvironment = LuaEnvironment.GetLua(); + } + + string s = GetLuaString(); + luaFunction = luaEnvironment.LoadLuaFunction(s, friendlyName); + + // Add a binding to the parent flowchart + if (flowchart.LuaBindingName != "") + { + Table globals = luaEnvironment.Interpreter.Globals; + if (globals != null) + { + globals[flowchart.LuaBindingName] = flowchart; + } + } + + // Always initialise when playing in the editor. + // Allows the user to edit the Lua script while the game is playing. + if ( !(Application.isPlaying && Application.isEditor) ) + { + initialised = true; + } + + } + + #region Public members + + public override string GetSummary() + { + if (string.IsNullOrEmpty(luaCompareString)) + { + return "Error: no lua compare string provided"; + } + + return luaCompareString; + } + + + public override bool OpenBlock() + { + return true; + } + + public override Color GetButtonColor() + { + return new Color32(253, 253, 150, 255); + } + + #endregion + } +} diff --git a/Assets/Fungus/Scripts/Commands/LuaCondition.cs.meta b/Assets/Fungus/Scripts/Commands/LuaCondition.cs.meta new file mode 100644 index 00000000..5073dfed --- /dev/null +++ b/Assets/Fungus/Scripts/Commands/LuaCondition.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 75ddfadd68d3d4713803a6b170cb0b51 +timeCreated: 1493078204 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Scripts/Commands/LuaElseIf.cs b/Assets/Fungus/Scripts/Commands/LuaElseIf.cs new file mode 100644 index 00000000..c7a647a5 --- /dev/null +++ b/Assets/Fungus/Scripts/Commands/LuaElseIf.cs @@ -0,0 +1,38 @@ +// 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) + +using UnityEngine; + +namespace Fungus +{ + /// + /// Marks the start of a command block to be executed when the preceding If statement is False and the test expression is true. + /// + [CommandInfo("Flow", + "Lua Else If", + "Marks the start of a command block to be executed when the preceding If statement is False and the test expression is true.")] + [AddComponentMenu("")] + public class LuaElseIf : LuaCondition + { + protected override bool IsElseIf { get { return true; } } + + #region Public members + + public override bool OpenBlock() + { + return true; + } + + public override bool CloseBlock() + { + return true; + } + + public override Color GetButtonColor() + { + return new Color32(253, 253, 150, 255); + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/Fungus/Scripts/Commands/LuaElseIf.cs.meta b/Assets/Fungus/Scripts/Commands/LuaElseIf.cs.meta new file mode 100644 index 00000000..fae44b6f --- /dev/null +++ b/Assets/Fungus/Scripts/Commands/LuaElseIf.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9739de3269e5246b399e3a1cd41b94de +timeCreated: 1493078204 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Scripts/Commands/LuaIf.cs b/Assets/Fungus/Scripts/Commands/LuaIf.cs new file mode 100644 index 00000000..0a69e412 --- /dev/null +++ b/Assets/Fungus/Scripts/Commands/LuaIf.cs @@ -0,0 +1,26 @@ +// 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) + +using UnityEngine; + +namespace Fungus +{ + /// + /// If the test expression is true, execute the following command block. + /// + [CommandInfo("Flow", + "Lua If", + "If the test expression is true, execute the following command block.")] + [AddComponentMenu("")] + public class LuaIf : LuaCondition + { + #region Public members + + public override Color GetButtonColor() + { + return new Color32(253, 253, 150, 255); + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/Fungus/Scripts/Commands/LuaIf.cs.meta b/Assets/Fungus/Scripts/Commands/LuaIf.cs.meta new file mode 100644 index 00000000..c67f5d4f --- /dev/null +++ b/Assets/Fungus/Scripts/Commands/LuaIf.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a8d396bcbf372485cad471c0bb64bb44 +timeCreated: 1493078204 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Fungus/Scripts/Commands/VariableCondition.cs b/Assets/Fungus/Scripts/Commands/VariableCondition.cs new file mode 100644 index 00000000..c06edbb7 --- /dev/null +++ b/Assets/Fungus/Scripts/Commands/VariableCondition.cs @@ -0,0 +1,110 @@ +// 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) + +using UnityEngine; + +namespace Fungus +{ + public abstract class VariableCondition : Condition + { + [Tooltip("The type of comparison to be performed")] + [SerializeField] protected CompareOperator compareOperator; + + [Tooltip("Variable to use in expression")] + [VariableProperty(typeof(BooleanVariable), + typeof(IntegerVariable), + typeof(FloatVariable), + typeof(StringVariable))] + [SerializeField] protected Variable variable; + + [Tooltip("Boolean value to compare against")] + [SerializeField] protected BooleanData booleanData; + + [Tooltip("Integer value to compare against")] + [SerializeField] protected IntegerData integerData; + + [Tooltip("Float value to compare against")] + [SerializeField] protected FloatData floatData; + + [Tooltip("String value to compare against")] + [SerializeField] protected StringDataMulti stringData; + + protected override bool EvaluateCondition() + { + BooleanVariable booleanVariable = variable as BooleanVariable; + IntegerVariable integerVariable = variable as IntegerVariable; + FloatVariable floatVariable = variable as FloatVariable; + StringVariable stringVariable = variable as StringVariable; + + bool condition = false; + + if (booleanVariable != null) + { + condition = booleanVariable.Evaluate(compareOperator, booleanData.Value); + } + else if (integerVariable != null) + { + condition = integerVariable.Evaluate(compareOperator, integerData.Value); + } + else if (floatVariable != null) + { + condition = floatVariable.Evaluate(compareOperator, floatData.Value); + } + else if (stringVariable != null) + { + condition = stringVariable.Evaluate(compareOperator, stringData.Value); + } + + return condition; + } + + protected override bool HasNeededProperties() + { + return (variable != null); + } + + #region Public members + + public override string GetSummary() + { + if (variable == null) + { + return "Error: No variable selected"; + } + + string summary = variable.Key + " "; + summary += Condition.GetOperatorDescription(compareOperator) + " "; + + if (variable.GetType() == typeof(BooleanVariable)) + { + summary += booleanData.GetDescription(); + } + else if (variable.GetType() == typeof(IntegerVariable)) + { + summary += integerData.GetDescription(); + } + else if (variable.GetType() == typeof(FloatVariable)) + { + summary += floatData.GetDescription(); + } + else if (variable.GetType() == typeof(StringVariable)) + { + summary += stringData.GetDescription(); + } + + return summary; + } + + public override bool HasReference(Variable variable) + { + return (variable == this.variable); + } + + public override Color GetButtonColor() + { + return new Color32(253, 253, 150, 255); + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/Fungus/Scripts/Commands/VariableCondition.cs.meta b/Assets/Fungus/Scripts/Commands/VariableCondition.cs.meta new file mode 100644 index 00000000..62776780 --- /dev/null +++ b/Assets/Fungus/Scripts/Commands/VariableCondition.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b065f7dff8779442ab5841ccc6ae375b +timeCreated: 1493077787 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: