您不能選擇超過 %s 個話題 話題必須以字母或數字為開頭,可包含連接號 ('-') 且最長為 35 個字
 
 
 

397 行
9.8 KiB

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using SUISS.Core;
  5. using SUISS.Core.Utilities;
  6. using UnityEngine;
  7. namespace SUISS.Scheduling
  8. {
  9. public class Scheduler : SingletonMonobehaviour<Scheduler>, IComparer<IEnumerator>
  10. {
  11. private SortedDictionary<IEnumerator, IEnumerator> Routines
  12. {
  13. get
  14. {
  15. if (this._routines == null)
  16. {
  17. this._routines = new SortedDictionary<IEnumerator, IEnumerator>(this);
  18. }
  19. return this._routines;
  20. }
  21. }
  22. private void Update()
  23. {
  24. foreach (IEnumerator enumerator2 in new List<IEnumerator>(this.Routines.Keys))
  25. {
  26. object obj = enumerator2.Current;
  27. if (obj != null)
  28. {
  29. if (obj is double)
  30. {
  31. if (Scheduler.TimeLeft(enumerator2) > 0.0)
  32. {
  33. break;
  34. }
  35. }
  36. else if (obj is AsyncOperation && !((AsyncOperation)obj).isDone)
  37. {
  38. continue;
  39. }
  40. }
  41. this.Execute(enumerator2);
  42. }
  43. }
  44. public int Compare(IEnumerator xEnum, IEnumerator yEnum)
  45. {
  46. object obj = xEnum.Current;
  47. object obj2 = yEnum.Current;
  48. if (obj == null || obj2 == null)
  49. {
  50. if (obj != null)
  51. {
  52. return 1;
  53. }
  54. if (obj2 != null)
  55. {
  56. return -1;
  57. }
  58. }
  59. else if (obj is double || obj2 is double)
  60. {
  61. if (!(obj is double))
  62. {
  63. return -1;
  64. }
  65. if (!(obj2 is double))
  66. {
  67. return 1;
  68. }
  69. double num = (double)obj;
  70. double num2 = (double)obj2;
  71. if (num < num2)
  72. {
  73. return -1;
  74. }
  75. if (num > num2)
  76. {
  77. return 1;
  78. }
  79. }
  80. if (!this._uniqueIdentifiers.ContainsKey(xEnum))
  81. {
  82. this._uniqueIdentifiers[xEnum] = this._nextUniqueIdentifier++;
  83. }
  84. if (!this._uniqueIdentifiers.ContainsKey(yEnum))
  85. {
  86. this._uniqueIdentifiers[yEnum] = this._nextUniqueIdentifier++;
  87. }
  88. return this._uniqueIdentifiers[xEnum] - this._uniqueIdentifiers[yEnum];
  89. }
  90. public void StartRoutine(IEnumerator routine, GameObject go)
  91. {
  92. if (go != null)
  93. {
  94. this._gameObjects.Add(routine, go);
  95. this._debugInfo.Add(routine, string.Format("{0}: {1}", this.FullName(go), SUISS.Core.Utilities.StackTraceUtility.ExtractStackTrace()));
  96. }
  97. this.StartRoutine(routine);
  98. }
  99. private string FullName(GameObject go)
  100. {
  101. string text = string.Empty;
  102. Transform transform = go.transform;
  103. while (transform != null)
  104. {
  105. if (text.Length == 0)
  106. {
  107. text = transform.name;
  108. }
  109. else
  110. {
  111. text = string.Format("{0}/{1}", transform.name, text);
  112. }
  113. transform = transform.parent;
  114. }
  115. return text;
  116. }
  117. public void StartRoutine(IEnumerator routine)
  118. {
  119. if (this.Routines.ContainsKey(routine))
  120. {
  121. throw new SchedulerException("You are calling StartRoutine on a routine that was already started.");
  122. }
  123. this.Routines.Add(routine, routine);
  124. this.Execute(routine);
  125. }
  126. public bool IsRunning(IEnumerator routine)
  127. {
  128. return this.Routines.ContainsKey(routine);
  129. }
  130. public void StopRoutine(IEnumerator routine)
  131. {
  132. bool leaf = this.Routines.Remove(routine);
  133. this.CleanupRoutine(routine, leaf, false);
  134. }
  135. [Obsolete("You are calling MonoBehaviour.StartCoroutine while you meant to use Scheduler.StartRoutine instead.", true)]
  136. public new void StartCoroutine(IEnumerator routine)
  137. {
  138. throw new InvalidOperationException("You are calling MonoBehaviour.StartCoroutine while you meant to use Scheduler.StartRoutine instead.");
  139. }
  140. [Obsolete("You are calling MonoBehaviour.StopCoroutine while you meant to use Scheduler.StopRoutine instead.", true)]
  141. public new void StopCoroutine(IEnumerator routine)
  142. {
  143. throw new InvalidOperationException("You are calling MonoBehaviour.StopCoroutine while you meant to use Scheduler.StopRoutine instead.");
  144. }
  145. public void ExecuteNextFrame(GameObject go, Action action)
  146. {
  147. this.StartRoutine(Scheduler.NextFrame(action), go);
  148. }
  149. public void ExecuteNextFrame(Action action)
  150. {
  151. this.StartRoutine(Scheduler.NextFrame(action));
  152. }
  153. public IEnumerator ExecuteDelayed(Action action, float delaySeconds)
  154. {
  155. IEnumerator result;
  156. this.StartRoutine(result = Scheduler.Delayed(action, delaySeconds));
  157. return result;
  158. }
  159. [Obsolete("This is nasty! Just keep track of your routines, and clean them up yourself.", false)]
  160. public void DestroyedGameObject(GameObject go)
  161. {
  162. IEnumerator enumerator;
  163. do
  164. {
  165. enumerator = null;
  166. foreach (KeyValuePair<IEnumerator, GameObject> keyValuePair in this._gameObjects)
  167. {
  168. if (object.ReferenceEquals(keyValuePair.Value, go))
  169. {
  170. enumerator = keyValuePair.Key;
  171. break;
  172. }
  173. }
  174. if (enumerator != null)
  175. {
  176. this.StopRoutine(enumerator);
  177. }
  178. }
  179. while (enumerator != null);
  180. }
  181. private void Execute(IEnumerator routine)
  182. {
  183. this.Routines.Remove(routine);
  184. GameObject gameObject = null;
  185. bool flag = false;
  186. if (this._gameObjects.TryGetValue(routine, out gameObject))
  187. {
  188. if (gameObject != null)
  189. {
  190. flag = routine.MoveNext();
  191. }
  192. else
  193. {
  194. string arg = "unknown";
  195. try
  196. {
  197. arg = gameObject.name;
  198. }
  199. catch
  200. {
  201. }
  202. string arg2 = string.Empty;
  203. if (this._debugInfo.ContainsKey(routine))
  204. {
  205. arg2 = "\n" + this._debugInfo[routine];
  206. }
  207. UnityEngine.Debug.LogError(string.Format("Routine was still running on gameObject ({0}) that has been destroyed.{1}", arg, arg2));
  208. }
  209. }
  210. else
  211. {
  212. flag = routine.MoveNext();
  213. }
  214. if (flag)
  215. {
  216. object obj = routine.Current;
  217. if (obj is IEnumerator)
  218. {
  219. IEnumerator enumerator = (IEnumerator)obj;
  220. if (!this._parents.ContainsKey(enumerator))
  221. {
  222. this._parents[enumerator] = new List<IEnumerator>();
  223. }
  224. this._parents[enumerator].Add(routine);
  225. bool flag2 = this.IsRunning(enumerator);
  226. if (!flag2)
  227. {
  228. foreach (List<IEnumerator> list in this._parents.Values)
  229. {
  230. if (list.Contains(enumerator))
  231. {
  232. flag2 = true;
  233. break;
  234. }
  235. }
  236. }
  237. if (!flag2)
  238. {
  239. this.Routines.Add(enumerator, enumerator);
  240. if (gameObject != null)
  241. {
  242. this._gameObjects.Add(enumerator, gameObject);
  243. this._debugInfo.Add(enumerator, string.Format("{0}: {1}", this.FullName(gameObject), SUISS.Core.Utilities.StackTraceUtility.ExtractStackTrace()));
  244. }
  245. this.Execute(enumerator);
  246. }
  247. else if (this._parents[enumerator].Count < 2)
  248. {
  249. UnityEngine.Debug.LogWarning("Child routine was already running, but it had no parent routines!");
  250. }
  251. }
  252. else
  253. {
  254. if (this.Routines.ContainsKey(routine))
  255. {
  256. UnityEngine.Debug.LogWarning(string.Format("Routine {0} with Current {1} is already in Routines as {2} with current {3}", new object[]
  257. {
  258. routine,
  259. routine.Current,
  260. this.Routines[routine],
  261. this.Routines[routine].Current
  262. }));
  263. }
  264. this.Routines.Add(routine, routine);
  265. }
  266. }
  267. else
  268. {
  269. this.CleanupRoutine(routine, true, true);
  270. }
  271. }
  272. private void CleanupRoutine(IEnumerator routine, bool leaf, bool executeParents)
  273. {
  274. this._gameObjects.Remove(routine);
  275. this._debugInfo.Remove(routine);
  276. this._uniqueIdentifiers.Remove(routine);
  277. if (leaf)
  278. {
  279. if (this._parents.ContainsKey(routine))
  280. {
  281. List<IEnumerator> list = this._parents[routine];
  282. this._parents.Remove(routine);
  283. foreach (IEnumerator enumerator2 in list)
  284. {
  285. this.Routines.Add(enumerator2, enumerator2);
  286. }
  287. if (executeParents)
  288. {
  289. foreach (IEnumerator routine2 in list)
  290. {
  291. this.Execute(routine2);
  292. }
  293. }
  294. }
  295. }
  296. else
  297. {
  298. IEnumerator enumerator4 = null;
  299. bool flag = false;
  300. foreach (IEnumerator enumerator6 in this._parents.Keys)
  301. {
  302. if (this._parents[enumerator6].Contains(routine))
  303. {
  304. enumerator4 = enumerator6;
  305. if (this._parents[enumerator6].Count > 1)
  306. {
  307. this._parents[enumerator6].Remove(routine);
  308. }
  309. else
  310. {
  311. flag = true;
  312. }
  313. break;
  314. }
  315. }
  316. if (enumerator4 == null)
  317. {
  318. UnityEngine.Debug.LogWarning("Unable to find routine in _parents");
  319. }
  320. else if (flag)
  321. {
  322. this._parents.Remove(enumerator4);
  323. bool leaf2 = this.Routines.Remove(enumerator4);
  324. this.CleanupRoutine(enumerator4, leaf2, false);
  325. }
  326. else
  327. {
  328. this.CleanupRoutine(routine, true, executeParents);
  329. }
  330. }
  331. }
  332. public static IEnumerator NextFrame(Action action)
  333. {
  334. if (action != null)
  335. {
  336. yield return null;
  337. action();
  338. }
  339. yield break;
  340. }
  341. public static IEnumerator Delayed(Action action, float delaySeconds)
  342. {
  343. if (action != null)
  344. {
  345. yield return Timing.time + (double)delaySeconds;
  346. action();
  347. }
  348. yield break;
  349. }
  350. public static double TimeLeft(IEnumerator routine)
  351. {
  352. object obj = routine.Current;
  353. if (obj == null)
  354. {
  355. return 1E-06;
  356. }
  357. if (obj is double)
  358. {
  359. return (double)obj - Timing.time;
  360. }
  361. UnityEngine.Debug.LogWarning(string.Format("TimeLeft requested on routine of which current (type {0}) is not a double", obj.GetType()));
  362. return 0.0;
  363. }
  364. private Dictionary<IEnumerator, int> _uniqueIdentifiers = new Dictionary<IEnumerator, int>();
  365. private int _nextUniqueIdentifier;
  366. private SortedDictionary<IEnumerator, IEnumerator> _routines;
  367. private Dictionary<IEnumerator, List<IEnumerator>> _parents = new Dictionary<IEnumerator, List<IEnumerator>>();
  368. private Dictionary<IEnumerator, GameObject> _gameObjects = new Dictionary<IEnumerator, GameObject>();
  369. private Dictionary<IEnumerator, string> _debugInfo = new Dictionary<IEnumerator, string>();
  370. }
  371. }