Home | History | Annotate | Download | only in animation
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.photoeditor.animation;
     18 
     19 import android.graphics.Camera;
     20 import android.graphics.Matrix;
     21 import android.view.animation.AccelerateInterpolator;
     22 import android.view.animation.Animation;
     23 import android.view.animation.DecelerateInterpolator;
     24 import android.view.animation.Transformation;
     25 
     26 /**
     27  * Rotation animation that rotates a 2D view 90 degrees on either X or Y axis in 3D space. The
     28  * rotation is performed around the view center point by its defined rotation direction and position
     29  * it will start from or end to. The rotation duration can be specified as well as whether the
     30  * rotation should be accelerated or decelerated in time.
     31  */
     32 public class Rotate3DAnimation extends Animation {
     33 
     34     public enum Rotate {
     35         UP, DOWN, LEFT, RIGHT
     36     }
     37 
     38     private enum Angle {
     39         FROM_DEGREES_0, TO_DEGREES_0
     40     }
     41 
     42     private static final float DEPTH_Z = 250.0f;
     43     private static final float ROTATE_DEGREES = 90f;
     44 
     45     private final Rotate rotate;
     46     private final Angle angle;
     47     private final int duration;
     48     private final boolean accelerate;
     49 
     50     private Camera camera;
     51     private float centerX;
     52     private float centerY;
     53     private float fromDegrees;
     54     private float toDegrees;
     55 
     56     /**
     57      * Gets animations that flip the view by 3D rotations.
     58      */
     59     public static AnimationPair getFlipAnimations(Rotate rotate, int duration) {
     60         return new AnimationPair(
     61                 new Rotate3DAnimation(rotate, Angle.FROM_DEGREES_0, duration, true),
     62                 new Rotate3DAnimation(rotate, Angle.TO_DEGREES_0, duration, false));
     63     }
     64 
     65     private Rotate3DAnimation(Rotate rotate, Angle angle, int duration, boolean accelerate) {
     66         this.rotate = rotate;
     67         this.angle = angle;
     68         this.duration = duration;
     69         this.accelerate = accelerate;
     70     }
     71 
     72     @Override
     73     public void initialize(int width, int height, int parentWidth, int parentHeight) {
     74         super.initialize(width, height, parentWidth, parentHeight);
     75         super.setDuration(duration);
     76         super.setInterpolator(
     77                 accelerate ? new AccelerateInterpolator() : new DecelerateInterpolator());
     78 
     79         camera = new Camera();
     80         centerX = width / 2.0f;
     81         centerY = height / 2.0f;
     82 
     83         if (angle == Angle.FROM_DEGREES_0) {
     84             fromDegrees = 0;
     85 
     86             switch (rotate) {
     87                 case RIGHT:
     88                 case UP:
     89                     toDegrees = ROTATE_DEGREES;
     90                     break;
     91 
     92                 case LEFT:
     93                 case DOWN:
     94                     toDegrees = -ROTATE_DEGREES;
     95                     break;
     96             }
     97         } else if (angle == Angle.TO_DEGREES_0) {
     98             toDegrees = 0;
     99 
    100             switch (rotate) {
    101                 case RIGHT:
    102                 case UP:
    103                     fromDegrees = -ROTATE_DEGREES;
    104                     break;
    105 
    106                 case LEFT:
    107                 case DOWN:
    108                     fromDegrees = ROTATE_DEGREES;
    109                     break;
    110             }
    111         }
    112     }
    113 
    114     @Override
    115     protected void applyTransformation(float interpolatedTime, Transformation t) {
    116         camera.save();
    117 
    118         if (angle == Angle.FROM_DEGREES_0) {
    119             camera.translate(0.0f, 0.0f, DEPTH_Z * interpolatedTime);
    120         } else if (angle == Angle.TO_DEGREES_0) {
    121             camera.translate(0.0f, 0.0f, DEPTH_Z * (1.0f - interpolatedTime));
    122         }
    123 
    124         float degrees = fromDegrees + ((toDegrees - fromDegrees) * interpolatedTime);
    125         switch (rotate) {
    126             case RIGHT:
    127             case LEFT:
    128                 camera.rotateY(degrees);
    129                 break;
    130 
    131             case UP:
    132             case DOWN:
    133                 camera.rotateX(degrees);
    134                 break;
    135         }
    136 
    137         final Matrix matrix = t.getMatrix();
    138         camera.getMatrix(matrix);
    139         camera.restore();
    140 
    141         matrix.preTranslate(-centerX, -centerY);
    142         matrix.postTranslate(centerX, centerY);
    143     }
    144 }
    145