blob: 7bd2b24bf56bba660653306d0fd17d9050e91159 [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
John Recke45b1fd2014-04-15 09:50:16 -070017#include "Animator.h"
18
John Reck68bfe0a2014-06-24 15:34:58 -070019#include <inttypes.h>
John Recke45b1fd2014-04-15 09:50:16 -070020#include <set>
21
John Reck119907c2014-08-14 09:02:01 -070022#include "AnimationContext.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040023#include "Interpolator.h"
John Reck52244ff2014-05-01 21:27:37 -070024#include "RenderNode.h"
John Recke45b1fd2014-04-15 09:50:16 -070025#include "RenderProperties.h"
26
27namespace android {
28namespace uirenderer {
29
30/************************************************************
John Reckff941dc2014-05-14 16:34:14 -070031 * BaseRenderNodeAnimator
John Recke45b1fd2014-04-15 09:50:16 -070032 ************************************************************/
33
John Reckff941dc2014-05-14 16:34:14 -070034BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
Chris Craikd41c4d82015-01-05 15:51:13 -080035 : mTarget(nullptr)
John Reck8d8af3c2014-07-01 15:23:45 -070036 , mFinalValue(finalValue)
John Reckff941dc2014-05-14 16:34:14 -070037 , mDeltaValue(0)
38 , mFromValue(0)
Chris Craikb9ce116d2015-08-20 15:14:06 -070039 , mStagingPlayState(PlayState::NotStarted)
40 , mPlayState(PlayState::NotStarted)
John Reck68bfe0a2014-06-24 15:34:58 -070041 , mHasStartValue(false)
John Recke45b1fd2014-04-15 09:50:16 -070042 , mStartTime(0)
Alan Viverettead2f8e32014-05-16 13:28:33 -070043 , mDuration(300)
Chris Craik572d9ac2014-09-12 17:40:20 -070044 , mStartDelay(0)
45 , mMayRunAsync(true) {
John Recke45b1fd2014-04-15 09:50:16 -070046}
47
John Reckff941dc2014-05-14 16:34:14 -070048BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
John Reck68bfe0a2014-06-24 15:34:58 -070049}
50
51void BaseRenderNodeAnimator::checkMutable() {
52 // Should be impossible to hit as the Java-side also has guards for this
Chris Craikb9ce116d2015-08-20 15:14:06 -070053 LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted,
John Reck68bfe0a2014-06-24 15:34:58 -070054 "Animator has already been started!");
John Recke45b1fd2014-04-15 09:50:16 -070055}
56
John Reckff941dc2014-05-14 16:34:14 -070057void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
John Reck68bfe0a2014-06-24 15:34:58 -070058 checkMutable();
Chris Craik51d6a3d2014-12-22 17:16:56 -080059 mInterpolator.reset(interpolator);
John Recke45b1fd2014-04-15 09:50:16 -070060}
61
John Reckff941dc2014-05-14 16:34:14 -070062void BaseRenderNodeAnimator::setStartValue(float value) {
John Reck68bfe0a2014-06-24 15:34:58 -070063 checkMutable();
64 doSetStartValue(value);
John Reckff941dc2014-05-14 16:34:14 -070065}
66
John Reck68bfe0a2014-06-24 15:34:58 -070067void BaseRenderNodeAnimator::doSetStartValue(float value) {
68 mFromValue = value;
69 mDeltaValue = (mFinalValue - mFromValue);
70 mHasStartValue = true;
John Reckff941dc2014-05-14 16:34:14 -070071}
72
Alan Viverettead2f8e32014-05-16 13:28:33 -070073void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
John Reck68bfe0a2014-06-24 15:34:58 -070074 checkMutable();
Alan Viverettead2f8e32014-05-16 13:28:33 -070075 mDuration = duration;
76}
77
78void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) {
John Reck68bfe0a2014-06-24 15:34:58 -070079 checkMutable();
Alan Viverettead2f8e32014-05-16 13:28:33 -070080 mStartDelay = startDelay;
81}
82
John Reck8d8af3c2014-07-01 15:23:45 -070083void BaseRenderNodeAnimator::attach(RenderNode* target) {
84 mTarget = target;
85 onAttached();
86}
87
John Reck119907c2014-08-14 09:02:01 -070088void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
John Reck68bfe0a2014-06-24 15:34:58 -070089 if (!mHasStartValue) {
John Reck8d8af3c2014-07-01 15:23:45 -070090 doSetStartValue(getValue(mTarget));
Alan Viverettead2f8e32014-05-16 13:28:33 -070091 }
John Reck68bfe0a2014-06-24 15:34:58 -070092 if (mStagingPlayState > mPlayState) {
Doris Liu766431a2016-02-04 22:17:11 +000093 if (mStagingPlayState == PlayState::Restarted) {
94 mStagingPlayState = PlayState::Running;
95 }
John Reck68bfe0a2014-06-24 15:34:58 -070096 mPlayState = mStagingPlayState;
97 // Oh boy, we're starting! Man the battle stations!
Chris Craikb9ce116d2015-08-20 15:14:06 -070098 if (mPlayState == PlayState::Running) {
John Reck119907c2014-08-14 09:02:01 -070099 transitionToRunning(context);
Chris Craikb9ce116d2015-08-20 15:14:06 -0700100 } else if (mPlayState == PlayState::Finished) {
John Reck4d2c4722014-08-29 10:40:56 -0700101 callOnFinishedListener(context);
John Recke45b1fd2014-04-15 09:50:16 -0700102 }
John Recke45b1fd2014-04-15 09:50:16 -0700103 }
John Reck68bfe0a2014-06-24 15:34:58 -0700104}
105
John Reck119907c2014-08-14 09:02:01 -0700106void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
107 nsecs_t frameTimeMs = context.frameTimeMs();
108 LOG_ALWAYS_FATAL_IF(frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", frameTimeMs);
John Reck68bfe0a2014-06-24 15:34:58 -0700109 if (mStartDelay < 0 || mStartDelay > 50000) {
110 ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
111 }
John Reck119907c2014-08-14 09:02:01 -0700112 mStartTime = frameTimeMs + mStartDelay;
John Reck68bfe0a2014-06-24 15:34:58 -0700113 if (mStartTime < 0) {
114 ALOGW("Ended up with a really weird start time of %" PRId64
115 " with frame time %" PRId64 " and start delay %" PRId64,
John Reck119907c2014-08-14 09:02:01 -0700116 mStartTime, frameTimeMs, mStartDelay);
John Reck68bfe0a2014-06-24 15:34:58 -0700117 // Set to 0 so that the animate() basically instantly finishes
118 mStartTime = 0;
119 }
120 // No interpolator was set, use the default
121 if (!mInterpolator) {
Chris Craik51d6a3d2014-12-22 17:16:56 -0800122 mInterpolator.reset(Interpolator::createDefaultInterpolator());
John Reck68bfe0a2014-06-24 15:34:58 -0700123 }
124 if (mDuration < 0 || mDuration > 50000) {
125 ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
126 }
127}
128
John Reck119907c2014-08-14 09:02:01 -0700129bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700130 if (mPlayState < PlayState::Running) {
John Reck68bfe0a2014-06-24 15:34:58 -0700131 return false;
132 }
Chris Craikb9ce116d2015-08-20 15:14:06 -0700133 if (mPlayState == PlayState::Finished) {
John Reck32fb6302014-07-07 09:50:32 -0700134 return true;
135 }
John Reck68bfe0a2014-06-24 15:34:58 -0700136
Doris Liu766431a2016-02-04 22:17:11 +0000137 // This should be set before setValue() so animators can query this time when setValue
138 // is called.
139 nsecs_t currentFrameTime = context.frameTimeMs();
140 onPlayTimeChanged(currentFrameTime - mStartTime);
141
John Reck8d8af3c2014-07-01 15:23:45 -0700142 // If BaseRenderNodeAnimator is handling the delay (not typical), then
143 // because the staging properties reflect the final value, we always need
144 // to call setValue even if the animation isn't yet running or is still
145 // being delayed as we need to override the staging value
John Reck119907c2014-08-14 09:02:01 -0700146 if (mStartTime > context.frameTimeMs()) {
John Reck8d8af3c2014-07-01 15:23:45 -0700147 setValue(mTarget, mFromValue);
John Reck68bfe0a2014-06-24 15:34:58 -0700148 return false;
149 }
John Recke45b1fd2014-04-15 09:50:16 -0700150
151 float fraction = 1.0f;
Doris Liu766431a2016-02-04 22:17:11 +0000152
Chris Craikb9ce116d2015-08-20 15:14:06 -0700153 if (mPlayState == PlayState::Running && mDuration > 0) {
Doris Liu766431a2016-02-04 22:17:11 +0000154 fraction = (float)(currentFrameTime - mStartTime) / mDuration;
John Recke45b1fd2014-04-15 09:50:16 -0700155 }
John Reck68bfe0a2014-06-24 15:34:58 -0700156 if (fraction >= 1.0f) {
157 fraction = 1.0f;
Chris Craikb9ce116d2015-08-20 15:14:06 -0700158 mPlayState = PlayState::Finished;
John Reck68bfe0a2014-06-24 15:34:58 -0700159 }
160
John Recke45b1fd2014-04-15 09:50:16 -0700161 fraction = mInterpolator->interpolate(fraction);
John Reck8d8af3c2014-07-01 15:23:45 -0700162 setValue(mTarget, mFromValue + (mDeltaValue * fraction));
John Recke45b1fd2014-04-15 09:50:16 -0700163
Chris Craikb9ce116d2015-08-20 15:14:06 -0700164 if (mPlayState == PlayState::Finished) {
John Reck119907c2014-08-14 09:02:01 -0700165 callOnFinishedListener(context);
John Recke45b1fd2014-04-15 09:50:16 -0700166 return true;
167 }
John Reck68bfe0a2014-06-24 15:34:58 -0700168
John Recke45b1fd2014-04-15 09:50:16 -0700169 return false;
170}
171
John Recke2478d42014-09-03 16:46:05 -0700172void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700173 if (mPlayState < PlayState::Finished) {
174 mPlayState = PlayState::Finished;
John Recke2478d42014-09-03 16:46:05 -0700175 callOnFinishedListener(context);
176 }
177}
178
John Reck119907c2014-08-14 09:02:01 -0700179void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
John Reck52244ff2014-05-01 21:27:37 -0700180 if (mListener.get()) {
John Reck119907c2014-08-14 09:02:01 -0700181 context.callOnFinished(this, mListener.get());
John Reck52244ff2014-05-01 21:27:37 -0700182 }
183}
184
185/************************************************************
John Recke45b1fd2014-04-15 09:50:16 -0700186 * RenderPropertyAnimator
187 ************************************************************/
188
John Reckff941dc2014-05-14 16:34:14 -0700189struct RenderPropertyAnimator::PropertyAccessors {
190 RenderNode::DirtyPropertyMask dirtyMask;
191 GetFloatProperty getter;
192 SetFloatProperty setter;
John Reck52244ff2014-05-01 21:27:37 -0700193};
194
John Reckff941dc2014-05-14 16:34:14 -0700195// Maps RenderProperty enum to accessors
196const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
197 {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
198 {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
199 {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
200 {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX },
201 {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY },
202 {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation },
203 {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX },
204 {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY },
205 {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX },
206 {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY },
207 {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ },
208 {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha },
209};
210
211RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
212 : BaseRenderNodeAnimator(finalValue)
213 , mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {
John Recke45b1fd2014-04-15 09:50:16 -0700214}
215
John Reck8d8af3c2014-07-01 15:23:45 -0700216void RenderPropertyAnimator::onAttached() {
John Reck68bfe0a2014-06-24 15:34:58 -0700217 if (!mHasStartValue
John Reck8d8af3c2014-07-01 15:23:45 -0700218 && mTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
219 setStartValue((mTarget->stagingProperties().*mPropertyAccess->getter)());
John Reckff941dc2014-05-14 16:34:14 -0700220 }
John Reck8d8af3c2014-07-01 15:23:45 -0700221}
222
223void RenderPropertyAnimator::onStagingPlayStateChanged() {
Chris Craikb9ce116d2015-08-20 15:14:06 -0700224 if (mStagingPlayState == PlayState::Running) {
John Reck8d8af3c2014-07-01 15:23:45 -0700225 (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
Chris Craikb9ce116d2015-08-20 15:14:06 -0700226 } else if (mStagingPlayState == PlayState::Finished) {
John Reck32fb6302014-07-07 09:50:32 -0700227 // We're being canceled, so make sure that whatever values the UI thread
228 // is observing for us is pushed over
229 mTarget->setPropertyFieldsDirty(dirtyMask());
John Reck8d8af3c2014-07-01 15:23:45 -0700230 }
John Recke45b1fd2014-04-15 09:50:16 -0700231}
232
John Reck22184722014-06-20 07:19:30 -0700233uint32_t RenderPropertyAnimator::dirtyMask() {
234 return mPropertyAccess->dirtyMask;
235}
236
John Reckff941dc2014-05-14 16:34:14 -0700237float RenderPropertyAnimator::getValue(RenderNode* target) const {
238 return (target->properties().*mPropertyAccess->getter)();
239}
240
241void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
242 (target->animatorProperties().*mPropertyAccess->setter)(value);
John Recke45b1fd2014-04-15 09:50:16 -0700243}
244
John Reck52244ff2014-05-01 21:27:37 -0700245/************************************************************
246 * CanvasPropertyPrimitiveAnimator
247 ************************************************************/
John Recke45b1fd2014-04-15 09:50:16 -0700248
John Reck52244ff2014-05-01 21:27:37 -0700249CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
John Reckff941dc2014-05-14 16:34:14 -0700250 CanvasPropertyPrimitive* property, float finalValue)
251 : BaseRenderNodeAnimator(finalValue)
John Reck52244ff2014-05-01 21:27:37 -0700252 , mProperty(property) {
253}
254
Andreas Gampe64bb4132014-11-22 00:35:09 +0000255float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
John Reck52244ff2014-05-01 21:27:37 -0700256 return mProperty->value;
257}
258
Andreas Gampe64bb4132014-11-22 00:35:09 +0000259void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) {
John Reck52244ff2014-05-01 21:27:37 -0700260 mProperty->value = value;
261}
262
John Recka7c2ea22014-08-08 13:21:00 -0700263uint32_t CanvasPropertyPrimitiveAnimator::dirtyMask() {
264 return RenderNode::DISPLAY_LIST;
265}
266
John Reck52244ff2014-05-01 21:27:37 -0700267/************************************************************
268 * CanvasPropertySkPaintAnimator
269 ************************************************************/
270
271CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
John Reckff941dc2014-05-14 16:34:14 -0700272 CanvasPropertyPaint* property, PaintField field, float finalValue)
273 : BaseRenderNodeAnimator(finalValue)
John Reck52244ff2014-05-01 21:27:37 -0700274 , mProperty(property)
275 , mField(field) {
276}
277
Andreas Gampe64bb4132014-11-22 00:35:09 +0000278float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
John Reck52244ff2014-05-01 21:27:37 -0700279 switch (mField) {
280 case STROKE_WIDTH:
281 return mProperty->value.getStrokeWidth();
282 case ALPHA:
283 return mProperty->value.getAlpha();
John Recke45b1fd2014-04-15 09:50:16 -0700284 }
John Reck52244ff2014-05-01 21:27:37 -0700285 LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
286 return -1;
John Recke45b1fd2014-04-15 09:50:16 -0700287}
288
John Reck531ee702014-05-13 10:06:08 -0700289static uint8_t to_uint8(float value) {
290 int c = (int) (value + .5f);
291 return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c );
292}
293
Andreas Gampe64bb4132014-11-22 00:35:09 +0000294void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
John Reck52244ff2014-05-01 21:27:37 -0700295 switch (mField) {
296 case STROKE_WIDTH:
297 mProperty->value.setStrokeWidth(value);
298 return;
299 case ALPHA:
John Reck531ee702014-05-13 10:06:08 -0700300 mProperty->value.setAlpha(to_uint8(value));
John Reck52244ff2014-05-01 21:27:37 -0700301 return;
302 }
303 LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
John Recke45b1fd2014-04-15 09:50:16 -0700304}
305
John Recka7c2ea22014-08-08 13:21:00 -0700306uint32_t CanvasPropertyPaintAnimator::dirtyMask() {
307 return RenderNode::DISPLAY_LIST;
308}
309
Chris Craikaf4d04c2014-07-29 12:50:14 -0700310RevealAnimator::RevealAnimator(int centerX, int centerY,
John Reckd3de42c2014-07-15 14:29:33 -0700311 float startValue, float finalValue)
312 : BaseRenderNodeAnimator(finalValue)
313 , mCenterX(centerX)
Chris Craikaf4d04c2014-07-29 12:50:14 -0700314 , mCenterY(centerY) {
John Reckd3de42c2014-07-15 14:29:33 -0700315 setStartValue(startValue);
316}
317
318float RevealAnimator::getValue(RenderNode* target) const {
Chris Craikaf4d04c2014-07-29 12:50:14 -0700319 return target->properties().getRevealClip().getRadius();
John Reckd3de42c2014-07-15 14:29:33 -0700320}
321
322void RevealAnimator::setValue(RenderNode* target, float value) {
Chris Craikaf4d04c2014-07-29 12:50:14 -0700323 target->animatorProperties().mutableRevealClip().set(true,
John Reckd3de42c2014-07-15 14:29:33 -0700324 mCenterX, mCenterY, value);
325}
326
John Recka7c2ea22014-08-08 13:21:00 -0700327uint32_t RevealAnimator::dirtyMask() {
328 return RenderNode::GENERIC;
329}
330
John Recke45b1fd2014-04-15 09:50:16 -0700331} /* namespace uirenderer */
332} /* namespace android */