/// <summary>Returns a routine that loads a scene with given name in given load mode and
        /// with given provider</summary>
        private IEnumerator LoadRoutine(string sceneName, LoadSceneMode mode, ITransitionProvider provider, Action onFinish = null)
        {
            AsyncOperation loadOperation = SceneManager.LoadSceneAsync(sceneName, mode);

            while (!loadOperation.isDone)
            {
                provider.OnProgressUpdated(mode == LoadSceneMode.Single ? loadOperation.progress : ((1.0f + loadOperation.progress) / 2.0f));
                yield return(null);
            }

            Scene sceneLoaded = SceneManager.GetSceneByName(sceneName);

            SceneManager.SetActiveScene(sceneLoaded);

            yield return(provider.Intro());

            TransitionCompleted?.Invoke(sceneLoaded, mode);
            onFinish?.Invoke();
        }
        public void PlayAsync()
        {
            ClientApi.Pause();
            ClientApi.SetSoundOn(false);
            Task.Run(async() =>
            {
                try
                {
                    IsPlaying        = true;
                    int waitAttempts = 10;
                    while (gui == null)                     //waiting for GUI
                    {
                        await Task.Delay(33);
                        waitAttempts--;
                        if (waitAttempts <= 0)
                        {
                            throw new Exception("No GUI Supplied");
                        }
                    }

                    DrawBackground(gui);
                    if (!transition.IsLoadCompleted)
                    {
                        CustomMainForm.Log("Transition isn't ready, preloading");
                        await transition.PreloadAsync();
                    }
                    waitAttempts = 10;
                    while (!IsROMReady && IsPlaying)
                    {
                        await Task.Delay(33);
                        waitAttempts--;
                        if (waitAttempts <= 0)
                        {
                            throw new Exception("ROM took too long to load");
                        }
                    }
                    await Task.Delay(33);
                    double deltaTime = 0;
                    DateTime n       = DateTime.Now;
                    InvokeOnMainThread?.Invoke(this, () =>
                    {
                        transition.Play();
                    });
                    for (double t = 0; t <= transition.Duration; t += deltaTime)
                    {
                        if (!IsPlaying)
                        {
                            return;
                        }
                        InvokeOnMainThread?.Invoke(this, () =>
                        {
                            ClearBackground(gui);
                            transition.DrawStart(gui);
                            try
                            {
                                transition.Draw(gui, t);
                            }
                            catch (Exception ex)
                            {
                                CustomMainForm.Log(ex.StackTrace);
                                CustomMainForm.Log(ex.Message);
                                CustomMainForm.Log("Draw Failed");
                            }
                            finally
                            {
                                transition.DrawEnd(gui);
                            }
                        });
                        await Task.Delay(33);
                        deltaTime = (DateTime.Now - n).TotalSeconds;
                        n         = DateTime.Now;
                    }
                }
                catch (Exception ex)
                {
                    CustomMainForm.Log(ex.StackTrace);
                    CustomMainForm.Log(ex.Message);
                }
                finally
                {
                    CustomMainForm.Log("Transition Complete");
                    ClientApi.Unpause();
                    ClientApi.SetSoundOn(true);
                    InvokeOnMainThread?.Invoke(this, () =>
                    {
                        transition.DrawClear(gui);
                        transition.Stop();
                        ClearBackground(gui);
                        ClearForeground(gui);
                    });
                    IsPlaying = false;
                    TransitionCompleted?.Invoke(this, null);
                }
            });
        }
 private void OnTransitionCompleted()
 {
     TransitionCompleted?.Invoke(this, EventArgs.Empty);
 }
 void OnTransitionCompleted(object sender, EventArgs e)
 {
     AbortTransition();
     TransitionCompleted?.Invoke(this, new RoutedEventArgs());
 }