diff options
author | 2016-08-03 17:54:28 -0700 | |
---|---|---|
committer | 2016-08-05 01:44:20 +0000 | |
commit | f7167e8f286cff91dec01fdf617bf568f1d100e6 (patch) | |
tree | f58d8288ef2ea02fdc8408dcc31e789c543983f8 | |
parent | 6f20514185f836bbab48fe3867d3b249da573ec9 (diff) |
Support repeatMode = reverse in AVD
BUG: 30641232
Change-Id: I34c823a0a45c8441873a9b467275174c5529994b
-rw-r--r-- | core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp | 8 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java | 5 | ||||
-rw-r--r-- | libs/hwui/Animator.h | 6 | ||||
-rw-r--r-- | libs/hwui/PropertyValuesAnimatorSet.cpp | 60 | ||||
-rw-r--r-- | libs/hwui/PropertyValuesAnimatorSet.h | 10 |
5 files changed, 58 insertions, 31 deletions
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp index 47252ad54468..ade718b9e6b8 100644 --- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp +++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp @@ -83,11 +83,13 @@ static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishLis } static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr, - jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount) { + jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount, + jint repeatMode) { PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr); Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); - set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount); + RepeatMode mode = static_cast<RepeatMode>(repeatMode); + set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount, mode); } static jlong createAnimatorSet(JNIEnv*, jobject) { @@ -185,7 +187,7 @@ static void reset(JNIEnv*, jobject, jlong animatorSetPtr) { static const JNINativeMethod gMethods[] = { {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet}, {"nSetVectorDrawableTarget", "(JJ)V", (void*)setVectorDrawableTarget}, - {"nAddAnimator", "(JJJJJI)V", (void*)addAnimator}, + {"nAddAnimator", "(JJJJJII)V", (void*)addAnimator}, {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder}, {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder}, {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder}, diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 0bdc76f9f359..87c472ec6c95 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -1358,7 +1358,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mStartDelays.add(startDelay); nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration, - repeatCount); + repeatCount, animator.getRepeatMode()); } /** @@ -1625,7 +1625,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static native long nCreateAnimatorSet(); private static native void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr); private static native void nAddAnimator(long setPtr, long propertyValuesHolder, - long nativeInterpolator, long startDelay, long duration, int repeatCount); + long nativeInterpolator, long startDelay, long duration, int repeatCount, + int repeatMode); private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId, float startValue, float endValue); diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 9476750afd52..259f21b9934f 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -44,6 +44,12 @@ protected: ANDROID_API virtual ~AnimationListener() {} }; +enum class RepeatMode { + // These are the same values as the RESTART and REVERSE in ValueAnimator.java. + Restart = 1, + Reverse = 2 +}; + class BaseRenderNodeAnimator : public VirtualLightRefBase { PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator); public: diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp index 796c73b9c3e7..961132ea42fa 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.cpp +++ b/libs/hwui/PropertyValuesAnimatorSet.cpp @@ -23,11 +23,11 @@ namespace android { namespace uirenderer { void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, - Interpolator* interpolator, nsecs_t startDelay, - nsecs_t duration, int repeatCount) { + Interpolator* interpolator, nsecs_t startDelay, nsecs_t duration, int repeatCount, + RepeatMode repeatMode) { PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder, - interpolator, startDelay, duration, repeatCount); + interpolator, startDelay, duration, repeatCount, repeatMode); mAnimators.emplace_back(animator); // Check whether any child animator is infinite after adding it them to the set. @@ -66,14 +66,9 @@ void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { // Note that this set may containing animators modifying the same property, so when we // reset the animators, we need to make sure the animators that end the first will // have the final say on what the property value should be. - (*it)->setFraction(0); + (*it)->setFraction(0, 0); } - } else if (playTime >= mDuration) { - // Skip all the animators to end - for (auto& anim : mAnimators) { - anim->setFraction(1); - } - } else { + } else { for (auto& anim : mAnimators) { anim->setCurrentPlayTime(playTime); } @@ -124,7 +119,8 @@ uint32_t PropertyValuesAnimatorSet::dirtyMask() { } PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, - nsecs_t startDelay, nsecs_t duration, int repeatCount) + nsecs_t startDelay, nsecs_t duration, int repeatCount, + RepeatMode repeatMode) : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay), mDuration(duration) { if (repeatCount < 0) { @@ -132,24 +128,44 @@ PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* i } else { mRepeatCount = repeatCount; } + mRepeatMode = repeatMode; mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay; } void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) { - if (playTime >= mStartDelay && playTime < mTotalDuration) { - nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration; - float fraction = currentIterationPlayTime / (float) mDuration; - setFraction(fraction); - } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) { - // This makes sure we only set the fraction = 1 once. It is needed because there might - // be another animator modifying the same property after this animator finishes, we need - // to make sure we don't set conflicting values on the same property within one frame. - setFraction(1.0f); + if (playTime < mStartDelay) { + return; } + + float currentIterationFraction; + long iteration; + if (playTime >= mTotalDuration) { + // Reached the end of the animation. + iteration = mRepeatCount; + currentIterationFraction = 1.0f; + } else { + // play time here is in range [mStartDelay, mTotalDuration) + iteration = (playTime - mStartDelay) / mDuration; + currentIterationFraction = ((playTime - mStartDelay) % mDuration) / (float) mDuration; + } + setFraction(currentIterationFraction, iteration); } -void PropertyAnimator::setFraction(float fraction) { - mLatestFraction = fraction; +void PropertyAnimator::setFraction(float fraction, long iteration) { + double totalFraction = fraction + iteration; + // This makes sure we only set the fraction = repeatCount + 1 once. It is needed because there + // might be another animator modifying the same property after this animator finishes, we need + // to make sure we don't set conflicting values on the same property within one frame. + if ((mLatestFraction == mRepeatCount + 1) && (totalFraction >= mRepeatCount + 1)) { + return; + } + + mLatestFraction = totalFraction; + // Check the play direction (i.e. reverse or restart) every other iteration, and calculate the + // fraction based on the play direction. + if (iteration % 2 && mRepeatMode == RepeatMode::Reverse) { + fraction = 1.0f - fraction; + } float interpolatedFraction = mInterpolator->interpolate(fraction); mPropertyValuesHolder->setFraction(interpolatedFraction); } diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h index f9274e173536..e208b08cc27a 100644 --- a/libs/hwui/PropertyValuesAnimatorSet.h +++ b/libs/hwui/PropertyValuesAnimatorSet.h @@ -26,12 +26,13 @@ namespace uirenderer { class PropertyAnimator { public: PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, nsecs_t startDelay, - nsecs_t duration, int repeatCount); + nsecs_t duration, int repeatCount, RepeatMode repeatMode); void setCurrentPlayTime(nsecs_t playTime); nsecs_t getTotalDuration() { return mTotalDuration; } - void setFraction(float fraction); + // fraction range: [0, 1], iteration range [0, repeatCount] + void setFraction(float fraction, long iteration); private: std::unique_ptr<PropertyValuesHolder> mPropertyValuesHolder; @@ -40,7 +41,8 @@ private: nsecs_t mDuration; uint32_t mRepeatCount; nsecs_t mTotalDuration; - float mLatestFraction = 0.0f; + RepeatMode mRepeatMode; + double mLatestFraction = 0; }; // TODO: This class should really be named VectorDrawableAnimator @@ -56,7 +58,7 @@ public: void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, Interpolator* interpolators, int64_t startDelays, - nsecs_t durations, int repeatCount); + nsecs_t durations, int repeatCount, RepeatMode repeatMode); virtual uint32_t dirtyMask(); bool isInfinite() { return mIsInfinite; } void setVectorDrawable(VectorDrawableRoot* vd) { mVectorDrawable = vd; } |