blob: 2a063362e8aa06b1da53dcfb09c55187f7878f97 [file] [log] [blame]
John Recke45b1fd2014-04-15 09:50:16 -07001/*
2 * Copyright (C) 2014 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
17package android.view;
18
Alan Viverettead2f8e32014-05-16 13:28:33 -070019import android.animation.Animator;
John Reck315c3292014-05-09 19:21:04 -070020import android.animation.TimeInterpolator;
John Reck8d8af3c2014-07-01 15:23:45 -070021import android.animation.ValueAnimator;
John Reck1c058e92014-05-02 14:20:53 -070022import android.graphics.Canvas;
John Reck52244ff2014-05-01 21:27:37 -070023import android.graphics.CanvasProperty;
24import android.graphics.Paint;
John Recke45b1fd2014-04-15 09:50:16 -070025import android.util.SparseIntArray;
26
John Reck9fa40712014-05-09 15:26:59 -070027import com.android.internal.util.VirtualRefBasePtr;
John Reck315c3292014-05-09 19:21:04 -070028import com.android.internal.view.animation.FallbackLUTInterpolator;
29import com.android.internal.view.animation.HasNativeInterpolator;
30import com.android.internal.view.animation.NativeInterpolatorFactory;
John Reck9fa40712014-05-09 15:26:59 -070031
John Recke45b1fd2014-04-15 09:50:16 -070032import java.lang.ref.WeakReference;
Alan Viverettead2f8e32014-05-16 13:28:33 -070033import java.util.ArrayList;
John Recke45b1fd2014-04-15 09:50:16 -070034
35/**
36 * @hide
37 */
John Reck8d8af3c2014-07-01 15:23:45 -070038public class RenderNodeAnimator extends Animator {
John Recke45b1fd2014-04-15 09:50:16 -070039 // Keep in sync with enum RenderProperty in Animator.h
John Reck52244ff2014-05-01 21:27:37 -070040 public static final int TRANSLATION_X = 0;
41 public static final int TRANSLATION_Y = 1;
42 public static final int TRANSLATION_Z = 2;
43 public static final int SCALE_X = 3;
44 public static final int SCALE_Y = 4;
45 public static final int ROTATION = 5;
46 public static final int ROTATION_X = 6;
47 public static final int ROTATION_Y = 7;
48 public static final int X = 8;
49 public static final int Y = 9;
50 public static final int Z = 10;
51 public static final int ALPHA = 11;
John Reck918988c2014-05-19 10:28:35 -070052 // The last value in the enum, used for array size initialization
53 public static final int LAST_VALUE = ALPHA;
John Reck52244ff2014-05-01 21:27:37 -070054
55 // Keep in sync with enum PaintFields in Animator.h
56 public static final int PAINT_STROKE_WIDTH = 0;
Alan Viverettead2f8e32014-05-16 13:28:33 -070057
58 /**
59 * Field for the Paint alpha channel, which should be specified as a value
60 * between 0 and 255.
61 */
John Reck52244ff2014-05-01 21:27:37 -070062 public static final int PAINT_ALPHA = 1;
John Recke45b1fd2014-04-15 09:50:16 -070063
64 // ViewPropertyAnimator uses a mask for its values, we need to remap them
65 // to the enum values here. RenderPropertyAnimator can't use the mask values
66 // directly as internally it uses a lookup table so it needs the values to
67 // be sequential starting from 0
68 private static final SparseIntArray sViewPropertyAnimatorMap = new SparseIntArray(15) {{
69 put(ViewPropertyAnimator.TRANSLATION_X, TRANSLATION_X);
70 put(ViewPropertyAnimator.TRANSLATION_Y, TRANSLATION_Y);
71 put(ViewPropertyAnimator.TRANSLATION_Z, TRANSLATION_Z);
72 put(ViewPropertyAnimator.SCALE_X, SCALE_X);
73 put(ViewPropertyAnimator.SCALE_Y, SCALE_Y);
74 put(ViewPropertyAnimator.ROTATION, ROTATION);
75 put(ViewPropertyAnimator.ROTATION_X, ROTATION_X);
76 put(ViewPropertyAnimator.ROTATION_Y, ROTATION_Y);
77 put(ViewPropertyAnimator.X, X);
78 put(ViewPropertyAnimator.Y, Y);
79 put(ViewPropertyAnimator.Z, Z);
80 put(ViewPropertyAnimator.ALPHA, ALPHA);
81 }};
82
John Reck9fa40712014-05-09 15:26:59 -070083 private VirtualRefBasePtr mNativePtr;
John Recke45b1fd2014-04-15 09:50:16 -070084
John Reck315c3292014-05-09 19:21:04 -070085 private RenderNode mTarget;
Alan Viverettead2f8e32014-05-16 13:28:33 -070086 private View mViewTarget;
John Reck8d8af3c2014-07-01 15:23:45 -070087 private int mRenderProperty = -1;
88 private float mFinalValue;
John Reck315c3292014-05-09 19:21:04 -070089 private TimeInterpolator mInterpolator;
Alan Viverettead2f8e32014-05-16 13:28:33 -070090
John Reck315c3292014-05-09 19:21:04 -070091 private boolean mStarted = false;
Alan Viverettead2f8e32014-05-16 13:28:33 -070092 private boolean mFinished = false;
John Reck315c3292014-05-09 19:21:04 -070093
John Reck8d8af3c2014-07-01 15:23:45 -070094 private long mUnscaledDuration = 300;
95 private long mUnscaledStartDelay = 0;
96
John Reck918988c2014-05-19 10:28:35 -070097 public static int mapViewPropertyToRenderProperty(int viewProperty) {
John Recke45b1fd2014-04-15 09:50:16 -070098 return sViewPropertyAnimatorMap.get(viewProperty);
99 }
100
John Reckff941dc2014-05-14 16:34:14 -0700101 public RenderNodeAnimator(int property, float finalValue) {
John Reck8d8af3c2014-07-01 15:23:45 -0700102 mRenderProperty = property;
103 mFinalValue = finalValue;
John Reck9fa40712014-05-09 15:26:59 -0700104 init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this),
John Reckff941dc2014-05-14 16:34:14 -0700105 property, finalValue));
John Recke45b1fd2014-04-15 09:50:16 -0700106 }
107
John Reckff941dc2014-05-14 16:34:14 -0700108 public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) {
John Reck9fa40712014-05-09 15:26:59 -0700109 init(nCreateCanvasPropertyFloatAnimator(
John Reck52244ff2014-05-01 21:27:37 -0700110 new WeakReference<RenderNodeAnimator>(this),
John Reckff941dc2014-05-14 16:34:14 -0700111 property.getNativeContainer(), finalValue));
John Reck52244ff2014-05-01 21:27:37 -0700112 }
113
Alan Viverettead2f8e32014-05-16 13:28:33 -0700114 /**
115 * Creates a new render node animator for a field on a Paint property.
116 *
117 * @param property The paint property to target
118 * @param paintField Paint field to animate, one of {@link #PAINT_ALPHA} or
119 * {@link #PAINT_STROKE_WIDTH}
120 * @param finalValue The target value for the property
121 */
John Reckff941dc2014-05-14 16:34:14 -0700122 public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, float finalValue) {
John Reck9fa40712014-05-09 15:26:59 -0700123 init(nCreateCanvasPropertyPaintAnimator(
John Reck52244ff2014-05-01 21:27:37 -0700124 new WeakReference<RenderNodeAnimator>(this),
John Reckff941dc2014-05-14 16:34:14 -0700125 property.getNativeContainer(), paintField, finalValue));
John Reck9fa40712014-05-09 15:26:59 -0700126 }
127
John Reckd3de42c2014-07-15 14:29:33 -0700128 public RenderNodeAnimator(int x, int y, boolean inverseClip,
129 float startRadius, float endRadius) {
130 init(nCreateRevealAnimator(new WeakReference<>(this),
131 x, y, inverseClip, startRadius, endRadius));
132 }
133
John Reck9fa40712014-05-09 15:26:59 -0700134 private void init(long ptr) {
135 mNativePtr = new VirtualRefBasePtr(ptr);
John Reck52244ff2014-05-01 21:27:37 -0700136 }
137
John Reck315c3292014-05-09 19:21:04 -0700138 private void checkMutable() {
139 if (mStarted) {
140 throw new IllegalStateException("Animator has already started, cannot change it now!");
141 }
142 }
143
John Reck918988c2014-05-19 10:28:35 -0700144 static boolean isNativeInterpolator(TimeInterpolator interpolator) {
145 return interpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class);
146 }
147
John Reck315c3292014-05-09 19:21:04 -0700148 private void applyInterpolator() {
149 if (mInterpolator == null) return;
150
151 long ni;
John Reck918988c2014-05-19 10:28:35 -0700152 if (isNativeInterpolator(mInterpolator)) {
John Reck315c3292014-05-09 19:21:04 -0700153 ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator();
154 } else {
Alan Viverettead2f8e32014-05-16 13:28:33 -0700155 long duration = nGetDuration(mNativePtr.get());
John Reck315c3292014-05-09 19:21:04 -0700156 ni = FallbackLUTInterpolator.createNativeInterpolator(mInterpolator, duration);
157 }
158 nSetInterpolator(mNativePtr.get(), ni);
159 }
160
Alan Viverettead2f8e32014-05-16 13:28:33 -0700161 @Override
162 public void start() {
163 if (mTarget == null) {
164 throw new IllegalStateException("Missing target!");
165 }
166
John Reck315c3292014-05-09 19:21:04 -0700167 if (mStarted) {
168 throw new IllegalStateException("Already started!");
169 }
Alan Viverettead2f8e32014-05-16 13:28:33 -0700170
John Reck315c3292014-05-09 19:21:04 -0700171 mStarted = true;
172 applyInterpolator();
John Reck8d8af3c2014-07-01 15:23:45 -0700173 nStart(mNativePtr.get());
174
175 // Alpha is a special snowflake that has the canonical value stored
176 // in mTransformationInfo instead of in RenderNode, so we need to update
177 // it with the final value here.
178 if (mRenderProperty == RenderNodeAnimator.ALPHA) {
179 // Don't need null check because ViewPropertyAnimator's
180 // ctor calls ensureTransformationInfo()
181 mViewTarget.mTransformationInfo.mAlpha = mFinalValue;
182 }
Alan Viverettead2f8e32014-05-16 13:28:33 -0700183
184 final ArrayList<AnimatorListener> listeners = getListeners();
185 final int numListeners = listeners == null ? 0 : listeners.size();
186 for (int i = 0; i < numListeners; i++) {
187 listeners.get(i).onAnimationStart(this);
188 }
189
190 if (mViewTarget != null) {
191 // Kick off a frame to start the process
192 mViewTarget.invalidateViewProperty(true, false);
193 }
John Reck315c3292014-05-09 19:21:04 -0700194 }
195
Alan Viverettead2f8e32014-05-16 13:28:33 -0700196 @Override
197 public void cancel() {
John Reck68bfe0a2014-06-24 15:34:58 -0700198 if (!mFinished) {
John Reckd3de42c2014-07-15 14:29:33 -0700199 nEnd(mNativePtr.get());
Alan Viverettead2f8e32014-05-16 13:28:33 -0700200
John Reck68bfe0a2014-06-24 15:34:58 -0700201 final ArrayList<AnimatorListener> listeners = getListeners();
202 final int numListeners = listeners == null ? 0 : listeners.size();
203 for (int i = 0; i < numListeners; i++) {
204 listeners.get(i).onAnimationCancel(this);
205 }
Alan Viverettead2f8e32014-05-16 13:28:33 -0700206 }
John Recke45b1fd2014-04-15 09:50:16 -0700207 }
208
Alan Viverettead2f8e32014-05-16 13:28:33 -0700209 @Override
210 public void end() {
John Reckd3de42c2014-07-15 14:29:33 -0700211 if (!mFinished) {
212 nEnd(mNativePtr.get());
213 }
Alan Viverettead2f8e32014-05-16 13:28:33 -0700214 }
215
216 @Override
217 public void pause() {
218 throw new UnsupportedOperationException();
219 }
220
221 @Override
222 public void resume() {
223 throw new UnsupportedOperationException();
224 }
225
226 public void setTarget(View view) {
227 mViewTarget = view;
228 mTarget = view.mRenderNode;
John Reck8d8af3c2014-07-01 15:23:45 -0700229 mTarget.addAnimator(this);
Alan Viverettead2f8e32014-05-16 13:28:33 -0700230 }
231
232 public void setTarget(Canvas canvas) {
John Reck1c058e92014-05-02 14:20:53 -0700233 if (!(canvas instanceof GLES20RecordingCanvas)) {
234 throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
235 }
Alan Viverettead2f8e32014-05-16 13:28:33 -0700236
237 final GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
238 setTarget(recordingCanvas.mNode);
John Reck1c058e92014-05-02 14:20:53 -0700239 }
240
Alan Viverettead2f8e32014-05-16 13:28:33 -0700241 public void setTarget(RenderNode node) {
John Reck8d8af3c2014-07-01 15:23:45 -0700242 if (mTarget != null) {
243 throw new IllegalStateException("Target already set!");
244 }
Alan Viverettead2f8e32014-05-16 13:28:33 -0700245 mViewTarget = null;
246 mTarget = node;
John Reck8d8af3c2014-07-01 15:23:45 -0700247 mTarget.addAnimator(this);
Alan Viverettead2f8e32014-05-16 13:28:33 -0700248 }
249
John Reckc6b32642014-06-02 11:00:09 -0700250 public void setStartValue(float startValue) {
251 checkMutable();
252 nSetStartValue(mNativePtr.get(), startValue);
253 }
254
Alan Viverettead2f8e32014-05-16 13:28:33 -0700255 @Override
256 public void setStartDelay(long startDelay) {
257 checkMutable();
John Reck68bfe0a2014-06-24 15:34:58 -0700258 if (startDelay < 0) {
259 throw new IllegalArgumentException("startDelay must be positive; " + startDelay);
260 }
John Reck8d8af3c2014-07-01 15:23:45 -0700261 mUnscaledStartDelay = startDelay;
262 nSetStartDelay(mNativePtr.get(), (long) (startDelay * ValueAnimator.getDurationScale()));
Alan Viverettead2f8e32014-05-16 13:28:33 -0700263 }
264
265 @Override
266 public long getStartDelay() {
John Reck8d8af3c2014-07-01 15:23:45 -0700267 return mUnscaledStartDelay;
Alan Viverettead2f8e32014-05-16 13:28:33 -0700268 }
269
270 @Override
271 public RenderNodeAnimator setDuration(long duration) {
John Reck315c3292014-05-09 19:21:04 -0700272 checkMutable();
John Reck68bfe0a2014-06-24 15:34:58 -0700273 if (duration < 0) {
274 throw new IllegalArgumentException("duration must be positive; " + duration);
275 }
John Reck8d8af3c2014-07-01 15:23:45 -0700276 mUnscaledDuration = duration;
277 nSetDuration(mNativePtr.get(), (long) (duration * ValueAnimator.getDurationScale()));
Alan Viverettead2f8e32014-05-16 13:28:33 -0700278 return this;
John Recke45b1fd2014-04-15 09:50:16 -0700279 }
280
Alan Viverettead2f8e32014-05-16 13:28:33 -0700281 @Override
282 public long getDuration() {
John Reck8d8af3c2014-07-01 15:23:45 -0700283 return mUnscaledDuration;
Alan Viverettead2f8e32014-05-16 13:28:33 -0700284 }
285
286 @Override
287 public boolean isRunning() {
288 return mStarted && !mFinished;
289 }
290
291 @Override
John Reckd3de42c2014-07-15 14:29:33 -0700292 public boolean isStarted() {
293 return mStarted;
294 }
295
296 @Override
John Reck315c3292014-05-09 19:21:04 -0700297 public void setInterpolator(TimeInterpolator interpolator) {
298 checkMutable();
299 mInterpolator = interpolator;
300 }
301
Alan Viverettead2f8e32014-05-16 13:28:33 -0700302 @Override
303 public TimeInterpolator getInterpolator() {
304 return mInterpolator;
John Recke45b1fd2014-04-15 09:50:16 -0700305 }
306
307 private void onFinished() {
Alan Viverettead2f8e32014-05-16 13:28:33 -0700308 mFinished = true;
Alan Viverettead2f8e32014-05-16 13:28:33 -0700309
310 final ArrayList<AnimatorListener> listeners = getListeners();
311 final int numListeners = listeners == null ? 0 : listeners.size();
312 for (int i = 0; i < numListeners; i++) {
313 listeners.get(i).onAnimationEnd(this);
314 }
315 }
316
317 long getNativeAnimator() {
318 return mNativePtr.get();
John Recke45b1fd2014-04-15 09:50:16 -0700319 }
320
321 // Called by native
322 private static void callOnFinished(WeakReference<RenderNodeAnimator> weakThis) {
323 RenderNodeAnimator animator = weakThis.get();
324 if (animator != null) {
325 animator.onFinished();
326 }
327 }
328
John Recke45b1fd2014-04-15 09:50:16 -0700329 private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
John Reckc6b32642014-06-02 11:00:09 -0700330 int property, float finalValue);
John Reck52244ff2014-05-01 21:27:37 -0700331 private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
John Reckc6b32642014-06-02 11:00:09 -0700332 long canvasProperty, float finalValue);
John Reck52244ff2014-05-01 21:27:37 -0700333 private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
John Reckc6b32642014-06-02 11:00:09 -0700334 long canvasProperty, int paintField, float finalValue);
John Reckd3de42c2014-07-15 14:29:33 -0700335 private static native long nCreateRevealAnimator(WeakReference<RenderNodeAnimator> weakThis,
336 int x, int y, boolean inverseClip, float startRadius, float endRadius);
John Reck68bfe0a2014-06-24 15:34:58 -0700337
John Reckc6b32642014-06-02 11:00:09 -0700338 private static native void nSetStartValue(long nativePtr, float startValue);
Alan Viverettead2f8e32014-05-16 13:28:33 -0700339 private static native void nSetDuration(long nativePtr, long duration);
340 private static native long nGetDuration(long nativePtr);
341 private static native void nSetStartDelay(long nativePtr, long startDelay);
342 private static native long nGetStartDelay(long nativePtr);
John Reck315c3292014-05-09 19:21:04 -0700343 private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
John Reck68bfe0a2014-06-24 15:34:58 -0700344
John Reck8d8af3c2014-07-01 15:23:45 -0700345 private static native void nStart(long animPtr);
John Reckd3de42c2014-07-15 14:29:33 -0700346 private static native void nEnd(long animPtr);
John Recke45b1fd2014-04-15 09:50:16 -0700347}