You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
10 KiB
328 lines
10 KiB
// 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; |
|
|
|
namespace Fungus |
|
{ |
|
/// <summary> |
|
/// Standard comparison operators. |
|
/// </summary> |
|
public enum CompareOperator |
|
{ |
|
/// <summary> == mathematical operator.</summary> |
|
Equals, |
|
/// <summary> != mathematical operator.</summary> |
|
NotEquals, |
|
/// <summary> < mathematical operator.</summary> |
|
LessThan, |
|
/// <summary> > mathematical operator.</summary> |
|
GreaterThan, |
|
/// <summary> <= mathematical operator.</summary> |
|
LessThanOrEquals, |
|
/// <summary> >= mathematical operator.</summary> |
|
GreaterThanOrEquals |
|
} |
|
|
|
/// <summary> |
|
/// Mathematical operations that can be performed on variables. |
|
/// </summary> |
|
public enum SetOperator |
|
{ |
|
/// <summary> = operator. </summary> |
|
Assign, |
|
/// <summary> =! operator. </summary> |
|
Negate, |
|
/// <summary> += operator. </summary> |
|
Add, |
|
/// <summary> -= operator. </summary> |
|
Subtract, |
|
/// <summary> *= operator. </summary> |
|
Multiply, |
|
/// <summary> /= operator. </summary> |
|
Divide |
|
} |
|
|
|
/// <summary> |
|
/// Scope types for Variables. |
|
/// </summary> |
|
public enum VariableScope |
|
{ |
|
/// <summary> Can only be accessed by commands in the same Flowchart. </summary> |
|
Private, |
|
/// <summary> Can be accessed from any command in any Flowchart. </summary> |
|
Public, |
|
/// <summary> Creates and/or references a global variable of that name, all variables of this name and scope share the same underlying fungus variable and exist for the duration of the instance of Unity.</summary> |
|
Global, |
|
} |
|
|
|
/// <summary> |
|
/// Attribute class for variables. |
|
/// </summary> |
|
public sealed class VariableInfoAttribute : System.Attribute |
|
{ |
|
//Note do not use "isPreviewedOnly:true", it causes the script to fail to load without errors shown |
|
public VariableInfoAttribute(string category, string variableType, int order = 0, bool isPreviewedOnly = false) |
|
{ |
|
this.Category = category; |
|
this.VariableType = variableType; |
|
this.Order = order; |
|
this.IsPreviewedOnly = isPreviewedOnly; |
|
} |
|
|
|
public string Category { get; set; } |
|
public string VariableType { get; set; } |
|
public int Order { get; set; } |
|
public bool IsPreviewedOnly { get; set; } |
|
} |
|
|
|
/// <summary> |
|
/// Attribute class for variable properties. |
|
/// </summary> |
|
public sealed class VariablePropertyAttribute : PropertyAttribute |
|
{ |
|
public VariablePropertyAttribute (params System.Type[] variableTypes) |
|
{ |
|
this.VariableTypes = variableTypes; |
|
} |
|
|
|
public VariablePropertyAttribute(AllVariableTypes.VariableAny any) |
|
{ |
|
VariableTypes = AllVariableTypes.AllFungusVarTypes; |
|
} |
|
|
|
public VariablePropertyAttribute (string defaultText, params System.Type[] variableTypes) |
|
{ |
|
this.defaultText = defaultText; |
|
this.VariableTypes = variableTypes; |
|
} |
|
|
|
public string defaultText = "<None>"; |
|
public string compatibleVariableName = string.Empty; |
|
|
|
public System.Type[] VariableTypes { get; set; } |
|
} |
|
|
|
/// <summary> |
|
/// Abstract base class for variables. |
|
/// </summary> |
|
[RequireComponent(typeof(Flowchart))] |
|
[System.Serializable] |
|
public abstract class Variable : MonoBehaviour |
|
{ |
|
[SerializeField] protected VariableScope scope; |
|
|
|
[SerializeField] protected string key = ""; |
|
|
|
#region Public members |
|
|
|
/// <summary> |
|
/// Visibility scope for the variable. |
|
/// </summary> |
|
public virtual VariableScope Scope { get { return scope; } set { scope = value; } } |
|
|
|
/// <summary> |
|
/// String identifier for the variable. |
|
/// </summary> |
|
public virtual string Key { get { return key; } set { key = value; } } |
|
|
|
/// <summary> |
|
/// Callback to reset the variable if the Flowchart is reset. |
|
/// </summary> |
|
public abstract void OnReset(); |
|
|
|
/// <summary> |
|
/// Used by SetVariable, child classes required to declare and implement operators. |
|
/// </summary> |
|
/// <param name="setOperator"></param> |
|
/// <param name="value"></param> |
|
public abstract void Apply(SetOperator setOperator, object value); |
|
|
|
/// <summary> |
|
/// Used by Ifs, While, and the like. Child classes required to declare and implement comparisons. |
|
/// </summary> |
|
/// <param name="compareOperator"></param> |
|
/// <param name="value"></param> |
|
/// <returns></returns> |
|
public abstract bool Evaluate(CompareOperator compareOperator, object value); |
|
|
|
/// <summary> |
|
/// Does the underlying type provide support for +-*/ |
|
/// </summary> |
|
public virtual bool IsArithmeticSupported(SetOperator setOperator) { return false; } |
|
|
|
/// <summary> |
|
/// Does the underlying type provide support for < <= > >= |
|
/// </summary> |
|
public virtual bool IsComparisonSupported() { return false; } |
|
|
|
/// <summary> |
|
/// Boxed or referenced value of type defined within inherited types. |
|
/// Not recommended for direct use, primarily intended for use in editor code. |
|
/// </summary> |
|
public abstract object GetValue(); |
|
|
|
//we are required to be on a flowchart so we provide this as a helper |
|
public virtual Flowchart GetFlowchart() |
|
{ |
|
return GetComponent<Flowchart>(); |
|
} |
|
#endregion |
|
} |
|
|
|
/// <summary> |
|
/// Generic concrete base class for variables. |
|
/// </summary> |
|
public abstract class VariableBase<T> : Variable |
|
{ |
|
//caching mechanism for global static variables |
|
private VariableBase<T> _globalStaicRef; |
|
private VariableBase<T> globalStaicRef |
|
{ |
|
get |
|
{ |
|
if (_globalStaicRef != null) |
|
{ |
|
return _globalStaicRef; |
|
} |
|
else if(Application.isPlaying) |
|
{ |
|
return _globalStaicRef = FungusManager.Instance.GlobalVariables.GetOrAddVariable(Key, value, this.GetType()); |
|
} |
|
else |
|
{ |
|
return null; |
|
} |
|
} |
|
} |
|
|
|
[SerializeField] protected T value; |
|
public virtual T Value |
|
{ |
|
get |
|
{ |
|
if (scope != VariableScope.Global || !Application.isPlaying) |
|
{ |
|
return this.value; |
|
} |
|
else |
|
{ |
|
return globalStaicRef.value; |
|
} |
|
} |
|
set |
|
{ |
|
if (scope != VariableScope.Global || !Application.isPlaying) |
|
{ |
|
this.value = value; |
|
} |
|
else |
|
{ |
|
globalStaicRef.Value = value; |
|
} |
|
} |
|
} |
|
|
|
public override object GetValue() |
|
{ |
|
return value; |
|
} |
|
|
|
protected T startValue; |
|
|
|
public override void OnReset() |
|
{ |
|
Value = startValue; |
|
} |
|
|
|
public override string ToString() |
|
{ |
|
if (Value != null) |
|
return Value.ToString(); |
|
else |
|
return "Null"; |
|
} |
|
|
|
protected virtual void Start() |
|
{ |
|
// Remember the initial value so we can reset later on |
|
startValue = Value; |
|
} |
|
|
|
//Apply to get from base system.object to T |
|
public override void Apply(SetOperator op, object value) |
|
{ |
|
if(value is T || value == null) |
|
{ |
|
Apply(op, (T)value); |
|
} |
|
else if(value is VariableBase<T>) |
|
{ |
|
var vbg = value as VariableBase<T>; |
|
Apply(op, vbg.Value); |
|
} |
|
else |
|
{ |
|
Debug.LogError("Cannot do Apply on variable, as object type: " + value.GetType().Name + " is incompatible with " + typeof(T).Name); |
|
} |
|
} |
|
|
|
public virtual void Apply(SetOperator setOperator, T value) |
|
{ |
|
switch (setOperator) |
|
{ |
|
case SetOperator.Assign: |
|
Value = value; |
|
break; |
|
default: |
|
Debug.LogError("The " + setOperator.ToString() + " set operator is not valid."); |
|
break; |
|
} |
|
} |
|
|
|
//Apply to get from base system.object to T |
|
public override bool Evaluate(CompareOperator op, object value) |
|
{ |
|
if (value is T || value == null) |
|
{ |
|
return Evaluate(op, (T)value); |
|
} |
|
else if (value is VariableBase<T>) |
|
{ |
|
var vbg = value as VariableBase<T>; |
|
return Evaluate(op, vbg.Value); |
|
} |
|
else |
|
{ |
|
Debug.LogError("Cannot do Evaluate on variable, as object type: " + value.GetType().Name + " is incompatible with " + typeof(T).Name); |
|
} |
|
|
|
return false; |
|
} |
|
|
|
public virtual bool Evaluate(CompareOperator compareOperator, T value) |
|
{ |
|
bool condition = false; |
|
|
|
switch (compareOperator) |
|
{ |
|
case CompareOperator.Equals: |
|
condition = Equals(Value, value);// Value.Equals(value); |
|
break; |
|
case CompareOperator.NotEquals: |
|
condition = !Equals(Value, value); |
|
break; |
|
default: |
|
Debug.LogError("The " + compareOperator.ToString() + " comparison operator is not valid."); |
|
break; |
|
} |
|
|
|
return condition; |
|
} |
|
|
|
public override bool IsArithmeticSupported(SetOperator setOperator) |
|
{ |
|
return setOperator == SetOperator.Assign || base.IsArithmeticSupported(setOperator); |
|
} |
|
} |
|
}
|
|
|