private void updateMixingFrom(TrackEntry entry, float delta) {
    TrackEntry from = entry.mixingFrom;
    if (from == null) return;

    updateMixingFrom(from, delta);

    if (entry.mixTime >= entry.mixDuration && from.mixingFrom == null && entry.mixTime > 0) {
      entry.mixingFrom = null;
      queue.end(from);
      return;
    }

    from.animationLast = from.nextAnimationLast;
    from.trackLast = from.nextTrackLast;
    from.trackTime += delta * from.timeScale;
    entry.mixTime += delta * entry.timeScale;
  }
  private void setCurrent(int index, TrackEntry current, boolean interrupt) {
    TrackEntry from = expandToIndex(index);
    tracks.set(index, current);

    if (from != null) {
      if (interrupt) queue.interrupt(from);
      current.mixingFrom = from;
      current.mixTime = 0;

      from.timelinesRotation.clear(); // Reset rotation for mixing out, in case entry was mixed in.

      // If not completely mixed in, set mixAlpha so mixing out happens from current mix to zero.
      if (from.mixingFrom != null && from.mixDuration > 0)
        current.mixAlpha *= Math.min(from.mixTime / from.mixDuration, 1);
    }

    queue.start(current);
  }
  /**
   * Removes all animations from the track, leaving skeletons in their previous pose.
   *
   * <p>It may be desired to use {@link AnimationState#setEmptyAnimation(int, float)} to mix the
   * skeletons back to the setup pose, rather than leaving them in their previous pose.
   */
  public void clearTrack(int trackIndex) {
    if (trackIndex >= tracks.size) return;
    TrackEntry current = tracks.get(trackIndex);
    if (current == null) return;

    queue.end(current);

    disposeNext(current);

    TrackEntry entry = current;
    while (true) {
      TrackEntry from = entry.mixingFrom;
      if (from == null) break;
      queue.end(from);
      entry.mixingFrom = null;
      entry = from;
    }

    tracks.set(current.trackIndex, null);

    queue.drain();
  }