4 using System.Collections.Generic;
6 using System.Threading;
22 private enum StatusValue
27 private readonly StatusValue value;
42 if (value == StatusValue.Failure)
44 DebugConsole.ThrowError(
"Coroutine \"" + handle.
Name +
"\" has failed");
46 return value != StatusValue.Running;
49 public override bool Equals(
object? obj)
56 return value.GetHashCode();
61 return value.ToString();
70 private readonly
bool ignorePause;
76 this.ignorePause = ignorePause;
82 if (ignorePause || !CoroutineManager.Paused)
109 Name =
string.IsNullOrWhiteSpace(name) ? (coroutine.ToString() ??
"") : name;
116 static class CoroutineManager
118 static readonly List<CoroutineHandle> Coroutines =
new List<CoroutineHandle>();
120 public static float DeltaTime {
get;
private set; }
122 public static bool Paused {
get;
private set; }
124 public static CoroutineHandle StartCoroutine(IEnumerable<CoroutineStatus> func,
string name =
"")
126 var handle =
new CoroutineHandle(func.GetEnumerator(), name);
129 Coroutines.Add(handle);
135 public static CoroutineHandle Invoke(Action action,
float delay = 0f)
137 return StartCoroutine(DoInvokeAfter(action, delay));
140 private static IEnumerable<CoroutineStatus> DoInvokeAfter(Action? action,
float delay)
144 yield
return CoroutineStatus.Failure;
150 yield
return new WaitForSeconds(delay);
155 yield
return CoroutineStatus.Success;
159 public static bool IsCoroutineRunning(
string name)
163 return Coroutines.Any(c => c.Name == name);
167 public static bool IsCoroutineRunning(CoroutineHandle handle)
171 return Coroutines.Contains(handle);
175 public static void StopCoroutines(
string name)
179 HandleCoroutineStopping(c => c.Name == name);
180 Coroutines.RemoveAll(c => c.Name == name);
184 public static void StopCoroutines(CoroutineHandle handle)
188 HandleCoroutineStopping(c => c == handle);
189 Coroutines.RemoveAll(c => c == handle);
193 private static void HandleCoroutineStopping(Func<CoroutineHandle, bool> filter)
196 foreach (CoroutineHandle coroutine
in Coroutines)
198 if (filter(coroutine))
200 coroutine.AbortRequested =
true;
205 private static bool PerformCoroutineStep(CoroutineHandle handle)
207 var current = handle.Coroutine.Current;
210 if (current.EndsCoroutine(handle) || handle.AbortRequested) {
return true; }
211 if (!current.CheckFinished(DeltaTime)) {
return false; }
213 if (!handle.Coroutine.MoveNext()) {
return true; }
217 private static bool IsDone(CoroutineHandle handle)
223 return PerformCoroutineStep(handle);
228 #if CLIENT && WINDOWS
229 if (e is SharpDX.SharpDXException) {
throw; }
231 DebugConsole.ThrowError(
"Coroutine " + handle.Name +
" threw an exception: " + e.Message +
"\n" + e.StackTrace.CleanupStackTrace());
232 handle.Exception = e;
238 private static readonly List<CoroutineHandle> coroutinePass =
new List<CoroutineHandle>();
239 public static void Update(
bool paused,
float deltaTime)
242 DeltaTime = deltaTime;
248 coroutinePass.AddRange(Coroutines);
250 foreach (var coroutine
in coroutinePass)
252 if (!IsDone(coroutine)) {
continue; }
255 Coroutines.Remove(coroutine);
258 coroutinePass.Clear();
261 public static void ListCoroutines()
265 DebugConsole.NewMessage(
"***********");
266 DebugConsole.NewMessage($
"{Coroutines.Count} coroutine(s)");
267 foreach (var c
in Coroutines)
269 DebugConsole.NewMessage($
"- {c.Name}");
readonly IEnumerator< CoroutineStatus > Coroutine
CoroutineHandle(IEnumerator< CoroutineStatus > coroutine, string name="")
abstract bool CheckFinished(float deltaTime)
static CoroutineStatus Running
static CoroutineStatus Failure
static CoroutineStatus Success
abstract bool EndsCoroutine(CoroutineHandle handle)
static new readonly EnumCoroutineStatus Running
override bool Equals(object? obj)
static new readonly EnumCoroutineStatus Failure
override bool CheckFinished(float deltaTime)
static new readonly EnumCoroutineStatus Success
override bool EndsCoroutine(CoroutineHandle handle)
override int GetHashCode()
override string ToString()
override bool EndsCoroutine(CoroutineHandle handle)
override bool CheckFinished(float deltaTime)
WaitForSeconds(float time, bool ignorePause=true)