using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ZenFulcrum.EmbeddedBrowser { /// /// A class that wraps a pending promise with it's predicate and time data /// internal class PredicateWait { /// /// Predicate for resolving the promise /// public Func predicate; /// /// The time the promise was started /// public float timeStarted; /// /// The pending promise which is an interface for a promise that can be rejected or resolved. /// public IPendingPromise pendingPromise; /// /// The time data specific to this pending promise. Includes elapsed time and delta time. /// public TimeData timeData; } /// /// Time data specific to a particular pending promise. /// public struct TimeData { /// /// The amount of time that has elapsed since the pending promise started running /// public float elapsedTime; /// /// The amount of time since the last time the pending promise was updated. /// public float deltaTime; } public interface IPromiseTimer { /// /// Resolve the returned promise once the time has elapsed /// IPromise WaitFor(float seconds); /// /// Resolve the returned promise once the predicate evaluates to true /// IPromise WaitUntil(Func predicate); /// /// Resolve the returned promise once the predicate evaluates to false /// IPromise WaitWhile(Func predicate); /// /// Update all pending promises. Must be called for the promises to progress and resolve at all. /// void Update(float deltaTime); } public class PromiseTimer : IPromiseTimer { /// /// The current running total for time that this PromiseTimer has run for /// private float curTime; /// /// Currently pending promises /// private List waiting = new List(); /// /// Resolve the returned promise once the time has elapsed /// public IPromise WaitFor(float seconds) { return WaitUntil(t => t.elapsedTime >= seconds); } /// /// Resolve the returned promise once the predicate evaluates to false /// public IPromise WaitWhile(Func predicate) { return WaitUntil(t => !predicate(t)); } /// /// Resolve the returned promise once the predicate evalutes to true /// public IPromise WaitUntil(Func predicate) { var promise = new Promise(); var wait = new PredicateWait() { timeStarted = curTime, pendingPromise = promise, timeData = new TimeData(), predicate = predicate }; waiting.Add(wait); return promise; } /// /// Update all pending promises. Must be called for the promises to progress and resolve at all. /// public void Update(float deltaTime) { curTime += deltaTime; int i = 0; while (i < waiting.Count) { var wait = waiting[i]; var newElapsedTime = curTime - wait.timeStarted; wait.timeData.deltaTime = newElapsedTime - wait.timeData.elapsedTime; wait.timeData.elapsedTime = newElapsedTime; bool result; try { result = wait.predicate(wait.timeData); } catch (Exception ex) { wait.pendingPromise.Reject(ex); waiting.RemoveAt(i); continue; } if (result) { wait.pendingPromise.Resolve(); waiting.RemoveAt(i); } else { i++; } } } } }