1 /* 2 * Copyright (C) 2012 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.gallery3d.anim; 18 19 import android.view.animation.AccelerateInterpolator; 20 import android.view.animation.DecelerateInterpolator; 21 import android.view.animation.Interpolator; 22 23 import com.android.gallery3d.glrenderer.GLCanvas; 24 import com.android.gallery3d.glrenderer.RawTexture; 25 import com.android.gallery3d.ui.GLView; 26 import com.android.gallery3d.ui.TiledScreenNail; 27 28 public class StateTransitionAnimation extends Animation { 29 30 public static class Spec { 31 public static final Spec OUTGOING; 32 public static final Spec INCOMING; 33 public static final Spec PHOTO_INCOMING; 34 35 private static final Interpolator DEFAULT_INTERPOLATOR = 36 new DecelerateInterpolator(); 37 38 public int duration = 330; 39 public float backgroundAlphaFrom = 0; 40 public float backgroundAlphaTo = 0; 41 public float backgroundScaleFrom = 0; 42 public float backgroundScaleTo = 0; 43 public float contentAlphaFrom = 1; 44 public float contentAlphaTo = 1; 45 public float contentScaleFrom = 1; 46 public float contentScaleTo = 1; 47 public float overlayAlphaFrom = 0; 48 public float overlayAlphaTo = 0; 49 public float overlayScaleFrom = 0; 50 public float overlayScaleTo = 0; 51 public Interpolator interpolator = DEFAULT_INTERPOLATOR; 52 53 static { 54 OUTGOING = new Spec(); 55 OUTGOING.backgroundAlphaFrom = 0.5f; 56 OUTGOING.backgroundAlphaTo = 0f; 57 OUTGOING.backgroundScaleFrom = 1f; 58 OUTGOING.backgroundScaleTo = 0f; 59 OUTGOING.contentAlphaFrom = 0.5f; 60 OUTGOING.contentAlphaTo = 1f; 61 OUTGOING.contentScaleFrom = 3f; 62 OUTGOING.contentScaleTo = 1f; 63 64 INCOMING = new Spec(); 65 INCOMING.overlayAlphaFrom = 1f; 66 INCOMING.overlayAlphaTo = 0f; 67 INCOMING.overlayScaleFrom = 1f; 68 INCOMING.overlayScaleTo = 3f; 69 INCOMING.contentAlphaFrom = 0f; 70 INCOMING.contentAlphaTo = 1f; 71 INCOMING.contentScaleFrom = 0.25f; 72 INCOMING.contentScaleTo = 1f; 73 74 PHOTO_INCOMING = INCOMING; 75 } 76 77 private static Spec specForTransition(Transition t) { 78 switch (t) { 79 case Outgoing: 80 return Spec.OUTGOING; 81 case Incoming: 82 return Spec.INCOMING; 83 case PhotoIncoming: 84 return Spec.PHOTO_INCOMING; 85 case None: 86 default: 87 return null; 88 } 89 } 90 } 91 92 public static enum Transition { None, Outgoing, Incoming, PhotoIncoming } 93 94 private final Spec mTransitionSpec; 95 private float mCurrentContentScale; 96 private float mCurrentContentAlpha; 97 private float mCurrentBackgroundScale; 98 private float mCurrentBackgroundAlpha; 99 private float mCurrentOverlayScale; 100 private float mCurrentOverlayAlpha; 101 private RawTexture mOldScreenTexture; 102 103 public StateTransitionAnimation(Transition t, RawTexture oldScreen) { 104 this(Spec.specForTransition(t), oldScreen); 105 } 106 107 public StateTransitionAnimation(Spec spec, RawTexture oldScreen) { 108 mTransitionSpec = spec != null ? spec : Spec.OUTGOING; 109 setDuration(mTransitionSpec.duration); 110 setInterpolator(mTransitionSpec.interpolator); 111 mOldScreenTexture = oldScreen; 112 TiledScreenNail.disableDrawPlaceholder(); 113 } 114 115 @Override 116 public boolean calculate(long currentTimeMillis) { 117 boolean retval = super.calculate(currentTimeMillis); 118 if (!isActive()) { 119 if (mOldScreenTexture != null) { 120 mOldScreenTexture.recycle(); 121 mOldScreenTexture = null; 122 } 123 TiledScreenNail.enableDrawPlaceholder(); 124 } 125 return retval; 126 } 127 128 @Override 129 protected void onCalculate(float progress) { 130 mCurrentContentScale = mTransitionSpec.contentScaleFrom 131 + (mTransitionSpec.contentScaleTo - mTransitionSpec.contentScaleFrom) * progress; 132 mCurrentContentAlpha = mTransitionSpec.contentAlphaFrom 133 + (mTransitionSpec.contentAlphaTo - mTransitionSpec.contentAlphaFrom) * progress; 134 mCurrentBackgroundAlpha = mTransitionSpec.backgroundAlphaFrom 135 + (mTransitionSpec.backgroundAlphaTo - mTransitionSpec.backgroundAlphaFrom) 136 * progress; 137 mCurrentBackgroundScale = mTransitionSpec.backgroundScaleFrom 138 + (mTransitionSpec.backgroundScaleTo - mTransitionSpec.backgroundScaleFrom) 139 * progress; 140 mCurrentOverlayScale = mTransitionSpec.overlayScaleFrom 141 + (mTransitionSpec.overlayScaleTo - mTransitionSpec.overlayScaleFrom) * progress; 142 mCurrentOverlayAlpha = mTransitionSpec.overlayAlphaFrom 143 + (mTransitionSpec.overlayAlphaTo - mTransitionSpec.overlayAlphaFrom) * progress; 144 } 145 146 private void applyOldTexture(GLView view, GLCanvas canvas, float alpha, float scale, boolean clear) { 147 if (mOldScreenTexture == null) 148 return; 149 if (clear) canvas.clearBuffer(view.getBackgroundColor()); 150 canvas.save(); 151 canvas.setAlpha(alpha); 152 int xOffset = view.getWidth() / 2; 153 int yOffset = view.getHeight() / 2; 154 canvas.translate(xOffset, yOffset); 155 canvas.scale(scale, scale, 1); 156 mOldScreenTexture.draw(canvas, -xOffset, -yOffset); 157 canvas.restore(); 158 } 159 160 public void applyBackground(GLView view, GLCanvas canvas) { 161 if (mCurrentBackgroundAlpha > 0f) { 162 applyOldTexture(view, canvas, mCurrentBackgroundAlpha, mCurrentBackgroundScale, true); 163 } 164 } 165 166 public void applyContentTransform(GLView view, GLCanvas canvas) { 167 int xOffset = view.getWidth() / 2; 168 int yOffset = view.getHeight() / 2; 169 canvas.translate(xOffset, yOffset); 170 canvas.scale(mCurrentContentScale, mCurrentContentScale, 1); 171 canvas.translate(-xOffset, -yOffset); 172 canvas.setAlpha(mCurrentContentAlpha); 173 } 174 175 public void applyOverlay(GLView view, GLCanvas canvas) { 176 if (mCurrentOverlayAlpha > 0f) { 177 applyOldTexture(view, canvas, mCurrentOverlayAlpha, mCurrentOverlayScale, false); 178 } 179 } 180 } 181