blob: 2c9c9c3fe0f9d60a766d4341fb26c92482804743 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANIMATOR_H
#define ANIMATOR_H
#include <memory>
#include <cutils/compiler.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
#include "utils/Macros.h"
namespace android {
namespace uirenderer {
class AnimationContext;
class BaseRenderNodeAnimator;
class CanvasPropertyPrimitive;
class CanvasPropertyPaint;
class Interpolator;
class RenderNode;
class RenderProperties;
class AnimationListener : public VirtualLightRefBase {
public:
ANDROID_API virtual void onAnimationFinished(BaseRenderNodeAnimator*) = 0;
protected:
ANDROID_API virtual ~AnimationListener() {}
};
class BaseRenderNodeAnimator : public VirtualLightRefBase {
PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator);
public:
ANDROID_API void setStartValue(float value);
ANDROID_API void setInterpolator(Interpolator* interpolator);
ANDROID_API void setDuration(nsecs_t durationInMs);
ANDROID_API nsecs_t duration() { return mDuration; }
ANDROID_API void setStartDelay(nsecs_t startDelayInMs);
ANDROID_API nsecs_t startDelay() { return mStartDelay; }
ANDROID_API void setListener(AnimationListener* listener) {
mListener = listener;
}
AnimationListener* listener() { return mListener.get(); }
ANDROID_API void setAllowRunningAsync(bool mayRunAsync) {
mMayRunAsync = mayRunAsync;
}
bool mayRunAsync() { return mMayRunAsync; }
ANDROID_API void start() {
if (mStagingPlayState == PlayState::NotStarted) {
mStagingPlayState = PlayState::Running;
} else {
mStagingPlayState = PlayState::Restarted;
}
onStagingPlayStateChanged(); }
ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); }
void attach(RenderNode* target);
virtual void onAttached() {}
void detach() { mTarget = nullptr; }
void pushStaging(AnimationContext& context);
bool animate(AnimationContext& context);
bool isRunning() { return mPlayState == PlayState::Running; }
bool isFinished() { return mPlayState == PlayState::Finished; }
float finalValue() { return mFinalValue; }
ANDROID_API virtual uint32_t dirtyMask() = 0;
void forceEndNow(AnimationContext& context);
protected:
// PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI
// thread and Render Thread animation state, respectively.
// From the UI thread, mStagingPlayState transition looks like
// NotStarted -> Running -> Finished
// ^ |
// | |
// Restarted <------
// Note: For mStagingState, the Finished state (optional) is only set when the animation is
// terminated by user.
//
// On Render Thread, mPlayState transition:
// NotStart -> Running -> Finished
// ^ |
// | |
// -------------
enum class PlayState {
NotStarted,
Running,
Finished,
Restarted,
};
BaseRenderNodeAnimator(float finalValue);
virtual ~BaseRenderNodeAnimator();
virtual float getValue(RenderNode* target) const = 0;
virtual void setValue(RenderNode* target, float value) = 0;
RenderNode* target() { return mTarget; }
void callOnFinishedListener(AnimationContext& context);
virtual void onStagingPlayStateChanged() {}
virtual void onPlayTimeChanged(nsecs_t playTime) {}
RenderNode* mTarget;
float mFinalValue;
float mDeltaValue;
float mFromValue;
std::unique_ptr<Interpolator> mInterpolator;
PlayState mStagingPlayState;
PlayState mPlayState;
bool mHasStartValue;
nsecs_t mStartTime;
nsecs_t mDuration;
nsecs_t mStartDelay;
bool mMayRunAsync;
sp<AnimationListener> mListener;
private:
inline void checkMutable();
virtual void transitionToRunning(AnimationContext& context);
void doSetStartValue(float value);
};
class RenderPropertyAnimator : public BaseRenderNodeAnimator {
public:
enum RenderProperty {
TRANSLATION_X = 0,
TRANSLATION_Y,
TRANSLATION_Z,
SCALE_X,
SCALE_Y,
ROTATION,
ROTATION_X,
ROTATION_Y,
X,
Y,
Z,
ALPHA,
};
ANDROID_API RenderPropertyAnimator(RenderProperty property, float finalValue);
ANDROID_API virtual uint32_t dirtyMask();
protected:
virtual float getValue(RenderNode* target) const override;
virtual void setValue(RenderNode* target, float value) override;
virtual void onAttached() override;
virtual void onStagingPlayStateChanged() override;
private:
typedef bool (RenderProperties::*SetFloatProperty)(float value);
typedef float (RenderProperties::*GetFloatProperty)() const;
struct PropertyAccessors;
const PropertyAccessors* mPropertyAccess;
static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
};
class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
public:
ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
float finalValue);
ANDROID_API virtual uint32_t dirtyMask();
protected:
virtual float getValue(RenderNode* target) const override;
virtual void setValue(RenderNode* target, float value) override;
private:
sp<CanvasPropertyPrimitive> mProperty;
};
class CanvasPropertyPaintAnimator : public BaseRenderNodeAnimator {
public:
enum PaintField {
STROKE_WIDTH = 0,
ALPHA,
};
ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
PaintField field, float finalValue);
ANDROID_API virtual uint32_t dirtyMask();
protected:
virtual float getValue(RenderNode* target) const override;
virtual void setValue(RenderNode* target, float value) override;
private:
sp<CanvasPropertyPaint> mProperty;
PaintField mField;
};
class RevealAnimator : public BaseRenderNodeAnimator {
public:
ANDROID_API RevealAnimator(int centerX, int centerY,
float startValue, float finalValue);
ANDROID_API virtual uint32_t dirtyMask();
protected:
virtual float getValue(RenderNode* target) const override;
virtual void setValue(RenderNode* target, float value) override;
private:
int mCenterX, mCenterY;
};
} /* namespace uirenderer */
} /* namespace android */
#endif /* ANIMATOR_H */