// Manages running active coroutines!
        private static void Runner()
        {
            // Tick all the coroutines we have stored
            for (int i = 0; i < coroutineStates.Count; i++)
            {
                TickState(coroutineStates[i]);
            }

            // if a coroutine was finished whilst we were ticking, clear it out now
            for (int i = 0; i < finishedThisUpdate.Count; i++)
            {
                coroutineStates.Remove(finishedThisUpdate[i]);

                if (uiCoroutineState == finishedThisUpdate[i])
                {
                    uiCoroutineState = null;
                    EditorUtility.ClearProgressBar();
                }
            }
            finishedThisUpdate.Clear();

            // stop the runner if were done.
            if (coroutineStates.Count == 0)
            {
                EditorApplication.update -= Runner;
            }
        }
 /// <summary>
 /// Start a coroutine and display a progress UI. only one EditorCoroutine can display a UI at once. equivilent of calling StartCoroutine on a mono behaviour
 /// </summary>
 /// <param name="coroutine">coroutine to run</param>
 /// <param name="title">Text to show in the UIs title bar</param>
 /// <param name="isCancelable">Displays a cancel button if true</param>
 public static EditorCoroutine StartCoroutineWithUI(IEnumerator coroutine, string title, bool isCancelable = false)
 {
     if (uiCoroutineState != null)
     {
         Debug.LogError("EditorCoroutineRunner only supports running one coroutine that draws a GUI! [" + title + "]");
         return(null);
     }
     EditorCoroutineRunner.uiCoroutineState = new EditorCoroutineState(coroutine, title, isCancelable);
     return(StoreCoroutine(uiCoroutineState));
 }
        // Creates objects to manage the coroutines lifecycle and stores them away to be processed
        private static EditorCoroutine StoreCoroutine(EditorCoroutineState state)
        {
            if (coroutineStates == null)
            {
                coroutineStates    = new List <EditorCoroutineState>();
                finishedThisUpdate = new List <EditorCoroutineState>();
            }

            if (coroutineStates.Count == 0)
            {
                EditorApplication.update += Runner;
            }

            coroutineStates.Add(state);

            return(state.editorCoroutineYieldInstruction);
        }
        public static void KillCoroutine(ref EditorCoroutine coroutine)
        {
            if (uiCoroutineState.editorCoroutineYieldInstruction == coroutine)
            {
                uiCoroutineState = null;
                coroutine        = null;
                EditorUtility.ClearProgressBar();
                return;
            }
            if (KillCoroutine(ref coroutine, ref coroutineStates))
            {
                return;
            }

            if (KillCoroutine(ref coroutine, ref finishedThisUpdate))
            {
                return;
            }
        }
        private static void TickState(EditorCoroutineState state)
        {
            if (state.IsValid)
            {
                // This coroutine is still valid, give it a chance to tick!
                state.Tick();

                // if this coroutine is the active UI coroutine, give it a chance to update the UI
                if (state.showUI && uiCoroutineState == state)
                {
                    uiCoroutineState.UpdateUI();
                }
            }
            else
            {
                // We have finished running the coroutine, lets scrap it
                finishedThisUpdate.Add(state);
            }
        }