Beispiel #1
0
        public void TestOnFinishedEventExecuted()
        {
            var myEvent = new Event();
            var counter = 0;

            IEnumerator <Wait> OnEvent()
            {
                counter++;
                yield return(new Wait(myEvent));
            }

            void SetCounterToUnreachableValue(ActiveCoroutine coroutine)
            {
                counter = -100;
            }

            var cr = CoroutineHandler.Start(OnEvent());

            CoroutineHandler.Tick(1);
            cr.OnFinished += SetCounterToUnreachableValue;
            for (var i = 0; i < 10; i++)
            {
                CoroutineHandler.RaiseEvent(myEvent);
            }
            Assert.AreEqual(-100, counter, "Incorrect counter value.");
        }
Beispiel #2
0
        public void DisplayCaption(string[] text, Action <GameImpl> afterDisplay = null)
        {
            IEnumerator <IWait> CaptionImpl()
            {
                foreach (var par in text)
                {
                    this.caption.RemoveChildren();
                    var lines      = par.Split("\n");
                    var paragraphs = new Paragraph[lines.Length];
                    for (var i = 0; i < lines.Length; i++)
                    {
                        paragraphs[i] = this.caption.AddChild(new Paragraph(Anchor.AutoCenter, 1, lines[i], true));
                    }

                    this.caption.DrawAlpha = 0;
                    while (this.caption.DrawAlpha < 1)
                    {
                        this.caption.DrawAlpha += 0.01F;
                        yield return(new WaitEvent(CoroutineEvents.Update));
                    }
                    yield return(new WaitSeconds(3));

                    while (this.caption.DrawAlpha > 0)
                    {
                        this.caption.DrawAlpha -= 0.01F;
                        yield return(new WaitEvent(CoroutineEvents.Update));
                    }
                    yield return(new WaitSeconds(1));
                }
                afterDisplay?.Invoke(this);
            }

            this.cutscene = CoroutineHandler.Start(CaptionImpl());
        }
Beispiel #3
0
        public void TestEventBasedCoroutine()
        {
            var counter = 0;
            var myEvent = new Event();

            IEnumerator <Wait> OnEventTriggered()
            {
                counter++;
                yield return(new Wait(myEvent));

                counter++;
            }

            var cr = CoroutineHandler.Start(OnEventTriggered());

            Assert.AreEqual(1, counter, "instruction before yield is not executed.");
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(myEvent);
            Assert.AreEqual(2, counter, "instruction after yield is not executed.");
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(myEvent);
            Assert.AreEqual(2, counter, "instruction after yield is not executed.");

            Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
            Assert.AreEqual(false, cr.WasCanceled, "Incorrect IsCanceled value.");
            Assert.AreEqual(cr.MoveNextCount, 2, "Incorrect MoveNextCount value.");
        }
Beispiel #4
0
        public static void Main()
        {
            var seconds = CoroutineHandler.Start(WaitSeconds(), "Awesome Waiting Coroutine");

            CoroutineHandler.Start(PrintEvery10Seconds(seconds));

            CoroutineHandler.Start(EmptyCoroutine());

            CoroutineHandler.InvokeLater(new Wait(5), () => {
                Console.WriteLine("Raising test event");
                CoroutineHandler.RaiseEvent(TestEvent);
            });
            CoroutineHandler.InvokeLater(new Wait(TestEvent), () => Console.WriteLine("Example event received"));

            CoroutineHandler.InvokeLater(new Wait(TestEvent), () => Console.WriteLine("I am invoked after 'Example event received'"), priority: -5);
            CoroutineHandler.InvokeLater(new Wait(TestEvent), () => Console.WriteLine("I am invoked before 'Example event received'"), priority: 2);

            var lastTime = DateTime.Now;

            while (true)
            {
                var currTime = DateTime.Now;
                CoroutineHandler.Tick(currTime - lastTime);
                lastTime = currTime;
                Thread.Sleep(1);
            }
        }
Beispiel #5
0
        private void OnActivated(Point pos)
        {
            foreach (var layer in this.Map.Tiles.TileLayers)
            {
                var tile = layer.GetTile(pos.X, pos.Y);
                if (tile.IsBlank)
                {
                    continue;
                }
                var tilesetTile = tile.GetTilesetTile(this.Map.Tiles);

                // switches
                if (tilesetTile.Properties.GetBool("Switch"))
                {
                    foreach (var other in this.Map.Tiles.TileLayers)
                    {
                        if (other.Properties.GetInt("ActivatorX") != pos.X || other.Properties.GetInt("ActivatorY") != pos.Y)
                        {
                            continue;
                        }
                        var activated = other.Properties.GetBool("Activated");
                        var co        = activated ? this.Map.RemoveLayerFromGround(other) : this.Map.AddLayerToGround(other);
                        this.activationCutscenes.Add(CoroutineHandler.Start(co));
                        other.Properties["Activated"] = (!activated).ToString();
                    }
                    var active = tilesetTile.Properties.GetInt("ActiveState");
                    if (active > 0)
                    {
                        this.Map.SetTile(pos.X, pos.Y, active, layer.Name);
                    }
                    MlemGame.LoadContent <SoundEffect>("Sounds/Button").Play();
                }
            }
        }
        public void TestTimerBasedCoroutine()
        {
            var counter = 0;

            IEnumerator <Wait> OnTimeTickCodeExecuted()
            {
                counter++;
                yield return(new Wait(0.1d));

                counter++;
            }

            var cr = CoroutineHandler.Start(OnTimeTickCodeExecuted());

            Assert.AreEqual(1, counter, "instruction before yield is not executed.");
            Assert.AreEqual(string.Empty, cr.Name, "Incorrect default name found");
            Assert.AreEqual(0, cr.Priority, "Default priority is not minimum");
            for (var i = 0; i < 5; i++)
            {
                CoroutineHandler.Tick(1);
            }
            Assert.AreEqual(2, counter, "instruction after yield is not executed.");
            Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
            Assert.AreEqual(false, cr.WasCanceled, "Incorrect IsCanceled value.");
            Assert.AreEqual(cr.MoveNextCount, 2, "Incorrect MoveNextCount value.");
        }
Beispiel #7
0
        public void Update(GameTime time)
        {
            if (this.currentMove != null && !this.currentMove.IsFinished)
            {
                return;
            }
            do
            {
                if (this.remainingRound.Count <= 0)
                {
                    this.PopulateRound();
                }

                this.currentEntity = this.remainingRound.Dequeue();
                if (this.currentEntity.IsDead)
                {
                    continue;
                }
                var turn = this.currentEntity.MakeTurn(this);
                if (turn == null)
                {
                    continue;
                }
                this.currentMove = CoroutineHandler.Start(turn.GetEnumerator());
                break;
            } while (true);
        }
Beispiel #8
0
        public void TestNestedRaiseEvent()
        {
            var event1            = new Event();
            var event2            = new Event();
            var event3            = new Event();
            var coroutineCreated  = new Event();
            var counterCoroutineA = 0;
            var counter           = 0;

            var infinite = CoroutineHandler.Start(OnCoroutineCreatedInfinite());

            CoroutineHandler.Start(OnEvent1());
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(event1);
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(event2);
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(event3);
            Assert.AreEqual(3, counter);
            Assert.AreEqual(2, counterCoroutineA);
            infinite.Cancel();

            IEnumerator <Wait> OnCoroutineCreatedInfinite()
            {
                while (true)
                {
                    yield return(new Wait(coroutineCreated));

                    counterCoroutineA++;
                }
            }

            IEnumerator <Wait> OnEvent1()
            {
                yield return(new Wait(event1));

                counter++;
                CoroutineHandler.Start(OnEvent2());
                CoroutineHandler.RaiseEvent(coroutineCreated);
            }

            IEnumerator <Wait> OnEvent2()
            {
                yield return(new Wait(event2));

                counter++;
                CoroutineHandler.Start(OnEvent3());
                CoroutineHandler.RaiseEvent(coroutineCreated);
            }

            IEnumerator <Wait> OnEvent3()
            {
                yield return(new Wait(event3));

                counter++;
            }
        }
Beispiel #9
0
    private IEnumerator Fade()
    {
        fadeHandler.Start();
        yield return(fadeHandler.coroutine);

        preloadCamera.enabled = false;
        rtCamera.enabled      = false;
        animator.enabled      = false;
    }
Beispiel #10
0
 public Example()
 {
     handler = new CoroutineHandler(this);
     // calling in the same thread
     handler.Start(ExampleCoroutine);
     // calling in another thread
     handler.StartThread(ExampleCoroutine);
     // calling in a task
     handler.StartThread(ExampleCoroutine);
 }
 private void SwitchMenu(MenuUI menuToHide, MenuUI menuToShow)
 {
     if (menuToShow == menuToHide)
     {
         return;                          /// don't reshow the same menu
     }
     // stops old routine, creates and starts new routine
     _transitionRoutine.Stop();
     _transitionRoutine.Start(SwitchMenuRoutine(menuToHide, menuToShow));
 }
Beispiel #12
0
        protected IEnumerable <IWait> Attack(Entity other)
        {
            CoroutineHandler.Start(other.ShowHealthBar(0.5F));
            foreach (var wait in this.MoveTo(other.VisualPosition))
            {
                yield return(wait);
            }
            other.OnAttacked(this);
            yield return(new WaitSeconds(0.1F));

            foreach (var wait in this.MoveTo(this.Position.ToVector2()))
            {
                yield return(wait);
            }
        }
Beispiel #13
0
        private void CloseMainMenu(Action <GameImpl> after = null)
        {
            this.mainMenu.IsHidden = true;

            IEnumerator <IWait> FadeMusic()
            {
                while (MediaPlayer.Volume > 0)
                {
                    MediaPlayer.Volume -= 0.007F;
                    yield return(new WaitEvent(CoroutineEvents.Update));
                }
                after?.Invoke(this);
            }

            CoroutineHandler.Start(FadeMusic());
        }
Beispiel #14
0
        public void TestInfiniteCoroutineNeverFinishesUnlessCanceled()
        {
            var myEvent      = new Event();
            var myOtherEvent = new Event();
            var counter      = 0;

            IEnumerator <Wait> OnEventTriggeredInfinite()
            {
                while (true)
                {
                    counter++;
                    yield return(new Wait(myEvent));
                }
            }

            void SetCounterToUnreachableValue(ActiveCoroutine coroutine)
            {
                counter = -100;
            }

            var cr = CoroutineHandler.Start(OnEventTriggeredInfinite());

            CoroutineHandler.Tick(1);
            cr.OnFinished += SetCounterToUnreachableValue;
            for (var i = 0; i < 50; i++)
            {
                CoroutineHandler.RaiseEvent(myOtherEvent);
            }

            for (var i = 0; i < 50; i++)
            {
                CoroutineHandler.RaiseEvent(myEvent);
            }

            Assert.AreEqual(51, counter, "Incorrect counter value.");
            Assert.AreEqual(false, cr.IsFinished, "Incorrect IsFinished value.");
            Assert.AreEqual(false, cr.WasCanceled, "Incorrect IsCanceled value.");
            Assert.AreEqual(51, cr.MoveNextCount, "Incorrect MoveNextCount value.");

            cr.Cancel();
            Assert.AreEqual(true, cr.WasCanceled, "Incorrect IsCanceled value after canceling.");
            Assert.AreEqual(-100, counter, "OnFinished event not triggered when canceled.");
            Assert.AreEqual(51, cr.MoveNextCount, "Incorrect MoveNextCount value.");
            Assert.AreEqual(true, cr.IsFinished, "Incorrect IsFinished value.");
        }
Beispiel #15
0
        public void MovingCoroutineTest()
        {
            var evt = new Event();

            IEnumerator <Wait> MovingCoroutine()
            {
                while (true)
                {
                    yield return(new Wait(evt));

                    yield return(new Wait(0d));
                }
            }

            var moving = CoroutineHandler.Start(MovingCoroutine(), "MovingCoroutine");

            CoroutineHandler.RaiseEvent(evt);
            CoroutineHandler.RaiseEvent(evt);
            CoroutineHandler.RaiseEvent(evt);
            CoroutineHandler.RaiseEvent(evt);

            CoroutineHandler.Tick(1d);
            CoroutineHandler.Tick(1d);
            CoroutineHandler.Tick(1d);
            CoroutineHandler.Tick(1d);

            CoroutineHandler.RaiseEvent(evt);
            CoroutineHandler.Tick(1d);
            CoroutineHandler.RaiseEvent(evt);
            CoroutineHandler.Tick(1d);
            CoroutineHandler.RaiseEvent(evt);
            CoroutineHandler.Tick(1d);

            CoroutineHandler.Tick(1d);
            CoroutineHandler.RaiseEvent(evt);
            CoroutineHandler.Tick(1d);
            CoroutineHandler.RaiseEvent(evt);
            CoroutineHandler.Tick(1d);
            CoroutineHandler.RaiseEvent(evt);

            moving.Cancel();
        }
Beispiel #16
0
        public void Fade(float speed, Action <GameImpl> afterFade = null)
        {
            IEnumerator <IWait> FadeImpl()
            {
                var fadingIn = this.fade.DrawAlpha >= 0.5F;

                if (fadingIn)
                {
                    speed *= -1;
                }
                while (fadingIn ? this.fade.DrawAlpha > 0 : this.fade.DrawAlpha < 1)
                {
                    this.fade.DrawAlpha += speed;
                    yield return(new WaitEvent(CoroutineEvents.Update));
                }
                afterFade?.Invoke(this);
            }

            this.cutscene = CoroutineHandler.Start(FadeImpl());
        }
Beispiel #17
0
        private static IEnumerator <Wait> WaitSeconds()
        {
            Console.WriteLine("First thing " + DateTime.Now);
            yield return(new Wait(1));

            Console.WriteLine("After 1 second " + DateTime.Now);
            yield return(new Wait(9));

            Console.WriteLine("After 10 seconds " + DateTime.Now);
            CoroutineHandler.Start(NestedCoroutine());
            yield return(new Wait(5));

            Console.WriteLine("After 5 more seconds " + DateTime.Now);
            yield return(new Wait(10));

            Console.WriteLine("After 10 more seconds " + DateTime.Now);

            yield return(new Wait(20));

            Console.WriteLine("First coroutine done");
        }
        public void TestCoroutineReturningWeirdYields()
        {
            var counter = 0;

            IEnumerator <Wait> OnTimeTickNeverReturnYield()
            {
                counter++; // 1
                // condition that's expected to be false
                if (counter == 100)
                {
                    yield return(new Wait(0.1d));
                }
                counter++; // 2
            }

            IEnumerator <Wait> OnTimeTickYieldBreak()
            {
                counter++; // 3
                yield break;
            }

            var cr = new ActiveCoroutine[2];

            cr[0] = CoroutineHandler.Start(OnTimeTickNeverReturnYield());
            cr[1] = CoroutineHandler.Start(OnTimeTickYieldBreak());
            for (var i = 0; i < 5; i++)
            {
                CoroutineHandler.Tick(1);
            }

            Assert.AreEqual(3, counter, "Incorrect counter value.");
            for (var i = 0; i < cr.Length; i++)
            {
                Assert.AreEqual(true, cr[i].IsFinished, $"Incorrect IsFinished value on index {i}.");
                Assert.AreEqual(false, cr[i].WasCanceled, $"Incorrect IsCanceled value on index {i}");
                Assert.AreEqual(1, cr[i].MoveNextCount, $"Incorrect MoveNextCount value on index {i}");
            }
        }
Beispiel #19
0
        public void OnWalkedOnto(Point pos)
        {
            var stuck = Direction2Helper.Adjacent.All(dir => {
                var offset = pos + dir.Offset();
                var tile   = this.Map.GetTile(offset.X, offset.Y);
                return(tile.IsBlank || !tile.GetTilesetTile(this.Map.Tiles).Properties.GetBool("Walkable"));
            });

            if (stuck)
            {
                CoroutineHandler.Start(GameImpl.Instance.DisplayTrigger("R to restart"));
            }

            foreach (var obj in this.Map.Tiles.GetObjects("Trigger", false, true))
            {
                if (obj.Properties.GetBool("Triggered"))
                {
                    continue;
                }
                if (!obj.GetArea(this.Map.Tiles).Contains(pos.ToVector2() + new Vector2(0.5F)))
                {
                    continue;
                }
                var content = obj.Properties.Get("Content");
                CoroutineHandler.Start(GameImpl.Instance.DisplayTrigger(content));
                obj.Properties.Add("Triggered", true.ToString());
                break;
            }

            foreach (var layer in this.Map.Tiles.TileLayers)
            {
                var tile = layer.GetTile(pos.X, pos.Y);
                if (tile.IsBlank)
                {
                    continue;
                }
                var tilesetTile = tile.GetTilesetTile(this.Map.Tiles);

                // buttons
                if (tilesetTile.Properties.GetBool("Activator"))
                {
                    foreach (var other in this.Map.Tiles.TileLayers)
                    {
                        if (other.Properties.GetBool("Activated"))
                        {
                            continue;
                        }
                        if (other.Properties.GetInt("ActivatorX") != pos.X || other.Properties.GetInt("ActivatorY") != pos.Y)
                        {
                            continue;
                        }
                        CoroutineHandler.Start(this.Map.AddLayerToGround(other));
                        other.Properties["Activated"] = true.ToString();
                        break;
                    }
                    var active = tilesetTile.Properties.GetInt("ActiveState");
                    if (active > 0)
                    {
                        this.Map.SetTile(pos.X, pos.Y, active, layer.Name);
                    }
                    MlemGame.LoadContent <SoundEffect>("Sounds/Button").Play();
                    continue;
                }

                // bed
                if (tilesetTile.Properties.GetBool("Goal"))
                {
                    this.Direction = Direction2.Down;
                    var nextLevel = Array.IndexOf(GameImpl.Levels, this.Map.Name) + 1;
                    GameImpl.Instance.Fade(0.005F, g => {
                        if (GameImpl.Levels.Length > nextLevel)
                        {
                            g.StartMap(GameImpl.Levels[nextLevel], g2 => g2.Fade(0.01F));
                        }
                        else
                        {
                            g.DisplayCaption(new[] {
                                "At last,\nI'm not panicking anymore.",
                                "I know it'll come back eventually,\nbut for now, I'm free."
                            }, g2 => g2.DisplayCaption(new[] {
                                "Thanks for playing this game.",
                                "If you're ever feeling depressed,\nplease reach out to someone."
                            }, g3 => {
                                g3.SetMap(null);
                                GameImpl.Save(null);
                                g3.OpenMainMenu();
                                g3.Fade(0.01F);
                            }));
                        }
                    });
                    MlemGame.LoadContent <SoundEffect>("Sounds/Bed").Play();
                    continue;
                }

                // step grid tiles
                var steppedOnOff = tile.GlobalIdentifier == 7;
                if (steppedOnOff || tile.GlobalIdentifier == 8)
                {
                    var grid = this.Map.Tiles.TileLayers.First(t => t.Properties.GetBool("StepGrid") && !t.GetTile(pos.X, pos.Y).IsBlank);
                    if (grid != layer)
                    {
                        var missing = grid.Tiles.Count(t => !t.IsBlank && this.Map.GetTile(t.X, t.Y).GlobalIdentifier != 8);
                        // only change tiles if the grid isn't complete
                        if (missing > 0)
                        {
                            // if we stepped on a disabled tile, turn it on
                            if (steppedOnOff)
                            {
                                this.Map.SetTile(pos.X, pos.Y, 8);
                            }
                            else
                            {
                                // otherwise, turn the whole grid off
                                foreach (var t in grid.Tiles.Where(t => !t.IsBlank))
                                {
                                    this.Map.SetTile(t.X, t.Y, (int)t.GlobalTileIdentifierWithFlags);
                                }
                            }
                        }
                        // if there's only one missing and we just switched on, we're done
                        if (missing == 1 && steppedOnOff)
                        {
                            foreach (var other in this.Map.Tiles.TileLayers)
                            {
                                if (other.Properties.Get("ActivatorGrid") != grid.Name)
                                {
                                    continue;
                                }
                                CoroutineHandler.Start(this.Map.AddLayerToGround(other));
                                other.Properties["Activated"] = true.ToString();
                                MlemGame.LoadContent <SoundEffect>("Sounds/Button").Play();
                                break;
                            }
                        }
                    }
                }
            }
        }
Beispiel #20
0
 public void StartCountDown(float seconds, System.Action on_complete)
 {
     CoroutineHandler.Start(CountDown(seconds, on_complete));
 }
Beispiel #21
0
        public void TestPriority()
        {
            var myEvent = new Event();
            var counterShouldExecuteBefore0 = 0;

            IEnumerator <Wait> ShouldExecuteBefore0()
            {
                while (true)
                {
                    yield return(new Wait(myEvent));

                    counterShouldExecuteBefore0++;
                }
            }

            var counterShouldExecuteBefore1 = 0;

            IEnumerator <Wait> ShouldExecuteBefore1()
            {
                while (true)
                {
                    yield return(new Wait(myEvent));

                    counterShouldExecuteBefore1++;
                }
            }

            var counterShouldExecuteAfter = 0;

            IEnumerator <Wait> ShouldExecuteAfter()
            {
                while (true)
                {
                    yield return(new Wait(myEvent));

                    if (counterShouldExecuteBefore0 == 1 &&
                        counterShouldExecuteBefore1 == 1)
                    {
                        counterShouldExecuteAfter++;
                    }
                }
            }

            var counterShouldExecuteFinally = 0;

            IEnumerator <Wait> ShouldExecuteFinally()
            {
                while (true)
                {
                    yield return(new Wait(myEvent));

                    if (counterShouldExecuteAfter > 0)
                    {
                        counterShouldExecuteFinally++;
                    }
                }
            }

            const int highPriority = int.MaxValue;
            var       before1      = CoroutineHandler.Start(ShouldExecuteBefore1(), priority: highPriority);
            var       after        = CoroutineHandler.Start(ShouldExecuteAfter());
            var       before0      = CoroutineHandler.Start(ShouldExecuteBefore0(), priority: highPriority);
            var       @finally     = CoroutineHandler.Start(ShouldExecuteFinally(), priority: -1);

            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(myEvent);
            Assert.AreEqual(1, counterShouldExecuteAfter, $"ShouldExecuteAfter counter  {counterShouldExecuteAfter} is invalid.");
            Assert.AreEqual(1, counterShouldExecuteFinally, $"ShouldExecuteFinally counter  {counterShouldExecuteFinally} is invalid.");

            before1.Cancel();
            after.Cancel();
            before0.Cancel();
            @finally.Cancel();
        }
Beispiel #22
0
        public void TestNestedCoroutine()
        {
            var onChildCreated       = new Event();
            var onParentCreated      = new Event();
            var myEvent              = new Event();
            var counterAlwaysRunning = 0;

            IEnumerator <Wait> AlwaysRunning()
            {
                while (true)
                {
                    yield return(new Wait(myEvent));

                    counterAlwaysRunning++;
                }
            }

            var counterChild = 0;

            IEnumerator <Wait> Child()
            {
                yield return(new Wait(myEvent));

                counterChild++;
            }

            var counterParent = 0;

            IEnumerator <Wait> Parent()
            {
                yield return(new Wait(myEvent));

                counterParent++;
                // OnFinish I will start child.
            }

            var counterGrandParent = 0;

            IEnumerator <Wait> GrandParent()
            {
                yield return(new Wait(myEvent));

                counterGrandParent++;
                // Nested corotuine starting.
                var p = CoroutineHandler.Start(Parent());

                CoroutineHandler.RaiseEvent(onParentCreated);
                // Nested corotuine starting in OnFinished.
                p.OnFinished += ac => {
                    CoroutineHandler.Start(Child());
                    CoroutineHandler.RaiseEvent(onChildCreated);
                };
            }

            var always = CoroutineHandler.Start(AlwaysRunning());

            CoroutineHandler.Start(GrandParent());
            Assert.AreEqual(0, counterAlwaysRunning, "Always running counter is invalid at event 0.");
            Assert.AreEqual(0, counterGrandParent, "Grand Parent counter is invalid at event 0.");
            Assert.AreEqual(0, counterParent, "Parent counter is invalid at event 0.");
            Assert.AreEqual(0, counterChild, "Child counter is invalid at event 0.");
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(myEvent);
            Assert.AreEqual(1, counterAlwaysRunning, "Always running counter is invalid at event 1.");
            Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at event 1.");
            Assert.AreEqual(0, counterParent, "Parent counter is invalid at event 1.");
            Assert.AreEqual(0, counterChild, "Child counter is invalid at event 1.");
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(myEvent);
            Assert.AreEqual(2, counterAlwaysRunning, "Always running counter is invalid at event 2.");
            Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at event 2.");
            Assert.AreEqual(1, counterParent, "Parent counter is invalid at event 2.");
            Assert.AreEqual(0, counterChild, "Child counter is invalid at event 2.");
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(myEvent);
            Assert.AreEqual(3, counterAlwaysRunning, "Always running counter is invalid at event 3.");
            Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at event 3.");
            Assert.AreEqual(1, counterParent, "Parent counter is invalid at event 3.");
            Assert.AreEqual(1, counterChild, "Child counter is invalid at event 3.");
            CoroutineHandler.Tick(1);
            CoroutineHandler.RaiseEvent(myEvent);
            Assert.AreEqual(4, counterAlwaysRunning, "Always running counter is invalid at event 4.");
            Assert.AreEqual(1, counterGrandParent, "Grand Parent counter is invalid at event 4.");
            Assert.AreEqual(1, counterParent, "Parent counter is invalid at event 4.");
            Assert.AreEqual(1, counterChild, "Child counter is invalid at event 4.");
            always.Cancel();
        }
 public SampleOverlay()
 {
     myRoutine1 = CoroutineHandler.Start(TickServiceAsync(), name: "MyRoutine-1");
     myRoutine2 = CoroutineHandler.Start(EventServiceAsync(), name: "MyRoutine-2");
 }
 static void Main()
 {
     CoroutineHandler.Start(UpdateOverlaySample2());
     CoroutineHandler.Start(SubmitRenderLogic());
     Overlay.RunInfiniteLoop();
 }