Пример #1
0
    /// <summary>
    /// Executes a callback inside an infinite loop until ttHandler.Break().
    /// </summary>
    private static IEnumerator ExecuteInfiniteLoop(MonoBehaviour instance, string queueName, Action <ttHandler> callback)
    {
        // #fix
        // Inmediate execution breaks the queue order with nested queues
        yield return(new WaitForEndOfFrame());

        ttHandler loopHandler = new ttHandler();


        // Run while active
        while (loopHandler.isActive)
        {
            // deltaTime
            float unityDeltaTime = Time.deltaTime;
            loopHandler.deltaTime       = unityDeltaTime;
            loopHandler.timeSinceStart += unityDeltaTime;


            // Pause
            while (IsPaused(instance, queueName))
            {
                yield return(null);
            }


            // Callback execution
            if (callback != null)
            {
                callback(loopHandler);
            }


            // Waits all the yields, once
            if (loopHandler.yieldsToWait != null)
            {
                foreach (YieldInstruction yi in loopHandler.yieldsToWait)
                {
                    yield return(yi);
                }

                loopHandler.yieldsToWait.Clear();
            }


            // Executes & waits all IEnumerators, once
            if (loopHandler.ienumsToWait != null)
            {
                foreach (IEnumerator ien in loopHandler.ienumsToWait)
                {
                    yield return(instance.StartCoroutine(ien));
                }

                loopHandler.ienumsToWait.Clear();
            }


            yield return(null);
        }
    }
Пример #2
0
    // THE COROUTINE

    /// This is the main algorithm. Executes all tasks, one after the
    /// other, calling their callbacks according to type, time and queue
    /// config.
    private IEnumerator ExecuteQueue()
    {
        _isPlaying = true;

        int reverseLastTask = -1; // Important: This value needs to be reset to default on most queue changes

        _lastPlayExecutedCount = 0;

        // :D!
        // Let's wait
        // 1 For secuencial Adds or Loops before their first execution
        // 2 Maybe a callback is trying to modify his own queue
        yield return(ttYield.EndOfFrame);

        while (_currentTask < _tasks.Count)
        {
            // Current task to be executed
            int taskId = _currentTask;
            if (_isReversed)
            {
                taskId = _tasks.Count - 1 - _currentTask;
            }
            ttTask currentTask = _tasks[taskId];

            // Next task (or previous if the queue is backward)
            _currentTask++;

            // Avoid executing a task twice when reversed and the queue
            // hasn't reached the end
            if (taskId == reverseLastTask)
            {
                continue;
            }
            reverseLastTask = taskId;

            // :D?
            // yield return ttYield.EndOfFrame;

            // It's a loop
            if (currentTask.isLoop)
            {
                // Holds the duration
                float loopDuration = currentTask.time;

                // Func<float> added
                if (currentTask.timeByFunc != null)
                {
                    loopDuration += currentTask.timeByFunc();
                }

                // Nothing to do, skip
                if (loopDuration == 0)
                {
                    continue;
                }

                // Loops will always need a handler
                ttHandler loopHandler = new ttHandler();
                loopHandler.self       = this;
                loopHandler.isLooping  = true;
                loopHandler.isReversed = _isReversed;

                // Negative time means the loop is infinite
                bool isInfinite = loopDuration < 0;

                // T quotient
                float tRate = isInfinite ? 0 : 1 / loopDuration;

                // Progresion depends on current direction
                if (loopHandler.isReversed)
                {
                    loopHandler.t = 1f;
                    tRate         = -tRate;
                }

                // While looping and, until time or infinite
                while (loopHandler.isLooping && (loopHandler.isReversed ? loopHandler.t >= 0 : loopHandler.t <= 1))
                {
                    // Check for queue reversal
                    if (_isReversed != loopHandler.isReversed)
                    {
                        tRate = -tRate;
                        loopHandler.isReversed = _isReversed;
                    }

                    float unityDeltaTime = Time.deltaTime;

                    // Completion % from 0 to 1
                    if (!isInfinite)
                    {
                        loopHandler.t += tRate * unityDeltaTime;
                    }

                    // On finite loops this .deltaTime is sincronized with
                    // the exact loop duration
                    loopHandler.deltaTime =
                        isInfinite ?
                        unityDeltaTime :
                        1 / (loopDuration - loopHandler.timeSinceStart) * unityDeltaTime;

                    // .deltaTime is also reversed
                    if (loopHandler.isReversed)
                    {
                        loopHandler.deltaTime = -loopHandler.deltaTime;
                    }

                    // A classic
                    loopHandler.timeSinceStart += unityDeltaTime;

                    // Pause?
                    while (_isPaused)
                    {
                        yield return(null);
                    }

                    // Loops will always have a callback with a handler
                    currentTask.callbackWithHandler(loopHandler);

                    // Handler .WaitFor(
                    if (loopHandler.yieldsToWait != null)
                    {
                        for (int i = 0, len = loopHandler.yieldsToWait.Count; i < len; i++)
                        {
                            yield return(loopHandler.yieldsToWait[i]);
                        }

                        loopHandler.yieldsToWait.Clear();
                    }

                    // Minimum sane delay
                    if (loopHandler.yieldsToWait == null)
                    {
                        yield return(null);
                    }
                }

                // Executed +1
                _executedCount         += 1;
                _lastPlayExecutedCount += 1;
            }
            // It's a timed callback
            else
            {
                // Holds the delay
                float delayDuration = currentTask.time;

                // Func<float> added
                if (currentTask.timeByFunc != null)
                {
                    delayDuration += currentTask.timeByFunc();
                }

                // // Time delay
                // if (delayDuration > 0)
                //     yield return ttYield.Seconds(delayDuration);

                // Is this more precise that the previous commented code?
                float time = 0;
                while (time < delayDuration)
                {
                    time += Time.deltaTime;
                    yield return(null);
                }

                // Pause?
                while (_isPaused)
                {
                    yield return(null);
                }

                // Normal callback
                if (currentTask.callback != null)
                {
                    currentTask.callback();
                }

                // Callback with handler
                if (currentTask.callbackWithHandler != null)
                {
                    ttHandler handler = new ttHandler();
                    handler.self = this;

                    handler.t = 1;
                    handler.timeSinceStart = delayDuration;
                    handler.deltaTime      = Time.deltaTime;

                    currentTask.callbackWithHandler(handler);

                    // Handler WaitFor
                    if (handler.yieldsToWait != null)
                    {
                        for (int i = 0, len = handler.yieldsToWait.Count; i < len; i++)
                        {
                            yield return(handler.yieldsToWait[i]);
                        }

                        handler.yieldsToWait.Clear();
                    }

                    // Minimum sane delay
                    if (delayDuration <= 0 && handler.yieldsToWait == null)
                    {
                        yield return(null);
                    }
                }
                else if (delayDuration <= 0)
                {
                    yield return(null);
                }

                // Executed +1
                _executedCount         += 1;
                _lastPlayExecutedCount += 1;
            }

            // Just at the end of a complete queue execution
            if (_tasks.Count > 0 && _currentTask >= _tasks.Count)
            {
                // Forget current nested queues
                _waiting.Clear();
            }

            // Consume mode removes the task after execution
            // #todo Need to be tested with .Reverse() stuff
            if (_isConsuming)
            {
                _currentTask -= 1;
                _tasks.Remove(currentTask);

                reverseLastTask = -1; // To default
            }

            // On Yoyo mode the queue is reversed at the end, only once per
            // play without Repeat mode
            if (_isYoyo && _currentTask >= _tasks.Count && (_lastPlayExecutedCount <= _tasks.Count || _isRepeating))
            {
                this.Reverse();

                reverseLastTask = -1; // To default
            }

            // Repeats on Repeat mode
            if (_isRepeating && _tasks.Count > 0 && _currentTask >= _tasks.Count)
            {
                _currentTask = 0;

                reverseLastTask = -1; // To default
            }
        }

        // Done!
        _isPlaying = false;

        yield return(null);
    }
Пример #3
0
    /// <summary>
    /// Executes a timed callback.
    /// </summary>
    private static IEnumerator ExecuteOnce(MonoBehaviour instance, string queueName,
                                           float timeToWait, YieldInstruction yieldToWait,
                                           Action callback, Action <ttHandler> callbackWithHandler)
    {
        // #fix
        // Inmediate execution breaks the queue order with nested queues
        if (timeToWait < Time.deltaTime && yieldToWait == null)
        {
            yield return(new WaitForEndOfFrame());
        }


        // Pause
        while (IsPaused(instance, queueName))
        {
            yield return(null);
        }


        // Wait for
        if (timeToWait > 0)
        {
            yield return(new WaitForSeconds(timeToWait));
        }

        if (yieldToWait != null)
        {
            yield return(yieldToWait);
        }


        // Executes the normal callback
        if (callback != null)
        {
            callback();
        }


        // Executes the callback with handler (and waits his yields / ienumerators)
        if (callbackWithHandler != null)
        {
            ttHandler t = new ttHandler();
            callbackWithHandler(t);


            // Waits all the handler yields
            if (t.yieldsToWait != null)
            {
                foreach (YieldInstruction yi in t.yieldsToWait)
                {
                    yield return(yi);
                }
            }


            // Executes and waits all the handler IEnumerators
            if (t.ienumsToWait != null)
            {
                foreach (IEnumerator ien in t.ienumsToWait)
                {
                    yield return(instance.StartCoroutine(ien));
                }
            }
        }


        yield return(null);
    }
Пример #4
0
    /// <summary>
    /// Executes a callback inside a loop for all his duration or until ttHandler.Break().
    /// </summary>
    private static IEnumerator ExecuteLoop(MonoBehaviour instance, string queueName,
                                           float duration,
                                           Action <ttHandler> callback)
    {
        // Only for positive values
        if (duration <= 0)
        {
            yield break;
        }


        // #fix
        // Inmediate execution breaks the queue order with nested queues
        yield return(new WaitForEndOfFrame());


        // Handler data
        ttHandler loopHandler = new ttHandler();
        float     tRate       = 1 / duration;


        // Run while active until duration
        while (loopHandler.isActive && loopHandler.t <= 1)
        {
            // deltaTime
            float unityDeltatime = Time.deltaTime;


            // Completion % from 0 to 1
            loopHandler.t += tRate * unityDeltatime;


            // Customized delta that represents the loop duration
            loopHandler.deltaTime       = 1 / (duration - loopHandler.timeSinceStart) * unityDeltatime;
            loopHandler.timeSinceStart += unityDeltatime;


            // Pause
            while (IsPaused(instance, queueName))
            {
                yield return(null);
            }


            // Callback execution
            if (callback != null)
            {
                callback(loopHandler);
            }


            // Waits all the yields, once
            if (loopHandler.yieldsToWait != null)
            {
                foreach (YieldInstruction yi in loopHandler.yieldsToWait)
                {
                    yield return(yi);
                }

                loopHandler.yieldsToWait.Clear();
            }


            // Executes and waits all IEnumerators, once
            if (loopHandler.ienumsToWait != null)
            {
                foreach (IEnumerator ien in loopHandler.ienumsToWait)
                {
                    yield return(instance.StartCoroutine(ien));
                }

                loopHandler.ienumsToWait.Clear();
            }


            yield return(null);
        }
    }