applyRotateTimeline method
void
applyRotateTimeline()
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;
}