diff options
author | chai <215380520@qq.com> | 2024-05-19 16:38:03 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2024-05-19 16:38:03 +0800 |
commit | 43a5ba7683a8d446fcdc6bd9939512a6e1700daf (patch) | |
tree | 71140c6dc58178b0735b0a810b37a679321f78ee | |
parent | 1b391f68c793406701a23dd2fd6026997288e9d3 (diff) |
+ utils + thirdparty
160 files changed, 15900 insertions, 0 deletions
diff --git a/YesCommander/Assets/Scripts/Common.meta b/YesCommander/Assets/Scripts/Common.meta new file mode 100644 index 0000000..1651128 --- /dev/null +++ b/YesCommander/Assets/Scripts/Common.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 29790d29244c47446a26d94f58ee2fc2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Common/Common.cs b/YesCommander/Assets/Scripts/Common/Common.cs new file mode 100644 index 0000000..711a228 --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/Common.cs @@ -0,0 +1,348 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// author: hanjun +// date: 2018/12/03 16:31:57 +// desc: 某类 +// +// +// +// +// +///////////////////////////////////////////////////////////////////////////////// + +using UnityEngine; +using System.Collections; + +namespace YC +{ + [System.Serializable] + public struct IntVector2 + { + public int x; + public int y; + + public IntVector2(int x, int y) + { + this.x = x; + this.y = y; + } + + static IntVector2 mZero = new IntVector2(0, 0); + static IntVector2 mOne = new IntVector2(1, 1); + public static IntVector2 Zero + { + get + { + return mZero; + } + } + + public static IntVector2 One + { + get + { + return mOne; + } + } + public int ConstCount + { + get + { + return 2; + } + } + public int this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + default: + throw new System.ArgumentOutOfRangeException("IntVector2索引越界"); + } + } + set + { + switch (index) + { + case 0: + x = value; + break; + case 1: + y = value; + break; + default: + throw new System.ArgumentOutOfRangeException("IntVector2索引越界"); + } + } + } + public static implicit operator Vector2(IntVector2 v) + { + return new Vector2(v.x, v.y); + } + public static IntVector2 operator *(int d, IntVector2 a) + { + a.x *= d; + a.y *= d; + return a; + } + public static bool operator ==(IntVector2 lhs, IntVector2 rhs) + { + return (lhs.x == rhs.x && lhs.y == rhs.y); + } + + public static bool operator !=(IntVector2 lhs, IntVector2 rhs) + { + return (lhs.x != rhs.x || lhs.y != rhs.y); + } + public override string ToString() + { + return StringUtil.Concat(x.ToTempString(), ",", y.ToTempString()); + } + public override bool Equals(object obj) + { + if (obj is IntVector2) + { + IntVector2 other = (IntVector2)obj; + return other.x == x && other.y == y; + } + else + { + return false; + } + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + } + + public struct IntVector3 + { + public int x; + public int y; + public int z; + + public IntVector3(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + + static IntVector3 mZero = new IntVector3(0, 0, 0); + public static IntVector3 Zero + { + get + { + return mZero; + } + } + public int ConstCount + { + get + { + return 3; + } + } + public int this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + default: + throw new System.ArgumentOutOfRangeException("IntVector3索引越界"); + } + } + set + { + switch (index) + { + case 0: + x = value; + break; + case 1: + y = value; + break; + case 2: + z = value; + break; + default: + throw new System.ArgumentOutOfRangeException("IntVector3索引越界"); + } + } + } + public static implicit operator Vector3(IntVector3 v) + { + return new Vector3(v.x, v.y, v.z); + } + public static IntVector3 operator *(int d, IntVector3 a) + { + a.x *= d; + a.y *= d; + a.z *= d; + return a; + } + public static bool operator ==(IntVector3 lhs, IntVector3 rhs) + { + return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); + } + public static bool operator !=(IntVector3 lhs, IntVector3 rhs) + { + return (lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z); + } + public override string ToString() + { + return StringUtil.Concat(x.ToTempString(), ",", y.ToTempString(), ",", z.ToTempString()); + } + public override bool Equals(object obj) + { + if (obj is IntVector3) + { + IntVector3 other = (IntVector3)obj; + return other.x == x && other.y == y && other.z == z; + } + else + { + return false; + } + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public bool Contains(int a) + { + if (x == a || y == a || z == a) + return true; + return false; + } + } + + public struct IntVector4 + { + public int x; + public int y; + public int z; + public int w; + + public IntVector4(int x, int y, int z, int w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + static IntVector4 mZero = new IntVector4(0, 0, 0, 0); + public static IntVector4 Zero + { + get + { + return mZero; + } + } + public static int ConstCount + { + get + { + return 4; + } + } + public int this[int index] + { + get + { + switch (index) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + default: + throw new System.ArgumentOutOfRangeException("IntVector4索引越界"); + } + } + set + { + switch (index) + { + case 0: + x = value; + break; + case 1: + y = value; + break; + case 2: + z = value; + break; + case 3: + w = value; + break; + default: + throw new System.ArgumentOutOfRangeException("IntVector4索引越界"); + } + } + } + public static implicit operator Vector4(IntVector4 v) + { + return new Vector4(v.x, v.y, v.z, v.w); + } + public static IntVector4 operator *(int d, IntVector4 a) + { + a.x *= d; + a.y *= d; + a.z *= d; + a.w *= d; + return a; + } + public static bool operator ==(IntVector4 lhs, IntVector4 rhs) + { + return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w); + } + public static bool operator !=(IntVector4 lhs, IntVector4 rhs) + { + return (lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w); + } + + public override string ToString() + { + return StringUtil.Concat(x.ToTempString(), ",", y.ToTempString(), ",", z.ToTempString(), ",", w.ToTempString()); + } + public override bool Equals(object obj) + { + if (obj is IntVector4) + { + IntVector4 other = (IntVector4)obj; + return other.x == x && other.y == y && other.z == z && other.w == w; + } + else + { + return false; + } + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + } +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Common/Common.cs.meta b/YesCommander/Assets/Scripts/Common/Common.cs.meta new file mode 100644 index 0000000..e738e0b --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/Common.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c2cff652623bdff42acbdbfe57c4b998 +timeCreated: 1543825917 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Common/CommonFunction.cs b/YesCommander/Assets/Scripts/Common/CommonFunction.cs new file mode 100644 index 0000000..e5b8d30 --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/CommonFunction.cs @@ -0,0 +1,57 @@ +using System; +using System.Reflection; +using System.Reflection.Emit; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using System.Linq; + +namespace YC +{ + + public static class CommonFunction + { + + public static void WriteFile(string content, string file) + { + if (File.Exists(file)) + { + File.Delete(file); + } + + string dir = Path.GetDirectoryName(file); + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + + File.WriteAllText(file, content); + } + + public static Type GetTypeByName(string name) + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Reverse()) + { + var tt = assembly.GetType(name); + if (tt != null) + { + return tt; + } + } + + return null; + } + + public static System.Object CreateInstance(string typeName) + { + Type t = GetTypeByName(typeName); + if (t == null) + return null; + var obj = Activator.CreateInstance(t); + return obj; + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Common/CommonFunction.cs.meta b/YesCommander/Assets/Scripts/Common/CommonFunction.cs.meta new file mode 100644 index 0000000..d61d02b --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/CommonFunction.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9a3413ddfeae9d48b8e4f5983bf3484 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Common/CommonParse.cs b/YesCommander/Assets/Scripts/Common/CommonParse.cs new file mode 100644 index 0000000..9acc93e --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/CommonParse.cs @@ -0,0 +1,317 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// author: hanjun +// date: 2018/12/03 16:33:35 +// desc: 某类 +// +// +// +// +// +///////////////////////////////////////////////////////////////////////////////// + +using UnityEngine; +using System.Collections; +using System; +using LitJson; + +namespace YC +{ + public class CommonParse + { + public static float ParseFloat(string str) + { + float target = 0f; + ParseFloat(ref target, str, 0f); + return target; + } + public static void ParseFloat(ref float target, string str) + { + ParseFloat(ref target, str, 0f); + } + public static void ParseFloat(ref float target, string str, float defaultValue) + { + if (string.IsNullOrEmpty(str)) + { + target = defaultValue; + return; + } + str = str.Replace("(", ""); + str = str.Replace(")", ""); + float result = defaultValue;//使用默认值 + if (float.TryParse(str, out result)) + { + target = result; + } + else + { + LogHelper.LogEditorError("ParseFloat Error at field : " + str); + target = defaultValue; + } + } + public static int ParseInt(string str) + { + int target = 0; + ParseInt(ref target, str, 0); + return target; + } + public static void ParseInt(ref int target, string str) + { + ParseInt(ref target, str, 0); + } + public static void ParseInt(ref int target, string str, int defaultValue) + { + if (string.IsNullOrEmpty(str)) + { + target = defaultValue; + return; + } + + int result = defaultValue;//使用默认值 + if (int.TryParse(str, out result)) + { + target = result; + } + else + { + if (str.Contains("0x")) + { + target = Convert.ToInt32(str, 16); + } + else + { + LogHelper.LogEditorError("ParseInt Error at field : " + str); + target = defaultValue; + } + } + } + public static byte ParseByte(string str) + { + byte target = 0; + ParseByte(ref target, str, 0); + return target; + } + public static void ParseByte(ref byte target, string str) + { + ParseByte(ref target, str, 0); + } + public static void ParseByte(ref byte target, string str, byte defaultValue) + { + if (string.IsNullOrEmpty(str)) + { + target = defaultValue; + return; + } + + byte result = defaultValue;//使用默认值 + if (byte.TryParse(str, out result)) + { + target = result; + } + else + { + if (str.Contains("0x")) + { + target = Convert.ToByte(str, 16); + } + else + { + LogHelper.LogEditorError("ParseByte Error at field : " + str); + target = defaultValue; + } + } + } + + public static void ParseVector2(ref Vector2 v2, string str) + { + if (string.IsNullOrEmpty(str)) + { + v2 = Vector2.zero; + return; + } + + string[] array = str.Split(',', ';', '='); + if (array.Length >= 1) + ParseFloat(ref v2.x, array[0]); + if (array.Length >= 2) + ParseFloat(ref v2.y, array[1]); + + //if (array.Length == 2) + //{ + // ParseFloat(ref v2.x, array[0]); + // ParseFloat(ref v2.y, array[1]); + //} + //else + //{ + // LogHelper.LogError("解析ParseVector2失败," + str); + //} + } + public static void ParseVector3(ref Vector3 v3, string str) + { + if (string.IsNullOrEmpty(str)) + { + v3 = Vector3.zero; + return; + } + string[] array = str.Split(',', ';', '='); + if (array.Length >= 1) + ParseFloat(ref v3.x, array[0]); + if (array.Length >= 2) + ParseFloat(ref v3.y, array[1]); + if (array.Length >= 3) + ParseFloat(ref v3.z, array[2]); + + //if (array.Length == 3) + //{ + // ParseFloat(ref v3.x, array[0]); + // ParseFloat(ref v3.y, array[1]); + // ParseFloat(ref v3.z, array[2]); + //} + //else + //{ + // LogHelper.LogError("解析ParseVector3失败," + str); + //} + } + public static void ParseVector4(ref Vector4 v4, string str) + { + if (string.IsNullOrEmpty(str)) + { + v4 = Vector4.zero; + return; + } + string[] array = str.Split(',', ';', '='); + if (array.Length >= 1) + ParseFloat(ref v4.x, array[0]); + if (array.Length >= 2) + ParseFloat(ref v4.y, array[1]); + if (array.Length >= 3) + ParseFloat(ref v4.z, array[2]); + if (array.Length >= 4) + ParseFloat(ref v4.w, array[3]); + + //if (array.Length == 4) + //{ + // ParseFloat(ref v4.x, array[0]); + // ParseFloat(ref v4.y, array[1]); + // ParseFloat(ref v4.z, array[2]); + // ParseFloat(ref v4.w, array[3]); + //} + //else + //{ + // LogHelper.LogError("解析ParseVector4失败," + str); + //} + } + + #region Json序列化 + public static Vector3 ParseVector4(string str) + { + Vector4 v = Vector4.zero; + ParseVector4(ref v, str); + return v; + } + + public static Vector3 ParseVector3(string str) + { + Vector3 v = Vector3.zero; + ParseVector3(ref v, str); + return v; + } + + public static Vector2 ParseVector2(string str) + { + Vector2 v = Vector2.zero; + ParseVector2(ref v, str); + return v; + } + + public static IntVector2 ParseIntVector2(string str) + { + IntVector2 iv2 = IntVector2.Zero; + if (string.IsNullOrEmpty(str)) + { + return iv2; + } + + string[] array = str.Split(',', ';', '='); + if (array.Length >= 1) + ParseInt(ref iv2.x, array[0]); + if (array.Length >= 2) + ParseInt(ref iv2.y, array[1]); + + return iv2; + } + + public static IntVector3 ParseIntVector3(string str) + { + IntVector3 iv3 = IntVector3.Zero; + if (string.IsNullOrEmpty(str)) + { + return iv3; + } + + string[] array = str.Split(',', ';', '='); + if (array.Length >= 1) + ParseInt(ref iv3.x, array[0]); + if (array.Length >= 2) + ParseInt(ref iv3.y, array[1]); + if (array.Length >= 3) + ParseInt(ref iv3.z, array[2]); + + return iv3; + } + + public static IntVector4 ParseIntVector4(string str) + { + IntVector4 iv4 = IntVector4.Zero; + if (string.IsNullOrEmpty(str)) + { + return iv4; + } + + string[] array = str.Split(',', ';', '='); + if (array.Length >= 1) + ParseInt(ref iv4.x, array[0]); + if (array.Length >= 2) + ParseInt(ref iv4.y, array[1]); + if (array.Length >= 3) + ParseInt(ref iv4.z, array[2]); + if (array.Length >= 4) + ParseInt(ref iv4.w, array[3]); + return iv4; + } + + public static Color ParseColor(string str) + { + Color col = Color.white; + string[] array = str.Split(',', ';', '='); + int i = array.Length; + if (i > 0) col.r = ParseFloat(array[0]); + if (i > 1) col.g = ParseFloat(array[1]); + if (i > 2) col.b = ParseFloat(array[2]); + if (i > 3) col.a = ParseFloat(array[3]); + return col; + } + + public static Color32 ParseColor32(string str) + { + Color32 col = new Color32(255,255,255,255); + string[] array = str.Split(',', ';', '='); + int i = array.Length; + if (i > 0) col.r = ParseByte(array[0]); + if (i > 1) col.g = ParseByte(array[1]); + if (i > 2) col.b = ParseByte(array[2]); + if (i > 3) col.a = ParseByte(array[3]); + return col; + } + #endregion + + public static string ToJsonByFormat(System.Object obj) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + JsonWriter jw = new JsonWriter(sb); + jw.PrettyPrint = true; + JsonMapper.ToJson(obj, jw); + return sb.ToString(); + } + } +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Common/CommonParse.cs.meta b/YesCommander/Assets/Scripts/Common/CommonParse.cs.meta new file mode 100644 index 0000000..0573243 --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/CommonParse.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d52e289ce1c1b5d4c836a2f671dca346 +timeCreated: 1543826015 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Common/Singleton.cs b/YesCommander/Assets/Scripts/Common/Singleton.cs new file mode 100644 index 0000000..86fff7a --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/Singleton.cs @@ -0,0 +1,20 @@ +using System; + +namespace YC +{ + + public class Singleton<T> where T : class, new() + { + private static T _instance; + + public static T Instance + { + get + { + if (_instance == null) + _instance = Activator.CreateInstance<T>(); + return _instance; + } + } + } +} diff --git a/YesCommander/Assets/Scripts/Common/Singleton.cs.meta b/YesCommander/Assets/Scripts/Common/Singleton.cs.meta new file mode 100644 index 0000000..9a9cdf7 --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/Singleton.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02534dc90b1e47743969d14d9386660d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Common/SingletonMB.cs b/YesCommander/Assets/Scripts/Common/SingletonMB.cs new file mode 100644 index 0000000..83575e7 --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/SingletonMB.cs @@ -0,0 +1,62 @@ +using UnityEngine; +using YC; + +namespace YC +{ + + public abstract class SingletonMB<T> : MonoBehaviour where T : class + { + protected static T m_Instance; + + public static T Instance + { + get { return m_Instance; } + set + { + if (m_Instance != null) + { + throw new System.ApplicationException("An instance was created duplicate!"); + } + + m_Instance = value; + } + } + + protected virtual void Awake() + { + //if (null != m_Instance) + //{ + // LogHelper.LogError(StringUtil.Concat("Exception: Duplicated Instance!! type is ", typeof(T).ToString(), ", plz send this error msg to hanjun!")); + //} + + m_Instance = gameObject.GetComponent<T>(); + } + + /// <summary> + /// CN: 加这个函数是为了同一个GameObject挂了多个Manager类,再OnDestroy里设置自己的单例为null + /// </summary> + protected virtual void OnDestroy() + { + //m_Instance = null; + DoWhenOnDestroy(); + } + + protected virtual void DoWhenOnDestroy() + { + + } + + public void ReleaseInstance() + { + if (m_Instance != null) + { + UnityEngine.Object.Destroy(this.gameObject); + //m_Instance = null; + } + else + { + LogHelper.LogError("m_Instance is already null!! type is " + typeof(T).ToString()); + } + } + } +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Common/SingletonMB.cs.meta b/YesCommander/Assets/Scripts/Common/SingletonMB.cs.meta new file mode 100644 index 0000000..2305ad2 --- /dev/null +++ b/YesCommander/Assets/Scripts/Common/SingletonMB.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4f80ac80ccf55c443ae18ec55cc8f37e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools.meta b/YesCommander/Assets/Scripts/Tools.meta new file mode 100644 index 0000000..27e14dd --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dfd71a1fbc824f34a8f9a3c8190c97cb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/CSVReader.cs b/YesCommander/Assets/Scripts/Tools/CSVReader.cs new file mode 100644 index 0000000..5721e8b --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/CSVReader.cs @@ -0,0 +1,147 @@ +using JetBrains.Annotations; +using LitJson; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net.Mime; +using System.Reflection; +using UnityEngine; +using yutokun; +using static UnityEngine.Rendering.DebugUI; + +namespace YC +{ + + public class CSVReader + { + private static Dictionary<string/*key*/, int/*index*/> m_KeyMapping = new Dictionary<string, int>(); + private static List<List<string>> m_Rows = new List<List<string>>(); + + /// <summary> + /// csvб + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="content"></param> + /// <returns></returns> + public static List<T> Read<T>(string content) where T : new() + { + List<T> result = new List<T>(); + Read<T>(result, content); + return result; + } + + /// <summary> + /// csv + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="content"></param> + /// <returns></returns> + public static int Read<T>(List<T> target, string content) where T : new() + { + m_KeyMapping.Clear(); + m_Rows.Clear(); + + m_Rows = CSVParser.LoadFromString(content); + // һkey + List<string> keys = m_Rows[0]; + for (int i = 0; i < keys.Count; ++i) + { + m_KeyMapping.Add(keys[i], i); + } + int count = 0; + Type type = typeof(T); + for (int i = 1; i < m_Rows.Count; ++i) + { + if (m_Rows[i] == null || m_Rows[i].Count == 0) // + continue; + + bool isBlank = true; + m_Rows[i].ForEach(s => { if (!string.IsNullOrEmpty(s)) isBlank = false; }); + if (isBlank) + continue; + + if (m_Rows[i][0].Length > 0 && m_Rows[i][0][0] == '#') // ע + continue; + + List<string> row = m_Rows[i]; + T obj = new T(); + foreach (var key in m_KeyMapping) + { + int index = key.Value; + var fieldInfo = type.GetField(key.Key); + if (fieldInfo != null) + { + Type fieldType = fieldInfo.FieldType; + if (fieldType.IsEnum) // ö٣תint + { + int value = int.Parse(row[index]); + fieldInfo.SetValue(obj, value); + } + else + { + fieldInfo.SetValue(obj, Convert.ChangeType(row[index], fieldInfo.FieldType)); + } + } + } + target.Add(obj); + count++; + } + return count; + } + + /// <summary> + /// csvkey洢ֵ + /// </summary> + /// <typeparam name="TKey"></typeparam> + /// <typeparam name="TValue"></typeparam> + /// <param name="target"></param> + /// <param name="content"></param> + /// <param name="keyName"></param> + /// <returns></returns> + public static int ReadDictionary<TKey, TValue>(Dictionary<TKey, TValue> target, string content, string keyName) where TValue : new() + { + List<TValue> data = CSVReader.Read<TValue>(content); + if (data == null || data.Count == 0) + return 0; + Type type_key = typeof(TKey); + Type type_value = typeof(TValue); + FieldInfo field = type_value.GetField(keyName); + Type type_field = field.FieldType; + int count = 0; + for (int i = 0; i < data.Count; ++i) + { + TValue d = data[i]; + + TKey key = default(TKey); + if (type_key.IsEnum) + { + if (type_field == typeof(string)) + { + key = (TKey)Enum.Parse(type_key, field.GetValue(d).ToString()); + } + else if (type_field == typeof(int)) + { + key = (TKey)field.GetValue(d); + } + } + else + { + key = (TKey)field.GetValue(d); + } + if (key == null) + { + LogHelper.LogError("CSVReader.ReadDictionary(): key is null"); + continue; + } + + target.Add(key, d); + count++; + } + return count; + } + + } + + +} diff --git a/YesCommander/Assets/Scripts/Tools/CSVReader.cs.meta b/YesCommander/Assets/Scripts/Tools/CSVReader.cs.meta new file mode 100644 index 0000000..52670ce --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/CSVReader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6b35022c04390a46beb2b27711a7950 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/ChildLocator.cs b/YesCommander/Assets/Scripts/Tools/ChildLocator.cs new file mode 100644 index 0000000..bc550ac --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/ChildLocator.cs @@ -0,0 +1,96 @@ +using System; +using UnityEngine; + +[DisallowMultipleComponent] +public class ChildLocator : MonoBehaviour +{ + [Serializable] + private struct NameTransformPair + { + public string name; + + public Transform transform; + } + + [SerializeField] + private NameTransformPair[] transformPairs = Array.Empty<NameTransformPair>(); + + public int Count => transformPairs.Length; + + public int FindChildIndex(string childName) + { + for (int i = 0; i < transformPairs.Length; i++) + { + if (childName == transformPairs[i].name) + { + return i; + } + } + return -1; + } + + public int FindChildIndex(Transform childTransform) + { + for (int i = 0; i < transformPairs.Length; i++) + { + if ((object)childTransform == transformPairs[i].transform) + { + return i; + } + } + return -1; + } + + public string FindChildName(int childIndex) + { + if ((uint)childIndex < transformPairs.Length) + { + return transformPairs[childIndex].name; + } + return null; + } + + public Transform FindChild(string childName) + { + return FindChild(FindChildIndex(childName)); + } + + public GameObject FindChildGameObject(int childIndex) + { + Transform transform = FindChild(childIndex); + if (!transform) + { + return null; + } + return transform.gameObject; + } + + public GameObject FindChildGameObject(string childName) + { + return FindChildGameObject(FindChildIndex(childName)); + } + + public Transform FindChild(int childIndex) + { + if ((uint)childIndex < transformPairs.Length) + { + return transformPairs[childIndex].transform; + } + return null; + } + + public T FindChildComponent<T>(string childName) + { + return FindChildComponent<T>(FindChildIndex(childName)); + } + + public T FindChildComponent<T>(int childIndex) + { + Transform transform = FindChild(childIndex); + if (!transform) + { + return default(T); + } + return transform.GetComponent<T>(); + } +} diff --git a/YesCommander/Assets/Scripts/Tools/ChildLocator.cs.meta b/YesCommander/Assets/Scripts/Tools/ChildLocator.cs.meta new file mode 100644 index 0000000..cb7b5a6 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/ChildLocator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c368a27551e7eb042a9e8cbb0735be81 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Commands.meta b/YesCommander/Assets/Scripts/Tools/Commands.meta new file mode 100644 index 0000000..e9f33f2 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Commands.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 43e010091f201b6468a42e7ea26b6885 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Commands/Command.cs b/YesCommander/Assets/Scripts/Tools/Commands/Command.cs new file mode 100644 index 0000000..69276ed --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Commands/Command.cs @@ -0,0 +1,50 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public abstract class Command + { + + public abstract void Execute(); + + } + + /// <summary> + /// һЩcmdҪʱ˳ִ + /// </summary> + public class CommandList + { + private List<Command> m_Commands = new List<Command>(); + + public void AddCommand(Command cmd) + { + if (cmd == null) + { + return; + } + m_Commands.Add(cmd); + } + + public void RemoveCommand(Command cmd) + { + if (cmd == null) + { + return; + } + m_Commands.Remove(cmd); + } + + public void Execute() + { + for (int i = 0; i < m_Commands.Count; ++i) + { + m_Commands[i].Execute(); + } + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/Commands/Command.cs.meta b/YesCommander/Assets/Scripts/Tools/Commands/Command.cs.meta new file mode 100644 index 0000000..651a018 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Commands/Command.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f81999dab5f39be408c8e5c5f809eddf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Commands/CommandGroup.cs b/YesCommander/Assets/Scripts/Tools/Commands/CommandGroup.cs new file mode 100644 index 0000000..2a09a0c --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Commands/CommandGroup.cs @@ -0,0 +1,96 @@ +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel.Design; +using System.Diagnostics.Tracing; +using System.Linq; +using UnityEngine; +using UnityEngine.AI; +using UnityEngine.UIElements; + +namespace YC +{ + //http://warmcat.org/chai/blog/?p=2343 + + public abstract class CommandsGroup + { + + public abstract class Command + { + public CommandID ID; + public Command(CommandID id) + { + this.ID = id; + } + /// <summary> + /// ִ + /// </summary> + public abstract void Execute(); + /// <summary> + /// עIJ + /// </summary> + /// <param name="_param"></param> + public abstract void Register(params object[] _param); + } + + protected List<Command> commandQueue = new List<Command>(); + protected void AddCommand(Command cmd) + { + commandQueue.Add(cmd); + } + + public CommandsGroup() + { + SetupCommands(); + } + + /// <summary> + /// commandQueue + /// </summary> + protected abstract void SetupCommands(); + + public void Execute() + { + foreach (Command e in commandQueue) + { + e.Execute(); + } + } + + public void RegisterParams(params object[] data) + { + if (data.Length < 1) + return; + CommandID id = (CommandID)data[0]; + int len = data.Length; + foreach (Command e in commandQueue) + { + if (e.ID == id) + { + e.Register(data.Skip(1).Take(len - 1)); + break; + } + } + } + } + + /* + /// <summary> + /// ʱִе + /// </summary> + class MainSceneLoadCommandsGroup : CommandsGroup + { + public MainSceneLoadCommandsGroup() : base() + { + // Ҫִе + + AddCommand(new OpenPanelCommand()); + // + //AddCommand(new MessageBox()); + //AddCommand(new OpenChest()); + //... + } + } + + */ + +} diff --git a/YesCommander/Assets/Scripts/Tools/Commands/CommandGroup.cs.meta b/YesCommander/Assets/Scripts/Tools/Commands/CommandGroup.cs.meta new file mode 100644 index 0000000..3df093c --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Commands/CommandGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 61d8f0e869532c64395b21a493d17a45 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/FlagManager.cs b/YesCommander/Assets/Scripts/Tools/FlagManager.cs new file mode 100644 index 0000000..cf7092d --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/FlagManager.cs @@ -0,0 +1,44 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + /// <summary> + /// ȫֱ־ + /// </summary> + public class FlagManager : Singleton<FlagManager> + { + public Dictionary<string, bool> m_Flags; + + public void AddFlag(string flag, bool value = false) + { + if(!HasFlag(flag)) + { + m_Flags.Add(flag, value); + } + } + + public bool HasFlag(string flag) + { + return m_Flags.ContainsKey(flag); + } + + public bool IsFlag(string flag) + { + if(m_Flags.ContainsKey(flag)) return false; + return m_Flags[flag]; + } + + public void RemoveFlag(string flag) + { + if(HasFlag(flag)) + { + m_Flags.Remove(flag); + } + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/FlagManager.cs.meta b/YesCommander/Assets/Scripts/Tools/FlagManager.cs.meta new file mode 100644 index 0000000..1738634 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/FlagManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2451904bd85094c40a69d59807d51c5e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/GameObjectPool.cs b/YesCommander/Assets/Scripts/Tools/GameObjectPool.cs new file mode 100644 index 0000000..667399f --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/GameObjectPool.cs @@ -0,0 +1,51 @@ +using UnityEngine; +using YC; + +namespace YC +{ + public class GameObjectPool : System.IDisposable, UnityObjectPool<GameObject>.IPooledInstanceInitializer + { + UnityObjectPool<GameObject> _pool; + Transform _poolParent; + + public GameObjectPool(GameObject sourceObject, Transform poolParent, int initialSize = 0) + { + _pool = new UnityObjectPool<GameObject>(sourceObject, poolParent, this, initialSize); + _poolParent = poolParent; + } + + public GameObject Acquire(Transform parent) + { + GameObject instance = _pool.Acquire(); + instance.transform.SetParent(parent); + instance.transform.ResetLocal(); + instance.SetActive(true); + + return instance; + } + + public void Release(GameObject instance) + { + instance.SetActive(false); + instance.transform.SetParent(_poolParent); + _pool.Release(instance); + } + + public void InitPooledInstance(GameObject instance) + { + instance.SetActive(false); + } + + public void DestroyPooledInstance(GameObject instance) + { + UnityEngine.Object.Destroy(instance); + } + + public void Dispose() + { + _pool.Dispose(); + _pool = null; + _poolParent = null; + } + } +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Tools/GameObjectPool.cs.meta b/YesCommander/Assets/Scripts/Tools/GameObjectPool.cs.meta new file mode 100644 index 0000000..d3234ce --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/GameObjectPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6df40d153f41aa446b2746e80abc19d9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/GlobalEventManager.cs b/YesCommander/Assets/Scripts/Tools/GlobalEventManager.cs new file mode 100644 index 0000000..daeccd5 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/GlobalEventManager.cs @@ -0,0 +1,97 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UIElements; + +namespace YC +{ + /// <summary> + /// ָߵȫ¼ + /// </summary> + public class GlobalEventManager : Singleton<GlobalEventManager> + { + + // callback + public delegate void EventCallback(params object[] objs); + public Dictionary<string, LinkedList<EventCallback>> AllEvents = new Dictionary<string, LinkedList<EventCallback>>(); + + public void Register(string eventName, EventCallback callback, bool addFirst = false) + { + if (callback == null) + { + Debug.LogError("Ϊ"); + return; + } + LinkedList<EventCallback> list; + if (!AllEvents.TryGetValue(eventName, out list)) + { + list = new LinkedList<EventCallback>(); // ôӳ + AllEvents.Add(eventName, list); + } + if (!list.Contains(callback)) + { + if (addFirst && list.Count > 0) + { + list.AddFirst(callback); + } + else + { + list.AddLast(callback); + } + } + else + { + Debug.LogError("ظӼ, eventName=" + eventName); + } + } + + public void UnRegister(string eventName, EventCallback callback) + { + if (callback == null) + { + Debug.LogError("Ϊ"); + return; + } + LinkedList<EventCallback> list; + if (!AllEvents.TryGetValue(eventName, out list)) + { + return; + } + list.Remove(callback); + if (list.Count == 0) + { + AllEvents.Remove(eventName); + // listǴӳõģ + } + } + + public void UnRegisterEvent(string eventName) + { + if (AllEvents.ContainsKey(eventName)) + { + AllEvents.Remove(eventName); + } + } + + public void UnRegisterAll(string eventName) + { + AllEvents.Remove(eventName); + } + + public void Notify(string eventName, params object[] objs) + { + LinkedList<EventCallback> list; + if (AllEvents.TryGetValue(eventName, out list) && list != null && list.Count > 0) + { + foreach (EventCallback callback in list) + { + if (callback != null) + { + callback.Invoke(objs); + } + } + } + } + + } +} diff --git a/YesCommander/Assets/Scripts/Tools/GlobalEventManager.cs.meta b/YesCommander/Assets/Scripts/Tools/GlobalEventManager.cs.meta new file mode 100644 index 0000000..0c2c8ec --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/GlobalEventManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a9f38c8080be5e41ad5220346ba8c7f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Info.cs b/YesCommander/Assets/Scripts/Tools/Info.cs new file mode 100644 index 0000000..54ca2b9 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Info.cs @@ -0,0 +1,41 @@ +// 滻tuple + +public class Info<T0> +{ + public T0 arg0; + + public Info(T0 arg0) + { + this.arg0 = arg0; + } +} +public class Info<T0, T1> : Info<T0> +{ + public T1 arg1; + + public Info(T0 arg0, T1 arg1) + : base(arg0) + { + this.arg1 = arg1; + } +} +public class Info<T0, T1, T2> : Info<T0, T1> +{ + public T2 arg2; + + public Info(T0 arg0, T1 arg1, T2 arg2) + : base(arg0, arg1) + { + this.arg2 = arg2; + } +} +public class Info<T0, T1, T2, T3> : Info<T0, T1, T2> +{ + public T3 arg3; + + public Info(T0 arg0, T1 arg1, T2 arg2, T3 arg3) + : base(arg0, arg1, arg2) + { + this.arg3 = arg3; + } +} diff --git a/YesCommander/Assets/Scripts/Tools/Info.cs.meta b/YesCommander/Assets/Scripts/Tools/Info.cs.meta new file mode 100644 index 0000000..4c72025 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Info.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5d784cbfaf251f4ba650732770efde9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Notification.meta b/YesCommander/Assets/Scripts/Tools/Notification.meta new file mode 100644 index 0000000..b20b283 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Notification.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 12f4a3b409f294746a9546c44272660c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Notification/NotificationCenter.cs b/YesCommander/Assets/Scripts/Tools/Notification/NotificationCenter.cs new file mode 100644 index 0000000..05affcd --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Notification/NotificationCenter.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public sealed class NotificationCenter : Singleton<NotificationCenter> + { + public delegate void NotificatonHandler(params object[] args); + + private Dictionary<string/*eventName*/, Dictionary<object/*publisher*/, List<NotificatonHandler>>> m_EventListeners = new Dictionary<string, Dictionary<object, List<NotificatonHandler>>>(); + + /// <summary> + /// ǰڵеĻص + /// </summary> + private HashSet<List<NotificatonHandler>> m_CurInvokingCallbacks = new HashSet<List<NotificatonHandler>>(); + + public void AddObserver(string notificationName, NotificatonHandler handler) + { + AddObserver(null, notificationName, handler); + } + + public void AddObserver(object sender, string notificationName, NotificatonHandler handler) + { + if (handler == null) + { + Debug.LogError("Can't add a null event handler for notification, " + notificationName); + return; + } + if (string.IsNullOrEmpty(notificationName)) + { + Debug.LogError("Can't observe an unnamed notification"); + return; + } + if (!m_EventListeners.ContainsKey(notificationName)) + { + m_EventListeners.Add(notificationName, new Dictionary<object, List<NotificatonHandler>>()); + } + Dictionary<object, List<NotificatonHandler>> dictionary = m_EventListeners[notificationName]; + object key = ((sender != null) ? sender : this); + if (!dictionary.ContainsKey(key)) + { + dictionary.Add(key, new List<NotificatonHandler>()); + } + List<NotificatonHandler> list = dictionary[key]; + if (m_CurInvokingCallbacks.Contains(list)) + { + list = (dictionary[key] = new List<NotificatonHandler>(list)); + } + list.Add(handler); + } + + public void RemoveObserver(string notificationName, NotificatonHandler handler) + { + RemoveObserver(null, notificationName, handler); + } + + public void RemoveObserver(object sender, string notificationName, NotificatonHandler handler) + { + if (handler == null) + { + Debug.LogError("Can't remove a null event handler for notification, " + notificationName); + } + else if (string.IsNullOrEmpty(notificationName)) + { + Debug.LogError("A notification name is required to stop observation"); + } + else + { + if (!m_EventListeners.ContainsKey(notificationName)) + { + return; + } + Dictionary<object, List<NotificatonHandler>> dictionary = m_EventListeners[notificationName]; + object key = ((sender != null) ? sender : this); + if (!dictionary.ContainsKey(key)) + { + return; + } + List<NotificatonHandler> list = dictionary[key]; + int num = list.IndexOf(handler); + if (num != -1) + { + if (m_CurInvokingCallbacks.Contains(list)) + { + list = (dictionary[key] = new List<NotificatonHandler>(list)); + } + list.RemoveAt(num); + } + } + } + + public void Clean() + { + string[] array = new string[m_EventListeners.Keys.Count]; + m_EventListeners.Keys.CopyTo(array, 0); + for (int num = array.Length - 1; num >= 0; num--) + { + string key = array[num]; + Dictionary<object, List<NotificatonHandler>> dictionary = m_EventListeners[key]; + object[] array2 = new object[dictionary.Keys.Count]; + dictionary.Keys.CopyTo(array2, 0); + for (int num2 = array2.Length - 1; num2 >= 0; num2--) + { + object key2 = array2[num2]; + if (dictionary[key2].Count == 0) + { + dictionary.Remove(key2); + } + } + if (dictionary.Count == 0) + { + m_EventListeners.Remove(key); + } + } + } + + public void PostNotification(string notificationName) + { + PostNotification(notificationName, null); + } + + public void PostNotification(object sender, string notificationName) + { + PostNotification(sender, notificationName, null); + } + + public void PostNotification(object sender, string notificationName, params object[] p) + { + if (string.IsNullOrEmpty(notificationName)) + { + Debug.LogError("A notification name is required"); + } + else + { + if (!m_EventListeners.ContainsKey(notificationName)) + { + return; + } + Dictionary<object, List<NotificatonHandler>> dictionary = m_EventListeners[notificationName]; + if (sender != null && dictionary.ContainsKey(sender)) + { + List<NotificatonHandler> list = dictionary[sender]; + m_CurInvokingCallbacks.Add(list); + for (int i = 0; i < list.Count; i++) + { + list[i](p); + } + m_CurInvokingCallbacks.Remove(list); + } + if (dictionary.ContainsKey(this)) + { + List<NotificatonHandler> list2 = dictionary[this]; + m_CurInvokingCallbacks.Add(list2); + for (int j = 0; j < list2.Count; j++) + { + list2[j](p); + } + m_CurInvokingCallbacks.Remove(list2); + } + } + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/Notification/NotificationCenter.cs.meta b/YesCommander/Assets/Scripts/Tools/Notification/NotificationCenter.cs.meta new file mode 100644 index 0000000..13d54ee --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Notification/NotificationCenter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f222398a57afbf446b471ccf17bb9575 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Notification/NotificationExtensions.cs b/YesCommander/Assets/Scripts/Tools/Notification/NotificationExtensions.cs new file mode 100644 index 0000000..f68f6d1 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Notification/NotificationExtensions.cs @@ -0,0 +1,19 @@ +using System; + +namespace YC +{ + + /// <summary> + /// ΪϢʵӿ + /// </summary> + public interface INotification + { + } + + public static class NotificationExtensions + { + public static void AddObserver(this INotification _this, string msg, NotificationCenter.NotificatonHandler handler) { NotificationCenter.Instance.AddObserver(_this, msg, handler); } + public static void RemoveObserver(this INotification _this, string msg, NotificationCenter.NotificatonHandler handler) { NotificationCenter.Instance.RemoveObserver(_this, msg, handler); } + public static void PostNotification(this INotification _this, string msg, params object[] p) { NotificationCenter.Instance.PostNotification(_this, msg, p); } + } +} diff --git a/YesCommander/Assets/Scripts/Tools/Notification/NotificationExtensions.cs.meta b/YesCommander/Assets/Scripts/Tools/Notification/NotificationExtensions.cs.meta new file mode 100644 index 0000000..a805d3a --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Notification/NotificationExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75fb0f8661eca5c4faf394f140fcae88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Notification/ScopedNotification.cs b/YesCommander/Assets/Scripts/Tools/Notification/ScopedNotification.cs new file mode 100644 index 0000000..c8717bf --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Notification/ScopedNotification.cs @@ -0,0 +1,92 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + /// <summary> + /// ΧϢ֪ͨ + /// </summary> + public class ScopedNotification + { + public delegate void NotificatonHandler(params object[] args); + + private Dictionary<string, List<NotificatonHandler>> m_EventListeners = new Dictionary<string, List<NotificatonHandler>>(); + + public void AddObserver(string eventName, NotificatonHandler handler) + { + if (handler == null) + { + return; + } + + if (string.IsNullOrEmpty(eventName)) + { + return; + } + + List<NotificatonHandler> handlers; + if (!m_EventListeners.ContainsKey(eventName)) + { + m_EventListeners.Add(eventName, new List<NotificatonHandler>()); + } + + handlers = m_EventListeners[eventName]; + handlers.Add(handler); + } + + public void RemoveObserver(string eventName, NotificatonHandler handler) + { + if(handler == null) { return; } + + if(string.IsNullOrEmpty(eventName)) { return; } + + if (!m_EventListeners.ContainsKey(eventName)) + return; + + List<NotificatonHandler> handlers = m_EventListeners[eventName]; + if(handlers.Contains(handler)) + handlers.Remove(handler); + } + + public void RemoveEvent(string eventName) + { + if (string.IsNullOrEmpty(eventName)) { return; } + if(m_EventListeners.ContainsKey(eventName)) + { + m_EventListeners.Remove(eventName); + } + } + + public void Clean() + { + m_EventListeners.Clear(); + } + + public void PostNotification(string eventName, params object[] args) + { + if (string.IsNullOrEmpty(eventName)) { return; } + + if (!m_EventListeners.ContainsKey(eventName)) + return; + + List<NotificatonHandler> handlers = m_EventListeners[eventName]; + for(int i = 0; i < handlers.Count; i++) + { + var handler = handlers[i]; + if(handler != null) + { + handler(args); + } + } + } + + public void PostNotification(string eventName) + { + PostNotification(eventName, null); + } + + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Tools/Notification/ScopedNotification.cs.meta b/YesCommander/Assets/Scripts/Tools/Notification/ScopedNotification.cs.meta new file mode 100644 index 0000000..4ec5672 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Notification/ScopedNotification.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 66ddfe88aa791154ea0663b56917da4a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/ObjectPool.cs b/YesCommander/Assets/Scripts/Tools/ObjectPool.cs new file mode 100644 index 0000000..73d974a --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/ObjectPool.cs @@ -0,0 +1,51 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Events; + +namespace YC +{ + class ObjectPool<T> where T : new() + { + private readonly Stack<T> m_Stack = new Stack<T>(); + private readonly UnityAction<T> m_ActionOnGet; + private readonly UnityAction<T> m_ActionOnRelease; + + public int countAll { get; private set; } + public int countActive { get { return countAll - countInactive; } } + public int countInactive { get { return m_Stack.Count; } } + + public ObjectPool(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease) + { + m_ActionOnGet = actionOnGet; + m_ActionOnRelease = actionOnRelease; + } + + public T Get() + { + T element; + if (m_Stack.Count == 0) + { + element = new T(); + countAll++; + } + else + { + element = m_Stack.Pop(); + } + if (m_ActionOnGet != null) + m_ActionOnGet(element); + return element; + } + + public void Release(T element) + { + if (m_Stack.Count > 0 && ReferenceEquals(m_Stack.Peek(), element)) + Debug.LogError("Internal error. Trying to destroy object that is already released to pool."); + if (m_ActionOnRelease != null) + m_ActionOnRelease(element); + m_Stack.Push(element); + } + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Tools/ObjectPool.cs.meta b/YesCommander/Assets/Scripts/Tools/ObjectPool.cs.meta new file mode 100644 index 0000000..b9cdb21 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/ObjectPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc1e2a929537ad04bb2ae5f26ce4ad77 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Recycle.cs b/YesCommander/Assets/Scripts/Tools/Recycle.cs new file mode 100644 index 0000000..9edb728 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Recycle.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; + +namespace YC +{ + + /// <summary> + /// ʵִ˽ӿûնijԱֵ + /// </summary> + public interface IRcycle + { + void Release(); + } + + public class Recycle<T> where T : IRcycle, new() + { + private List<T> cachedNodeList; + private int maxCapacity; + + public Recycle(int initCapacity, int maxCapacity) + { + this.maxCapacity = maxCapacity; + if (cachedNodeList == null) + { + cachedNodeList = new List<T>(initCapacity); + for (int i = 0; i < initCapacity; ++i) + { + cachedNodeList.Add(new T()); + } + } + } + + public T GetUnusedNode() + { + if (cachedNodeList.Count > 0) + { + // remove and return last node + int i = cachedNodeList.Count - 1; + T t = cachedNodeList[i]; + cachedNodeList.RemoveAt(i); + return t; + } + return new T(); + } + + //նԭΪʼֵ(0null) + public bool ReleaseNode(ref T t) + { + if (t == null) + return false; + + T refT = t; + t = default(T); + + if (cachedNodeList.Count > maxCapacity) + return false; + + if (cachedNodeList.Contains(refT)) + { + LogHelper.LogError("ظ"); + return false; + } + + refT.Release(); + cachedNodeList.Add(refT); + return true; + } + + } +} diff --git a/YesCommander/Assets/Scripts/Tools/Recycle.cs.meta b/YesCommander/Assets/Scripts/Tools/Recycle.cs.meta new file mode 100644 index 0000000..e0a21a6 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Recycle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 413419b3354bc304691bcf8c075052fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/ScopedEvent.cs b/YesCommander/Assets/Scripts/Tools/ScopedEvent.cs new file mode 100644 index 0000000..66666d0 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/ScopedEvent.cs @@ -0,0 +1,54 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.AI; + +namespace YC +{ + + /// <summary> + /// UnityEventǸ + /// </summary> + public class ScopedEvent + { + public delegate void EventHandler(params object[] args); + + private List<EventHandler> m_Handlers = new List<EventHandler>(); + + public void AddListener(EventHandler handler) + { + if(handler == null) + { + return; + } + if (m_Handlers.Contains(handler)) + return; + m_Handlers.Add(handler); + } + + public void RemoveListener(EventHandler handler) + { + + if (handler == null) + { + return; + } + m_Handlers.Remove(handler); + } + + public bool HasHandler(EventHandler handler) + { + return m_Handlers.Contains(handler); + } + + public void Invoke(params object[] args) + { + for(int i = 0; i < m_Handlers.Count; ++i) + { + m_Handlers[i](args); + } + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/ScopedEvent.cs.meta b/YesCommander/Assets/Scripts/Tools/ScopedEvent.cs.meta new file mode 100644 index 0000000..bcbce6e --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/ScopedEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 332ddd24c01402a498f667a06c63b3cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Statemachine.meta b/YesCommander/Assets/Scripts/Tools/Statemachine.meta new file mode 100644 index 0000000..77a2746 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Statemachine.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a7c937b01d531843b68e7ecf1ac0ca9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs b/YesCommander/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs new file mode 100644 index 0000000..4b34aa3 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs @@ -0,0 +1,254 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using MovementEffects; + +namespace YC +{ + + /// <summary> + /// ״̬ + /// </summary> + public class AsyncStatemachine + { + + public delegate void LoadStateComplete(); + + public abstract class State + { + public AsyncStatemachine owner; + public int stateID; // stateIDstring.GetHashCode() ṩչ + public abstract IEnumerator<float> OnStart(); + public abstract IEnumerator<float> OnEnd(); + public abstract void OnUpdate(float deltaTime); + } + + public const int NULL_STATE_ID = -1; + public const float COROUINT_DELTIME = 0.01f; + + private Dictionary<int/*stateID*/, State> allState = new Dictionary<int, State>(); + private int curStateID = NULL_STATE_ID; + private int stateIDDistributor = 0; + // ״̬лǰΪfalse,ܽupdate + private bool isUpdateActive = false; + + /// <summary> + /// ״̬״̬еID + /// </summary> + /// <param name="newState"></param> + /// <returns></returns> + public int RegisterState(State newState) + { + if (newState == null) + return NULL_STATE_ID; + if (stateIDDistributor + 1 >= int.MaxValue) + { + LogHelper.LogError("״̬״̬ʧܣ״̬ӵ״̬"); + return NULL_STATE_ID; + } + ++stateIDDistributor; + if (!allState.ContainsKey(stateIDDistributor)) + { + newState.owner = this; + newState.stateID = stateIDDistributor; + allState.Add(stateIDDistributor, newState); + return stateIDDistributor; + } + LogHelper.LogError("״̬״̬ʧܣ״̬Ѿ"); + return NULL_STATE_ID; + } + + public bool RemoveState(State state) + { + if (state != null) + { + return RemoveState(state.stateID); + } + LogHelper.LogError("״̬ɾ״̬ʧܣ״̬Ϊ"); + return false; + } + + public bool RemoveState(int stateID) + { + if (allState.ContainsKey(stateID)) + { + allState.Remove(stateID); + return true; + } + LogHelper.LogError("״̬ɾ״̬ʧܣ״̬ڣstateID = " + stateID); + return false; + } + + /// <summary> + /// ʼ״̬ + /// </summary> + /// <param name="stateID"></param> + /// <returns></returns> + public bool Start(int stateID) + { + if (!HasBegin()) + { + ForceGotoState(stateID); + return true; + } + return false; + } + + /// <summary> + /// ״̬ + /// </summary> + /// <returns></returns> + public bool Stop() + { + if (HasBegin()) + { + ForceGotoState(NULL_STATE_ID); + return true; + } + return false; + } + + /// <summary> + /// ״̬ + /// </summary> + /// <param name="deltaTime"></param> + public void Update(float deltaTime) + { + if (HasBegin()) + { + UpdateState(curStateID, deltaTime); + } + } + + public bool GotoState(int stateID, bool skipStartFunc = false, bool bForce = false, LoadStateComplete callback = null) + { + if (HasBegin()) + return ForceGotoState(stateID, skipStartFunc, bForce, callback); + return false; + } + + public bool ForceGotoState(int nextStateID, bool skipStartFunc = false, bool bForce = false, LoadStateComplete callback = null) + { + if (curStateID != nextStateID || bForce) + { + Timing.Instance.RunCoroutineOnInstance(AyncForceGotoState(nextStateID, skipStartFunc, callback)); + return true; + } + if (callback != null) + callback(); + return false; + } + + /// <summary> + /// 첽лij״̬ + /// </summary> + /// <returns></returns> + private IEnumerator<float> AyncForceGotoState(int nextStateID, bool skipStartFunc = false, LoadStateComplete callback = null) + { + isUpdateActive = false; + CoroutineHandle handle = Timing.RunCoroutine(EndState(curStateID)); + while (handle.IsRunning) + { + yield return Timing.WaitForSeconds(COROUINT_DELTIME); + } + curStateID = nextStateID; + if (!skipStartFunc) + { + CoroutineHandle handle2 = Timing.RunCoroutine(StartState(curStateID)); + while (handle2.IsRunning) + { + yield return Timing.WaitForSeconds(COROUINT_DELTIME); + } + } + if (callback != null) + callback(); + isUpdateActive = true; + } + + public int GetCurStateID() + { + return curStateID; + } + + public bool HasBegin() + { + if (curStateID != NULL_STATE_ID && allState.ContainsKey(curStateID)) + return true; + return false; + } + + public bool IsInState(int stateID) + { + if (HasBegin()) + { + return curStateID == stateID; + } + return false; + } + + public State GetState(int stateID) + { + if (allState.ContainsKey(stateID)) + { + return allState[stateID]; + } + return null; + } + + public void Clean() + { + allState.Clear(); + curStateID = NULL_STATE_ID; + stateIDDistributor = 0; + } + + public void ResetCurState() + { + curStateID = NULL_STATE_ID; + } + + private IEnumerator<float> StartState(int stateID) + { + if (HasBegin()) + { + State state = GetState(stateID); + if (state != null) + { + CoroutineHandle handle = Timing.RunCoroutine(state.OnStart()); + while (handle.IsRunning) + { + yield return Timing.WaitForSeconds(COROUINT_DELTIME); + } + } + } + } + + private IEnumerator<float> EndState(int stateID) + { + if (HasBegin()) + { + State state = GetState(stateID); + if (state != null) + { + CoroutineHandle handle = Timing.RunCoroutine(state.OnEnd()); + while (handle.IsRunning) + { + yield return Timing.WaitForSeconds(COROUINT_DELTIME); + } + } + } + } + + private void UpdateState(int stateID, float deltaTime) + { + if (HasBegin()) + { + State state = GetState(stateID); + if (state != null) + state.OnUpdate(deltaTime); + } + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs.meta b/YesCommander/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs.meta new file mode 100644 index 0000000..e2b8d49 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c43b283f086a24140b0e6e6e0e9efbef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Statemachine/BasicStatemachine.cs b/YesCommander/Assets/Scripts/Tools/Statemachine/BasicStatemachine.cs new file mode 100644 index 0000000..340fa93 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Statemachine/BasicStatemachine.cs @@ -0,0 +1,250 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; + +namespace YC +{ + /// <summary> + /// һ״̬ + /// </summary> + public class BasicStatemachine + { + public delegate void StateEvent(); + public delegate bool StateFinishChecker(); + public class State + { + public BasicStatemachine owner; + public int stateId; + + public virtual void BeginState() + { + //reserve function + } + public virtual void EndState() + { + //reserve function + } + //ʱ䵥λǺ + public virtual bool UpdateState(int deltaTimeMS) + { + return true; + } + } + + private Dictionary<int/*state id*/, State> stateDic = new Dictionary<int/*state id*/, State>(); + private int currentStateId = -1; + private int stateIdDistributor = 0; + + private int recordLastStateId = -1; + + public int RegisterState(State newState) + { + if (newState != null) + { + if (stateIdDistributor + 1 > int.MaxValue) + { + LogHelper.LogError("״̬״̬ʧܣһ״̬˹״̬"); + return -1; + } + + stateIdDistributor++; + if (!stateDic.ContainsKey(stateIdDistributor)) + { + stateDic.Add(stateIdDistributor, newState); + newState.owner = this; + newState.stateId = stateIdDistributor; + return stateIdDistributor; + } + } + LogHelper.LogError("״̬״̬ʧܣЧ״̬״̬Ѵڣ"); + return -1; + } + + public bool RemoveState(State toBeRemoveState) + { + if (toBeRemoveState != null) + return RemoveState(toBeRemoveState.stateId); + LogHelper.LogError("״̬ɾ״̬ʧܣЧ״̬"); + return false; + } + + public bool RemoveState(int stateId) + { + if (stateDic.ContainsKey(stateId)) + { + stateDic.Remove(stateId); + return true; + } + LogHelper.LogError("״̬ɾ״̬ʧܣ״̬ڣ"); + return false; + } + + public bool Begin(int beginStateId) + { + if (!HasBegin()) + { + ForceGoToState(beginStateId, false); + return true; + } + + return false; + } + + public bool Stop() + { + if (HasBegin()) + { + ForceGoToState(-1); + return true; + } + + return false; + } + + public bool GoToState(int newStateId, bool skipBeginFunc = false, bool forceLoad = false) + { + if (HasBegin()) + { + return ForceGoToState(newStateId, skipBeginFunc, forceLoad); + } + return false; + } + + private bool ForceGoToState(int newStateId) + { + return ForceGoToState(newStateId, false); + } + private bool ForceGoToState(int newStateId, bool skipBeginFunc, bool bForce = false) + { + if (currentStateId != newStateId || bForce) + { + OnStateEnd(currentStateId); + currentStateId = newStateId; + if (!skipBeginFunc) OnStateBegin(currentStateId); + return true; + } + else + { + return false; + } + } + + /// <summary> + /// + /// </summary> + /// <param name="filterState">state</param> + public void RecordCurrentState(int filterState) + { + if (currentStateId != filterState) + { + recordLastStateId = currentStateId; + } + } + + public void ClearRecordState() + { + recordLastStateId = -1; + } + + public void RevertToRecordState(int fallbackState, bool skipBeginFunc, bool bForce = false) + { + if (recordLastStateId >= 0 && stateDic.ContainsKey(recordLastStateId)) + { + GoToState(recordLastStateId, skipBeginFunc, bForce); + } + else if (fallbackState >= 0 && stateDic.ContainsKey(fallbackState)) + { + GoToState(fallbackState, skipBeginFunc, bForce); + } + } + + + //ʱ䵥λǺ + public void OnUpdate(int mSecDeltaTime) + { + if (HasBegin()) + { + UpdateState(currentStateId, mSecDeltaTime); + } + } + + public bool HasBegin() + { + if (currentStateId != -1 && stateDic.ContainsKey(currentStateId)) + return true; + else + return false; + } + + public bool IsInState(int stateId) + { + if (HasBegin()) + { + return currentStateId == stateId; + } + return false; + } + + + public int GetCurrentStateId() + { + return currentStateId; + } + + public State GetState(int stateId) + { + if (stateDic.ContainsKey(stateId)) + { + return stateDic[stateId]; + } + return null; + } + + public void Clean() + { + stateDic.Clear(); + currentStateId = -1; + stateIdDistributor = 0; + recordLastStateId = -1; + } + + /// <summary> + /// õǰ״̬(Ϊ-1) + /// </summary> + public void ResetCurrentState() + { + currentStateId = -1; + } + + private void OnStateBegin(int stateId) + { + if (HasBegin()) + { + State state = GetState(stateId); + if (state != null) + state.BeginState(); + } + } + + private void OnStateEnd(int stateId) + { + if (HasBegin()) + { + State state = GetState(stateId); + if (state != null) + state.EndState(); + } + } + //ʱ䵥λǺ + private void UpdateState(int stateId, int mSecDeltaTime) + { + if (HasBegin()) + { + State state = GetState(stateId); + if (state != null) + state.UpdateState(mSecDeltaTime); + } + } + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Tools/Statemachine/BasicStatemachine.cs.meta b/YesCommander/Assets/Scripts/Tools/Statemachine/BasicStatemachine.cs.meta new file mode 100644 index 0000000..1f9dc33 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Statemachine/BasicStatemachine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 740b9ccdbc7196546acfadecbcbd71f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Statemachine/LiteStatemachine.cs b/YesCommander/Assets/Scripts/Tools/Statemachine/LiteStatemachine.cs new file mode 100644 index 0000000..34393b0 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Statemachine/LiteStatemachine.cs @@ -0,0 +1,23 @@ +using JetBrains.Annotations; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + /// <summary> + /// ״̬ + /// </summary> + public abstract class LiteStatemachine + { + + + public void GotoState(int target) + { + + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/Statemachine/LiteStatemachine.cs.meta b/YesCommander/Assets/Scripts/Tools/Statemachine/LiteStatemachine.cs.meta new file mode 100644 index 0000000..1243aac --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Statemachine/LiteStatemachine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a8fe740cda5abcf489e9188cdd7150ce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs b/YesCommander/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs new file mode 100644 index 0000000..50da91b --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs @@ -0,0 +1,87 @@ +using System; +using System.Diagnostics; + +/// <summary> +/// 线程安全的时间流逝类 +/// 从游戏运行开始计时 +/// </summary> +public static class ThreadSafeElapsedTime +{ + private static bool _isStart = false; + private static Stopwatch _stopwatch; + private static long _curRawElapsedTicks; + private static float _curRawElapsedSeconds; + + static private double ticks2seconds = 1 / (double) TimeSpan.TicksPerSecond; + + + //必须在启动后调用 + public static void Start() + { + if (!_isStart) + { + _isStart = true; + _stopwatch = new Stopwatch(); + _stopwatch.Start(); + _curRawElapsedTicks = 0; + _curRawElapsedSeconds = 0; + } + } + + public static void Stop() + { + if (_isStart) + { + _isStart = false; + _stopwatch.Stop(); + } + } + + public static void Update() + { + if (_isStart) + { + _curRawElapsedTicks = _stopwatch.ElapsedTicks; + //_curRawElapsedSeconds = (int)(_curRawElapsedTicks / System.TimeSpan.TicksPerSecond); + _curRawElapsedSeconds = (float)(((double) _curRawElapsedTicks ) * ticks2seconds); + } + } + + /// <summary> + /// 自游戏启动以来的ticks + /// </summary> + /// <returns></returns> + public static long GetElapsedTicksSinceStartUp() + { + #if UNITY_EDITOR + Start(); + Update(); + #endif + return _curRawElapsedTicks; + } + /// <summary> + /// 自游戏启动以来的seconds + /// </summary> + /// <returns></returns> + public static float GetElapsedSecondsSinceStartUp() + { +#if UNITY_EDITOR + Start(); + Update(); +#endif + return _curRawElapsedSeconds; + } + + /// <summary> + /// 自游戏启动以来的miniseconds + /// </summary> + /// <returns></returns> + public static int GetElapsedMiniSecondsSinceStartUp() + { +#if UNITY_EDITOR + Start(); + Update(); +#endif + return (int)(_curRawElapsedSeconds * 1000); + } +} diff --git a/YesCommander/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs.meta b/YesCommander/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs.meta new file mode 100644 index 0000000..072611a --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6767239866ef68a4b841b36c5bd140b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem.meta b/YesCommander/Assets/Scripts/Tools/TriggerSystem.meta new file mode 100644 index 0000000..a6922dc --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 035c400d50feb2747bb551b48ff42f8f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem/Action.cs b/YesCommander/Assets/Scripts/Tools/TriggerSystem/Action.cs new file mode 100644 index 0000000..ad304b1 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem/Action.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public abstract class Action + { + public abstract void Execute(params object[] args); + + public virtual void Init() { } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem/Action.cs.meta b/YesCommander/Assets/Scripts/Tools/TriggerSystem/Action.cs.meta new file mode 100644 index 0000000..124d597 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem/Action.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ce0de120c2520f84492089c52286f7cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalActiveTrigger.cs b/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalActiveTrigger.cs new file mode 100644 index 0000000..4933660 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalActiveTrigger.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + /// <summary> + /// ѵʽȫ + /// </summary> + public class GlobalActiveTrigger + { + + + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalActiveTrigger.cs.meta b/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalActiveTrigger.cs.meta new file mode 100644 index 0000000..1fa37dc --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalActiveTrigger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6e06c17e867b36f4bb0b6796ed74b89b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalPassiveTrigger.cs b/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalPassiveTrigger.cs new file mode 100644 index 0000000..2ef3063 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalPassiveTrigger.cs @@ -0,0 +1,110 @@ +using System.Collections.Generic; +using System.Diagnostics.Tracing; + +namespace YC +{ + + /// <summary> + /// ¼ı + /// </summary> + public class GlobalPassiveTrigger + { + public class ConditionBase + { + public virtual bool Evaluate(params object[] args) { return false; } + + public static ConditionBase Always = new ConditionAlways(); + public static ConditionBase AlwaysNot = new ConditionAlwaysNot(); + } + + public class ConditionAlways : ConditionBase + { + public override bool Evaluate(params object[] args) + { + return true; + } + } + + public class ConditionAlwaysNot : ConditionBase + { + public override bool Evaluate(params object[] args) + { + return false; + } + } + + public class ConditionAnd : ConditionBase + { + private ConditionBase m_Left; + private ConditionBase m_Right; + public ConditionAnd(ConditionBase left, ConditionBase right) + { + m_Left = left; + m_Right = right; + } + public override bool Evaluate(params object[] args) + { + return m_Left.Evaluate(args) && m_Right.Evaluate(args); + } + } + + public class ConditionOr : ConditionBase + { + private ConditionBase m_Left; + private ConditionBase m_Right; + public ConditionOr(ConditionBase left, ConditionBase right) + { + m_Left = left; + m_Right = right; + } + public override bool Evaluate(params object[] args) + { + return m_Left.Evaluate(args) || m_Right.Evaluate(args); + } + } + + public delegate void Action(params object[] args); + + // ¼ + private string m_Event; + // + private ConditionBase m_Condition; + // + private List<Action> m_Actions = new List<Action>(); + + public void SetEvent(string eventType) + { + if (m_Event != string.Empty || m_Event != null) + { + GlobalEventManager.Instance.UnRegister(m_Event, OnEvent); + } + m_Event = eventType; + GlobalEventManager.Instance.Register(eventType, OnEvent); + } + + public void AddAction(Action action) + { + m_Actions.Add(action); + } + + public void SetCondition(ConditionBase condition) + { + m_Condition = condition; + } + + public void OnEvent(params object[] args) + { + if (m_Condition == null) + return; + if (m_Condition.Evaluate()) + { + foreach (Action action in m_Actions) + { + action.Invoke(args); + } + } + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalPassiveTrigger.cs.meta b/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalPassiveTrigger.cs.meta new file mode 100644 index 0000000..c5f1c19 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalPassiveTrigger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c3ee81c4dceea3346b4c5e7b1d371e92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem/Trigger.cs b/YesCommander/Assets/Scripts/Tools/TriggerSystem/Trigger.cs new file mode 100644 index 0000000..ab03971 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem/Trigger.cs @@ -0,0 +1,44 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + /// <summary> + /// actionOnActive()ָʱ + /// </summary> + public abstract class Trigger + { + public delegate void TriggerHandler(params object[] args); + + public event TriggerHandler handler; + + //ҪָFireTriggerʱ + public abstract void OnActive(); + + public virtual void OnDeactive() + { + } + + protected void FireTrigger(params object[] args) + { + handler?.Invoke(args); + } + + } + /* + public class OnPlayerHurt : Trigger + { + public override void OnActive() + { + UnitManager.Instance.player.AddObserver("Player.Hurt", OnPlayerHurtCallbak); + } + + private void OnPlayerHurtCallbak() + { + FireTrigger(); + } + } + */ +} diff --git a/YesCommander/Assets/Scripts/Tools/TriggerSystem/Trigger.cs.meta b/YesCommander/Assets/Scripts/Tools/TriggerSystem/Trigger.cs.meta new file mode 100644 index 0000000..08630d3 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/TriggerSystem/Trigger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93ca5bd37a4caea40ad66ea9d41f8530 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Trinary Software.meta b/YesCommander/Assets/Scripts/Tools/Trinary Software.meta new file mode 100644 index 0000000..616b6fb --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Trinary Software.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 78018ab10cd0fdf48ba17bb3bc57ed62 +folderAsset: yes +timeCreated: 1456470394 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor.meta b/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor.meta new file mode 100644 index 0000000..2e833c9 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0d53480b6fb0cb246b44b84ec5156cc6 +folderAsset: yes +timeCreated: 1475431041 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png b/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png Binary files differnew file mode 100644 index 0000000..caf3365 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png diff --git a/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png.meta b/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png.meta new file mode 100644 index 0000000..733447a --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: a0f854455b10ba44d819f36586b0909b +timeCreated: 1510247977 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 1 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 64 + textureSettings: + filterMode: 2 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 2 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf b/YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf Binary files differnew file mode 100644 index 0000000..e2f028f --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf diff --git a/YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf.meta b/YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf.meta new file mode 100644 index 0000000..4a34c89 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a2df0cfe12cb0d64c9d151d10f8ec206 +timeCreated: 1456009584 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/Trinary Software/Timing.cs b/YesCommander/Assets/Scripts/Tools/Trinary Software/Timing.cs new file mode 100644 index 0000000..6e38b0c --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Timing.cs @@ -0,0 +1,4655 @@ +using UnityEngine; +using System.Collections.Generic; +#if UNITY_EDITOR +using UnityEditor; +#endif +#if UNITY_5_5_OR_NEWER +using UnityEngine.Profiling; +#endif + +// ///////////////////////////////////////////////////////////////////////////////////////// +// More Effective Coroutines Pro +// v2.03.0 +// +// This is an improved implementation of coroutines that boasts zero per-frame memory allocations, +// runs about twice as fast as Unity's built in coroutines and has a range of extra features. +// +// For manual, support, or upgrade guide visit http://trinary.tech/ +// +// Created by Teal Rogers +// Trinary Software +// All rights preserved +// trinaryllc@gmail.com +// ///////////////////////////////////////////////////////////////////////////////////////// + +namespace MovementEffects +{ + public class Timing : MonoBehaviour + { + public enum DebugInfoType + { + None, + SeperateCoroutines, + SeperateTags + } + + /// <summary> + /// The time between calls to SlowUpdate. + /// </summary> + [Tooltip("How quickly the SlowUpdate segment ticks.")] + public float TimeBetweenSlowUpdateCalls = 1f / 7f; + /// <summary> + /// The amount that each coroutine should be seperated inside the Unity profiler. NOTE: When the profiler window + /// is not open this value is ignored and all coroutines behave as if "None" is selected. + /// </summary> + [Tooltip("How much data should be sent to the profiler window when it's open.")] + public DebugInfoType ProfilerDebugAmount = DebugInfoType.None; + /// <summary> + /// Whether the manual timeframe should automatically trigger during the update segment. + /// </summary> + [Tooltip("When using manual timeframe, should it run automatically after the update loop or only when TriggerManualTimframeUpdate is called.")] + public bool AutoTriggerManualTimeframe = true; + /// <summary> + /// The number of coroutines that are being run in the Update segment. + /// </summary> + [Tooltip("A count of the number of Update coroutines that are currently running."), Space(12)] + public int UpdateCoroutines; + /// <summary> + /// The number of coroutines that are being run in the FixedUpdate segment. + /// </summary> + [Tooltip("A count of the number of FixedUpdate coroutines that are currently running.")] + public int FixedUpdateCoroutines; + /// <summary> + /// The number of coroutines that are being run in the LateUpdate segment. + /// </summary> + [Tooltip("A count of the number of LateUpdate coroutines that are currently running.")] + public int LateUpdateCoroutines; + /// <summary> + /// The number of coroutines that are being run in the SlowUpdate segment. + /// </summary> + [Tooltip("A count of the number of SlowUpdate coroutines that are currently running.")] + public int SlowUpdateCoroutines; + /// <summary> + /// The number of coroutines that are being run in the RealtimeUpdate segment. + /// </summary> + [Tooltip("A count of the number of RealtimeUpdate coroutines that are currently running.")] + public int RealtimeUpdateCoroutines; + /// <summary> + /// The number of coroutines that are being run in the EditorUpdate segment. + /// </summary> + [Tooltip("A count of the number of EditorUpdate coroutines that are currently running.")] + public int EditorUpdateCoroutines; + /// <summary> + /// The number of coroutines that are being run in the EditorSlowUpdate segment. + /// </summary> + [Tooltip("A count of the number of EditorSlowUpdate coroutines that are currently running.")] + public int EditorSlowUpdateCoroutines; + /// <summary> + /// The number of coroutines that are being run in the EndOfFrame segment. + /// </summary> + [Tooltip("A count of the number of EndOfFrame coroutines that are currently running.")] + public int EndOfFrameCoroutines; + /// <summary> + /// The number of coroutines that are being run in the ManualTimeframe segment. + /// </summary> + [Tooltip("A count of the number of ManualTimeframe coroutines that are currently running.")] + public int ManualTimeframeCoroutines; + + /// <summary> + /// The time in seconds that the current segment has been running. + /// </summary> + [HideInInspector] + public double localTime; + /// <summary> + /// The time in seconds that the current segment has been running. + /// </summary> + public static float LocalTime { get { return (float)Instance.localTime; } } + /// <summary> + /// The amount of time in fractional seconds that elapsed between this frame and the last frame. + /// </summary> + [HideInInspector] + public float deltaTime; + /// <summary> + /// The amount of time in fractional seconds that elapsed between this frame and the last frame. + /// </summary> + public static float DeltaTime { get { return Instance.deltaTime; } } + /// <summary> + /// When defined, all errors from inside coroutines will be passed into this function instead of falling through to the Unity console. + /// </summary> + public System.Action<System.Exception> OnError; + /// <summary> + /// When defined, this function will be called every time manual timeframe needs to be set. The last manual timeframe time is passed in, and + /// the new manual timeframe time needs to be returned. If this function is left as null, manual timeframe will be set to the current Time.time. + /// </summary> + public System.Func<double, double> SetManualTimeframeTime; + /// <summary> + /// Used for advanced coroutine control. + /// </summary> + public static System.Func<IEnumerator<float>, Timing, CoroutineHandle, IEnumerator<float>> ReplacementFunction; + + private bool _runningUpdate; + private bool _runningFixedUpdate; + private bool _runningLateUpdate; + private bool _runningRealtimeUpdate; + private bool _runningEditorUpdate; + private int _nextUpdateProcessSlot; + private int _nextLateUpdateProcessSlot; + private int _nextFixedUpdateProcessSlot; + private int _nextSlowUpdateProcessSlot; + private int _nextRealtimeUpdateProcessSlot; + private int _nextEditorUpdateProcessSlot; + private int _nextEditorSlowUpdateProcessSlot; + private int _nextEndOfFrameProcessSlot; + private int _nextManualTimeframeProcessSlot; + private double _lastUpdateTime; + private double _lastLateUpdateTime; + private double _lastFixedUpdateTime; + private double _lastSlowUpdateTime; + private double _lastRealtimeUpdateTime; + private double _lastEditorUpdateTime; + private double _lastEditorSlowUpdateTime; + private double _lastManualTimeframeTime; + private ushort _framesSinceUpdate; + private ushort _expansions = 1; + private byte _instanceID; + private bool _EOFPumpRan; + + private readonly WaitForEndOfFrame _EOFWaitObject = new WaitForEndOfFrame(); + private readonly Dictionary<CoroutineHandle, HashSet<ProcessData>> _waitingTriggers = new Dictionary<CoroutineHandle, HashSet<ProcessData>>(); + private readonly Queue<System.Exception> _exceptions = new Queue<System.Exception>(); + private readonly Dictionary<CoroutineHandle, ProcessIndex> _handleToIndex = new Dictionary<CoroutineHandle, ProcessIndex>(); + private readonly Dictionary<ProcessIndex, CoroutineHandle> _indexToHandle = new Dictionary<ProcessIndex, CoroutineHandle>(); + private readonly Dictionary<ProcessIndex, string> _processTags = new Dictionary<ProcessIndex, string>(); + private readonly Dictionary<string, HashSet<ProcessIndex>> _taggedProcesses = new Dictionary<string, HashSet<ProcessIndex>>(); + private readonly Dictionary<ProcessIndex, int> _processLayers = new Dictionary<ProcessIndex, int>(); + private readonly Dictionary<int, HashSet<ProcessIndex>> _layeredProcesses = new Dictionary<int, HashSet<ProcessIndex>>(); + + private IEnumerator<float>[] UpdateProcesses = new IEnumerator<float>[InitialBufferSizeLarge]; + private IEnumerator<float>[] LateUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + private IEnumerator<float>[] FixedUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium]; + private IEnumerator<float>[] SlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium]; + private IEnumerator<float>[] RealtimeUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + private IEnumerator<float>[] EditorUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + private IEnumerator<float>[] EditorSlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + private IEnumerator<float>[] EndOfFrameProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + private IEnumerator<float>[] ManualTimeframeProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + + private volatile bool[] UpdatePaused = new bool[InitialBufferSizeLarge]; + private volatile bool[] LateUpdatePaused = new bool[InitialBufferSizeSmall]; + private volatile bool[] FixedUpdatePaused = new bool[InitialBufferSizeMedium]; + private volatile bool[] SlowUpdatePaused = new bool[InitialBufferSizeMedium]; + private volatile bool[] RealtimeUpdatePaused = new bool[InitialBufferSizeSmall]; + private volatile bool[] EditorUpdatePaused = new bool[InitialBufferSizeSmall]; + private volatile bool[] EditorSlowUpdatePaused = new bool[InitialBufferSizeSmall]; + private volatile bool[] EndOfFramePaused = new bool[InitialBufferSizeSmall]; + private volatile bool[] ManualTimeframePaused = new bool[InitialBufferSizeSmall]; + + private const ushort FramesUntilMaintenance = 64; + private const int ProcessArrayChunkSize = 64; + private const int InitialBufferSizeLarge = 256; + private const int InitialBufferSizeMedium = 64; + private const int InitialBufferSizeSmall = 8; + + private static readonly Dictionary<byte, Timing> ActiveInstances = new Dictionary<byte, Timing>(); + private static Timing _instance; + + public static Timing Instance + { + get + { + if (_instance == null || !_instance.gameObject) + { + GameObject instanceHome = GameObject.Find("Movement Effects"); + System.Type movementType = + System.Type.GetType("MovementEffects.Movement, MovementOverTime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"); + + if (instanceHome == null) + { + instanceHome = new GameObject { name = "Movement Effects" }; + DontDestroyOnLoad(instanceHome); + + if (movementType != null) + instanceHome.AddComponent(movementType); + + _instance = instanceHome.AddComponent<Timing>(); + } + else + { + if (movementType != null && instanceHome.GetComponent(movementType) == null) + instanceHome.AddComponent(movementType); + + _instance = instanceHome.GetComponent<Timing>() ?? instanceHome.AddComponent<Timing>(); + } + } + + return _instance; + } + + set { _instance = value; } + } + + void Awake() + { + if (_instance == null) + _instance = this; + else + deltaTime = Instance.deltaTime; + + _instanceID = 0x01; + while (ActiveInstances.ContainsKey(_instanceID)) + _instanceID++; + + if (_instanceID == 0x20) + { + GameObject.Destroy(gameObject); + throw new System.OverflowException("You are only allowed 31 instances of MEC at one time."); + } + + ActiveInstances.Add(_instanceID, this); + } + + void OnDestroy() + { + if (_instance == this) + _instance = null; + + ActiveInstances.Remove(_instanceID); + } + + void OnEnable() + { + if (_nextEditorUpdateProcessSlot > 0 || _nextEditorSlowUpdateProcessSlot > 0) + OnEditorStart(); + + if (_nextEndOfFrameProcessSlot > 0) + RunCoroutineSingletonOnInstance(_EOFPumpWatcher(), "MEC_EOFPumpWatcher"); + } + + void Update() + { + if (_lastSlowUpdateTime + TimeBetweenSlowUpdateCalls < ThreadSafeElapsedTime.GetElapsedSecondsSinceStartUp() && _nextSlowUpdateProcessSlot > 0) + { + ProcessIndex coindex = new ProcessIndex { seg = Segment.SlowUpdate }; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextSlowUpdateProcessSlot; coindex.i++) + { + if (!SlowUpdatePaused[coindex.i] && SlowUpdateProcesses[coindex.i] != null && !(localTime < SlowUpdateProcesses[coindex.i].Current)) + { + if (ProfilerDebugAmount != DebugInfoType.None) + { + Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine (Slow Update), " + + (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") + + (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) + : "Processing Coroutine (Slow Update)"); + } + + try + { + if (!SlowUpdateProcesses[coindex.i].MoveNext()) + { + SlowUpdateProcesses[coindex.i] = null; + } + else if (SlowUpdateProcesses[coindex.i] != null && float.IsNaN(SlowUpdateProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + SlowUpdateProcesses[coindex.i] = null; + } + else + { + SlowUpdateProcesses[coindex.i] = ReplacementFunction(SlowUpdateProcesses[coindex.i], this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + SlowUpdateProcesses[coindex.i] = null; + } + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + } + } + + if (_nextRealtimeUpdateProcessSlot > 0) + { + ProcessIndex coindex = new ProcessIndex { seg = Segment.RealtimeUpdate }; + _runningRealtimeUpdate = true; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextRealtimeUpdateProcessSlot; coindex.i++) + { + if (!RealtimeUpdatePaused[coindex.i] && RealtimeUpdateProcesses[coindex.i] != null && !(localTime < RealtimeUpdateProcesses[coindex.i].Current)) + { + if (ProfilerDebugAmount != DebugInfoType.None) + { + Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine (Realtime Update), " + + (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") + + (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) + : "Processing Coroutine (Realtime Update)"); + } + + try + { + if (!RealtimeUpdateProcesses[coindex.i].MoveNext()) + { + RealtimeUpdateProcesses[coindex.i] = null; + } + else if (RealtimeUpdateProcesses[coindex.i] != null && float.IsNaN(RealtimeUpdateProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + RealtimeUpdateProcesses[coindex.i] = null; + } + else + { + RealtimeUpdateProcesses[coindex.i] = ReplacementFunction(RealtimeUpdateProcesses[coindex.i], this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + RealtimeUpdateProcesses[coindex.i] = null; + } + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + } + + _runningRealtimeUpdate = false; + } + + if (_nextUpdateProcessSlot > 0) + { + ProcessIndex coindex = new ProcessIndex { seg = Segment.Update }; + _runningUpdate = true; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextUpdateProcessSlot; coindex.i++) + { + if (!UpdatePaused[coindex.i] && UpdateProcesses[coindex.i] != null && !(localTime < UpdateProcesses[coindex.i].Current)) + { + if (ProfilerDebugAmount != DebugInfoType.None) + { + Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine, " + + (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") + + (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) : "Processing Coroutine"); + } + + try + { + if (!UpdateProcesses[coindex.i].MoveNext()) + { + UpdateProcesses[coindex.i] = null; + } + else if (UpdateProcesses[coindex.i] != null && float.IsNaN(UpdateProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + UpdateProcesses[coindex.i] = null; + } + else + { + UpdateProcesses[coindex.i] = ReplacementFunction(UpdateProcesses[coindex.i], this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + UpdateProcesses[coindex.i] = null; + } + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + } + + _runningUpdate = false; + } + + if (AutoTriggerManualTimeframe) + { + TriggerManualTimeframeUpdate(); + } + else + { + if (++_framesSinceUpdate > FramesUntilMaintenance) + { + _framesSinceUpdate = 0; + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.BeginSample("Maintenance Task"); + + RemoveUnused(); + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + + if (_exceptions.Count > 0) + throw _exceptions.Dequeue(); + } + } + + void FixedUpdate() + { + if (_nextFixedUpdateProcessSlot > 0) + { + ProcessIndex coindex = new ProcessIndex { seg = Segment.FixedUpdate }; + _runningFixedUpdate = true; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextFixedUpdateProcessSlot; coindex.i++) + { + if (!FixedUpdatePaused[coindex.i] && FixedUpdateProcesses[coindex.i] != null && !(localTime < FixedUpdateProcesses[coindex.i].Current)) + { + if (ProfilerDebugAmount != DebugInfoType.None) + { + Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine, " + + (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") + + (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) : "Processing Coroutine"); + } + + try + { + if (!FixedUpdateProcesses[coindex.i].MoveNext()) + { + FixedUpdateProcesses[coindex.i] = null; + } + else if (FixedUpdateProcesses[coindex.i] != null && float.IsNaN(FixedUpdateProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + FixedUpdateProcesses[coindex.i] = null; + } + else + { + FixedUpdateProcesses[coindex.i] = ReplacementFunction(FixedUpdateProcesses[coindex.i], this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + FixedUpdateProcesses[coindex.i] = null; + } + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + } + + _runningFixedUpdate = false; + } + + if (_exceptions.Count > 0) + throw _exceptions.Dequeue(); + } + + void LateUpdate() + { + if (_nextLateUpdateProcessSlot > 0) + { + ProcessIndex coindex = new ProcessIndex { seg = Segment.LateUpdate }; + _runningLateUpdate = true; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextLateUpdateProcessSlot; coindex.i++) + { + if (!LateUpdatePaused[coindex.i] && LateUpdateProcesses[coindex.i] != null && !(localTime < LateUpdateProcesses[coindex.i].Current)) + { + if (ProfilerDebugAmount != DebugInfoType.None) + { + Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine, " + + (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") + + (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) : "Processing Coroutine"); + } + + try + { + if (!LateUpdateProcesses[coindex.i].MoveNext()) + { + LateUpdateProcesses[coindex.i] = null; + } + else if (LateUpdateProcesses[coindex.i] != null && float.IsNaN(LateUpdateProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + LateUpdateProcesses[coindex.i] = null; + } + else + { + LateUpdateProcesses[coindex.i] = ReplacementFunction(LateUpdateProcesses[coindex.i], this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + LateUpdateProcesses[coindex.i] = null; + } + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + } + + _runningLateUpdate = false; + } + + if (_exceptions.Count > 0) + throw _exceptions.Dequeue(); + } + + /// <summary> + /// This will trigger an update in the manual timeframe segment. If the AutoTriggerManualTimeframeDuringUpdate variable is set to true + /// then this function will be automitically called every Update, so you would normally want to set that variable to false before + /// calling this function yourself. + /// </summary> + public void TriggerManualTimeframeUpdate() + { + if (_nextManualTimeframeProcessSlot > 0) + { + ProcessIndex coindex = new ProcessIndex { seg = Segment.ManualTimeframe }; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextManualTimeframeProcessSlot; coindex.i++) + { + if (!ManualTimeframePaused[coindex.i] && ManualTimeframeProcesses[coindex.i] != null && + !(localTime < ManualTimeframeProcesses[coindex.i].Current)) + { + if (ProfilerDebugAmount != DebugInfoType.None) + { + Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine (Manual Timeframe), " + + (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") + + (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) + : "Processing Coroutine (Manual Timeframe)"); + } + + try + { + if (!ManualTimeframeProcesses[coindex.i].MoveNext()) + { + ManualTimeframeProcesses[coindex.i] = null; + } + else if (ManualTimeframeProcesses[coindex.i] != null && float.IsNaN(ManualTimeframeProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + ManualTimeframeProcesses[coindex.i] = null; + } + else + { + ManualTimeframeProcesses[coindex.i] = ReplacementFunction(ManualTimeframeProcesses[coindex.i], + this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + ManualTimeframeProcesses[coindex.i] = null; + } + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + } + } + + if (++_framesSinceUpdate > FramesUntilMaintenance) + { + _framesSinceUpdate = 0; + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.BeginSample("Maintenance Task"); + + RemoveUnused(); + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + + if (_exceptions.Count > 0) + throw _exceptions.Dequeue(); + } + + private bool OnEditorStart() + { +#if UNITY_EDITOR + if (EditorApplication.isPlayingOrWillChangePlaymode) + return false; + + if (_lastEditorUpdateTime == 0d) + _lastEditorUpdateTime = EditorApplication.timeSinceStartup; + + EditorApplication.update -= OnEditorUpdate; + + EditorApplication.update += OnEditorUpdate; + + return true; +#else + return false; +#endif + } + +#if UNITY_EDITOR + private void OnEditorUpdate() + { + if (EditorApplication.isPlayingOrWillChangePlaymode) + { + for (int i = 0; i < _nextEditorUpdateProcessSlot; i++) + EditorUpdateProcesses[i] = null; + _nextEditorUpdateProcessSlot = 0; + for (int i = 0; i < _nextEditorSlowUpdateProcessSlot; i++) + EditorSlowUpdateProcesses[i] = null; + _nextEditorSlowUpdateProcessSlot = 0; + + EditorApplication.update -= OnEditorUpdate; + _instance = null; + } + + if (_lastEditorSlowUpdateTime + TimeBetweenSlowUpdateCalls < EditorApplication.timeSinceStartup && _nextEditorSlowUpdateProcessSlot > 0) + { + ProcessIndex coindex = new ProcessIndex { seg = Segment.EditorSlowUpdate }; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextEditorSlowUpdateProcessSlot; coindex.i++) + { + if (!EditorSlowUpdatePaused[coindex.i] && EditorSlowUpdateProcesses[coindex.i] != null && + !(EditorApplication.timeSinceStartup < EditorSlowUpdateProcesses[coindex.i].Current)) + { + try + { + if (!EditorSlowUpdateProcesses[coindex.i].MoveNext()) + { + EditorSlowUpdateProcesses[coindex.i] = null; + } + else if (EditorSlowUpdateProcesses[coindex.i] != null && float.IsNaN(EditorSlowUpdateProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + EditorSlowUpdateProcesses[coindex.i] = null; + } + else + { + EditorSlowUpdateProcesses[coindex.i] = ReplacementFunction(EditorSlowUpdateProcesses[coindex.i], + this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + EditorSlowUpdateProcesses[coindex.i] = null; + } + } + } + } + + if (_nextEditorUpdateProcessSlot > 0) + { + ProcessIndex coindex = new ProcessIndex { seg = Segment.EditorUpdate }; + _runningEditorUpdate = true; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextEditorUpdateProcessSlot; coindex.i++) + { + if (!EditorUpdatePaused[coindex.i] && EditorUpdateProcesses[coindex.i] != null && + !(EditorApplication.timeSinceStartup < EditorUpdateProcesses[coindex.i].Current)) + { + try + { + if (!EditorUpdateProcesses[coindex.i].MoveNext()) + { + EditorUpdateProcesses[coindex.i] = null; + } + else if (EditorUpdateProcesses[coindex.i] != null && float.IsNaN(EditorUpdateProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + EditorUpdateProcesses[coindex.i] = null; + } + else + { + EditorUpdateProcesses[coindex.i] = ReplacementFunction(EditorUpdateProcesses[coindex.i], this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + EditorUpdateProcesses[coindex.i] = null; + } + } + } + + _runningEditorUpdate = false; + } + + if (++_framesSinceUpdate > FramesUntilMaintenance) + { + _framesSinceUpdate = 0; + + EditorRemoveUnused(); + } + + if (_exceptions.Count > 0) + throw _exceptions.Dequeue(); + } +#endif + + private IEnumerator<float> _EOFPumpWatcher() + { + while (_nextEndOfFrameProcessSlot > 0) + { + if (!_EOFPumpRan) + base.StartCoroutine(_EOFPump()); + + _EOFPumpRan = false; + + yield return 0f; + } + + _EOFPumpRan = false; + } + + private System.Collections.IEnumerator _EOFPump() + { + while (_nextEndOfFrameProcessSlot > 0) + { + yield return _EOFWaitObject; + + ProcessIndex coindex = new ProcessIndex { seg = Segment.EndOfFrame }; + _EOFPumpRan = true; + UpdateTimeValues(coindex.seg); + + for (coindex.i = 0; coindex.i < _nextEndOfFrameProcessSlot; coindex.i++) + { + if (!EndOfFramePaused[coindex.i] && EndOfFrameProcesses[coindex.i] != null && !(localTime < EndOfFrameProcesses[coindex.i].Current)) + { + if (ProfilerDebugAmount != DebugInfoType.None) + { + Profiler.BeginSample(ProfilerDebugAmount == DebugInfoType.SeperateTags ? ("Processing Coroutine, " + + (_processLayers.ContainsKey(coindex) ? "layer " + _processLayers[coindex] : "no layer") + + (_processTags.ContainsKey(coindex) ? ", tag " + _processTags[coindex] : ", no tag")) : "Processing Coroutine"); + } + + try + { + if (!EndOfFrameProcesses[coindex.i].MoveNext()) + { + EndOfFrameProcesses[coindex.i] = null; + } + else if (EndOfFrameProcesses[coindex.i] != null && float.IsNaN(EndOfFrameProcesses[coindex.i].Current)) + { + if (ReplacementFunction == null) + { + EndOfFrameProcesses[coindex.i] = null; + } + else + { + EndOfFrameProcesses[coindex.i] = ReplacementFunction(EndOfFrameProcesses[coindex.i], this, _indexToHandle[coindex]); + + ReplacementFunction = null; + coindex.i--; + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + EndOfFrameProcesses[coindex.i] = null; + } + + if (ProfilerDebugAmount != DebugInfoType.None) + Profiler.EndSample(); + } + } + } + } + + private void RemoveUnused() + { + var waitTrigsEnum = _waitingTriggers.GetEnumerator(); + while (waitTrigsEnum.MoveNext()) + { + if (waitTrigsEnum.Current.Value.Count == 0) + { + _waitingTriggers.Remove(waitTrigsEnum.Current.Key); + waitTrigsEnum = _waitingTriggers.GetEnumerator(); + continue; + } + + if (_handleToIndex.ContainsKey(waitTrigsEnum.Current.Key) && CoindexIsNull(_handleToIndex[waitTrigsEnum.Current.Key])) + { + CloseWaitingProcess(waitTrigsEnum.Current.Key); + waitTrigsEnum = _waitingTriggers.GetEnumerator(); + } + } + + ProcessIndex outer, inner; + outer.seg = inner.seg = Segment.Update; + for (outer.i = inner.i = 0; outer.i < _nextUpdateProcessSlot; outer.i++) + { + if (UpdateProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + UpdateProcesses[inner.i] = UpdateProcesses[outer.i]; + UpdatePaused[inner.i] = UpdatePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextUpdateProcessSlot; outer.i++) + { + UpdateProcesses[outer.i] = null; + UpdatePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + UpdateCoroutines = _nextUpdateProcessSlot = inner.i; + + outer.seg = inner.seg = Segment.FixedUpdate; + for (outer.i = inner.i = 0; outer.i < _nextFixedUpdateProcessSlot; outer.i++) + { + if (FixedUpdateProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + FixedUpdateProcesses[inner.i] = FixedUpdateProcesses[outer.i]; + FixedUpdatePaused[inner.i] = FixedUpdatePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextFixedUpdateProcessSlot; outer.i++) + { + FixedUpdateProcesses[outer.i] = null; + FixedUpdatePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + FixedUpdateCoroutines = _nextFixedUpdateProcessSlot = inner.i; + + outer.seg = inner.seg = Segment.LateUpdate; + for (outer.i = inner.i = 0; outer.i < _nextLateUpdateProcessSlot; outer.i++) + { + if (LateUpdateProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + LateUpdateProcesses[inner.i] = LateUpdateProcesses[outer.i]; + LateUpdatePaused[inner.i] = LateUpdatePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextLateUpdateProcessSlot; outer.i++) + { + LateUpdateProcesses[outer.i] = null; + LateUpdatePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + LateUpdateCoroutines = _nextLateUpdateProcessSlot = inner.i; + + outer.seg = inner.seg = Segment.SlowUpdate; + for (outer.i = inner.i = 0; outer.i < _nextSlowUpdateProcessSlot; outer.i++) + { + if (SlowUpdateProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + SlowUpdateProcesses[inner.i] = SlowUpdateProcesses[outer.i]; + SlowUpdatePaused[inner.i] = SlowUpdatePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextSlowUpdateProcessSlot; outer.i++) + { + SlowUpdateProcesses[outer.i] = null; + SlowUpdatePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + SlowUpdateCoroutines = _nextSlowUpdateProcessSlot = inner.i; + + outer.seg = inner.seg = Segment.RealtimeUpdate; + for (outer.i = inner.i = 0; outer.i < _nextRealtimeUpdateProcessSlot; outer.i++) + { + if (RealtimeUpdateProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + RealtimeUpdateProcesses[inner.i] = RealtimeUpdateProcesses[outer.i]; + RealtimeUpdatePaused[inner.i] = RealtimeUpdatePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextRealtimeUpdateProcessSlot; outer.i++) + { + RealtimeUpdateProcesses[outer.i] = null; + RealtimeUpdatePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + RealtimeUpdateCoroutines = _nextRealtimeUpdateProcessSlot = inner.i; + + outer.seg = inner.seg = Segment.EndOfFrame; + for (outer.i = inner.i = 0; outer.i < _nextEndOfFrameProcessSlot; outer.i++) + { + if (EndOfFrameProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + EndOfFrameProcesses[inner.i] = EndOfFrameProcesses[outer.i]; + EndOfFramePaused[inner.i] = EndOfFramePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextEndOfFrameProcessSlot; outer.i++) + { + EndOfFrameProcesses[outer.i] = null; + EndOfFramePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + EndOfFrameCoroutines = _nextEndOfFrameProcessSlot = inner.i; + + outer.seg = inner.seg = Segment.ManualTimeframe; + for (outer.i = inner.i = 0; outer.i < _nextManualTimeframeProcessSlot; outer.i++) + { + if (ManualTimeframeProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + ManualTimeframeProcesses[inner.i] = ManualTimeframeProcesses[outer.i]; + ManualTimeframePaused[inner.i] = ManualTimeframePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextManualTimeframeProcessSlot; outer.i++) + { + ManualTimeframeProcesses[outer.i] = null; + ManualTimeframePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + ManualTimeframeCoroutines = _nextManualTimeframeProcessSlot = inner.i; + } + + private void EditorRemoveUnused() + { + var waitTrigsEnum = _waitingTriggers.GetEnumerator(); + while (waitTrigsEnum.MoveNext()) + { + if (_handleToIndex.ContainsKey(waitTrigsEnum.Current.Key) && CoindexIsNull(_handleToIndex[waitTrigsEnum.Current.Key])) + { + CloseWaitingProcess(waitTrigsEnum.Current.Key); + waitTrigsEnum = _waitingTriggers.GetEnumerator(); + } + } + + ProcessIndex outer, inner; + outer.seg = inner.seg = Segment.EditorUpdate; + for (outer.i = inner.i = 0; outer.i < _nextEditorUpdateProcessSlot; outer.i++) + { + if (EditorUpdateProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + EditorUpdateProcesses[inner.i] = EditorUpdateProcesses[outer.i]; + EditorUpdatePaused[inner.i] = EditorUpdatePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextEditorUpdateProcessSlot; outer.i++) + { + EditorUpdateProcesses[outer.i] = null; + EditorUpdatePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + EditorUpdateCoroutines = _nextEditorUpdateProcessSlot = inner.i; + + outer.seg = inner.seg = Segment.EditorSlowUpdate; + for (outer.i = inner.i = 0; outer.i < _nextEditorSlowUpdateProcessSlot; outer.i++) + { + if (EditorSlowUpdateProcesses[outer.i] != null) + { + if (outer.i != inner.i) + { + EditorSlowUpdateProcesses[inner.i] = EditorSlowUpdateProcesses[outer.i]; + EditorUpdatePaused[inner.i] = EditorUpdatePaused[outer.i]; + MoveGraffiti(outer, inner); + } + inner.i++; + } + } + for (outer.i = inner.i; outer.i < _nextEditorSlowUpdateProcessSlot; outer.i++) + { + EditorSlowUpdateProcesses[outer.i] = null; + EditorSlowUpdatePaused[outer.i] = false; + RemoveGraffiti(outer); + } + + EditorSlowUpdateCoroutines = _nextEditorSlowUpdateProcessSlot = inner.i; + } + + /// <summary> + /// Retrieves the MEC manager that corresponds to the supplied instance id. + /// </summary> + /// <param name="ID">The instance ID.</param> + /// <returns>The manager, or null if not found.</returns> + public static Timing GetInstance(byte ID) + { + return ActiveInstances.ContainsKey(ID) ? ActiveInstances[ID] : null; + } + + /// <summary> + /// Run a new coroutine in the Update segment. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, Segment.Update, null, null, new CoroutineHandle(Instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, string tag) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, Segment.Update, null, tag, new CoroutineHandle(Instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, int layer) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, Segment.Update, layer, null, new CoroutineHandle(Instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, int layer, string tag) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(Instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment timing) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, timing, null, null, new CoroutineHandle(Instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment timing, string tag) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, timing, null, tag, new CoroutineHandle(Instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment timing, int layer) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, timing, layer, null, new CoroutineHandle(Instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public static CoroutineHandle RunCoroutine(IEnumerator<float> coroutine, Segment timing, int layer, string tag) + { + return coroutine == null ? new CoroutineHandle() + : Instance.RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(Instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine on this Timing instance in the Update segment. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, Segment.Update, null, null, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine on this Timing instance in the Update segment. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, string tag) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, Segment.Update, null, tag, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine on this Timing instance in the Update segment. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, int layer) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, Segment.Update, layer, null, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine on this Timing instance in the Update segment. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, int layer, string tag) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine on this Timing instance. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment timing) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, timing, null, null, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine on this Timing instance. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment timing, string tag) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, timing, null, tag, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine on this Timing instance. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment timing, int layer) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, timing, layer, null, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine on this Timing instance. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="layer">An optional layer to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <param name="tag">An optional tag to attach to the coroutine which can later be used to identify this coroutine.</param> + /// <returns>The coroutine's handle, which can be used for Wait and Kill operations.</returns> + public CoroutineHandle RunCoroutineOnInstance(IEnumerator<float> coroutine, Segment timing, int layer, string tag) + { + return coroutine == null ? new CoroutineHandle() + : RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, string tag, bool overwrite = false) + { + if (_instance == null || coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(tag); + } + else if (_instance._taggedProcesses.ContainsKey(tag)) + { + var indexEnum = _instance._taggedProcesses[tag].GetEnumerator(); + if (indexEnum.MoveNext()) + return _instance._indexToHandle[indexEnum.Current]; + } + + return _instance.RunCoroutineInternal(coroutine, Segment.Update, null, tag, new CoroutineHandle(_instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, int layer, bool overwrite = false) + { + if (_instance == null || coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(layer); + } + else if (_instance._layeredProcesses.ContainsKey(layer)) + { + var indexEnum = _instance._layeredProcesses[layer].GetEnumerator(); + if (indexEnum.MoveNext()) + return _instance._indexToHandle[indexEnum.Current]; + } + + return _instance.RunCoroutineInternal(coroutine, Segment.Update, layer, null, new CoroutineHandle(_instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param> + /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, int layer, string tag, bool overwrite = false) + { + if (_instance == null || coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(layer, tag); + return _instance.RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instance._instanceID), true); + } + + if (!_instance._taggedProcesses.ContainsKey(tag) || !_instance._layeredProcesses.ContainsKey(layer)) + return _instance.RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instance._instanceID), true); + + var matchesEnum = _instance._taggedProcesses[tag].GetEnumerator(); + while (matchesEnum.MoveNext()) + if (_instance._processLayers.ContainsKey(matchesEnum.Current) && _instance._processLayers[matchesEnum.Current] == layer) + return _instance._indexToHandle[matchesEnum.Current]; + + return _instance.RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, Segment timing, int layer, bool overwrite = false) + { + if (_instance == null || coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(layer); + } + else if (_instance._layeredProcesses.ContainsKey(layer)) + { + var indexEnum = _instance._layeredProcesses[layer].GetEnumerator(); + if (indexEnum.MoveNext()) + return _instance._indexToHandle[indexEnum.Current]; + } + + return _instance.RunCoroutineInternal(coroutine, timing, layer, null, new CoroutineHandle(_instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, Segment timing, string tag, bool overwrite = false) + { + if (_instance == null || coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(tag); + } + else if (_instance._taggedProcesses.ContainsKey(tag)) + { + var indexEnum = _instance._taggedProcesses[tag].GetEnumerator(); + if (indexEnum.MoveNext()) + return _instance._indexToHandle[indexEnum.Current]; + } + + return _instance.RunCoroutineInternal(coroutine, timing, null, tag, new CoroutineHandle(_instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param> + /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public static CoroutineHandle RunCoroutineSingleton(IEnumerator<float> coroutine, Segment timing, int layer, string tag, bool overwrite = false) + { + if (_instance == null || coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(layer, tag); + return _instance.RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instance._instanceID), true); + } + + if (!_instance._taggedProcesses.ContainsKey(tag) || !_instance._layeredProcesses.ContainsKey(layer)) + return _instance.RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instance._instanceID), true); + + var matchesEnum = _instance._taggedProcesses[tag].GetEnumerator(); + while (matchesEnum.MoveNext()) + if (_instance._processLayers.ContainsKey(matchesEnum.Current) && _instance._processLayers[matchesEnum.Current] == layer) + return _instance._indexToHandle[matchesEnum.Current]; + + return _instance.RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instance._instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, int layer, bool overwrite = false) + { + if (coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(layer); + } + else if (_layeredProcesses.ContainsKey(layer)) + { + var indexEnum = _layeredProcesses[layer].GetEnumerator(); + if (indexEnum.MoveNext()) + return _indexToHandle[indexEnum.Current]; + } + + return RunCoroutineInternal(coroutine, Segment.Update, layer, null, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, string tag, bool overwrite = false) + { + if (coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(tag); + } + else if (_taggedProcesses.ContainsKey(tag)) + { + var indexEnum = _taggedProcesses[tag].GetEnumerator(); + if (indexEnum.MoveNext()) + return _indexToHandle[indexEnum.Current]; + } + + return RunCoroutineInternal(coroutine, Segment.Update, null, tag, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine in the Update segment with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param> + /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, int layer, string tag, bool overwrite = false) + { + if (coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(layer, tag); + return RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instanceID), true); + } + + if (!_taggedProcesses.ContainsKey(tag) || !_layeredProcesses.ContainsKey(layer)) + return RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instanceID), true); + + var matchesEnum = _taggedProcesses[tag].GetEnumerator(); + while (matchesEnum.MoveNext()) + if (_processLayers.ContainsKey(matchesEnum.Current) && _processLayers[matchesEnum.Current] == layer) + return _indexToHandle[matchesEnum.Current]; + + return RunCoroutineInternal(coroutine, Segment.Update, layer, tag, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, Segment timing, int layer, bool overwrite = false) + { + if (coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(layer); + } + else if (_layeredProcesses.ContainsKey(layer)) + { + var indexEnum = _layeredProcesses[layer].GetEnumerator(); + if (indexEnum.MoveNext()) + return _indexToHandle[indexEnum.Current]; + } + + return RunCoroutineInternal(coroutine, timing, layer, null, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, Segment timing, string tag, bool overwrite = false) + { + if (coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(tag); + } + else if (_taggedProcesses.ContainsKey(tag)) + { + var indexEnum = _taggedProcesses[tag].GetEnumerator(); + if (indexEnum.MoveNext()) + return _indexToHandle[indexEnum.Current]; + } + + return RunCoroutineInternal(coroutine, timing, null, tag, new CoroutineHandle(_instanceID), true); + } + + /// <summary> + /// Run a new coroutine with the supplied tag unless there is already one or more coroutines running with that tag. + /// </summary> + /// <param name="coroutine">The new coroutine's handle.</param> + /// <param name="timing">The segment that the coroutine should run in.</param> + /// <param name="layer">A layer to attach to the coroutine, and to check for existing instances.</param> + /// <param name="tag">A tag to attach to the coroutine, and to check for existing instances.</param> + /// <param name="overwrite">True will kill any pre-existing coroutines. False will only start this coroutine if none exist.</param> + /// <returns>The newly created or existing handle.</returns> + public CoroutineHandle RunCoroutineSingletonOnInstance(IEnumerator<float> coroutine, Segment timing, int layer, string tag, bool overwrite = false) + { + if (coroutine == null) + return new CoroutineHandle(); + + if (overwrite) + { + KillCoroutines(layer, tag); + return RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instanceID), true); + } + + if (!_taggedProcesses.ContainsKey(tag) || !_layeredProcesses.ContainsKey(layer)) + return RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instanceID), true); + + var matchesEnum = _taggedProcesses[tag].GetEnumerator(); + while (matchesEnum.MoveNext()) + if (_processLayers.ContainsKey(matchesEnum.Current) && _processLayers[matchesEnum.Current] == layer) + return _indexToHandle[matchesEnum.Current]; + + return RunCoroutineInternal(coroutine, timing, layer, tag, new CoroutineHandle(_instanceID), true); + } + + private CoroutineHandle RunCoroutineInternal(IEnumerator<float> coroutine, Segment timing, int? layer, string tag, CoroutineHandle handle, bool prewarm) + { + ProcessIndex slot = new ProcessIndex { seg = timing }; + + if (_handleToIndex.ContainsKey(handle)) + { + _indexToHandle.Remove(_handleToIndex[handle]); + _handleToIndex.Remove(handle); + } + + switch (timing) + { + case Segment.Update: + + if (_nextUpdateProcessSlot >= UpdateProcesses.Length) + { + IEnumerator<float>[] oldProcArray = UpdateProcesses; + bool[] oldPausedArray = UpdatePaused; + + UpdateProcesses = new IEnumerator<float>[UpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + UpdatePaused = new bool[UpdateProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + UpdateProcesses[i] = oldProcArray[i]; + UpdatePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextUpdateProcessSlot++; + UpdateProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + if (!_runningUpdate && prewarm) + { + try + { + _runningUpdate = true; + SetTimeValues(slot.seg); + + if (UpdateProcesses[slot.i] != null && !UpdateProcesses[slot.i].MoveNext()) + { + UpdateProcesses[slot.i] = null; + } + else if (UpdateProcesses[slot.i] != null && float.IsNaN(UpdateProcesses[slot.i].Current)) + { + if (ReplacementFunction == null) + { + UpdateProcesses[slot.i] = null; + } + else + { + UpdateProcesses[slot.i] = ReplacementFunction(UpdateProcesses[slot.i], this, _indexToHandle[slot]); + + ReplacementFunction = null; + + if (UpdateProcesses[slot.i] != null) + UpdateProcesses[slot.i].MoveNext(); + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + UpdateProcesses[slot.i] = null; + } + finally + { + _runningUpdate = false; + } + } + + return handle; + + case Segment.FixedUpdate: + + if (_nextFixedUpdateProcessSlot >= FixedUpdateProcesses.Length) + { + IEnumerator<float>[] oldProcArray = FixedUpdateProcesses; + bool[] oldPausedArray = FixedUpdatePaused; + + FixedUpdateProcesses = new IEnumerator<float>[FixedUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + FixedUpdatePaused = new bool[FixedUpdateProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + FixedUpdateProcesses[i] = oldProcArray[i]; + FixedUpdatePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextFixedUpdateProcessSlot++; + FixedUpdateProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + if (!_runningFixedUpdate && prewarm) + { + try + { + _runningFixedUpdate = true; + SetTimeValues(slot.seg); + + if (FixedUpdateProcesses[slot.i] != null && !FixedUpdateProcesses[slot.i].MoveNext()) + { + FixedUpdateProcesses[slot.i] = null; + } + else if (FixedUpdateProcesses[slot.i] != null && float.IsNaN(FixedUpdateProcesses[slot.i].Current)) + { + if (ReplacementFunction == null) + { + FixedUpdateProcesses[slot.i] = null; + } + else + { + FixedUpdateProcesses[slot.i] = ReplacementFunction(FixedUpdateProcesses[slot.i], this, _indexToHandle[slot]); + + ReplacementFunction = null; + + if (FixedUpdateProcesses[slot.i] != null) + FixedUpdateProcesses[slot.i].MoveNext(); + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + FixedUpdateProcesses[slot.i] = null; + } + finally + { + _runningFixedUpdate = false; + } + } + + return handle; + + case Segment.LateUpdate: + + if (_nextLateUpdateProcessSlot >= LateUpdateProcesses.Length) + { + IEnumerator<float>[] oldProcArray = LateUpdateProcesses; + bool[] oldPausedArray = LateUpdatePaused; + + LateUpdateProcesses = new IEnumerator<float>[LateUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + LateUpdatePaused = new bool[LateUpdateProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + LateUpdateProcesses[i] = oldProcArray[i]; + LateUpdatePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextLateUpdateProcessSlot++; + LateUpdateProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + if (!_runningLateUpdate && prewarm) + { + try + { + _runningLateUpdate = true; + SetTimeValues(slot.seg); + + if (LateUpdateProcesses[slot.i] != null && !LateUpdateProcesses[slot.i].MoveNext()) + { + LateUpdateProcesses[slot.i] = null; + } + else if (LateUpdateProcesses[slot.i] != null && float.IsNaN(LateUpdateProcesses[slot.i].Current)) + { + if (ReplacementFunction == null) + { + LateUpdateProcesses[slot.i] = null; + } + else + { + LateUpdateProcesses[slot.i] = ReplacementFunction(LateUpdateProcesses[slot.i], + this, _indexToHandle[slot]); + + ReplacementFunction = null; + + if (LateUpdateProcesses[slot.i] != null) + LateUpdateProcesses[slot.i].MoveNext(); + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + LateUpdateProcesses[slot.i] = null; + } + finally + { + _runningLateUpdate = false; + } + } + + return handle; + + case Segment.SlowUpdate: + + if (_nextSlowUpdateProcessSlot >= SlowUpdateProcesses.Length) + { + IEnumerator<float>[] oldProcArray = SlowUpdateProcesses; + bool[] oldPausedArray = SlowUpdatePaused; + + SlowUpdateProcesses = new IEnumerator<float>[SlowUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + SlowUpdatePaused = new bool[SlowUpdateProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + SlowUpdateProcesses[i] = oldProcArray[i]; + SlowUpdatePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextSlowUpdateProcessSlot++; + SlowUpdateProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + return handle; + + case Segment.RealtimeUpdate: + + if (_nextRealtimeUpdateProcessSlot >= RealtimeUpdateProcesses.Length) + { + IEnumerator<float>[] oldProcArray = RealtimeUpdateProcesses; + bool[] oldPausedArray = RealtimeUpdatePaused; + + RealtimeUpdateProcesses = new IEnumerator<float>[RealtimeUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + RealtimeUpdatePaused = new bool[RealtimeUpdateProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + RealtimeUpdateProcesses[i] = oldProcArray[i]; + RealtimeUpdatePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextRealtimeUpdateProcessSlot++; + RealtimeUpdateProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + if (!_runningRealtimeUpdate && prewarm) + { + try + { + _runningRealtimeUpdate = true; + SetTimeValues(slot.seg); + + if (RealtimeUpdateProcesses[slot.i] != null && !RealtimeUpdateProcesses[slot.i].MoveNext()) + { + RealtimeUpdateProcesses[slot.i] = null; + } + else if (RealtimeUpdateProcesses[slot.i] != null && float.IsNaN(RealtimeUpdateProcesses[slot.i].Current)) + { + if (ReplacementFunction == null) + { + RealtimeUpdateProcesses[slot.i] = null; + } + else + { + RealtimeUpdateProcesses[slot.i] = ReplacementFunction(RealtimeUpdateProcesses[slot.i], + this, _indexToHandle[slot]); + + ReplacementFunction = null; + + if (RealtimeUpdateProcesses[slot.i] != null) + RealtimeUpdateProcesses[slot.i].MoveNext(); + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + RealtimeUpdateProcesses[slot.i] = null; + } + finally + { + _runningRealtimeUpdate = false; + } + } + + return handle; + + case Segment.EditorUpdate: + + if (!OnEditorStart()) + return new CoroutineHandle(); + + if (_nextEditorUpdateProcessSlot >= EditorUpdateProcesses.Length) + { + IEnumerator<float>[] oldProcArray = EditorUpdateProcesses; + bool[] oldPausedArray = EditorUpdatePaused; + + EditorUpdateProcesses = new IEnumerator<float>[EditorUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + EditorUpdatePaused = new bool[EditorUpdateProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + EditorUpdateProcesses[i] = oldProcArray[i]; + EditorUpdatePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextEditorUpdateProcessSlot++; + EditorUpdateProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + if (!_runningEditorUpdate && prewarm) + { + try + { + _runningEditorUpdate = true; + SetTimeValues(slot.seg); + + if (EditorUpdateProcesses[slot.i] != null && !EditorUpdateProcesses[slot.i].MoveNext()) + { + EditorUpdateProcesses[slot.i] = null; + } + else if (EditorUpdateProcesses[slot.i] != null && float.IsNaN(EditorUpdateProcesses[slot.i].Current)) + { + if (ReplacementFunction == null) + { + EditorUpdateProcesses[slot.i] = null; + } + else + { + EditorUpdateProcesses[slot.i] = ReplacementFunction(EditorUpdateProcesses[slot.i], + this, _indexToHandle[slot]); + + ReplacementFunction = null; + + if (EditorUpdateProcesses[slot.i] != null) + EditorUpdateProcesses[slot.i].MoveNext(); + } + } + } + catch (System.Exception ex) + { + if (OnError == null) + _exceptions.Enqueue(ex); + else + OnError(ex); + + EditorUpdateProcesses[slot.i] = null; + } + finally + { + _runningEditorUpdate = false; + } + } + + return handle; + + case Segment.EditorSlowUpdate: + + if (!OnEditorStart()) + return new CoroutineHandle(); + + if (_nextEditorSlowUpdateProcessSlot >= EditorSlowUpdateProcesses.Length) + { + IEnumerator<float>[] oldProcArray = EditorSlowUpdateProcesses; + bool[] oldPausedArray = EditorSlowUpdatePaused; + + EditorSlowUpdateProcesses = new IEnumerator<float>[EditorSlowUpdateProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + EditorSlowUpdatePaused = new bool[EditorSlowUpdateProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + EditorSlowUpdateProcesses[i] = oldProcArray[i]; + EditorSlowUpdatePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextEditorSlowUpdateProcessSlot++; + EditorSlowUpdateProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + return handle; + + case Segment.EndOfFrame: + + if (_nextEndOfFrameProcessSlot >= EndOfFrameProcesses.Length) + { + IEnumerator<float>[] oldProcArray = EndOfFrameProcesses; + bool[] oldPausedArray = EndOfFramePaused; + + EndOfFrameProcesses = new IEnumerator<float>[EndOfFrameProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + EndOfFramePaused = new bool[EndOfFrameProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + EndOfFrameProcesses[i] = oldProcArray[i]; + EndOfFramePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextEndOfFrameProcessSlot++; + EndOfFrameProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + RunCoroutineSingletonOnInstance(_EOFPumpWatcher(), "MEC_EOFPumpWatcher"); + + return handle; + + case Segment.ManualTimeframe: + + if (_nextManualTimeframeProcessSlot >= ManualTimeframeProcesses.Length) + { + IEnumerator<float>[] oldProcArray = ManualTimeframeProcesses; + bool[] oldPausedArray = ManualTimeframePaused; + + ManualTimeframeProcesses = new IEnumerator<float>[ManualTimeframeProcesses.Length + (ProcessArrayChunkSize * _expansions++)]; + ManualTimeframePaused = new bool[ManualTimeframeProcesses.Length]; + + for (int i = 0; i < oldProcArray.Length; i++) + { + ManualTimeframeProcesses[i] = oldProcArray[i]; + ManualTimeframePaused[i] = oldPausedArray[i]; + } + } + + slot.i = _nextManualTimeframeProcessSlot++; + ManualTimeframeProcesses[slot.i] = coroutine; + + if (null != tag) + AddTag(tag, slot); + + if (layer.HasValue) + AddLayer((int)layer, slot); + + _indexToHandle.Add(slot, handle); + _handleToIndex.Add(handle, slot); + + return handle; + + default: + return new CoroutineHandle(); + } + } + + /// <summary> + /// This will kill all coroutines running on the main MEC instance and reset the context. + /// </summary> + /// <returns>The number of coroutines that were killed.</returns> + public static int KillCoroutines() + { + return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(); + } + + /// <summary> + /// This will kill all coroutines running on the current MEC instance and reset the context. + /// </summary> + /// <returns>The number of coroutines that were killed.</returns> + public int KillCoroutinesOnInstance() + { + int retVal = _nextUpdateProcessSlot + _nextLateUpdateProcessSlot + _nextFixedUpdateProcessSlot + _nextSlowUpdateProcessSlot + + _nextRealtimeUpdateProcessSlot + _nextEditorUpdateProcessSlot + _nextEditorSlowUpdateProcessSlot + + _nextEndOfFrameProcessSlot + _nextManualTimeframeProcessSlot; + + UpdateProcesses = new IEnumerator<float>[InitialBufferSizeLarge]; + UpdatePaused = new bool[InitialBufferSizeLarge]; + UpdateCoroutines = 0; + _nextUpdateProcessSlot = 0; + + LateUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + LateUpdatePaused = new bool[InitialBufferSizeSmall]; + LateUpdateCoroutines = 0; + _nextLateUpdateProcessSlot = 0; + + FixedUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium]; + FixedUpdatePaused = new bool[InitialBufferSizeMedium]; + FixedUpdateCoroutines = 0; + _nextFixedUpdateProcessSlot = 0; + + SlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeMedium]; + SlowUpdatePaused = new bool[InitialBufferSizeMedium]; + SlowUpdateCoroutines = 0; + _nextSlowUpdateProcessSlot = 0; + + RealtimeUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + RealtimeUpdatePaused = new bool[InitialBufferSizeSmall]; + RealtimeUpdateCoroutines = 0; + _nextRealtimeUpdateProcessSlot = 0; + + EditorUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + EditorUpdatePaused = new bool[InitialBufferSizeSmall]; + EditorUpdateCoroutines = 0; + _nextEditorUpdateProcessSlot = 0; + + EditorSlowUpdateProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + EditorSlowUpdatePaused = new bool[InitialBufferSizeSmall]; + EditorSlowUpdateCoroutines = 0; + _nextEditorSlowUpdateProcessSlot = 0; + + EndOfFrameProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + EndOfFramePaused = new bool[InitialBufferSizeSmall]; + EndOfFrameCoroutines = 0; + _nextEndOfFrameProcessSlot = 0; + + ManualTimeframeProcesses = new IEnumerator<float>[InitialBufferSizeSmall]; + ManualTimeframePaused = new bool[InitialBufferSizeSmall]; + ManualTimeframeCoroutines = 0; + _nextManualTimeframeProcessSlot = 0; + + _processTags.Clear(); + _taggedProcesses.Clear(); + _processLayers.Clear(); + _layeredProcesses.Clear(); + _handleToIndex.Clear(); + _indexToHandle.Clear(); + _waitingTriggers.Clear(); + _expansions = (ushort)((_expansions / 2) + 1); + + ResetTimeCountOnInstance(); + +#if UNITY_EDITOR + EditorApplication.update -= OnEditorUpdate; +#endif + return retVal; + } + + /// <summary> + /// Kills all coroutines that have the given tag. + /// </summary> + /// <param name="tag">All coroutines with this tag will be killed.</param> + /// <returns>The number of coroutines that were found and killed.</returns> + public static int KillCoroutines(string tag) + { + return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(tag); + } + + /// <summary> + /// Kills all coroutines that have the given tag. + /// </summary> + /// <param name="tag">All coroutines with this tag will be killed.</param> + /// <returns>The number of coroutines that were found and killed.</returns> + public int KillCoroutinesOnInstance(string tag) + { + if (tag == null) return 0; + int numberFound = 0; + + while (_taggedProcesses.ContainsKey(tag)) + { + var matchEnum = _taggedProcesses[tag].GetEnumerator(); + matchEnum.MoveNext(); + + if (CoindexKill(matchEnum.Current)) + { + if (_waitingTriggers.ContainsKey(_indexToHandle[matchEnum.Current])) + CloseWaitingProcess(_indexToHandle[matchEnum.Current]); + + numberFound++; + } + + RemoveGraffiti(matchEnum.Current); + } + + return numberFound; + } + + /// <summary> + /// Kills all coroutines on the given layer. + /// </summary> + /// <param name="layer">All coroutines on this layer will be killed.</param> + /// <returns>The number of coroutines that were found and killed.</returns> + public static int KillCoroutines(int layer) + { + return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(layer); + } + + /// <summary> + /// Kills all coroutines on the given layer. + /// </summary> + /// <param name="layer">All coroutines on this layer will be killed.</param> + /// <returns>The number of coroutines that were found and killed.</returns> + public int KillCoroutinesOnInstance(int layer) + { + int numberFound = 0; + + while (_layeredProcesses.ContainsKey(layer)) + { + var matchEnum = _layeredProcesses[layer].GetEnumerator(); + matchEnum.MoveNext(); + + if (CoindexKill(matchEnum.Current)) + { + if (_waitingTriggers.ContainsKey(_indexToHandle[matchEnum.Current])) + CloseWaitingProcess(_indexToHandle[matchEnum.Current]); + + numberFound++; + } + + RemoveGraffiti(matchEnum.Current); + } + + return numberFound; + } + + /// <summary> + /// Kills all coroutines with the given tag on the given layer. + /// </summary> + /// <param name="layer">All coroutines on this layer with the given tag will be killed.</param> + /// <param name="tag">All coroutines with this tag on the given layer will be killed.</param> + /// <returns>The number of coroutines that were found and killed.</returns> + public static int KillCoroutines(int layer, string tag) + { + return _instance == null ? 0 : _instance.KillCoroutinesOnInstance(layer, tag); + } + + /// <summary> + /// Kills all coroutines with the given tag on the given layer. + /// </summary> + /// <param name="layer">All coroutines on this layer with the given tag will be killed.</param> + /// <param name="tag">All coroutines with this tag on the given layer will be killed.</param> + /// <returns>The number of coroutines that were found and killed.</returns> + public int KillCoroutinesOnInstance(int layer, string tag) + { + if (tag == null) + return KillCoroutinesOnInstance(layer); + if (!_layeredProcesses.ContainsKey(layer) || !_taggedProcesses.ContainsKey(tag)) + return 0; + int count = 0; + + var indexesEnum = _taggedProcesses[tag].GetEnumerator(); + while (indexesEnum.MoveNext()) + { + if (CoindexIsNull(indexesEnum.Current) || !_layeredProcesses[layer].Contains(indexesEnum.Current) || !CoindexKill(indexesEnum.Current)) + continue; + + if (_waitingTriggers.ContainsKey(_indexToHandle[indexesEnum.Current])) + CloseWaitingProcess(_indexToHandle[indexesEnum.Current]); + + count++; + RemoveGraffiti(indexesEnum.Current); + + if (!_taggedProcesses.ContainsKey(tag) || !_layeredProcesses.ContainsKey(layer)) + break; + + indexesEnum = _taggedProcesses[tag].GetEnumerator(); + } + + return count; + } + + /// <summary> + /// Kills the instance of the coroutine handle if it exists. + /// </summary> + /// <param name="handle">The handle of the coroutine to kill.</param> + /// <returns>The number of coroutines that were found and killed (0 or 1).</returns> + public static int KillCoroutines(CoroutineHandle handle) + { + return ActiveInstances.ContainsKey(handle.Key) ? GetInstance(handle.Key).KillCoroutinesOnInstance(handle) : 0; + } + + /// <summary> + /// Kills the instance of the coroutine handle on this Timing instance if it exists. + /// </summary> + /// <param name="handle">The handle of the coroutine to kill.</param> + /// <returns>The number of coroutines that were found and killed (0 or 1).</returns> + public int KillCoroutinesOnInstance(CoroutineHandle handle) + { + bool foundOne = false; + + if (_handleToIndex.ContainsKey(handle)) + { + if (_waitingTriggers.ContainsKey(handle)) + CloseWaitingProcess(handle); + + foundOne = CoindexExtract(_handleToIndex[handle]) != null; + RemoveGraffiti(_handleToIndex[handle]); + } + + return foundOne ? 1 : 0; + } + + /// <summary> + /// Use "yield return Timing.WaitForSeconds(time);" to wait for the specified number of seconds. + /// </summary> + /// <param name="waitTime">Number of seconds to wait.</param> + public static float WaitForSeconds(float waitTime) + { + if (float.IsNaN(waitTime)) waitTime = 0f; + return LocalTime + waitTime; + } + + /// <summary> + /// Use "yield return timingInstance.WaitForSecondsOnInstance(time);" to wait for the specified number of seconds. + /// </summary> + /// <param name="waitTime">Number of seconds to wait.</param> + public float WaitForSecondsOnInstance(float waitTime) + { + if (float.IsNaN(waitTime)) waitTime = 0f; + return (float)localTime + waitTime; + } + + private void UpdateTimeValues(Segment segment) + { + switch (segment) + { + case Segment.Update: + deltaTime = Time.deltaTime; + _lastUpdateTime += deltaTime; + localTime = _lastUpdateTime; + return; + case Segment.LateUpdate: + deltaTime = Time.deltaTime; + _lastLateUpdateTime += deltaTime; + localTime = _lastLateUpdateTime; + return; + case Segment.FixedUpdate: + deltaTime = Time.deltaTime; + _lastFixedUpdateTime += deltaTime; + localTime = _lastFixedUpdateTime; + return; + case Segment.SlowUpdate: + if (_lastSlowUpdateTime == 0d) + deltaTime = TimeBetweenSlowUpdateCalls; + else + deltaTime = ThreadSafeElapsedTime.GetElapsedSecondsSinceStartUp() - (float)_lastSlowUpdateTime; + + localTime = _lastSlowUpdateTime = ThreadSafeElapsedTime.GetElapsedSecondsSinceStartUp(); + return; + case Segment.RealtimeUpdate: + deltaTime = Time.unscaledDeltaTime; + _lastRealtimeUpdateTime += deltaTime; + localTime = _lastRealtimeUpdateTime; + return; +#if UNITY_EDITOR + case Segment.EditorUpdate: + deltaTime = (float)(EditorApplication.timeSinceStartup - _lastEditorUpdateTime); + + if (deltaTime > Time.maximumDeltaTime) + deltaTime = Time.maximumDeltaTime; + + localTime = _lastEditorUpdateTime = EditorApplication.timeSinceStartup; + return; + case Segment.EditorSlowUpdate: + deltaTime = (float)(EditorApplication.timeSinceStartup - _lastEditorSlowUpdateTime); + localTime = _lastEditorSlowUpdateTime = EditorApplication.timeSinceStartup; + return; +#endif + case Segment.EndOfFrame: + deltaTime = Time.deltaTime; + localTime = _lastUpdateTime; + return; + case Segment.ManualTimeframe: + localTime = SetManualTimeframeTime == null ? Time.time : SetManualTimeframeTime(_lastManualTimeframeTime); + deltaTime = (float)(localTime - _lastManualTimeframeTime); + + if (deltaTime > Time.maximumDeltaTime) + deltaTime = Time.maximumDeltaTime; + + _lastManualTimeframeTime = localTime; + return; + } + } + + private void SetTimeValues(Segment segment) + { + switch (segment) + { + case Segment.Update: + deltaTime = Time.deltaTime; + localTime = _lastUpdateTime; + return; + case Segment.LateUpdate: + deltaTime = Time.deltaTime; + localTime = _lastLateUpdateTime; + return; + case Segment.FixedUpdate: + deltaTime = Time.deltaTime; + localTime = _lastFixedUpdateTime; + return; + case Segment.SlowUpdate: + deltaTime = ThreadSafeElapsedTime.GetElapsedSecondsSinceStartUp() - (float)_lastSlowUpdateTime; + localTime = _lastSlowUpdateTime; + return; + case Segment.RealtimeUpdate: + deltaTime = Time.unscaledDeltaTime; + localTime = _lastRealtimeUpdateTime; + return; +#if UNITY_EDITOR + case Segment.EditorUpdate: + deltaTime = (float)(EditorApplication.timeSinceStartup - _lastEditorUpdateTime); + + if (deltaTime > Time.maximumDeltaTime) + deltaTime = Time.maximumDeltaTime; + + localTime = _lastEditorUpdateTime; + return; + case Segment.EditorSlowUpdate: + deltaTime = (float)(EditorApplication.timeSinceStartup - _lastEditorSlowUpdateTime); + localTime = _lastEditorSlowUpdateTime; + return; +#endif + case Segment.EndOfFrame: + deltaTime = Time.deltaTime; + localTime = _lastUpdateTime; + return; + case Segment.ManualTimeframe: + deltaTime = Time.deltaTime; + localTime = _lastManualTimeframeTime; + return; + } + } + + private double GetSegmentTime(Segment segment) + { + switch (segment) + { + case Segment.Update: + return _lastUpdateTime; + case Segment.LateUpdate: + return _lastLateUpdateTime; + case Segment.FixedUpdate: + return _lastFixedUpdateTime; + case Segment.SlowUpdate: + return _lastSlowUpdateTime; + case Segment.RealtimeUpdate: + return _lastRealtimeUpdateTime; + case Segment.EditorUpdate: + return _lastEditorUpdateTime; + case Segment.EditorSlowUpdate: + return _lastEditorSlowUpdateTime; + case Segment.EndOfFrame: + return _lastUpdateTime; + case Segment.ManualTimeframe: + return _lastManualTimeframeTime; + default: + return 0d; + } + } + + /// <summary> + /// Resets the value of LocalTime to zero (only for the Update, LateUpdate, FixedUpdate, and RealtimeUpdate loops). + /// </summary> + public void ResetTimeCountOnInstance() + { + localTime = 0d; + + _lastUpdateTime = 0d; + _lastLateUpdateTime = 0d; + _lastFixedUpdateTime = 0d; + _lastRealtimeUpdateTime = 0d; + + _EOFPumpRan = false; + } + + /// <summary> + /// This will pause all coroutines running on the current MEC instance until ResumeCoroutines is called. + /// </summary> + /// <returns>The number of coroutines that were paused.</returns> + public static int PauseCoroutines() + { + return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(); + } + + /// <summary> + /// This will pause all coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called. + /// </summary> + /// <returns>The number of coroutines that were paused.</returns> + public int PauseCoroutinesOnInstance() + { + int count = 0; + int i; + for (i = 0; i < _nextUpdateProcessSlot; i++) + { + if (!UpdatePaused[i] && UpdateProcesses[i] != null) + { + UpdatePaused[i] = true; + count++; + } + } + + for (i = 0; i < _nextLateUpdateProcessSlot; i++) + { + if (!LateUpdatePaused[i] && LateUpdateProcesses[i] != null) + { + LateUpdatePaused[i] = true; + count++; + } + } + + for (i = 0; i < _nextFixedUpdateProcessSlot; i++) + { + if (!FixedUpdatePaused[i] && FixedUpdateProcesses[i] != null) + { + FixedUpdatePaused[i] = true; + count++; + } + } + + for (i = 0; i < _nextSlowUpdateProcessSlot; i++) + { + if (!SlowUpdatePaused[i] && SlowUpdateProcesses[i] != null) + { + SlowUpdatePaused[i] = true; + count++; + } + } + + for (i = 0; i < _nextRealtimeUpdateProcessSlot; i++) + { + if (!RealtimeUpdatePaused[i] && RealtimeUpdateProcesses[i] != null) + { + RealtimeUpdatePaused[i] = true; + count++; + } + } + + for (i = 0; i < _nextEditorUpdateProcessSlot; i++) + { + if (!EditorUpdatePaused[i] && EditorUpdateProcesses[i] != null) + { + EditorUpdatePaused[i] = true; + count++; + } + } + + for (i = 0; i < _nextEditorSlowUpdateProcessSlot; i++) + { + if (!EditorSlowUpdatePaused[i] && EditorSlowUpdateProcesses[i] != null) + { + EditorSlowUpdatePaused[i] = true; + count++; + } + } + + for (i = 0; i < _nextEndOfFrameProcessSlot; i++) + { + if (!EndOfFramePaused[i] && EndOfFrameProcesses[i] != null) + { + EndOfFramePaused[i] = true; + count++; + } + } + + for (i = 0; i < _nextManualTimeframeProcessSlot; i++) + { + if (!ManualTimeframePaused[i] && ManualTimeframeProcesses[i] != null) + { + ManualTimeframePaused[i] = true; + count++; + } + } + + return count; + } + + /// <summary> + /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called. + /// </summary> + /// <param name="tag">Any coroutines with a matching tag will be paused.</param> + /// <returns>The number of coroutines that were paused.</returns> + public static int PauseCoroutines(string tag) + { + return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(tag); + } + + /// <summary> + /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called. + /// </summary> + /// <param name="tag">Any coroutines with a matching tag will be paused.</param> + /// <returns>The number of coroutines that were paused.</returns> + public int PauseCoroutinesOnInstance(string tag) + { + if (tag == null || !_taggedProcesses.ContainsKey(tag)) + return 0; + + int count = 0; + var matchesEnum = _taggedProcesses[tag].GetEnumerator(); + + while (matchesEnum.MoveNext()) + if (!CoindexIsNull(matchesEnum.Current) && !CoindexSetPause(matchesEnum.Current)) + count++; + + return count; + } + + /// <summary> + /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called. + /// </summary> + /// <param name="layer">Any coroutines on the matching layer will be paused.</param> + /// <returns>The number of coroutines that were paused.</returns> + public static int PauseCoroutines(int layer) + { + return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(layer); + } + + /// <summary> + /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called. + /// </summary> + /// <param name="layer">Any coroutines on the matching layer will be paused.</param> + /// <returns>The number of coroutines that were paused.</returns> + public int PauseCoroutinesOnInstance(int layer) + { + if (!_layeredProcesses.ContainsKey(layer)) + return 0; + + int count = 0; + var matchesEnum = _layeredProcesses[layer].GetEnumerator(); + + while (matchesEnum.MoveNext()) + if (!CoindexIsNull(matchesEnum.Current) && !CoindexSetPause(matchesEnum.Current)) + count++; + + return count; + } + + /// <summary> + /// This will pause any matching coroutines running on the current MEC instance until ResumeCoroutines is called. + /// </summary> + /// <param name="layer">Any coroutines on the matching layer will be paused.</param> + /// <param name="tag">Any coroutines with a matching tag will be paused.</param> + /// <returns>The number of coroutines that were paused.</returns> + public static int PauseCoroutines(int layer, string tag) + { + return _instance == null ? 0 : _instance.PauseCoroutinesOnInstance(layer, tag); + } + + /// <summary> + /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called. + /// </summary> + /// <param name="layer">Any coroutines on the matching layer will be paused.</param> + /// <param name="tag">Any coroutines with a matching tag will be paused.</param> + /// <returns>The number of coroutines that were paused.</returns> + public int PauseCoroutinesOnInstance(int layer, string tag) + { + if (tag == null) + return PauseCoroutinesOnInstance(layer); + + if (!_taggedProcesses.ContainsKey(tag) || !_layeredProcesses.ContainsKey(layer)) + return 0; + + int count = 0; + var matchesEnum = _taggedProcesses[tag].GetEnumerator(); + + while (matchesEnum.MoveNext()) + if (_processLayers.ContainsKey(matchesEnum.Current) && _processLayers[matchesEnum.Current] == layer + && !CoindexIsNull(matchesEnum.Current) && !CoindexSetPause(matchesEnum.Current)) + count++; + + return count; + } + + /// <summary> + /// This will pause any matching coroutines until ResumeCoroutines is called. + /// </summary> + /// <param name="handle">The handle of the coroutine to pause.</param> + /// <returns>The number of coroutines that were paused (0 or 1).</returns> + public static int PauseCoroutines(CoroutineHandle handle) + { + return ActiveInstances.ContainsKey(handle.Key) ? GetInstance(handle.Key).PauseCoroutinesOnInstance(handle) : 0; + } + + /// <summary> + /// This will pause any matching coroutines running on this MEC instance until ResumeCoroutinesOnInstance is called. + /// </summary> + /// <param name="handle">The handle of the coroutine to pause.</param> + /// <returns>The number of coroutines that were paused (0 or 1).</returns> + public int PauseCoroutinesOnInstance(CoroutineHandle handle) + { + return _handleToIndex.ContainsKey(handle) && !CoindexIsNull(_handleToIndex[handle]) && !CoindexSetPause(_handleToIndex[handle]) ? 1 : 0; + } + + /// <summary> + /// This resumes all coroutines on the current MEC instance if they are currently paused, otherwise it has + /// no effect. + /// </summary> + /// <returns>The number of coroutines that were resumed.</returns> + public static int ResumeCoroutines() + { + return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(); + } + + /// <summary> + /// This resumes all coroutines on this MEC instance if they are currently paused, otherwise it has no effect. + /// </summary> + /// <returns>The number of coroutines that were resumed.</returns> + public int ResumeCoroutinesOnInstance() + { + int count = 0; + int i; + for (i = 0; i < _nextUpdateProcessSlot; i++) + { + if (UpdatePaused[i] && UpdateProcesses[i] != null) + { + UpdatePaused[i] = false; + count++; + } + } + + for (i = 0; i < _nextLateUpdateProcessSlot; i++) + { + if (LateUpdatePaused[i] && LateUpdateProcesses[i] != null) + { + LateUpdatePaused[i] = false; + count++; + } + } + + for (i = 0; i < _nextFixedUpdateProcessSlot; i++) + { + if (FixedUpdatePaused[i] && FixedUpdateProcesses[i] != null) + { + FixedUpdatePaused[i] = false; + count++; + } + } + + for (i = 0; i < _nextSlowUpdateProcessSlot; i++) + { + if (SlowUpdatePaused[i] && SlowUpdateProcesses[i] != null) + { + SlowUpdatePaused[i] = false; + count++; + } + } + + for (i = 0; i < _nextRealtimeUpdateProcessSlot; i++) + { + if (RealtimeUpdatePaused[i] && RealtimeUpdateProcesses[i] != null) + { + RealtimeUpdatePaused[i] = false; + count++; + } + } + + for (i = 0; i < _nextEditorUpdateProcessSlot; i++) + { + if (EditorUpdatePaused[i] && EditorUpdateProcesses[i] != null) + { + EditorUpdatePaused[i] = false; + count++; + } + } + + for (i = 0; i < _nextEditorSlowUpdateProcessSlot; i++) + { + if (EditorSlowUpdatePaused[i] && EditorSlowUpdateProcesses[i] != null) + { + EditorSlowUpdatePaused[i] = false; + count++; + } + } + + for (i = 0; i < _nextEndOfFrameProcessSlot; i++) + { + if (EndOfFramePaused[i] && EndOfFrameProcesses[i] != null) + { + EndOfFramePaused[i] = false; + count++; + } + } + + for (i = 0; i < _nextManualTimeframeProcessSlot; i++) + { + if (ManualTimeframePaused[i] && ManualTimeframeProcesses[i] != null) + { + ManualTimeframePaused[i] = false; + count++; + } + } + + var waitingEnum = _waitingTriggers.GetEnumerator(); + while (waitingEnum.MoveNext()) + { + int listCount = 0; + var pausedList = waitingEnum.Current.Value.GetEnumerator(); + + while (pausedList.MoveNext()) + { + if (_handleToIndex.ContainsKey(pausedList.Current.Handle) && !CoindexIsNull(_handleToIndex[pausedList.Current.Handle])) + { + CoindexSetPause(_handleToIndex[pausedList.Current.Handle]); + listCount++; + } + else + { + waitingEnum.Current.Value.Remove(pausedList.Current); + listCount = 0; + pausedList = waitingEnum.Current.Value.GetEnumerator(); + } + } + + count -= listCount; + } + + return count; + } + + /// <summary> + /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has no effect. + /// </summary> + /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param> + /// <returns>The number of coroutines that were resumed.</returns> + public static int ResumeCoroutines(string tag) + { + return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(tag); + } + + /// <summary> + /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect. + /// </summary> + /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param> + /// <returns>The number of coroutines that were resumed.</returns> + public int ResumeCoroutinesOnInstance(string tag) + { + if (tag == null || !_taggedProcesses.ContainsKey(tag)) + return 0; + int count = 0; + + var indexesEnum = _taggedProcesses[tag].GetEnumerator(); + while (indexesEnum.MoveNext()) + if (!CoindexIsNull(indexesEnum.Current) && CoindexSetPause(indexesEnum.Current, false)) + count++; + + var waitingEnum = _waitingTriggers.GetEnumerator(); + while (waitingEnum.MoveNext()) + { + var pausedList = waitingEnum.Current.Value.GetEnumerator(); + while (pausedList.MoveNext()) + { + if (_handleToIndex.ContainsKey(pausedList.Current.Handle) && !CoindexIsNull(_handleToIndex[pausedList.Current.Handle]) + && !CoindexSetPause(_handleToIndex[pausedList.Current.Handle])) + count--; + } + } + + return count; + } + + /// <summary> + /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has + /// no effect. + /// </summary> + /// <param name="layer">Any coroutines previously paused on the matching layer will be resumend.</param> + /// <returns>The number of coroutines that were resumed.</returns> + public static int ResumeCoroutines(int layer) + { + return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(layer); + } + + /// <summary> + /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect. + /// </summary> + /// <param name="layer">Any coroutines previously paused on the matching layer will be resumend.</param> + /// <returns>The number of coroutines that were resumed.</returns> + public int ResumeCoroutinesOnInstance(int layer) + { + if (!_layeredProcesses.ContainsKey(layer)) + return 0; + int count = 0; + + var indexesEnum = _layeredProcesses[layer].GetEnumerator(); + while (indexesEnum.MoveNext()) + if (!CoindexIsNull(indexesEnum.Current) && CoindexSetPause(indexesEnum.Current, false)) + count++; + + var waitingEnum = _waitingTriggers.GetEnumerator(); + while (waitingEnum.MoveNext()) + { + var pausedList = waitingEnum.Current.Value.GetEnumerator(); + while (pausedList.MoveNext()) + { + if (_handleToIndex.ContainsKey(pausedList.Current.Handle) && !CoindexIsNull(_handleToIndex[pausedList.Current.Handle]) + && !CoindexSetPause(_handleToIndex[pausedList.Current.Handle])) + count--; + } + } + + return count; + } + + /// <summary> + /// This resumes any matching coroutines on the current MEC instance if they are currently paused, otherwise it has + /// no effect. + /// </summary> + /// <param name="layer">Any coroutines previously paused on the matching layer will be resumend.</param> + /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param> + /// <returns>The number of coroutines that were resumed.</returns> + public static int ResumeCoroutines(int layer, string tag) + { + return _instance == null ? 0 : _instance.ResumeCoroutinesOnInstance(layer, tag); + } + + /// <summary> + /// This resumes any matching coroutines on this MEC instance if they are currently paused, otherwise it has no effect. + /// </summary> + /// <param name="layer">Any coroutines previously paused on the matching layer will be resumend.</param> + /// <param name="tag">Any coroutines previously paused with a matching tag will be resumend.</param> + /// <returns>The number of coroutines that were resumed.</returns> + public int ResumeCoroutinesOnInstance(int layer, string tag) + { + if (tag == null) + return ResumeCoroutinesOnInstance(layer); + if (!_layeredProcesses.ContainsKey(layer) || !_taggedProcesses.ContainsKey(tag)) + return 0; + int count = 0; + + var indexesEnum = _taggedProcesses[tag].GetEnumerator(); + while (indexesEnum.MoveNext()) + if (!CoindexIsNull(indexesEnum.Current) && _layeredProcesses[layer].Contains(indexesEnum.Current) && + CoindexSetPause(indexesEnum.Current, false)) + count++; + + var waitingEnum = _waitingTriggers.GetEnumerator(); + while (waitingEnum.MoveNext()) + { + var pausedList = waitingEnum.Current.Value.GetEnumerator(); + while (pausedList.MoveNext()) + { + if (_handleToIndex.ContainsKey(pausedList.Current.Handle) && !CoindexIsNull(_handleToIndex[pausedList.Current.Handle]) + && !CoindexSetPause(_handleToIndex[pausedList.Current.Handle])) + count--; + } + } + + return count; + } + + /// <summary> + /// This will resume any matching coroutines. + /// </summary> + /// <param name="handle">The handle of the coroutine to resume.</param> + /// <returns>The number of coroutines that were resumed (0 or 1).</returns> + public static int ResumeCoroutines(CoroutineHandle handle) + { + return ActiveInstances.ContainsKey(handle.Key) ? GetInstance(handle.Key).ResumeCoroutinesOnInstance(handle) : 0; + } + + /// <summary> + /// This will resume any matching coroutines running on this MEC instance. + /// </summary> + /// <param name="handle">The handle of the coroutine to resume.</param> + /// <returns>The number of coroutines that were resumed (0 or 1).</returns> + public int ResumeCoroutinesOnInstance(CoroutineHandle handle) + { + var waitingEnum = _waitingTriggers.GetEnumerator(); + while (waitingEnum.MoveNext()) + { + var pausedList = waitingEnum.Current.Value.GetEnumerator(); + while (pausedList.MoveNext()) + if (pausedList.Current.Handle == handle) + return 0; + } + + return _handleToIndex.ContainsKey(handle) && + !CoindexIsNull(_handleToIndex[handle]) && CoindexSetPause(_handleToIndex[handle], false) ? 1 : 0; + } + + /// <summary> + /// Returns the tag associated with the coroutine that the given handle points to, if it is running. + /// </summary> + /// <param name="handle">The handle to the coroutine.</param> + /// <returns>The coroutine's tag, or null if there is no matching tag.</returns> + public static string GetTag(CoroutineHandle handle) + { + Timing inst = GetInstance(handle.Key); + return inst != null && inst._handleToIndex.ContainsKey(handle) && inst._processTags.ContainsKey(inst._handleToIndex[handle]) + ? inst._processTags[inst._handleToIndex[handle]] : null; + } + + /// <summary> + /// Returns the layer associated with the coroutine that the given handle points to, if it is running. + /// </summary> + /// <param name="handle">The handle to the coroutine.</param> + /// <returns>The coroutine's layer as a nullable integer, or null if there is no matching layer.</returns> + public static int? GetLayer(CoroutineHandle handle) + { + Timing inst = GetInstance(handle.Key); + return inst != null && inst._handleToIndex.ContainsKey(handle) && inst._processLayers.ContainsKey(inst._handleToIndex[handle]) + ? inst._processLayers[inst._handleToIndex[handle]] : (int?)null; + } + + /// <summary> + /// Returns the segment that the coroutine with the given handle is running on. + /// </summary> + /// <param name="handle">The handle to the coroutine.</param> + /// <returns>The coroutine's segment, or Segment.Invalid if it's not found.</returns> + public static Segment GetSegment(CoroutineHandle handle) + { + Timing inst = GetInstance(handle.Key); + return inst != null && inst._handleToIndex.ContainsKey(handle) ? inst._handleToIndex[handle].seg : Segment.Invalid; + } + + /// <summary> + /// Sets the coroutine that the handle points to to have the given tag. + /// </summary> + /// <param name="handle">The handle to the coroutine.</param> + /// <param name="newTag">The new tag to assign, or null to clear the tag.</param> + /// <param name="overwriteExisting">If set to false then the tag will not be changed if the coroutine has an existing tag.</param> + /// <returns>Whether the tag was set successfully.</returns> + public static bool SetTag(CoroutineHandle handle, string newTag, bool overwriteExisting = true) + { + Timing inst = GetInstance(handle.Key); + if (inst == null || !inst._handleToIndex.ContainsKey(handle) || inst.CoindexIsNull(inst._handleToIndex[handle]) + || (!overwriteExisting && inst._processTags.ContainsKey(inst._handleToIndex[handle]))) + return false; + + if (newTag == null) + { + inst.RemoveTag(inst._handleToIndex[handle]); + return true; + } + + if (inst._processTags.ContainsKey(inst._handleToIndex[handle])) + { + if (inst._taggedProcesses[inst._processTags[inst._handleToIndex[handle]]].Count <= 1) + inst._taggedProcesses.Remove(inst._processTags[inst._handleToIndex[handle]]); + else + inst._taggedProcesses[inst._processTags[inst._handleToIndex[handle]]].Remove(inst._handleToIndex[handle]); + + inst._processTags[inst._handleToIndex[handle]] = newTag; + } + else + { + inst._processTags.Add(inst._handleToIndex[handle], newTag); + } + + if (inst._taggedProcesses.ContainsKey(newTag)) + inst._taggedProcesses[newTag].Add(inst._handleToIndex[handle]); + else + inst._taggedProcesses.Add(newTag, new HashSet<ProcessIndex> { inst._handleToIndex[handle] }); + + return true; + } + + /// <summary> + /// Sets the coroutine that the handle points to to have the given layer. + /// </summary> + /// <param name="handle">The handle to the coroutine.</param> + /// <param name="newLayer">The new tag to assign.</param> + /// <param name="overwriteExisting">If set to false then the tag will not be changed if the coroutine has an existing tag.</param> + /// <returns>Whether the layer was set successfully.</returns> + public static bool SetLayer(CoroutineHandle handle, int newLayer, bool overwriteExisting = true) + { + Timing inst = GetInstance(handle.Key); + if (inst == null || !inst._handleToIndex.ContainsKey(handle) || inst.CoindexIsNull(inst._handleToIndex[handle]) + || (!overwriteExisting && inst._processLayers.ContainsKey(inst._handleToIndex[handle]))) + return false; + + if (inst._processLayers.ContainsKey(inst._handleToIndex[handle])) + { + if (inst._layeredProcesses[inst._processLayers[inst._handleToIndex[handle]]].Count <= 1) + inst._layeredProcesses.Remove(inst._processLayers[inst._handleToIndex[handle]]); + else + inst._layeredProcesses[inst._processLayers[inst._handleToIndex[handle]]].Remove(inst._handleToIndex[handle]); + + inst._processLayers[inst._handleToIndex[handle]] = newLayer; + } + else + { + inst._processLayers.Add(inst._handleToIndex[handle], newLayer); + } + + if (inst._layeredProcesses.ContainsKey(newLayer)) + inst._layeredProcesses[newLayer].Add(inst._handleToIndex[handle]); + else + inst._layeredProcesses.Add(newLayer, new HashSet<ProcessIndex> { inst._handleToIndex[handle] }); + + return true; + } + + /// <summary> + /// Sets the segment for the coroutine with the given handle. + /// </summary> + /// <param name="handle">The handle to the coroutine.</param> + /// <param name="newSegment">The new segment to run the coroutine in.</param> + /// <returns>Whether the segment was set successfully.</returns> + public static bool SetSegment(CoroutineHandle handle, Segment newSegment) + { + Timing inst = GetInstance(handle.Key); + if (inst == null || !inst._handleToIndex.ContainsKey(handle) || inst.CoindexIsNull(inst._handleToIndex[handle])) + return false; + + inst.RunCoroutineInternal(inst.CoindexExtract(inst._handleToIndex[handle]), newSegment, inst._processLayers.ContainsKey(inst._handleToIndex[handle]) + ? inst._processLayers[inst._handleToIndex[handle]] : (int?)null, inst._processTags.ContainsKey(inst._handleToIndex[handle]) + ? inst._processTags[inst._handleToIndex[handle]] : null, handle, false); + + return true; + } + + /// <summary> + /// Sets the coroutine that the handle points to to have the given tag. + /// </summary> + /// <param name="handle">The handle to the coroutine.</param> + /// <returns>Whether the tag was removed successfully.</returns> + public static bool RemoveTag(CoroutineHandle handle) + { + return SetTag(handle, null); + } + + /// <summary> + /// Sets the coroutine that the handle points to to have the given layer. + /// </summary> + /// <param name="handle">The handle to the coroutine.</param> + /// <returns>Whether the layer was removed successfully.</returns> + public static bool RemoveLayer(CoroutineHandle handle) + { + Timing inst = GetInstance(handle.Key); + if (inst == null || !inst._handleToIndex.ContainsKey(handle) || inst.CoindexIsNull(inst._handleToIndex[handle])) + return false; + + inst.RemoveLayer(inst._handleToIndex[handle]); + + return true; + } + + /// <summary> + /// Tests to see if the handle you have points to a valid coroutine. + /// </summary> + /// <param name="handle">The handle to test.</param> + /// <returns>Whether it's a valid coroutine.</returns> + public static bool IsRunning(CoroutineHandle handle) + { + Timing inst = GetInstance(handle.Key); + return inst != null && inst._handleToIndex.ContainsKey(handle) && !inst.CoindexIsNull(inst._handleToIndex[handle]); + } + + /// <summary> + /// Tests to see if the handle you have points to a paused coroutine. + /// </summary> + /// <param name="handle">The handle to test.</param> + /// <returns>Whether it's a paused coroutine.</returns> + public static bool IsPaused(CoroutineHandle handle) + { + Timing inst = GetInstance(handle.Key); + return inst != null && inst._handleToIndex.ContainsKey(handle) && !inst.CoindexIsNull(inst._handleToIndex[handle]) && + !inst.CoindexIsPaused(inst._handleToIndex[handle]); + } + + private void AddTag(string tag, ProcessIndex coindex) + { + _processTags.Add(coindex, tag); + + if (_taggedProcesses.ContainsKey(tag)) + _taggedProcesses[tag].Add(coindex); + else + _taggedProcesses.Add(tag, new HashSet<ProcessIndex> { coindex }); + } + + private void AddLayer(int layer, ProcessIndex coindex) + { + _processLayers.Add(coindex, layer); + + if (_layeredProcesses.ContainsKey(layer)) + _layeredProcesses[layer].Add(coindex); + else + _layeredProcesses.Add(layer, new HashSet<ProcessIndex> { coindex }); + } + + private void RemoveTag(ProcessIndex coindex) + { + if (_processTags.ContainsKey(coindex)) + { + if (_taggedProcesses[_processTags[coindex]].Count > 1) + _taggedProcesses[_processTags[coindex]].Remove(coindex); + else + _taggedProcesses.Remove(_processTags[coindex]); + + _processTags.Remove(coindex); + } + } + + private void RemoveLayer(ProcessIndex coindex) + { + if (_processLayers.ContainsKey(coindex)) + { + if (_layeredProcesses[_processLayers[coindex]].Count > 1) + _layeredProcesses[_processLayers[coindex]].Remove(coindex); + else + _layeredProcesses.Remove(_processLayers[coindex]); + + _processLayers.Remove(coindex); + } + } + + private void RemoveGraffiti(ProcessIndex coindex) + { + if (_processLayers.ContainsKey(coindex)) + { + if (_layeredProcesses[_processLayers[coindex]].Count > 1) + _layeredProcesses[_processLayers[coindex]].Remove(coindex); + else + _layeredProcesses.Remove(_processLayers[coindex]); + + _processLayers.Remove(coindex); + } + + if (_processTags.ContainsKey(coindex)) + { + if (_taggedProcesses[_processTags[coindex]].Count > 1) + _taggedProcesses[_processTags[coindex]].Remove(coindex); + else + _taggedProcesses.Remove(_processTags[coindex]); + + _processTags.Remove(coindex); + } + + if (_indexToHandle.ContainsKey(coindex)) + { + _handleToIndex.Remove(_indexToHandle[coindex]); + _indexToHandle.Remove(coindex); + } + } + + private void MoveGraffiti(ProcessIndex coindexFrom, ProcessIndex coindexTo) + { + RemoveGraffiti(coindexTo); + + int layer; + if (_processLayers.TryGetValue(coindexFrom, out layer)) + { + _layeredProcesses[layer].Remove(coindexFrom); + _layeredProcesses[layer].Add(coindexTo); + + _processLayers.Add(coindexTo, layer); + _processLayers.Remove(coindexFrom); + } + + string tag; + if (_processTags.TryGetValue(coindexFrom, out tag)) + { + _taggedProcesses[tag].Remove(coindexFrom); + _taggedProcesses[tag].Add(coindexTo); + + _processTags.Add(coindexTo, tag); + _processTags.Remove(coindexFrom); + } + + _handleToIndex[_indexToHandle[coindexFrom]] = coindexTo; + _indexToHandle.Add(coindexTo, _indexToHandle[coindexFrom]); + _indexToHandle.Remove(coindexFrom); + } + + private IEnumerator<float> CoindexExtract(ProcessIndex coindex) + { + IEnumerator<float> retVal; + + switch (coindex.seg) + { + case Segment.Update: + retVal = UpdateProcesses[coindex.i]; + UpdateProcesses[coindex.i] = null; + return retVal; + case Segment.FixedUpdate: + retVal = FixedUpdateProcesses[coindex.i]; + FixedUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.LateUpdate: + retVal = LateUpdateProcesses[coindex.i]; + LateUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.SlowUpdate: + retVal = SlowUpdateProcesses[coindex.i]; + SlowUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.RealtimeUpdate: + retVal = RealtimeUpdateProcesses[coindex.i]; + RealtimeUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.EditorUpdate: + retVal = EditorUpdateProcesses[coindex.i]; + EditorUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.EditorSlowUpdate: + retVal = EditorSlowUpdateProcesses[coindex.i]; + EditorSlowUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.EndOfFrame: + retVal = EndOfFrameProcesses[coindex.i]; + EndOfFrameProcesses[coindex.i] = null; + return retVal; + case Segment.ManualTimeframe: + retVal = ManualTimeframeProcesses[coindex.i]; + ManualTimeframeProcesses[coindex.i] = null; + return retVal; + default: + return null; + } + } + + private bool CoindexIsNull(ProcessIndex coindex) + { + switch (coindex.seg) + { + case Segment.Update: + return UpdateProcesses[coindex.i] == null; + case Segment.FixedUpdate: + return FixedUpdateProcesses[coindex.i] == null; + case Segment.LateUpdate: + return LateUpdateProcesses[coindex.i] == null; + case Segment.SlowUpdate: + return SlowUpdateProcesses[coindex.i] == null; + case Segment.RealtimeUpdate: + return RealtimeUpdateProcesses[coindex.i] == null; + case Segment.EditorUpdate: + return EditorUpdateProcesses[coindex.i] == null; + case Segment.EditorSlowUpdate: + return EditorSlowUpdateProcesses[coindex.i] == null; + case Segment.EndOfFrame: + return EndOfFrameProcesses[coindex.i] == null; + case Segment.ManualTimeframe: + return ManualTimeframeProcesses[coindex.i] == null; + default: + return true; + } + } + + private IEnumerator<float> CoindexPeek(ProcessIndex coindex) + { + switch (coindex.seg) + { + case Segment.Update: + return UpdateProcesses[coindex.i]; + case Segment.FixedUpdate: + return FixedUpdateProcesses[coindex.i]; + case Segment.LateUpdate: + return LateUpdateProcesses[coindex.i]; + case Segment.SlowUpdate: + return SlowUpdateProcesses[coindex.i]; + case Segment.RealtimeUpdate: + return RealtimeUpdateProcesses[coindex.i]; + case Segment.EditorUpdate: + return EditorUpdateProcesses[coindex.i]; + case Segment.EditorSlowUpdate: + return EditorSlowUpdateProcesses[coindex.i]; + case Segment.EndOfFrame: + return EndOfFrameProcesses[coindex.i]; + case Segment.ManualTimeframe: + return ManualTimeframeProcesses[coindex.i]; + default: + return null; + } + } + + private bool CoindexKill(ProcessIndex coindex) + { + bool retVal; + + switch (coindex.seg) + { + case Segment.Update: + retVal = UpdateProcesses[coindex.i] != null; + UpdateProcesses[coindex.i] = null; + return retVal; + case Segment.FixedUpdate: + retVal = FixedUpdateProcesses[coindex.i] != null; + FixedUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.LateUpdate: + retVal = LateUpdateProcesses[coindex.i] != null; + LateUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.SlowUpdate: + retVal = SlowUpdateProcesses[coindex.i] != null; + SlowUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.RealtimeUpdate: + retVal = RealtimeUpdateProcesses[coindex.i] != null; + RealtimeUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.EditorUpdate: + retVal = UpdateProcesses[coindex.i] != null; + EditorUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.EditorSlowUpdate: + retVal = EditorSlowUpdateProcesses[coindex.i] != null; + EditorSlowUpdateProcesses[coindex.i] = null; + return retVal; + case Segment.EndOfFrame: + retVal = EndOfFrameProcesses[coindex.i] != null; + EndOfFrameProcesses[coindex.i] = null; + return retVal; + case Segment.ManualTimeframe: + retVal = ManualTimeframeProcesses[coindex.i] != null; + ManualTimeframeProcesses[coindex.i] = null; + return retVal; + default: + return false; + } + } + + private bool CoindexSetPause(ProcessIndex coindex, bool newPausedState = true) + { + bool isPaused; + + switch (coindex.seg) + { + case Segment.Update: + isPaused = UpdatePaused[coindex.i]; + UpdatePaused[coindex.i] = newPausedState; + return isPaused; + case Segment.FixedUpdate: + isPaused = FixedUpdatePaused[coindex.i]; + FixedUpdatePaused[coindex.i] = newPausedState; + return isPaused; + case Segment.LateUpdate: + isPaused = LateUpdatePaused[coindex.i]; + LateUpdatePaused[coindex.i] = newPausedState; + return isPaused; + case Segment.SlowUpdate: + isPaused = SlowUpdatePaused[coindex.i]; + SlowUpdatePaused[coindex.i] = newPausedState; + return isPaused; + case Segment.RealtimeUpdate: + isPaused = RealtimeUpdatePaused[coindex.i]; + RealtimeUpdatePaused[coindex.i] = newPausedState; + return isPaused; + case Segment.EditorUpdate: + isPaused = EditorUpdatePaused[coindex.i]; + EditorUpdatePaused[coindex.i] = newPausedState; + return isPaused; + case Segment.EditorSlowUpdate: + isPaused = EditorSlowUpdatePaused[coindex.i]; + EditorSlowUpdatePaused[coindex.i] = newPausedState; + return isPaused; + case Segment.EndOfFrame: + isPaused = EndOfFramePaused[coindex.i]; + EndOfFramePaused[coindex.i] = newPausedState; + return isPaused; + case Segment.ManualTimeframe: + isPaused = ManualTimeframePaused[coindex.i]; + ManualTimeframePaused[coindex.i] = newPausedState; + return isPaused; + default: + return false; + } + } + + private bool CoindexIsPaused(ProcessIndex coindex) + { + switch (coindex.seg) + { + case Segment.Update: + return UpdatePaused[coindex.i]; + case Segment.FixedUpdate: + return FixedUpdatePaused[coindex.i]; + case Segment.LateUpdate: + return LateUpdatePaused[coindex.i]; + case Segment.SlowUpdate: + return SlowUpdatePaused[coindex.i]; + case Segment.RealtimeUpdate: + return RealtimeUpdatePaused[coindex.i]; + case Segment.EditorUpdate: + return EditorUpdatePaused[coindex.i]; + case Segment.EditorSlowUpdate: + return EditorSlowUpdatePaused[coindex.i]; + case Segment.EndOfFrame: + return EndOfFramePaused[coindex.i]; + case Segment.ManualTimeframe: + return ManualTimeframePaused[coindex.i]; + default: + return false; + } + } + + private void CoindexReplace(ProcessIndex coindex, IEnumerator<float> replacement) + { + switch (coindex.seg) + { + case Segment.Update: + UpdateProcesses[coindex.i] = replacement; + return; + case Segment.FixedUpdate: + FixedUpdateProcesses[coindex.i] = replacement; + return; + case Segment.LateUpdate: + LateUpdateProcesses[coindex.i] = replacement; + return; + case Segment.SlowUpdate: + SlowUpdateProcesses[coindex.i] = replacement; + return; + case Segment.RealtimeUpdate: + RealtimeUpdateProcesses[coindex.i] = replacement; + return; + case Segment.EditorUpdate: + EditorUpdateProcesses[coindex.i] = replacement; + return; + case Segment.EditorSlowUpdate: + EditorSlowUpdateProcesses[coindex.i] = replacement; + return; + case Segment.EndOfFrame: + EndOfFrameProcesses[coindex.i] = replacement; + return; + case Segment.ManualTimeframe: + ManualTimeframeProcesses[coindex.i] = replacement; + return; + } + } + + /// <summary> + /// Use the command "yield return Timing.WaitUntilDone(otherCoroutine);" to pause the current + /// coroutine until otherCoroutine is done. + /// </summary> + /// <param name="otherCoroutine">The coroutine to pause for.</param> + //public static float WaitUntilDone(CoroutineHandle otherCoroutine) + //{ + // return Instance.WaitUntilDoneOnInstance(otherCoroutine); + //} + + ///// <summary> + ///// Use the command "yield return Timing.WaitUntilDone(otherCoroutine);" to pause the current + ///// coroutine until otherCoroutine is done. + ///// </summary> + ///// <param name="otherCoroutine">The coroutine to pause for.</param> + ///// <param name="warnOnIssue">Post a warning to the console if no hold action was actually performed.</param> + //public static float WaitUntilDone(CoroutineHandle otherCoroutine, bool warnOnIssue) + //{ + // return Instance.WaitUntilDoneOnInstance(otherCoroutine, warnOnIssue); + //} + + ///// <summary> + ///// Use the command "yield return timingInstance.WaitUntilDoneOnInstance(otherCoroutine);" to pause the current + ///// coroutine until the otherCoroutine is done. + ///// </summary> + ///// <param name="otherCoroutine">The coroutine to pause for.</param> + ///// <param name="warnOnIssue">Post a warning to the console if no hold action was actually performed.</param> + //public float WaitUntilDoneOnInstance(CoroutineHandle otherCoroutine, bool warnOnIssue = true) + //{ + // if (_handleToIndex.ContainsKey(otherCoroutine)) + // { + // if (CoindexIsNull(_handleToIndex[otherCoroutine])) + // return 0f; + + // if (!_waitingTriggers.ContainsKey(otherCoroutine)) + // { + // CoindexReplace(_handleToIndex[otherCoroutine], _StartWhenDone(otherCoroutine, CoindexPeek(_handleToIndex[otherCoroutine]))); + // _waitingTriggers.Add(otherCoroutine, new HashSet<ProcessData>()); + // } + + // ReplacementFunction = (coptr, instance, handle) => + // { + // if (handle == otherCoroutine) + // { + // if (warnOnIssue) + // Debug.LogWarning("A coroutine attempted to wait for itself."); + + // return coptr; + // } + + // _waitingTriggers[otherCoroutine].Add(new ProcessData + // { + // Handle = handle, + // PauseTime = coptr.Current > GetSegmentTime(_handleToIndex[handle].seg) + // ? coptr.Current - (float)GetSegmentTime(_handleToIndex[handle].seg) : 0f + // }); + + // CoindexSetPause(_handleToIndex[handle]); + + // return coptr; + // }; + + // return float.NaN; + // } + + // if (warnOnIssue) + // Debug.LogWarning("WaitUntilDone cannot hold: The coroutine handle that was passed in is invalid.\n" + otherCoroutine); + + // return 0f; + //} + + private IEnumerator<float> _StartWhenDone(CoroutineHandle handle, IEnumerator<float> proc) + { + if (!_waitingTriggers.ContainsKey(handle)) yield break; + + try + { + if (proc.Current > localTime) + yield return proc.Current; + + while (proc.MoveNext()) + yield return proc.Current; + } + finally + { + CloseWaitingProcess(handle); + } + } + + private void CloseWaitingProcess(CoroutineHandle handle) + { + if (!_waitingTriggers.ContainsKey(handle)) return; + + var tasksEnum = _waitingTriggers[handle].GetEnumerator(); + _waitingTriggers.Remove(handle); + + while (tasksEnum.MoveNext()) + { + if (_handleToIndex.ContainsKey(tasksEnum.Current.Handle)) + { + ProcessIndex coIndex = _handleToIndex[tasksEnum.Current.Handle]; + + //if (tasksEnum.Current.PauseTime > 0d) + //CoindexReplace(coIndex, _InjectDelay(CoindexPeek(coIndex), (float)(GetSegmentTime(coIndex.seg) + tasksEnum.Current.PauseTime))); + + CoindexSetPause(coIndex, false); + } + } + } + + private static IEnumerator<float> _InjectDelay(IEnumerator<float> proc, float returnAt) + { + yield return returnAt; + + ReplacementFunction = delegate { return proc; }; + yield return float.NaN; + } + + /// <summary> + /// Use the command "yield return Timing.SwitchCoroutine(segment);" to switch this coroutine to + /// the given segment on the default instance. + /// </summary> + /// <param name="newSegment">The new segment to run in.</param> + public static float SwitchCoroutine(Segment newSegment) + { + ReplacementFunction = (coptr, instance, handle) => + { + ProcessIndex index = instance._handleToIndex[handle]; + instance.RunCoroutineInternal(coptr, newSegment, instance._processLayers.ContainsKey(index) ? instance._processLayers[index] : (int?)null, + instance._processTags.ContainsKey(index) ? instance._processTags[index] : null, handle, false); + return null; + }; + + return float.NaN; + } + + /// <summary> + /// Use the command "yield return Timing.SwitchCoroutine(segment, tag);" to switch this coroutine to + /// the given values. + /// </summary> + /// <param name="newSegment">The new segment to run in.</param> + /// <param name="newTag">The new tag to apply, or null to remove this coroutine's tag.</param> + public static float SwitchCoroutine(Segment newSegment, string newTag) + { + ReplacementFunction = (coptr, instance, handle) => + { + ProcessIndex index = instance._handleToIndex[handle]; + instance.RunCoroutineInternal(coptr, newSegment, + instance._processLayers.ContainsKey(index) ? instance._processLayers[index] : (int?)null, newTag, handle, false); + return null; + }; + + return float.NaN; + } + + /// <summary> + /// Use the command "yield return Timing.SwitchCoroutine(segment, layer);" to switch this coroutine to + /// the given values. + /// </summary> + /// <param name="newSegment">The new segment to run in.</param> + /// <param name="newLayer">The new layer to apply.</param> + public static float SwitchCoroutine(Segment newSegment, int newLayer) + { + ReplacementFunction = (coptr, instance, handle) => + { + ProcessIndex index = instance._handleToIndex[handle]; + instance.RunCoroutineInternal(coptr, newSegment, newLayer, + instance._processTags.ContainsKey(index) ? instance._processTags[index] : null, handle, false); + return null; + }; + + return float.NaN; + } + + /// <summary> + /// Use the command "yield return Timing.SwitchCoroutine(segment, layer, tag);" to switch this coroutine to + /// the given values. + /// </summary> + /// <param name="newSegment">The new segment to run in.</param> + /// <param name="newLayer">The new layer to apply.</param> + /// <param name="newTag">The new tag to apply, or null to remove this coroutine's tag.</param> + public static float SwitchCoroutine(Segment newSegment, int newLayer, string newTag) + { + ReplacementFunction = (coptr, instance, handle) => + { + instance.RunCoroutineInternal(coptr, newSegment, newLayer, newTag, handle, false); + return null; + }; + + return float.NaN; + } + + /// <summary> + /// Use the command "yield return Timing.SwitchCoroutine(tag);" to switch this coroutine to + /// the given tag. + /// </summary> + /// <param name="newTag">The new tag to apply, or null to remove this coroutine's tag.</param> + public static float SwitchCoroutine(string newTag) + { + ReplacementFunction = (coptr, instance, handle) => + { + instance.RemoveTag(instance._handleToIndex[handle]); + if (newTag != null) + instance.AddTag(newTag, instance._handleToIndex[handle]); + return coptr; + }; + return float.NaN; + } + + /// <summary> + /// Use the command "yield return Timing.SwitchCoroutine(layer);" to switch this coroutine to + /// the given layer. + /// </summary> + /// <param name="newLayer">The new layer to apply.</param> + public static float SwitchCoroutine(int newLayer) + { + ReplacementFunction = (coptr, instance, handle) => + { + instance.RemoveLayer(instance._handleToIndex[handle]); + instance.AddLayer(newLayer, instance._handleToIndex[handle]); + return coptr; + }; + + return float.NaN; + } + + /// <summary> + /// Use the command "yield return Timing.SwitchCoroutine(layer, tag);" to switch this coroutine to + /// the given tag. + /// </summary> + /// <param name="newLayer">The new layer to apply.</param> + /// <param name="newTag">The new tag to apply, or null to remove this coroutine's tag.</param> + public static float SwitchCoroutine(int newLayer, string newTag) + { + ReplacementFunction = (coptr, instance, handle) => + { + instance.RemoveLayer(instance._handleToIndex[handle]); + instance.AddLayer(newLayer, instance._handleToIndex[handle]); + instance.RemoveTag(instance._handleToIndex[handle]); + if (newTag != null) + instance.AddTag(newTag, instance._handleToIndex[handle]); + return coptr; + }; + + return float.NaN; + } + + ///// <summary> + ///// Use the command "yield return Timing.WaitUntilDone(wwwObject);" to pause the current + ///// coroutine until the wwwObject is done. + ///// </summary> + ///// <param name="wwwObject">The www object to pause for.</param> + //public static float WaitUntilDone(WWW wwwObject) + //{ + // if(wwwObject == null || wwwObject.isDone) return 0f; + // ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(wwwObject, coptr); + + // return float.NaN; + //} + + private static IEnumerator<float> _StartWhenDone(WWW wwwObject, IEnumerator<float> pausedProc) + { + while (!wwwObject.isDone) + yield return 0f; + + ReplacementFunction = delegate { return pausedProc; }; + yield return float.NaN; + } + + ///// <summary> + ///// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current + ///// coroutine until the operation is done. + ///// </summary> + ///// <param name="operation">The operation variable returned.</param> + //public static float WaitUntilDone(AsyncOperation operation) + //{ + // if (operation == null || operation.isDone) return 0f; + // ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(operation, coptr); + // return float.NaN; + //} + + private static IEnumerator<float> _StartWhenDone(AsyncOperation operation, IEnumerator<float> pausedProc) + { + while (!operation.isDone) + yield return 0f; + + ReplacementFunction = delegate { return pausedProc; }; + yield return float.NaN; + } + +#if !UNITY_4_6 && !UNITY_4_7 && !UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 + /// <summary> + /// Use the command "yield return Timing.WaitUntilDone(operation);" to pause the current + /// coroutine until the operation is done. + /// </summary> + /// <param name="operation">The operation variable returned.</param> + //public static float WaitUntilDone(CustomYieldInstruction operation) + //{ + // if (operation == null || !operation.keepWaiting) return 0f; + // ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(operation, coptr); + // return float.NaN; + //} + + private static IEnumerator<float> _StartWhenDone(CustomYieldInstruction operation, IEnumerator<float> pausedProc) + { + while (operation.keepWaiting) + yield return 0f; + + ReplacementFunction = delegate { return pausedProc; }; + yield return float.NaN; + } +#endif + + /// <summary> + /// Use the command "yield return Timing.WaitUntilTrue(evaluatorFunc);" to pause the current + /// coroutine until the evaluator function returns true. + /// </summary> + /// <param name="evaluatorFunc">The evaluator function.</param> + public static float WaitUntilTrue(System.Func<bool> evaluatorFunc) + { + if (evaluatorFunc == null || evaluatorFunc()) return 0f; + ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(evaluatorFunc, false, coptr); + return float.NaN; + } + + /// <summary> + /// Use the command "yield return Timing.WaitUntilFalse(evaluatorFunc);" to pause the current + /// coroutine until the evaluator function returns false. + /// </summary> + /// <param name="evaluatorFunc">The evaluator function.</param> + public static float WaitUntilFalse(System.Func<bool> evaluatorFunc) + { + if (evaluatorFunc == null || !evaluatorFunc()) return 0f; + ReplacementFunction = (coptr, instance, handle) => _StartWhenDone(evaluatorFunc, true, coptr); + return float.NaN; + } + + private static IEnumerator<float> _StartWhenDone(System.Func<bool> evaluatorFunc, bool continueOn, IEnumerator<float> pausedProc) + { + while (evaluatorFunc() == continueOn) + yield return 0f; + + ReplacementFunction = delegate { return pausedProc; }; + yield return float.NaN; + } + + + + + /// <summary> + /// Calls the specified action after a specified number of seconds. + /// </summary> + /// <param name="delay">The number of seconds to wait before calling the action.</param> + /// <param name="action">The action to call.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallDelayed(float delay, System.Action action) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._DelayedCall(delay, action)); + } + + /// <summary> + /// Calls the specified action after a specified number of seconds. + /// </summary> + /// <param name="delay">The number of seconds to wait before calling the action.</param> + /// <param name="action">The action to call.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallDelayedOnInstance(float delay, System.Action action) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_DelayedCall(delay, action)); + } + + private IEnumerator<float> _DelayedCall(float delay, System.Action action) + { + yield return WaitForSecondsOnInstance(delay); + + action(); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="period">The amount of time between calls.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallPeriodically(float timeframe, float period, System.Action action, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, period, action, onDone), Segment.Update); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="period">The amount of time between calls.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallPeriodicallyOnInstance(float timeframe, float period, System.Action action, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, period, action, onDone), Segment.Update); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="period">The amount of time between calls.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="timing">The timing segment to run in.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallPeriodically(float timeframe, float period, System.Action action, Segment timing, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, period, action, onDone), timing); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="period">The amount of time between calls.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="timing">The timing segment to run in.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallPeriodicallyOnInstance(float timeframe, float period, System.Action action, Segment timing, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, period, action, onDone), timing); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallContinuously(float timeframe, System.Action action, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, 0f, action, onDone), Segment.Update); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallContinuouslyOnInstance(float timeframe, System.Action action, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, 0f, action, onDone), Segment.Update); + } + + /// <summary> + /// Calls the supplied action every frame for a given number of seconds. + /// </summary> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="timing">The timing segment to run in.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallContinuously(float timeframe, System.Action action, Segment timing, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(timeframe, 0f, action, onDone), timing); + } + + /// <summary> + /// Calls the supplied action every frame for a given number of seconds. + /// </summary> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="timing">The timing segment to run in.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallContinuouslyOnInstance(float timeframe, System.Action action, Segment timing, System.Action onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(timeframe, 0f, action, onDone), timing); + } + + private IEnumerator<float> _CallContinuously(float timeframe, float period, System.Action action, System.Action onDone) + { + double startTime = localTime; + while (localTime <= startTime + timeframe) + { + yield return WaitForSecondsOnInstance(period); + + action(); + } + + if (onDone != null) + onDone(); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="reference">A value that will be passed in to the supplied action each period.</param> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="period">The amount of time between calls.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallPeriodically<T>(T reference, float timeframe, float period, + System.Action<T> action, System.Action<T> onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), Segment.Update); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="reference">A value that will be passed in to the supplied action each period.</param> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="period">The amount of time between calls.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallPeriodicallyOnInstance<T>(T reference, float timeframe, float period, + System.Action<T> action, System.Action<T> onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), Segment.Update); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="reference">A value that will be passed in to the supplied action each period.</param> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="period">The amount of time between calls.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="timing">The timing segment to run in.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallPeriodically<T>(T reference, float timeframe, float period, System.Action<T> action, + Segment timing, System.Action<T> onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(reference, timeframe, period, action, onDone), timing); + } + + /// <summary> + /// Calls the supplied action at the given rate for a given number of seconds. + /// </summary> + /// <param name="reference">A value that will be passed in to the supplied action each period.</param> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="period">The amount of time between calls.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="timing">The timing segment to run in.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallPeriodicallyOnInstance<T>(T reference, float timeframe, float period, System.Action<T> action, + Segment timing, System.Action<T> onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(reference, timeframe, period, action, onDone), timing); + } + + /// <summary> + /// Calls the supplied action every frame for a given number of seconds. + /// </summary> + /// <param name="reference">A value that will be passed in to the supplied action each frame.</param> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallContinuously<T>(T reference, float timeframe, System.Action<T> action, System.Action<T> onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update); + } + + /// <summary> + /// Calls the supplied action every frame for a given number of seconds. + /// </summary> + /// <param name="reference">A value that will be passed in to the supplied action each frame.</param> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallContinuouslyOnInstance<T>(T reference, float timeframe, System.Action<T> action, System.Action<T> onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), Segment.Update); + } + + /// <summary> + /// Calls the supplied action every frame for a given number of seconds. + /// </summary> + /// <param name="reference">A value that will be passed in to the supplied action each frame.</param> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="timing">The timing segment to run in.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public static CoroutineHandle CallContinuously<T>(T reference, float timeframe, System.Action<T> action, + Segment timing, System.Action<T> onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutine(Instance._CallContinuously(reference, timeframe, 0f, action, onDone), timing); + } + + /// <summary> + /// Calls the supplied action every frame for a given number of seconds. + /// </summary> + /// <param name="reference">A value that will be passed in to the supplied action each frame.</param> + /// <param name="timeframe">The number of seconds that this function should run.</param> + /// <param name="action">The action to call every frame.</param> + /// <param name="timing">The timing segment to run in.</param> + /// <param name="onDone">An optional action to call when this function finishes.</param> + /// <returns>The handle to the coroutine that is started by this function.</returns> + public CoroutineHandle CallContinuouslyOnInstance<T>(T reference, float timeframe, System.Action<T> action, + Segment timing, System.Action<T> onDone = null) + { + return action == null ? new CoroutineHandle() : RunCoroutineOnInstance(_CallContinuously(reference, timeframe, 0f, action, onDone), timing); + } + + private IEnumerator<float> _CallContinuously<T>(T reference, float timeframe, float period, + System.Action<T> action, System.Action<T> onDone = null) + { + double startTime = localTime; + while (localTime <= startTime + timeframe) + { + yield return WaitForSecondsOnInstance(period); + + action(reference); + } + + if (onDone != null) + onDone(reference); + } + + private struct ProcessData : System.IEquatable<ProcessData> + { + public CoroutineHandle Handle; + //public float PauseTime; + + public bool Equals(ProcessData other) + { + return Handle == other.Handle; + } + + public override bool Equals(object other) + { + if (other is ProcessData) + return Equals((ProcessData)other); + return false; + } + + public override int GetHashCode() + { + return Handle.GetHashCode(); + } + } + + private struct ProcessIndex : System.IEquatable<ProcessIndex> + { + public Segment seg; + public int i; + + public bool Equals(ProcessIndex other) + { + return seg == other.seg && i == other.i; + } + + public override bool Equals(object other) + { + if (other is ProcessIndex) + return Equals((ProcessIndex)other); + return false; + } + + public static bool operator ==(ProcessIndex a, ProcessIndex b) + { + return a.seg == b.seg && a.i == b.i; + } + + public static bool operator !=(ProcessIndex a, ProcessIndex b) + { + return a.seg != b.seg || a.i != b.i; + } + + public override int GetHashCode() + { + return (((int)seg - 4) * (int.MaxValue / 7)) + i; + } + } + + } + + public enum Segment + { + Invalid = -1, + Update, + FixedUpdate, + LateUpdate, + SlowUpdate, + RealtimeUpdate, + EditorUpdate, + EditorSlowUpdate, + EndOfFrame, + ManualTimeframe + } + + /// <summary> + /// A handle for a MEC coroutine. + /// </summary> + public struct CoroutineHandle : System.IEquatable<CoroutineHandle> + { + private static int _nextIndex; + private readonly int _id; + + public byte Key { get { return (byte)(_id & 0x1F); } } + + public CoroutineHandle(byte ind) + { + if (ind > 0x1F) + ind -= 0x1F; + + _id = _nextIndex + ind; + _nextIndex += 0x20; + } + + public bool Equals(CoroutineHandle other) + { + return _id == other._id; + } + + public override bool Equals(object other) + { + if (other is CoroutineHandle) + return Equals((CoroutineHandle)other); + return false; + } + + public static bool operator ==(CoroutineHandle a, CoroutineHandle b) + { + return a._id == b._id; + } + + public static bool operator !=(CoroutineHandle a, CoroutineHandle b) + { + return a._id != b._id; + } + + public override int GetHashCode() + { + return _id; + } + + /// <summary> + /// Get or set the corrosponding coroutine's tag. Null removes the tag or represents no tag assigned. + /// </summary> + public string Tag + { + get { return Timing.GetTag(this); } + set { Timing.SetTag(this, value); } + } + + /// <summary> + /// Get or set the corrosponding coroutine's layer. Null removes the layer or represents no layer assigned. + /// </summary> + public int? Layer + { + get { return Timing.GetLayer(this); } + set + { + if (value == null) + Timing.RemoveLayer(this); + else + Timing.SetLayer(this, (int)value); + } + } + + /// <summary> + /// Get or set the coorsponding coroutine's segment. + /// </summary> + public Segment Segment + { + get { return Timing.GetSegment(this); } + set { Timing.SetSegment(this, value); } + } + + /// <summary> + /// Is true until the coroutine function ends or is killed. Setting this to false will kill the coroutine. + /// </summary> + public bool IsRunning + { + get { return Timing.IsRunning(this); } + set { if (!value) Timing.KillCoroutines(this); } + } + + /// <summary> + /// Is true while the coroutine is paused (but not in a WaitUntilDone holding pattern). Setting this will pause and resume the coroutine. + /// </summary> + public bool IsPaused + { + get { return Timing.IsPaused(this); } + set { if (value) Timing.PauseCoroutines(this); else Timing.ResumeCoroutines(this); } + } + } +} + +public static class MECExtensionMethods +{ + /// <summary> + /// Adds a delay to the beginning of this coroutine. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="timeToDelay">The number of seconds to delay this coroutine.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Delay(this IEnumerator<float> coroutine, float timeToDelay) + { + yield return MovementEffects.Timing.WaitForSeconds(timeToDelay); + + while (coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Adds a delay to the beginning of this coroutine until a function returns true. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="condition">The coroutine will be paused until this function returns true.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Delay(this IEnumerator<float> coroutine, System.Func<bool> condition) + { + while (!condition()) + yield return 0f; + + while (coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Adds a delay to the beginning of this coroutine until a function returns true. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="data">A variable that will be passed into the condition function each time it is tested.</param> + /// <param name="condition">The coroutine will be paused until this function returns true.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Delay<T>(this IEnumerator<float> coroutine, T data, System.Func<T, bool> condition) + { + while (!condition(data)) + yield return 0f; + + while (coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Cancels this coroutine when the supplied game object is destroyed or made inactive. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="gameObject">The GameObject to test.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, GameObject gameObject) + { + while (gameObject && gameObject.activeInHierarchy && coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Cancels this coroutine when the supplied game objects are destroyed or made inactive. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="gameObject1">The first GameObject to test.</param> + /// <param name="gameObject2">The second GameObject to test</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, GameObject gameObject1, GameObject gameObject2) + { + while (gameObject1 && gameObject1.activeInHierarchy && gameObject2 && gameObject2.activeInHierarchy && coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Cancels this coroutine when the supplied game objects are destroyed or made inactive. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="gameObject1">The first GameObject to test.</param> + /// <param name="gameObject2">The second GameObject to test</param> + /// <param name="gameObject3">The third GameObject to test.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, + GameObject gameObject1, GameObject gameObject2, GameObject gameObject3) + { + while (gameObject1 && gameObject1.activeInHierarchy && gameObject2 && gameObject2.activeInHierarchy && + gameObject3 && gameObject3.activeInHierarchy && coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Cancels this coroutine when the supplied function returns false. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="condition">The test function. True for continue, false to stop.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> CancelWith(this IEnumerator<float> coroutine, System.Func<bool> condition) + { + if (condition == null) yield break; + + while (condition() && coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Runs the supplied coroutine immediately after this one. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="nextCoroutine">The coroutine to run next.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Append(this IEnumerator<float> coroutine, IEnumerator<float> nextCoroutine) + { + while (coroutine.MoveNext()) + yield return coroutine.Current; + + if (nextCoroutine != null) + while (nextCoroutine.MoveNext()) + yield return nextCoroutine.Current; + } + + /// <summary> + /// Runs the supplied function immediately after this coroutine finishes. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="onDone">The action to run after this coroutine finishes.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Append(this IEnumerator<float> coroutine, System.Action onDone) + { + while (coroutine.MoveNext()) + yield return coroutine.Current; + + if (onDone != null) + onDone(); + } + + /// <summary> + /// Runs the supplied coroutine immediately before this one. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="lastCoroutine">The coroutine to run first.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Prepend(this IEnumerator<float> coroutine, IEnumerator<float> lastCoroutine) + { + if (lastCoroutine != null) + while (lastCoroutine.MoveNext()) + yield return lastCoroutine.Current; + + while (coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Runs the supplied function immediately before this coroutine starts. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="onStart">The action to run before this coroutine starts.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Prepend(this IEnumerator<float> coroutine, System.Action onStart) + { + if (onStart != null) + onStart(); + + while (coroutine.MoveNext()) + yield return coroutine.Current; + } + + /// <summary> + /// Combines the this coroutine with another and runs them in a combined handle. + /// </summary> + /// <param name="coroutineA">The coroutine handle to act upon.</param> + /// <param name="coroutineB">The coroutine handle to combine.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Superimpose(this IEnumerator<float> coroutineA, IEnumerator<float> coroutineB) + { + return Superimpose(coroutineA, coroutineB, MovementEffects.Timing.Instance); + } + + /// <summary> + /// Combines the this coroutine with another and runs them in a combined handle. + /// </summary> + /// <param name="coroutineA">The coroutine handle to act upon.</param> + /// <param name="coroutineB">The coroutine handle to combine.</param> + /// <param name="instance">The timing instance that this will be run in, if not the default instance.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Superimpose(this IEnumerator<float> coroutineA, IEnumerator<float> coroutineB, MovementEffects.Timing instance) + { + while (coroutineA != null || coroutineB != null) + { + if (coroutineA != null && !(instance.localTime < coroutineA.Current) && !coroutineA.MoveNext()) + coroutineA = null; + + if (coroutineB != null && !(instance.localTime < coroutineB.Current) && !coroutineB.MoveNext()) + coroutineB = null; + + if ((coroutineA != null && float.IsNaN(coroutineA.Current)) || (coroutineB != null && float.IsNaN(coroutineB.Current))) + yield return float.NaN; + else if (coroutineA != null && coroutineB != null) + yield return coroutineA.Current < coroutineB.Current ? coroutineA.Current : coroutineB.Current; + else if (coroutineA == null && coroutineB != null) + yield return coroutineB.Current; + else if (coroutineA != null) + yield return coroutineA.Current; + } + } + + /// <summary> + /// Uses the passed in function to change the return values of this coroutine. + /// </summary> + /// <param name="coroutine">The coroutine handle to act upon.</param> + /// <param name="newReturn">A function that takes the current return value and returns the new return.</param> + /// <returns>The modified coroutine handle.</returns> + public static IEnumerator<float> Hijack(this IEnumerator<float> coroutine, System.Func<float, float> newReturn) + { + if (newReturn == null) yield break; + + while (coroutine.MoveNext()) + yield return newReturn(coroutine.Current); + } +} + diff --git a/YesCommander/Assets/Scripts/Tools/Trinary Software/Timing.cs.meta b/YesCommander/Assets/Scripts/Tools/Trinary Software/Timing.cs.meta new file mode 100644 index 0000000..21e6c1b --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Timing.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2d2433f4570c1404da40af9ea0b12741 +timeCreated: 1510248004 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: a0f854455b10ba44d819f36586b0909b, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/UniqueStringMap.cs b/YesCommander/Assets/Scripts/Tools/UniqueStringMap.cs new file mode 100644 index 0000000..6f5000f --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/UniqueStringMap.cs @@ -0,0 +1,51 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC.Tools +{ + + public class UniqueStringMap + { + private int m_Index = 1; + + private Dictionary<string, int/*ID*/> m_StringMap = new Dictionary<string, int>(); + + public int RegisterString(string str) + { + if(m_StringMap.ContainsKey(str)) + return m_StringMap[str]; + + int index = m_Index++; + m_StringMap.Add(str, index); + + return index; + } + + public int GetStringCode(string str) + { + if (!m_StringMap.ContainsKey(str)) + return 0; + return m_StringMap[str]; + } + + //public int GetOrAddStringCode(string str) + //{ + // if (!m_StringMap.ContainsKey(str)) + // { + // RegisterString(str); + // } + // return m_StringMap[str]; + //} + + public int this[string str] + { + get + { + return GetStringCode(str); + } + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Tools/UniqueStringMap.cs.meta b/YesCommander/Assets/Scripts/Tools/UniqueStringMap.cs.meta new file mode 100644 index 0000000..0e1c43d --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/UniqueStringMap.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f24ea275bd009864e8b1e4c0d64f2316 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Tools/UnityObjectPool.cs b/YesCommander/Assets/Scripts/Tools/UnityObjectPool.cs new file mode 100644 index 0000000..c52c0cd --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/UnityObjectPool.cs @@ -0,0 +1,128 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public class UnityObjectPool<T> : System.IDisposable where T : UnityEngine.Object + { + public interface IPooledInstanceInitializer + { + void InitPooledInstance(T instance); + void DestroyPooledInstance(T instance); + } + + private T _sourceObject; + private Transform _poolParent; + private int _initialSize; + + private IPooledInstanceInitializer _initalizer; + + private List<T> _usedInstances; + private Stack<T> _freeInstances; + + public UnityObjectPool(T sourceObject, Transform poolParent, IPooledInstanceInitializer initializer, int initialSize = 0) + { + Debug.Assert(sourceObject != null); + Debug.Assert(poolParent != null); + Debug.Assert(initializer != null); + Debug.Assert(initialSize >= 0); + + _sourceObject = sourceObject; + _poolParent = poolParent; + _initalizer = initializer; + _initialSize = initialSize; + + _usedInstances = new List<T>(); + _freeInstances = new Stack<T>(initialSize); + + for (int i = 0; i < _initialSize; ++i) + { + T instance = CreateInstance(); + _freeInstances.Push(instance); + } + } + + public T Acquire() + { + T instance; + if (_freeInstances.Count > 0) + { + instance = _freeInstances.Pop(); + } + else + { + instance = CreateInstance(); + } + + _usedInstances.Add(instance); + + return instance; + } + + public void Release(T instance) + { + Debug.Assert(instance != null); + Debug.Assert(!_freeInstances.Contains(instance)); + + bool res = _usedInstances.Remove(instance); + Debug.Assert(res); + _freeInstances.Push(instance); + } + + private T CreateInstance() + { + T instance = Object.Instantiate(_sourceObject, _poolParent); + + // Let the client code initialize the object however it want to + _initalizer.InitPooledInstance(instance); + + return instance; + } + + #region IDisposable Support + private bool _disposed = false; + + protected virtual void Dispose(bool disposing) + { + if (Application.isPlaying) + { + Debug.Assert(!_disposed, "Trying to dispose an pool twice!"); + Debug.Assert(_usedInstances.Count == 0, "Disposing pool before releasing all objects!"); + } + + foreach (T instance in _freeInstances) + { + // We can't destroy a UnityEngine.Object without knowing if it's a Gameobject or Component. Calling Destroy(instance) directly here will give not destroy the Gameobject if it's a component + _initalizer.DestroyPooledInstance(instance); + } + _freeInstances.Clear(); + + _sourceObject = null; + _poolParent = null; + _initalizer = null; + + _disposed = true; + } + + public void Dispose() + { + Dispose(true); + System.GC.SuppressFinalize(this); + } + +#if ENABLE_ASSERTS + ~UnityObjectPool() + { + MainThreadDispatcher.BeginInvoke(() => // Can't call Application.isPlaying in Unity's finalizer thread + { + if (Application.isPlaying) + { + DebugTools.Assert(false, string.Format("Failed to dispose a pool of type {0}!", typeof(T))); + } + }); + } +#endif + #endregion + } +} diff --git a/YesCommander/Assets/Scripts/Tools/UnityObjectPool.cs.meta b/YesCommander/Assets/Scripts/Tools/UnityObjectPool.cs.meta new file mode 100644 index 0000000..b5da7d0 --- /dev/null +++ b/YesCommander/Assets/Scripts/Tools/UnityObjectPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9d3e19936e347184b9b193d4a0688a73 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/AsyncUtils.cs b/YesCommander/Assets/Scripts/Utils/AsyncUtils.cs new file mode 100644 index 0000000..912e646 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/AsyncUtils.cs @@ -0,0 +1,22 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using MovementEffects; + +namespace YC +{ + public static class AsyncUtils + { + /// <summary> + /// 첽 + /// </summary> + /// <param name="asyncAct"></param> + /// <returns></returns> + public static CoroutineHandle AsyncAction(IEnumerator<float> asyncAct) + { + var handle = Timing.Instance.RunCoroutineOnInstance(asyncAct); + return handle; + } + + } +} diff --git a/YesCommander/Assets/Scripts/Utils/AsyncUtils.cs.meta b/YesCommander/Assets/Scripts/Utils/AsyncUtils.cs.meta new file mode 100644 index 0000000..7540550 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/AsyncUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59a14efd34714d1498d15731d63bfdfe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/DontDestroySelf.cs b/YesCommander/Assets/Scripts/Utils/DontDestroySelf.cs new file mode 100644 index 0000000..425cdc2 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/DontDestroySelf.cs @@ -0,0 +1,19 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + [DefaultExecutionOrder(-1000)] + public class DontDestroySelf : MonoBehaviour + { + + private void Awake() + { + DontDestroyOnLoad(this.gameObject); + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Utils/DontDestroySelf.cs.meta b/YesCommander/Assets/Scripts/Utils/DontDestroySelf.cs.meta new file mode 100644 index 0000000..f975f4a --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/DontDestroySelf.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 42ab9985cd771d24caccb1941aa97895 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/Extents.meta b/YesCommander/Assets/Scripts/Utils/Extents.meta new file mode 100644 index 0000000..8dcde94 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Extents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 59524d0919f5fc9459472e22699c9965 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/Extents/TransformExtent.cs b/YesCommander/Assets/Scripts/Utils/Extents/TransformExtent.cs new file mode 100644 index 0000000..c5a004e --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Extents/TransformExtent.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public static class TransformExtent + { + public static void Iterate(this Transform root, Action<Transform> action) + { + if (root == null) + return; + if (action != null) + action(root); + int childCount = root.childCount; + if (childCount == 0) + return; + for (int i = 0; i < childCount; ++i) + { + Transform child = root.GetChild(i); + Iterate(child, action); + } + } + + /// <summary> + /// Enumerates all children in the hierarchy starting at the root object. + /// </summary> + /// <param name="root">Start point of the traversion set</param> + public static IEnumerable<Transform> EnumerateHierarchy(this Transform root) + { + if (root == null) { throw new ArgumentNullException("root"); } + return root.EnumerateHierarchyCore(new List<Transform>(0)); + } + + /// <summary> + /// Enumerates all children in the hierarchy starting at the root object except for the branches in ignore. + /// </summary> + /// <param name="root">Start point of the traversion set</param> + /// <param name="ignore">Transforms and all its children to be ignored</param> + public static IEnumerable<Transform> EnumerateHierarchy(this Transform root, ICollection<Transform> ignore) + { + if (root == null) { throw new ArgumentNullException("root"); } + if (ignore == null) + { + throw new ArgumentNullException("ignore", "Ignore collection can't be null, use EnumerateHierarchy(root) instead."); + } + return root.EnumerateHierarchyCore(ignore); + } + + /// <summary> + /// Enumerates all children in the hierarchy starting at the root object except for the branches in ignore. + /// </summary> + /// <param name="root">Start point of the traversion set</param> + /// <param name="ignore">Transforms and all its children to be ignored</param> + private static IEnumerable<Transform> EnumerateHierarchyCore(this Transform root, ICollection<Transform> ignore) + { + var transformQueue = new Queue<Transform>(); + transformQueue.Enqueue(root); + + while (transformQueue.Count > 0) + { + var parentTransform = transformQueue.Dequeue(); + + if (!parentTransform || ignore.Contains(parentTransform)) { continue; } + + for (var i = 0; i < parentTransform.childCount; i++) + { + transformQueue.Enqueue(parentTransform.GetChild(i)); + } + + yield return parentTransform; + } + } + + public static void SetPositionX(this Transform trans, float value) + { + Vector3 pos = trans.position; + pos.x = value; + trans.position = pos; + } + + public static void SetPositionY(this Transform trans, float value) + { + Vector3 pos = trans.position; + pos.y = value; + trans.position = pos; + } + + public static void SetPositionZ(this Transform trans, float value) + { + Vector3 pos = trans.position; + pos.z = value; + trans.position = pos; + } + + public static void SetLocalPositionX(this Transform trans, float value) + { + Vector3 pos = trans.localPosition; + pos.x = value; + trans.localPosition = pos; + } + + public static void SetLocalPositionY(this Transform trans, float value) + { + Vector3 pos = trans.localPosition; + pos.y = value; + trans.localPosition = pos; + } + + public static void SetLocalPositionZ(this Transform trans, float value) + { + Vector3 pos = trans.localPosition; + pos.z = value; + trans.localPosition = pos; + } + + public static void SetToGlobalScale(this Transform trans, Vector3 desiredScale) + { + Transform t = trans; + Vector3 res = desiredScale; + while (t.parent != null) + { + Transform parent = t.parent; + res.x /= parent.localScale.x; + res.y /= parent.localScale.y; + res.z /= parent.localScale.z; + t = t.parent; + } + Debug.Log("DragonIsleMapRoll scale=" + res); + trans.localScale = res; + } + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Utils/Extents/TransformExtent.cs.meta b/YesCommander/Assets/Scripts/Utils/Extents/TransformExtent.cs.meta new file mode 100644 index 0000000..4b4a4a5 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Extents/TransformExtent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44a8e3b191f80f841b3647664a9d5b35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/FPSScript.cs b/YesCommander/Assets/Scripts/Utils/FPSScript.cs new file mode 100644 index 0000000..cd339ce --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/FPSScript.cs @@ -0,0 +1,33 @@ +using UnityEngine; +using UnityEngine.UI; +using System.Collections; + +namespace YC +{ + public class FPSScript : MonoBehaviour + { + /// <summary> + /// Delta time + /// </summary> + float deltaTime = 0.0f; + + /// <summary> + /// It will be used for printing out fps text on screen + /// </summary> + Text text; + + void Start() + { + text = GetComponent<Text>(); + } + + void Update() + { + deltaTime += (Time.deltaTime - deltaTime) * 0.1f; + float msec = deltaTime * 1000.0f; + float fps = 1.0f / deltaTime; + text.text = string.Format("{0:0.0} ms ({1:0.} fps)", msec, fps); + } + } + +} diff --git a/YesCommander/Assets/Scripts/Utils/FPSScript.cs.meta b/YesCommander/Assets/Scripts/Utils/FPSScript.cs.meta new file mode 100644 index 0000000..d6119a8 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/FPSScript.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: db0f6a04d6782e54bafd5a1865a0dae5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/GameObjectExtensions.cs b/YesCommander/Assets/Scripts/Utils/GameObjectExtensions.cs new file mode 100644 index 0000000..a32986b --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/GameObjectExtensions.cs @@ -0,0 +1,50 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public static class GameObjectExtensions + { + public static void SetParent(this GameObject obj, Transform parent) + { + if (!(obj == null)) + { + obj.transform.SetParent(parent); + } + } + + public static GameObject Find(this GameObject obj, string name) + { + if (obj == null) + { + return null; + } + + Transform transform = obj.transform.Find(name); + if (!(transform != null)) + { + return null; + } + + return transform.gameObject; + } + + public static T GetOrAddComponent<T>(this GameObject go) where T : Component + { + if (go == null) + { + return null; + } + + T val = go.GetComponent<T>(); + if ((Object)val == (Object)null) + { + val = go.AddComponent<T>(); + } + + return val; + } + } +} diff --git a/YesCommander/Assets/Scripts/Utils/GameObjectExtensions.cs.meta b/YesCommander/Assets/Scripts/Utils/GameObjectExtensions.cs.meta new file mode 100644 index 0000000..2dd16b6 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/GameObjectExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 460610b6a0fd5e14ba71f016385ca356 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/LogHelper.cs b/YesCommander/Assets/Scripts/Utils/LogHelper.cs new file mode 100644 index 0000000..c755397 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/LogHelper.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +namespace YC +{ + + public static class LogHelper + { + + public static void LogError(object msg) + { + Debug.LogError(msg); + } + + public static void Log(object msg) + { + Debug.Log(msg); + } + + public static void LogEditorError(object msg) + { + Debug.Log(msg); + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Utils/LogHelper.cs.meta b/YesCommander/Assets/Scripts/Utils/LogHelper.cs.meta new file mode 100644 index 0000000..de4caf3 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/LogHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86b288cdb7866dd4ba565219c11fc94e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/MathUtils.cs b/YesCommander/Assets/Scripts/Utils/MathUtils.cs new file mode 100644 index 0000000..a221adc --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/MathUtils.cs @@ -0,0 +1,27 @@ +using UnityEngine; + +namespace YC +{ + + public static class MathUtils + { + + public static Vector2 Abs(Vector2 v) + { + return new Vector2(Mathf.Abs(v.x), Mathf.Abs(v.y)); + } + + public static Vector2 Max(Vector2 src, float v) + { + return new Vector2(Mathf.Max(src.x, v), Mathf.Max(src.y, v)); + } + + public static void Swap(ref float f1, ref float f2) + { + float t = f1; + f1 = f2; + f2 = t; + } + + } +} diff --git a/YesCommander/Assets/Scripts/Utils/MathUtils.cs.meta b/YesCommander/Assets/Scripts/Utils/MathUtils.cs.meta new file mode 100644 index 0000000..8e8b33c --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/MathUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b829e1e17fa796408f3a7b1a42ed1ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/SetSortingOrder.cs b/YesCommander/Assets/Scripts/Utils/SetSortingOrder.cs new file mode 100644 index 0000000..05dc315 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/SetSortingOrder.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public class SetSortingOrder : MonoBehaviour + { + public int sortingOrder; + + public void ForceRefreshSortingOrder() + { + transform.Iterate((trans) => + { + Renderer render = trans.gameObject.GetComponent<Renderer>(); + if (render != null) + { + render.sortingOrder += sortingOrder; + } + }); + } + + public void Start() + { + ForceRefreshSortingOrder(); + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Utils/SetSortingOrder.cs.meta b/YesCommander/Assets/Scripts/Utils/SetSortingOrder.cs.meta new file mode 100644 index 0000000..b12ae8d --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/SetSortingOrder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11a34b72b3ea9804c8fc1ed3f61148c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/StringUtils.cs b/YesCommander/Assets/Scripts/Utils/StringUtils.cs new file mode 100644 index 0000000..b4946d5 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/StringUtils.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; +using UnityEngine; +using VSCodeEditor; + +namespace YC +{ + public class GizmosColor : IDisposable + { + Color precolor; + + public GizmosColor(Color c) + { + precolor = Gizmos.color; + Gizmos.color = c; + } + + public void Dispose() + { + Gizmos.color = precolor; + } + } + + + public class StringUtils + { + + public static byte[] GetHash(string inputString) + { + using (HashAlgorithm algorithm = SHA256.Create()) + return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); + } + + public static string GetHashString(string inputString) + { + StringBuilder sb = new StringBuilder(); + foreach (byte b in GetHash(inputString)) + sb.Append(b.ToString("X2")); + + return sb.ToString(); + } + + } + +} diff --git a/YesCommander/Assets/Scripts/Utils/StringUtils.cs.meta b/YesCommander/Assets/Scripts/Utils/StringUtils.cs.meta new file mode 100644 index 0000000..555da6c --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/StringUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 917c8c50054333a45b8925c7b33ffdf5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/TransformUtils.cs b/YesCommander/Assets/Scripts/Utils/TransformUtils.cs new file mode 100644 index 0000000..6e0d301 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/TransformUtils.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public static class TransformUtils + { + public static void ResetLocal(this Transform transform) + { + transform.localPosition = Vector3.zero; + transform.localRotation = Quaternion.identity; + transform.localScale = Vector3.one; + } + } + +} diff --git a/YesCommander/Assets/Scripts/Utils/TransformUtils.cs.meta b/YesCommander/Assets/Scripts/Utils/TransformUtils.cs.meta new file mode 100644 index 0000000..ef5cea8 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/TransformUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 644de0d155567684eb770eafd8e91ac4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/Vector2Extension.cs b/YesCommander/Assets/Scripts/Utils/Vector2Extension.cs new file mode 100644 index 0000000..a341bfd --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Vector2Extension.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; +using Unity.VisualScripting; +using UnityEditor; +using UnityEngine; + +namespace YC +{ + + public static class Vector2Extension + { + + public static Vector3 ConvertToVector3(Vector2 src) + { + Vector3 dst = new Vector3(); + dst.x = src.x; + dst.y = src.y; + dst.z = 0; + return dst; + } + + public static Vector3 ToVector3(this Vector2 src) + { + return ConvertToVector3(src); + } + + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Utils/Vector2Extension.cs.meta b/YesCommander/Assets/Scripts/Utils/Vector2Extension.cs.meta new file mode 100644 index 0000000..3acd9ed --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Vector2Extension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4919fc0478a262544b3b7149ec7a331d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/Vector3Extension.cs b/YesCommander/Assets/Scripts/Utils/Vector3Extension.cs new file mode 100644 index 0000000..f4f716c --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Vector3Extension.cs @@ -0,0 +1,31 @@ +using System.Collections; +using System.Collections.Generic; +using Unity.VisualScripting; +using UnityEditor; +using UnityEngine; + +namespace YC +{ + + public static class Vector3Extension + { + + public static Vector2 xy(this Vector3 src) + { + Vector2 xy = new Vector2(); + xy.x = src.x; + xy.y = src.y; + return xy; + } + + public static Vector2 ToVector2(this Vector3 src) + { + Vector2 xy = new Vector2(); + xy.x = src.x; + xy.y = src.y; + return xy; + } + + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Utils/Vector3Extension.cs.meta b/YesCommander/Assets/Scripts/Utils/Vector3Extension.cs.meta new file mode 100644 index 0000000..e563122 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Vector3Extension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3ec9d2ccbb46814eaa97fe04f1089e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/Scripts/Utils/Vector4Extension.cs b/YesCommander/Assets/Scripts/Utils/Vector4Extension.cs new file mode 100644 index 0000000..76955dd --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Vector4Extension.cs @@ -0,0 +1,39 @@ +using System.Collections; +using System.Collections.Generic; +using Unity.VisualScripting; +using UnityEditor; +using UnityEngine; + +namespace YC +{ + + public static class Vector4Extension + { + + public static Vector2 xy(this Vector4 src) + { + Vector2 xy = new Vector2(); + xy.x = src.x; + xy.y = src.y; + return xy; + } + + public static Vector2 zw(this Vector4 src) + { + Vector2 zw = new Vector2(); + zw.x = src.z; + zw.y = src.w; + return zw; + } + + public static Vector2 ToVector2(this Vector4 src) + { + Vector2 xy = new Vector2(); + xy.x = src.x; + xy.y = src.y; + return xy; + } + + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/Scripts/Utils/Vector4Extension.cs.meta b/YesCommander/Assets/Scripts/Utils/Vector4Extension.cs.meta new file mode 100644 index 0000000..b2d1dc0 --- /dev/null +++ b/YesCommander/Assets/Scripts/Utils/Vector4Extension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8a622b0bd09ab0242af55f6fb5660eda +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty.meta b/YesCommander/Assets/ThirdParty.meta new file mode 100644 index 0000000..48b4948 --- /dev/null +++ b/YesCommander/Assets/ThirdParty.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fddc01bb20c52664cbe6ad9bfba1721f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser.meta b/YesCommander/Assets/ThirdParty/CSV-Parser.meta new file mode 100644 index 0000000..c49c672 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f2fe36487065064e821650e6429d9d9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/.gitignore b/YesCommander/Assets/ThirdParty/CSV-Parser/.gitignore new file mode 100644 index 0000000..19f0983 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/.gitignore @@ -0,0 +1,15 @@ +obj/ +bin/ +.vs/ +.vscode/ +.idea/ +*.DotSettings +*.user + +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db
\ No newline at end of file diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.meta new file mode 100644 index 0000000..1b9c4db --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 85cabb48324945548a8b18124ed3918a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.sln b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.sln new file mode 100644 index 0000000..9e25d75 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSV Parser", "CSV Parser\CSV Parser.csproj", "{BB50E0DE-75A1-4E9A-AEFA-A823A434EFF3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{C7E7ACFD-66DB-4296-8536-4418728F3A5D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BB50E0DE-75A1-4E9A-AEFA-A823A434EFF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB50E0DE-75A1-4E9A-AEFA-A823A434EFF3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB50E0DE-75A1-4E9A-AEFA-A823A434EFF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB50E0DE-75A1-4E9A-AEFA-A823A434EFF3}.Release|Any CPU.Build.0 = Release|Any CPU + {C7E7ACFD-66DB-4296-8536-4418728F3A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7E7ACFD-66DB-4296-8536-4418728F3A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7E7ACFD-66DB-4296-8536-4418728F3A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7E7ACFD-66DB-4296-8536-4418728F3A5D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.sln.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.sln.meta new file mode 100644 index 0000000..3f5d3cf --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.sln.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2d428b7f5708308489ff910a5977b13c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/CSV Parser.csproj b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/CSV Parser.csproj new file mode 100644 index 0000000..bf48c73 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/CSV Parser.csproj @@ -0,0 +1,13 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net6.0</TargetFramework> + <RootNamespace>CSV_Parser</RootNamespace> + <LangVersion>7.3</LangVersion> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="System.Memory" Version="4.5.4" /> + </ItemGroup> + +</Project> diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/CSV Parser.csproj.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/CSV Parser.csproj.meta new file mode 100644 index 0000000..da4f4a8 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/CSV Parser.csproj.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c9cc963a877064748a9e6fe4397c807f +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src.meta new file mode 100644 index 0000000..8e65917 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3e17c685928714443973ed558020bdee +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/CSVParser.cs b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/CSVParser.cs new file mode 100644 index 0000000..c886c19 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/CSVParser.cs @@ -0,0 +1,181 @@ +/* + * CSV Parser for C#. + * + * These codes are licensed under CC0. + * https://github.com/yutokun/CSV-Parser + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace yutokun +{ + public static class CSVParser + { + /// <summary> + /// Load CSV data from specified path. + /// </summary> + /// <param name="path">CSV file path.</param> + /// <param name="delimiter">Delimiter.</param> + /// <param name="encoding">Type of text encoding. (default UTF-8)</param> + /// <returns>Nested list that CSV parsed.</returns> + public static List<List<string>> LoadFromPath(string path, Delimiter delimiter = Delimiter.Auto, Encoding encoding = null) + { + encoding = encoding ?? Encoding.UTF8; + + if (delimiter == Delimiter.Auto) + { + delimiter = EstimateDelimiter(path); + } + + var data = File.ReadAllText(path, encoding); + return Parse(data, delimiter); + } + + /// <summary> + /// Load CSV data asynchronously from specified path. + /// </summary> + /// <param name="path">CSV file path.</param> + /// <param name="delimiter">Delimiter.</param> + /// <param name="encoding">Type of text encoding. (default UTF-8)</param> + /// <returns>Nested list that CSV parsed.</returns> + public static async Task<List<List<string>>> LoadFromPathAsync(string path, Delimiter delimiter = Delimiter.Auto, Encoding encoding = null) + { + encoding = encoding ?? Encoding.UTF8; + + if (delimiter == Delimiter.Auto) + { + delimiter = EstimateDelimiter(path); + } + + using (var reader = new StreamReader(path, encoding)) + { + var data = await reader.ReadToEndAsync(); + return Parse(data, delimiter); + } + } + + static Delimiter EstimateDelimiter(string path) + { + var extension = Path.GetExtension(path); + if (extension.Equals(".csv", StringComparison.OrdinalIgnoreCase)) + { + return Delimiter.Comma; + } + + if (extension.Equals(".tsv", StringComparison.OrdinalIgnoreCase)) + { + return Delimiter.Tab; + } + + throw new Exception($"Delimiter estimation failed. Unknown Extension: {extension}"); + } + + /// <summary> + /// Load CSV data from string. + /// </summary> + /// <param name="data">CSV string</param> + /// <param name="delimiter">Delimiter.</param> + /// <returns>Nested list that CSV parsed.</returns> + public static List<List<string>> LoadFromString(string data, Delimiter delimiter = Delimiter.Comma) + { + if (delimiter == Delimiter.Auto) throw new InvalidEnumArgumentException("Delimiter estimation from string is not supported."); + return Parse(data, delimiter); + } + + static List<List<string>> Parse(string data, Delimiter delimiter) + { + ConvertToCrlf(ref data); + + var sheet = new List<List<string>>(); + var row = new List<string>(); + var cell = new StringBuilder(); + var insideQuoteCell = false; + var start = 0; + + var delimiterSpan = delimiter.ToChar().ToString().AsSpan(); + var crlfSpan = "\r\n".AsSpan(); + var oneDoubleQuotSpan = "\"".AsSpan(); + var twoDoubleQuotSpan = "\"\"".AsSpan(); + + while (start < data.Length) + { + var length = start <= data.Length - 2 ? 2 : 1; + var span = data.AsSpan(start, length); + + if (span.StartsWith(delimiterSpan)) + { + if (insideQuoteCell) + { + cell.Append(delimiter.ToChar()); + } + else + { + AddCell(row, cell); + } + + start += 1; + } + else if (span.StartsWith(crlfSpan)) + { + if (insideQuoteCell) + { + cell.Append("\r\n"); + } + else + { + AddCell(row, cell); + AddRow(sheet, ref row); + } + + start += 2; + } + else if (span.StartsWith(twoDoubleQuotSpan)) + { + cell.Append("\""); + start += 2; + } + else if (span.StartsWith(oneDoubleQuotSpan)) + { + insideQuoteCell = !insideQuoteCell; + start += 1; + } + else + { + cell.Append(span[0]); + start += 1; + } + } + + if (row.Count > 0 || cell.Length > 0) + { + AddCell(row, cell); + AddRow(sheet, ref row); + } + + return sheet; + } + + static void AddCell(List<string> row, StringBuilder cell) + { + row.Add(cell.ToString()); + cell.Length = 0; // Old C#. + } + + static void AddRow(List<List<string>> sheet, ref List<string> row) + { + sheet.Add(row); + row = new List<string>(); + } + + static void ConvertToCrlf(ref string data) + { + data = Regex.Replace(data, @"\r\n|\r|\n", "\r\n"); + } + } +} diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/CSVParser.cs.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/CSVParser.cs.meta new file mode 100644 index 0000000..fb3cd58 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/CSVParser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1dcf43e5bd8e0204580fc6899a086b00 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/Delimiter.cs b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/Delimiter.cs new file mode 100644 index 0000000..b32dcc3 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/Delimiter.cs @@ -0,0 +1,9 @@ +namespace yutokun +{ + public enum Delimiter + { + Auto, + Comma, + Tab + } +} diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/Delimiter.cs.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/Delimiter.cs.meta new file mode 100644 index 0000000..8f7cf00 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/Delimiter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0e2bb27fdbb714468ca87aeaf607331 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/DelimiterExtensions.cs b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/DelimiterExtensions.cs new file mode 100644 index 0000000..a38371d --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/DelimiterExtensions.cs @@ -0,0 +1,24 @@ +using System; +using System.ComponentModel; + +namespace yutokun +{ + public static class DelimiterExtensions + { + public static char ToChar(this Delimiter delimiter) + { + // C# 7.3: Unity 2018.2 - 2020.1 Compatible + switch (delimiter) + { + case Delimiter.Auto: + throw new InvalidEnumArgumentException("Could not return char of Delimiter.Auto."); + case Delimiter.Comma: + return ','; + case Delimiter.Tab: + return '\t'; + default: + throw new ArgumentOutOfRangeException(nameof(delimiter), delimiter, null); + } + } + } +} diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/DelimiterExtensions.cs.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/DelimiterExtensions.cs.meta new file mode 100644 index 0000000..d98b86d --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/DelimiterExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b9ab5b183dd311459e9893fe735bea6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/LICENSE b/YesCommander/Assets/ThirdParty/CSV-Parser/LICENSE new file mode 100644 index 0000000..8a9b3dc --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/LICENSE @@ -0,0 +1,35 @@ +For unique parts of the repository + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to <http://unlicense.org> + +-------------------------------------------------------------------------------------------- + +For .NET Runtimes (included in the .unitypackage for old Unity) + +The MIT License +Copyright (c) .NET Foundation and Contributors + +https://github.com/dotnet/runtime/blob/main/LICENSE.TXT
\ No newline at end of file diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/LICENSE.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/LICENSE.meta new file mode 100644 index 0000000..1df5cd4 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e44599b63f0a77d408c64fcf15e388e1 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/README.md b/YesCommander/Assets/ThirdParty/CSV-Parser/README.md new file mode 100644 index 0000000..c87aaef --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/README.md @@ -0,0 +1,102 @@ +# CSV Parser for C# + +[](https://github.com/yutokun/CSV-Parser/actions/workflows/test.yml) + +CSV Parser with CC0 License. + +Best for: + +- [Unity](https://unity3d.com/) projects that requires cross-platform CSV parser. (maybe works on any platform supported by Unity) +- Commercial products that you could not display the license. + +## Prerequisites + +| Environment | Prerequisites | +| ----------------------- | ------------------------------------------------------------------------- | +| Unity 2019.2 or later | None | +| Unity 2019.1 or earlier | .NET 4.x Equivalent | +| .NET Project | [System.Memory](https://www.nuget.org/packages/System.Memory/) from NuGet | + +## Download + +Download zip or unitypackage from [**Releases**](https://github.com/yutokun/CSV-Parser/releases). + +## Usage + +### Methods + +This returns CSV data as `List<List<string>>`. + +```c# +CSVParser.LoadFromString(string data) +``` + +or + +```c# +CSVParser.LoadFromPath(string path, Encoding encoding = null) +``` + +### Examples + +```c# +var sheet = CSVParser.LoadFromString(csvString); + +var styled = new StringBuilder(); +foreach (var row in sheet) +{ + styled.Append("| "); + + foreach (var cell in row) + { + styled.Append(cell); + styled.Append(" | "); + } + + styled.AppendLine(); +} + +Debug.Log(styled.ToString()); // Unity +Console.WriteLine(styled.ToString()); // C# +``` + +## Specs + +Compliant with [RFC 4180](http://www.ietf.org/rfc/rfc4180.txt). + +- Correctly parse new lines, commas, quotation marks inside cell. +- Escaped double quotes. +- Some encoding types. (default UTF-8) + +## Beta + +- Tab delimiter support + +- Async loading + +## Development + +The repository contains multiple types of newline code. Run `git config core.autocrlf false` in your local repository. + +## Why this repo has multiple Unity Examples? + +One of the reasons is to check operation in different Unity versions. Another one is to build .unitypackage with CI. + +Unity changes a lot between their Tech Streams. It leads different requisites / dependency to the parser. Affected changes below. + +| Versions | Difference | +| ----------------- | ---------------------------------------------- | +| 2019.1 and 2019.2 | Has Scripting Runtime Version selector or not. | +| 2021.1 and 2021.2 | Requires additional DLLs or not. | + +## License + +### Unique part of the repository + +[CC0](https://creativecommons.org/publicdomain/zero/1.0/) or [Public Domain](LICENSE) + +### .NET Runtimes (included in the .unitypackage for old Unity) + +[The MIT License](https://github.com/dotnet/runtime/blob/main/LICENSE.TXT) + +Copyright (c) .NET Foundation and Contributors diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/README.md.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/README.md.meta new file mode 100644 index 0000000..97d3fa3 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 369bbbb3341b6ec4583dce723dc805f4 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/RELEASE.md b/YesCommander/Assets/ThirdParty/CSV-Parser/RELEASE.md new file mode 100644 index 0000000..99ec2e9 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/RELEASE.md @@ -0,0 +1,14 @@ +# Change + +- Updated project to .NET 6. It because deprecation of .NET 5 by GitHub Actions. + - CSV Parser itself has same prerequisites as before. + +# Fix + +- Fixed a bug that last cell will be ignored when single cell rows not ending with CRLF. (Thank you so much @gmichaudAniki !) + +# Misc. Changes + +- Fixed some errors in README. + +- Updated CI to compliant with Node.js 16.
\ No newline at end of file diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/RELEASE.md.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/RELEASE.md.meta new file mode 100644 index 0000000..cc47df1 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/RELEASE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: baea5598d0dce0441a1b60a3364f3cc7 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/Tests.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/Tests.meta new file mode 100644 index 0000000..c219211 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 229bb474319e02440b7fde15814d354e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/Unity Examples.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/Unity Examples.meta new file mode 100644 index 0000000..eb2f7be --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/Unity Examples.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6e45f679bb3e6f54a8ae2adea95ddc1e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/global.json b/YesCommander/Assets/ThirdParty/CSV-Parser/global.json new file mode 100644 index 0000000..1bcf6c0 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "6.0.0", + "rollForward": "latestMinor", + "allowPrerelease": false + } +}
\ No newline at end of file diff --git a/YesCommander/Assets/ThirdParty/CSV-Parser/global.json.meta b/YesCommander/Assets/ThirdParty/CSV-Parser/global.json.meta new file mode 100644 index 0000000..b2d9917 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/CSV-Parser/global.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d4150b58aa163dc4d8a2aa3241ae51ea +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson.meta b/YesCommander/Assets/ThirdParty/LitJson.meta new file mode 100644 index 0000000..662dc44 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9ccf60bb6d211e43b32dcc579bc9c21 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/IJsonWrapper.cs b/YesCommander/Assets/ThirdParty/LitJson/IJsonWrapper.cs new file mode 100644 index 0000000..db0963a --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/IJsonWrapper.cs @@ -0,0 +1,60 @@ +#region Header +/** + * IJsonWrapper.cs + * Interface that represents a type capable of handling all kinds of JSON + * data. This is mainly used when mapping objects through JsonMapper, and + * it's implemented by JsonData. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System.Collections; +using System.Collections.Specialized; + + +namespace LitJson +{ + public enum JsonType + { + None, + + Object, + Array, + String, + Int, + Long, + Double, + Boolean + } + + public interface IJsonWrapper : IList, IOrderedDictionary + { + bool IsArray { get; } + bool IsBoolean { get; } + bool IsDouble { get; } + bool IsInt { get; } + bool IsLong { get; } + bool IsObject { get; } + bool IsString { get; } + + bool GetBoolean (); + double GetDouble (); + int GetInt (); + JsonType GetJsonType (); + long GetLong (); + string GetString (); + + void SetBoolean (bool val); + void SetDouble (double val); + void SetInt (int val); + void SetJsonType (JsonType type); + void SetLong (long val); + void SetString (string val); + + string ToJson (); + void ToJson (JsonWriter writer); + } +} diff --git a/YesCommander/Assets/ThirdParty/LitJson/IJsonWrapper.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/IJsonWrapper.cs.meta new file mode 100644 index 0000000..14fc748 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/IJsonWrapper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: de017f99299ca2e45adc9613360567df +timeCreated: 1474349755 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonData.cs b/YesCommander/Assets/ThirdParty/LitJson/JsonData.cs new file mode 100644 index 0000000..fd34425 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonData.cs @@ -0,0 +1,1032 @@ +#region Header +/** + * JsonData.cs + * Generic type to hold JSON data (objects, arrays, and so on). This is + * the default type returned by JsonMapper.ToObject(). + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; + + +namespace LitJson +{ + public sealed class JsonData : IJsonWrapper, IEquatable<JsonData> + { + #region Fields + private IList<JsonData> inst_array; + private bool inst_boolean; + private double inst_double; + private int inst_int; + private long inst_long; + private IDictionary<string, JsonData> inst_object; + private string inst_string; + private string json; + private JsonType type; + + // Used to implement the IOrderedDictionary interface + private IList<KeyValuePair<string, JsonData>> object_list; + #endregion + + + #region Properties + public int Count { + get { return EnsureCollection ().Count; } + } + + public bool IsArray { + get { return type == JsonType.Array; } + } + + public bool IsBoolean { + get { return type == JsonType.Boolean; } + } + + public bool IsDouble { + get { return type == JsonType.Double; } + } + + public bool IsInt { + get { return type == JsonType.Int; } + } + + public bool IsLong { + get { return type == JsonType.Long; } + } + + public bool IsObject { + get { return type == JsonType.Object; } + } + + public bool IsString { + get { return type == JsonType.String; } + } + + public IDictionary<String, JsonData> Inst_Object + { + get { + if (type == JsonType.Object) + return inst_object; + else + return null; + } + } + #endregion + + + #region ICollection Properties + int ICollection.Count { + get { + return Count; + } + } + + bool ICollection.IsSynchronized { + get { + return EnsureCollection ().IsSynchronized; + } + } + + object ICollection.SyncRoot { + get { + return EnsureCollection ().SyncRoot; + } + } + #endregion + + + #region IDictionary Properties + bool IDictionary.IsFixedSize { + get { + return EnsureDictionary ().IsFixedSize; + } + } + + bool IDictionary.IsReadOnly { + get { + return EnsureDictionary ().IsReadOnly; + } + } + + ICollection IDictionary.Keys { + get { + EnsureDictionary (); + IList<string> keys = new List<string> (); + + foreach (KeyValuePair<string, JsonData> entry in + object_list) { + keys.Add (entry.Key); + } + + return (ICollection) keys; + } + } + + ICollection IDictionary.Values { + get { + EnsureDictionary (); + IList<JsonData> values = new List<JsonData> (); + + foreach (KeyValuePair<string, JsonData> entry in + object_list) { + values.Add (entry.Value); + } + + return (ICollection) values; + } + } + #endregion + + + + #region IJsonWrapper Properties + bool IJsonWrapper.IsArray { + get { return IsArray; } + } + + bool IJsonWrapper.IsBoolean { + get { return IsBoolean; } + } + + bool IJsonWrapper.IsDouble { + get { return IsDouble; } + } + + bool IJsonWrapper.IsInt { + get { return IsInt; } + } + + bool IJsonWrapper.IsLong { + get { return IsLong; } + } + + bool IJsonWrapper.IsObject { + get { return IsObject; } + } + + bool IJsonWrapper.IsString { + get { return IsString; } + } + #endregion + + + #region IList Properties + bool IList.IsFixedSize { + get { + return EnsureList ().IsFixedSize; + } + } + + bool IList.IsReadOnly { + get { + return EnsureList ().IsReadOnly; + } + } + #endregion + + + #region IDictionary Indexer + object IDictionary.this[object key] { + get { + return EnsureDictionary ()[key]; + } + + set { + if (! (key is String)) + throw new ArgumentException ( + "The key has to be a string"); + + JsonData data = ToJsonData (value); + + this[(string) key] = data; + } + } + #endregion + + + #region IOrderedDictionary Indexer + object IOrderedDictionary.this[int idx] { + get { + EnsureDictionary (); + return object_list[idx].Value; + } + + set { + EnsureDictionary (); + JsonData data = ToJsonData (value); + + KeyValuePair<string, JsonData> old_entry = object_list[idx]; + + inst_object[old_entry.Key] = data; + + KeyValuePair<string, JsonData> entry = + new KeyValuePair<string, JsonData> (old_entry.Key, data); + + object_list[idx] = entry; + } + } + #endregion + + + #region IList Indexer + object IList.this[int index] { + get { + return EnsureList ()[index]; + } + + set { + EnsureList (); + JsonData data = ToJsonData (value); + + this[index] = data; + } + } + #endregion + + + #region Public Indexers + public JsonData this[string prop_name] { + get { + EnsureDictionary (); + return inst_object[prop_name]; + } + + set { + EnsureDictionary (); + + KeyValuePair<string, JsonData> entry = + new KeyValuePair<string, JsonData> (prop_name, value); + + if (inst_object.ContainsKey (prop_name)) { + for (int i = 0; i < object_list.Count; i++) { + if (object_list[i].Key == prop_name) { + object_list[i] = entry; + break; + } + } + } else + object_list.Add (entry); + + inst_object[prop_name] = value; + + json = null; + } + } + + public JsonData this[int index] { + get { + EnsureCollection (); + + if (type == JsonType.Array) + return inst_array[index]; + + return object_list[index].Value; + } + + set { + EnsureCollection (); + + if (type == JsonType.Array) + inst_array[index] = value; + else { + KeyValuePair<string, JsonData> entry = object_list[index]; + KeyValuePair<string, JsonData> new_entry = + new KeyValuePair<string, JsonData> (entry.Key, value); + + object_list[index] = new_entry; + inst_object[entry.Key] = value; + } + + json = null; + } + } + #endregion + + + #region Constructors + public JsonData () + { + } + + public JsonData (bool boolean) + { + type = JsonType.Boolean; + inst_boolean = boolean; + } + + public JsonData (double number) + { + type = JsonType.Double; + inst_double = number; + } + + public JsonData (int number) + { + type = JsonType.Int; + inst_int = number; + } + + public JsonData (long number) + { + type = JsonType.Long; + inst_long = number; + } + + public JsonData (object obj) + { + if (obj is Boolean) { + type = JsonType.Boolean; + inst_boolean = (bool) obj; + return; + } + + if (obj is Double) { + type = JsonType.Double; + inst_double = (double) obj; + return; + } + + if (obj is Int32) { + type = JsonType.Int; + inst_int = (int) obj; + return; + } + + if (obj is Int64) { + type = JsonType.Long; + inst_long = (long) obj; + return; + } + + if (obj is String) { + type = JsonType.String; + inst_string = (string) obj; + return; + } + + throw new ArgumentException ( + "Unable to wrap the given object with JsonData"); + } + + public JsonData (string str) + { + type = JsonType.String; + inst_string = str; + } + #endregion + + + #region Implicit Conversions + public static implicit operator JsonData (Boolean data) + { + return new JsonData (data); + } + + public static implicit operator JsonData (Double data) + { + return new JsonData (data); + } + + public static implicit operator JsonData (Int32 data) + { + return new JsonData (data); + } + + public static implicit operator JsonData (Int64 data) + { + return new JsonData (data); + } + + public static implicit operator JsonData (String data) + { + return new JsonData (data); + } + #endregion + + + #region Explicit Conversions + public static explicit operator Boolean (JsonData data) + { + if (data.type != JsonType.Boolean) + throw new InvalidCastException ( + "Instance of JsonData doesn't hold a boolean, type is " + data.type); + + return data.inst_boolean; + } + + public static explicit operator Double (JsonData data) + { + if (data.type != JsonType.Double) + throw new InvalidCastException ( + "Instance of JsonData doesn't hold a double, type is " + data.type); + + return data.inst_double; + } + + public static explicit operator Single (JsonData data) + { + if(data.type == JsonType.Double) + { + return (Single)data.inst_double; + } + + if(data.type == JsonType.Int) + { + return (Single)data.inst_int; + } + + throw new InvalidCastException( + "Instance of JsonData doesn't hold a Single, type is " + data.type); + } + + public static explicit operator Int32 (JsonData data) + { + if (data.type != JsonType.Int) + throw new InvalidCastException ( + "Instance of JsonData doesn't hold an int, type is "+ data.type); + + return data.inst_int; + } + + public static explicit operator Int64 (JsonData data) + { + if (data.type != JsonType.Long) + throw new InvalidCastException ( + "Instance of JsonData doesn't hold an int64, type is " + data.type); + + return data.inst_long; + } + + public static explicit operator String (JsonData data) + { + if (data.type != JsonType.String) + throw new InvalidCastException ( + "Instance of JsonData doesn't hold a string, type is " + data.type); + + return data.inst_string; + } + #endregion + + + #region ICollection Methods + void ICollection.CopyTo (Array array, int index) + { + EnsureCollection ().CopyTo (array, index); + } + #endregion + + + #region IDictionary Methods + void IDictionary.Add (object key, object value) + { + JsonData data = ToJsonData (value); + + EnsureDictionary ().Add (key, data); + + KeyValuePair<string, JsonData> entry = + new KeyValuePair<string, JsonData> ((string) key, data); + object_list.Add (entry); + + json = null; + } + + void IDictionary.Clear () + { + EnsureDictionary ().Clear (); + object_list.Clear (); + json = null; + } + + bool IDictionary.Contains (object key) + { + return EnsureDictionary ().Contains (key); + } + + IDictionaryEnumerator IDictionary.GetEnumerator () + { + return ((IOrderedDictionary) this).GetEnumerator (); + } + + void IDictionary.Remove (object key) + { + EnsureDictionary ().Remove (key); + + for (int i = 0; i < object_list.Count; i++) { + if (object_list[i].Key == (string) key) { + object_list.RemoveAt (i); + break; + } + } + + json = null; + } + #endregion + + + #region IEnumerable Methods + IEnumerator IEnumerable.GetEnumerator () + { + return EnsureCollection ().GetEnumerator (); + } + #endregion + + + #region IJsonWrapper Methods + bool IJsonWrapper.GetBoolean () + { + if (type != JsonType.Boolean) + throw new InvalidOperationException ( + "JsonData instance doesn't hold a boolean, type is " + type); + + return inst_boolean; + } + + double IJsonWrapper.GetDouble () + { + if (type != JsonType.Double) + throw new InvalidOperationException ( + "JsonData instance doesn't hold a double, type is " + type); + + return inst_double; + } + + int IJsonWrapper.GetInt () + { + if (type != JsonType.Int) + throw new InvalidOperationException ( + "JsonData instance doesn't hold an int, type is " + type); + + return inst_int; + } + + long IJsonWrapper.GetLong () + { + if (type != JsonType.Long) + throw new InvalidOperationException ( + "JsonData instance doesn't hold a long, type is " + type); + + return inst_long; + } + + string IJsonWrapper.GetString () + { + if (type != JsonType.String) + throw new InvalidOperationException ( + "JsonData instance doesn't hold a string, type is " + type); + + return inst_string; + } + + void IJsonWrapper.SetBoolean (bool val) + { + type = JsonType.Boolean; + inst_boolean = val; + json = null; + } + + void IJsonWrapper.SetDouble (double val) + { + type = JsonType.Double; + inst_double = val; + json = null; + } + + void IJsonWrapper.SetInt (int val) + { + type = JsonType.Int; + inst_int = val; + json = null; + } + + void IJsonWrapper.SetLong (long val) + { + type = JsonType.Long; + inst_long = val; + json = null; + } + + void IJsonWrapper.SetString (string val) + { + type = JsonType.String; + inst_string = val; + json = null; + } + + string IJsonWrapper.ToJson () + { + return ToJson (); + } + + void IJsonWrapper.ToJson (JsonWriter writer) + { + ToJson (writer); + } + #endregion + + + #region IList Methods + int IList.Add (object value) + { + return Add (value); + } + + void IList.Clear () + { + EnsureList ().Clear (); + json = null; + } + + bool IList.Contains (object value) + { + return EnsureList ().Contains (value); + } + + int IList.IndexOf (object value) + { + return EnsureList ().IndexOf (value); + } + + void IList.Insert (int index, object value) + { + EnsureList ().Insert (index, value); + json = null; + } + + void IList.Remove (object value) + { + EnsureList ().Remove (value); + json = null; + } + + void IList.RemoveAt (int index) + { + EnsureList ().RemoveAt (index); + json = null; + } + #endregion + + + #region IOrderedDictionary Methods + IDictionaryEnumerator IOrderedDictionary.GetEnumerator () + { + EnsureDictionary (); + + return new OrderedDictionaryEnumerator ( + object_list.GetEnumerator ()); + } + + void IOrderedDictionary.Insert (int idx, object key, object value) + { + string property = (string) key; + JsonData data = ToJsonData (value); + + this[property] = data; + + KeyValuePair<string, JsonData> entry = + new KeyValuePair<string, JsonData> (property, data); + + object_list.Insert (idx, entry); + } + + void IOrderedDictionary.RemoveAt (int idx) + { + EnsureDictionary (); + + inst_object.Remove (object_list[idx].Key); + object_list.RemoveAt (idx); + } + #endregion + + + #region Private Methods + private ICollection EnsureCollection () + { + if (type == JsonType.Array) + return (ICollection) inst_array; + + if (type == JsonType.Object) + return (ICollection) inst_object; + + throw new InvalidOperationException ( + "The JsonData instance has to be initialized first"); + } + + private IDictionary EnsureDictionary () + { + if (type == JsonType.Object) + return (IDictionary) inst_object; + + if (type != JsonType.None) + throw new InvalidOperationException ( + "Instance of JsonData is not a dictionary"); + + type = JsonType.Object; + inst_object = new Dictionary<string, JsonData> (); + object_list = new List<KeyValuePair<string, JsonData>> (); + + return (IDictionary) inst_object; + } + + private IList EnsureList () + { + if (type == JsonType.Array) + return (IList) inst_array; + + if (type != JsonType.None) + throw new InvalidOperationException ( + "Instance of JsonData is not a list"); + + type = JsonType.Array; + inst_array = new List<JsonData> (); + + return (IList) inst_array; + } + + private JsonData ToJsonData (object obj) + { + if (obj == null) + return null; + + if (obj is JsonData) + return (JsonData) obj; + + return new JsonData (obj); + } + + private static void WriteJson (IJsonWrapper obj, JsonWriter writer) + { + if (null == obj) + { + writer.Write(null); + return; + } + + if (obj.IsString) { + writer.Write (obj.GetString ()); + return; + } + + if (obj.IsBoolean) { + writer.Write (obj.GetBoolean ()); + return; + } + + if (obj.IsDouble) { + writer.Write (obj.GetDouble ()); + return; + } + + if (obj.IsInt) { + writer.Write (obj.GetInt ()); + return; + } + + if (obj.IsLong) { + writer.Write (obj.GetLong ()); + return; + } + + if (obj.IsArray) { + writer.WriteArrayStart (); + foreach (object elem in (IList) obj) + WriteJson ((JsonData) elem, writer); + writer.WriteArrayEnd (); + + return; + } + + if (obj.IsObject) { + writer.WriteObjectStart (); + + foreach (DictionaryEntry entry in ((IDictionary) obj)) { + writer.WritePropertyName ((string) entry.Key); + WriteJson ((JsonData) entry.Value, writer); + } + writer.WriteObjectEnd (); + + return; + } + } + #endregion + + + public int Add (object value) + { + JsonData data = ToJsonData (value); + + json = null; + + return EnsureList ().Add (data); + } + + public void MakeArray() + { + EnsureList(); + } + + public void Clear () + { + if (IsObject) { + ((IDictionary) this).Clear (); + return; + } + + if (IsArray) { + ((IList) this).Clear (); + return; + } + } + + public bool Equals (JsonData x) + { + if (x == null) + return false; + + if (x.type != this.type) + return false; + + switch (this.type) { + case JsonType.None: + return true; + + case JsonType.Object: + return this.inst_object.Equals (x.inst_object); + + case JsonType.Array: + return this.inst_array.Equals (x.inst_array); + + case JsonType.String: + return this.inst_string.Equals (x.inst_string); + + case JsonType.Int: + return this.inst_int.Equals (x.inst_int); + + case JsonType.Long: + return this.inst_long.Equals (x.inst_long); + + case JsonType.Double: + return this.inst_double.Equals (x.inst_double); + + case JsonType.Boolean: + return this.inst_boolean.Equals (x.inst_boolean); + } + + return false; + } + + public JsonType GetJsonType () + { + return type; + } + + public void SetJsonType (JsonType type) + { + if (this.type == type) + return; + + switch (type) { + case JsonType.None: + break; + + case JsonType.Object: + inst_object = new Dictionary<string, JsonData> (); + object_list = new List<KeyValuePair<string, JsonData>> (); + break; + + case JsonType.Array: + inst_array = new List<JsonData> (); + break; + + case JsonType.String: + inst_string = default (String); + break; + + case JsonType.Int: + inst_int = default (Int32); + break; + + case JsonType.Long: + inst_long = default (Int64); + break; + + case JsonType.Double: + inst_double = default (Double); + break; + + case JsonType.Boolean: + inst_boolean = default (Boolean); + break; + } + + this.type = type; + } + + public string ToJson () + { + if (json != null) + return json; + + StringWriter sw = new StringWriter (); + JsonWriter writer = new JsonWriter(sw) + { + Validate = false + }; + + WriteJson (this, writer); + json = sw.ToString (); + + return json; + } + + public void ToJson (JsonWriter writer) + { + bool old_validate = writer.Validate; + + writer.Validate = false; + + WriteJson (this, writer); + + writer.Validate = old_validate; + } + + public override string ToString () + { + switch (type) { + case JsonType.Array: + return "JsonData array"; + + case JsonType.Boolean: + return inst_boolean.ToString (); + + case JsonType.Double: + return inst_double.ToString (); + + case JsonType.Int: + return inst_int.ToString (); + + case JsonType.Long: + return inst_long.ToString (); + + case JsonType.Object: + return "JsonData object"; + + case JsonType.String: + return inst_string; + } + + return "Uninitialized JsonData"; + } + } + + + internal class OrderedDictionaryEnumerator : IDictionaryEnumerator + { + IEnumerator<KeyValuePair<string, JsonData>> list_enumerator; + + + public object Current { + get { return Entry; } + } + + public DictionaryEntry Entry { + get { + KeyValuePair<string, JsonData> curr = list_enumerator.Current; + return new DictionaryEntry (curr.Key, curr.Value); + } + } + + public object Key { + get { return list_enumerator.Current.Key; } + } + + public object Value { + get { return list_enumerator.Current.Value; } + } + + + public OrderedDictionaryEnumerator ( + IEnumerator<KeyValuePair<string, JsonData>> enumerator) + { + list_enumerator = enumerator; + } + + + public bool MoveNext () + { + return list_enumerator.MoveNext (); + } + + public void Reset () + { + list_enumerator.Reset (); + } + } +} diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonData.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/JsonData.cs.meta new file mode 100644 index 0000000..e9f4732 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f80de13689cd2ed4d921eea0e26c6d63 +timeCreated: 1474349755 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonException.cs b/YesCommander/Assets/ThirdParty/LitJson/JsonException.cs new file mode 100644 index 0000000..cbf7ae3 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonException.cs @@ -0,0 +1,60 @@ +#region Header +/** + * JsonException.cs + * Base class throwed by LitJSON when a parsing error occurs. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; + + +namespace LitJson +{ + public class JsonException : ApplicationException + { + public JsonException () : base () + { + } + + internal JsonException (ParserToken token) : + base (String.Format ( + "Invalid token '{0}' in input string", token)) + { + } + + internal JsonException (ParserToken token, + Exception inner_exception) : + base (String.Format ( + "Invalid token '{0}' in input string", token), + inner_exception) + { + } + + internal JsonException (int c) : + base (String.Format ( + "Invalid character '{0}' in input string", (char) c)) + { + } + + internal JsonException (int c, Exception inner_exception) : + base (String.Format ( + "Invalid character '{0}' in input string", (char) c), + inner_exception) + { + } + + + public JsonException (string message) : base (message) + { + } + + public JsonException (string message, Exception inner_exception) : + base (message, inner_exception) + { + } + } +} diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonException.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/JsonException.cs.meta new file mode 100644 index 0000000..b9c077f --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonException.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8c99017edfc479b44aafcc84674b178c +timeCreated: 1474349755 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonFormatter.cs b/YesCommander/Assets/ThirdParty/LitJson/JsonFormatter.cs new file mode 100644 index 0000000..4d5f9c7 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonFormatter.cs @@ -0,0 +1,144 @@ +using System.Text; +using System.Collections.Generic; + +public class JsonFormatter +{ + #region class members + const string Space = " "; + const int DefaultIndent = 0; + const string Indent = Space + Space + Space + Space; + static readonly string NewLine = "\n"; + #endregion + + static bool inDoubleString = false; + static bool inSingleString = false; + static bool inVariableAssignment = false; + static char prevChar = '\0'; + + static Stack<JsonContextType> context = new Stack<JsonContextType>(); + + private enum JsonContextType + { + Object, Array + } + + static void BuildIndents(int indents, StringBuilder output) + { + indents += DefaultIndent; + for (; indents > 0; indents--) + output.Append(Indent); + } + + static bool InString() + { + return inDoubleString || inSingleString; + } + + public static string PrettyPrint(string input) + { + // Clear all states + inDoubleString = false; + inSingleString = false; + inVariableAssignment = false; + prevChar = '\0'; + context.Clear(); + + var output = new StringBuilder(input.Length * 2); + char c; + + for (int i = 0; i < input.Length; i++) + { + c = input[i]; + + switch (c) + { + case '[': + case '{': + if (!InString()) + { + if (inVariableAssignment || (context.Count > 0 && context.Peek() != JsonContextType.Array)) + { + output.Append(NewLine); + BuildIndents(context.Count, output); + } + output.Append(c); + context.Push(JsonContextType.Object); + output.Append(NewLine); + BuildIndents(context.Count, output); + } + else + output.Append(c); + + break; + + case ']': + case '}': + if (!InString()) + { + output.Append(NewLine); + context.Pop(); + BuildIndents(context.Count, output); + output.Append(c); + } + else + output.Append(c); + + break; + case '=': + output.Append(c); + break; + + case ',': + output.Append(c); + + if (!InString()) + { + BuildIndents(context.Count, output); + output.Append(NewLine); + BuildIndents(context.Count, output); + inVariableAssignment = false; + } + + break; + + case '\'': + if (!inDoubleString && prevChar != '\\') + inSingleString = !inSingleString; + + output.Append(c); + break; + + case ':': + if (!InString()) + { + inVariableAssignment = true; + output.Append(Space); + output.Append(c); + output.Append(Space); + } + else + output.Append(c); + + break; + + case '"': + if (!inSingleString && prevChar != '\\') + inDoubleString = !inDoubleString; + + output.Append(c); + break; + case ' ': + if (InString()) + output.Append(c); + break; + + default: + output.Append(c); + break; + } + prevChar = c; + } + + return output.ToString(); + } +}
\ No newline at end of file diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonFormatter.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/JsonFormatter.cs.meta new file mode 100644 index 0000000..02bdada --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonFormatter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cdcb71cedd669b947bd44cfa54439994 +timeCreated: 1474349755 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonMapper.cs b/YesCommander/Assets/ThirdParty/LitJson/JsonMapper.cs new file mode 100644 index 0000000..48532e8 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonMapper.cs @@ -0,0 +1,1091 @@ +#region Header +/** + * JsonMapper.cs + * JSON to .Net object and object to JSON conversions. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; + + +namespace LitJson +{ + internal struct PropertyMetadata + { + public MemberInfo Info; + public bool IsField; + public Type Type; + } + + + internal struct ArrayMetadata + { + private Type element_type; + private bool is_array; + private bool is_list; + + + public Type ElementType { + get { + if (element_type == null) + return typeof (JsonData); + + return element_type; + } + + set { element_type = value; } + } + + public bool IsArray { + get { return is_array; } + set { is_array = value; } + } + + public bool IsList { + get { return is_list; } + set { is_list = value; } + } + } + + + internal struct ObjectMetadata + { + private Type element_type; + private bool is_dictionary; + + private IDictionary<string, PropertyMetadata> properties; + + + public Type ElementType { + get { + if (element_type == null) + return typeof (JsonData); + + return element_type; + } + + set { element_type = value; } + } + + public bool IsDictionary { + get { return is_dictionary; } + set { is_dictionary = value; } + } + + public IDictionary<string, PropertyMetadata> Properties { + get { return properties; } + set { properties = value; } + } + + + private Type genericKeyType; + public Type GenericKeyType + { + get + { + return genericKeyType; + } + set + { + genericKeyType = value; + } + } + } + + + internal delegate void ExporterFunc (object obj, JsonWriter writer); + public delegate void ExporterFunc<T> (T obj, JsonWriter writer); + + internal delegate object ImporterFunc (object input); + public delegate TValue ImporterFunc<TJson, TValue> (TJson input); + + public delegate IJsonWrapper WrapperFactory (); + + + public class JsonMapper + { + #region Fields + private static int max_nesting_depth; + + private static IFormatProvider datetime_format; + + private static IDictionary<Type, ExporterFunc> base_exporters_table; + private static IDictionary<Type, ExporterFunc> custom_exporters_table; + + private static IDictionary<Type, + IDictionary<Type, ImporterFunc>> base_importers_table; + private static IDictionary<Type, + IDictionary<Type, ImporterFunc>> custom_importers_table; + + private static IDictionary<Type, ArrayMetadata> array_metadata; + private static readonly object array_metadata_lock = new Object (); + + private static IDictionary<Type, + IDictionary<Type, MethodInfo>> conv_ops; + private static readonly object conv_ops_lock = new Object (); + + private static IDictionary<Type, ObjectMetadata> object_metadata; + private static readonly object object_metadata_lock = new Object (); + + private static IDictionary<Type, + IList<PropertyMetadata>> type_properties; + private static readonly object type_properties_lock = new Object (); + + private static JsonWriter static_writer; + private static readonly object static_writer_lock = new Object (); + #endregion + + + #region Constructors + public static void ResetStatic() + { + max_nesting_depth = 100; + + array_metadata = new Dictionary<Type, ArrayMetadata>(); + conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>(); + object_metadata = new Dictionary<Type, ObjectMetadata>(); + type_properties = new Dictionary<Type, + IList<PropertyMetadata>>(); + + static_writer = new JsonWriter(); + + datetime_format = DateTimeFormatInfo.InvariantInfo; + + base_exporters_table = new Dictionary<Type, ExporterFunc>(); + custom_exporters_table = new Dictionary<Type, ExporterFunc>(); + + base_importers_table = new Dictionary<Type, + IDictionary<Type, ImporterFunc>>(); + custom_importers_table = new Dictionary<Type, + IDictionary<Type, ImporterFunc>>(); + + RegisterBaseExporters(); + RegisterBaseImporters(); + } + static JsonMapper () + { + ResetStatic(); + } + #endregion + + + #region Private Methods + private static void AddArrayMetadata (Type type) + { + if (array_metadata.ContainsKey (type)) + return; + + ArrayMetadata data = new ArrayMetadata + { + IsArray = type.IsArray + }; + + if (type.GetInterface ("System.Collections.IList") != null) + data.IsList = true; + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name != "Item") + continue; + + ParameterInfo[] parameters = p_info.GetIndexParameters (); + + if (parameters.Length != 1) + continue; + + if (parameters[0].ParameterType == typeof (int)) + data.ElementType = p_info.PropertyType; + } + + lock (array_metadata_lock) { + try { + array_metadata.Add (type, data); + } catch (ArgumentException) { + return; + } + } + } + + private static void AddObjectMetadata (Type type) + { + if (object_metadata.ContainsKey (type)) + return; + + ObjectMetadata data = new ObjectMetadata (); + + if (type.GetInterface ("System.Collections.IDictionary") != null) + data.IsDictionary = true; + + data.Properties = new Dictionary<string, PropertyMetadata> (); + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name == "Item") { + ParameterInfo[] parameters = p_info.GetIndexParameters (); + + if (parameters.Length != 1) + continue; + + if (data.IsDictionary) + { + data.ElementType = p_info.PropertyType; + } + else + { + if (parameters[0].ParameterType == typeof(string)) + data.ElementType = p_info.PropertyType; + } + + continue; + } + + PropertyMetadata p_data = new PropertyMetadata + { + Info = p_info, + Type = p_info.PropertyType + }; + + data.Properties.Add (p_info.Name, p_data); + } + + foreach (FieldInfo f_info in type.GetFields ()) { + PropertyMetadata p_data = new PropertyMetadata + { + Info = f_info, + IsField = true, + Type = f_info.FieldType + }; + + data.Properties.Add (f_info.Name, p_data); + } + + if (type.IsGenericType) + { + data.GenericKeyType = type.GetGenericArguments()[0]; + } + + lock (object_metadata_lock) { + try { + object_metadata.Add (type, data); + } catch (ArgumentException) { + return; + } + } + } + + private static void AddTypeProperties (Type type) + { + if (type_properties.ContainsKey (type)) + return; + + IList<PropertyMetadata> props = new List<PropertyMetadata> (); + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name == "Item") + continue; + + PropertyMetadata p_data = new PropertyMetadata + { + Info = p_info, + IsField = false + }; + props.Add (p_data); + } + + foreach (FieldInfo f_info in type.GetFields ()) { + PropertyMetadata p_data = new PropertyMetadata + { + Info = f_info, + IsField = true + }; + + props.Add (p_data); + } + + lock (type_properties_lock) { + try { + type_properties.Add (type, props); + } catch (ArgumentException) { + return; + } + } + } + + private static MethodInfo GetConvOp (Type t1, Type t2) + { + lock (conv_ops_lock) { + if (! conv_ops.ContainsKey (t1)) + conv_ops.Add (t1, new Dictionary<Type, MethodInfo> ()); + } + + if (conv_ops[t1].ContainsKey (t2)) + return conv_ops[t1][t2]; + + MethodInfo op = t1.GetMethod ( + "op_Implicit", new Type[] { t2 }); + + lock (conv_ops_lock) { + try { + conv_ops[t1].Add (t2, op); + } catch (ArgumentException) { + return conv_ops[t1][t2]; + } + } + + return op; + } + + private static object ReadValue (Type inst_type, JsonReader reader) + { + reader.Read (); + + if (reader.Token == JsonToken.ArrayEnd) + return null; + + if (reader.Token == JsonToken.Null) { + + if (! inst_type.IsClass) + throw new JsonException (String.Format ( + "Can't assign null to an instance of type {0}", + inst_type)); + + return null; + } + + if (reader.Token == JsonToken.Double || + reader.Token == JsonToken.Int || + reader.Token == JsonToken.Long || + reader.Token == JsonToken.String || + reader.Token == JsonToken.Boolean) { + + Type json_type = reader.Value.GetType (); + + if (inst_type.IsAssignableFrom (json_type)) + return reader.Value; + + // If there's a custom importer that fits, use it + if (custom_importers_table.ContainsKey (json_type) && + custom_importers_table[json_type].ContainsKey ( + inst_type)) { + + ImporterFunc importer = + custom_importers_table[json_type][inst_type]; + + return importer (reader.Value); + } + + // Maybe there's a base importer that works + if (base_importers_table.ContainsKey (json_type) && + base_importers_table[json_type].ContainsKey ( + inst_type)) { + + ImporterFunc importer = + base_importers_table[json_type][inst_type]; + + return importer (reader.Value); + } + + // Maybe it's an enum + if (inst_type.IsEnum) + return Enum.ToObject (inst_type, reader.Value); + + // Try using an implicit conversion operator + MethodInfo conv_op = GetConvOp (inst_type, json_type); + + if (conv_op != null) + return conv_op.Invoke (null, + new object[] { reader.Value }); + + //=====================扩展===================== + if (json_type == typeof(Double) && inst_type == typeof(System.Single)) + { + return Convert.ToSingle(reader.Value); + } + if (json_type == typeof(int) && inst_type == typeof(bool)) + { + return (int)reader.Value == 1; + } + if (inst_type == typeof(UnityEngine.Vector4)) + { + return YC.CommonParse.ParseVector4(reader.Value.ToString()); + } + if (inst_type == typeof(UnityEngine.Vector3)) + { + return YC.CommonParse.ParseVector3(reader.Value.ToString()); + } + if (inst_type == typeof(UnityEngine.Vector2)) + { + return YC.CommonParse.ParseVector2(reader.Value.ToString()); + } + if (inst_type == typeof(YC.IntVector4)) + { + return YC.CommonParse.ParseIntVector4(reader.Value.ToString()); + } + if (inst_type == typeof(YC.IntVector3)) + { + return YC.CommonParse.ParseIntVector3(reader.Value.ToString()); + } + if (inst_type == typeof(YC.IntVector2)) + { + return YC.CommonParse.ParseIntVector2(reader.Value.ToString()); + } + if (inst_type == typeof(UnityEngine.Color)) + { + return YC.CommonParse.ParseColor(reader.Value.ToString()); + } + if (inst_type == typeof(UnityEngine.Color32)) + { + return YC.CommonParse.ParseColor32(reader.Value.ToString()); + } + //========================================== + + // No luck + throw new JsonException (String.Format ( + "Can't assign value '{0}' (type {1}) to type {2}", + reader.Value, json_type, inst_type)); + } + + object instance = null; + + if (reader.Token == JsonToken.ArrayStart) { + + AddArrayMetadata (inst_type); + ArrayMetadata t_data = array_metadata[inst_type]; + + if (! t_data.IsArray && ! t_data.IsList) + throw new JsonException (String.Format ( + "Type {0} can't act as an array", + inst_type)); + + IList list; + Type elem_type; + + if (! t_data.IsArray) { + list = (IList) Activator.CreateInstance (inst_type); + elem_type = t_data.ElementType; + } else { + list = new ArrayList (); + elem_type = inst_type.GetElementType (); + } + + while (true) { + object item = ReadValue (elem_type, reader); + if (reader.Token == JsonToken.ArrayEnd) + break; + + list.Add (item); + } + + if (t_data.IsArray) { + int n = list.Count; + instance = Array.CreateInstance (elem_type, n); + + for (int i = 0; i < n; i++) + ((Array) instance).SetValue (list[i], i); + } else + instance = list; + + } else if (reader.Token == JsonToken.ObjectStart) { + + AddObjectMetadata (inst_type); + ObjectMetadata t_data = object_metadata[inst_type]; + + instance = Activator.CreateInstance (inst_type); + + while (true) { + reader.Read (); + + if (reader.Token == JsonToken.ObjectEnd) + break; + + //====修改新增逻辑==== + if (reader.Token != JsonToken.PropertyName) + { + continue; + } + //====修改新增逻辑==== + + string property = (string) reader.Value; + + if (t_data.Properties.ContainsKey (property)) { + PropertyMetadata prop_data = + t_data.Properties[property]; + + if (prop_data.IsField) { + FieldInfo fi = (FieldInfo)prop_data.Info; + object obj = ReadValue(prop_data.Type, reader); + //过滤const标记 + if (!fi.IsLiteral) + { + fi.SetValue(instance, obj); + } + } else { + PropertyInfo p_info = + (PropertyInfo) prop_data.Info; + + if (p_info.CanWrite) + p_info.SetValue ( + instance, + ReadValue (prop_data.Type, reader), + null); + else + ReadValue (prop_data.Type, reader); + } + + } else { + if (!t_data.IsDictionary) + { + //====修改注释掉==== + //throw new JsonException(String.Format( + // "The type {0} doesn't have the " + + // "property '{1}'", inst_type, property)); + //====修改注释掉==== + + //====修改新增逻辑==== + //报错,并暂停编辑器UI + YC.LogHelper.LogError(String.Format( + "The type {0} doesn't have the " + + "property '{1}'", inst_type, property)); + UnityEngine.Debug.Break(); + continue; + //====修改新增逻辑==== + } + object keyObj = property; + if (t_data.GenericKeyType == typeof(int)) + { + keyObj = YC.CommonParse.ParseInt(property); + } + + ((IDictionary) instance).Add ( + keyObj, ReadValue ( + t_data.ElementType, reader)); + } + + } + + } + + return instance; + } + + private static IJsonWrapper ReadValue (WrapperFactory factory, + JsonReader reader) + { + reader.Read (); + + if (reader.Token == JsonToken.ArrayEnd || + reader.Token == JsonToken.Null) + return null; + + IJsonWrapper instance = factory (); + + if (reader.Token == JsonToken.String) { + instance.SetString ((string) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Double) { + instance.SetDouble ((double) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Int) { + instance.SetInt ((int) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Long) { + instance.SetLong ((long) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Boolean) { + instance.SetBoolean ((bool) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.ArrayStart) { + instance.SetJsonType (JsonType.Array); + + while (true) { + IJsonWrapper item = ReadValue (factory, reader); + if (reader.Token == JsonToken.ArrayEnd) + break; + + ((IList) instance).Add (item); + } + } + else if (reader.Token == JsonToken.ObjectStart) { + instance.SetJsonType (JsonType.Object); + + while (true) { + reader.Read (); + + if (reader.Token == JsonToken.ObjectEnd) + break; + + string property = (string) reader.Value; + + ((IDictionary) instance)[property] = ReadValue ( + factory, reader); + } + + } + + return instance; + } + + private static void RegisterBaseExporters () + { + base_exporters_table[typeof (byte)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((byte) obj)); + }; + + base_exporters_table[typeof (char)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToString ((char) obj)); + }; + + base_exporters_table[typeof (DateTime)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToString ((DateTime) obj, + datetime_format)); + }; + + base_exporters_table[typeof (decimal)] = + delegate (object obj, JsonWriter writer) { + writer.Write ((decimal) obj); + }; + + base_exporters_table[typeof (sbyte)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((sbyte) obj)); + }; + + base_exporters_table[typeof (short)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((short) obj)); + }; + + base_exporters_table[typeof (ushort)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((ushort) obj)); + }; + + base_exporters_table[typeof (uint)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToUInt64 ((uint) obj)); + }; + + base_exporters_table[typeof (ulong)] = + delegate (object obj, JsonWriter writer) { + writer.Write ((ulong) obj); + }; + } + + private static void RegisterBaseImporters () + { + ImporterFunc importer; + + importer = delegate (object input) { + return Convert.ToByte ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (byte), importer); + + importer = delegate (object input) { + return Convert.ToInt64 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (long), importer); + + importer = delegate (object input) { + return Convert.ToUInt64 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (ulong), importer); + + importer = delegate (object input) { + return Convert.ToSByte ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (sbyte), importer); + + importer = delegate (object input) { + return Convert.ToInt16 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (short), importer); + + importer = delegate (object input) { + return Convert.ToUInt16 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (ushort), importer); + + importer = delegate (object input) { + return Convert.ToUInt32 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (uint), importer); + + importer = delegate (object input) { + return Convert.ToSingle ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (float), importer); + + importer = delegate (object input) { + return Convert.ToDouble ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (double), importer); + + importer = delegate (object input) { + return Convert.ToDecimal ((double) input); + }; + RegisterImporter (base_importers_table, typeof (double), + typeof (decimal), importer); + + + importer = delegate (object input) { + return Convert.ToUInt32 ((long) input); + }; + RegisterImporter (base_importers_table, typeof (long), + typeof (uint), importer); + + importer = delegate (object input) { + return Convert.ToChar ((string) input); + }; + RegisterImporter (base_importers_table, typeof (string), + typeof (char), importer); + + importer = delegate (object input) { + return Convert.ToDateTime ((string) input, datetime_format); + }; + RegisterImporter (base_importers_table, typeof (string), + typeof (DateTime), importer); + } + + private static void RegisterImporter ( + IDictionary<Type, IDictionary<Type, ImporterFunc>> table, + Type json_type, Type value_type, ImporterFunc importer) + { + if (! table.ContainsKey (json_type)) + table.Add (json_type, new Dictionary<Type, ImporterFunc> ()); + + table[json_type][value_type] = importer; + } + + private static void WriteValue (object obj, JsonWriter writer, + bool writer_is_private, + int depth) + { + if (depth > max_nesting_depth) + throw new JsonException ( + String.Format ("Max allowed object depth reached while " + + "trying to export from type {0}", + null != obj ? obj.GetType ().ToString() : "null")); + + if (obj == null) { + writer.Write (null); + return; + } + + if (obj is IJsonWrapper) { + if (writer_is_private) + writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ()); + else + ((IJsonWrapper) obj).ToJson (writer); + + return; + } + + //=====================扩展开始===================== + if (obj is UnityEngine.Vector4) + { + writer.Write((UnityEngine.Vector4)obj); + return; + } + + if (obj is UnityEngine.Vector3) + { + writer.Write((UnityEngine.Vector3)obj); + return; + } + + if (obj is UnityEngine.Vector2) + { + writer.Write((UnityEngine.Vector2)obj); + return; + } + if (obj is YC.IntVector4) + { + writer.Write((YC.IntVector4)obj); + return; + } + + if (obj is YC.IntVector3) + { + writer.Write((YC.IntVector3)obj); + return; + } + + if (obj is YC.IntVector2) + { + writer.Write((YC.IntVector2)obj); + return; + } + + if (obj is System.Single) //float + { + writer.Write((System.Single)obj); + return; + } + + if (obj is String) { + writer.Write ((string) obj); + return; + } + + if (obj is UnityEngine.Color) + { + writer.Write((UnityEngine.Color)obj); + return; + } + + if (obj is UnityEngine.Color32) + { + writer.Write((UnityEngine.Color32)obj); + return; + } + //=====================扩展结束===================== + + if (obj is Double) { + writer.Write ((double) obj); + return; + } + + if (obj is Int32) { + writer.Write ((int) obj); + return; + } + + if (obj is Boolean) { + writer.Write ((bool) obj); + return; + } + + if (obj is Int64) { + writer.Write ((long) obj); + return; + } + + if (obj is Array) { + writer.WriteArrayStart (); + + foreach (object elem in (Array) obj) + WriteValue (elem, writer, writer_is_private, depth + 1); + + writer.WriteArrayEnd (); + + return; + } + + if (obj is IList) { + writer.WriteArrayStart (); + foreach (object elem in (IList) obj) + WriteValue (elem, writer, writer_is_private, depth + 1); + writer.WriteArrayEnd (); + + return; + } + + if (obj is IDictionary) { + writer.WriteObjectStart (); + foreach (DictionaryEntry entry in (IDictionary) obj) { + writer.WritePropertyName (entry.Key.ToString()); + WriteValue (entry.Value, writer, writer_is_private, + depth + 1); + } + writer.WriteObjectEnd (); + + return; + } + + Type obj_type = obj.GetType (); + + // See if there's a custom exporter for the object + if (custom_exporters_table.ContainsKey (obj_type)) { + ExporterFunc exporter = custom_exporters_table[obj_type]; + exporter (obj, writer); + + return; + } + + // If not, maybe there's a base exporter + if (base_exporters_table.ContainsKey (obj_type)) { + ExporterFunc exporter = base_exporters_table[obj_type]; + exporter (obj, writer); + + return; + } + + // Last option, let's see if it's an enum + if (obj is Enum) { + Type e_type = Enum.GetUnderlyingType (obj_type); + + if (e_type == typeof (long) + || e_type == typeof (uint) + || e_type == typeof (ulong)) + writer.Write ((ulong) obj); + else + writer.Write ((int) obj); + + return; + } + + // Okay, so it looks like the input should be exported as an + // object + AddTypeProperties (obj_type); + IList<PropertyMetadata> props = type_properties[obj_type]; + + writer.WriteObjectStart (); + foreach (PropertyMetadata p_data in props) { + if (p_data.IsField) { + writer.WritePropertyName (p_data.Info.Name); + WriteValue (((FieldInfo) p_data.Info).GetValue (obj), + writer, writer_is_private, depth + 1); + } + else { + PropertyInfo p_info = (PropertyInfo) p_data.Info; + + if (p_info.CanRead) { + writer.WritePropertyName (p_data.Info.Name); + WriteValue (p_info.GetValue (obj, null), + writer, writer_is_private, depth + 1); + } + } + } + writer.WriteObjectEnd (); + } + #endregion + + + public static string ToJson (object obj) + { + lock (static_writer_lock) { + static_writer.Reset (); + + WriteValue (obj, static_writer, true, 0); + + return static_writer.ToString (); + } + } + + public static void ToJson (object obj, JsonWriter writer) + { + WriteValue (obj, writer, false, 0); + } + + public static JsonData ToObject (JsonReader reader) + { + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, reader); + } + + public static JsonData ToObject (TextReader reader) + { + JsonReader json_reader = new JsonReader (reader); + + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, json_reader); + } + + public static JsonData ToObject (string json) + { + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, json); + } + + public static T ToObject<T> (JsonReader reader) + { + return (T) ReadValue (typeof (T), reader); + } + + public static T ToObject<T> (TextReader reader) + { + JsonReader json_reader = new JsonReader (reader); + + return (T) ReadValue (typeof (T), json_reader); + } + + public static T ToObject<T> (string json) + { + JsonReader reader = new JsonReader (json); + + return (T) ReadValue (typeof (T), reader); + } + + public static object ToObject(Type t, string json) + { + JsonReader reader = new JsonReader(json); + + return ReadValue(t, reader); + } + + public static IJsonWrapper ToWrapper (WrapperFactory factory, + JsonReader reader) + { + return ReadValue (factory, reader); + } + + public static IJsonWrapper ToWrapper (WrapperFactory factory, + string json) + { + JsonReader reader = new JsonReader (json); + + return ReadValue (factory, reader); + } + + public static void RegisterExporter<T> (ExporterFunc<T> exporter) + { + ExporterFunc exporter_wrapper = + delegate (object obj, JsonWriter writer) { + exporter ((T) obj, writer); + }; + + custom_exporters_table[typeof (T)] = exporter_wrapper; + } + + public static void RegisterImporter<TJson, TValue> ( + ImporterFunc<TJson, TValue> importer) + { + ImporterFunc importer_wrapper = + delegate (object input) { + return importer ((TJson) input); + }; + + RegisterImporter (custom_importers_table, typeof (TJson), + typeof (TValue), importer_wrapper); + } + + public static void UnregisterExporters () + { + custom_exporters_table.Clear (); + } + + public static void UnregisterImporters () + { + custom_importers_table.Clear (); + } + } +} diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonMapper.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/JsonMapper.cs.meta new file mode 100644 index 0000000..1f88d0a --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonMapper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0d00865104600c7449d358a6cbb3d9e7 +timeCreated: 1474349754 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonReader.cs b/YesCommander/Assets/ThirdParty/LitJson/JsonReader.cs new file mode 100644 index 0000000..4616864 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonReader.cs @@ -0,0 +1,455 @@ +#region Header +/** + * JsonReader.cs + * Stream-like access to JSON text. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + + +namespace LitJson +{ + public enum JsonToken + { + None, + + ObjectStart, + PropertyName, + ObjectEnd, + + ArrayStart, + ArrayEnd, + + Int, + Long, + Double, + + String, + + Boolean, + Null + } + + + public class JsonReader + { + #region Fields + private static IDictionary<int, IDictionary<int, int[]>> parse_table; + + private Stack<int> automaton_stack; + private int current_input; + private int current_symbol; + private bool end_of_json; + private bool end_of_input; + private Lexer lexer; + private bool parser_in_string; + private bool parser_return; + private bool read_started; + private TextReader reader; + private bool reader_is_owned; + private object token_value; + private JsonToken token; + #endregion + + + #region Public Properties + public bool AllowComments { + get { return lexer.AllowComments; } + set { lexer.AllowComments = value; } + } + + public bool AllowSingleQuotedStrings { + get { return lexer.AllowSingleQuotedStrings; } + set { lexer.AllowSingleQuotedStrings = value; } + } + + public bool EndOfInput { + get { return end_of_input; } + } + + public bool EndOfJson { + get { return end_of_json; } + } + + public JsonToken Token { + get { return token; } + } + + public object Value { + get { return token_value; } + } + #endregion + + + #region Constructors + static JsonReader () + { + PopulateParseTable (); + } + + public JsonReader (string json_text) : + this (new StringReader (json_text), true) + { + } + + public JsonReader (TextReader reader) : + this (reader, false) + { + } + + private JsonReader (TextReader reader, bool owned) + { + if (reader == null) + throw new ArgumentNullException ("reader"); + + parser_in_string = false; + parser_return = false; + + read_started = false; + automaton_stack = new Stack<int> (); + automaton_stack.Push ((int) ParserToken.End); + automaton_stack.Push ((int) ParserToken.Text); + + lexer = new Lexer (reader); + + end_of_input = false; + end_of_json = false; + + this.reader = reader; + reader_is_owned = owned; + } + #endregion + + + #region Static Methods + private static void PopulateParseTable () + { + parse_table = new Dictionary<int, IDictionary<int, int[]>> (); + + TableAddRow (ParserToken.Array); + TableAddCol (ParserToken.Array, '[', + '[', + (int) ParserToken.ArrayPrime); + + TableAddRow (ParserToken.ArrayPrime); + TableAddCol (ParserToken.ArrayPrime, '"', + (int) ParserToken.Value, + + (int) ParserToken.ValueRest, + ']'); + TableAddCol (ParserToken.ArrayPrime, '[', + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (ParserToken.ArrayPrime, ']', + ']'); + TableAddCol (ParserToken.ArrayPrime, '{', + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.Number, + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.True, + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.False, + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (ParserToken.ArrayPrime, (int) ParserToken.Null, + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + + TableAddRow (ParserToken.Object); + TableAddCol (ParserToken.Object, '{', + '{', + (int) ParserToken.ObjectPrime); + + TableAddRow (ParserToken.ObjectPrime); + TableAddCol (ParserToken.ObjectPrime, '"', + (int) ParserToken.Pair, + (int) ParserToken.PairRest, + '}'); + TableAddCol (ParserToken.ObjectPrime, '}', + '}'); + + TableAddRow (ParserToken.Pair); + TableAddCol (ParserToken.Pair, '"', + (int) ParserToken.String, + ':', + (int) ParserToken.Value); + + TableAddRow (ParserToken.PairRest); + TableAddCol (ParserToken.PairRest, ',', + ',', + (int) ParserToken.Pair, + (int) ParserToken.PairRest); + TableAddCol (ParserToken.PairRest, '}', + (int) ParserToken.Epsilon); + + TableAddRow (ParserToken.String); + TableAddCol (ParserToken.String, '"', + '"', + (int) ParserToken.CharSeq, + '"'); + + TableAddRow (ParserToken.Text); + TableAddCol (ParserToken.Text, '[', + (int) ParserToken.Array); + TableAddCol (ParserToken.Text, '{', + (int) ParserToken.Object); + + TableAddRow (ParserToken.Value); + TableAddCol (ParserToken.Value, '"', + (int) ParserToken.String); + TableAddCol (ParserToken.Value, '[', + (int) ParserToken.Array); + TableAddCol (ParserToken.Value, '{', + (int) ParserToken.Object); + TableAddCol (ParserToken.Value, (int) ParserToken.Number, + (int) ParserToken.Number); + TableAddCol (ParserToken.Value, (int) ParserToken.True, + (int) ParserToken.True); + TableAddCol (ParserToken.Value, (int) ParserToken.False, + (int) ParserToken.False); + TableAddCol (ParserToken.Value, (int) ParserToken.Null, + (int) ParserToken.Null); + + TableAddRow (ParserToken.ValueRest); + TableAddCol (ParserToken.ValueRest, ',', + ',', + (int) ParserToken.Value, + (int) ParserToken.ValueRest); + TableAddCol (ParserToken.ValueRest, ']', + (int) ParserToken.Epsilon); + } + + private static void TableAddCol (ParserToken row, int col, + params int[] symbols) + { + parse_table[(int) row].Add (col, symbols); + } + + private static void TableAddRow (ParserToken rule) + { + parse_table.Add ((int) rule, new Dictionary<int, int[]> ()); + } + #endregion + + + #region Private Methods + private void ProcessNumber (string number) + { + if (number.IndexOf ('.') != -1 || + number.IndexOf ('e') != -1 || + number.IndexOf ('E') != -1) { + + double n_double; + if (Double.TryParse (number, out n_double)) { + token = JsonToken.Double; + token_value = n_double; + + return; + } + } + + int n_int32; + if (Int32.TryParse (number, out n_int32)) { + token = JsonToken.Int; + token_value = n_int32; + + return; + } + + long n_int64; + if (Int64.TryParse (number, out n_int64)) { + token = JsonToken.Long; + token_value = n_int64; + + return; + } + + // Shouldn't happen, but just in case, return something + token = JsonToken.Int; + token_value = 0; + } + + private void ProcessSymbol () + { + if (current_symbol == '[') { + token = JsonToken.ArrayStart; + parser_return = true; + + } else if (current_symbol == ']') { + token = JsonToken.ArrayEnd; + parser_return = true; + + } else if (current_symbol == '{') { + token = JsonToken.ObjectStart; + parser_return = true; + + } else if (current_symbol == '}') { + token = JsonToken.ObjectEnd; + parser_return = true; + + } else if (current_symbol == '"') { + if (parser_in_string) { + parser_in_string = false; + + parser_return = true; + + } else { + if (token == JsonToken.None) + token = JsonToken.String; + + parser_in_string = true; + } + + } else if (current_symbol == (int) ParserToken.CharSeq) { + token_value = lexer.StringValue; + + } else if (current_symbol == (int) ParserToken.False) { + token = JsonToken.Boolean; + token_value = false; + parser_return = true; + + } else if (current_symbol == (int) ParserToken.Null) { + token = JsonToken.Null; + parser_return = true; + + } else if (current_symbol == (int) ParserToken.Number) { + ProcessNumber (lexer.StringValue); + + parser_return = true; + + } else if (current_symbol == (int) ParserToken.Pair) { + token = JsonToken.PropertyName; + + } else if (current_symbol == (int) ParserToken.True) { + token = JsonToken.Boolean; + token_value = true; + parser_return = true; + + } + } + + private bool ReadToken () + { + if (end_of_input) + return false; + + lexer.NextToken (); + + if (lexer.EndOfInput) { + Close (); + + return false; + } + + current_input = lexer.Token; + + return true; + } + #endregion + + + public void Close () + { + if (end_of_input) + return; + + end_of_input = true; + end_of_json = true; + + if (reader_is_owned) + reader.Close (); + + reader = null; + } + + public bool Read () + { + if (end_of_input) + return false; + + if (end_of_json) { + end_of_json = false; + automaton_stack.Clear (); + automaton_stack.Push ((int) ParserToken.End); + automaton_stack.Push ((int) ParserToken.Text); + } + + parser_in_string = false; + parser_return = false; + + token = JsonToken.None; + token_value = null; + + if (! read_started) { + read_started = true; + + if (! ReadToken ()) + return false; + } + + + int[] entry_symbols; + + while (true) { + if (parser_return) { + if (automaton_stack.Peek () == (int) ParserToken.End) + end_of_json = true; + + return true; + } + + current_symbol = automaton_stack.Pop (); + + ProcessSymbol (); + + if (current_symbol == current_input) { + if (! ReadToken ()) { + if (automaton_stack.Peek () != (int) ParserToken.End) + throw new JsonException ( + "Input doesn't evaluate to proper JSON text"); + + if (parser_return) + return true; + + return false; + } + + continue; + } + + try { + + entry_symbols = + parse_table[current_symbol][current_input]; + + } catch (KeyNotFoundException e) { + throw new JsonException ((ParserToken) current_input, e); + } + + if (entry_symbols[0] == (int) ParserToken.Epsilon) + continue; + + for (int i = entry_symbols.Length - 1; i >= 0; i--) + automaton_stack.Push (entry_symbols[i]); + } + } + + } +} diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonReader.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/JsonReader.cs.meta new file mode 100644 index 0000000..2090450 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonReader.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8d4fad23f0c1df8488cd1ce850b1b88e +timeCreated: 1474349755 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonWriter.cs b/YesCommander/Assets/ThirdParty/LitJson/JsonWriter.cs new file mode 100644 index 0000000..dc8493c --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonWriter.cs @@ -0,0 +1,595 @@ +#region Header +/** + * JsonWriter.cs + * Stream-like facility to output JSON text. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; + + +namespace LitJson +{ + internal enum Condition + { + InArray, + InObject, + NotAProperty, + Property, + Value + } + + internal class WriterContext + { + public int Count; + public bool InArray; + public bool InObject; + public bool ExpectingValue; + public int Padding; + } + + public class JsonWriter + { + #region Fields + private static NumberFormatInfo number_format; + + private WriterContext context; + private Stack<WriterContext> ctx_stack; + private bool has_reached_end; + private char[] hex_seq; + private int indentation; + private int indent_value; + private StringBuilder inst_string_builder; + private bool pretty_print; + private bool validate; + private TextWriter writer; + #endregion + + + #region Properties + public int IndentValue { + get { return indent_value; } + set { + indentation = (indentation / indent_value) * value; + indent_value = value; + } + } + + public bool PrettyPrint { + get { return pretty_print; } + set { pretty_print = value; } + } + + public TextWriter TextWriter { + get { return writer; } + } + + public bool Validate { + get { return validate; } + set { validate = value; } + } + #endregion + + + #region Constructors + static JsonWriter () + { + number_format = NumberFormatInfo.InvariantInfo; + } + + public JsonWriter () + { + inst_string_builder = new StringBuilder (); + writer = new StringWriter (inst_string_builder); + + Init (); + } + + public JsonWriter (StringBuilder sb) : + this (new StringWriter (sb)) + { + } + + public JsonWriter (TextWriter writer) + { + if (writer == null) + throw new ArgumentNullException ("writer"); + + this.writer = writer; + + Init (); + } + #endregion + + + #region Private Methods + private void DoValidation (Condition cond) + { + if (! context.ExpectingValue) + context.Count++; + + if (! validate) + return; + + if (has_reached_end) + throw new JsonException ( + "A complete JSON symbol has already been written"); + + switch (cond) { + case Condition.InArray: + if (! context.InArray) + throw new JsonException ( + "Can't close an array here"); + break; + + case Condition.InObject: + if (! context.InObject || context.ExpectingValue) + throw new JsonException ( + "Can't close an object here"); + break; + + case Condition.NotAProperty: + if (context.InObject && ! context.ExpectingValue) + throw new JsonException ( + "Expected a property"); + break; + + case Condition.Property: + if (! context.InObject || context.ExpectingValue) + throw new JsonException ( + "Can't add a property here"); + break; + + case Condition.Value: + if (! context.InArray && + (! context.InObject || ! context.ExpectingValue)) + throw new JsonException ( + "Can't add a value here"); + + break; + } + } + + private void Init () + { + has_reached_end = false; + hex_seq = new char[4]; + indentation = 0; + indent_value = 4; + pretty_print = false; + validate = true; + + ctx_stack = new Stack<WriterContext> (); + context = new WriterContext (); + ctx_stack.Push (context); + } + + private static void IntToHex (int n, char[] hex) + { + int num; + + for (int i = 0; i < 4; i++) { + num = n % 16; + + if (num < 10) + hex[3 - i] = (char) ('0' + num); + else + hex[3 - i] = (char) ('A' + (num - 10)); + + n >>= 4; + } + } + + private void Indent () + { + if (pretty_print) + indentation += indent_value; + } + + + private void Put (string str) + { + if (pretty_print && ! context.ExpectingValue) + for (int i = 0; i < indentation; i++) + writer.Write (' '); + + writer.Write (str); + } + + private void PutNewline () + { + PutNewline (true); + } + + private void PutNewline (bool add_comma) + { + if (add_comma && ! context.ExpectingValue && + context.Count > 1) + writer.Write (','); + + if (pretty_print && ! context.ExpectingValue) + writer.Write ('\n'); + } + + private void PutString (string str) + { + Put (String.Empty); + + writer.Write ('"'); + + int n = str.Length; + for (int i = 0; i < n; i++) { + switch (str[i]) { + case '\n': + writer.Write ("\\n"); + continue; + + case '\r': + writer.Write ("\\r"); + continue; + + case '\t': + writer.Write ("\\t"); + continue; + + case '"': + case '\\': + writer.Write ('\\'); + writer.Write (str[i]); + continue; + + case '\f': + writer.Write ("\\f"); + continue; + + case '\b': + writer.Write ("\\b"); + continue; + } + + if ((int) str[i] >= 32 && (int) str[i] <= 126) { + writer.Write (str[i]); + continue; + } + + // Default, turn into a \uXXXX sequence + IntToHex ((int) str[i], hex_seq); + writer.Write ("\\u"); + writer.Write (hex_seq); + } + + writer.Write ('"'); + } + + private void Unindent () + { + if (pretty_print) + indentation -= indent_value; + } + #endregion + + + public override string ToString () + { + if (inst_string_builder == null) + return String.Empty; + + return inst_string_builder.ToString (); + } + + public void Reset () + { + has_reached_end = false; + + ctx_stack.Clear (); + context = new WriterContext (); + ctx_stack.Push (context); + + if (inst_string_builder != null) + inst_string_builder.Remove (0, inst_string_builder.Length); + } + + //=====================扩展开始===================== + public void Write(UnityEngine.Vector4 v4) + { + DoValidation(Condition.Value); + PutNewline(); + + Put("\""); + Put(v4.x.ToString()); Put(","); + Put(v4.y.ToString()); Put(","); + Put(v4.z.ToString()); Put(","); + Put(v4.w.ToString()); + Put("\""); + + context.ExpectingValue = false; + } + + public void Write(UnityEngine.Vector3 v3) + { + DoValidation(Condition.Value); + PutNewline(); + + Put("\""); + Put(v3.x.ToString()); Put(","); + Put(v3.y.ToString()); Put(","); + Put(v3.z.ToString()); + Put("\""); + + context.ExpectingValue = false; + } + + public void Write(UnityEngine.Vector2 v2) + { + DoValidation(Condition.Value); + PutNewline(); + + Put("\""); + Put(v2.x.ToString()); Put(","); + Put(v2.y.ToString()); + Put("\""); + + context.ExpectingValue = false; + } + + //public void Write(YC.IntVector4 v4) + //{ + // DoValidation(Condition.Value); + // PutNewline(); + + // context.ExpectingValue = false; + // Put("\""); + // Put(v4.ToString()); + // Put("\""); + + // context.ExpectingValue = false; + //} + + //public void Write(YC.IntVector3 v3) + //{ + // DoValidation(Condition.Value); + // PutNewline(); + + // context.ExpectingValue = false; + // Put("\""); + // Put(v3.ToString()); + // Put("\""); + + // context.ExpectingValue = false; + //} + + //public void Write(YC.IntVector2 v2) + //{ + // DoValidation(Condition.Value); + // PutNewline(); + + // context.ExpectingValue = false; + // Put("\""); + // Put(v2.ToString()); + // Put("\""); + + // context.ExpectingValue = false; + //} + + public void Write(UnityEngine.Color color) + { + DoValidation(Condition.Value); + PutNewline(); + + Put("\""); + Put(color.r.ToString()); Put(","); + Put(color.g.ToString()); Put(","); + Put(color.b.ToString()); Put(","); + Put(color.a.ToString()); + Put("\""); + + context.ExpectingValue = false; + } + + public void Write(UnityEngine.Color32 color) + { + DoValidation(Condition.Value); + PutNewline(); + + Put("\""); + Put(color.r.ToString()); Put(","); + Put(color.g.ToString()); Put(","); + Put(color.b.ToString()); Put(","); + Put(color.a.ToString()); + Put("\""); + + context.ExpectingValue = false; + } + + //=====================扩展结束===================== + + public void Write (bool boolean) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (boolean ? "true" : "false"); + + context.ExpectingValue = false; + } + + public void Write (decimal number) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (Convert.ToString (number, number_format)); + + context.ExpectingValue = false; + } + + public void Write(float number) + { + DoValidation(Condition.Value); + PutNewline(); + + string str = Convert.ToString(number, number_format); + Put(str); + + if (str.IndexOf('.') == -1 && + str.IndexOf('E') == -1) + writer.Write(".0"); + + context.ExpectingValue = false; + } + + public void Write (double number) + { + DoValidation (Condition.Value); + PutNewline (); + + string str = Convert.ToString (number, number_format); + Put (str); + + if (str.IndexOf ('.') == -1 && + str.IndexOf ('E') == -1) + writer.Write (".0"); + + context.ExpectingValue = false; + } + + public void Write (int number) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (Convert.ToString (number, number_format)); + + context.ExpectingValue = false; + } + + public void Write (long number) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (Convert.ToString (number, number_format)); + context.ExpectingValue = false; + } + + public void Write (string str) + { + DoValidation (Condition.Value); + PutNewline (); + + if (str == null) + Put ("null"); + else + PutString (str); + + context.ExpectingValue = false; + } + + //[CLSCompliant(false)] Todisable warring CS3021 + public void Write (ulong number) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (Convert.ToString (number, number_format)); + + context.ExpectingValue = false; + } + + public void WriteArrayEnd () + { + DoValidation (Condition.InArray); + PutNewline (false); + + ctx_stack.Pop (); + if (ctx_stack.Count == 1) + has_reached_end = true; + else { + context = ctx_stack.Peek (); + context.ExpectingValue = false; + } + + Unindent (); + Put ("]"); + } + + public void WriteArrayStart () + { + DoValidation (Condition.NotAProperty); + PutNewline (); + + Put ("["); + + context = new WriterContext + { + InArray = true + }; + ctx_stack.Push (context); + + Indent (); + } + + public void WriteObjectEnd () + { + DoValidation (Condition.InObject); + PutNewline (false); + + ctx_stack.Pop (); + if (ctx_stack.Count == 1) + has_reached_end = true; + else { + context = ctx_stack.Peek (); + context.ExpectingValue = false; + } + + Unindent (); + Put ("}"); + } + + public void WriteObjectStart () + { + DoValidation (Condition.NotAProperty); + PutNewline (); + + Put ("{"); + + context = new WriterContext + { + InObject = true + }; + ctx_stack.Push (context); + + Indent (); + } + + public void WritePropertyName (string property_name) + { + DoValidation (Condition.Property); + PutNewline (); + + PutString (property_name); + + if (pretty_print) { + if (property_name.Length > context.Padding) + context.Padding = property_name.Length; + + for (int i = context.Padding - property_name.Length; + i >= 0; i--) + writer.Write (' '); + + writer.Write (": "); + } else + writer.Write (':'); + + context.ExpectingValue = true; + } + } +} diff --git a/YesCommander/Assets/ThirdParty/LitJson/JsonWriter.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/JsonWriter.cs.meta new file mode 100644 index 0000000..ad597f9 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/JsonWriter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b8439c843e82dfe48b235906797bcda7 +timeCreated: 1474349755 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/Lexer.cs b/YesCommander/Assets/ThirdParty/LitJson/Lexer.cs new file mode 100644 index 0000000..37534bb --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/Lexer.cs @@ -0,0 +1,912 @@ +#region Header +/** + * Lexer.cs + * JSON lexer implementation based on a finite state machine. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + + +namespace LitJson +{ + internal class FsmContext + { + public bool Return; + public int NextState; + public Lexer L; + public int StateStack; + } + + + internal class Lexer + { + #region Fields + private delegate bool StateHandler (FsmContext ctx); + + private static int[] fsm_return_table; + private static StateHandler[] fsm_handler_table; + + private bool allow_comments; + private bool allow_single_quoted_strings; + private bool end_of_input; + private FsmContext fsm_context; + private int input_buffer; + private int input_char; + private TextReader reader; + private int state; + private StringBuilder string_buffer; + private string string_value; + private int token; + private int unichar; + #endregion + + + #region Properties + public bool AllowComments { + get { return allow_comments; } + set { allow_comments = value; } + } + + public bool AllowSingleQuotedStrings { + get { return allow_single_quoted_strings; } + set { allow_single_quoted_strings = value; } + } + + public bool EndOfInput { + get { return end_of_input; } + } + + public int Token { + get { return token; } + } + + public string StringValue { + get { return string_value; } + } + #endregion + + + #region Constructors + static Lexer () + { + PopulateFsmTables (); + } + + public Lexer (TextReader reader) + { + allow_comments = true; + allow_single_quoted_strings = true; + + input_buffer = 0; + string_buffer = new StringBuilder (128); + state = 1; + end_of_input = false; + this.reader = reader; + + fsm_context = new FsmContext + { + L = this + }; + } + #endregion + + + #region Static Methods + private static int HexValue (int digit) + { + switch (digit) { + case 'a': + case 'A': + return 10; + + case 'b': + case 'B': + return 11; + + case 'c': + case 'C': + return 12; + + case 'd': + case 'D': + return 13; + + case 'e': + case 'E': + return 14; + + case 'f': + case 'F': + return 15; + + default: + return digit - '0'; + } + } + + private static void PopulateFsmTables () + { + fsm_handler_table = new StateHandler[28] { + State1, + State2, + State3, + State4, + State5, + State6, + State7, + State8, + State9, + State10, + State11, + State12, + State13, + State14, + State15, + State16, + State17, + State18, + State19, + State20, + State21, + State22, + State23, + State24, + State25, + State26, + State27, + State28 + }; + + fsm_return_table = new int[28] { + (int) ParserToken.Char, + 0, + (int) ParserToken.Number, + (int) ParserToken.Number, + 0, + (int) ParserToken.Number, + 0, + (int) ParserToken.Number, + 0, + 0, + (int) ParserToken.True, + 0, + 0, + 0, + (int) ParserToken.False, + 0, + 0, + (int) ParserToken.Null, + (int) ParserToken.CharSeq, + (int) ParserToken.Char, + 0, + 0, + (int) ParserToken.CharSeq, + (int) ParserToken.Char, + 0, + 0, + 0, + 0 + }; + } + + private static char ProcessEscChar (int esc_char) + { + switch (esc_char) { + case '"': + case '\'': + case '\\': + case '/': + return Convert.ToChar (esc_char); + + case 'n': + return '\n'; + + case 't': + return '\t'; + + case 'r': + return '\r'; + + case 'b': + return '\b'; + + case 'f': + return '\f'; + + default: + // Unreachable + return '?'; + } + } + + private static bool State1 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') + continue; + + if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 3; + return true; + } + + switch (ctx.L.input_char) { + case '"': + ctx.NextState = 19; + ctx.Return = true; + return true; + + case ',': + case ':': + case '[': + case ']': + case '{': + case '}': + ctx.NextState = 1; + ctx.Return = true; + return true; + + case '-': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 2; + return true; + + case '0': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 4; + return true; + + case 'f': + ctx.NextState = 12; + return true; + + case 'n': + ctx.NextState = 16; + return true; + + case 't': + ctx.NextState = 9; + return true; + + case '\'': + if (! ctx.L.allow_single_quoted_strings) + return false; + + ctx.L.input_char = '"'; + ctx.NextState = 23; + ctx.Return = true; + return true; + + case '/': + if (! ctx.L.allow_comments) + return false; + + ctx.NextState = 25; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State2 (FsmContext ctx) + { + ctx.L.GetChar (); + + if (ctx.L.input_char >= '1' && ctx.L.input_char<= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 3; + return true; + } + + switch (ctx.L.input_char) { + case '0': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 4; + return true; + + default: + return false; + } + } + + private static bool State3 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) { + case ',': + case ']': + case '}': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case '.': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 5; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + return true; + } + + private static bool State4 (FsmContext ctx) + { + ctx.L.GetChar (); + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) { + case ',': + case ']': + case '}': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case '.': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 5; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + + private static bool State5 (FsmContext ctx) + { + ctx.L.GetChar (); + + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 6; + return true; + } + + return false; + } + + private static bool State6 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) { + case ',': + case ']': + case '}': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State7 (FsmContext ctx) + { + ctx.L.GetChar (); + + if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 8; + return true; + } + + switch (ctx.L.input_char) { + case '+': + case '-': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 8; + return true; + + default: + return false; + } + } + + private static bool State8 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char<= '\r') { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) { + case ',': + case ']': + case '}': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State9 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'r': + ctx.NextState = 10; + return true; + + default: + return false; + } + } + + private static bool State10 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'u': + ctx.NextState = 11; + return true; + + default: + return false; + } + } + + private static bool State11 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'e': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State12 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'a': + ctx.NextState = 13; + return true; + + default: + return false; + } + } + + private static bool State13 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'l': + ctx.NextState = 14; + return true; + + default: + return false; + } + } + + private static bool State14 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 's': + ctx.NextState = 15; + return true; + + default: + return false; + } + } + + private static bool State15 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'e': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State16 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'u': + ctx.NextState = 17; + return true; + + default: + return false; + } + } + + private static bool State17 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'l': + ctx.NextState = 18; + return true; + + default: + return false; + } + } + + private static bool State18 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'l': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State19 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + switch (ctx.L.input_char) { + case '"': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 20; + return true; + + case '\\': + ctx.StateStack = 19; + ctx.NextState = 21; + return true; + + default: + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + } + + return true; + } + + private static bool State20 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case '"': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State21 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'u': + ctx.NextState = 22; + return true; + + case '"': + case '\'': + case '/': + case '\\': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + ctx.L.string_buffer.Append ( + ProcessEscChar (ctx.L.input_char)); + ctx.NextState = ctx.StateStack; + return true; + + default: + return false; + } + } + + private static bool State22 (FsmContext ctx) + { + int counter = 0; + int mult = 4096; + + ctx.L.unichar = 0; + + while (ctx.L.GetChar ()) { + + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9' || + ctx.L.input_char >= 'A' && ctx.L.input_char <= 'F' || + ctx.L.input_char >= 'a' && ctx.L.input_char <= 'f') { + + ctx.L.unichar += HexValue (ctx.L.input_char) * mult; + + counter++; + mult /= 16; + + if (counter == 4) { + ctx.L.string_buffer.Append ( + Convert.ToChar (ctx.L.unichar)); + ctx.NextState = ctx.StateStack; + return true; + } + + continue; + } + + return false; + } + + return true; + } + + private static bool State23 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + switch (ctx.L.input_char) { + case '\'': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 24; + return true; + + case '\\': + ctx.StateStack = 23; + ctx.NextState = 21; + return true; + + default: + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + } + + return true; + } + + private static bool State24 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case '\'': + ctx.L.input_char = '"'; + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State25 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case '*': + ctx.NextState = 27; + return true; + + case '/': + ctx.NextState = 26; + return true; + + default: + return false; + } + } + + private static bool State26 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char == '\n') { + ctx.NextState = 1; + return true; + } + } + + return true; + } + + private static bool State27 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char == '*') { + ctx.NextState = 28; + return true; + } + } + + return true; + } + + private static bool State28 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char == '*') + continue; + + if (ctx.L.input_char == '/') { + ctx.NextState = 1; + return true; + } + + ctx.NextState = 27; + return true; + } + + return true; + } + #endregion + + + private bool GetChar () + { + if ((input_char = NextChar ()) != -1) + return true; + + end_of_input = true; + return false; + } + + private int NextChar () + { + if (input_buffer != 0) { + int tmp = input_buffer; + input_buffer = 0; + + return tmp; + } + + return reader.Read (); + } + + public bool NextToken () + { + StateHandler handler; + fsm_context.Return = false; + + while (true) { + handler = fsm_handler_table[state - 1]; + + if (! handler (fsm_context)) + throw new JsonException (input_char); + + if (end_of_input) + return false; + + if (fsm_context.Return) { + string_value = string_buffer.ToString (); + string_buffer.Remove (0, string_buffer.Length); + token = fsm_return_table[state - 1]; + + if (token == (int) ParserToken.Char) + token = input_char; + + state = fsm_context.NextState; + + return true; + } + + state = fsm_context.NextState; + } + } + + private void UngetChar () + { + input_buffer = input_char; + } + } +} diff --git a/YesCommander/Assets/ThirdParty/LitJson/Lexer.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/Lexer.cs.meta new file mode 100644 index 0000000..5468201 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/Lexer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c044d0a258f8a014f9c13b83ed68d346 +timeCreated: 1474349755 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/LitJson/ParserToken.cs b/YesCommander/Assets/ThirdParty/LitJson/ParserToken.cs new file mode 100644 index 0000000..01174df --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/ParserToken.cs @@ -0,0 +1,44 @@ +#region Header +/** + * ParserToken.cs + * Internal representation of the tokens used by the lexer and the parser. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +namespace LitJson +{ + internal enum ParserToken + { + // Lexer tokens + None = System.Char.MaxValue + 1, + Number, + True, + False, + Null, + CharSeq, + // Single char + Char, + + // Parser Rules + Text, + Object, + ObjectPrime, + Pair, + PairRest, + Array, + ArrayPrime, + Value, + ValueRest, + String, + + // End of input + End, + + // The empty rule + Epsilon + } +} diff --git a/YesCommander/Assets/ThirdParty/LitJson/ParserToken.cs.meta b/YesCommander/Assets/ThirdParty/LitJson/ParserToken.cs.meta new file mode 100644 index 0000000..3766b80 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/LitJson/ParserToken.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 712024c872ac84c4a99a7e6479b8cb99 +timeCreated: 1474349755 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/StringUtil.meta b/YesCommander/Assets/ThirdParty/StringUtil.meta new file mode 100644 index 0000000..878753e --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f5ab78f3fb911749afba18449589ba4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/StringUtil/DoubleVString.cs b/YesCommander/Assets/ThirdParty/StringUtil/DoubleVString.cs new file mode 100644 index 0000000..5318c02 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/DoubleVString.cs @@ -0,0 +1,40 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + /// <summary> + /// 给UI.Text使用的double buffer string + /// </summary> + public class DoubleVString + { + private int index; + private VString stringA; + private VString stringB; + + public DoubleVString(int maxCount) + { + stringA = new VString(maxCount); + stringB = new VString(maxCount); + } + + public VString GetCurrentVString() + { + return (index % 2) == 0 ? stringA : stringB; + } + + public VString GetNextVString() + { + return (index % 2) == 0 ? stringB : stringA; + } + + + //交换current 和Next string对象 + public void SwapVString() + { + index = (index + 1) % 2; + } + } +} diff --git a/YesCommander/Assets/ThirdParty/StringUtil/DoubleVString.cs.meta b/YesCommander/Assets/ThirdParty/StringUtil/DoubleVString.cs.meta new file mode 100644 index 0000000..5e79416 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/DoubleVString.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9a865a66c8bd9444f9b481e3a62e500e +timeCreated: 1526353967 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/StringUtil/StringUtil.cs b/YesCommander/Assets/ThirdParty/StringUtil/StringUtil.cs new file mode 100644 index 0000000..05042a0 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/StringUtil.cs @@ -0,0 +1,750 @@ +using UnityEngine; +using System.Collections; +using System.Text; +using System; +using System.Collections.Generic; + +public partial class StringUtil +{ + //自定义字符串函数公用的StringBuilder + static StringBuilder _customSB = new StringBuilder(); + //共享的StringBuilder + static StringBuilder shareSB = new StringBuilder(); + + #region Concat + /// <summary> + /// 拼接字符串(2个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <returns></returns> + public static string Concat(string a1, string a2) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(3个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(4个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(5个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(6个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(7个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <param name="a7"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(8个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <param name="a7"></param> + /// <param name="a8"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(9个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <param name="a7"></param> + /// <param name="a8"></param> + /// <param name="a9"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(10个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <param name="a7"></param> + /// <param name="a8"></param> + /// <param name="a9"></param> + /// <param name="a10"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(11个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <param name="a7"></param> + /// <param name="a8"></param> + /// <param name="a9"></param> + /// <param name="a10"></param> + /// <param name="a11"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(12个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <param name="a7"></param> + /// <param name="a8"></param> + /// <param name="a9"></param> + /// <param name="a10"></param> + /// <param name="a11"></param> + /// <param name="a12"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(13个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <param name="a7"></param> + /// <param name="a8"></param> + /// <param name="a9"></param> + /// <param name="a10"></param> + /// <param name="a11"></param> + /// <param name="a12"></param> + /// <param name="a13"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12, string a13) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + _customSB.Append(a13); + return _customSB.ToString(); + } + + /// <summary> + /// 拼接字符串(14个) + /// </summary> + /// <param name="a1"></param> + /// <param name="a2"></param> + /// <param name="a3"></param> + /// <param name="a4"></param> + /// <param name="a5"></param> + /// <param name="a6"></param> + /// <param name="a7"></param> + /// <param name="a8"></param> + /// <param name="a9"></param> + /// <param name="a10"></param> + /// <param name="a11"></param> + /// <param name="a12"></param> + /// <param name="a13"></param> + /// <param name="a14"></param> + /// <returns></returns> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12, string a13, string a14) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + _customSB.Append(a13); + _customSB.Append(a14); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(15个) + /// </summary> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12, string a13, string a14, string a15) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + _customSB.Append(a13); + _customSB.Append(a14); + _customSB.Append(a15); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(16个) + /// </summary> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12, string a13, string a14, string a15, + string a16) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + _customSB.Append(a13); + _customSB.Append(a14); + _customSB.Append(a15); + _customSB.Append(a16); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(17个) + /// </summary> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12, string a13, string a14, string a15, + string a16, string a17) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + _customSB.Append(a13); + _customSB.Append(a14); + _customSB.Append(a15); + _customSB.Append(a16); + _customSB.Append(a17); + return _customSB.ToString(); + } + + /// <summary> + /// 拼接字符串(18个) + /// </summary> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12, string a13, string a14, string a15, + string a16, string a17, string a18) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + _customSB.Append(a13); + _customSB.Append(a14); + _customSB.Append(a15); + _customSB.Append(a16); + _customSB.Append(a17); + _customSB.Append(a18); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(19个) + /// </summary> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12, string a13, string a14, string a15, + string a16, string a17, string a18, string a19) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + _customSB.Append(a13); + _customSB.Append(a14); + _customSB.Append(a15); + _customSB.Append(a16); + _customSB.Append(a17); + _customSB.Append(a18); + _customSB.Append(a19); + return _customSB.ToString(); + } + /// <summary> + /// 拼接字符串(20个) + /// </summary> + public static string Concat(string a1, string a2, string a3, string a4, string a5, + string a6, string a7, string a8, string a9, string a10, + string a11, string a12, string a13, string a14, string a15, + string a16, string a17, string a18, string a19, string a20) + { + _customSB.Remove(0, _customSB.Length); + _customSB.Append(a1); + _customSB.Append(a2); + _customSB.Append(a3); + _customSB.Append(a4); + _customSB.Append(a5); + _customSB.Append(a6); + _customSB.Append(a7); + _customSB.Append(a8); + _customSB.Append(a9); + _customSB.Append(a10); + _customSB.Append(a11); + _customSB.Append(a12); + _customSB.Append(a13); + _customSB.Append(a14); + _customSB.Append(a15); + _customSB.Append(a16); + _customSB.Append(a17); + _customSB.Append(a18); + _customSB.Append(a19); + _customSB.Append(a20); + return _customSB.ToString(); + } + #endregion + + /// <summary> + /// 获得公用的StringBuilder + /// </summary> + /// <returns></returns> + public static StringBuilder GetShareStringBuilder(bool bReset = true) + { + if (bReset) + { + shareSB.Remove(0, shareSB.Length); + } + return shareSB; + } + + /// <summary> + /// 格式化字符串 + /// </summary> + /// <param name="format"></param> + /// <param name="args"></param> + /// <returns></returns> + public static string Format(string format, params object[] args) + { + try + { + _customSB.Remove(0, _customSB.Length); + _customSB.AppendFormat(format, args); + return _customSB.ToString(); + } + catch (Exception e) + { + YC.LogHelper.LogError(e.Message); + return format; + } + } + + /// <summary> + /// 替换\\n 为\n + /// </summary> + /// <param name="baseStr"></param> + /// <returns></returns> + public static string ReplaceNewLineChar(string baseStr) + { + //if (!baseStr.Contains("\\n")) + //{ + // return baseStr; + //} + return baseStr.Replace("\\n", "\n"); + } + + /// <summary> + /// 替换转义字符 + /// </summary> + /// <param name="baseStr"></param> + /// <returns></returns> + public static string ReplaceTranslateChar(string baseStr) + { + baseStr = baseStr.Replace("\\n", "\n"); + baseStr = baseStr.Replace("\\t", "\t"); + baseStr = baseStr.Replace("\\b", " "); + return baseStr; + } + + /// <summary> + /// 替换\\s 为(全角)空格 + /// </summary> + /// <param name="baseStr"></param> + /// <returns></returns> + public static string ReplaceNewBlankSpaceChar(string baseStr) + { + //if (!baseStr.Contains("\\s")) + //{ + // return baseStr; + //} + return baseStr.Replace("\\s", " "); + } + + // 正则匹配空格规则 + static System.Text.RegularExpressions.Regex SpaceRgx = null; + private static string GetSpacePattern() + { + return "\\s(?![a-z]|\\s)"; + } + + public static System.Text.RegularExpressions.Regex GetSpaceRgx() + { + if(SpaceRgx == null) + { + SpaceRgx = new System.Text.RegularExpressions.Regex(GetSpacePattern(), System.Text.RegularExpressions.RegexOptions.IgnoreCase); + } + return SpaceRgx; + } + // 处理英文混排时空格换行的问题 + public static string ProSpace(string value) + { + if (string.IsNullOrEmpty(value)) + return value; + return ProSpaceSp(value); + } + private static string ProSpaceSp(string value) + { + return value.Replace("{sp}", "\u00A0"); + } + private static string ProSpaceNormal(string value) + { + return GetSpaceRgx().Replace(value, "\u00A0"); + } + + + /// <summary> + /// 文本加持颜色 + /// </summary> + /// <param name="color"></param> + /// <param name="text"></param> + /// <returns></returns> + public static string UITextColor(string color, string text) + { + return StringUtil.Format("<color=#{0}>{1}</color>", color, text); + } + + /// <summary> + /// 文本加持颜色 + /// </summary> + /// <param name="color"></param> + /// <param name="text"></param> + /// <returns></returns> + public static string UITextColor(Color color, string text) + { + return UITextColor(ColorUtility.ToHtmlStringRGBA(color), text); + } + + /// <summary> + /// 整数转字符串 + /// </summary> + /// <param name="num"></param> + /// <param name="limit"></param> + /// <param name="param"></param> + /// <returns></returns> + public static string Int2StringLimit(int num, int limit, string param = "") + { + if (num < limit) + { + return num.ToString(param); + } + else + { + return limit.ToString(param); + } + } + + /// <summary> + /// 替换为linux的斜杠 + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static string StringSlashOfLinux(string str) + { + return str.Replace('\\', '/'); ; + } + + /// <summary> + /// 替换为win的斜杠 + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static string StringSlashOfWin(string str) + { + return str.Replace('/', '\\'); ; + } + + /// <summary> + /// 服务器接收的字符串不可有竖线 + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static string ToServerSafeString(string str) + { + return str.Replace("|", "/"); + } + + public static string DictionaryConvertString(Dictionary<int, int> dic) + { + _customSB.Remove(0, _customSB.Length); + if(dic != null) + { + Dictionary<int, int>.Enumerator itor = dic.GetEnumerator(); + while(itor.MoveNext()) + { + _customSB.Append(itor.Current.Key); + _customSB.Append(","); + _customSB.Append(itor.Current.Value); + _customSB.Append(";"); + } + } + return _customSB.ToString(); + } + #region 数字转美式字符串 +#if VERSION_OVERSEA_GAIYA && !(GAIYA_BURNING_GAME ||GAIYA_MYCARD_GAME) + public static string Num2US(float num) + { + return num.ToString("n2"); + } + public static string Num2US(int num) + { + return num.ToString("n0"); + } + public static string Num2US(long num) + { + return num.ToString("n0"); + } +#else + public static string Num2US(float num) + { + return num.ToString("n2").Replace(',',' '); + } + public static string Num2US(int num) + { + return num.ToString("n0").Replace(',', ' '); + } + public static string Num2US(long num) + { + return num.ToString("n0").Replace(',', ' '); + } +#endif + #endregion +}
\ No newline at end of file diff --git a/YesCommander/Assets/ThirdParty/StringUtil/StringUtil.cs.meta b/YesCommander/Assets/ThirdParty/StringUtil/StringUtil.cs.meta new file mode 100644 index 0000000..ad52d51 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/StringUtil.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 657e94996dc5d074a9944a0c4f8df3c9 +timeCreated: 1493006408 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/StringUtil/StringUtil_Other.cs b/YesCommander/Assets/ThirdParty/StringUtil/StringUtil_Other.cs new file mode 100644 index 0000000..71a38fd --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/StringUtil_Other.cs @@ -0,0 +1,300 @@ +using UnityEngine; +using System.Collections; +using System.Text; +using System; + +public partial class StringUtil +{ + /// <summary> + /// 计算字符串的长度(包含处理中文字符) + /// </summary> + /// <param name="input"></param> + /// <returns></returns> + public static int CalcStringLetterNum(string input) + { + int counter = 0; + for (int i = 0, imax = input.Length; i < imax; ++i) + { + if (IsChineseLetter(input, i)) + { + counter += 2; + } + else + { + counter += 1; + } + } + + return counter; + } + + /// <summary> + /// 截断字符串(包含处理中文字符) + /// </summary> + /// <param name="input"></param> + /// <param name="maxEnglishLength"></param> + /// <returns></returns> + public static string TrancString(string input, int maxEnglishLength) + { + int counter = 0; + for (int i = 0, imax = input.Length; i < imax; ++i) + { + if (IsChineseLetter(input, i)) + { + if (counter <= maxEnglishLength && maxEnglishLength < (counter + 2)) + return input.Substring(0, i); + counter += 2; + } + else + { + if (counter <= maxEnglishLength && maxEnglishLength < (counter + 1)) + return input.Substring(0, i); + counter += 1; + } + } + + return input; + } + + /// <summary> + /// 是不是中文字符 + /// </summary> + /// <param name="input"></param> + /// <param name="index"></param> + /// <returns></returns> + public static bool IsChineseLetter(string input, int index) + { + int code = 0; + int chfrom = System.Convert.ToInt32("4e00", 16); + int chend = System.Convert.ToInt32("9fff", 16); + if (input != "") + { + code = System.Char.ConvertToUtf32(input, index); + + if (code >= chfrom && code <= chend) + { + return true; + } + else + { + return false; + } + } + return false; + } + + /// <summary> + /// 缩减字符串 + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static string ShrinkString(string str) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0, imax = str.Length; i < imax; i++) + { + if (str[i] == '\0') + break; + sb.Append(str[i]); + } + + return sb.ToString(); + } + + /// <summary> + /// 自定义的字符串比较 + /// </summary> + /// <param name="left"></param> + /// <param name="right"></param> + /// <returns></returns> + public static bool IsStringEqual(string left, string right) + { + if (System.Object.ReferenceEquals(left, right)) + { + return true; + } + + if (left == null && right == null) + return true; + if (left == null) + return false; + if (right == null) + return false; + + int leftLen = left.Length; + int rightLen = right.Length; + int count = Mathf.Min(leftLen, rightLen); + for (int index = 0; index < count; ++index) + { + char leftChar = left[index]; + char rightChar = right[index]; + if (leftChar != rightChar) + return false; + } + + if (leftLen > count && left[count] == '\0') + return true; + if (rightLen > count && right[count] == '\0') + return true; + if (leftLen == rightLen) + return true; + + return false; + } + + /// <summary> + /// Bytes数组转utf8字符串 + /// </summary> + /// <param name="buffer"></param> + /// <param name="fromIndex"></param> + /// <param name="count"></param> + /// <param name="bufferSize"></param> + /// <returns></returns> + public static string GetUtf8StringFromByteBuffer(ref byte[] buffer, int fromIndex, int count, int bufferSize) + { + if (buffer == null) + return string.Empty; + if (fromIndex < bufferSize) + { + int maxCount = bufferSize - fromIndex; + count = Mathf.Min(maxCount, count); + + string str = ShrinkString(System.Text.Encoding.UTF8.GetString(buffer, fromIndex, count)); + return str; + } + + YC.LogHelper.LogError("fromIndex over flow."); + return ""; + } + + /// <summary> + /// Bytes数组转utf8字符串 + /// </summary> + /// <param name="buffer"></param> + /// <returns></returns> + public static string GetUtf8StringFromByteBuffer(ref byte[] buffer) + { + return GetUtf8StringFromByteBuffer(ref buffer, 0, buffer.Length, buffer.Length); + } + + /// <summary> + /// Utf8字符串转Byte数组 + /// </summary> + /// <param name="srcStr"></param> + /// <param name="srcOffset"></param> + /// <param name="dstBuffer"></param> + /// <param name="dstOffset"></param> + /// <param name="dstBufferSize"></param> + public static void CopyByteBufferFromUtf8String(string srcStr, int srcOffset, ref byte[] dstBuffer, int dstOffset, int dstBufferSize) + { + int copyCount; + CopyByteBufferFromUtf8String(srcStr, srcOffset, ref dstBuffer, dstOffset, dstBufferSize, out copyCount); + } + + /// <summary> + /// Utf8字符串转Byte数组 + /// </summary> + /// <param name="srcStr"></param> + /// <param name="srcOffset"></param> + /// <param name="dstBuffer"></param> + /// <param name="dstOffset"></param> + /// <param name="dstBufferSize"></param> + /// <param name="copyCount"></param> + public static void CopyByteBufferFromUtf8String(string srcStr, int srcOffset, ref byte[] dstBuffer, int dstOffset, int dstBufferSize, out int copyCount) + { + byte[] srcBuffer = System.Text.Encoding.UTF8.GetBytes(srcStr); + int srcLen = srcBuffer.Length; + srcLen = Mathf.Max(srcLen - srcOffset, 0); + int dstMaxCopyCount = dstBufferSize - dstOffset; + dstMaxCopyCount = Mathf.Max(dstMaxCopyCount, 0); + dstMaxCopyCount = Mathf.Min(dstMaxCopyCount, srcLen); + System.Buffer.BlockCopy(srcBuffer, srcOffset, dstBuffer, dstOffset, dstMaxCopyCount); + + copyCount = dstMaxCopyCount; + } + + /// <summary> + /// Byte数组复制 + /// </summary> + /// <param name="srcBuffer"></param> + /// <param name="srcOffset"></param> + /// <param name="dstBuffer"></param> + /// <param name="dstOffset"></param> + /// <param name="dstBufferSize"></param> + public static void CopyByteBuffer(ref byte[] srcBuffer, int srcOffset, ref byte[] dstBuffer, int dstOffset, int dstBufferSize) + { + int copyCount; + CopyByteBuffer(ref srcBuffer, srcOffset, ref dstBuffer, dstOffset, dstBufferSize, out copyCount); + } + + /// <summary> + /// Byte数组复制 + /// </summary> + /// <param name="srcBuffer"></param> + /// <param name="srcOffset"></param> + /// <param name="dstBuffer"></param> + /// <param name="dstOffset"></param> + /// <param name="dstBufferSize"></param> + /// <param name="copyCount"></param> + public static void CopyByteBuffer(ref byte[] srcBuffer, int srcOffset, ref byte[] dstBuffer, int dstOffset, int dstBufferSize, out int copyCount) + { + int srcLen = srcBuffer.Length; + srcLen = Mathf.Max(srcLen - srcOffset, 0); + int dstMaxCopyCount = dstBufferSize - dstOffset; + dstMaxCopyCount = Mathf.Max(dstMaxCopyCount, 0); + dstMaxCopyCount = Mathf.Min(dstMaxCopyCount, srcLen); + System.Buffer.BlockCopy(srcBuffer, srcOffset, dstBuffer, dstOffset, dstMaxCopyCount); + + copyCount = dstMaxCopyCount; + } + + /// <summary> + /// Byte数组转十六进制字符串 + /// </summary> + /// <param name="bytes"></param> + /// <returns></returns> + public static string BytesToHex(byte[] bytes) + { + char[] c = new char[bytes.Length * 2]; + + byte b; + + for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx) + { + b = ((byte)(bytes[bx] >> 4)); + c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30); + + b = ((byte)(bytes[bx] & 0x0F)); + c[++cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30); + } + + return new string(c); + } + + /// <summary> + /// 十六进制字符串转Byte数组 + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static byte[] HexToBytes(string str) + { + if (str.Length == 0 || str.Length % 2 != 0) + return new byte[0]; + + byte[] buffer = new byte[str.Length / 2]; + char c; + for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx) + { + // Convert first half of byte + c = str[sx]; + buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4); + + // Convert second half of byte + c = str[++sx]; + buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')); + } + + return buffer; + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/ThirdParty/StringUtil/StringUtil_Other.cs.meta b/YesCommander/Assets/ThirdParty/StringUtil/StringUtil_Other.cs.meta new file mode 100644 index 0000000..6db4c41 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/StringUtil_Other.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5ae4f16a2f4c7254da9d834963922b33 +timeCreated: 1493352224 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/StringUtil/VString.cs b/YesCommander/Assets/ThirdParty/StringUtil/VString.cs new file mode 100644 index 0000000..3b716f7 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/VString.cs @@ -0,0 +1,620 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public static class StringExtend + { + private static volatile object lockThis = new object(); + + public static string ToTempString(this int i) + { + lock (lockThis) + { + return VString.IntToString(i); + } + } + + public static string ToTempString(this float f, int digits = 2) + { + lock (lockThis) + { + return VString.FloatToString(f, digits); + } + } + + public static string ToTempString(this long l) + { + lock (lockThis) + { + return VString.LongToString(l); + } + } + + public static string ToTempStringLower(this string str) + { + lock (lockThis) + { + return VString.ToLower(str); + } + } + + public static string ToTempStringUpper(this string str) + { + lock (lockThis) + { + return VString.ToUpper(str); + } + } + + public static string ToTempSubString(this string str, int index, int count) + { + lock (lockThis) + { + return VString.ToTempSubString(str, index, count); + } + } + + + + #region 转美式数字 + public static string ToStringUS(this float f) + { + return StringUtil.Num2US(f); + } + public static string ToStringUS(this int i) + { + return StringUtil.Num2US(i); + } + public static string ToStringUS(this long i) + { + return StringUtil.Num2US(i); + } + #endregion + + } + + + + + + + /// <summary> + /// 内容可变的字符串 + /// !!!只能作为临时变量使用,绝对不可以在逻辑中存储引用,包含VString和返回的string对象 + /// </summary> + public class VString + { + private string _data; + private int maxCount; + + private static int _internalVsIndex; + private static VString[] _internalVSArray = new VString[] + { + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64), + new VString(64) + }; + private static string[] digitalNumberArray = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + + + public VString(int maxCount = 1024) + { + this.maxCount = maxCount + 1; //多加一个,用于留1个给字符串结束符 + _data = new string('\0', this.maxCount); + Clear(); + } + + public string GetString() + { + return _data; + } + + + + /// <summary> + /// int转string,无GC,注意生成的string一定不能进行存贮 + /// </summary> + /// <param name="val"></param> + /// <returns></returns> + public static string IntToString(int val) + { + return LongToString(val); + } + + /// <summary> + /// long转string,无GC,注意生成的string一定不能进行存贮 + /// </summary> + /// <param name="val"></param> + /// <returns></returns> + public static string LongToString(long val) + { + if (val == 0) + { + return "0"; + } + + VString tempVS = GetInternalVString(); + bool isNegative = false; + if (val < 0) + { + val = -val; + isNegative = true; + } + + while (val != 0) + { + long mod = val % 10; + val = val / 10; + tempVS.Push(digitalNumberArray[mod]); + } + + if (isNegative) + { + tempVS.Push("-"); + } + + tempVS.ReverseString(); + return tempVS.GetString(); + } + + /// <summary> + /// float转string,无GC,注意生成的string一定不能进行存贮 + /// </summary> + /// <param name="f"></param> + /// <param name="digits">小数的位数</param> + /// <returns></returns> + public static string FloatToString(float f, int digits = 2) + { + bool isNegative = false; + if (f < 0) + { + f = -f; + isNegative = true; + } + + int iPart = Mathf.FloorToInt(f); + float fPart = f - iPart; + + VString tempVS0 = GetInternalVString(); + + + if (iPart != 0) + { + while (iPart != 0) + { + long mod = iPart % 10; + iPart = iPart / 10; + tempVS0.Push(digitalNumberArray[mod]); + } + } + else + { + tempVS0.Push("0"); + } + + if (isNegative) + { + tempVS0.Push("-"); + } + tempVS0.ReverseString(); + + + if (digits != 0) + { + VString tempVS1 = GetInternalVString(); + fPart = fPart * Mathf.Pow(10, digits); + int iPart2 = Mathf.RoundToInt(fPart); + + int i = 0; + while (iPart2 != 0 && i < digits) + { + long mod = iPart2 % 10; + iPart2 = iPart2 / 10; + i++; + tempVS1.Push(digitalNumberArray[mod]); + } + tempVS1.ReverseString(); + + tempVS0.Push("."); + tempVS0.Push(tempVS1.GetString()); + while (i < digits) + { + i++; + tempVS0.Push("0"); + } + } + else + { + tempVS0.Push("."); + for (int i = 0; i < digits; ++i) + { + tempVS0.Push("0"); + } + } + + return tempVS0.GetString(); + } + + + /// <summary> + /// 把一个字符串拷贝后,转换为lower case,,注意生成的string一定不能进行存贮 + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static string ToLower(string str) + { + if (!string.IsNullOrEmpty(str)) + { + VString tempVS = VStringShareObject.GetShareVString(); + tempVS.Push(str); + tempVS.ToLower(); + return tempVS.GetString(); + } + return str; + } + + /// <summary> + /// 把一个字符串拷贝后,转换为upper case,,注意生成的string一定不能进行存贮 + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static string ToUpper(string str) + { + if (!string.IsNullOrEmpty(str)) + { + VString tempVS = VStringShareObject.GetShareVString(); + tempVS.Push(str); + tempVS.ToUpper(); + return tempVS.GetString(); + } + return str; + } + + public static string ToTempSubString(string str, int index, int count) + { + if (string.IsNullOrEmpty(str) || count <= 0 || index < 0) + { + LogHelper.LogError(VStringUtil.Concat("ToTempSubString IsNullOrEmpty ", index.ToTempString(), "/", count.ToTempString())); + return str; + } + + if (index + count > str.Length) + { + LogHelper.LogError(VStringUtil.Concat("ToTempSubString ", str, index.ToTempString(), "/", count.ToTempString())); + return str; + } + + VString tempVS1 = VStringShareObject.GetShareVString(); + tempVS1.Push(str); + VString tempVS2 = VStringShareObject.GetShareVString(); + tempVS2.CopyFrom(tempVS1, index, count); + return tempVS2.GetString(); + } + + + /// <summary> + /// 拼接两个字符串 + /// </summary> + /// <param name="a"></param> + /// <param name="b"></param> + /// <param name="clear"></param> + /// <returns></returns> + public string Concat(string a, string b, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + return _data; + } + + + + public string Concat(string a, string b, string c, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + Push(c); + return _data; + } + public string Concat(string a, string b, string c, string d, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + Push(c); + Push(d); + return _data; + } + public string Concat(string a, string b, string c, string d, string e, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + Push(c); + Push(d); + Push(e); + return _data; + } + public string Concat(string a, string b, string c, string d, string e, string f, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + Push(c); + Push(d); + Push(e); + Push(f); + return _data; + } + public string Concat(string a, string b, string c, string d, string e, string f, string g, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + Push(c); + Push(d); + Push(e); + Push(f); + Push(g); + return _data; + } + public string Concat(string a, string b, string c, string d, string e, string f, string g, string h, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + Push(c); + Push(d); + Push(e); + Push(f); + Push(g); + Push(h); + return _data; + } + public string Concat(string a, string b, string c, string d, string e, string f, string g, string h, string i, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + Push(c); + Push(d); + Push(e); + Push(f); + Push(g); + Push(h); + Push(i); + return _data; + } + public string Concat(string a, string b, string c, string d, string e, string f, string g, string h, string i, string j, bool clear = true) + { + if (clear) + { + Clear(); + } + + Push(a); + Push(b); + Push(c); + Push(d); + Push(e); + Push(f); + Push(g); + Push(h); + Push(i); + Push(j); + return _data; + } + + + public static bool UseShareObject(string str) + { + for (int i = 0; i < _internalVSArray.Length; ++i) + { + if (string.ReferenceEquals(str, _internalVSArray[i].GetString())) + { + return true; + } + } + return false; + } + + + //往当前的字符串中添加字符串 + public unsafe void Push(string newStr) + { + if (string.IsNullOrEmpty(newStr)) + { + return; + } + + int copyLen = newStr.Length; + int newLen = _data.Length + copyLen; + if ((newLen + 1) > maxCount) //留1个给字符串结束符 + { + int len = newLen; + copyLen = maxCount - _data.Length - 1; + newLen = maxCount - 1; //设置新的长度 + //这个地方不使用VstringUtil.Concat避免死循环 + LogHelper.LogEditorError(StringUtil.Concat("超过了最大添加长度 ", maxCount.ToTempString(), " ", len.ToTempString())); + } + + if (copyLen <= 0) + { + return; + } + + fixed (char* src = newStr) + { + fixed (char* dst = _data) + { + UnsafeFunction.memcpyimpl((byte*)src, (byte*)(dst + _data.Length), copyLen * 2); //system.string的存储每个元素两个字节 + + int* iDst = (int*)dst; + iDst = iDst - 1; //字符串的长度在第一个元素的前面4个字节 + *iDst = newLen; + + char* iEnd = (char*)(dst + newLen); + *iEnd = (char)0;//设置字符串结束符 + } + } + } + + + public unsafe void Clear() + { + fixed (char* p = _data) + { + int* pSize = (int*)p; + pSize = pSize - 1; + *pSize = 0; + } + } + + public unsafe void CopyFrom(VString srcVstring, int startIndex, int count) + { + if ((count + 1) > maxCount) //留1个给字符串结束符 + { + throw new ArgumentException(VStringUtil.Concat("copy count is larger then maxCount ", + count.ToTempString(), " ", maxCount.ToTempString())); + } + + string srcStr = srcVstring.GetString(); + if (startIndex + count > srcStr.Length) + { + throw new ArgumentException(VStringUtil.Concat("copy count is larger then srcString len ", + count.ToTempString(), " ", srcStr.Length.ToTempString(), " ", startIndex.ToTempString())); + } + + Clear(); + + fixed (char* src = srcStr) + { + fixed (char* dst = _data) + { + UnsafeFunction.memcpyimpl((byte*)(src + startIndex), (byte*)dst, count * 2); //system.string的存储每个元素两个字节 + + int* iDst = (int*)dst; + iDst = iDst - 1; //字符串的长度在第一个元素的前面4个字节 + *iDst = count; + + char* iEnd = (char*)(dst + _data.Length); + *iEnd = (char)0;//设置字符串结束符 + } + } + } + + public unsafe void ToLower() + { + int index = 0; + int len = _data.Length; + fixed (char* dst = _data) + { + while (index < len) + { + char tempChar = *(dst + index); + *(dst + index) = char.ToLower(tempChar); + ++index; + } + } + } + + public unsafe void ToUpper() + { + int index = 0; + int len = _data.Length; + fixed (char* dst = _data) + { + while (index < len) + { + char tempChar = *(dst + index); + *(dst + index) = char.ToUpper(tempChar); + ++index; + } + } + } + + //反转字符串的内容 + private unsafe string ReverseString() + { + int len = _data.Length; + if (len > 0) + { + fixed (char* pHead = _data) + { + int count = len / 2; + for (int i = 0; i < count; ++i) + { + char temp = pHead[i]; + pHead[i] = pHead[len - 1 - i]; + pHead[len - 1 - i] = temp; + } + } + } + return _data; + } + + + private static VString GetInternalVString() + { + _internalVsIndex = (_internalVsIndex + 1) % _internalVSArray.Length; + VString vString = _internalVSArray[_internalVsIndex]; + vString.Clear(); + return vString; + } + + } +} diff --git a/YesCommander/Assets/ThirdParty/StringUtil/VString.cs.meta b/YesCommander/Assets/ThirdParty/StringUtil/VString.cs.meta new file mode 100644 index 0000000..1a0afa7 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/VString.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 070edb2882bc15d49917028ddea695e2 +timeCreated: 1525942883 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/StringUtil/VStringShareObject.cs b/YesCommander/Assets/ThirdParty/StringUtil/VStringShareObject.cs new file mode 100644 index 0000000..22fd660 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/VStringShareObject.cs @@ -0,0 +1,56 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + public static class VStringShareObject + { + + private static volatile object lockThis = new object(); + private static int _internalVsIndex; + private static VString[] _internalVSArray = new VString[] + { + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048), + new VString(2048) + }; + + + public static VString GetShareVString() + { + lock (lockThis) + { + _internalVsIndex = (_internalVsIndex + 1) % _internalVSArray.Length; + VString vString = _internalVSArray[_internalVsIndex]; + vString.Clear(); + return vString; + } + } + + public static bool UseShareObject(string str) + { + for (int i = 0; i < _internalVSArray.Length; ++i) + { + if (string.ReferenceEquals(str, _internalVSArray[i].GetString())) + { + return true; + } + } + return false; + } + } +} diff --git a/YesCommander/Assets/ThirdParty/StringUtil/VStringShareObject.cs.meta b/YesCommander/Assets/ThirdParty/StringUtil/VStringShareObject.cs.meta new file mode 100644 index 0000000..b40aa4a --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/VStringShareObject.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c6d08c5051585094fb4d23fdf6fe4b7b +timeCreated: 1552276176 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/StringUtil/VStringUtil.cs b/YesCommander/Assets/ThirdParty/StringUtil/VStringUtil.cs new file mode 100644 index 0000000..18d4334 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/VStringUtil.cs @@ -0,0 +1,110 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace YC +{ + + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public class VStringUtil + { + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, true); + return vString.GetString(); + } + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b, string c) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, c, true); + return vString.GetString(); + } + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b, string c, string d) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, c, d, true); + return vString.GetString(); + } + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b, string c, string d, string e) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, c, d, e, true); + return vString.GetString(); + } + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b, string c, string d, string e, string f) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, c, d, e, f, true); + return vString.GetString(); + } + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b, string c, string d, string e, string f, string g) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, c, d, e, f, g, true); + return vString.GetString(); + } + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b, string c, string d, string e, string f, string g, string h) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, c, d, e, f, g, h, true); + return vString.GetString(); + } + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b, string c, string d, string e, string f, string g, string h, string i) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, c, d, e, f, g, h, i, true); + return vString.GetString(); + } + /// <summary> + /// 只能作为临时字符串使用,代码任何地方使用只能赋值给临时变量,不可保存 + /// </summary> + public static string Concat(string a, string b, string c, string d, string e, string f, string g, string h, string i, string j) + { + VString vString = VStringShareObject.GetShareVString(); + vString.Concat(a, b, c, d, e, f, g, h, i, j, true); + return vString.GetString(); + } + + /// <summary> + /// 如果不是共享string,则返回str,如果是共享string则返回copy str + /// </summary> + /// <param name="str"></param> + /// <returns></returns> + public static string ConvertToNormalString(string str) + { + if (VStringShareObject.UseShareObject(str) || VString.UseShareObject(str)) + { + return string.Copy(str); + } + return str; + } + + } +} diff --git a/YesCommander/Assets/ThirdParty/StringUtil/VStringUtil.cs.meta b/YesCommander/Assets/ThirdParty/StringUtil/VStringUtil.cs.meta new file mode 100644 index 0000000..721f40c --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/VStringUtil.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1816e678bcdfdb646b247fb5419f1279 +timeCreated: 1525954142 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/StringUtil/VTypingString.cs b/YesCommander/Assets/ThirdParty/StringUtil/VTypingString.cs new file mode 100644 index 0000000..727ea62 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/VTypingString.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +namespace YC +{ + + /// <summary> + /// 优化打字功能的字符串 + /// </summary> + public class VTypingString + { + enum Tags + { + Color = 0, + Size, + B, + I + } + + + private VString allContentString; + private DoubleVString partialDisplayString; + private VString willShowString; + + private int _timerMS; + private int _factor; + private int _miniSecondPerWord; + + private static readonly string[] endTags = new string[] { "</color>", "</size>", "</b>", "</i>" }; + private static readonly string[] startTags = new string[] { "<color", "<size", "<b", "<i" }; + + List<int> endTagCaches = new List<int>(); + + + /// <summary> + /// + /// </summary> + /// <param name="text"></param> + /// <param name="miniSecondPerWord">出一个字符需要的毫秒时间</param> + public VTypingString(string text, int miniSecondPerWord = 240) + { + if (string.IsNullOrEmpty(text)) + { + throw new ArgumentException("text is null or empty"); + } + + _miniSecondPerWord = Mathf.Max(miniSecondPerWord, 10); + allContentString = new VString(text.Length); + allContentString.Push(text); + partialDisplayString = new DoubleVString(text.Length); + willShowString = new VString(text.Length); + JumpToBegin(); + } + + public bool IsEnd() + { + return _factor > allContentString.GetString().Length; + } + + public string GetString() + { + return partialDisplayString.GetCurrentVString().GetString(); + } + + /// <summary> + /// + /// </summary> + /// <param name="deltaTimeMS"></param> + /// <returns>true表示触发了一次打字变化</returns> + public bool OnUpdate(int deltaTimeMS) + { + _timerMS += deltaTimeMS; + if (_timerMS >= _miniSecondPerWord) + { + _timerMS = 0; + OnTyping(); + return true; + } + return false; + } + + private void OnTyping() + { + if (CheckStart(Tags.Color)) { } + else if (CheckStart(Tags.Size)) { } + else if (CheckStart(Tags.B)) { } + else if (CheckStart(Tags.I)) { } + else + { + partialDisplayString.GetCurrentVString().Clear(); + partialDisplayString.SwapVString(); + partialDisplayString.GetCurrentVString().CopyFrom(allContentString, 0, Mathf.Min(_factor, allContentString.GetString().Length)); + for (int i = endTagCaches.Count - 1; i >= 0; --i) + { + partialDisplayString.GetCurrentVString().Push(endTags[endTagCaches[i]]); + } + _factor++; + } + } + + public void JumpToBegin() + { + _factor = 0; + _timerMS = -_miniSecondPerWord; + endTagCaches.Clear(); + partialDisplayString.GetCurrentVString().Clear(); + partialDisplayString.GetNextVString().Clear(); + } + + public void JumpToEnd() + { + _factor = allContentString.GetString().Length; + endTagCaches.Clear(); + OnTyping(); + } + + + bool CheckStart(Tags tag) + { + if (_factor >= allContentString.GetString().Length) + { + return false; + } + + int iTag = (int)tag; + willShowString.CopyFrom(allContentString, _factor, allContentString.GetString().Length - _factor); + string willShow = willShowString.GetString(); + string endTag = endTags[iTag]; + if (willShow.StartsWith(startTags[iTag])) + { + int tagLeng = willShow.IndexOf(">") + 1; + _factor += tagLeng; + endTagCaches.Add(iTag);//倒叙 + + if (CheckStart(Tags.Color)) { } + else if (CheckStart(Tags.Size)) { } + else if (CheckStart(Tags.B)) { } + else if (CheckStart(Tags.I)) { } + else + { + return false; + } + return true; + } + else if (willShow.StartsWith(endTag)) + { + int endleng = endTag.Length;//"</color>"的长度 + _factor += endleng; + for (int i = endTagCaches.Count - 1; i >= 0; --i) + { + if (iTag == endTagCaches[i]) + { + endTagCaches.RemoveAt(i); + } + } + + if (CheckStart(Tags.Color)) { } + else if (CheckStart(Tags.Size)) { } + else if (CheckStart(Tags.B)) { } + else if (CheckStart(Tags.I)) { } + else + { + return false; + } + return true; + } + return false; + } + + + } + +} diff --git a/YesCommander/Assets/ThirdParty/StringUtil/VTypingString.cs.meta b/YesCommander/Assets/ThirdParty/StringUtil/VTypingString.cs.meta new file mode 100644 index 0000000..6f7b5ae --- /dev/null +++ b/YesCommander/Assets/ThirdParty/StringUtil/VTypingString.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 49843f8b3aca65e4ca985d3226e77ad0 +timeCreated: 1542200708 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/YesCommander/Assets/ThirdParty/UnsafeFunction.cs b/YesCommander/Assets/ThirdParty/UnsafeFunction.cs new file mode 100644 index 0000000..3362626 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/UnsafeFunction.cs @@ -0,0 +1,53 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + + + +public class UnsafeFunction +{ + + public unsafe static void memcpyimpl(byte* src, byte* dest, int len) + { + if (len >= 16) + { + do + { + *(int*)dest = *(int*)src; + *(int*)(dest + 4) = *(int*)(src + 4); + *(int*)(dest + 8) = *(int*)(src + 8); + *(int*)(dest + 12) = *(int*)(src + 12); + dest += 16; + src += 16; + } + while ((len -= 16) >= 16); + } + if (len > 0) + { + if ((len & 8) != 0) + { + *(int*)dest = *(int*)src; + *(int*)(dest + 4) = *(int*)(src + 4); + dest += 8; + src += 8; + } + if ((len & 4) != 0) + { + *(int*)dest = *(int*)src; + dest += 4; + src += 4; + } + if ((len & 2) != 0) + { + *(short*)dest = *(short*)src; + dest += 2; + src += 2; + } + if ((len & 1) != 0) + { + *(dest++) = *(src++); + } + } + } + +}
\ No newline at end of file diff --git a/YesCommander/Assets/ThirdParty/UnsafeFunction.cs.meta b/YesCommander/Assets/ThirdParty/UnsafeFunction.cs.meta new file mode 100644 index 0000000..f8daf55 --- /dev/null +++ b/YesCommander/Assets/ThirdParty/UnsafeFunction.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e441a31642a642f40a94673eadc379dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |