1/* 2 * Copyright (C) 2016 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#include "PropertyValuesAnimatorSet.h" 18#include "RenderNode.h" 19 20#include <algorithm> 21 22namespace android { 23namespace uirenderer { 24 25void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, 26 Interpolator* interpolator, nsecs_t startDelay, 27 nsecs_t duration, int repeatCount) { 28 29 PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder, 30 interpolator, startDelay, duration, repeatCount); 31 mAnimators.emplace_back(animator); 32 setListener(new PropertyAnimatorSetListener(this)); 33} 34 35PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() 36 : BaseRenderNodeAnimator(1.0f) { 37 setStartValue(0); 38 mLastFraction = 0.0f; 39 setInterpolator(new LinearInterpolator()); 40} 41 42void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) { 43 if (mOneShotListener.get()) { 44 mOneShotListener->onAnimationFinished(animator); 45 mOneShotListener = nullptr; 46 } 47} 48 49float PropertyValuesAnimatorSet::getValue(RenderNode* target) const { 50 return mLastFraction; 51} 52 53void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) { 54 mLastFraction = value; 55} 56 57void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { 58 if (playTime == 0 && mDuration > 0) { 59 // Reset all the animators 60 for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) { 61 // Note that this set may containing animators modifying the same property, so when we 62 // reset the animators, we need to make sure the animators that end the first will 63 // have the final say on what the property value should be. 64 (*it)->setFraction(0); 65 } 66 } else if (playTime >= mDuration) { 67 // Skip all the animators to end 68 for (auto& anim : mAnimators) { 69 anim->setFraction(1); 70 } 71 } else { 72 for (auto& anim : mAnimators) { 73 anim->setCurrentPlayTime(playTime); 74 } 75 } 76} 77 78void PropertyValuesAnimatorSet::start(AnimationListener* listener) { 79 init(); 80 mOneShotListener = listener; 81 BaseRenderNodeAnimator::start(); 82} 83 84void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { 85 init(); 86 mOneShotListener = listener; 87 BaseRenderNodeAnimator::reverse(); 88} 89 90void PropertyValuesAnimatorSet::init() { 91 if (mInitialized) { 92 return; 93 } 94 95 // Sort the animators by their total duration. Note that all the animators in the set start at 96 // the same time, so the ones with longer total duration (which includes start delay) will 97 // be the ones that end later. 98 std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) { 99 return a->getTotalDuration() < b->getTotalDuration(); 100 }); 101 mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration(); 102 mInitialized = true; 103} 104 105uint32_t PropertyValuesAnimatorSet::dirtyMask() { 106 return RenderNode::DISPLAY_LIST; 107} 108 109PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, 110 nsecs_t startDelay, nsecs_t duration, int repeatCount) 111 : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay), 112 mDuration(duration) { 113 if (repeatCount < 0) { 114 mRepeatCount = UINT32_MAX; 115 } else { 116 mRepeatCount = repeatCount; 117 } 118 mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay; 119} 120 121void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) { 122 if (playTime >= mStartDelay && playTime < mTotalDuration) { 123 nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration; 124 float fraction = currentIterationPlayTime / (float) mDuration; 125 setFraction(fraction); 126 } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) { 127 // This makes sure we only set the fraction = 1 once. It is needed because there might 128 // be another animator modifying the same property after this animator finishes, we need 129 // to make sure we don't set conflicting values on the same property within one frame. 130 setFraction(1.0f); 131 } 132} 133 134void PropertyAnimator::setFraction(float fraction) { 135 mLatestFraction = fraction; 136 float interpolatedFraction = mInterpolator->interpolate(fraction); 137 mPropertyValuesHolder->setFraction(interpolatedFraction); 138} 139 140void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) { 141 mSet->onFinished(animator); 142} 143 144} 145} 146