Animator start value...

Change-Id: Ifd35ed95a28c625086d7fa97764fe63ab4a997f1
This commit is contained in:
John Reck
2014-05-14 16:34:14 -07:00
parent 951ecb77c5
commit ff941dcd81
11 changed files with 229 additions and 208 deletions

View File

@@ -21,7 +21,6 @@ import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.util.SparseIntArray;
import android.util.TimeUtils;
import com.android.internal.util.VirtualRefBasePtr;
import com.android.internal.view.animation.FallbackLUTInterpolator;
@@ -72,10 +71,6 @@ public final class RenderNodeAnimator {
put(ViewPropertyAnimator.ALPHA, ALPHA);
}};
// Keep in sync DeltaValueType in Animator.h
public static final int DELTA_TYPE_ABSOLUTE = 0;
public static final int DELTA_TYPE_DELTA = 1;
private VirtualRefBasePtr mNativePtr;
private RenderNode mTarget;
@@ -86,22 +81,21 @@ public final class RenderNodeAnimator {
return sViewPropertyAnimatorMap.get(viewProperty);
}
public RenderNodeAnimator(int property, int deltaType, float deltaValue) {
public RenderNodeAnimator(int property, float finalValue) {
init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this),
property, deltaType, deltaValue));
property, finalValue));
}
public RenderNodeAnimator(CanvasProperty<Float> property, int deltaType, float deltaValue) {
public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) {
init(nCreateCanvasPropertyFloatAnimator(
new WeakReference<RenderNodeAnimator>(this),
property.getNativeContainer(), deltaType, deltaValue));
property.getNativeContainer(), finalValue));
}
public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField,
int deltaType, float deltaValue) {
public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, float finalValue) {
init(nCreateCanvasPropertyPaintAnimator(
new WeakReference<RenderNodeAnimator>(this),
property.getNativeContainer(), paintField, deltaType, deltaValue));
property.getNativeContainer(), paintField, finalValue));
}
private void init(long ptr) {
@@ -182,11 +176,11 @@ public final class RenderNodeAnimator {
}
private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
int property, int deltaValueType, float deltaValue);
int property, float deltaValue);
private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
long canvasProperty, int deltaValueType, float deltaValue);
long canvasProperty, float deltaValue);
private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
long canvasProperty, int paintField, int deltaValueType, float deltaValue);
long canvasProperty, int paintField, float deltaValue);
private static native void nSetDuration(long nativePtr, int duration);
private static native int nGetDuration(long nativePtr);
private static native void nSetInterpolator(long animPtr, long interpolatorPtr);

View File

@@ -80,6 +80,7 @@ static void android_view_RenderNode_setCaching(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean caching) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setCaching(caching);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setStaticMatrix(JNIEnv* env,
@@ -87,6 +88,7 @@ static void android_view_RenderNode_setStaticMatrix(JNIEnv* env,
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
renderNode->mutateStagingProperties().setStaticMatrix(matrix);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
@@ -94,24 +96,28 @@ static void android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
renderNode->mutateStagingProperties().setAnimationMatrix(matrix);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setClipToBounds(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean clipToBounds) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setClipToBounds(clipToBounds);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setProjectBackwards(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean shouldProject) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setProjectBackwards(shouldProject);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setProjectionReceiver(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean shouldRecieve) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setProjectionReceiver(shouldRecieve);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
@@ -119,6 +125,7 @@ static void android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
jint right, jint bottom, jfloat radius) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
@@ -126,18 +133,21 @@ static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
jobject clazz, jlong renderNodePtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutableOutline().setEmpty();
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setClipToOutline(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setRevealClip(JNIEnv* env,
@@ -146,114 +156,133 @@ static void android_view_RenderNode_setRevealClip(JNIEnv* env,
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().mutableRevealClip().set(
shouldClip, inverseClip, x, y, radius);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setAlpha(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float alpha) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setAlpha(alpha);
renderNode->setPropertyFieldsDirty(RenderNode::ALPHA);
}
static void android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env,
jobject clazz, jlong renderNodePtr, bool hasOverlappingRendering) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setHasOverlappingRendering(hasOverlappingRendering);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setElevation(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float elevation) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setElevation(elevation);
renderNode->setPropertyFieldsDirty(RenderNode::Z);
}
static void android_view_RenderNode_setTranslationX(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float tx) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setTranslationX(tx);
renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_X | RenderNode::X);
}
static void android_view_RenderNode_setTranslationY(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float ty) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setTranslationY(ty);
renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_Y | RenderNode::Y);
}
static void android_view_RenderNode_setTranslationZ(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float tz) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setTranslationZ(tz);
renderNode->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z | RenderNode::Z);
}
static void android_view_RenderNode_setRotation(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float rotation) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setRotation(rotation);
renderNode->setPropertyFieldsDirty(RenderNode::ROTATION);
}
static void android_view_RenderNode_setRotationX(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float rx) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setRotationX(rx);
renderNode->setPropertyFieldsDirty(RenderNode::ROTATION_X);
}
static void android_view_RenderNode_setRotationY(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float ry) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setRotationY(ry);
renderNode->setPropertyFieldsDirty(RenderNode::ROTATION_Y);
}
static void android_view_RenderNode_setScaleX(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float sx) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setScaleX(sx);
renderNode->setPropertyFieldsDirty(RenderNode::SCALE_X);
}
static void android_view_RenderNode_setScaleY(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float sy) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setScaleY(sy);
renderNode->setPropertyFieldsDirty(RenderNode::SCALE_Y);
}
static void android_view_RenderNode_setPivotX(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float px) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setPivotX(px);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setPivotY(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float py) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setPivotY(py);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setCameraDistance(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float distance) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setCameraDistance(distance);
renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
}
static void android_view_RenderNode_setLeft(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int left) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setLeft(left);
renderNode->setPropertyFieldsDirty(RenderNode::X);
}
static void android_view_RenderNode_setTop(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int top) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setTop(top);
renderNode->setPropertyFieldsDirty(RenderNode::Y);
}
static void android_view_RenderNode_setRight(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int right) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setRight(right);
renderNode->setPropertyFieldsDirty(RenderNode::X);
}
static void android_view_RenderNode_setBottom(JNIEnv* env,
jobject clazz, jlong renderNodePtr, int bottom) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setBottom(bottom);
renderNode->setPropertyFieldsDirty(RenderNode::Y);
}
static void android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
@@ -261,18 +290,21 @@ static void android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
int right, int bottom) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
}
static void android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float offset) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().offsetLeftRight(offset);
renderNode->setPropertyFieldsDirty(RenderNode::X);
}
static void android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
jobject clazz, jlong renderNodePtr, float offset) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
renderNode->mutateStagingProperties().offsetTopBottom(offset);
renderNode->setPropertyFieldsDirty(RenderNode::Y);
}
// ----------------------------------------------------------------------------

View File

@@ -62,7 +62,7 @@ public:
mWeakThis = NULL;
}
virtual void onAnimationFinished(BaseAnimator*) {
virtual void onAnimationFinished(BaseRenderNodeAnimator*) {
JNIEnv* env = getEnv(mJvm);
env->CallStaticVoidMethod(
gRenderNodeAnimatorClassInfo.clazz,
@@ -81,13 +81,6 @@ static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint prope
return static_cast<RenderPropertyAnimator::RenderProperty>(property);
}
static inline RenderPropertyAnimator::DeltaValueType toDeltaType(jint deltaType) {
LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA
&& deltaType != RenderPropertyAnimator::ABSOLUTE,
"Invalid delta type %d", deltaType);
return static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType);
}
static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) {
LOG_ALWAYS_FATAL_IF(field < 0
|| field > CanvasPropertyPaintAnimator::ALPHA,
@@ -96,49 +89,46 @@ static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) {
}
static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
jint propertyRaw, jint deltaTypeRaw, jfloat deltaValue) {
jint propertyRaw, jfloat finalValue) {
RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw);
RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
BaseAnimator* animator = new RenderPropertyAnimator(property, deltaType, deltaValue);
BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue);
animator->setListener(new AnimationListenerBridge(env, weakThis));
return reinterpret_cast<jlong>( animator );
}
static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz,
jobject weakThis, jlong canvasPropertyPtr, jint deltaTypeRaw, jfloat deltaValue) {
RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
jobject weakThis, jlong canvasPropertyPtr, jfloat finalValue) {
CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr);
BaseAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, deltaType, deltaValue);
BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue);
animator->setListener(new AnimationListenerBridge(env, weakThis));
return reinterpret_cast<jlong>( animator );
}
static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw,
jint deltaTypeRaw, jfloat deltaValue) {
RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
jfloat finalValue) {
CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr);
CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw);
BaseAnimator* animator = new CanvasPropertyPaintAnimator(
canvasProperty, paintField, deltaType, deltaValue);
BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator(
canvasProperty, paintField, finalValue);
animator->setListener(new AnimationListenerBridge(env, weakThis));
return reinterpret_cast<jlong>( animator );
}
static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) {
LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
animator->setDuration(duration);
}
static jint getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) {
BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
return static_cast<jint>(animator->duration());
}
static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) {
BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr);
animator->setInterpolator(interpolator);
}
@@ -153,9 +143,9 @@ const char* const kClassPathName = "android/view/RenderNodeAnimator";
static JNINativeMethod gMethods[] = {
#ifdef USE_OPENGL_RENDERER
{ "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator },
{ "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator },
{ "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator },
{ "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IF)J", (void*) createAnimator },
{ "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JF)J", (void*) createCanvasPropertyFloatAnimator },
{ "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyPaintAnimator },
{ "nSetDuration", "(JI)V", (void*) setDuration },
{ "nGetDuration", "(J)I", (void*) getDuration },
{ "nSetInterpolator", "(JJ)V", (void*) setInterpolator },

View File

@@ -92,9 +92,9 @@ private:
class OnFinishedEvent {
public:
OnFinishedEvent(BaseAnimator* animator, AnimationListener* listener)
OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
: animator(animator), listener(listener) {}
sp<BaseAnimator> animator;
sp<BaseRenderNodeAnimator> animator;
sp<AnimationListener> listener;
};
@@ -127,7 +127,7 @@ public:
virtual ~RootRenderNode() {}
virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) {
virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
OnFinishedEvent event(animator, listener);
mOnFinishedEvents.push_back(event);
}

View File

@@ -27,31 +27,48 @@ namespace android {
namespace uirenderer {
/************************************************************
* Base animator
* BaseRenderNodeAnimator
************************************************************/
BaseAnimator::BaseAnimator()
: mInterpolator(0)
, mPlayState(PENDING)
BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
: mFinalValue(finalValue)
, mDeltaValue(0)
, mFromValue(0)
, mInterpolator(0)
, mPlayState(NEEDS_START)
, mStartTime(0)
, mDuration(300) {
, mDuration(300){
}
BaseAnimator::~BaseAnimator() {
BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
setInterpolator(NULL);
}
void BaseAnimator::setInterpolator(Interpolator* interpolator) {
void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
delete mInterpolator;
mInterpolator = interpolator;
}
void BaseAnimator::setDuration(nsecs_t duration) {
void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
mDuration = duration;
}
bool BaseAnimator::animateFrame(TreeInfo& info) {
void BaseRenderNodeAnimator::setStartValue(float value) {
LOG_ALWAYS_FATAL_IF(mPlayState != NEEDS_START,
"Cannot set the start value after the animator has started!");
mFromValue = value;
mDeltaValue = (mFinalValue - mFromValue);
mPlayState = PENDING;
}
void BaseRenderNodeAnimator::setupStartValueIfNecessary(RenderNode* target, TreeInfo& info) {
if (mPlayState == NEEDS_START) {
setStartValue(getValue(target));
mPlayState = PENDING;
}
}
bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
if (mPlayState == PENDING) {
mPlayState = RUNNING;
mStartTime = info.frameTimeMs;
@@ -59,7 +76,6 @@ bool BaseAnimator::animateFrame(TreeInfo& info) {
if (!mInterpolator) {
setInterpolator(Interpolator::createDefaultInterpolator());
}
onAnimationStarted();
}
float fraction = 1.0f;
@@ -71,17 +87,16 @@ bool BaseAnimator::animateFrame(TreeInfo& info) {
}
}
fraction = mInterpolator->interpolate(fraction);
onAnimationUpdated(fraction);
setValue(target, mFromValue + (mDeltaValue * fraction));
if (mPlayState == FINISHED) {
onAnimationFinished();
callOnFinishedListener(info);
return true;
}
return false;
}
void BaseAnimator::callOnFinishedListener(TreeInfo& info) {
void BaseRenderNodeAnimator::callOnFinishedListener(TreeInfo& info) {
if (mListener.get()) {
if (!info.animationHook) {
mListener->onAnimationFinished(this);
@@ -91,71 +106,50 @@ void BaseAnimator::callOnFinishedListener(TreeInfo& info) {
}
}
/************************************************************
* BaseRenderNodeAnimator
************************************************************/
BaseRenderNodeAnimator::BaseRenderNodeAnimator(
BaseRenderNodeAnimator::DeltaValueType deltaType, float delta)
: mTarget(0)
, mDeltaValueType(deltaType)
, mDeltaValue(delta)
, mFromValue(-1) {
}
bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
mTarget = target;
bool finished = animateFrame(info);
mTarget = NULL;
return finished;
}
void BaseRenderNodeAnimator::onAnimationStarted() {
mFromValue = getValue();
if (mDeltaValueType == BaseRenderNodeAnimator::ABSOLUTE) {
mDeltaValue = (mDeltaValue - mFromValue);
mDeltaValueType = BaseRenderNodeAnimator::DELTA;
}
}
void BaseRenderNodeAnimator::onAnimationUpdated(float fraction) {
float value = mFromValue + (mDeltaValue * fraction);
setValue(value);
}
/************************************************************
* RenderPropertyAnimator
************************************************************/
// Maps RenderProperty enum to accessors
const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::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 },
struct RenderPropertyAnimator::PropertyAccessors {
RenderNode::DirtyPropertyMask dirtyMask;
GetFloatProperty getter;
SetFloatProperty setter;
};
RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
DeltaValueType deltaType, float deltaValue)
: BaseRenderNodeAnimator(deltaType, deltaValue)
, mPropertyAccess(PROPERTY_ACCESSOR_LUT[property]) {
// Maps RenderProperty enum to accessors
const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
{RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
{RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
{RenderNode::TRANSLATION_X, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
{RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX },
{RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY },
{RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation },
{RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX },
{RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY },
{RenderNode::X, &RenderProperties::getX, &RenderProperties::setX },
{RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY },
{RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ },
{RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha },
};
RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
: BaseRenderNodeAnimator(finalValue)
, mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {
}
float RenderPropertyAnimator::getValue() const {
return (target()->animatorProperties().*mPropertyAccess.getter)();
void RenderPropertyAnimator::onAttached(RenderNode* target) {
if (target->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
setStartValue((target->stagingProperties().*mPropertyAccess->getter)());
}
(target->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
}
void RenderPropertyAnimator::setValue(float value) {
(target()->animatorProperties().*mPropertyAccess.setter)(value);
float RenderPropertyAnimator::getValue(RenderNode* target) const {
return (target->properties().*mPropertyAccess->getter)();
}
void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
(target->animatorProperties().*mPropertyAccess->setter)(value);
}
/************************************************************
@@ -163,16 +157,16 @@ void RenderPropertyAnimator::setValue(float value) {
************************************************************/
CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
CanvasPropertyPrimitive* property, DeltaValueType deltaType, float deltaValue)
: BaseRenderNodeAnimator(deltaType, deltaValue)
CanvasPropertyPrimitive* property, float finalValue)
: BaseRenderNodeAnimator(finalValue)
, mProperty(property) {
}
float CanvasPropertyPrimitiveAnimator::getValue() const {
float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
return mProperty->value;
}
void CanvasPropertyPrimitiveAnimator::setValue(float value) {
void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) {
mProperty->value = value;
}
@@ -181,14 +175,13 @@ void CanvasPropertyPrimitiveAnimator::setValue(float value) {
************************************************************/
CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
CanvasPropertyPaint* property, PaintField field,
DeltaValueType deltaType, float deltaValue)
: BaseRenderNodeAnimator(deltaType, deltaValue)
CanvasPropertyPaint* property, PaintField field, float finalValue)
: BaseRenderNodeAnimator(finalValue)
, mProperty(property)
, mField(field) {
}
float CanvasPropertyPaintAnimator::getValue() const {
float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
switch (mField) {
case STROKE_WIDTH:
return mProperty->value.getStrokeWidth();
@@ -204,7 +197,7 @@ static uint8_t to_uint8(float value) {
return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c );
}
void CanvasPropertyPaintAnimator::setValue(float value) {
void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
switch (mField) {
case STROKE_WIDTH:
mProperty->value.setStrokeWidth(value);

View File

@@ -33,16 +33,14 @@ class RenderProperties;
class AnimationListener : public VirtualLightRefBase {
public:
ANDROID_API virtual void onAnimationFinished(BaseAnimator*) = 0;
ANDROID_API virtual void onAnimationFinished(BaseRenderNodeAnimator*) = 0;
protected:
ANDROID_API virtual ~AnimationListener() {}
};
// Helper class to contain generic animator helpers
class BaseAnimator : public VirtualLightRefBase {
PREVENT_COPY_AND_ASSIGN(BaseAnimator);
class BaseRenderNodeAnimator : public VirtualLightRefBase {
PREVENT_COPY_AND_ASSIGN(BaseRenderNodeAnimator);
public:
ANDROID_API void setInterpolator(Interpolator* interpolator);
ANDROID_API void setDuration(nsecs_t durationInMs);
ANDROID_API nsecs_t duration() { return mDuration; }
@@ -50,31 +48,38 @@ public:
mListener = listener;
}
ANDROID_API virtual void onAttached(RenderNode* target) {}
// Guaranteed to happen before the staging push
void setupStartValueIfNecessary(RenderNode* target, TreeInfo& info);
bool animate(RenderNode* target, TreeInfo& info);
bool isFinished() { return mPlayState == FINISHED; }
float finalValue() { return mFinalValue; }
protected:
BaseAnimator();
virtual ~BaseAnimator();
BaseRenderNodeAnimator(float finalValue);
virtual ~BaseRenderNodeAnimator();
// 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(TreeInfo& info);
// Called when PlayState switches from PENDING to RUNNING
virtual void onAnimationStarted() {}
virtual void onAnimationUpdated(float fraction) = 0;
virtual void onAnimationFinished() {}
void setStartValue(float value);
virtual float getValue(RenderNode* target) const = 0;
virtual void setValue(RenderNode* target, float value) = 0;
private:
void callOnFinishedListener(TreeInfo& info);
enum PlayState {
NEEDS_START,
PENDING,
RUNNING,
FINISHED,
};
float mFinalValue;
float mDeltaValue;
float mFromValue;
Interpolator* mInterpolator;
PlayState mPlayState;
long mStartTime;
@@ -83,42 +88,6 @@ private:
sp<AnimationListener> mListener;
};
class BaseRenderNodeAnimator : public BaseAnimator {
public:
// Since the UI thread doesn't necessarily know what the current values
// actually are and thus can't do the calculations, this is used to inform
// the animator how to lazy-resolve the input value
enum DeltaValueType {
// The delta value represents an absolute value endpoint
// mDeltaValue needs to be recalculated to be mDelta = (mDelta - fromValue)
// in onAnimationStarted()
ABSOLUTE = 0,
// The final value represents an offset from the current value
// No recalculation is needed
DELTA,
};
bool animate(RenderNode* target, TreeInfo& info);
protected:
BaseRenderNodeAnimator(DeltaValueType deltaType, float deltaValue);
RenderNode* target() const { return mTarget; }
virtual float getValue() const = 0;
virtual void setValue(float value) = 0;
private:
virtual void onAnimationStarted();
virtual void onAnimationUpdated(float fraction);
// mTarget is only valid inside animate()
RenderNode* mTarget;
BaseRenderNodeAnimator::DeltaValueType mDeltaValueType;
float mDeltaValue;
float mFromValue;
};
class RenderPropertyAnimator : public BaseRenderNodeAnimator {
public:
enum RenderProperty {
@@ -136,23 +105,20 @@ public:
ALPHA,
};
ANDROID_API RenderPropertyAnimator(RenderProperty property,
DeltaValueType deltaType, float deltaValue);
ANDROID_API RenderPropertyAnimator(RenderProperty property, float finalValue);
ANDROID_API virtual void onAttached(RenderNode* target);
protected:
ANDROID_API virtual float getValue() const;
ANDROID_API virtual void setValue(float value);
virtual float getValue(RenderNode* target) const;
virtual void setValue(RenderNode* target, float value);
private:
typedef void (RenderProperties::*SetFloatProperty)(float value);
typedef float (RenderProperties::*GetFloatProperty)() const;
struct PropertyAccessors {
GetFloatProperty getter;
SetFloatProperty setter;
};
PropertyAccessors mPropertyAccess;
struct PropertyAccessors;
const PropertyAccessors* mPropertyAccess;
static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
};
@@ -160,10 +126,10 @@ private:
class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
public:
ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
DeltaValueType deltaType, float deltaValue);
float finalValue);
protected:
ANDROID_API virtual float getValue() const;
ANDROID_API virtual void setValue(float value);
virtual float getValue(RenderNode* target) const;
virtual void setValue(RenderNode* target, float value);
private:
sp<CanvasPropertyPrimitive> mProperty;
};
@@ -176,10 +142,10 @@ public:
};
ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
PaintField field, DeltaValueType deltaType, float deltaValue);
PaintField field, float finalValue);
protected:
ANDROID_API virtual float getValue() const;
ANDROID_API virtual void setValue(float value);
virtual float getValue(RenderNode* target) const;
virtual void setValue(RenderNode* target, float value);
private:
sp<CanvasPropertyPaint> mProperty;
PaintField mField;

View File

@@ -53,7 +53,7 @@ void RenderNode::outputLogBuffer(int fd) {
}
RenderNode::RenderNode()
: mNeedsPropertiesSync(false)
: mDirtyPropertyFields(0)
, mNeedsDisplayListDataSync(false)
, mDisplayListData(0)
, mStagingDisplayListData(0)
@@ -109,23 +109,37 @@ void RenderNode::prepareTreeImpl(TreeInfo& info) {
prepareSubTree(info, mDisplayListData);
}
static bool is_finished(const sp<BaseRenderNodeAnimator>& animator) {
return animator->isFinished();
}
class PushAnimatorsFunctor {
public:
PushAnimatorsFunctor(RenderNode* target, TreeInfo& info)
: mTarget(target), mInfo(info) {}
bool operator() (const sp<BaseRenderNodeAnimator>& animator) {
animator->setupStartValueIfNecessary(mTarget, mInfo);
return animator->isFinished();
}
private:
RenderNode* mTarget;
TreeInfo& mInfo;
};
void RenderNode::pushStagingChanges(TreeInfo& info) {
if (mNeedsPropertiesSync) {
mNeedsPropertiesSync = false;
mProperties = mStagingProperties;
}
// Push the animators first so that setupStartValueIfNecessary() is called
// before properties() is trampled by stagingProperties(), as they are
// required by some animators.
if (mNeedsAnimatorsSync) {
mAnimators.resize(mStagingAnimators.size());
std::vector< sp<BaseRenderNodeAnimator> >::iterator it;
PushAnimatorsFunctor functor(this, info);
// hint: this means copy_if_not()
it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
mAnimators.begin(), is_finished);
mAnimators.begin(), functor);
mAnimators.resize(std::distance(mAnimators.begin(), it));
}
if (mDirtyPropertyFields) {
mDirtyPropertyFields = 0;
mProperties = mStagingProperties;
}
if (mNeedsDisplayListDataSync) {
mNeedsDisplayListDataSync = false;
// Do a push pass on the old tree to handle freeing DisplayListData
@@ -144,7 +158,7 @@ public:
AnimateFunctor(RenderNode* target, TreeInfo& info)
: mTarget(target), mInfo(info) {}
bool operator() (sp<BaseRenderNodeAnimator>& animator) {
bool operator() (const sp<BaseRenderNodeAnimator>& animator) {
return animator->animate(mTarget, mInfo);
}
private:

View File

@@ -82,6 +82,22 @@ class DrawDisplayListOp;
*/
class RenderNode : public VirtualLightRefBase {
public:
enum DirtyPropertyMask {
GENERIC = 1 << 1,
TRANSLATION_X = 1 << 2,
TRANSLATION_Y = 1 << 3,
TRANSLATION_Z = 1 << 4,
SCALE_X = 1 << 5,
SCALE_Y = 1 << 6,
ROTATION = 1 << 7,
ROTATION_X = 1 << 8,
ROTATION_Y = 1 << 9,
X = 1 << 10,
Y = 1 << 11,
Z = 1 << 12,
ALPHA = 1 << 13,
};
ANDROID_API RenderNode();
ANDROID_API virtual ~RenderNode();
@@ -123,6 +139,14 @@ public:
}
}
bool isPropertyFieldDirty(DirtyPropertyMask field) const {
return mDirtyPropertyFields & field;
}
void setPropertyFieldsDirty(uint32_t fields) {
mDirtyPropertyFields |= fields;
}
const RenderProperties& properties() {
return mProperties;
}
@@ -136,7 +160,6 @@ public:
}
RenderProperties& mutateStagingProperties() {
mNeedsPropertiesSync = true;
return mStagingProperties;
}
@@ -152,6 +175,7 @@ public:
// UI thread only!
ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
animator->onAttached(this);
mStagingAnimators.insert(animator);
mNeedsAnimatorsSync = true;
}
@@ -227,7 +251,7 @@ private:
String8 mName;
bool mNeedsPropertiesSync;
uint32_t mDirtyPropertyFields;
RenderProperties mProperties;
RenderProperties mStagingProperties;

View File

@@ -21,12 +21,12 @@
namespace android {
namespace uirenderer {
class BaseAnimator;
class BaseRenderNodeAnimator;
class AnimationListener;
class AnimationHook {
public:
virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) = 0;
virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) = 0;
protected:
~AnimationHook() {}
};

View File

@@ -109,26 +109,27 @@ public class CirclePropActivity extends Activity {
mToggle = !mToggle;
mRunningAnimations.add(new RenderNodeAnimator(
mX, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 400.0f : 200.0f));
mX, mToggle ? 400.0f : 200.0f));
mRunningAnimations.add(new RenderNodeAnimator(
mY, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 600.0f : 200.0f));
mY, mToggle ? 600.0f : 200.0f));
mRunningAnimations.add(new RenderNodeAnimator(
mRadius, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 250.0f : 150.0f));
mRadius, mToggle ? 250.0f : 150.0f));
mRunningAnimations.add(new RenderNodeAnimator(
mPaint, RenderNodeAnimator.PAINT_ALPHA,
RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 64.0f : 255.0f));
mToggle ? 64.0f : 255.0f));
mRunningAnimations.add(new RenderNodeAnimator(
mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH,
RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 5.0f : 60.0f));
mToggle ? 5.0f : 60.0f));
TimeInterpolator interp = new OvershootInterpolator(3.0f);
for (int i = 0; i < mRunningAnimations.size(); i++) {
RenderNodeAnimator anim = mRunningAnimations.get(i);
anim.setInterpolator(interp);
anim.setDuration(1000);
anim.start(this);
}

View File

@@ -5,6 +5,7 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.HardwareRenderer;
import android.view.RenderNodeAnimator;
import android.view.View;
@@ -73,14 +74,20 @@ public class MainActivity extends Activity implements OnItemClickListener {
float delta = (pos - clickedPosition) * 1.1f;
if (delta == 0) delta = -1;
RenderNodeAnimator animator = new RenderNodeAnimator(
RenderNodeAnimator.TRANSLATION_Y, RenderNodeAnimator.DELTA_TYPE_DELTA, dy * delta);
RenderNodeAnimator.TRANSLATION_Y, dy * delta);
animator.setDuration(DURATION);
if (child == clickedView) logTranslationY(clickedView);
animator.start(child);
if (child == clickedView) logTranslationY(clickedView);
}
//mHandler.postDelayed(mLaunchActivity, (long) (DURATION * .4));
mLaunchActivity.run();
}
private void logTranslationY(View v) {
Log.d("RTTest", "View has translationY: " + v.getTranslationY());
}
private Runnable mLaunchActivity = new Runnable() {
@Override