private IEnumerator WaitForNestedCoroutinesDepthOne()
        {
            yield return(new WaitForSeconds(2f));

            Debug.Log("EditorCoroutine Demo. Nested routine depth 1. Waiting for nested coroutines to finish now.");
            yield return(EditorCoroutineService.StartCoroutine(WaitForNestedCoroutinesDepthTwo()));
        }
 private void Button_4()
 {
     if (loopEveryTwoSecondsHandle != null)
     {
         EditorCoroutineService.StopCoroutine(loopEveryTwoSecondsHandle);
     }
 }
        public IEnumerator StopAllCoroutines_SpecificOwnerArg_StopsAllCoroutinesCorrectly()
        {
            OwnerOfRoutine ownerA        = new OwnerOfRoutine();
            RefBool        wasCancelledA = new RefBool();
            RefBool        wasCancelledB = new RefBool();

            // Test coroutines will be stopped. Check in 1 second for expected results. Test coroutines should finish by then, successfully or not.
            DateTime     then          = DateTime.Now;
            const double secondsToWait = 1;

            TestContext.WriteLine("Starting SimpleIteratorToBeStoppedB and ownerA.SimpleIteratorToBeStoppedA routines.\nWill automatically attempt to stop routines belonging to ownerA after a frame.");
            // All the following coroutines will be attempted to be cancelled after 1 frame, in the line after the following `yield return null`.
            EditorCoroutineService.StartCoroutine(ownerA, "SimpleIteratorToBeStoppedA", new object[] { wasCancelledA });
            EditorCoroutineService.StartCoroutine(SimpleIteratorToBeStoppedB(wasCancelledB));
            yield return(null);

            EditorCoroutineService.StopAllCoroutines(ownerA);

            double deltaSeconds = (DateTime.Now - then).TotalSeconds;

            while (deltaSeconds < secondsToWait)
            {
                yield return(null);

                deltaSeconds = (DateTime.Now - then).TotalSeconds;
            }

            Assert.IsTrue(wasCancelledA.Value && !wasCancelledB.Value, "EditorCoroutines belonging to a specific owner were not stopped correctly.");
        }
        private void OnGUI()
        {
            if (GUILayout.Button("Wait for two seconds"))
            {
                _loopEveryTwoSecondsHandle = EditorCoroutineService.StartCoroutine(WaitForTwoSeconds());
            }

            if (GUILayout.Button("Wait for 20 frames"))
            {
                EditorCoroutineService.StartCoroutine(WaitForTwentyFrames());
            }

            if (GUILayout.Button("Wait for UnityWebRequest"))
            {
                EditorCoroutineService.StartCoroutine(WaitForUnityWebRequest());
            }

            if (GUILayout.Button("Wait for nested coroutines"))
            {
                EditorCoroutineService.StartCoroutine(WaitForNestedCoroutines());
            }

            if (GUILayout.Button("Stop 'Wait for two seconds' coroutine"))
            {
                if (_loopEveryTwoSecondsHandle != null)
                {
                    EditorCoroutineService.StopCoroutine(_loopEveryTwoSecondsHandle);
                }
            }

            if (GUILayout.Button("Stop all"))
            {
                EditorCoroutineService.StopAllCoroutines();
            }
        }
    private IEnumerator WaitForNestedCoroutinesDepthOne()
    {
        yield return(new WaitForSeconds(2f));

        CustomLog("嵌套一层协程");
        yield return(EditorCoroutineService.StartCoroutine(WaitForNestedCoroutinesDepthTwo()));
    }
        public IEnumerator StartCoroutine_IEnumeratorArg_StartsCorrectly()
        {
            RefBool isTestComplete = new RefBool();

            EditorCoroutineService.StartCoroutine(SimpleIterator(isTestComplete));
            yield return(null);

            Assert.IsTrue(isTestComplete.Value, "EditorCoroutine was not started correctly via IEnumerator arg.");
        }
    private IEnumerator WaitForNestedCoroutines()
    {
        while (true)
        {
            yield return(new WaitForSeconds(2f));

            CustomLog("2秒进入另一个嵌套协程.");
            yield return(EditorCoroutineService.StartCoroutine(WaitForNestedCoroutinesDepthOne()));
        }
    }
        private IEnumerator WaitForNestedCoroutines()
        {
            while (true)
            {
                yield return(new WaitForSeconds(2f));

                Debug.Log("EditorCoroutine Demo. Parent coroutine. Logging again after nested coroutines finish + 2 seconds...");
                yield return(EditorCoroutineService.StartCoroutine(WaitForNestedCoroutinesDepthOne()));
            }
        }
        public IEnumerator StartCoroutine_MethodNameArg_StartsCorrectly()
        {
            RefBool      isTestComplete = new RefBool();
            object       owner          = this;
            const string methodName     = "SimpleIterator";

            EditorCoroutineService.StartCoroutine(owner, methodName, new object[] { isTestComplete });
            yield return(null);

            Assert.IsTrue(isTestComplete.Value, $"EditorCoroutine was not started correctly via method name {methodName}.");
        }
        private IEnumerator ReturnAfterCustomYieldInstructionSucceeds(RefBool isTestComplete)
        {
            TestContext.WriteLine("In ReturnAfterCustomYieldInstructionSucceeds routine. Starting.");
            EditorCoroutineService.StartCoroutine(SetIndexAfterSeconds(2f));
            yield return(new CustomWaitWhile(IsIndexStillZero));

            TestContext.WriteLine("In ReturnAfterCustomYieldInstructionSucceeds routine. Finished.");
            isTestComplete.Value = true;

            bool IsIndexStillZero()
            {
                return(_customIndex == 0);
            }
        }
        public IEnumerator StartCoroutine_CustomYieldInstruction_ReturnsCorrectly()
        {
            RefBool isTestComplete = new RefBool();

            _customIndex = 0;

            EditorCoroutineService.StartCoroutine(ReturnAfterCustomYieldInstructionSucceeds(isTestComplete));
            while (!isTestComplete.Value)
            {
                yield return(null);
            }

            Assert.AreEqual(1, _customIndex, "EditorCoroutine yielding on a CustomYieldInstruction was not returned correctly.");
        }
        public IEnumerator StartCoroutine_IndependentCoroutinesInParallel_ReturnInCorrectOrder()
        {
            RefBool isTestComplete = new RefBool();

            _parallelRoutinesTracker = new Queue <char> ();

            EditorCoroutineService.StartCoroutine(ReturnAfterRoutinesRunInParallel(isTestComplete));
            while (!isTestComplete.Value)
            {
                yield return(null);
            }

            Assert.AreEqual(0, _parallelRoutinesTracker.Count, "EditorCoroutines started in parallel were not run in the correct order.");
        }
        private IEnumerator ReturnAfterRoutinesRunInParallel(RefBool isTestComplete)
        {
            const float secondsToWaitInEachRoutine = 2f;
            const float secondRoutineStartDelay    = 0.5f;

            TestContext.WriteLine("In ReturnAfterRoutinesRunInParallel routine. Starting.");
            _parallelRoutinesTracker.Enqueue('a');
            EditorCoroutineService.StartCoroutine(ReturnAfterSecondsA(secondsToWaitInEachRoutine));
            TestContext.WriteLine($"In ReturnAfterRoutinesRunInParallel routine. Waiting for {secondRoutineStartDelay} seconds.");
            yield return(new WaitForSeconds(secondRoutineStartDelay));

            _parallelRoutinesTracker.Enqueue('b');
            EditorCoroutineService.StartCoroutine(ReturnAfterSecondsB(secondsToWaitInEachRoutine, isTestComplete));
            TestContext.WriteLine("In ReturnAfterRoutinesRunInParallel routine. Finished, though an EditorCoroutine started in parallel may still be running.");
        }
        public IEnumerator StartCoroutine_YieldWaitForAsyncOperation_ReturnsCorrectly()
        {
            RefBool isTestComplete = new RefBool();

            _webRequestData = null;
            const string uri = "http://httpbin.org/get";

            EditorCoroutineService.StartCoroutine(ReturnAfterWebRequest(uri, isTestComplete));
            while (!isTestComplete.Value)
            {
                yield return(null);
            }

            Assert.IsNotNull(_webRequestData,
                             $"WebRequest EditorCoroutine did not return any data.\nThis may be an issue with the URI {uri} itself, but for now, this test has failed.");
        }
        public IEnumerator StartCoroutine_YieldWaitForNestedCoroutines_ReturnsInCorrectOrder()
        {
            RefBool isTestComplete = new RefBool();

            _nestedRoutinesTracker = new Stack <int> ();
            for (int i = 0; i < 3; i++)
            {
                _nestedRoutinesTracker.Push(i);
            }

            EditorCoroutineService.StartCoroutine(ReturnAfterNestedRoutines(isTestComplete));
            while (!isTestComplete.Value)
            {
                yield return(null);
            }

            Assert.AreEqual(0, _nestedRoutinesTracker.Count, "Nested EditorCoroutines were not run in the correct order.");
        }
        public IEnumerator StartCoroutine_YieldWaitForSeconds_SuccessAfterSeconds()
        {
            RefBool     isTestComplete = new RefBool();
            DateTime    then           = DateTime.Now;
            const float secondsToWait  = 2f;

            EditorCoroutineService.StartCoroutine(ReturnAfterSeconds(secondsToWait, isTestComplete));
            while (!isTestComplete.Value)
            {
                yield return(null);
            }

            double deltaSeconds = (DateTime.Now - then).TotalSeconds;

            Assert.AreEqual(secondsToWait,
                            deltaSeconds,
                            0.024,  // A little over a single frame margin of error at 60 fps, which Unity Editor _definitely_ runs at. /s
                            $"WaitForSeconds EditorCoroutine returned in {deltaSeconds}, when expected to return in {secondsToWait} seconds.");
        }
        private IEnumerator ReturnAfterNestedRoutinesDepthOne()
        {
            const float secondsToWait = 1f;

            TestContext.WriteLine("In nested routine depth one. Starting.");
            yield return(new WaitForSeconds(secondsToWait));

            yield return(EditorCoroutineService.StartCoroutine(ReturnAfterNestedRoutinesDepthTwo()));

            if (_nestedRoutinesTracker.Count == 2)
            {
                _nestedRoutinesTracker.Pop();
            }
            else
            {
                throw new Exception("Nested routine depth one is run in wrong order.");
            }

            TestContext.WriteLine("In nested routine depth one. Finished.");
        }
        private IEnumerator ReturnAfterNestedRoutines(RefBool isTestComplete)
        {
            const float secondsToWait = 1f;

            TestContext.WriteLine("In parent routine. Starting.");
            yield return(new WaitForSeconds(secondsToWait));

            yield return(EditorCoroutineService.StartCoroutine(ReturnAfterNestedRoutinesDepthOne()));

            if (_nestedRoutinesTracker.Count == 1)
            {
                _nestedRoutinesTracker.Pop();
            }
            else
            {
                throw new Exception("Parent routine is run in wrong order.");
            }

            isTestComplete.Value = true;
            TestContext.WriteLine("In parent routine. Finished.");
        }
        public IEnumerator StopCoroutine_MethodName_StopsCorrectly()
        {
            RefBool isTestComplete = new RefBool();
            RefBool wasCancelled   = new RefBool();

            // Test coroutine will be stopped. Check in 1 second for expected results. Test coroutine should finish by then, successfully or not.
            EditorCoroutineService.StartCoroutine(ReturnAfterSecondsToBeStopped(1f, isTestComplete));

            TestContext.WriteLine("Starting SimpleIteratorToBeStopped routine.\nWill automatically attempt to stop it after a frame.");
            // This coroutine will be attempted to be cancelled after 1 frame, in the line after the following `yield return null`.
            EditorCoroutineService.StartCoroutine(this, "SimpleIteratorToBeStopped", new object[] { wasCancelled });
            yield return(null);

            EditorCoroutineService.StopCoroutine(this, "SimpleIteratorToBeStopped");

            while (!isTestComplete.Value)
            {
                yield return(null);
            }

            Assert.IsTrue(wasCancelled.Value, "EditorCoroutine was not stopped correctly via Method Name arg.");
        }
 private void Button_5()
 {
     EditorCoroutineService.StopAllCoroutines();
 }
 private void Button_3()
 {
     EditorCoroutineService.StartCoroutine(WaitForNestedCoroutines());
 }
 private void Button_2()
 {
     EditorCoroutineService.StartCoroutine(WaitForUnityWebRequest());
 }
 private void Button_1()
 {
     EditorCoroutineService.StartCoroutine(WaitForTwentyFrames());
 }
 private void Button_0()
 {
     loopEveryTwoSecondsHandle = EditorCoroutineService.StartCoroutine(WaitForTwoSeconds());
 }