Example #1
0
    /// <summary>
    /// appends a Tween at the end of the current flow
    /// </summary>
    public GoTweenChain append( AbstractGoTween tween )
    {
        var item = new TweenFlowItem ( this.duration, tween );
        append( item );

        return this;
    }
Example #2
0
    /// <summary>
    /// the item being added already has a start time so no extra parameter is needed
    /// </summary>
    private void insert( TweenFlowItem item )
    {
        // early out for invalid items
        if( item.tween != null && !item.tween.isValid() )
            return;

        if( float.IsInfinity( item.duration ) )
        {
            Debug.Log( "adding a Tween with infinite iterations to a TweenFlow is not permitted" );
            return;
        }

        // ensure the tween isnt already live
        if( item.tween != null )
            Go.removeTween( item.tween );

        // add the item then sort based on startTimes
        // 		_tweenFlows.Add( item );
        // 		_tweenFlows.Sort( ( x, y ) =>
        // 		{
        // 			return x.startTime.CompareTo( y.startTime );
        // 		} );
        int insertionIndex = _tweenFlows.Count;
        while ( insertionIndex > 0 )
        {
            if ( item.startTime >= _tweenFlows[insertionIndex - 1].startTime )
                break;
            insertionIndex--;
        }
        _tweenFlows.Insert ( insertionIndex, item );

        duration = Mathf.Max( item.startTime + item.duration, duration );
        totalDuration = duration * iterations;
    }
Example #3
0
    /// <summary>
    /// adds a delay to the front of the flow
    /// </summary>
    public TweenChain prependDelay( float delay )
    {
        var item = new TweenFlowItem( 0, delay );
        prepend( item );

        return this;
    }
Example #4
0
    /// <summary>
    /// adds a Tween to the front of the flow
    /// </summary>
    public GoTweenChain prepend( AbstractGoTween tween )
    {
        var item = new TweenFlowItem( 0, tween );
        prepend( item );

        return this;
    }
Example #5
0
    /// <summary>
    /// appends a delegate to the end of the current flow
    /// </summary>
    public GoTweenChain appendAction( System.Action action, float delay = 0 )
    {
        var item = new TweenFlowItem ( this.duration + delay, action );
        append( item );

        return this;
    }
Example #6
0
    /// <summary>
    /// appends a delay to the end of the current flow
    /// </summary>
    public TweenChain appendDelay( float delay )
    {
        var item = new TweenFlowItem( duration, delay );
        append( item );

        return this;
    }
Example #7
0
	private void append( TweenFlowItem item )
	{
		// early out for invalid items
		if( item.tween != null && !item.tween.isValid() )
			return;
		
		if( float.IsInfinity( item.duration ) )
		{
			Debug.Log( "adding a Tween with infinite iterations to a TweenChain is not permitted" );
			return;
		}
		
		// ensure the tween isnt already live
		if( item.tween != null )
			Go.removeTween( item.tween );
		
		_tweenFlows.Add( item );
		
		// update the duration and total duration
		duration += item.duration;
		
		if( iterations > 0 )
			totalDuration = duration * iterations;
		else
			totalDuration = float.PositiveInfinity;
	}
Example #8
0
    /// <summary>
    /// inserts a Tween and sets it to start at the given startTime
    /// </summary>
    public GoTweenFlow insert( float startTime, AbstractGoTween tween )
    {
        var item = new TweenFlowItem( startTime, tween );
        insert( item );

        return this;
    }
Example #9
0
    /// <summary>
    /// inserts a delegate and sets it to start at the given startTime
    /// </summary>
    public GoTweenFlow insertAction( float startTime, System.Action action )
    {
        var item = new TweenFlowItem ( startTime, action );
        insert ( item );

        return this;
    }
Example #10
0
	private void prepend( TweenFlowItem item )
	{
		// early out for invalid items
		if( item.tween != null && !item.tween.isValid() )
			return;
		
		if( float.IsInfinity( item.duration ) )
		{
			Debug.Log( "adding a Tween with infinite iterations to a TweenChain is not permitted" );
			return;
		}
		
		// ensure the tween isnt already live
		if( item.tween != null )
			Go.removeTween( item.tween );
		
		// fix all the start times on our previous chains
		foreach( var ci in _tweenFlows )
			ci.startTime += item.duration;
		
		_tweenFlows.Add( item );
		
		// update the duration and total duration
		duration += item.duration;
		totalDuration = duration * iterations;
	}
Example #11
0
    /// <summary>
    /// the item being added already has a start time so no extra parameter is needed
    /// </summary>
    private void insert( TweenFlowItem item )
    {
        // early out for invalid items
        if( item.tween != null && !item.tween.isValid() )
            return;

        if( float.IsInfinity( item.duration ) )
        {
            Debug.Log( "adding a Tween with infinite iterations to a TweenFlow is not permitted" );
            return;
        }

        // ensure the tween isnt already live
        if( item.tween != null )
            Go.removeTween( item.tween );

        // add the item then sort based on startTimes
        _tweenFlows.Add( item );
        _tweenFlows.Sort( ( x, y ) =>
        {
            return x.startTime.CompareTo( y.startTime );
        } );

        duration = Mathf.Max( item.startTime + item.duration, duration );
        totalDuration = duration * iterations;
    }
Example #12
0
    /// <summary>
    /// appends a delay to the end of the current flow
    /// </summary>
    public GoTweenChain appendDelay( float delay )
    {
        if ( delay > 0 )
        {
            var item = new TweenFlowItem ( this.duration, delay );
            append ( item );
        }

        return this;
    }
Example #13
0
    /// <summary>
    /// inserts a delay and sets it to start at the given startTime
    /// </summary>
    public GoTweenFlow insertDelay( float startTime, float delay )
    {
        if ( delay > 0 )
        {
            var item = new TweenFlowItem ( startTime, delay );
            insert ( item );
        }

        return this;
    }
 private void changeTimeForFlowItem(TweenFlowItem flowItem, float time)
 {
     if (flowItem != null && flowItem.tween != null)
     {
         if (flowItem.tween.isReversed != (base.isReversed || _isLoopingBackOnPingPong))
         {
             flowItem.tween.reverse();
         }
         float time2 = Mathf.Clamp(time - flowItem.startTime, 0f, flowItem.endTime);
         if (flowItem.startTime <= time && flowItem.endTime >= time)
         {
             flowItem.tween.goToAndPlay(time2);
             return;
         }
         flowItem.tween.goTo(time2);
         flowItem.tween.pause();
     }
 }
    public override List <AbstractTweenProperty> allTweenProperties()
    {
        var propList = new List <AbstractTweenProperty>();

        for (int k = 0; k < _tweenFlows.Count; ++k)
        {
            TweenFlowItem flowItem = _tweenFlows[k];
            // skip delay items which have no tween
            if (flowItem.tween == null)
            {
                continue;
            }

            propList.AddRange(flowItem.tween.allTweenProperties());
        }

        return(propList);
    }
Example #16
0
	private void prepend( TweenFlowItem item )
	{
		// early out for invalid items
		if( item.tween != null && !item.tween.isValid() )
			return;
		
		if( float.IsInfinity( item.duration ) )
		{
			Debug.LogError( "adding a Tween with infinite iterations to a TweenChain is not permitted" );
			return;
		}

        if ( item.tween != null )
        {
            if ( item.tween.isReversed != isReversed )
            {
                Debug.LogError( "adding a Tween that doesn't match the isReversed property of the TweenChain is not permitted." );
                return;
            }

            // ensure the tween isnt already live
            Go.removeTween( item.tween );

            // ensure that the item is marked to play.
            item.tween.play();
        }
		
		// fix all the start times on our previous chains
		for ( int k = 0; k < _tweenFlows.Count; ++k )
		{
			TweenFlowItem flowItem = _tweenFlows[k];
			flowItem.startTime += item.duration;
		}

        _tweenFlows.Insert( 0, item );
		
		// update the duration and total duration
		duration += item.duration;

        if ( iterations < 0 )
            totalDuration = float.PositiveInfinity;
        else
            totalDuration = duration * iterations;
    }
    public override bool containsTweenProperty(AbstractTweenProperty property)
    {
        for (int k = 0; k < _tweenFlows.Count; ++k)
        {
            TweenFlowItem flowItem = _tweenFlows[k];
            // skip delay items which have no tween
            if (flowItem.tween == null)
            {
                continue;
            }

            if (flowItem.tween.containsTweenProperty(property))
            {
                return(true);
            }
        }

        return(false);
    }
Example #18
0
    private void append(TweenFlowItem item)
    {
        // early out for invalid items
        if (item.tween != null && !item.tween.isValid())
        {
            return;
        }

        if (float.IsInfinity(item.duration))
        {
            Debug.LogError("adding a Tween with infinite iterations to a TweenChain is not permitted");
            return;
        }

        if (item.tween != null)
        {
            if (item.tween.isReversed != isReversed)
            {
                Debug.LogError("adding a Tween that doesn't match the isReversed property of the TweenChain is not permitted.");
                return;
            }

            // ensure the tween isnt already live
            Go.removeTween(item.tween);

            // ensure that the item is marked to play.
            item.tween.play();
        }

        _tweenFlows.Add(item);

        // update the duration and total duration
        duration += item.duration;

        if (iterations < 0)
        {
            totalDuration = float.PositiveInfinity;
        }
        else
        {
            totalDuration = duration * iterations;
        }
    }
Example #19
0
    /// <summary>
    /// the item being added already has a start time so no extra parameter is needed
    /// </summary>
    private void insert(TweenFlowItem item)
    {
        // early out for invalid items
        if (item.tween != null && !item.tween.isValid())
        {
            return;
        }

        if (float.IsInfinity(item.duration))
        {
            Debug.Log("adding a Tween with infinite iterations to a TweenFlow is not permitted");
            return;
        }

        // ensure the tween isnt already live
        if (item.tween != null)
        {
            Go.removeTween(item.tween);
        }

        // add the item then sort based on startTimes
//      _tweenFlows.Add( item );
//      _tweenFlows.Sort( ( x, y ) =>
//      {
//          return x.startTime.CompareTo( y.startTime );
//      } );
        int insertionIndex = _tweenFlows.Count;

        while (insertionIndex > 0)
        {
            if (item.startTime >= _tweenFlows[insertionIndex - 1].startTime)
            {
                break;
            }
            insertionIndex--;
        }
        _tweenFlows.Insert(insertionIndex, item);


        duration      = Mathf.Max(item.startTime + item.duration, duration);
        totalDuration = duration * iterations;
    }
Example #20
0
	/// <summary>
	/// the item being added already has a start time so no extra parameter is needed
	/// </summary>
	private void insert( TweenFlowItem item )
	{
		// early out for invalid items
		if( item.tween != null && !item.tween.isValid() )
			return;
		
		if( float.IsInfinity( item.duration ) )
		{
			Debug.LogError( "adding a Tween with infinite iterations to a TweenFlow is not permitted" );
			return;
		}
		
		if( item.tween != null )
        {
            if (item.tween.isReversed != isReversed)
            {
                Debug.LogError( "adding a Tween that doesn't match the isReversed property of the TweenFlow is not permitted." );
                return;
            }

            // ensure the tween isnt already live
            Go.removeTween(item.tween);

            // ensure that the item is marked to play.
            item.tween.play();
        }

		// add the item then sort based on startTimes
		_tweenFlows.Add( item );
		_tweenFlows.Sort( ( x, y ) =>
		{
			return x.startTime.CompareTo( y.startTime );
		} );
		
		duration = Mathf.Max( item.startTime + item.duration, duration );

        if (iterations < 0)
            totalDuration = float.PositiveInfinity;
        else
            totalDuration = duration * iterations;
	}
    /// <summary>
    /// reverses playback. if going forward it will be going backward after this and vice versa.
    /// </summary>
    public override void reverse()
    {
        base.reverse();

        var convertedElapsedTime = _isLoopingBackOnPingPong ? duration - _elapsedTime : _elapsedTime;

        for (int k = 0; k < _tweenFlows.Count; ++k)
        {
            TweenFlowItem flowItem = _tweenFlows[k];

            if (flowItem.tween == null)
            {
                continue;
            }

            if (isReversed != flowItem.tween.isReversed)
            {
                flowItem.tween.reverse();
            }

            flowItem.tween.pause();

            // we selectively mark tweens for play if they will be played immediately or in the future.
            // update() will filter out more tweens that should not be played yet.
            if (isReversed || _isLoopingBackOnPingPong)
            {
                if (flowItem.startTime <= convertedElapsedTime)
                {
                    flowItem.tween.play();
                }
            }
            else
            {
                if (flowItem.endTime >= convertedElapsedTime)
                {
                    flowItem.tween.play();
                }
            }
        }
    }
Example #22
0
    /// <summary>
    /// the item being added already has a start time so no extra parameter is needed
    /// </summary>
    private void insert(TweenFlowItem item)
    {
        // early out for invalid items
        if (item.tween != null && !item.tween.isValid())
        {
            return;
        }

        if (float.IsInfinity(item.duration))
        {
            Debug.Log("adding a Tween with infinite iterations to a TweenFlow is not permitted");
            return;
        }

        // ensure the tween isnt already live
        if (item.tween != null)
        {
            Go.removeTween(item.tween);
        }

        // add the item then sort based on startTimes
        _tweenFlows.Add(item);
        _tweenFlows.Sort((x, y) =>
        {
            return(x.startTime.CompareTo(y.startTime));
        });

        duration = Mathf.Max(item.startTime + item.duration, duration);

        if (iterations >= 0)
        {
            totalDuration = duration * iterations;
        }
        else
        {
            totalDuration = float.PositiveInfinity;
        }
    }
 private void prepend(TweenFlowItem item)
 {
     if (item.tween != null && !item.tween.isValid())
     {
         return;
     }
     if (float.IsInfinity(item.duration))
     {
         UnityEngine.Debug.LogError("adding a Tween with infinite iterations to a TweenChain is not permitted");
         return;
     }
     if (item.tween != null)
     {
         if (item.tween.isReversed != base.isReversed)
         {
             UnityEngine.Debug.LogError("adding a Tween that doesn't match the isReversed property of the TweenChain is not permitted.");
             return;
         }
         Go.removeTween(item.tween);
         item.tween.play();
     }
     for (int i = 0; i < _tweenFlows.Count; i++)
     {
         TweenFlowItem tweenFlowItem = _tweenFlows[i];
         tweenFlowItem.startTime += item.duration;
     }
     _tweenFlows.Insert(0, item);
     base.duration += item.duration;
     if (base.iterations < 0)
     {
         base.totalDuration = float.PositiveInfinity;
     }
     else
     {
         base.totalDuration = base.duration * (float)base.iterations;
     }
 }
    /// <summary>
    /// returns a list of all Tweens with the given target in the collection
    /// technically, this should be marked as internal
    /// </summary>
    public List <GoTween> tweensWithTarget(object target)
    {
        List <GoTween> list = new List <GoTween>();

        for (int k = 0; k < _tweenFlows.Count; ++k)
        {
            TweenFlowItem flowItem = _tweenFlows[k];
            // skip TweenFlowItems with no target
            if (flowItem.tween == null)
            {
                continue;
            }

            // check Tweens first
            var tween = flowItem.tween as GoTween;
            if (tween != null && tween.target == target)
            {
                list.Add(tween);
            }

            // check for TweenCollections
            if (tween == null)
            {
                var tweenCollection = flowItem.tween as AbstractGoTweenCollection;
                if (tweenCollection != null)
                {
                    var tweensInCollection = tweenCollection.tweensWithTarget(target);
                    if (tweensInCollection.Count > 0)
                    {
                        list.AddRange(tweensInCollection);
                    }
                }
            }
        }

        return(list);
    }
Example #25
0
	private void append( TweenFlowItem item )
	{
		// early out for invalid items
		if( item.tween != null && !item.tween.isValid() )
			return;
		
		if( float.IsInfinity( item.duration ) )
		{
			Debug.LogError( "adding a Tween with infinite iterations to a TweenChain is not permitted" );
			return;
		}

        if ( item.tween != null )
        {
            if ( item.tween.isReversed != isReversed )
            {
                Debug.LogError( "adding a Tween that doesn't match the isReversed property of the TweenChain is not permitted." );
                return;
            }

            // ensure the tween isnt already live
            Go.removeTween(item.tween);

            // ensure that the item is marked to play.
            item.tween.play();
        }
		
		_tweenFlows.Add( item );
		
		// update the duration and total duration
		duration += item.duration;
		
		if( iterations < 0 )
			totalDuration = float.PositiveInfinity;
		else
            totalDuration = duration * iterations;
	}
    private void changeTimeForFlowItem(TweenFlowItem flowItem, float time)
    {
        if (flowItem == null || flowItem.tween == null)
        {
            return;
        }

        if (flowItem.tween.isReversed != (isReversed || _isLoopingBackOnPingPong))
        {
            flowItem.tween.reverse();
        }

        var convertedTime = Mathf.Clamp(time - flowItem.startTime, 0f, flowItem.endTime);

        if (flowItem.startTime <= time && flowItem.endTime >= time)
        {
            flowItem.tween.goToAndPlay(convertedTime);
        }
        else
        {
            flowItem.tween.goTo(convertedTime);
            flowItem.tween.pause();
        }
    }
    /// <summary>
    /// returns a list of all Tweens with the given target in the collection
    /// technically, this should be marked as internal
    /// </summary>
    public List <GoTween> tweensWithTarget(object target)
    {
        List <GoTween> list = new List <GoTween>();

        for (int i = 0; _tweenFlows.Count > i; i++)
        {
            TweenFlowItem item = _tweenFlows[i];

            // skip TweenFlowItems with no target
            if (item == null)
            {
                continue;
            }

            GoTween tween = item.tween as GoTween;

            if (tween != null && tween.target == target)
            {
                list.Add(tween);
            }
            else if (tween == null)
            {
                AbstractGoTweenCollection tweenCollection = ( AbstractGoTweenCollection )item.tween;

                if (tweenCollection != null)
                {
                    List <GoTween> tweensInCollection = tweenCollection.tweensWithTarget(target);

                    if (tweensInCollection.Count > 0)
                    {
                        list.AddRange(tweensInCollection);
                    }
                }
            }
        }

        /*foreach ( var flowItem in _tweenFlows )
         * {
         *  // skip TweenFlowItems with no target
         *  if ( flowItem.tween == null )
         *      continue;
         *
         *  // check Tweens first
         *  var tween = flowItem.tween as GoTween;
         *  if ( tween != null && tween.target == target )
         *      list.Add( tween );
         *
         *  // check for TweenCollections
         *  if ( tween == null )
         *  {
         *      var tweenCollection = flowItem.tween as AbstractGoTweenCollection;
         *      if ( tweenCollection != null )
         *      {
         *          var tweensInCollection = tweenCollection.tweensWithTarget( target );
         *          if ( tweensInCollection.Count > 0 )
         *              list.AddRange( tweensInCollection );
         *      }
         *  }
         * }*/

        return(list);
    }
    public override bool update(float deltaTime)
    {
        if (!_didInit)
        {
            onInit();
        }
        if (!_didBegin)
        {
            onBegin();
        }
        if (_fireIterationStart)
        {
            onIterationStart();
        }
        base.update(deltaTime);
        float         num           = (!_isLoopingBackOnPingPong) ? _elapsedTime : (base.duration - _elapsedTime);
        TweenFlowItem tweenFlowItem = null;

        if (_didIterateLastFrame && base.loopType == GoLoopType.RestartFromBeginning)
        {
            if (base.isReversed || _isLoopingBackOnPingPong)
            {
                for (int i = 0; i < _tweenFlows.Count; i++)
                {
                    tweenFlowItem = _tweenFlows[i];
                    if (tweenFlowItem.tween != null)
                    {
                        bool allowEvents = tweenFlowItem.tween.allowEvents;
                        tweenFlowItem.tween.allowEvents = false;
                        tweenFlowItem.tween.restart();
                        tweenFlowItem.tween.allowEvents = allowEvents;
                    }
                }
            }
            else
            {
                for (int num2 = _tweenFlows.Count - 1; num2 >= 0; num2--)
                {
                    tweenFlowItem = _tweenFlows[num2];
                    if (tweenFlowItem.tween != null)
                    {
                        bool allowEvents2 = tweenFlowItem.tween.allowEvents;
                        tweenFlowItem.tween.allowEvents = false;
                        tweenFlowItem.tween.restart();
                        tweenFlowItem.tween.allowEvents = allowEvents2;
                    }
                }
            }
        }
        else if ((base.isReversed && !_isLoopingBackOnPingPong) || (!base.isReversed && _isLoopingBackOnPingPong))
        {
            for (int num3 = _tweenFlows.Count - 1; num3 >= 0; num3--)
            {
                tweenFlowItem = _tweenFlows[num3];
                if (tweenFlowItem.tween != null)
                {
                    if (_didIterateLastFrame && base.state != GoTweenState.Complete)
                    {
                        if (!tweenFlowItem.tween.isReversed)
                        {
                            tweenFlowItem.tween.reverse();
                        }
                        tweenFlowItem.tween.play();
                    }
                    if (tweenFlowItem.tween.state == GoTweenState.Running && tweenFlowItem.endTime >= num)
                    {
                        float deltaTime2 = Mathf.Abs(num - tweenFlowItem.startTime - tweenFlowItem.tween.totalElapsedTime);
                        tweenFlowItem.tween.update(deltaTime2);
                    }
                }
            }
        }
        else
        {
            for (int j = 0; j < _tweenFlows.Count; j++)
            {
                tweenFlowItem = _tweenFlows[j];
                if (tweenFlowItem.tween == null)
                {
                    continue;
                }
                if (_didIterateLastFrame && base.state != GoTweenState.Complete)
                {
                    if (tweenFlowItem.tween.isReversed)
                    {
                        tweenFlowItem.tween.reverse();
                    }
                    tweenFlowItem.tween.play();
                }
                if (tweenFlowItem.tween.state == GoTweenState.Running && tweenFlowItem.startTime <= num)
                {
                    float deltaTime3 = num - tweenFlowItem.startTime - tweenFlowItem.tween.totalElapsedTime;
                    tweenFlowItem.tween.update(deltaTime3);
                }
            }
        }
        onUpdate();
        if (_fireIterationEnd)
        {
            onIterationEnd();
        }
        if (base.state == GoTweenState.Complete)
        {
            onComplete();
            return(true);
        }
        return(false);
    }
    public override void goTo(float time, bool skipDelay)
    {
        time = Mathf.Clamp(time, 0f, base.totalDuration);
        if (time == _totalElapsedTime)
        {
            return;
        }
        if ((base.isReversed && time == base.totalDuration) || (!base.isReversed && time == 0f))
        {
            _didBegin           = false;
            _fireIterationStart = true;
        }
        else
        {
            _didBegin           = true;
            _fireIterationStart = false;
        }
        _didIterateThisFrame = false;
        _totalElapsedTime    = time;
        _completedIterations = ((!base.isReversed) ? Mathf.FloorToInt(_totalElapsedTime / base.duration) : Mathf.CeilToInt(_totalElapsedTime / base.duration));
        base.update(0f);
        float         num           = (!_isLoopingBackOnPingPong) ? _elapsedTime : (base.duration - _elapsedTime);
        TweenFlowItem tweenFlowItem = null;

        if (base.isReversed || _isLoopingBackOnPingPong)
        {
            for (int i = 0; i < _tweenFlows.Count; i++)
            {
                tweenFlowItem = _tweenFlows[i];
                if (tweenFlowItem != null)
                {
                    if (tweenFlowItem.endTime >= num)
                    {
                        break;
                    }
                    changeTimeForFlowItem(tweenFlowItem, num);
                }
            }
            for (int num2 = _tweenFlows.Count - 1; num2 >= 0; num2--)
            {
                tweenFlowItem = _tweenFlows[num2];
                if (tweenFlowItem != null)
                {
                    if (tweenFlowItem.endTime < num)
                    {
                        break;
                    }
                    changeTimeForFlowItem(tweenFlowItem, num);
                }
            }
            return;
        }
        for (int num3 = _tweenFlows.Count - 1; num3 >= 0; num3--)
        {
            tweenFlowItem = _tweenFlows[num3];
            if (tweenFlowItem != null)
            {
                if (tweenFlowItem.startTime <= num)
                {
                    break;
                }
                changeTimeForFlowItem(tweenFlowItem, num);
            }
        }
        for (int j = 0; j < _tweenFlows.Count; j++)
        {
            tweenFlowItem = _tweenFlows[j];
            if (tweenFlowItem != null)
            {
                if (tweenFlowItem.startTime > num)
                {
                    break;
                }
                changeTimeForFlowItem(tweenFlowItem, num);
            }
        }
    }
    /// <summary>
    /// goes to the specified time clamping it from 0 to the total duration of the tween. if the tween is
    /// not playing it will be force updated to the time specified.
    /// </summary>
    public override void goTo(float time, bool skipDelay)
    {
        time = Mathf.Clamp(time, 0f, totalDuration);

        // provide an early out for calling goTo on the same time multiple times.
        if (time == _totalElapsedTime)
        {
            return;
        }

        // we don't simply call base.goTo because that would force an update within AbstractGoTweenCollection,
        // which forces an update on all the tweenFlowItems without putting them in the right position.
        // it's also possible that people will move around a tween via the goTo method, so we want to
        // try to make that as efficient as possible.

        // if we are doing a goTo at the "start" of the timeline, based on the isReversed variable,
        // allow the onBegin and onIterationStart callback to fire again.
        // we only allow the onIterationStart event callback to fire at the start of the timeline,
        // as doing a goTo(x) where x % duration == 0 will trigger the onIterationEnd before we
        // go to the start.
        if ((isReversed && time == totalDuration) || (!isReversed && time == 0f))
        {
            _didBegin           = false;
            _fireIterationStart = true;
        }
        else
        {
            _didBegin           = true;
            _fireIterationStart = false;
        }

        // since we're doing a goTo, we want to stop this tween from remembering that it iterated.
        // this could cause issues if you caused the tween to complete an iteration and then goTo somewhere
        // else while still paused.
        _didIterateThisFrame = false;

        // force a time and completedIterations before we update
        _totalElapsedTime    = time;
        _completedIterations = isReversed ? Mathf.CeilToInt(_totalElapsedTime / duration) : Mathf.FloorToInt(_totalElapsedTime / duration);

        // we don't want to use the Collection update function, because we don't have all of our
        // child tweenFlowItems setup properly. this will properly setup our iterations,
        // totalElapsedTime, and other useful information.
        base.update(0);

        var convertedElapsedTime = _isLoopingBackOnPingPong ? duration - _elapsedTime : _elapsedTime;

        // we always want to process items in the future of this tween from last to first.
        // and items that have already occured from first to last.
        TweenFlowItem flowItem = null;

        if (isReversed || _isLoopingBackOnPingPong)
        {
            // flowItems in the future of the timeline
            for (int i = 0; i < _tweenFlows.Count; ++i)
            {
                flowItem = _tweenFlows[i];

                if (flowItem == null)
                {
                    continue;
                }

                if (flowItem.endTime >= convertedElapsedTime)
                {
                    break;
                }

                changeTimeForFlowItem(flowItem, convertedElapsedTime);
            }

            // flowItems in the past & current part of the timeline
            for (int i = _tweenFlows.Count - 1; i >= 0; --i)
            {
                flowItem = _tweenFlows[i];

                if (flowItem == null)
                {
                    continue;
                }

                if (flowItem.endTime < convertedElapsedTime)
                {
                    break;
                }

                changeTimeForFlowItem(flowItem, convertedElapsedTime);
            }
        }
        else
        {
            // flowItems in the future of the timeline
            for (int i = _tweenFlows.Count - 1; i >= 0; --i)
            {
                flowItem = _tweenFlows[i];

                if (flowItem == null)
                {
                    continue;
                }

                if (flowItem.startTime <= convertedElapsedTime)
                {
                    break;
                }

                changeTimeForFlowItem(flowItem, convertedElapsedTime);
            }

            // flowItems in the past & current part of the timeline
            for (int i = 0; i < _tweenFlows.Count; ++i)
            {
                flowItem = _tweenFlows[i];

                if (flowItem == null)
                {
                    continue;
                }

                if (flowItem.startTime > convertedElapsedTime)
                {
                    break;
                }

                changeTimeForFlowItem(flowItem, convertedElapsedTime);
            }
        }
    }
    /// <summary>
    /// tick method. if it returns true it indicates the tween is complete
    /// </summary>
    public override bool update(float deltaTime)
    {
        if (!_didInit)
        {
            onInit();
        }

        if (!_didBegin)
        {
            onBegin();
        }

        if (_fireIterationStart)
        {
            onIterationStart();
        }

        // update the timeline and state.
        base.update(deltaTime);

        // get the proper elapsedTime if we're doing a PingPong
        var convertedElapsedTime = _isLoopingBackOnPingPong ? duration - _elapsedTime : _elapsedTime;

        // used for iterating over flowItems below.
        TweenFlowItem flowItem = null;

        // if we iterated last frame and this flow restarts from the beginning, we now need to reset all
        // of the flowItem tweens to either the beginning or the end of their respective timelines
        // we also want to do this in the _opposite_ way that we would normally iterate on them
        // as the start value of a later flowItem may alter a property of an earlier flowItem.
        if (_didIterateLastFrame && loopType == GoLoopType.RestartFromBeginning)
        {
            if (isReversed || _isLoopingBackOnPingPong)
            {
                for (int i = 0; i < _tweenFlows.Count; ++i)
                {
                    flowItem = _tweenFlows[i];

                    if (flowItem.tween == null)
                    {
                        continue;
                    }

                    var cacheAllow = flowItem.tween.allowEvents;
                    flowItem.tween.allowEvents = false;
                    flowItem.tween.restart();
                    flowItem.tween.allowEvents = cacheAllow;
                }
            }
            else
            {
                for (int i = _tweenFlows.Count - 1; i >= 0; --i)
                {
                    flowItem = _tweenFlows[i];

                    if (flowItem.tween == null)
                    {
                        continue;
                    }

                    var cacheAllow = flowItem.tween.allowEvents;
                    flowItem.tween.allowEvents = false;
                    flowItem.tween.restart();
                    flowItem.tween.allowEvents = cacheAllow;
                }
            }
        }
        else
        {
            if ((isReversed && !_isLoopingBackOnPingPong) || (!isReversed && _isLoopingBackOnPingPong))
            {
                // if we are moving the tween in reverse, we should be iterating over the flowItems in reverse
                // to help properties behave a bit better.
                for (var i = _tweenFlows.Count - 1; i >= 0; --i)
                {
                    flowItem = _tweenFlows[i];

                    if (flowItem.tween == null)
                    {
                        continue;
                    }

                    // if there's been an iteration this frame and we're not done yet, we want to make sure
                    // this tween is set to play in the right direction, and isn't set to complete/paused.
                    if (_didIterateLastFrame && state != GoTweenState.Complete)
                    {
                        if (!flowItem.tween.isReversed)
                        {
                            flowItem.tween.reverse();
                        }

                        flowItem.tween.play();
                    }

                    if (flowItem.tween.state == GoTweenState.Running && flowItem.endTime >= convertedElapsedTime)
                    {
                        var convertedDeltaTime = Mathf.Abs(convertedElapsedTime - flowItem.startTime - flowItem.tween.totalElapsedTime);
                        flowItem.tween.update(convertedDeltaTime);
                    }
                }
            }
            else
            {
                for (int i = 0; i < _tweenFlows.Count; ++i)
                {
                    flowItem = _tweenFlows[i];

                    if (flowItem.tween == null)
                    {
                        continue;
                    }

                    // if there's been an iteration this frame and we're not done yet, we want to make sure
                    // this tween is set to play in the right direction, and isn't set to complete/paused.
                    if (_didIterateLastFrame && state != GoTweenState.Complete)
                    {
                        if (flowItem.tween.isReversed)
                        {
                            flowItem.tween.reverse();
                        }

                        flowItem.tween.play();
                    }

                    if (flowItem.tween.state == GoTweenState.Running && flowItem.startTime <= convertedElapsedTime)
                    {
                        var convertedDeltaTime = convertedElapsedTime - flowItem.startTime - flowItem.tween.totalElapsedTime;
                        flowItem.tween.update(convertedDeltaTime);
                    }
                }
            }
        }

        onUpdate();

        if (_fireIterationEnd)
        {
            onIterationEnd();
        }
        if (state == GoTweenState.Complete)
        {
            onComplete();

            return(true); // true if complete
        }

        return(false); // false if not complete
    }
    private void changeTimeForFlowItem( TweenFlowItem flowItem, float time )
    {
        if ( flowItem == null || flowItem.tween == null )
            return;

        if ( flowItem.tween.isReversed != ( isReversed || _isLoopingBackOnPingPong ) )
            flowItem.tween.reverse();

        var convertedTime = Mathf.Clamp( time - flowItem.startTime, 0f, flowItem.endTime );

        if ( flowItem.startTime <= time && flowItem.endTime >= time )
        {
            flowItem.tween.goToAndPlay( convertedTime );
        }
        else
        {
            flowItem.tween.goTo( convertedTime );
            flowItem.tween.pause();
        }
    }