summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2024-05-19 16:38:03 +0800
committerchai <215380520@qq.com>2024-05-19 16:38:03 +0800
commit43a5ba7683a8d446fcdc6bd9939512a6e1700daf (patch)
tree71140c6dc58178b0735b0a810b37a679321f78ee
parent1b391f68c793406701a23dd2fd6026997288e9d3 (diff)
+ utils + thirdparty
-rw-r--r--YesCommander/Assets/Scripts/Common.meta8
-rw-r--r--YesCommander/Assets/Scripts/Common/Common.cs348
-rw-r--r--YesCommander/Assets/Scripts/Common/Common.cs.meta12
-rw-r--r--YesCommander/Assets/Scripts/Common/CommonFunction.cs57
-rw-r--r--YesCommander/Assets/Scripts/Common/CommonFunction.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Common/CommonParse.cs317
-rw-r--r--YesCommander/Assets/Scripts/Common/CommonParse.cs.meta12
-rw-r--r--YesCommander/Assets/Scripts/Common/Singleton.cs20
-rw-r--r--YesCommander/Assets/Scripts/Common/Singleton.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Common/SingletonMB.cs62
-rw-r--r--YesCommander/Assets/Scripts/Common/SingletonMB.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools.meta8
-rw-r--r--YesCommander/Assets/Scripts/Tools/CSVReader.cs147
-rw-r--r--YesCommander/Assets/Scripts/Tools/CSVReader.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/ChildLocator.cs96
-rw-r--r--YesCommander/Assets/Scripts/Tools/ChildLocator.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Commands.meta8
-rw-r--r--YesCommander/Assets/Scripts/Tools/Commands/Command.cs50
-rw-r--r--YesCommander/Assets/Scripts/Tools/Commands/Command.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Commands/CommandGroup.cs96
-rw-r--r--YesCommander/Assets/Scripts/Tools/Commands/CommandGroup.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/FlagManager.cs44
-rw-r--r--YesCommander/Assets/Scripts/Tools/FlagManager.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/GameObjectPool.cs51
-rw-r--r--YesCommander/Assets/Scripts/Tools/GameObjectPool.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/GlobalEventManager.cs97
-rw-r--r--YesCommander/Assets/Scripts/Tools/GlobalEventManager.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Info.cs41
-rw-r--r--YesCommander/Assets/Scripts/Tools/Info.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Notification.meta8
-rw-r--r--YesCommander/Assets/Scripts/Tools/Notification/NotificationCenter.cs167
-rw-r--r--YesCommander/Assets/Scripts/Tools/Notification/NotificationCenter.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Notification/NotificationExtensions.cs19
-rw-r--r--YesCommander/Assets/Scripts/Tools/Notification/NotificationExtensions.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Notification/ScopedNotification.cs92
-rw-r--r--YesCommander/Assets/Scripts/Tools/Notification/ScopedNotification.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/ObjectPool.cs51
-rw-r--r--YesCommander/Assets/Scripts/Tools/ObjectPool.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Recycle.cs70
-rw-r--r--YesCommander/Assets/Scripts/Tools/Recycle.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/ScopedEvent.cs54
-rw-r--r--YesCommander/Assets/Scripts/Tools/ScopedEvent.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Statemachine.meta8
-rw-r--r--YesCommander/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs254
-rw-r--r--YesCommander/Assets/Scripts/Tools/Statemachine/AsyncStatemachine.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Statemachine/BasicStatemachine.cs250
-rw-r--r--YesCommander/Assets/Scripts/Tools/Statemachine/BasicStatemachine.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Statemachine/LiteStatemachine.cs23
-rw-r--r--YesCommander/Assets/Scripts/Tools/Statemachine/LiteStatemachine.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs87
-rw-r--r--YesCommander/Assets/Scripts/Tools/ThreadSafeElapsedTime.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem.meta8
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem/Action.cs16
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem/Action.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalActiveTrigger.cs18
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalActiveTrigger.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalPassiveTrigger.cs110
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem/GlobalPassiveTrigger.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem/Trigger.cs44
-rw-r--r--YesCommander/Assets/Scripts/Tools/TriggerSystem/Trigger.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/Trinary Software.meta9
-rw-r--r--YesCommander/Assets/Scripts/Tools/Trinary Software/Editor.meta9
-rw-r--r--YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.pngbin0 -> 36388 bytes
-rw-r--r--YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png.meta57
-rw-r--r--YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdfbin0 -> 690071 bytes
-rw-r--r--YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf.meta8
-rw-r--r--YesCommander/Assets/Scripts/Tools/Trinary Software/Timing.cs4655
-rw-r--r--YesCommander/Assets/Scripts/Tools/Trinary Software/Timing.cs.meta12
-rw-r--r--YesCommander/Assets/Scripts/Tools/UniqueStringMap.cs51
-rw-r--r--YesCommander/Assets/Scripts/Tools/UniqueStringMap.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Tools/UnityObjectPool.cs128
-rw-r--r--YesCommander/Assets/Scripts/Tools/UnityObjectPool.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/AsyncUtils.cs22
-rw-r--r--YesCommander/Assets/Scripts/Utils/AsyncUtils.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/DontDestroySelf.cs19
-rw-r--r--YesCommander/Assets/Scripts/Utils/DontDestroySelf.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/Extents.meta8
-rw-r--r--YesCommander/Assets/Scripts/Utils/Extents/TransformExtent.cs135
-rw-r--r--YesCommander/Assets/Scripts/Utils/Extents/TransformExtent.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/FPSScript.cs33
-rw-r--r--YesCommander/Assets/Scripts/Utils/FPSScript.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/GameObjectExtensions.cs50
-rw-r--r--YesCommander/Assets/Scripts/Utils/GameObjectExtensions.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/LogHelper.cs26
-rw-r--r--YesCommander/Assets/Scripts/Utils/LogHelper.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/MathUtils.cs27
-rw-r--r--YesCommander/Assets/Scripts/Utils/MathUtils.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/SetSortingOrder.cs31
-rw-r--r--YesCommander/Assets/Scripts/Utils/SetSortingOrder.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/StringUtils.cs48
-rw-r--r--YesCommander/Assets/Scripts/Utils/StringUtils.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/TransformUtils.cs18
-rw-r--r--YesCommander/Assets/Scripts/Utils/TransformUtils.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/Vector2Extension.cs29
-rw-r--r--YesCommander/Assets/Scripts/Utils/Vector2Extension.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/Vector3Extension.cs31
-rw-r--r--YesCommander/Assets/Scripts/Utils/Vector3Extension.cs.meta11
-rw-r--r--YesCommander/Assets/Scripts/Utils/Vector4Extension.cs39
-rw-r--r--YesCommander/Assets/Scripts/Utils/Vector4Extension.cs.meta11
-rw-r--r--YesCommander/Assets/ThirdParty.meta8
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser.meta8
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/.gitignore15
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.meta8
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.sln22
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser.sln.meta7
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/CSV Parser.csproj13
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/CSV Parser.csproj.meta7
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src.meta8
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/CSVParser.cs181
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/CSVParser.cs.meta11
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/Delimiter.cs9
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/Delimiter.cs.meta11
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/DelimiterExtensions.cs24
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/CSV Parser/src/DelimiterExtensions.cs.meta11
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/LICENSE35
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/LICENSE.meta7
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/README.md102
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/README.md.meta7
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/RELEASE.md14
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/RELEASE.md.meta7
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/Tests.meta8
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/Unity Examples.meta8
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/global.json7
-rw-r--r--YesCommander/Assets/ThirdParty/CSV-Parser/global.json.meta7
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson.meta8
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/IJsonWrapper.cs60
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/IJsonWrapper.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonData.cs1032
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonData.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonException.cs60
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonException.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonFormatter.cs144
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonFormatter.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonMapper.cs1091
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonMapper.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonReader.cs455
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonReader.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonWriter.cs595
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/JsonWriter.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/Lexer.cs912
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/Lexer.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/ParserToken.cs44
-rw-r--r--YesCommander/Assets/ThirdParty/LitJson/ParserToken.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil.meta8
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/DoubleVString.cs40
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/DoubleVString.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/StringUtil.cs750
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/StringUtil.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/StringUtil_Other.cs300
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/StringUtil_Other.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/VString.cs620
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/VString.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/VStringShareObject.cs56
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/VStringShareObject.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/VStringUtil.cs110
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/VStringUtil.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/VTypingString.cs176
-rw-r--r--YesCommander/Assets/ThirdParty/StringUtil/VTypingString.cs.meta12
-rw-r--r--YesCommander/Assets/ThirdParty/UnsafeFunction.cs53
-rw-r--r--YesCommander/Assets/ThirdParty/UnsafeFunction.cs.meta11
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>
+ /// csv񣬲key洢ֵ
+ /// </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
new file mode 100644
index 0000000..caf3365
--- /dev/null
+++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Editor/MecIcon.png
Binary files differ
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
new file mode 100644
index 0000000..e2f028f
--- /dev/null
+++ b/YesCommander/Assets/Scripts/Tools/Trinary Software/Quick Start Guide.pdf
Binary files differ
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#
+
+[![Test](https://github.com/yutokun/CSV-Parser/actions/workflows/test.yml/badge.svg)](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: