diff options
author | Doris Liu <tianliu@google.com> | 2016-02-19 21:39:21 +0000 |
---|---|---|
committer | Doris Liu <tianliu@google.com> | 2016-02-19 13:51:31 -0800 |
commit | c4bb185d41cfb960ed9a3178a4f8974c351abdb0 (patch) | |
tree | 8fce2eab0422581acb8342def694abe23ed2c824 /libs/hwui/Animator.cpp | |
parent | 53503069895918a59a305addaac84ea11937edcf (diff) |
VectorDrawable native rendering - Step 5 of MANY
This is reverting the revert of what reverts the revert of the original
implementation. Fourth revert is a charm!
This reverts commit df7fdb1e0bdb5c289bbc08047e5c710185503309.
Change-Id: I6fc3a5accfd8b79c3da31bbc101ad9e9b4d6e7dd
Diffstat (limited to 'libs/hwui/Animator.cpp')
-rw-r--r-- | libs/hwui/Animator.cpp | 144 |
1 files changed, 119 insertions, 25 deletions
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp index 7bd2b24bf56b..372bcb3b2375 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -42,7 +42,8 @@ BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue) , mStartTime(0) , mDuration(300) , mStartDelay(0) - , mMayRunAsync(true) { + , mMayRunAsync(true) + , mPlayTime(0) { } BaseRenderNodeAnimator::~BaseRenderNodeAnimator() { @@ -85,20 +86,113 @@ void BaseRenderNodeAnimator::attach(RenderNode* target) { onAttached(); } +void BaseRenderNodeAnimator::start() { + mStagingPlayState = PlayState::Running; + mStagingRequests.push_back(Request::Start); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::cancel() { + mStagingPlayState = PlayState::Finished; + mStagingRequests.push_back(Request::Cancel); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::reset() { + mStagingPlayState = PlayState::Finished; + mStagingRequests.push_back(Request::Reset); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::reverse() { + mStagingPlayState = PlayState::Reversing; + mStagingRequests.push_back(Request::Reverse); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::end() { + mStagingPlayState = PlayState::Finished; + mStagingRequests.push_back(Request::End); + onStagingPlayStateChanged(); +} + +void BaseRenderNodeAnimator::resolveStagingRequest(Request request) { + switch (request) { + case Request::Start: + mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ? + mPlayTime : 0; + mPlayState = PlayState::Running; + break; + case Request::Reverse: + mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ? + mPlayTime : mDuration; + mPlayState = PlayState::Reversing; + break; + case Request::Reset: + mPlayTime = 0; + mPlayState = PlayState::Finished; + break; + case Request::Cancel: + mPlayState = PlayState::Finished; + break; + case Request::End: + mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration; + mPlayState = PlayState::Finished; + break; + default: + LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request)); + }; +} + void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) { if (!mHasStartValue) { doSetStartValue(getValue(mTarget)); } - if (mStagingPlayState > mPlayState) { - if (mStagingPlayState == PlayState::Restarted) { - mStagingPlayState = PlayState::Running; + + if (!mStagingRequests.empty()) { + // Keep track of the play state and play time before they are changed when + // staging requests are resolved. + nsecs_t currentPlayTime = mPlayTime; + PlayState prevFramePlayState = mPlayState; + + // Resolve staging requests one by one. + for (Request request : mStagingRequests) { + resolveStagingRequest(request); } - mPlayState = mStagingPlayState; - // Oh boy, we're starting! Man the battle stations! - if (mPlayState == PlayState::Running) { - transitionToRunning(context); - } else if (mPlayState == PlayState::Finished) { + mStagingRequests.clear(); + + if (mStagingPlayState == PlayState::Finished) { + // Set the staging play time and end the animation + updatePlayTime(mPlayTime); callOnFinishedListener(context); + } else if (mStagingPlayState == PlayState::Running + || mStagingPlayState == PlayState::Reversing) { + bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState; + if (prevFramePlayState != mStagingPlayState) { + transitionToRunning(context); + } + if (changed) { + // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was + // requested from UI thread). It is achieved by modifying mStartTime, such that + // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the + // case of reversing) + nsecs_t currentFrameTime = context.frameTimeMs(); + if (mPlayState == PlayState::Reversing) { + // Reverse is not supported for animations with a start delay, so here we + // assume no start delay. + mStartTime = currentFrameTime - (mDuration - mPlayTime); + } else { + // Animation should play forward + if (mPlayTime == 0) { + // If the request is to start from the beginning, include start delay. + mStartTime = currentFrameTime + mStartDelay; + } else { + // If the request is to seek to a non-zero play time, then we skip start + // delay. + mStartTime = currentFrameTime - mPlayTime; + } + } + } } } } @@ -136,37 +230,37 @@ bool BaseRenderNodeAnimator::animate(AnimationContext& context) { // This should be set before setValue() so animators can query this time when setValue // is called. - nsecs_t currentFrameTime = context.frameTimeMs(); - onPlayTimeChanged(currentFrameTime - mStartTime); + nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime; + bool finished = updatePlayTime(currentPlayTime); + if (finished && mPlayState != PlayState::Finished) { + mPlayState = PlayState::Finished; + callOnFinishedListener(context); + } + return finished; +} +bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) { + mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime; + onPlayTimeChanged(mPlayTime); // If BaseRenderNodeAnimator is handling the delay (not typical), then // because the staging properties reflect the final value, we always need // to call setValue even if the animation isn't yet running or is still // being delayed as we need to override the staging value - if (mStartTime > context.frameTimeMs()) { + if (playTime < 0) { setValue(mTarget, mFromValue); return false; } float fraction = 1.0f; - - if (mPlayState == PlayState::Running && mDuration > 0) { - fraction = (float)(currentFrameTime - mStartTime) / mDuration; - } - if (fraction >= 1.0f) { - fraction = 1.0f; - mPlayState = PlayState::Finished; + if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) { + fraction = mPlayTime / (float) mDuration; } + fraction = MathUtils::clamp(fraction, 0.0f, 1.0f); fraction = mInterpolator->interpolate(fraction); setValue(mTarget, mFromValue + (mDeltaValue * fraction)); - if (mPlayState == PlayState::Finished) { - callOnFinishedListener(context); - return true; - } - - return false; + return playTime >= mDuration; } void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) { |