/* * Copyright (C) 2013 Fairphone Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fairphone.oobe.utils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import android.view.animation.Interpolator; public class KWAnimation { public interface KWAnimationListener { public void onAnimationStart(KWAnimation animation); public void onAnimationUpdate(KWAnimation animation, float curAnimationProgress); public void onAnimationEnd(KWAnimation animation); } public enum KWValueType { X,Y,Rotation,Scale,ScaleX,ScaleY,PivotX,PivotY, Alpha, Width,Height }; public static class KWValueAnimation { KWValueType type; ArrayList<KWKeyframe> keyframes = new ArrayList<KWAnimation.KWKeyframe>(); long duration = 0; KWValueAnimation(KWValueType type) { this.type = type; } public KWValueAnimation addKeyframe(float value, long time, Interpolator interpolator) { if(time>duration) { duration = time; } keyframes.add(new KWKeyframe(time,value,interpolator)); Collections.sort(keyframes,new KWKeyComparator()); return this; } public float getValueAt(long time) { if(keyframes.isEmpty()) { return 0; } int key=0; for(int i=0;i<keyframes.size();i++) { key = i; if(keyframes.get(i).time>time) { break; } } KWKeyframe keyA = keyframes.get(key); KWKeyframe keyB = keyframes.get(key); if(key>0) { keyA = keyframes.get(key-1); } float ratio = KWMathUtils.getLongRatio(keyA.time, keyB.time, time); if(keyB.interpolator!=null) { ratio = keyB.interpolator.getInterpolation(ratio); } float val = keyA.value+(keyB.value-keyA.value)*ratio; return val; } public void applyValueAt(long time, KWSprite sprite) { switch(type) { case X: { sprite.x = getValueAt(time); } break; case Y: { sprite.y = getValueAt(time); } break; case Rotation: { sprite.rotation = getValueAt(time); } break; case Scale: { sprite.scaleX = getValueAt(time); sprite.scaleY = sprite.scaleX; } break; case ScaleX: { sprite.scaleX = getValueAt(time); } break; case ScaleY: { sprite.scaleY = getValueAt(time); } break; case PivotX: { sprite.pivotX = getValueAt(time); } break; case PivotY: { sprite.pivotY = getValueAt(time); } break; case Alpha: { sprite.alpha = getValueAt(time); } break; case Width: { sprite.width = getValueAt(time); } break; case Height: { sprite.height = getValueAt(time); } break; } } } private static class KWKeyComparator implements Comparator<KWKeyframe> { @Override public int compare(KWKeyframe lhs, KWKeyframe rhs) { long dif = (lhs.time-rhs.time); return dif>0?1:dif<0?-1:0; } } private static class KWKeyframe { long time; float value; Interpolator interpolator; private KWKeyframe(long time, float value, Interpolator interpolator) { this.time = time; this.value = value; this.interpolator = interpolator; } } private long curAnimTime=0; private boolean isRunning = false; private LinkedList<KWValueAnimation> animations = new LinkedList<KWAnimation.KWValueAnimation>(); private KWAnimationListener listener; private KWSprite sprite; public KWAnimation(KWSprite animatedSprite) { curAnimTime=0; this.sprite = animatedSprite; } public KWValueAnimation addValueAnimation(KWValueType type) { KWValueAnimation anim = new KWValueAnimation(type); animations.add(anim); return anim; } public void setAnimationListener(KWAnimationListener listener) { this.listener = listener; } public KWSprite getSprite() { return sprite; } public boolean isRunning() { return isRunning; } public long getCurAnimTime() { return curAnimTime; } public void start() { isRunning = true; curAnimTime=0; if(listener!=null) { listener.onAnimationStart(this); } } public void pause() { isRunning = false; } public void unpause() { isRunning = true; } public void stop() { reset(); isRunning = false; } public void reset() { curAnimTime = 0; } public void update(long dt) { if(isRunning) { curAnimTime+=dt; long maxDuration = 0; for(KWValueAnimation anim: animations) { anim.applyValueAt(curAnimTime, sprite); if(anim.duration>maxDuration) { maxDuration = anim.duration; } } if(curAnimTime>=maxDuration) { curAnimTime = maxDuration; isRunning = false; if(listener!=null) { listener.onAnimationEnd(this); } } else { if(listener!=null) { float curAnimationProgress = KWMathUtils.getLongRatio(0, maxDuration, curAnimTime); listener.onAnimationUpdate(this, curAnimationProgress); } } } } }