package loon.action.sprite;
import java.util.Arrays;
import loon.LSystem;
import loon.utils.MathUtils;
/**
* 一个Animation播放序列的存储器,需要与Animation或Sprite合用才能生效
*/
public class AnimationData {
public static final int LOOP_CONTINUOUS = -1;
private int _frameCount;
private int[] _frames;
private long[] _frameDurations;
private int _firstFrameIndex;
private int _loopCount;
private long[] _frameEndsInNanoseconds;
private long _animationDuration;
public AnimationData() {
this(new long[] { 0, 0 });
}
public AnimationData(final long frameDurationEach, final int frameCount) {
this.set(frameDurationEach, frameCount);
}
public AnimationData(final long frameDurationEach, final int frameCount,
final boolean loop) {
this.set(frameDurationEach, frameCount, loop);
}
public AnimationData(final long frameDurationEach, final int frameCount,
final int loopCount) {
this.set(frameDurationEach, frameCount, loopCount);
}
public AnimationData(final long[] frameDurations) {
this.set(frameDurations);
}
public AnimationData(final long[] frameDurations, final boolean loop) {
this.set(frameDurations, loop);
}
public AnimationData(final long[] frameDurations, final int loopCount) {
this.set(frameDurations, loopCount);
}
public AnimationData(final long[] frameDurations,
final int firstFrameIndex, final int lastFrameIndex,
final boolean loop) {
this.set(frameDurations, firstFrameIndex, lastFrameIndex, loop);
}
public AnimationData(final long[] frameDurations, final int[] frames,
final int loopCount) {
this.set(frameDurations, frames, loopCount);
}
public AnimationData(final long[] frameDurations,
final int firstFrameIndex, final int lastFrameIndex,
final int loopCount) {
this.set(frameDurations, firstFrameIndex, lastFrameIndex, loopCount);
}
public AnimationData(final AnimationData animationData) {
this.set(animationData);
}
public int[] getFrames() {
return this._frames;
}
public long[] getFrameDurations() {
return this._frameDurations;
}
public int getLoopCount() {
return this._loopCount;
}
public int getFrameCount() {
return this._frameCount;
}
public int getFirstFrameIndex() {
return this._firstFrameIndex;
}
public long getAnimationDuration() {
return this._animationDuration;
}
public int calculateCurrentFrameIndex(final long animationProgress) {
final long[] frameEnds = this._frameEndsInNanoseconds;
final int frameCount = this._frameCount;
for (int i = 0; i < frameCount; i++) {
if (frameEnds[i] > animationProgress) {
return i;
}
}
return frameCount - 1;
}
public void set(final long frameDurationEach, final int frameCount) {
this.set(frameDurationEach, frameCount, true);
}
public void set(final long frameDurationEach, final int frameCount,
final boolean loop) {
this.set(frameDurationEach, frameCount,
(loop) ? AnimationData.LOOP_CONTINUOUS : 0);
}
public void set(final long frameDurationEach, final int frameCount,
final int loopCount) {
this.set(
AnimationData.fillFrameDurations(frameDurationEach, frameCount),
loopCount);
}
public void set(final long[] frameDurations) {
this.set(frameDurations, true);
}
public void set(final long[] frameDurations, final boolean loop) {
this.set(frameDurations, (loop) ? AnimationData.LOOP_CONTINUOUS : 0);
}
public void set(final long[] frameDurations, final int loopCount) {
this.set(frameDurations, 0, frameDurations.length - 1, loopCount);
}
public void set(final long[] frameDurations, final int firstFrameIndex,
final int lastFrameIndex) {
this.set(frameDurations, firstFrameIndex, lastFrameIndex, true);
}
public void set(final long[] frameDurations, final int firstFrameIndex,
final int lastFrameIndex, final boolean loop) {
this.set(frameDurations, firstFrameIndex, lastFrameIndex,
(loop) ? AnimationData.LOOP_CONTINUOUS : 0);
}
public void set(final long[] frameDurations, final int firstFrameIndex,
final int lastFrameIndex, final int loopCount) {
this.set(frameDurations, (lastFrameIndex - firstFrameIndex) + 1, null,
firstFrameIndex, loopCount);
if ((firstFrameIndex + 1) > lastFrameIndex) {
throw new IllegalArgumentException(
"An animation needs at least two tiles to animate between.");
}
}
public void set(final long[] frameDurations, final int[] frames) {
this.set(frameDurations, frames, true);
}
public void set(final long[] frameDurations, final int[] frames,
final boolean loop) {
this.set(frameDurations, frames, (loop) ? AnimationData.LOOP_CONTINUOUS
: 0);
}
public void set(final long[] frameDurations, final int[] frames,
final int loopCount) {
this.set(frameDurations, frames.length, frames, 0, loopCount);
}
public void set(final AnimationData animationData) {
this.set(animationData.getFrameDurations(),
animationData.getFrameCount(), animationData.getFrames(),
animationData.getFirstFrameIndex(),
animationData.getLoopCount());
}
private void set(final long[] frameDurations, final int frameCount,
final int[] frames, final int firstFrameIndex, final int loopCount) {
if (frameDurations.length != frameCount) {
throw new IllegalArgumentException(
"frameDurations does not equal frameCount!");
}
this._frameDurations = frameDurations;
this._frameCount = frameCount;
this._frames = frames;
this._firstFrameIndex = firstFrameIndex;
this._loopCount = loopCount;
if ((this._frameEndsInNanoseconds == null)
|| (this._frameCount > this._frameEndsInNanoseconds.length)) {
this._frameEndsInNanoseconds = new long[this._frameCount];
}
final long[] frameEndsInNanoseconds = this._frameEndsInNanoseconds;
MathUtils.arraySumInto(this._frameDurations, frameEndsInNanoseconds,
LSystem.SECOND);
final long lastFrameEnd = frameEndsInNanoseconds[this._frameCount - 1];
this._animationDuration = lastFrameEnd;
}
private static long[] fillFrameDurations(final long frameDurationEach,
final int frameCount) {
final long[] frameDurations = new long[frameCount];
Arrays.fill(frameDurations, frameDurationEach);
return frameDurations;
}
public AnimationData cpy() {
return new AnimationData(this);
}
}