private void addTimelineState(String timelineName) {
   Bone bone = _armature.getBone(timelineName);
   if (bone != null) {
     for (TimelineState eachState : _timelineStateList) {
       if (Objects.equals(eachState.name, timelineName)) {
         return;
       }
     }
     TimelineState timelineState = TimelineState.borrowObject();
     timelineState.fadeIn(bone, this, _clip.getTimeline(timelineName));
     _timelineStateList.add(timelineState);
   }
 }
  /** @private */
  private static void clearStatic() {
    int i = _pool.size();
    while (i-- > 0) {
      _pool.get(i).clear();
    }
    _pool.clear();

    TimelineState.clearStatic();
  }
  void resetTimelineStateList() {
    int i = _timelineStateList.size();
    while (i-- > 0) {
      TimelineState.returnObject(_timelineStateList.get(i));
    }
    _timelineStateList.clear();

    i = _slotTimelineStateList.size();
    while (i-- > 0) {
      SlotTimelineState.returnObject(_slotTimelineStateList.get(i));
    }
    _slotTimelineStateList.clear();
  }
  /**
   * Fade out the animation state
   *
   * @param fadeTotalTime
   * @param pausePlayhead pause the animation before fade out complete
   */
  public AnimationState fadeOut(double fadeTotalTime, boolean pausePlayhead) {
    if (_armature == null) {
      return null;
    }

    if (Double.isNaN(fadeTotalTime) || fadeTotalTime < 0) {
      fadeTotalTime = 0;
    }
    _pausePlayheadInFade = pausePlayhead;

    if (_isFadeOut) {
      if (fadeTotalTime > _fadeTotalTime / _timeScale - (_fadeCurrentTime - _fadeBeginTime)) {
        // 如果已经在淡出中,新的淡出需要更长的淡出时间,则忽略
        // If the animation is already in fade out, the new fade out will be ignored.
        return this;
      }
    } else {
      // 第一次淡出
      // The first time to fade out.
      for (TimelineState timelineState : _timelineStateList) {
        timelineState.fadeOut();
      }
    }

    // fade start
    _isFadeOut = true;
    _fadeTotalWeight = _fadeWeight;
    _fadeState = -1;
    _fadeBeginTime = _fadeCurrentTime;
    _fadeTotalTime = _fadeTotalWeight >= 0 ? fadeTotalTime * _timeScale : 0;

    // default
    displayControl = false;

    return this;
  }
  private void advanceTimelinesTime(double passedTime) {
    if (_isPlaying && !_pausePlayheadInFade) {
      _time += passedTime;
    }

    boolean startFlg = false;
    boolean completeFlg = false;
    boolean loopCompleteFlg = false;
    boolean isThisComplete = false;
    int currentPlayTimes = 0;
    int currentTime = (int) (_time * 1000);
    if (_playTimes == 0) {
      isThisComplete = false;
      currentPlayTimes = (int) Math.ceil(Math.abs(currentTime) / _totalTime);
      if (currentPlayTimes == 0) currentPlayTimes = 1;
      // currentTime -= Math.floor(currentTime / _totalTime) * _totalTime;

      currentTime -= (int) (currentTime / _totalTime) * _totalTime;

      if (currentTime < 0) {
        currentTime += _totalTime;
      }
    } else {
      int totalTimes = _playTimes * _totalTime;
      if (currentTime >= totalTimes) {
        currentTime = totalTimes;
        isThisComplete = true;
      } else if (currentTime <= -totalTimes) {
        currentTime = -totalTimes;
        isThisComplete = true;
      } else {
        isThisComplete = false;
      }

      if (currentTime < 0) {
        currentTime += totalTimes;
      }

      currentPlayTimes = (int) Math.ceil(currentTime / _totalTime);
      if (currentPlayTimes == 0) currentPlayTimes = 1;
      // currentTime -= Math.floor(currentTime / _totalTime) * _totalTime;
      currentTime -= (int) (currentTime / _totalTime) * _totalTime;

      if (isThisComplete) {
        currentTime = _totalTime;
      }
    }

    // update timeline
    _isComplete = isThisComplete;
    double progress = _time * 1000 / _totalTime;
    for (TimelineState timeline : _timelineStateList) {
      timeline.update(progress);
      _isComplete = timeline._isComplete && _isComplete;
    }
    // update slotTimelie
    for (SlotTimelineState slotTimeline : _slotTimelineStateList) {
      slotTimeline.update(progress);
      _isComplete = slotTimeline._isComplete && _isComplete;
    }
    // update main timeline
    if (_currentTime != currentTime) {
      if (_currentPlayTimes != currentPlayTimes) // check loop complete
      {
        if (_currentPlayTimes > 0 && currentPlayTimes > 1) {
          loopCompleteFlg = true;
        }
        _currentPlayTimes = currentPlayTimes;
      }

      if (_currentTime < 0) // check start
      {
        startFlg = true;
      }

      if (_isComplete) // check complete
      {
        completeFlg = true;
      }
      _lastTime = _currentTime;
      _currentTime = currentTime;
      /*
      if(isThisComplete)
      {
      currentTime = _totalTime * 0.999999;
      }
      //[0, _totalTime)
      */
      updateMainTimeline(isThisComplete);
    }

    AnimationEvent event;
    if (startFlg) {
      if (_armature.hasEventListener(AnimationEvent.START)) {
        event = new AnimationEvent(AnimationEvent.START);
        event.animationState = this;
        _armature._eventList.add(event);
      }
    }

    if (completeFlg) {
      if (_armature.hasEventListener(AnimationEvent.COMPLETE)) {
        event = new AnimationEvent(AnimationEvent.COMPLETE);
        event.animationState = this;
        _armature._eventList.add(event);
      }
      if (autoFadeOut) {
        fadeOut(fadeOutTime, true);
      }
    } else if (loopCompleteFlg) {
      if (_armature.hasEventListener(AnimationEvent.LOOP_COMPLETE)) {
        event = new AnimationEvent(AnimationEvent.LOOP_COMPLETE);
        event.animationState = this;
        _armature._eventList.add(event);
      }
    }
  }
 private void removeTimelineState(TimelineState timelineState) {
   _timelineStateList.remove(timelineState);
   TimelineState.returnObject(timelineState);
 }