blob: ee16586e7366c3d576d0a7f076751e23c11f515e [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.
*/
#define LOG_TAG "RT-Animator"
#include "Animator.h"
#include <set>
#include "RenderProperties.h"
namespace android {
namespace uirenderer {
/************************************************************
* Private header
************************************************************/
typedef void (RenderProperties::*SetFloatProperty)(float value);
typedef float (RenderProperties::*GetFloatProperty)() const;
struct PropertyAccessors {
GetFloatProperty getter;
SetFloatProperty setter;
};
// Maps RenderProperty enum to accessors
static const PropertyAccessors PROPERTY_ACCESSOR_LUT[] = {
{&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
{&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
{&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
{&RenderProperties::getScaleX, &RenderProperties::setScaleX },
{&RenderProperties::getScaleY, &RenderProperties::setScaleY },
{&RenderProperties::getRotation, &RenderProperties::setRotation },
{&RenderProperties::getRotationX, &RenderProperties::setRotationX },
{&RenderProperties::getRotationY, &RenderProperties::setRotationY },
{&RenderProperties::getX, &RenderProperties::setX },
{&RenderProperties::getY, &RenderProperties::setY },
{&RenderProperties::getZ, &RenderProperties::setZ },
{&RenderProperties::getAlpha, &RenderProperties::setAlpha },
};
// Helper class to contain generic animator helpers
class BaseAnimator {
public:
BaseAnimator();
virtual ~BaseAnimator();
void setInterpolator(Interpolator* interpolator);
void setDuration(nsecs_t durationInMs);
bool isFinished() { return mPlayState == FINISHED; }
protected:
// This is the main animation entrypoint that subclasses should call
// to generate the onAnimation* lifecycle events
// Returns true if the animation has finished, false otherwise
bool animateFrame(nsecs_t frameTime);
// Called when PlayState switches from PENDING to RUNNING
virtual void onAnimationStarted() {}
virtual void onAnimationUpdated(float fraction) = 0;
virtual void onAnimationFinished() {}
private:
enum PlayState {
PENDING,
RUNNING,
FINISHED,
};
Interpolator* mInterpolator;
PlayState mPlayState;
long mStartTime;
long mDuration;
};
// Hide the base classes & private bits from the exported RenderPropertyAnimator
// in this Impl class so that subclasses of RenderPropertyAnimator don't require
// knowledge of the inner guts but only the public virtual methods.
// Animates a single property
class RenderPropertyAnimatorImpl : public BaseAnimator {
public:
RenderPropertyAnimatorImpl(GetFloatProperty getter, SetFloatProperty setter,
RenderPropertyAnimator::DeltaValueType deltaType, float delta);
~RenderPropertyAnimatorImpl();
bool animate(RenderProperties* target, TreeInfo& info);
protected:
virtual void onAnimationStarted();
virtual void onAnimationUpdated(float fraction);
private:
// mTarget is only valid inside animate()
RenderProperties* mTarget;
GetFloatProperty mGetter;
SetFloatProperty mSetter;
RenderPropertyAnimator::DeltaValueType mDeltaValueType;
float mDeltaValue;
float mFromValue;
};
RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
DeltaValueType deltaType, float deltaValue) {
PropertyAccessors pa = PROPERTY_ACCESSOR_LUT[property];
mImpl = new RenderPropertyAnimatorImpl(pa.getter, pa.setter, deltaType, deltaValue);
}
RenderPropertyAnimator::~RenderPropertyAnimator() {
delete mImpl;
mImpl = NULL;
}
void RenderPropertyAnimator::setInterpolator(Interpolator* interpolator) {
mImpl->setInterpolator(interpolator);
}
void RenderPropertyAnimator::setDuration(nsecs_t durationInMs) {
mImpl->setDuration(durationInMs);
}
bool RenderPropertyAnimator::isFinished() {
return mImpl->isFinished();
}
bool RenderPropertyAnimator::animate(RenderProperties* target, TreeInfo& info) {
return mImpl->animate(target, info);
}
/************************************************************
* Base animator
************************************************************/
BaseAnimator::BaseAnimator()
: mInterpolator(0)
, mPlayState(PENDING)
, mStartTime(0)
, mDuration(300) {
}
BaseAnimator::~BaseAnimator() {
setInterpolator(NULL);
}
void BaseAnimator::setInterpolator(Interpolator* interpolator) {
delete mInterpolator;
mInterpolator = interpolator;
}
void BaseAnimator::setDuration(nsecs_t duration) {
mDuration = duration;
}
bool BaseAnimator::animateFrame(nsecs_t frameTime) {
if (mPlayState == PENDING) {
mPlayState = RUNNING;
mStartTime = frameTime;
// No interpolator was set, use the default
if (!mInterpolator) {
setInterpolator(Interpolator::createDefaultInterpolator());
}
onAnimationStarted();
}
float fraction = 1.0f;
if (mPlayState == RUNNING) {
fraction = mDuration > 0 ? (float)(frameTime - mStartTime) / mDuration : 1.0f;
if (fraction >= 1.0f) {
fraction = 1.0f;
mPlayState = FINISHED;
}
}
fraction = mInterpolator->interpolate(fraction);
onAnimationUpdated(fraction);
if (mPlayState == FINISHED) {
onAnimationFinished();
return true;
}
return false;
}
/************************************************************
* RenderPropertyAnimator
************************************************************/
RenderPropertyAnimatorImpl::RenderPropertyAnimatorImpl(
GetFloatProperty getter, SetFloatProperty setter,
RenderPropertyAnimator::DeltaValueType deltaType, float delta)
: mTarget(0)
, mGetter(getter)
, mSetter(setter)
, mDeltaValueType(deltaType)
, mDeltaValue(delta)
, mFromValue(-1) {
}
RenderPropertyAnimatorImpl::~RenderPropertyAnimatorImpl() {
}
bool RenderPropertyAnimatorImpl::animate(RenderProperties* target, TreeInfo& info) {
mTarget = target;
bool finished = animateFrame(info.frameTimeMs);
mTarget = NULL;
return finished;
}
void RenderPropertyAnimatorImpl::onAnimationStarted() {
mFromValue = (mTarget->*mGetter)();
if (mDeltaValueType == RenderPropertyAnimator::ABSOLUTE) {
mDeltaValue = (mDeltaValue - mFromValue);
mDeltaValueType = RenderPropertyAnimator::DELTA;
}
}
void RenderPropertyAnimatorImpl::onAnimationUpdated(float fraction) {
float value = mFromValue + (mDeltaValue * fraction);
(mTarget->*mSetter)(value);
}
} /* namespace uirenderer */
} /* namespace android */