1*d57664e9SAndroid Build Coastguard Worker /* 2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*d57664e9SAndroid Build Coastguard Worker * 4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*d57664e9SAndroid Build Coastguard Worker * 8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*d57664e9SAndroid Build Coastguard Worker * 10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*d57664e9SAndroid Build Coastguard Worker * limitations under the License. 15*d57664e9SAndroid Build Coastguard Worker */ 16*d57664e9SAndroid Build Coastguard Worker #ifndef ANIMATOR_H 17*d57664e9SAndroid Build Coastguard Worker #define ANIMATOR_H 18*d57664e9SAndroid Build Coastguard Worker 19*d57664e9SAndroid Build Coastguard Worker #include "CanvasProperty.h" 20*d57664e9SAndroid Build Coastguard Worker 21*d57664e9SAndroid Build Coastguard Worker #include <cutils/compiler.h> 22*d57664e9SAndroid Build Coastguard Worker #include <utils/RefBase.h> 23*d57664e9SAndroid Build Coastguard Worker #include <utils/StrongPointer.h> 24*d57664e9SAndroid Build Coastguard Worker #include <utils/Timers.h> 25*d57664e9SAndroid Build Coastguard Worker #include <memory> 26*d57664e9SAndroid Build Coastguard Worker 27*d57664e9SAndroid Build Coastguard Worker #include "utils/Macros.h" 28*d57664e9SAndroid Build Coastguard Worker 29*d57664e9SAndroid Build Coastguard Worker #include <vector> 30*d57664e9SAndroid Build Coastguard Worker 31*d57664e9SAndroid Build Coastguard Worker namespace android { 32*d57664e9SAndroid Build Coastguard Worker namespace uirenderer { 33*d57664e9SAndroid Build Coastguard Worker 34*d57664e9SAndroid Build Coastguard Worker class AnimationContext; 35*d57664e9SAndroid Build Coastguard Worker class BaseRenderNodeAnimator; 36*d57664e9SAndroid Build Coastguard Worker class Interpolator; 37*d57664e9SAndroid Build Coastguard Worker class RenderNode; 38*d57664e9SAndroid Build Coastguard Worker class RenderProperties; 39*d57664e9SAndroid Build Coastguard Worker 40*d57664e9SAndroid Build Coastguard Worker class AnimationListener : public VirtualLightRefBase { 41*d57664e9SAndroid Build Coastguard Worker public: 42*d57664e9SAndroid Build Coastguard Worker virtual void onAnimationFinished(BaseRenderNodeAnimator*) = 0; 43*d57664e9SAndroid Build Coastguard Worker 44*d57664e9SAndroid Build Coastguard Worker protected: ~AnimationListener()45*d57664e9SAndroid Build Coastguard Worker virtual ~AnimationListener() {} 46*d57664e9SAndroid Build Coastguard Worker }; 47*d57664e9SAndroid Build Coastguard Worker 48*d57664e9SAndroid Build Coastguard Worker enum class RepeatMode { 49*d57664e9SAndroid Build Coastguard Worker // These are the same values as the RESTART and REVERSE in ValueAnimator.java. 50*d57664e9SAndroid Build Coastguard Worker Restart = 1, 51*d57664e9SAndroid Build Coastguard Worker Reverse = 2 52*d57664e9SAndroid Build Coastguard Worker }; 53*d57664e9SAndroid Build Coastguard Worker 54*d57664e9SAndroid Build Coastguard Worker class BaseRenderNodeAnimator : public VirtualLightRefBase { 55*d57664e9SAndroid Build Coastguard Worker PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator); 56*d57664e9SAndroid Build Coastguard Worker 57*d57664e9SAndroid Build Coastguard Worker public: 58*d57664e9SAndroid Build Coastguard Worker void setStartValue(float value); 59*d57664e9SAndroid Build Coastguard Worker void setInterpolator(Interpolator* interpolator); 60*d57664e9SAndroid Build Coastguard Worker void setDuration(nsecs_t durationInMs); duration()61*d57664e9SAndroid Build Coastguard Worker nsecs_t duration() { return mDuration; } 62*d57664e9SAndroid Build Coastguard Worker void setStartDelay(nsecs_t startDelayInMs); startDelay()63*d57664e9SAndroid Build Coastguard Worker nsecs_t startDelay() { return mStartDelay; } setListener(AnimationListener * listener)64*d57664e9SAndroid Build Coastguard Worker void setListener(AnimationListener* listener) { mListener = listener; } listener()65*d57664e9SAndroid Build Coastguard Worker AnimationListener* listener() { return mListener.get(); } setAllowRunningAsync(bool mayRunAsync)66*d57664e9SAndroid Build Coastguard Worker void setAllowRunningAsync(bool mayRunAsync) { mMayRunAsync = mayRunAsync; } mayRunAsync()67*d57664e9SAndroid Build Coastguard Worker bool mayRunAsync() { return mMayRunAsync; } 68*d57664e9SAndroid Build Coastguard Worker void start(); 69*d57664e9SAndroid Build Coastguard Worker virtual void reset(); 70*d57664e9SAndroid Build Coastguard Worker void reverse(); 71*d57664e9SAndroid Build Coastguard Worker // Terminates the animation at its current progress. 72*d57664e9SAndroid Build Coastguard Worker void cancel(); 73*d57664e9SAndroid Build Coastguard Worker 74*d57664e9SAndroid Build Coastguard Worker // Terminates the animation and skip to the end of the animation. 75*d57664e9SAndroid Build Coastguard Worker virtual void end(); 76*d57664e9SAndroid Build Coastguard Worker 77*d57664e9SAndroid Build Coastguard Worker void attach(RenderNode* target); onAttached()78*d57664e9SAndroid Build Coastguard Worker virtual void onAttached() {} detach()79*d57664e9SAndroid Build Coastguard Worker void detach() { mTarget = nullptr; } 80*d57664e9SAndroid Build Coastguard Worker void pushStaging(AnimationContext& context); 81*d57664e9SAndroid Build Coastguard Worker bool animate(AnimationContext& context); 82*d57664e9SAndroid Build Coastguard Worker 83*d57664e9SAndroid Build Coastguard Worker // Returns the remaining time in ms for the animation. Note this should only be called during 84*d57664e9SAndroid Build Coastguard Worker // an animation on RenderThread. 85*d57664e9SAndroid Build Coastguard Worker nsecs_t getRemainingPlayTime(); 86*d57664e9SAndroid Build Coastguard Worker isRunning()87*d57664e9SAndroid Build Coastguard Worker bool isRunning() { 88*d57664e9SAndroid Build Coastguard Worker return mPlayState == PlayState::Running || mPlayState == PlayState::Reversing; 89*d57664e9SAndroid Build Coastguard Worker } isFinished()90*d57664e9SAndroid Build Coastguard Worker bool isFinished() { return mPlayState == PlayState::Finished; } finalValue()91*d57664e9SAndroid Build Coastguard Worker float finalValue() { return mFinalValue; } 92*d57664e9SAndroid Build Coastguard Worker 93*d57664e9SAndroid Build Coastguard Worker virtual uint32_t dirtyMask() = 0; 94*d57664e9SAndroid Build Coastguard Worker 95*d57664e9SAndroid Build Coastguard Worker void forceEndNow(AnimationContext& context); target()96*d57664e9SAndroid Build Coastguard Worker RenderNode* target() { return mTarget; } stagingTarget()97*d57664e9SAndroid Build Coastguard Worker RenderNode* stagingTarget() { return mStagingTarget; } 98*d57664e9SAndroid Build Coastguard Worker 99*d57664e9SAndroid Build Coastguard Worker protected: 100*d57664e9SAndroid Build Coastguard Worker // PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI 101*d57664e9SAndroid Build Coastguard Worker // thread and Render Thread animation state, respectively. 102*d57664e9SAndroid Build Coastguard Worker // From the UI thread, mStagingPlayState transition looks like 103*d57664e9SAndroid Build Coastguard Worker // NotStarted -> Running/Reversing -> Finished 104*d57664e9SAndroid Build Coastguard Worker // ^ | 105*d57664e9SAndroid Build Coastguard Worker // | | 106*d57664e9SAndroid Build Coastguard Worker // ---------------------- 107*d57664e9SAndroid Build Coastguard Worker // Note: For mStagingState, the Finished state (optional) is only set when the animation is 108*d57664e9SAndroid Build Coastguard Worker // terminated by user. 109*d57664e9SAndroid Build Coastguard Worker // 110*d57664e9SAndroid Build Coastguard Worker // On Render Thread, mPlayState transition: 111*d57664e9SAndroid Build Coastguard Worker // NotStart -> Running/Reversing-> Finished 112*d57664e9SAndroid Build Coastguard Worker // ^ | 113*d57664e9SAndroid Build Coastguard Worker // | | 114*d57664e9SAndroid Build Coastguard Worker // ------------------ 115*d57664e9SAndroid Build Coastguard Worker // Note that if the animation is in Running/Reversing state, calling start or reverse again 116*d57664e9SAndroid Build Coastguard Worker // would do nothing if the animation has the same play direction as the request; otherwise, 117*d57664e9SAndroid Build Coastguard Worker // the animation would start from where it is and change direction (i.e. Reversing <-> Running) 118*d57664e9SAndroid Build Coastguard Worker 119*d57664e9SAndroid Build Coastguard Worker enum class PlayState { 120*d57664e9SAndroid Build Coastguard Worker NotStarted, 121*d57664e9SAndroid Build Coastguard Worker Running, 122*d57664e9SAndroid Build Coastguard Worker Reversing, 123*d57664e9SAndroid Build Coastguard Worker Finished, 124*d57664e9SAndroid Build Coastguard Worker }; 125*d57664e9SAndroid Build Coastguard Worker 126*d57664e9SAndroid Build Coastguard Worker explicit BaseRenderNodeAnimator(float finalValue); 127*d57664e9SAndroid Build Coastguard Worker virtual ~BaseRenderNodeAnimator(); 128*d57664e9SAndroid Build Coastguard Worker 129*d57664e9SAndroid Build Coastguard Worker virtual float getValue(RenderNode* target) const = 0; 130*d57664e9SAndroid Build Coastguard Worker virtual void setValue(RenderNode* target, float value) = 0; 131*d57664e9SAndroid Build Coastguard Worker 132*d57664e9SAndroid Build Coastguard Worker void callOnFinishedListener(AnimationContext& context); 133*d57664e9SAndroid Build Coastguard Worker onStagingPlayStateChanged()134*d57664e9SAndroid Build Coastguard Worker virtual void onStagingPlayStateChanged() {} onPlayTimeChanged(nsecs_t playTime)135*d57664e9SAndroid Build Coastguard Worker virtual void onPlayTimeChanged(nsecs_t playTime) {} onPushStaging()136*d57664e9SAndroid Build Coastguard Worker virtual void onPushStaging() {} 137*d57664e9SAndroid Build Coastguard Worker 138*d57664e9SAndroid Build Coastguard Worker RenderNode* mTarget; 139*d57664e9SAndroid Build Coastguard Worker RenderNode* mStagingTarget; 140*d57664e9SAndroid Build Coastguard Worker 141*d57664e9SAndroid Build Coastguard Worker float mFinalValue; 142*d57664e9SAndroid Build Coastguard Worker float mDeltaValue; 143*d57664e9SAndroid Build Coastguard Worker float mFromValue; 144*d57664e9SAndroid Build Coastguard Worker 145*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<Interpolator> mInterpolator; 146*d57664e9SAndroid Build Coastguard Worker PlayState mStagingPlayState; 147*d57664e9SAndroid Build Coastguard Worker PlayState mPlayState; 148*d57664e9SAndroid Build Coastguard Worker bool mHasStartValue; 149*d57664e9SAndroid Build Coastguard Worker nsecs_t mStartTime; 150*d57664e9SAndroid Build Coastguard Worker nsecs_t mDuration; 151*d57664e9SAndroid Build Coastguard Worker nsecs_t mStartDelay; 152*d57664e9SAndroid Build Coastguard Worker bool mMayRunAsync; 153*d57664e9SAndroid Build Coastguard Worker // Play Time tracks the progress of animation, it should always be [0, mDuration], 0 being 154*d57664e9SAndroid Build Coastguard Worker // the beginning of the animation, will reach mDuration at the end of an animation. 155*d57664e9SAndroid Build Coastguard Worker nsecs_t mPlayTime; 156*d57664e9SAndroid Build Coastguard Worker 157*d57664e9SAndroid Build Coastguard Worker sp<AnimationListener> mListener; 158*d57664e9SAndroid Build Coastguard Worker 159*d57664e9SAndroid Build Coastguard Worker private: 160*d57664e9SAndroid Build Coastguard Worker enum class Request { Start, Reverse, Reset, Cancel, End }; 161*d57664e9SAndroid Build Coastguard Worker 162*d57664e9SAndroid Build Coastguard Worker // Defines different actions upon finish. 163*d57664e9SAndroid Build Coastguard Worker enum class Action { 164*d57664e9SAndroid Build Coastguard Worker // For animations that got canceled or finished normally. no more action needs to be done. 165*d57664e9SAndroid Build Coastguard Worker None, 166*d57664e9SAndroid Build Coastguard Worker // For animations that get reset, the reset will happen in the next animation pulse. 167*d57664e9SAndroid Build Coastguard Worker Reset, 168*d57664e9SAndroid Build Coastguard Worker // For animations being ended, in the next animation pulse the animation will skip to end. 169*d57664e9SAndroid Build Coastguard Worker End 170*d57664e9SAndroid Build Coastguard Worker }; 171*d57664e9SAndroid Build Coastguard Worker 172*d57664e9SAndroid Build Coastguard Worker inline void checkMutable(); 173*d57664e9SAndroid Build Coastguard Worker virtual void transitionToRunning(AnimationContext& context); 174*d57664e9SAndroid Build Coastguard Worker void doSetStartValue(float value); 175*d57664e9SAndroid Build Coastguard Worker bool updatePlayTime(nsecs_t playTime); 176*d57664e9SAndroid Build Coastguard Worker void resolveStagingRequest(Request request); 177*d57664e9SAndroid Build Coastguard Worker 178*d57664e9SAndroid Build Coastguard Worker std::vector<Request> mStagingRequests; 179*d57664e9SAndroid Build Coastguard Worker Action mPendingActionUponFinish = Action::None; 180*d57664e9SAndroid Build Coastguard Worker }; 181*d57664e9SAndroid Build Coastguard Worker 182*d57664e9SAndroid Build Coastguard Worker class RenderPropertyAnimator : public BaseRenderNodeAnimator { 183*d57664e9SAndroid Build Coastguard Worker public: 184*d57664e9SAndroid Build Coastguard Worker enum RenderProperty { 185*d57664e9SAndroid Build Coastguard Worker TRANSLATION_X = 0, 186*d57664e9SAndroid Build Coastguard Worker TRANSLATION_Y, 187*d57664e9SAndroid Build Coastguard Worker TRANSLATION_Z, 188*d57664e9SAndroid Build Coastguard Worker SCALE_X, 189*d57664e9SAndroid Build Coastguard Worker SCALE_Y, 190*d57664e9SAndroid Build Coastguard Worker ROTATION, 191*d57664e9SAndroid Build Coastguard Worker ROTATION_X, 192*d57664e9SAndroid Build Coastguard Worker ROTATION_Y, 193*d57664e9SAndroid Build Coastguard Worker X, 194*d57664e9SAndroid Build Coastguard Worker Y, 195*d57664e9SAndroid Build Coastguard Worker Z, 196*d57664e9SAndroid Build Coastguard Worker ALPHA, 197*d57664e9SAndroid Build Coastguard Worker }; 198*d57664e9SAndroid Build Coastguard Worker 199*d57664e9SAndroid Build Coastguard Worker RenderPropertyAnimator(RenderProperty property, float finalValue); 200*d57664e9SAndroid Build Coastguard Worker 201*d57664e9SAndroid Build Coastguard Worker virtual uint32_t dirtyMask(); 202*d57664e9SAndroid Build Coastguard Worker 203*d57664e9SAndroid Build Coastguard Worker protected: 204*d57664e9SAndroid Build Coastguard Worker virtual float getValue(RenderNode* target) const override; 205*d57664e9SAndroid Build Coastguard Worker virtual void setValue(RenderNode* target, float value) override; 206*d57664e9SAndroid Build Coastguard Worker virtual void onAttached() override; 207*d57664e9SAndroid Build Coastguard Worker virtual void onStagingPlayStateChanged() override; 208*d57664e9SAndroid Build Coastguard Worker virtual void onPushStaging() override; 209*d57664e9SAndroid Build Coastguard Worker 210*d57664e9SAndroid Build Coastguard Worker private: 211*d57664e9SAndroid Build Coastguard Worker typedef bool (RenderProperties::*SetFloatProperty)(float value); 212*d57664e9SAndroid Build Coastguard Worker typedef float (RenderProperties::*GetFloatProperty)() const; 213*d57664e9SAndroid Build Coastguard Worker 214*d57664e9SAndroid Build Coastguard Worker struct PropertyAccessors; 215*d57664e9SAndroid Build Coastguard Worker const PropertyAccessors* mPropertyAccess; 216*d57664e9SAndroid Build Coastguard Worker 217*d57664e9SAndroid Build Coastguard Worker static const PropertyAccessors PROPERTY_ACCESSOR_LUT[]; 218*d57664e9SAndroid Build Coastguard Worker bool mShouldSyncPropertyFields = false; 219*d57664e9SAndroid Build Coastguard Worker bool mShouldUpdateStagingProperties = false; 220*d57664e9SAndroid Build Coastguard Worker }; 221*d57664e9SAndroid Build Coastguard Worker 222*d57664e9SAndroid Build Coastguard Worker class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator { 223*d57664e9SAndroid Build Coastguard Worker public: 224*d57664e9SAndroid Build Coastguard Worker CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property, 225*d57664e9SAndroid Build Coastguard Worker float finalValue); 226*d57664e9SAndroid Build Coastguard Worker 227*d57664e9SAndroid Build Coastguard Worker virtual uint32_t dirtyMask(); 228*d57664e9SAndroid Build Coastguard Worker 229*d57664e9SAndroid Build Coastguard Worker protected: 230*d57664e9SAndroid Build Coastguard Worker virtual float getValue(RenderNode* target) const override; 231*d57664e9SAndroid Build Coastguard Worker virtual void setValue(RenderNode* target, float value) override; 232*d57664e9SAndroid Build Coastguard Worker 233*d57664e9SAndroid Build Coastguard Worker private: 234*d57664e9SAndroid Build Coastguard Worker sp<CanvasPropertyPrimitive> mProperty; 235*d57664e9SAndroid Build Coastguard Worker }; 236*d57664e9SAndroid Build Coastguard Worker 237*d57664e9SAndroid Build Coastguard Worker class CanvasPropertyPaintAnimator : public BaseRenderNodeAnimator { 238*d57664e9SAndroid Build Coastguard Worker public: 239*d57664e9SAndroid Build Coastguard Worker enum PaintField { 240*d57664e9SAndroid Build Coastguard Worker STROKE_WIDTH = 0, 241*d57664e9SAndroid Build Coastguard Worker ALPHA, 242*d57664e9SAndroid Build Coastguard Worker }; 243*d57664e9SAndroid Build Coastguard Worker 244*d57664e9SAndroid Build Coastguard Worker CanvasPropertyPaintAnimator(CanvasPropertyPaint* property, PaintField field, 245*d57664e9SAndroid Build Coastguard Worker float finalValue); 246*d57664e9SAndroid Build Coastguard Worker 247*d57664e9SAndroid Build Coastguard Worker virtual uint32_t dirtyMask(); 248*d57664e9SAndroid Build Coastguard Worker 249*d57664e9SAndroid Build Coastguard Worker protected: 250*d57664e9SAndroid Build Coastguard Worker virtual float getValue(RenderNode* target) const override; 251*d57664e9SAndroid Build Coastguard Worker virtual void setValue(RenderNode* target, float value) override; 252*d57664e9SAndroid Build Coastguard Worker 253*d57664e9SAndroid Build Coastguard Worker private: 254*d57664e9SAndroid Build Coastguard Worker sp<CanvasPropertyPaint> mProperty; 255*d57664e9SAndroid Build Coastguard Worker PaintField mField; 256*d57664e9SAndroid Build Coastguard Worker }; 257*d57664e9SAndroid Build Coastguard Worker 258*d57664e9SAndroid Build Coastguard Worker class RevealAnimator : public BaseRenderNodeAnimator { 259*d57664e9SAndroid Build Coastguard Worker public: 260*d57664e9SAndroid Build Coastguard Worker RevealAnimator(int centerX, int centerY, float startValue, float finalValue); 261*d57664e9SAndroid Build Coastguard Worker 262*d57664e9SAndroid Build Coastguard Worker virtual uint32_t dirtyMask(); 263*d57664e9SAndroid Build Coastguard Worker 264*d57664e9SAndroid Build Coastguard Worker protected: 265*d57664e9SAndroid Build Coastguard Worker virtual float getValue(RenderNode* target) const override; 266*d57664e9SAndroid Build Coastguard Worker virtual void setValue(RenderNode* target, float value) override; 267*d57664e9SAndroid Build Coastguard Worker 268*d57664e9SAndroid Build Coastguard Worker private: 269*d57664e9SAndroid Build Coastguard Worker int mCenterX, mCenterY; 270*d57664e9SAndroid Build Coastguard Worker }; 271*d57664e9SAndroid Build Coastguard Worker 272*d57664e9SAndroid Build Coastguard Worker } /* namespace uirenderer */ 273*d57664e9SAndroid Build Coastguard Worker } /* namespace android */ 274*d57664e9SAndroid Build Coastguard Worker 275*d57664e9SAndroid Build Coastguard Worker #endif /* ANIMATOR_H */ 276