Пример #1
0
        // @
        // LOOP


        /// <summary>
        /// Appends a callback loop (if duration is less than 0, the loop runs
        /// infinitely).
        /// </summary>
        private TeaTime Loop(float duration, Func <float> durationByFunc, Action <ttHandler> callback)
        {
            // Ignores appends on Immutable mode
            if (!_isImmutable)
            {
                ttTask newTask = new ttTask();
                newTask.isLoop              = true;
                newTask.time                = duration;
                newTask.timeByFunc          = durationByFunc;
                newTask.callbackWithHandler = callback;

                _tasks.Add(newTask);
            }


            // Autoplay if not paused or playing
            return(_isPaused || _isPlaying ? this : this.Play());
        }
Пример #2
0
        // @
        // ADD


        /// <summary>
        /// Appends a new ttTask.
        /// </summary>
        private TeaTime Add(float timeDelay, Func <float> timeDelayByFunc, Action callback, Action <ttHandler> callbackWithHandler)
        {
            // Ignores appends on Immutable mode
            if (!_isImmutable)
            {
                ttTask newTask = new ttTask();
                newTask.time                = timeDelay;
                newTask.timeByFunc          = timeDelayByFunc;
                newTask.callback            = callback;
                newTask.callbackWithHandler = callbackWithHandler;

                _tasks.Add(newTask);
            }


            // Autoplay if not paused or playing
            return(_isPaused || _isPlaying ? this : this.Play());
        }
Пример #3
0
        // @
        // THE COROUTINE


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


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

            _lastPlayExecutedCount = 0;

            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;


                // 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);


                // 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));
                    }


                    // 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;
                }


                // 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
                }


                // Just at the end of a complete queue execution
                if (_tasks.Count > 0 && _currentTask >= _tasks.Count)
                {
                    // A new cycle begins
                    _waiting.Clear();
                }
            }


            // Done!
            _isPlaying = false;


            yield return(null);
        }
Пример #4
0
		// ^
		// LOOP


		/// <summary>
		/// Appends a callback loop (if duration is less than 0,
		/// the loop runs infinitely).
		/// </summary>
		public TeaTime Loop(float duration, Action<ttHandler> callback)
		{
			// Ignores appends on Wait mode
			if (!_isWaiting)
			{
				ttTask newTask = new ttTask();
				newTask.isLoop = true;
				newTask.time = duration;
				newTask.callbackWithHandler = callback;

				_tasks.Add(newTask);
			}


			// Autoplay if not paused or playing
			return _isPaused || _isPlaying ? this : this.Play();
		}
Пример #5
0
		// ^
		// ADD


		/// <summary>
		/// Appends a new ttTask.
		/// </summary>
		private TeaTime Add(float timeDelay, YieldInstruction yi, Action callback, Action<ttHandler> callbackWithHandler)
		{
			// Ignores appends on Wait mode
			if (!_isWaiting)
			{
				ttTask newTask = new ttTask();
				newTask.time = timeDelay;
				newTask.yieldInstruction = yi;
				newTask.callback = callback;
				newTask.callbackWithHandler = callbackWithHandler;

				_tasks.Add(newTask);
			}


			// Autoplay if not paused or playing
			return _isPaused || _isPlaying ? this : this.Play();
		}