/**
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.keyframes.model;
import java.util.Comparator;
import java.util.List;
import com.facebook.keyframes.model.keyframedmodels.KeyFramedAnchorPoint;
import com.facebook.keyframes.model.keyframedmodels.KeyFramedMatrixAnimation;
import com.facebook.keyframes.model.keyframedmodels.KeyFramedObject;
import com.facebook.keyframes.model.keyframedmodels.KeyFramedOpacity;
import com.facebook.keyframes.model.keyframedmodels.KeyFramedStrokeWidth;
import com.facebook.keyframes.util.ArgCheckUtil;
import com.facebook.keyframes.util.ListHelper;
/**
* The base class for describing an animated property. This can range from matrix based properties
* such as scale, rotation, position, to others like stroke width.
*/
public class KFAnimation {
public static final Comparator<KFAnimation> ANIMATION_PROPERTY_COMPARATOR =
new Comparator<KFAnimation>() {
@Override
public int compare(
KFAnimation lhs, KFAnimation rhs) {
return lhs.getPropertyType().compareTo(rhs.getPropertyType());
}
};
/**
* Enum for the different supported animation types, listed in order of transform application.
* Standard transform ordering is SCALE * ROTATION * TRANSLATION.
*/
public enum PropertyType {
SCALE (true),
ROTATION (true),
POSITION (true),
X_POSITION (true),
Y_POSITION (true),
ANCHOR_POINT (false),
STROKE_WIDTH (false),
OPACITY (false);
/**
* Whether this animation is matrix based or not. Currently, the only non-matrix based
* animation is stroke width, which is specific to {@link KFFeature}.
*/
final boolean mIsMatrixBased;
PropertyType(boolean isMatrixBased) {
mIsMatrixBased = isMatrixBased;
}
/**
* Returns whether this animation is matrix based or not. Currently, the only non-matrix based
* animation is stroke width, which is specific to {@link KFFeature}.
*/
public boolean isMatrixBased() {
return mIsMatrixBased;
}
}
/**
* The property animated by this KFAnimation instance.
*/
public static final String PROPERTY_TYPE_JSON_FIELD = "property";
private final PropertyType mPropertyType;
/**
* A list of {@link KFAnimationFrame}s, each describing timing and value data for a
* specific key frame.
*/
public static final String ANIMATION_FRAMES_JSON_FIELD = "key_values";
private final List<KFAnimationFrame> mAnimationFrames;
/**
* An array of timing curve data. This array describes transition values between each key frame
* in mAnimationFrames. For each timing curve, there are two sets of points which are the control
* points describing how to draw the cubic curve from (0,0) to (1,1).
*/
public static final String TIMING_CURVES_JSON_FIELD = "timing_curves";
private final float[][][] mTimingCurves;
/**
* An anchor point, which changes the origin of a matrix based property.
* Deprecated in favor of the ANCHOR_POINT animation.
*/
@Deprecated
public static final String ANCHOR_JSON_FIELD = "anchor";
@Deprecated
private final float[] mAnchor;
/**
* A post-processed data structure containing cached information for this key frame animation.
*/
private final KeyFramedObject mKeyFramedAnimation;
public static class Builder {
public PropertyType propertyType;
public List<KFAnimationFrame> animationFrames;
public float[][][] timingCurves;
public float[] anchor;
public KFAnimation build() {
return new KFAnimation(propertyType, animationFrames, timingCurves, anchor);
}
}
public KFAnimation(
PropertyType propertyType,
List<KFAnimationFrame> animationFrames,
float[][][] timingCurves,
float[] anchor) {
mPropertyType = ArgCheckUtil.checkArg(
propertyType,
propertyType != null,
PROPERTY_TYPE_JSON_FIELD);
mAnimationFrames = ArgCheckUtil.checkArg(
ListHelper.immutableOrEmpty(animationFrames),
animationFrames != null && animationFrames.size() > 0,
ANIMATION_FRAMES_JSON_FIELD);
mTimingCurves = ArgCheckUtil.checkArg(
timingCurves,
ArgCheckUtil.checkTimingCurveObjectValidity(timingCurves, mAnimationFrames.size()),
TIMING_CURVES_JSON_FIELD);
mAnchor = ArgCheckUtil.checkArg(
anchor,
anchor == null || anchor.length == 2,
ANCHOR_JSON_FIELD);
if (mPropertyType.isMatrixBased()) {
mKeyFramedAnimation = KeyFramedMatrixAnimation.fromAnimation(this);
} else if (mPropertyType == PropertyType.STROKE_WIDTH){
mKeyFramedAnimation = KeyFramedStrokeWidth.fromAnimation(this);
} else if (mPropertyType == PropertyType.ANCHOR_POINT) {
mKeyFramedAnimation = KeyFramedAnchorPoint.fromAnchorPoint(this);
} else if (mPropertyType == PropertyType.OPACITY) {
mKeyFramedAnimation = KeyFramedOpacity.fromAnimation(this);
} else {
throw new IllegalArgumentException(
"Unknown property type for animation post processing: " + mPropertyType);
}
}
public PropertyType getPropertyType() {
return mPropertyType;
}
public List<KFAnimationFrame> getAnimationFrames() {
return mAnimationFrames;
}
public float[][][] getTimingCurves() {
return mTimingCurves;
}
/**
* Deprecated in favor of the ANCHOR_POINT animation.
*/
@Deprecated
public float[] getAnchor() {
return mAnchor;
}
public KeyFramedObject getAnimation() {
return mKeyFramedAnimation;
}
}