using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace Coroutine { /// /// An object of this class can be used to start, tick and otherwise manage active s as well as their s. /// Note that a static implementation of this can be found in . /// public class CoroutineHandlerInstance { private readonly List tickingCoroutines = new List(); private readonly List eventCoroutines = new List(); private readonly Stopwatch stopwatch = new Stopwatch(); /// /// The amount of instances that are currently waiting for a tick (waiting for time to pass) /// public int TickingCount => this.tickingCoroutines.Count; /// /// The amount of instances that are currently waiting for an /// public int EventCount => this.eventCoroutines.Count; /// /// Starts the given coroutine, returning a object for management. /// Note that this calls to get the enumerator. /// /// The coroutine to start /// The name that this coroutine should have. Defaults to an empty string. /// An active coroutine object representing this coroutine public ActiveCoroutine Start(IEnumerable coroutine, string name = "") { return this.Start(coroutine.GetEnumerator(), name); } /// /// Starts the given coroutine, returning a object for management. /// /// The coroutine to start /// The name that this coroutine should have. Defaults to an empty string. /// An active coroutine object representing this coroutine public ActiveCoroutine Start(IEnumerator coroutine, string name = "") { var inst = new ActiveCoroutine(coroutine, name, this.stopwatch); if (inst.MoveNext()) { if (inst.IsWaitingForEvent()) { this.eventCoroutines.Add(inst); } else { this.tickingCoroutines.Add(inst); } } return inst; } /// /// Causes the given action to be invoked after the given . /// This is equivalent to a coroutine that waits for the given wait and then executes the given . /// /// The wait to wait for /// The action to execute after waiting /// An active coroutine object representing this coroutine public ActiveCoroutine InvokeLater(Wait wait, Action action) { return this.Start(InvokeLaterImpl(wait, action)); } /// /// Ticks this coroutine handler, causing all time-based s to be ticked. /// /// The amount of seconds that have passed since the last time this method was invoked public void Tick(double deltaSeconds) { for (var i = this.tickingCoroutines.Count - 1; i >= 0; i--) { var coroutine = this.tickingCoroutines[i]; if (coroutine.Tick(deltaSeconds)) { this.tickingCoroutines.RemoveAt(i); } else if (coroutine.IsWaitingForEvent()) { this.tickingCoroutines.RemoveAt(i); this.eventCoroutines.Add(coroutine); } } } /// /// Raises the given event, causing all event-based s to be updated. /// /// The event to raise public void RaiseEvent(Event evt) { for (var i = this.eventCoroutines.Count - 1; i >= 0; i--) { var coroutine = this.eventCoroutines[i]; if (coroutine.OnEvent(evt)) { this.eventCoroutines.RemoveAt(i); } else if (!coroutine.IsWaitingForEvent()) { this.eventCoroutines.RemoveAt(i); this.tickingCoroutines.Add(coroutine); } } } /// /// Returns a list of all currently active objects under this handler. /// /// All active coroutines public IEnumerable GetActiveCoroutines() { return this.tickingCoroutines.Concat(this.eventCoroutines); } private static IEnumerator InvokeLaterImpl(Wait wait, Action action) { yield return wait; action(); } } }