/// <summary> /// Takes an Enumerable of a given type, and a function that converts /// T into a CommandDelegate, the executes them in parallel. /// </summary> /// <param name="collection">A collection of objects.</param> /// <param name="factory">The conversion method.</param> /// <param name="delay"> Each successive element in the collection is delayed by delay * index.</param> public static CommandDelegate ForEachParallelWithDelay <T>(this IEnumerable <T> collection, Func <T, CommandDelegate> factory, double delay) { CheckArgumentNonNull(collection, "collection"); CheckArgumentNonNull(factory, "factory"); CheckDurationGreaterThanZero(delay); var commands = new List <CommandDelegate>(); double totalDelay = 0f; foreach (var item in collection) { CommandDelegate output = factory(item); if (totalDelay > 0.0) { output = Cmd.Sequence( Cmd.WaitForSeconds(totalDelay), output ); } totalDelay += delay; commands.Add(output); } return(Cmd.Parallel(commands.ToArray())); }
public static void TestTiming() { CommandQueue queue = new CommandQueue(); const double FIRST_Command_DURATION = 4.5; const double SECOND_Command_DURATION = 1.0; const double WAIT_DURATION = 1.5; const int REPEAT_COUNT = 8640; double lastT = 0.0; // This test ensures that between alternating CommandDurations, // there is no accumulation of error in timing. We use a repeat // here to accentuate the error. queue.Enqueue( Cmd.Repeat(REPEAT_COUNT, Cmd.Sequence( Cmd.WaitForSeconds(WAIT_DURATION), Cmd.Do(() => lastT = 0.0), Cmd.Duration((t) => { Assert.IsTrue(t <= 1.0); Assert.IsTrue(lastT <= t); lastT = t; }, FIRST_Command_DURATION), Cmd.Do(() => lastT = 0.0), Cmd.Parallel( Cmd.Duration((t) => {}, SECOND_Command_DURATION / 2.0), // The following two Duration Cmd should finish in the same Update call. Cmd.Duration((t) => {}, SECOND_Command_DURATION - (DELTA_TIME_RATE / 2.0)), Cmd.Duration((t) => { Assert.IsTrue(t <= 1.0); Assert.IsTrue(lastT <= t); lastT = t; }, SECOND_Command_DURATION) ) ) ) ); double totalTime = 0.0; while (!queue.Update(DELTA_TIME_RATE)) { totalTime += DELTA_TIME_RATE; } const double EXPECTED_TIME = (FIRST_Command_DURATION + SECOND_Command_DURATION + WAIT_DURATION) * REPEAT_COUNT; Assert.AreEqual(totalTime, EXPECTED_TIME, DELTA_TIME_RATE, "Time delta accumulation too large."); }
public static IEnumerator <CommandDelegate> CoroutineOne(Ref <float> val, int depth, Ref <int> calledCount) { if (depth > 0) { ++calledCount.Value; yield return(Cmd.ChangeTo(val, 5.0f, 4.0f)); yield return(Cmd.WaitForSeconds(1.0f)); yield return(Cmd.ChangeBy(val, -4.0f, 4.0f)); yield return(null); // Wait for a single frame yield return(Cmd.Coroutine(() => CoroutineOne(val, depth - 1, calledCount))); } }
public static void TestOrdering() { CommandScheduler scheduler = new CommandScheduler(); int a = 0; scheduler.Add( Cmd.Sequence( Cmd.WaitForSeconds(1.0f), Cmd.Do(() => ++ a) ) ); int b = 0; scheduler.Add( Cmd.Sequence( Cmd.WaitForSeconds(1.0f), Cmd.Do(() => ++ b) ) ); scheduler.Add( Cmd.Sequence( Cmd.WaitForSeconds(1.5f), Cmd.Do(() => ++ b) ) ); Assert.AreEqual(a, 0); Assert.AreEqual(b, 0); scheduler.Update(1.0f); Assert.AreEqual(a, 1); Assert.AreEqual(b, 1); scheduler.Update(0.5f); Assert.AreEqual(a, 1); Assert.AreEqual(b, 2); }