package rajawali.animation; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import rajawali.ATransformable3D; import android.os.SystemClock; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; public class Animation3D { public static final int INFINITE = -1; public static final int RESTART = 1; public static final int REVERSE = 2; protected long mDuration; protected long mStart = -1; protected long mLength = -1; protected Interpolator mInterpolator; protected int mRepeatCount; protected int mRepeatMode = RESTART; protected int mNumRepeats; protected int mDirection = 1; protected long mStartOffset; protected long mStartTime; protected long mDelay; protected long mUpdateRate = 1000 / 60; protected boolean mHasStarted; protected boolean mHasEnded; protected boolean mIsPaused; protected List<Animation3DListener> mAnimationListeners = new ArrayList<Animation3DListener>(); protected Timer mTimer; protected ATransformable3D mTransformable3D; protected Animation3D mInstance; protected float mInterpolatedTime; public Animation3D() { mInstance = this; } class UpdateTimeTask extends TimerTask { long millis; float interpolatedTime; long timeInPause; boolean wasPaused = false; boolean firstRun = true; int i, j; public void run() { if(firstRun) { firstRun = false; mStartTime = SystemClock.uptimeMillis(); } if (mIsPaused) { if (!wasPaused) timeInPause = SystemClock.uptimeMillis(); wasPaused = true; return; } else { if (wasPaused) mStartTime += SystemClock.uptimeMillis() - timeInPause; wasPaused = false; } millis = SystemClock.uptimeMillis() - mStartTime; if (millis > mDuration) { if (mRepeatCount == mNumRepeats) { setHasEnded(true); cancel(); for (i = 0, j = mAnimationListeners.size(); i < j; i++) mAnimationListeners.get(i).onAnimationEnd(mInstance); } else { if (mRepeatMode == REVERSE) mDirection *= -1; mStartTime = SystemClock.uptimeMillis(); mNumRepeats++; for (i = 0, j = mAnimationListeners.size(); i < j; i++) mAnimationListeners.get(i).onAnimationRepeat(mInstance); } millis = mDuration; } if (mDirection == -1) { millis = mDuration - millis; } if (millis > mStart && millis < (mStart + mLength)) { float diff = (float) (millis - mStart); interpolatedTime = mInterpolator.getInterpolation(diff / (float) mLength); setHasStarted(true); applyTransformation(interpolatedTime > 1 ? 1 : interpolatedTime < 0 ? 0 : interpolatedTime); for (i = 0, j = mAnimationListeners.size(); i < j; i++) mAnimationListeners.get(i).onAnimationUpdate(mInstance, interpolatedTime); } } } public void cancel() { if (mTimer != null) { TimerManager.getInstance().killTimer(mTimer); } } public void reset() { mStartTime = SystemClock.uptimeMillis(); mNumRepeats = 0; } public void start() { if (mInterpolator == null) mInterpolator = new LinearInterpolator(); reset(); if (mTimer == null) mTimer = TimerManager.getInstance().createNewTimer(); try { mTimer.scheduleAtFixedRate(new UpdateTimeTask(), mDelay, mUpdateRate); } catch (IllegalStateException e) { // timer was cancelled mTimer = TimerManager.getInstance().createNewTimer(); // try once more try { mTimer.scheduleAtFixedRate(new UpdateTimeTask(), mDelay, mUpdateRate); } catch (IllegalStateException ie) { } } for (int i = 0, j = mAnimationListeners.size(); i < j; i++) mAnimationListeners.get(i).onAnimationStart(this); } protected void applyTransformation(float interpolatedTime) { this.mInterpolatedTime = interpolatedTime; } public float getCurrentTime() { return this.mInterpolatedTime; } public ATransformable3D getTransformable3D() { return mTransformable3D; } public void setTransformable3D(ATransformable3D transformable3D) { mTransformable3D = transformable3D; } public void setAnimationListener(Animation3DListener animationListener) { mAnimationListeners.clear(); mAnimationListeners.add(animationListener); } public void addAnimationListener(Animation3DListener animationListener) { mAnimationListeners.add(animationListener); } public void setDuration(long duration) { mDuration = duration; if (mLength < 0) { mLength = mDuration; } if (mStart < 0) { mStart = 0; } } public long getDuration() { return mDuration; } public void setStart(long start) { mStart = start; } public long getStart() { return mStart; } public void setLength(long length) { mLength = length; } public long getLength() { return mLength; } /** * AccelerateDecelerateInterpolator, AccelerateInterpolator, * AnticipateInterpolator, AnticipateOvershootInterpolator, * BounceInterpolator, CycleInterpolator, DecelerateInterpolator, * LinearInterpolator, OvershootInterpolator * * @param interpolator */ public void setInterpolator(Interpolator interpolator) { mInterpolator = interpolator; } public Interpolator getInterpolator() { return mInterpolator; } public void setRepeatCount(int repeatCount) { mRepeatCount = repeatCount; } public int getRepeatCount() { return mRepeatCount; } public void setRepeatMode(int repeatMode) { mRepeatMode = repeatMode; } public int getRepeatMode() { return mRepeatMode; } public boolean isHasStarted() { return mHasStarted; } public void setHasStarted(boolean hasStarted) { this.mHasStarted = hasStarted; } public boolean isHasEnded() { return mHasEnded; } public void setHasEnded(boolean hasEnded) { this.mHasEnded = hasEnded; } public void setPaused(boolean doPause) { mIsPaused = doPause; } public boolean isPaused() { return mIsPaused; } public long getDelay() { return mDelay; } public void setDelay(long delay) { mDelay = delay; } public long getUpdateRate() { return mUpdateRate; } public void setUpdateRate(long updateRate) { this.mUpdateRate = updateRate; } }