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