| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 1 | /* | 
|  | 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 Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 17 | #include "Animator.h" | 
|  | 18 |  | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 19 | #include <inttypes.h> | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 20 | #include <set> | 
|  | 21 |  | 
| John Reck | 119907c | 2014-08-14 09:02:01 -0700 | [diff] [blame] | 22 | #include "AnimationContext.h" | 
| Tom Hudson | 2dc236b | 2014-10-15 15:46:42 -0400 | [diff] [blame] | 23 | #include "Interpolator.h" | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 24 | #include "RenderNode.h" | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 25 | #include "RenderProperties.h" | 
|  | 26 |  | 
|  | 27 | namespace android { | 
|  | 28 | namespace uirenderer { | 
|  | 29 |  | 
|  | 30 | /************************************************************ | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 31 | *  BaseRenderNodeAnimator | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 32 | ************************************************************/ | 
|  | 33 |  | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 34 | BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue) | 
| Chris Craik | d41c4d8 | 2015-01-05 15:51:13 -0800 | [diff] [blame] | 35 | : mTarget(nullptr) | 
| Doris Liu | 8b08320 | 2016-02-19 21:46:06 +0000 | [diff] [blame] | 36 | , mStagingTarget(nullptr) | 
| John Reck | 8d8af3c | 2014-07-01 15:23:45 -0700 | [diff] [blame] | 37 | , mFinalValue(finalValue) | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 38 | , mDeltaValue(0) | 
|  | 39 | , mFromValue(0) | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 40 | , mStagingPlayState(PlayState::NotStarted) | 
|  | 41 | , mPlayState(PlayState::NotStarted) | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 42 | , mHasStartValue(false) | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 43 | , mStartTime(0) | 
| Alan Viverette | ad2f8e3 | 2014-05-16 13:28:33 -0700 | [diff] [blame] | 44 | , mDuration(300) | 
| Chris Craik | 572d9ac | 2014-09-12 17:40:20 -0700 | [diff] [blame] | 45 | , mStartDelay(0) | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 46 | , mMayRunAsync(true) | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 47 | , mPlayTime(0) {} | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 48 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 49 | BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {} | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 50 |  | 
|  | 51 | void BaseRenderNodeAnimator::checkMutable() { | 
|  | 52 | // Should be impossible to hit as the Java-side also has guards for this | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 53 | LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted, | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 54 | "Animator has already been started!"); | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 55 | } | 
|  | 56 |  | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 57 | void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) { | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 58 | checkMutable(); | 
| Chris Craik | 51d6a3d | 2014-12-22 17:16:56 -0800 | [diff] [blame] | 59 | mInterpolator.reset(interpolator); | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 60 | } | 
|  | 61 |  | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 62 | void BaseRenderNodeAnimator::setStartValue(float value) { | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 63 | checkMutable(); | 
|  | 64 | doSetStartValue(value); | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 65 | } | 
|  | 66 |  | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 67 | void BaseRenderNodeAnimator::doSetStartValue(float value) { | 
|  | 68 | mFromValue = value; | 
|  | 69 | mDeltaValue = (mFinalValue - mFromValue); | 
|  | 70 | mHasStartValue = true; | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 71 | } | 
|  | 72 |  | 
| Alan Viverette | ad2f8e3 | 2014-05-16 13:28:33 -0700 | [diff] [blame] | 73 | void BaseRenderNodeAnimator::setDuration(nsecs_t duration) { | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 74 | checkMutable(); | 
| Alan Viverette | ad2f8e3 | 2014-05-16 13:28:33 -0700 | [diff] [blame] | 75 | mDuration = duration; | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) { | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 79 | checkMutable(); | 
| Alan Viverette | ad2f8e3 | 2014-05-16 13:28:33 -0700 | [diff] [blame] | 80 | mStartDelay = startDelay; | 
|  | 81 | } | 
|  | 82 |  | 
| John Reck | 8d8af3c | 2014-07-01 15:23:45 -0700 | [diff] [blame] | 83 | void BaseRenderNodeAnimator::attach(RenderNode* target) { | 
| Doris Liu | 8b08320 | 2016-02-19 21:46:06 +0000 | [diff] [blame] | 84 | mStagingTarget = target; | 
| John Reck | 8d8af3c | 2014-07-01 15:23:45 -0700 | [diff] [blame] | 85 | onAttached(); | 
|  | 86 | } | 
|  | 87 |  | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 88 | void BaseRenderNodeAnimator::start() { | 
|  | 89 | mStagingPlayState = PlayState::Running; | 
|  | 90 | mStagingRequests.push_back(Request::Start); | 
|  | 91 | onStagingPlayStateChanged(); | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | void BaseRenderNodeAnimator::cancel() { | 
|  | 95 | mStagingPlayState = PlayState::Finished; | 
|  | 96 | mStagingRequests.push_back(Request::Cancel); | 
|  | 97 | onStagingPlayStateChanged(); | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | void BaseRenderNodeAnimator::reset() { | 
|  | 101 | mStagingPlayState = PlayState::Finished; | 
|  | 102 | mStagingRequests.push_back(Request::Reset); | 
|  | 103 | onStagingPlayStateChanged(); | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | void BaseRenderNodeAnimator::reverse() { | 
|  | 107 | mStagingPlayState = PlayState::Reversing; | 
|  | 108 | mStagingRequests.push_back(Request::Reverse); | 
|  | 109 | onStagingPlayStateChanged(); | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | void BaseRenderNodeAnimator::end() { | 
|  | 113 | mStagingPlayState = PlayState::Finished; | 
|  | 114 | mStagingRequests.push_back(Request::End); | 
|  | 115 | onStagingPlayStateChanged(); | 
|  | 116 | } | 
|  | 117 |  | 
|  | 118 | void BaseRenderNodeAnimator::resolveStagingRequest(Request request) { | 
|  | 119 | switch (request) { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 120 | case Request::Start: | 
|  | 121 | mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) | 
|  | 122 | ? mPlayTime | 
|  | 123 | : 0; | 
|  | 124 | mPlayState = PlayState::Running; | 
|  | 125 | mPendingActionUponFinish = Action::None; | 
|  | 126 | break; | 
|  | 127 | case Request::Reverse: | 
|  | 128 | mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) | 
|  | 129 | ? mPlayTime | 
|  | 130 | : mDuration; | 
|  | 131 | mPlayState = PlayState::Reversing; | 
|  | 132 | mPendingActionUponFinish = Action::None; | 
|  | 133 | break; | 
|  | 134 | case Request::Reset: | 
|  | 135 | mPlayTime = 0; | 
|  | 136 | mPlayState = PlayState::Finished; | 
|  | 137 | mPendingActionUponFinish = Action::Reset; | 
|  | 138 | break; | 
|  | 139 | case Request::Cancel: | 
|  | 140 | mPlayState = PlayState::Finished; | 
|  | 141 | mPendingActionUponFinish = Action::None; | 
|  | 142 | break; | 
|  | 143 | case Request::End: | 
|  | 144 | mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration; | 
|  | 145 | mPlayState = PlayState::Finished; | 
|  | 146 | mPendingActionUponFinish = Action::End; | 
|  | 147 | break; | 
|  | 148 | default: | 
|  | 149 | LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request)); | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 150 | }; | 
|  | 151 | } | 
|  | 152 |  | 
| John Reck | 119907c | 2014-08-14 09:02:01 -0700 | [diff] [blame] | 153 | void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) { | 
| Doris Liu | 8b08320 | 2016-02-19 21:46:06 +0000 | [diff] [blame] | 154 | if (mStagingTarget) { | 
|  | 155 | RenderNode* oldTarget = mTarget; | 
|  | 156 | mTarget = mStagingTarget; | 
|  | 157 | mStagingTarget = nullptr; | 
|  | 158 | if (oldTarget && oldTarget != mTarget) { | 
|  | 159 | oldTarget->onAnimatorTargetChanged(this); | 
|  | 160 | } | 
|  | 161 | } | 
|  | 162 |  | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 163 | if (!mStagingRequests.empty()) { | 
| Doris Liu | 148f57f | 2016-02-19 17:19:24 -0800 | [diff] [blame] | 164 | // No interpolator was set, use the default | 
|  | 165 | if (mPlayState == PlayState::NotStarted && !mInterpolator) { | 
|  | 166 | mInterpolator.reset(Interpolator::createDefaultInterpolator()); | 
|  | 167 | } | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 168 | // Keep track of the play state and play time before they are changed when | 
|  | 169 | // staging requests are resolved. | 
|  | 170 | nsecs_t currentPlayTime = mPlayTime; | 
|  | 171 | PlayState prevFramePlayState = mPlayState; | 
|  | 172 |  | 
|  | 173 | // Resolve staging requests one by one. | 
|  | 174 | for (Request request : mStagingRequests) { | 
|  | 175 | resolveStagingRequest(request); | 
| Doris Liu | 766431a | 2016-02-04 22:17:11 +0000 | [diff] [blame] | 176 | } | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 177 | mStagingRequests.clear(); | 
|  | 178 |  | 
|  | 179 | if (mStagingPlayState == PlayState::Finished) { | 
| John Reck | 4d2c472 | 2014-08-29 10:40:56 -0700 | [diff] [blame] | 180 | callOnFinishedListener(context); | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 181 | } else if (mStagingPlayState == PlayState::Running || | 
|  | 182 | mStagingPlayState == PlayState::Reversing) { | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 183 | bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState; | 
|  | 184 | if (prevFramePlayState != mStagingPlayState) { | 
|  | 185 | transitionToRunning(context); | 
|  | 186 | } | 
|  | 187 | if (changed) { | 
|  | 188 | // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was | 
|  | 189 | // requested from UI thread). It is achieved by modifying mStartTime, such that | 
|  | 190 | // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the | 
|  | 191 | // case of reversing) | 
|  | 192 | nsecs_t currentFrameTime = context.frameTimeMs(); | 
|  | 193 | if (mPlayState == PlayState::Reversing) { | 
|  | 194 | // Reverse is not supported for animations with a start delay, so here we | 
|  | 195 | // assume no start delay. | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 196 | mStartTime = currentFrameTime - (mDuration - mPlayTime); | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 197 | } else { | 
|  | 198 | // Animation should play forward | 
|  | 199 | if (mPlayTime == 0) { | 
|  | 200 | // If the request is to start from the beginning, include start delay. | 
|  | 201 | mStartTime = currentFrameTime + mStartDelay; | 
|  | 202 | } else { | 
|  | 203 | // If the request is to seek to a non-zero play time, then we skip start | 
|  | 204 | // delay. | 
|  | 205 | mStartTime = currentFrameTime - mPlayTime; | 
|  | 206 | } | 
|  | 207 | } | 
|  | 208 | } | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 209 | } | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 210 | } | 
| Doris Liu | 8b08320 | 2016-02-19 21:46:06 +0000 | [diff] [blame] | 211 | onPushStaging(); | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 212 | } | 
|  | 213 |  | 
| John Reck | 119907c | 2014-08-14 09:02:01 -0700 | [diff] [blame] | 214 | void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) { | 
|  | 215 | nsecs_t frameTimeMs = context.frameTimeMs(); | 
|  | 216 | LOG_ALWAYS_FATAL_IF(frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", frameTimeMs); | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 217 | if (mStartDelay < 0 || mStartDelay > 50000) { | 
|  | 218 | ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay); | 
|  | 219 | } | 
| John Reck | 119907c | 2014-08-14 09:02:01 -0700 | [diff] [blame] | 220 | mStartTime = frameTimeMs + mStartDelay; | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 221 | if (mStartTime < 0) { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 222 | ALOGW("Ended up with a really weird start time of %" PRId64 " with frame time %" PRId64 | 
|  | 223 | " and start delay %" PRId64, | 
|  | 224 | mStartTime, frameTimeMs, mStartDelay); | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 225 | // Set to 0 so that the animate() basically instantly finishes | 
|  | 226 | mStartTime = 0; | 
|  | 227 | } | 
| Doris Liu | 952670d | 2016-04-12 17:43:00 -0700 | [diff] [blame] | 228 | if (mDuration < 0) { | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 229 | ALOGW("Your duration is strange and confusing: %" PRId64, mDuration); | 
|  | 230 | } | 
|  | 231 | } | 
|  | 232 |  | 
| John Reck | 119907c | 2014-08-14 09:02:01 -0700 | [diff] [blame] | 233 | bool BaseRenderNodeAnimator::animate(AnimationContext& context) { | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 234 | if (mPlayState < PlayState::Running) { | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 235 | return false; | 
|  | 236 | } | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 237 | if (mPlayState == PlayState::Finished) { | 
| Doris Liu | 6725d58 | 2016-08-04 13:20:17 -0700 | [diff] [blame] | 238 | if (mPendingActionUponFinish == Action::Reset) { | 
|  | 239 | // Skip to start. | 
|  | 240 | updatePlayTime(0); | 
|  | 241 | } else if (mPendingActionUponFinish == Action::End) { | 
|  | 242 | // Skip to end. | 
|  | 243 | updatePlayTime(mDuration); | 
|  | 244 | } | 
|  | 245 | // Reset pending action. | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 246 | mPendingActionUponFinish = Action::None; | 
| John Reck | 32fb630 | 2014-07-07 09:50:32 -0700 | [diff] [blame] | 247 | return true; | 
|  | 248 | } | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 249 |  | 
| Doris Liu | 766431a | 2016-02-04 22:17:11 +0000 | [diff] [blame] | 250 | // This should be set before setValue() so animators can query this time when setValue | 
|  | 251 | // is called. | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 252 | nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime; | 
|  | 253 | bool finished = updatePlayTime(currentPlayTime); | 
|  | 254 | if (finished && mPlayState != PlayState::Finished) { | 
|  | 255 | mPlayState = PlayState::Finished; | 
|  | 256 | callOnFinishedListener(context); | 
|  | 257 | } | 
|  | 258 | return finished; | 
|  | 259 | } | 
| Doris Liu | 766431a | 2016-02-04 22:17:11 +0000 | [diff] [blame] | 260 |  | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 261 | bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) { | 
|  | 262 | mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime; | 
|  | 263 | onPlayTimeChanged(mPlayTime); | 
| John Reck | 8d8af3c | 2014-07-01 15:23:45 -0700 | [diff] [blame] | 264 | // If BaseRenderNodeAnimator is handling the delay (not typical), then | 
|  | 265 | // because the staging properties reflect the final value, we always need | 
|  | 266 | // to call setValue even if the animation isn't yet running or is still | 
|  | 267 | // being delayed as we need to override the staging value | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 268 | if (playTime < 0) { | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 269 | return false; | 
|  | 270 | } | 
| Jay Aliomer | f8ecd48 | 2020-10-19 14:43:17 -0400 | [diff] [blame] | 271 | if (!this->mHasStartValue) { | 
|  | 272 | doSetStartValue(getValue(mTarget)); | 
|  | 273 | } | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 274 |  | 
|  | 275 | float fraction = 1.0f; | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 276 | if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 277 | fraction = mPlayTime / (float)mDuration; | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 278 | } | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 279 | fraction = MathUtils::clamp(fraction, 0.0f, 1.0f); | 
| John Reck | 68bfe0a | 2014-06-24 15:34:58 -0700 | [diff] [blame] | 280 |  | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 281 | fraction = mInterpolator->interpolate(fraction); | 
| John Reck | 8d8af3c | 2014-07-01 15:23:45 -0700 | [diff] [blame] | 282 | setValue(mTarget, mFromValue + (mDeltaValue * fraction)); | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 283 |  | 
| Doris Liu | c4bb185 | 2016-02-19 21:39:21 +0000 | [diff] [blame] | 284 | return playTime >= mDuration; | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 285 | } | 
|  | 286 |  | 
| Doris Liu | 718cd3e | 2016-05-17 16:50:31 -0700 | [diff] [blame] | 287 | nsecs_t BaseRenderNodeAnimator::getRemainingPlayTime() { | 
|  | 288 | return mPlayState == PlayState::Reversing ? mPlayTime : mDuration - mPlayTime; | 
|  | 289 | } | 
|  | 290 |  | 
| John Reck | e2478d4 | 2014-09-03 16:46:05 -0700 | [diff] [blame] | 291 | void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) { | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 292 | if (mPlayState < PlayState::Finished) { | 
|  | 293 | mPlayState = PlayState::Finished; | 
| John Reck | e2478d4 | 2014-09-03 16:46:05 -0700 | [diff] [blame] | 294 | callOnFinishedListener(context); | 
|  | 295 | } | 
|  | 296 | } | 
|  | 297 |  | 
| John Reck | 119907c | 2014-08-14 09:02:01 -0700 | [diff] [blame] | 298 | void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) { | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 299 | if (mListener.get()) { | 
| John Reck | 119907c | 2014-08-14 09:02:01 -0700 | [diff] [blame] | 300 | context.callOnFinished(this, mListener.get()); | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 301 | } | 
|  | 302 | } | 
|  | 303 |  | 
|  | 304 | /************************************************************ | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 305 | *  RenderPropertyAnimator | 
|  | 306 | ************************************************************/ | 
|  | 307 |  | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 308 | struct RenderPropertyAnimator::PropertyAccessors { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 309 | RenderNode::DirtyPropertyMask dirtyMask; | 
|  | 310 | GetFloatProperty getter; | 
|  | 311 | SetFloatProperty setter; | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 312 | }; | 
|  | 313 |  | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 314 | // Maps RenderProperty enum to accessors | 
|  | 315 | const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 316 | {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, | 
|  | 317 | &RenderProperties::setTranslationX}, | 
|  | 318 | {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, | 
|  | 319 | &RenderProperties::setTranslationY}, | 
|  | 320 | {RenderNode::TRANSLATION_Z, &RenderProperties::getTranslationZ, | 
|  | 321 | &RenderProperties::setTranslationZ}, | 
|  | 322 | {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX}, | 
|  | 323 | {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY}, | 
|  | 324 | {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation}, | 
|  | 325 | {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX}, | 
|  | 326 | {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY}, | 
|  | 327 | {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX}, | 
|  | 328 | {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY}, | 
|  | 329 | {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ}, | 
|  | 330 | {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha}, | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 331 | }; | 
|  | 332 |  | 
|  | 333 | RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue) | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 334 | : BaseRenderNodeAnimator(finalValue), mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {} | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 335 |  | 
| John Reck | 8d8af3c | 2014-07-01 15:23:45 -0700 | [diff] [blame] | 336 | void RenderPropertyAnimator::onAttached() { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 337 | if (!mHasStartValue && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) { | 
| Doris Liu | 8b08320 | 2016-02-19 21:46:06 +0000 | [diff] [blame] | 338 | setStartValue((mStagingTarget->stagingProperties().*mPropertyAccess->getter)()); | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 339 | } | 
| John Reck | 8d8af3c | 2014-07-01 15:23:45 -0700 | [diff] [blame] | 340 | } | 
|  | 341 |  | 
|  | 342 | void RenderPropertyAnimator::onStagingPlayStateChanged() { | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 343 | if (mStagingPlayState == PlayState::Running) { | 
| Doris Liu | 8b08320 | 2016-02-19 21:46:06 +0000 | [diff] [blame] | 344 | if (mStagingTarget) { | 
|  | 345 | (mStagingTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue()); | 
|  | 346 | } else { | 
|  | 347 | // In the case of start delay where stagingTarget has been sync'ed over and null'ed | 
|  | 348 | // we delay the properties update to push staging. | 
|  | 349 | mShouldUpdateStagingProperties = true; | 
|  | 350 | } | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 351 | } else if (mStagingPlayState == PlayState::Finished) { | 
| John Reck | 32fb630 | 2014-07-07 09:50:32 -0700 | [diff] [blame] | 352 | // We're being canceled, so make sure that whatever values the UI thread | 
|  | 353 | // is observing for us is pushed over | 
| Doris Liu | 8b08320 | 2016-02-19 21:46:06 +0000 | [diff] [blame] | 354 | mShouldSyncPropertyFields = true; | 
|  | 355 | } | 
|  | 356 | } | 
|  | 357 |  | 
|  | 358 | void RenderPropertyAnimator::onPushStaging() { | 
|  | 359 | if (mShouldUpdateStagingProperties) { | 
|  | 360 | (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue()); | 
|  | 361 | mShouldUpdateStagingProperties = false; | 
|  | 362 | } | 
|  | 363 |  | 
|  | 364 | if (mShouldSyncPropertyFields) { | 
| John Reck | 32fb630 | 2014-07-07 09:50:32 -0700 | [diff] [blame] | 365 | mTarget->setPropertyFieldsDirty(dirtyMask()); | 
| Doris Liu | 8b08320 | 2016-02-19 21:46:06 +0000 | [diff] [blame] | 366 | mShouldSyncPropertyFields = false; | 
| John Reck | 8d8af3c | 2014-07-01 15:23:45 -0700 | [diff] [blame] | 367 | } | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 368 | } | 
|  | 369 |  | 
| John Reck | 2218472 | 2014-06-20 07:19:30 -0700 | [diff] [blame] | 370 | uint32_t RenderPropertyAnimator::dirtyMask() { | 
|  | 371 | return mPropertyAccess->dirtyMask; | 
|  | 372 | } | 
|  | 373 |  | 
| John Reck | ff941dc | 2014-05-14 16:34:14 -0700 | [diff] [blame] | 374 | float RenderPropertyAnimator::getValue(RenderNode* target) const { | 
|  | 375 | return (target->properties().*mPropertyAccess->getter)(); | 
|  | 376 | } | 
|  | 377 |  | 
|  | 378 | void RenderPropertyAnimator::setValue(RenderNode* target, float value) { | 
|  | 379 | (target->animatorProperties().*mPropertyAccess->setter)(value); | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 380 | } | 
|  | 381 |  | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 382 | /************************************************************ | 
|  | 383 | *  CanvasPropertyPrimitiveAnimator | 
|  | 384 | ************************************************************/ | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 385 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 386 | CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property, | 
|  | 387 | float finalValue) | 
|  | 388 | : BaseRenderNodeAnimator(finalValue), mProperty(property) {} | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 389 |  | 
| Andreas Gampe | 64bb413 | 2014-11-22 00:35:09 +0000 | [diff] [blame] | 390 | float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const { | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 391 | return mProperty->value; | 
|  | 392 | } | 
|  | 393 |  | 
| Andreas Gampe | 64bb413 | 2014-11-22 00:35:09 +0000 | [diff] [blame] | 394 | void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) { | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 395 | mProperty->value = value; | 
|  | 396 | } | 
|  | 397 |  | 
| John Reck | a7c2ea2 | 2014-08-08 13:21:00 -0700 | [diff] [blame] | 398 | uint32_t CanvasPropertyPrimitiveAnimator::dirtyMask() { | 
|  | 399 | return RenderNode::DISPLAY_LIST; | 
|  | 400 | } | 
|  | 401 |  | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 402 | /************************************************************ | 
|  | 403 | *  CanvasPropertySkPaintAnimator | 
|  | 404 | ************************************************************/ | 
|  | 405 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 406 | CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(CanvasPropertyPaint* property, | 
|  | 407 | PaintField field, float finalValue) | 
|  | 408 | : BaseRenderNodeAnimator(finalValue), mProperty(property), mField(field) {} | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 409 |  | 
| Andreas Gampe | 64bb413 | 2014-11-22 00:35:09 +0000 | [diff] [blame] | 410 | float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const { | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 411 | switch (mField) { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 412 | case STROKE_WIDTH: | 
|  | 413 | return mProperty->value.getStrokeWidth(); | 
|  | 414 | case ALPHA: | 
|  | 415 | return mProperty->value.getAlpha(); | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 416 | } | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 417 | LOG_ALWAYS_FATAL("Unknown field %d", (int)mField); | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 418 | return -1; | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 419 | } | 
|  | 420 |  | 
| John Reck | 531ee70 | 2014-05-13 10:06:08 -0700 | [diff] [blame] | 421 | static uint8_t to_uint8(float value) { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 422 | int c = (int)(value + .5f); | 
|  | 423 | return static_cast<uint8_t>(c < 0 ? 0 : c > 255 ? 255 : c); | 
| John Reck | 531ee70 | 2014-05-13 10:06:08 -0700 | [diff] [blame] | 424 | } | 
|  | 425 |  | 
| Andreas Gampe | 64bb413 | 2014-11-22 00:35:09 +0000 | [diff] [blame] | 426 | void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) { | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 427 | switch (mField) { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 428 | case STROKE_WIDTH: | 
|  | 429 | mProperty->value.setStrokeWidth(value); | 
|  | 430 | return; | 
|  | 431 | case ALPHA: | 
|  | 432 | mProperty->value.setAlpha(to_uint8(value)); | 
|  | 433 | return; | 
| John Reck | 52244ff | 2014-05-01 21:27:37 -0700 | [diff] [blame] | 434 | } | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 435 | LOG_ALWAYS_FATAL("Unknown field %d", (int)mField); | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 436 | } | 
|  | 437 |  | 
| John Reck | a7c2ea2 | 2014-08-08 13:21:00 -0700 | [diff] [blame] | 438 | uint32_t CanvasPropertyPaintAnimator::dirtyMask() { | 
|  | 439 | return RenderNode::DISPLAY_LIST; | 
|  | 440 | } | 
|  | 441 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 442 | RevealAnimator::RevealAnimator(int centerX, int centerY, float startValue, float finalValue) | 
|  | 443 | : BaseRenderNodeAnimator(finalValue), mCenterX(centerX), mCenterY(centerY) { | 
| John Reck | d3de42c | 2014-07-15 14:29:33 -0700 | [diff] [blame] | 444 | setStartValue(startValue); | 
|  | 445 | } | 
|  | 446 |  | 
|  | 447 | float RevealAnimator::getValue(RenderNode* target) const { | 
| Chris Craik | af4d04c | 2014-07-29 12:50:14 -0700 | [diff] [blame] | 448 | return target->properties().getRevealClip().getRadius(); | 
| John Reck | d3de42c | 2014-07-15 14:29:33 -0700 | [diff] [blame] | 449 | } | 
|  | 450 |  | 
|  | 451 | void RevealAnimator::setValue(RenderNode* target, float value) { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 452 | target->animatorProperties().mutableRevealClip().set(true, mCenterX, mCenterY, value); | 
| John Reck | d3de42c | 2014-07-15 14:29:33 -0700 | [diff] [blame] | 453 | } | 
|  | 454 |  | 
| John Reck | a7c2ea2 | 2014-08-08 13:21:00 -0700 | [diff] [blame] | 455 | uint32_t RevealAnimator::dirtyMask() { | 
|  | 456 | return RenderNode::GENERIC; | 
|  | 457 | } | 
|  | 458 |  | 
| John Reck | e45b1fd | 2014-04-15 09:50:16 -0700 | [diff] [blame] | 459 | } /* namespace uirenderer */ | 
|  | 460 | } /* namespace android */ |