Advertisement
Guest User

Untitled

a guest
Dec 18th, 2014
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.69 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public delegate bool Condition();
  6. public delegate void Operation();
  7.  
  8. namespace Edge
  9. {
  10. /// <summary>
  11. /// The context of each action, it may spawn more sub coroutines.
  12. /// </summary>
  13. class ActionContext
  14. {
  15. public IEnumerator Action;
  16. public List<IEnumerator> Spawns;
  17.  
  18. public ActionContext(IEnumerator body)
  19. {
  20. Action = body;
  21. Spawns = new List<IEnumerator>();
  22. }
  23. }
  24.  
  25. /// <summary>
  26. /// The basic yield instruction of the scheduler system.
  27. /// </summary>
  28. public class YieldCommand : IEnumerator
  29. {
  30. public virtual object Current
  31. {
  32. get { return null; }
  33. }
  34.  
  35. public virtual bool MoveNext()
  36. {
  37. return true;
  38. }
  39.  
  40. public virtual void Reset()
  41. {
  42. // nop
  43. }
  44. }
  45.  
  46. /// <summary>
  47. /// A simple conditional yield instruction of the scheduler system.
  48. /// </summary>
  49. public class IfThenYieldCommand : YieldCommand
  50. {
  51. public override object Current
  52. {
  53. get { return mLock ? this : mBody.Current; }
  54. }
  55.  
  56. public IfThenYieldCommand(Condition cond, IEnumerator body)
  57. {
  58. mLock = true;
  59. mCond = cond;
  60. mBody = body;
  61. }
  62.  
  63. public override bool MoveNext()
  64. {
  65. if (mLock)
  66. {
  67. // release the lock if the condition meet
  68. mLock = !mCond();
  69. }
  70.  
  71. if (!mLock)
  72. {
  73. return mBody.MoveNext();
  74. }
  75. else
  76. {
  77. // always wait
  78. return true;
  79. }
  80. }
  81.  
  82. bool mLock = true;
  83. Condition mCond = null;
  84. IEnumerator mBody = null;
  85. }
  86.  
  87. /// <summary>
  88. /// A sequence contains several actions. It allow the nested action and join a certain action dynamically.
  89. /// </summary>
  90. public class Flow
  91. {
  92. public string UniqueFlowId = string.Empty;
  93.  
  94. public Flow(string name)
  95. {
  96. UniqueFlowId = name;
  97. mPendingJobs = new List<IEnumerator>();
  98. mRequestQuit = false;
  99. mRequestWait = false;
  100. mNestedStack = new Stack<ActionContext>();
  101. }
  102.  
  103. public void Stop()
  104. {
  105. mRequestQuit = true;
  106. }
  107.  
  108. public void Suspend(bool pause)
  109. {
  110. mRequestWait = pause;
  111. }
  112.  
  113. public Flow Join(IEnumerator body)
  114. {
  115. if (mNestedStack.Count <= 0)
  116. {
  117. // start sequence after the first action is added
  118. mNestedStack.Push(new ActionContext(body));
  119. Scheduler.StartUnityCoroutine(SequenceCorountine());
  120. }
  121. else
  122. {
  123. // put the action to the end of the current action
  124. Current.Spawns.Add(body);
  125. }
  126. return this;
  127. }
  128.  
  129. public Flow Fork(IEnumerator body)
  130. {
  131. if (mRequestFork != null)
  132. {
  133. Debug.LogError("Cannot fork recursively");
  134. }
  135. else
  136. {
  137. mRequestFork = body;
  138. }
  139.  
  140. return this;
  141. }
  142.  
  143. ActionContext Current
  144. {
  145. get { return mNestedStack.Peek(); }
  146. }
  147.  
  148. IEnumerator SequenceCorountine()
  149. {
  150. while (true)
  151. {
  152. if (mRequestQuit == true)
  153. {
  154. break;
  155. }
  156.  
  157. if (mRequestWait == true)
  158. {
  159. yield return null;
  160. }
  161. else
  162. if (!Current.Action.MoveNext())
  163. {
  164. // insert all sub-coroutine spawn in the current action orderly
  165. if (Current.Spawns.Count > 0)
  166. {
  167. mPendingJobs.InsertRange(0, Current.Spawns);
  168. Current.Spawns.Clear();
  169. }
  170.  
  171. // then leave this action
  172. mNestedStack.Pop();
  173.  
  174. // check if we have unfinished actions
  175. if (mPendingJobs.Count > 0)
  176. {
  177. // Debug.Log("Fork into a new sub coroutine.");
  178. mNestedStack.Push(new ActionContext(mPendingJobs[0]));
  179. mPendingJobs.RemoveAt(0);
  180. continue;
  181. }
  182. else
  183. if (mNestedStack.Count > 0)
  184. {
  185. continue;
  186. }
  187. else
  188. {
  189. break; // all action have been done!
  190. }
  191. }
  192. else
  193. if (mRequestFork != null)
  194. {
  195. // prepare to fork
  196. mNestedStack.Push(new ActionContext(mRequestFork));
  197. mRequestFork = null;
  198. continue;
  199. }
  200.  
  201. // some action may wait until some condition meet
  202. var peek = Current.Action.Current;
  203.  
  204. if (peek != Current.Action && peek is IEnumerator)
  205. {
  206. //Debug.Log("Fork into a new sub coroutine");
  207. mNestedStack.Push(new ActionContext(peek as IEnumerator));
  208. }
  209.  
  210. yield return peek;
  211. }
  212. }
  213.  
  214. IEnumerator mRequestFork = null;
  215. bool mRequestWait = true;
  216. bool mRequestQuit = true;
  217. Stack<ActionContext> mNestedStack = null;
  218. List<IEnumerator> mPendingJobs = null;
  219. }
  220.  
  221. /// <summary>
  222. /// Sequence manager, used to append/remove sequence from app.
  223. /// </summary>
  224. public class Scheduler : MonoBehaviour
  225. {
  226. public static YieldCommand Noop
  227. {
  228. get { return noop; }
  229. }
  230.  
  231. static Scheduler self;
  232. static YieldCommand noop;
  233.  
  234. static Scheduler Self()
  235. {
  236. if (self == null)
  237. {
  238. self = new GameObject("Scheduler").AddComponent<Scheduler>();
  239. noop = new YieldCommand();
  240. }
  241. return self;
  242. }
  243.  
  244. Flow AppendFlow(string name)
  245. {
  246. mActiveFlows.Add(new Flow(name));
  247. return mActiveFlows[mActiveFlows.Count - 1];
  248. }
  249.  
  250. Flow RemoveFlow(string name)
  251. {
  252. for(int i = 0; i < mActiveFlows.Count; ++i)
  253. {
  254. var flow = mActiveFlows[i];
  255. if (flow.UniqueFlowId == name)
  256. {
  257. flow.Stop();
  258. mActiveFlows.RemoveAt(i);
  259. return flow;
  260. }
  261. }
  262. return null;
  263. }
  264.  
  265. public static Flow CreateFlow(string name)
  266. {
  267. return Self().AppendFlow(name);
  268. }
  269.  
  270. public static Flow DeleteFlow(string name)
  271. {
  272. return Self().RemoveFlow(name);
  273. }
  274.  
  275. public static void StartUnityCoroutine(IEnumerator coroutine)
  276. {
  277. Self().StartCoroutine(coroutine);
  278. }
  279.  
  280. public static void Quit()
  281. {
  282. Self ().StopAllCoroutines();
  283. }
  284.  
  285. List<Flow> mActiveFlows = new List<Flow>();
  286. }
  287. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement