applyRotateTimeline method

void applyRotateTimeline(
  1. Timeline timeline,
  2. Skeleton skeleton,
  3. double time,
  4. double alpha,
  5. MixPose pose,
  6. List<double> timelinesRotation,
  7. int i,
  8. bool firstFrame,
)

Implementation

void applyRotateTimeline(
    Timeline timeline,
    Skeleton skeleton,
    double time,
    double alpha,
    MixPose pose,
    List<double> timelinesRotation,
    int i,
    bool firstFrame) {
  if (firstFrame) timelinesRotation[i] = 0.0;

  if (alpha == 1) {
    timeline.apply(
        skeleton, 0.0, time, <Event?>[], 1.0, pose, MixDirection.mixIn);
    return;
  }

  final RotateTimeline rotateTimeline = timeline as RotateTimeline;
  final Float32List frames = rotateTimeline.frames;
  final Bone bone = skeleton.bones[rotateTimeline.boneIndex];
  if (time < frames[0]) {
    if (pose == MixPose.setup) bone.rotation = bone.data.rotation;
    return;
  }

  double r2 = 0.0;
  if (time >= frames[frames.length - RotateTimeline.entries]) {
    r2 = bone.data.rotation +
        frames[frames.length + RotateTimeline.prevRotation];
  } else {
    // Interpolate between the previous frame and the current frame.
    final int frame =
        Animation.binarySearch(frames, time, RotateTimeline.entries);
    final double prevRotation = frames[frame + RotateTimeline.prevRotation];
    final double frameTime = frames[frame];
    final double percent = rotateTimeline.getCurvePercent(
        (frame >> 1) - 1,
        1 -
            (time - frameTime) /
                (frames[frame + RotateTimeline.prevTime] - frameTime));

    r2 = frames[frame + RotateTimeline.rotation] - prevRotation;
    r2 -= (16384 - (16384.499999999996 - r2 / 360).toInt()) * 360;
    r2 = prevRotation + r2 * percent + bone.data.rotation;
    r2 -= (16384 - (16384.499999999996 - r2 / 360).toInt()) * 360;
  }

  // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
  double r1 = pose == MixPose.setup ? bone.data.rotation : bone.rotation;
  double total = 0.0, diff = r2 - r1;
  if (diff == 0) {
    total = timelinesRotation[i];
  } else {
    diff -= (16384 - (16384.499999999996 - diff / 360).toInt()) * 360;
    double lastTotal = 0.0, lastDiff = 0.0;
    if (firstFrame) {
      lastTotal = 0.0;
      lastDiff = diff;
    } else {
      lastTotal = timelinesRotation[
          i]; // Angle and direction of mix, including loops.
      lastDiff = timelinesRotation[i + 1]; // Difference between bones.
    }
    final bool current = diff > 0;
    bool dir = lastTotal >= 0;
    // Detect cross at 0 (not 180).
    if (MathUtils.signum(lastDiff) != MathUtils.signum(diff) &&
        lastDiff.abs() <= 90) {
      // A cross after a 360 rotation is a loop.
      if (lastTotal.abs() > 180) {
        lastTotal += 360 * MathUtils.signum(lastTotal);
      }
      dir = current;
    }
    total = diff +
        lastTotal -
        lastTotal % 360; // Store loops as part of lastTotal.
    if (dir != current) total += 360 * MathUtils.signum(lastTotal);
    timelinesRotation[i] = total;
  }
  timelinesRotation[i + 1] = diff;
  r1 += total * alpha;
  bone.rotation =
      r1 - (16384 - (16384.499999999996 - r1 / 360).toInt()) * 360;
}