diff --git a/Project/Assets/LunarConsole/Scripts/Actions/CVar.cs b/Project/Assets/LunarConsole/Scripts/Actions/CVar.cs index 13c77a58..72ce6577 100644 --- a/Project/Assets/LunarConsole/Scripts/Actions/CVar.cs +++ b/Project/Assets/LunarConsole/Scripts/Actions/CVar.cs @@ -19,7 +19,8 @@ // limitations under the License. // -using System; +using System; +using System.CodeDom; using System.Collections; using System.Collections.Generic; using System.Reflection; @@ -39,17 +40,79 @@ public enum CVarType String } - struct CValue + public class CValue { public string stringValue; public int intValue; public float floatValue; + public bool boolValue; + + public CVarType Type { get; } + + public CValue(CVarType type, string value) + { + Type = type; + + stringValue = value; + floatValue = IsInt || IsFloat ? StringUtils.ParseFloat(value, 0.0f) : 0.0f; + intValue = IsInt || IsFloat ? (int) floatValue : 0; + } + + public CValue(CVarType type, int value) + { + Type = type; + + stringValue = StringUtils.ToString(value); + intValue = value; + floatValue = value; + } + + public CValue(CVarType type, float value) + { + Type = type; + + stringValue = StringUtils.ToString(value); + intValue = (int) value; + floatValue = value; + } + + + public CValue(CVarType type, bool value) + { + Type = type; + + boolValue = value; + intValue = value ? 1 : 0; + floatValue = intValue; + stringValue = intValue.ToString(); + } public bool Equals(ref CValue other) { return other.intValue == intValue && other.floatValue == floatValue && - other.stringValue == stringValue; + other.stringValue == stringValue && + other.boolValue == boolValue; + } + + public bool IsInt + { + get { return Type == CVarType.Integer || Type == CVarType.Boolean; } + } + + public bool IsString + { + get { return Type == CVarType.String; } + } + + public bool IsFloat + { + get { return Type == CVarType.Float; } + } + + public bool IsBool + { + get { return Type == CVarType.Boolean; } } } @@ -73,7 +136,7 @@ public bool IsValid } public enum CFlags - { + { /// /// No flags (default value) /// @@ -90,6 +153,115 @@ public enum CFlags NoArchive = 1 << 2 } + public interface ICVarProxy + { + CValue Value { get; set; } + } + + public class CVarProxy : ICVarProxy + { + private Func GetFunc { get; } + private Func SetFunc { get; } + private CValue _value; + + public CVarProxy() + { + GetFunc = () => + { + if (typeof(T) == typeof(int)) + { + return (T) Convert.ChangeType(_value.intValue, typeof(T)); + } + + if (typeof(T) == typeof(float)) + { + return (T) Convert.ChangeType(_value.floatValue, typeof(T)); + } + + if (typeof(T) == typeof(string)) + { + return (T) Convert.ChangeType(_value.stringValue, typeof(T)); + } + + if (typeof(T) == typeof(bool)) + { + return (T) Convert.ChangeType(_value.boolValue, typeof(T)); + } + + throw new ArgumentException(); + }; + + SetFunc = value => value; + } + + public CVarProxy(Func getFunc, Func setFunc) + { + GetFunc = getFunc; + SetFunc = setFunc; + } + + public CValue Value + { + get + { + var value = GetFunc.Invoke(); + + if (typeof(T) == typeof(int)) + { + _value = new CValue(CVarType.Integer, (int) Convert.ChangeType(value, typeof(int))); + } + else if (typeof(T) == typeof(float)) + { + _value = new CValue(CVarType.Float, (float) Convert.ChangeType(value, typeof(float))); + } + else if (typeof(T) == typeof(string)) + { + _value = new CValue(CVarType.String, (string) Convert.ChangeType(value, typeof(string))); + } + else if (typeof(T) == typeof(bool)) + { + _value = new CValue(CVarType.Boolean, (bool) Convert.ChangeType(value, typeof(bool))); + } + else + { + throw new ArgumentException(); + } + + return _value; + } + set + { + _value = value; + + if (typeof(T) == typeof(int)) + { + SetFunc.Invoke((T) Convert.ChangeType(_value.intValue, typeof(T))); + return; + } + + if (typeof(T) == typeof(float)) + { + SetFunc.Invoke((T) Convert.ChangeType(_value.floatValue, typeof(T))); + return; + } + + if (typeof(T) == typeof(string)) + { + SetFunc.Invoke((T) Convert.ChangeType(_value.stringValue, typeof(T))); + return; + } + + if (typeof(T) == typeof(bool)) + { + SetFunc.Invoke((T) Convert.ChangeType(_value.boolValue, typeof(T))); + return; + } + + throw new ArgumentException(); + } + } + } + public class CVar : IEquatable, IComparable { private static int s_nextId; @@ -99,38 +271,59 @@ public class CVar : IEquatable, IComparable private readonly CVarType m_type; private readonly CFlags m_flags; - private CValue m_value; private CValue m_defaultValue; private CVarValueRange m_range = CVarValueRange.Undefined; private CVarChangedDelegateList m_delegateList; - public CVar(string name, bool defaultValue, CFlags flags = CFlags.None) + private CVarProxy m_intProxy; + private CVarProxy m_boolProxy; + private CVarProxy m_floatProxy; + private CVarProxy m_stringProxy; + + private ICVarProxy Proxy + { + get + { + if (m_intProxy != null) return m_intProxy; + if (m_boolProxy != null) return m_boolProxy; + if (m_floatProxy != null) return m_floatProxy; + if (m_stringProxy != null) return m_stringProxy; + + throw new ArgumentException(); + } + } + + public CVar(string name, bool defaultValue, CFlags flags = CFlags.None, CVarProxy proxy = null) : this(name, CVarType.Boolean, flags) { - this.IntValue = defaultValue ? 1 : 0; - m_defaultValue = m_value; + m_boolProxy = proxy ?? new CVarProxy(); + BoolValue = defaultValue; + m_defaultValue = new CValue(m_type, defaultValue); } - public CVar(string name, int defaultValue, CFlags flags = CFlags.None) + public CVar(string name, int defaultValue, CFlags flags = CFlags.None, CVarProxy proxy = null) : this(name, CVarType.Integer, flags) { - this.IntValue = defaultValue; - m_defaultValue = m_value; + m_intProxy = proxy ?? new CVarProxy(); + IntValue = defaultValue; + m_defaultValue = new CValue(m_type, defaultValue); } - public CVar(string name, float defaultValue, CFlags flags = CFlags.None) + public CVar(string name, float defaultValue, CFlags flags = CFlags.None, CVarProxy proxy = null) : this(name, CVarType.Float, flags) { - this.FloatValue = defaultValue; - m_defaultValue = m_value; + m_floatProxy = proxy ?? new CVarProxy(); + FloatValue = defaultValue; + m_defaultValue = new CValue(m_type, defaultValue); } - public CVar(string name, string defaultValue, CFlags flags = CFlags.None) + public CVar(string name, string defaultValue, CFlags flags = CFlags.None, CVarProxy proxy = null) : this(name, CVarType.String, flags) { - this.Value = defaultValue; - m_defaultValue = m_value; + m_stringProxy = proxy ?? new CVarProxy(); + Value = defaultValue; + m_defaultValue = new CValue(m_type, defaultValue); } private CVar(string name, CVarType type, CFlags flags) @@ -219,7 +412,7 @@ public bool Equals(CVar other) { return other != null && other.m_name == m_name && - other.m_value.Equals(ref m_value) && + other.Proxy.Value.Equals(Proxy.Value) && other.m_defaultValue.Equals(ref m_defaultValue) && other.m_type == m_type; } @@ -263,19 +456,17 @@ public string DefaultValue public bool IsString { - get { return m_type == CVarType.String; } + get { return Proxy.Value.IsString; } } public string Value { - get { return m_value.stringValue; } + get { return Proxy.Value.stringValue; } set { - bool changed = m_value.stringValue != value; + var changed = Proxy.Value.stringValue != value; - m_value.stringValue = value; - m_value.floatValue = IsInt || IsFloat ? StringUtils.ParseFloat(value, 0.0f) : 0.0f; - m_value.intValue = IsInt || IsFloat ? (int)FloatValue : 0; + Proxy.Value = new CValue(m_type, value); if (changed) { @@ -297,19 +488,17 @@ public bool HasRange public bool IsInt { - get { return m_type == CVarType.Integer || m_type == CVarType.Boolean; } + get { return Proxy.Value.IsInt; } } public int IntValue { - get { return m_value.intValue; } + get => Proxy.Value.intValue; set { - bool changed = m_value.intValue != value; + var changed = Proxy.Value.intValue != value; - m_value.stringValue = StringUtils.ToString(value); - m_value.intValue = value; - m_value.floatValue = (float)value; + Proxy.Value = new CValue(m_type, value); if (changed) { @@ -320,21 +509,19 @@ public int IntValue public bool IsFloat { - get { return m_type == CVarType.Float; } + get { return Proxy.Value.Type == CVarType.Float; } } public float FloatValue { - get { return m_value.floatValue; } + get { return Proxy.Value.floatValue; } set { - float oldValue = m_value.floatValue; + var changed = Proxy.Value.floatValue != value; - m_value.stringValue = StringUtils.ToString(value); - m_value.intValue = (int)value; - m_value.floatValue = value; + Proxy.Value = new CValue(m_type, value); - if (oldValue != value) + if (changed) { NotifyValueChanged(); } @@ -343,22 +530,25 @@ public float FloatValue public bool IsBool { - get { return m_type == CVarType.Boolean; } + get { return Proxy.Value.IsBool; } } public bool BoolValue { - get { return m_value.intValue != 0; } - set { this.IntValue = value ? 1 : 0; } + get { return Proxy.Value.intValue != 0; } + set + { + Proxy.Value = new CValue(m_type, value); + } } public bool IsDefault { - get { return m_value.Equals(m_defaultValue); } + get { return Proxy.Value.Equals(m_defaultValue); } set { - bool changed = this.IsDefault ^ value; - m_value = m_defaultValue; + bool changed = IsDefault ^ value; + Proxy.Value = m_defaultValue; if (changed) { @@ -383,22 +573,22 @@ public CFlags Flags public static implicit operator string(CVar cvar) { - return cvar.m_value.stringValue; + return cvar.Proxy.Value.stringValue; } public static implicit operator int(CVar cvar) { - return cvar.m_value.intValue; + return cvar.Proxy.Value.intValue; } public static implicit operator float(CVar cvar) { - return cvar.m_value.floatValue; + return cvar.Proxy.Value.floatValue; } public static implicit operator bool(CVar cvar) { - return cvar.m_value.intValue != 0; + return cvar.Proxy.Value.intValue != 0; } #endregion @@ -470,7 +660,7 @@ public IEnumerator GetEnumerator() #region IEnumerable implementation - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + IEnumerator IEnumerable.GetEnumerator() { return m_variables.GetEnumerator(); } @@ -483,7 +673,7 @@ public int Count } } - [AttributeUsage (AttributeTargets.Field, Inherited = true, AllowMultiple = false)] + [AttributeUsage (AttributeTargets.Field)] public sealed class CVarRangeAttribute : Attribute { public readonly float min; @@ -538,4 +728,4 @@ static void NullCVarChangedDelegate(CVar cvar) { } } -} \ No newline at end of file +}