Browse Source

Merge branch 'preda2or-multiple_logical_conditions' into develop

master
Steve Halliwell 5 years ago
parent
commit
98953ee3c5
  1. 3
      Assets/Fungus/Scripts/Commands/Condition.cs
  2. 329
      Assets/Fungus/Scripts/Commands/VariableCondition.cs
  3. 81
      Assets/Fungus/Scripts/Editor/VariableConditionEditor.cs
  4. 8
      Assets/FungusExamples/Conditions.meta
  5. 2020
      Assets/FungusExamples/Conditions/MultipleConditionsExample.unity
  6. 7
      Assets/FungusExamples/Conditions/MultipleConditionsExample.unity.meta

3
Assets/Fungus/Scripts/Commands/Condition.cs

@ -13,8 +13,6 @@ namespace Fungus
{
protected End endCommand;
#region Public members
public override void OnEnter()
{
if (ParentBlock == null)
@ -88,7 +86,6 @@ namespace Fungus
}
}
#endregion
protected End FindOurEndCommand()
{

329
Assets/Fungus/Scripts/Commands/VariableCondition.cs

@ -1,55 +1,141 @@
// This code is part of the Fungus library (https://github.com/snozbot/fungus)
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
using UnityEngine;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace Fungus
{
public abstract class VariableCondition : Condition, ISerializationCallbackReceiver
/// <summary>
/// class for a single condition. A list of this is used for multiple conditions.
/// </summary>
[System.Serializable]
public class ConditionExpression
{
[Tooltip("The type of comparison to be performed")]
[SerializeField] protected CompareOperator compareOperator;
[SerializeField] protected AnyVariableAndDataPair anyVar;
[SerializeField] protected AnyVariableAndDataPair anyVar = new AnyVariableAndDataPair();
public virtual AnyVariableAndDataPair AnyVar { get { return anyVar; } }
public virtual CompareOperator CompareOperator { get { return compareOperator; } }
protected override bool EvaluateCondition()
public ConditionExpression()
{
if (anyVar.variable == null)
{
return false;
}
}
bool condition = false;
anyVar.Compare(compareOperator, ref condition);
return condition;
public ConditionExpression(CompareOperator op, AnyVariableAndDataPair variablePair)
{
compareOperator = op;
anyVar = variablePair;
}
}
protected override bool HasNeededProperties()
public abstract class VariableCondition : Condition, ISerializationCallbackReceiver
{
public enum AnyOrAll
{
return (anyVar.variable != null);
AnyOf_OR,//Use as a chain of ORs
AllOf_AND,//Use as a chain of ANDs
}
#region Public members
[Tooltip("Selecting AnyOf will result in true if at least one of the conditions is true. Selecting AllOF will result in true only when all the conditions are true.")]
[SerializeField] protected AnyOrAll anyOrAllConditions;
[SerializeField] protected List<ConditionExpression> conditions = new List<ConditionExpression>();
/// <summary>
/// The type of comparison operation to be performed.
/// Called when the script is loaded or a value is changed in the
/// inspector (Called in the editor only).
/// </summary>
public virtual CompareOperator CompareOperator { get { return compareOperator; } }
public override void OnValidate()
{
base.OnValidate();
if (conditions == null)
{
conditions = new List<ConditionExpression>();
}
if (conditions.Count == 0)
{
conditions.Add(new ConditionExpression());
}
}
protected override bool EvaluateCondition()
{
if (conditions == null || conditions.Count == 0)
{
return false;
}
bool resultAny = false, resultAll = true;
foreach (ConditionExpression condition in conditions)
{
bool curResult = false;
if (condition.AnyVar == null)
{
resultAll &= curResult;
resultAny |= curResult;
continue;
}
condition.AnyVar.Compare(condition.CompareOperator, ref curResult);
resultAll &= curResult;
resultAny |= curResult;
}
if (anyOrAllConditions == AnyOrAll.AnyOf_OR) return resultAny;
return resultAll;
}
protected override bool HasNeededProperties()
{
if (conditions == null || conditions.Count == 0)
{
return false;
}
foreach (ConditionExpression condition in conditions)
{
if (condition.AnyVar == null || condition.AnyVar.variable == null)
{
return false;
}
}
return true;
}
public override string GetSummary()
{
if (anyVar.variable == null)
if (!this.HasNeededProperties())
{
return "Error: No variable selected";
}
string summary = anyVar.variable.Key + " ";
summary += VariableUtil.GetCompareOperatorDescription(compareOperator) + " ";
summary += anyVar.GetDataDescription();
string connector = "";
if (anyOrAllConditions == AnyOrAll.AnyOf_OR)
{
connector = " <b>OR</b> ";
}
else
{
connector = " <b>AND</b> ";
}
return summary;
StringBuilder summary = new StringBuilder("");
for (int i = 0; i < conditions.Count; i++)
{
summary.Append(conditions[i].AnyVar.variable.Key + " " +
VariableUtil.GetCompareOperatorDescription(conditions[i].CompareOperator) + " " +
conditions[i].AnyVar.GetDataDescription());
if (i < conditions.Count - 1)
{
summary.Append(connector);
}
}
return summary.ToString();
}
public override bool HasReference(Variable variable)
@ -57,10 +143,14 @@ namespace Fungus
return anyVar.HasReference(variable);
}
#endregion
#region backwards compat
[HideInInspector]
[SerializeField] protected CompareOperator compareOperator;
[HideInInspector]
[SerializeField] protected AnyVariableAndDataPair anyVar;
[Tooltip("Variable to use in expression")]
[VariableProperty(AllVariableTypes.VariableAny.Any)]
@ -113,107 +203,118 @@ namespace Fungus
[Tooltip("Vector3 value to compare against")]
[SerializeField] protected Vector3Data vector3Data;
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (variable == null)
{
return;
}
else
if (variable != null)
{
anyVar.variable = variable;
}
if (variable.GetType() == typeof(BooleanVariable) && !booleanData.Equals(new BooleanData()))
{
anyVar.data.booleanData = booleanData;
booleanData = new BooleanData();
}
else if (variable.GetType() == typeof(IntegerVariable) && !integerData.Equals(new IntegerData()))
{
anyVar.data.integerData = integerData;
integerData = new IntegerData();
}
else if (variable.GetType() == typeof(FloatVariable) && !floatData.Equals(new FloatData()))
{
anyVar.data.floatData = floatData;
floatData = new FloatData();
}
else if (variable.GetType() == typeof(StringVariable) && !stringData.Equals(new StringDataMulti()))
{
anyVar.data.stringData.stringRef = stringData.stringRef;
anyVar.data.stringData.stringVal = stringData.stringVal;
stringData = new StringDataMulti();
if (variable.GetType() == typeof(BooleanVariable) && !booleanData.Equals(new BooleanData()))
{
anyVar.data.booleanData = booleanData;
booleanData = new BooleanData();
}
else if (variable.GetType() == typeof(IntegerVariable) && !integerData.Equals(new IntegerData()))
{
anyVar.data.integerData = integerData;
integerData = new IntegerData();
}
else if (variable.GetType() == typeof(FloatVariable) && !floatData.Equals(new FloatData()))
{
anyVar.data.floatData = floatData;
floatData = new FloatData();
}
else if (variable.GetType() == typeof(StringVariable) && !stringData.Equals(new StringDataMulti()))
{
anyVar.data.stringData.stringRef = stringData.stringRef;
anyVar.data.stringData.stringVal = stringData.stringVal;
stringData = new StringDataMulti();
}
else if (variable.GetType() == typeof(AnimatorVariable) && !animatorData.Equals(new AnimatorData()))
{
anyVar.data.animatorData = animatorData;
animatorData = new AnimatorData();
}
else if (variable.GetType() == typeof(AudioSourceVariable) && !audioSourceData.Equals(new AudioSourceData()))
{
anyVar.data.audioSourceData = audioSourceData;
audioSourceData = new AudioSourceData();
}
else if (variable.GetType() == typeof(ColorVariable) && !colorData.Equals(new ColorData()))
{
anyVar.data.colorData = colorData;
colorData = new ColorData();
}
else if (variable.GetType() == typeof(GameObjectVariable) && !gameObjectData.Equals(new GameObjectData()))
{
anyVar.data.gameObjectData = gameObjectData;
gameObjectData = new GameObjectData();
}
else if (variable.GetType() == typeof(MaterialVariable) && !materialData.Equals(new MaterialData()))
{
anyVar.data.materialData = materialData;
materialData = new MaterialData();
}
else if (variable.GetType() == typeof(ObjectVariable) && !objectData.Equals(new ObjectData()))
{
anyVar.data.objectData = objectData;
objectData = new ObjectData();
}
else if (variable.GetType() == typeof(Rigidbody2DVariable) && !rigidbody2DData.Equals(new Rigidbody2DData()))
{
anyVar.data.rigidbody2DData = rigidbody2DData;
rigidbody2DData = new Rigidbody2DData();
}
else if (variable.GetType() == typeof(SpriteVariable) && !spriteData.Equals(new SpriteData()))
{
anyVar.data.spriteData = spriteData;
spriteData = new SpriteData();
}
else if (variable.GetType() == typeof(TextureVariable) && !textureData.Equals(new TextureData()))
{
anyVar.data.textureData = textureData;
textureData = new TextureData();
}
else if (variable.GetType() == typeof(TransformVariable) && !transformData.Equals(new TransformData()))
{
anyVar.data.transformData = transformData;
transformData = new TransformData();
}
else if (variable.GetType() == typeof(Vector2Variable) && !vector2Data.Equals(new Vector2Data()))
{
anyVar.data.vector2Data = vector2Data;
vector2Data = new Vector2Data();
}
else if (variable.GetType() == typeof(Vector3Variable) && !vector3Data.Equals(new Vector3Data()))
{
anyVar.data.vector3Data = vector3Data;
vector3Data = new Vector3Data();
}
//moved to new anyvar storage, clear legacy.
variable = null;
}
else if (variable.GetType() == typeof(AnimatorVariable) && !animatorData.Equals(new AnimatorData()))
{
anyVar.data.animatorData = animatorData;
animatorData = new AnimatorData();
}
else if (variable.GetType() == typeof(AudioSourceVariable) && !audioSourceData.Equals(new AudioSourceData()))
{
anyVar.data.audioSourceData = audioSourceData;
audioSourceData = new AudioSourceData();
}
else if (variable.GetType() == typeof(ColorVariable) && !colorData.Equals(new ColorData()))
{
anyVar.data.colorData = colorData;
colorData = new ColorData();
}
else if (variable.GetType() == typeof(GameObjectVariable) && !gameObjectData.Equals(new GameObjectData()))
{
anyVar.data.gameObjectData = gameObjectData;
gameObjectData = new GameObjectData();
}
else if (variable.GetType() == typeof(MaterialVariable) && !materialData.Equals(new MaterialData()))
{
anyVar.data.materialData = materialData;
materialData = new MaterialData();
}
else if (variable.GetType() == typeof(ObjectVariable) && !objectData.Equals(new ObjectData()))
{
anyVar.data.objectData = objectData;
objectData = new ObjectData();
}
else if (variable.GetType() == typeof(Rigidbody2DVariable) && !rigidbody2DData.Equals(new Rigidbody2DData()))
{
anyVar.data.rigidbody2DData = rigidbody2DData;
rigidbody2DData = new Rigidbody2DData();
}
else if (variable.GetType() == typeof(SpriteVariable) && !spriteData.Equals(new SpriteData()))
{
anyVar.data.spriteData = spriteData;
spriteData = new SpriteData();
}
else if (variable.GetType() == typeof(TextureVariable) && !textureData.Equals(new TextureData()))
{
anyVar.data.textureData = textureData;
textureData = new TextureData();
}
else if (variable.GetType() == typeof(TransformVariable) && !transformData.Equals(new TransformData()))
{
anyVar.data.transformData = transformData;
transformData = new TransformData();
}
else if (variable.GetType() == typeof(Vector2Variable) && !vector2Data.Equals(new Vector2Data()))
{
anyVar.data.vector2Data = vector2Data;
vector2Data = new Vector2Data();
}
else if (variable.GetType() == typeof(Vector3Variable) && !vector3Data.Equals(new Vector3Data()))
// just checking for anyVar != null fails here. is any var being reintilaized somewhere?
if (anyVar != null && anyVar.variable != null)
{
anyVar.data.vector3Data = vector3Data;
vector3Data = new Vector3Data();
ConditionExpression c = new ConditionExpression(compareOperator, anyVar);
if (!conditions.Contains(c))
{
conditions.Add(c);
}
anyVar = null;
variable = null;
}
//moved to new anyvar storage, clear legacy.
variable = null;
}
#endregion
#endregion backwards compat
}
}
}

81
Assets/Fungus/Scripts/Editor/VariableConditionEditor.cs

@ -3,11 +3,15 @@
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
namespace Fungus.EditorUtils
{
[CustomEditor (typeof(VariableCondition), true)]
/// <summary>
/// Handles custom drawing for ConditionExperssions within the VariableCondition and inherited commands.
///
/// TODO; refactor to allow a propertydrawer on ConditionExperssion and potentially list as reorderable
/// </summary>
[CustomEditor(typeof(VariableCondition), true)]
public class VariableConditionEditor : CommandEditor
{
public static readonly GUIContent None = new GUIContent("<None>");
@ -17,7 +21,7 @@ namespace Fungus.EditorUtils
None,
};
static readonly GUIContent[] compareListAll = new GUIContent[]
private static readonly GUIContent[] compareListAll = new GUIContent[]
{
new GUIContent(VariableUtil.GetCompareOperatorDescription(CompareOperator.Equals)),
new GUIContent(VariableUtil.GetCompareOperatorDescription(CompareOperator.NotEquals)),
@ -27,29 +31,30 @@ namespace Fungus.EditorUtils
new GUIContent(VariableUtil.GetCompareOperatorDescription(CompareOperator.GreaterThanOrEquals)),
};
static readonly GUIContent[] compareListEqualOnly = new GUIContent[]
private static readonly GUIContent[] compareListEqualOnly = new GUIContent[]
{
new GUIContent(VariableUtil.GetCompareOperatorDescription(CompareOperator.Equals)),
new GUIContent(VariableUtil.GetCompareOperatorDescription(CompareOperator.NotEquals)),
};
protected SerializedProperty compareOperatorProp;
protected SerializedProperty anyVarProp;
protected Dictionary<System.Type, SerializedProperty> propByVariableType;
protected SerializedProperty conditions;
public override void OnEnable()
{
base.OnEnable();
compareOperatorProp = serializedObject.FindProperty("compareOperator");
anyVarProp = serializedObject.FindProperty("anyVar");
conditions = serializedObject.FindProperty("conditions");
}
public override void DrawCommandGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(serializedObject.FindProperty("anyOrAllConditions"));
conditions.arraySize = EditorGUILayout.IntField("Size", conditions.arraySize);
GUILayout.Label("Conditions", EditorStyles.boldLabel);
VariableCondition t = target as VariableCondition;
var flowchart = (Flowchart)t.GetFlowchart();
@ -58,37 +63,43 @@ namespace Fungus.EditorUtils
return;
}
EditorGUILayout.PropertyField(anyVarProp, true);
// Get selected variable
Variable selectedVariable = anyVarProp.FindPropertyRelative("variable").objectReferenceValue as Variable;
GUIContent[] operatorsList = emptyList;
if (selectedVariable != null)
EditorGUI.indentLevel++;
for (int i = 0; i < conditions.arraySize; i++)
{
var conditionAnyVar = conditions.GetArrayElementAtIndex(i).FindPropertyRelative("anyVar");
var conditionCompare = conditions.GetArrayElementAtIndex(i).FindPropertyRelative("compareOperator");
EditorGUILayout.PropertyField(conditionAnyVar, new GUIContent("Variable"), true);
// Get selected variable
Variable selectedVariable = conditionAnyVar.FindPropertyRelative("variable").objectReferenceValue as Variable;
if (selectedVariable == null)
continue;
GUIContent[] operatorsList = emptyList;
operatorsList = selectedVariable.IsComparisonSupported() ? compareListAll : compareListEqualOnly;
}
// Get previously selected operator
int selectedIndex = (int)t.CompareOperator;
if (selectedIndex < 0)
{
// Default to first index if the operator is not found in the available operators list
// This can occur when changing between variable types
selectedIndex = 0;
}
selectedIndex = EditorGUILayout.Popup(
new GUIContent("Compare", "The comparison operator to use when comparing values"),
selectedIndex,
operatorsList);
// Get previously selected operator
int selectedIndex = conditionCompare.enumValueIndex;
if (selectedIndex < 0 || selectedIndex >= operatorsList.Length)
{
// Default to first index if the operator is not found in the available operators list
// This can occur when changing between variable types
selectedIndex = 0;
}
if (selectedVariable != null)
{
compareOperatorProp.enumValueIndex = selectedIndex;
}
selectedIndex = EditorGUILayout.Popup(
new GUIContent("Compare", "The comparison operator to use when comparing values"),
selectedIndex,
operatorsList);
conditionCompare.enumValueIndex = selectedIndex;
EditorGUILayout.Separator();
}
EditorGUI.indentLevel--;
serializedObject.ApplyModifiedProperties();
}
}
}
}

8
Assets/FungusExamples/Conditions.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ab073c9a6f825fe4b82cbe37c37addb0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

2020
Assets/FungusExamples/Conditions/MultipleConditionsExample.unity

File diff suppressed because it is too large Load Diff

7
Assets/FungusExamples/Conditions/MultipleConditionsExample.unity.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0d9b345eec71ebc46bfb14d1a3b8af20
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Loading…
Cancel
Save