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 22 namespace android { 23 namespace uirenderer { 24 25 void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, 26 Interpolator* interpolator, nsecs_t startDelay, nsecs_t duration, int repeatCount, 27 RepeatMode repeatMode) { 28 29 PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder, 30 interpolator, startDelay, duration, repeatCount, repeatMode); 31 mAnimators.emplace_back(animator); 32 33 // Check whether any child animator is infinite after adding it them to the set. 34 if (repeatCount == -1) { 35 mIsInfinite = true; 36 } 37 } 38 39 PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() 40 : BaseRenderNodeAnimator(1.0f) { 41 setStartValue(0); 42 mLastFraction = 0.0f; 43 setInterpolator(new LinearInterpolator()); 44 setListener(new PropertyAnimatorSetListener(this)); 45 } 46 47 void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) { 48 if (mOneShotListener.get()) { 49 mOneShotListener->onAnimationFinished(animator); 50 mOneShotListener = nullptr; 51 } 52 } 53 54 float PropertyValuesAnimatorSet::getValue(RenderNode* target) const { 55 return mLastFraction; 56 } 57 58 void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) { 59 mLastFraction = value; 60 } 61 62 void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { 63 if (playTime == 0 && mDuration > 0) { 64 // Reset all the animators 65 for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) { 66 // Note that this set may containing animators modifying the same property, so when we 67 // reset the animators, we need to make sure the animators that end the first will 68 // have the final say on what the property value should be. 69 (*it)->setFraction(0, 0); 70 } 71 } else { 72 for (auto& anim : mAnimators) { 73 anim->setCurrentPlayTime(playTime); 74 } 75 } 76 } 77 78 void PropertyValuesAnimatorSet::start(AnimationListener* listener) { 79 init(); 80 mOneShotListener = listener; 81 mRequestId++; 82 BaseRenderNodeAnimator::start(); 83 } 84 85 void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { 86 init(); 87 mOneShotListener = listener; 88 mRequestId++; 89 BaseRenderNodeAnimator::reverse(); 90 } 91 92 void PropertyValuesAnimatorSet::reset() { 93 mRequestId++; 94 BaseRenderNodeAnimator::reset(); 95 } 96 97 void PropertyValuesAnimatorSet::end() { 98 mRequestId++; 99 BaseRenderNodeAnimator::end(); 100 } 101 102 void PropertyValuesAnimatorSet::init() { 103 if (mInitialized) { 104 return; 105 } 106 107 // Sort the animators by their total duration. Note that all the animators in the set start at 108 // the same time, so the ones with longer total duration (which includes start delay) will 109 // be the ones that end later. 110 std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) { 111 return a->getTotalDuration() < b->getTotalDuration(); 112 }); 113 mDuration = mAnimators.empty() ? 0 : mAnimators[mAnimators.size() - 1]->getTotalDuration(); 114 mInitialized = true; 115 } 116 117 uint32_t PropertyValuesAnimatorSet::dirtyMask() { 118 return RenderNode::DISPLAY_LIST; 119 } 120 121 PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, 122 nsecs_t startDelay, nsecs_t duration, int repeatCount, 123 RepeatMode repeatMode) 124 : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay), 125 mDuration(duration) { 126 if (repeatCount < 0) { 127 mRepeatCount = UINT32_MAX; 128 } else { 129 mRepeatCount = repeatCount; 130 } 131 mRepeatMode = repeatMode; 132 mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay; 133 } 134 135 void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) { 136 if (playTime < mStartDelay) { 137 return; 138 } 139 140 float currentIterationFraction; 141 long iteration; 142 if (playTime >= mTotalDuration) { 143 // Reached the end of the animation. 144 iteration = mRepeatCount; 145 currentIterationFraction = 1.0f; 146 } else { 147 // play time here is in range [mStartDelay, mTotalDuration) 148 iteration = (playTime - mStartDelay) / mDuration; 149 currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float) mDuration; 150 } 151 setFraction(currentIterationFraction, iteration); 152 } 153 154 void PropertyAnimator::setFraction(float fraction, long iteration) { 155 double totalFraction = fraction + iteration; 156 // This makes sure we only set the fraction = repeatCount + 1 once. It is needed because there 157 // might be another animator modifying the same property after this animator finishes, we need 158 // to make sure we don't set conflicting values on the same property within one frame. 159 if ((mLatestFraction == mRepeatCount + 1.0) && (totalFraction >= mRepeatCount + 1.0)) { 160 return; 161 } 162 163 mLatestFraction = totalFraction; 164 // Check the play direction (i.e. reverse or restart) every other iteration, and calculate the 165 // fraction based on the play direction. 166 if (iteration % 2 && mRepeatMode == RepeatMode::Reverse) { 167 fraction = 1.0f - fraction; 168 } 169 float interpolatedFraction = mInterpolator->interpolate(fraction); 170 mPropertyValuesHolder->setFraction(interpolatedFraction); 171 } 172 173 void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) { 174 mSet->onFinished(animator); 175 } 176 177 } 178 } 179