1/*
2 * Copyright (C) 2014 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#ifndef ANIMATOR_H
17#define ANIMATOR_H
18
19#include <memory>
20#include <cutils/compiler.h>
21#include <utils/RefBase.h>
22#include <utils/StrongPointer.h>
23#include <utils/Timers.h>
24
25#include "utils/Macros.h"
26
27#include <vector>
28
29namespace android {
30namespace uirenderer {
31
32class AnimationContext;
33class BaseRenderNodeAnimator;
34class CanvasPropertyPrimitive;
35class CanvasPropertyPaint;
36class Interpolator;
37class RenderNode;
38class RenderProperties;
39
40class AnimationListener : public VirtualLightRefBase {
41public:
42    ANDROID_API virtual void onAnimationFinished(BaseRenderNodeAnimator*) = 0;
43protected:
44    ANDROID_API virtual ~AnimationListener() {}
45};
46
47class BaseRenderNodeAnimator : public VirtualLightRefBase {
48    PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator);
49public:
50    ANDROID_API void setStartValue(float value);
51    ANDROID_API void setInterpolator(Interpolator* interpolator);
52    ANDROID_API void setDuration(nsecs_t durationInMs);
53    ANDROID_API nsecs_t duration() { return mDuration; }
54    ANDROID_API void setStartDelay(nsecs_t startDelayInMs);
55    ANDROID_API nsecs_t startDelay() { return mStartDelay; }
56    ANDROID_API void setListener(AnimationListener* listener) {
57        mListener = listener;
58    }
59    AnimationListener* listener() { return mListener.get(); }
60    ANDROID_API void setAllowRunningAsync(bool mayRunAsync) {
61        mMayRunAsync = mayRunAsync;
62    }
63    bool mayRunAsync() { return mMayRunAsync; }
64    ANDROID_API void start();
65    ANDROID_API void reset();
66    ANDROID_API void reverse();
67    // Terminates the animation at its current progress.
68    ANDROID_API void cancel();
69
70    // Terminates the animation and skip to the end of the animation.
71    ANDROID_API void end();
72
73    void attach(RenderNode* target);
74    virtual void onAttached() {}
75    void detach() { mTarget = nullptr; }
76    void pushStaging(AnimationContext& context);
77    bool animate(AnimationContext& context);
78
79    bool isRunning() { return mPlayState == PlayState::Running
80            || mPlayState == PlayState::Reversing; }
81    bool isFinished() { return mPlayState == PlayState::Finished; }
82    float finalValue() { return mFinalValue; }
83
84    ANDROID_API virtual uint32_t dirtyMask() = 0;
85
86    void forceEndNow(AnimationContext& context);
87    RenderNode* target() { return mTarget; }
88    RenderNode* stagingTarget() { return mStagingTarget; }
89
90protected:
91    // PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI
92    // thread and Render Thread animation state, respectively.
93    // From the UI thread, mStagingPlayState transition looks like
94    // NotStarted -> Running/Reversing -> Finished
95    //                ^                     |
96    //                |                     |
97    //                ----------------------
98    // Note: For mStagingState, the Finished state (optional) is only set when the animation is
99    // terminated by user.
100    //
101    // On Render Thread, mPlayState transition:
102    // NotStart -> Running/Reversing-> Finished
103    //                ^                 |
104    //                |                 |
105    //                ------------------
106    // Note that if the animation is in Running/Reversing state, calling start or reverse again
107    // would do nothing if the animation has the same play direction as the request; otherwise,
108    // the animation would start from where it is and change direction (i.e. Reversing <-> Running)
109
110    enum class PlayState {
111        NotStarted,
112        Running,
113        Reversing,
114        Finished,
115    };
116
117    BaseRenderNodeAnimator(float finalValue);
118    virtual ~BaseRenderNodeAnimator();
119
120    virtual float getValue(RenderNode* target) const = 0;
121    virtual void setValue(RenderNode* target, float value) = 0;
122
123    void callOnFinishedListener(AnimationContext& context);
124
125    virtual void onStagingPlayStateChanged() {}
126    virtual void onPlayTimeChanged(nsecs_t playTime) {}
127    virtual void onPushStaging() {}
128
129    RenderNode* mTarget;
130    RenderNode* mStagingTarget;
131
132    float mFinalValue;
133    float mDeltaValue;
134    float mFromValue;
135
136    std::unique_ptr<Interpolator> mInterpolator;
137    PlayState mStagingPlayState;
138    PlayState mPlayState;
139    bool mHasStartValue;
140    nsecs_t mStartTime;
141    nsecs_t mDuration;
142    nsecs_t mStartDelay;
143    bool mMayRunAsync;
144    // Play Time tracks the progress of animation, it should always be [0, mDuration], 0 being
145    // the beginning of the animation, will reach mDuration at the end of an animation.
146    nsecs_t mPlayTime;
147
148    sp<AnimationListener> mListener;
149
150private:
151    enum class Request {
152        Start,
153        Reverse,
154        Reset,
155        Cancel,
156        End
157    };
158    inline void checkMutable();
159    virtual void transitionToRunning(AnimationContext& context);
160    void doSetStartValue(float value);
161    bool updatePlayTime(nsecs_t playTime);
162    void resolveStagingRequest(Request request);
163
164    std::vector<Request> mStagingRequests;
165
166};
167
168class RenderPropertyAnimator : public BaseRenderNodeAnimator {
169public:
170    enum RenderProperty {
171        TRANSLATION_X = 0,
172        TRANSLATION_Y,
173        TRANSLATION_Z,
174        SCALE_X,
175        SCALE_Y,
176        ROTATION,
177        ROTATION_X,
178        ROTATION_Y,
179        X,
180        Y,
181        Z,
182        ALPHA,
183    };
184
185    ANDROID_API RenderPropertyAnimator(RenderProperty property, float finalValue);
186
187    ANDROID_API virtual uint32_t dirtyMask();
188
189protected:
190    virtual float getValue(RenderNode* target) const override;
191    virtual void setValue(RenderNode* target, float value) override;
192    virtual void onAttached() override;
193    virtual void onStagingPlayStateChanged() override;
194    virtual void onPushStaging() override;
195
196private:
197    typedef bool (RenderProperties::*SetFloatProperty)(float value);
198    typedef float (RenderProperties::*GetFloatProperty)() const;
199
200    struct PropertyAccessors;
201    const PropertyAccessors* mPropertyAccess;
202
203    static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
204    bool mShouldSyncPropertyFields = false;
205    bool mShouldUpdateStagingProperties = false;
206};
207
208class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
209public:
210    ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
211            float finalValue);
212
213    ANDROID_API virtual uint32_t dirtyMask();
214
215protected:
216    virtual float getValue(RenderNode* target) const override;
217    virtual void setValue(RenderNode* target, float value) override;
218private:
219    sp<CanvasPropertyPrimitive> mProperty;
220};
221
222class CanvasPropertyPaintAnimator : public BaseRenderNodeAnimator {
223public:
224    enum PaintField {
225        STROKE_WIDTH = 0,
226        ALPHA,
227    };
228
229    ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
230            PaintField field, float finalValue);
231
232    ANDROID_API virtual uint32_t dirtyMask();
233
234protected:
235    virtual float getValue(RenderNode* target) const override;
236    virtual void setValue(RenderNode* target, float value) override;
237private:
238    sp<CanvasPropertyPaint> mProperty;
239    PaintField mField;
240};
241
242class RevealAnimator : public BaseRenderNodeAnimator {
243public:
244    ANDROID_API RevealAnimator(int centerX, int centerY,
245            float startValue, float finalValue);
246
247    ANDROID_API virtual uint32_t dirtyMask();
248
249protected:
250    virtual float getValue(RenderNode* target) const override;
251    virtual void setValue(RenderNode* target, float value) override;
252
253private:
254    int mCenterX, mCenterY;
255};
256
257} /* namespace uirenderer */
258} /* namespace android */
259
260#endif /* ANIMATOR_H */
261