Generalize KeyframeAnimatorBuilder to AnimatorBuilder
Change-Id: I116489a1261a93d9b2513ca53f04e1305e6fd85b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/432957 Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Avinash Parchuri <aparchur@google.com> Commit-Queue: Avinash Parchuri <aparchur@google.com>
This commit is contained in:
parent
6bf9189ae5
commit
6bbd7df9fb
@ -49,7 +49,7 @@ void AnimatablePropertyContainer::shrink_to_fit() {
|
||||
|
||||
bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder,
|
||||
const skjson::ObjectValue* jprop,
|
||||
KeyframeAnimatorBuilder& builder) {
|
||||
AnimatorBuilder& builder) {
|
||||
if (!jprop) {
|
||||
return false;
|
||||
}
|
||||
@ -80,7 +80,7 @@ bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder,
|
||||
sk_sp<KeyframeAnimator> animator;
|
||||
const skjson::ArrayValue* jkfs = jpropK;
|
||||
if (jkfs && jkfs->size() > 0) {
|
||||
animator = builder.make(abuilder, *jkfs);
|
||||
animator = builder.makeFromKeyframes(abuilder, *jkfs);
|
||||
}
|
||||
|
||||
if (!animator) {
|
||||
|
@ -24,7 +24,7 @@ namespace skottie {
|
||||
namespace internal {
|
||||
|
||||
class AnimationBuilder;
|
||||
class KeyframeAnimatorBuilder;
|
||||
class AnimatorBuilder;
|
||||
|
||||
class Animator : public SkRefCnt {
|
||||
public:
|
||||
@ -72,7 +72,7 @@ protected:
|
||||
private:
|
||||
StateChanged onSeek(float) final;
|
||||
|
||||
bool bindImpl(const AnimationBuilder&, const skjson::ObjectValue*, KeyframeAnimatorBuilder&);
|
||||
bool bindImpl(const AnimationBuilder&, const skjson::ObjectValue*, AnimatorBuilder&);
|
||||
|
||||
std::vector<sk_sp<Animator>> fAnimators;
|
||||
bool fHasSynced = false;
|
||||
|
@ -86,9 +86,9 @@ float KeyframeAnimator::compute_weight(const KFSegment &seg, float t) const {
|
||||
return w;
|
||||
}
|
||||
|
||||
KeyframeAnimatorBuilder::~KeyframeAnimatorBuilder() = default;
|
||||
AnimatorBuilder::~AnimatorBuilder() = default;
|
||||
|
||||
bool KeyframeAnimatorBuilder::parseKeyframes(const AnimationBuilder& abuilder,
|
||||
bool AnimatorBuilder::parseKeyframes(const AnimationBuilder& abuilder,
|
||||
const skjson::ArrayValue& jkfs) {
|
||||
// Keyframe format:
|
||||
//
|
||||
@ -196,7 +196,7 @@ bool KeyframeAnimatorBuilder::parseKeyframes(const AnimationBuilder& abuilder,
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t KeyframeAnimatorBuilder::parseMapping(const skjson::ObjectValue& jkf) {
|
||||
uint32_t AnimatorBuilder::parseMapping(const skjson::ObjectValue& jkf) {
|
||||
if (ParseDefault(jkf["h"], false)) {
|
||||
return Keyframe::kConstantMapping;
|
||||
}
|
||||
|
@ -104,11 +104,11 @@ private:
|
||||
mutable KFSegment fCurrentSegment = { nullptr, nullptr }; // Cached segment.
|
||||
};
|
||||
|
||||
class KeyframeAnimatorBuilder : public SkNoncopyable {
|
||||
class AnimatorBuilder : public SkNoncopyable {
|
||||
public:
|
||||
virtual ~KeyframeAnimatorBuilder();
|
||||
virtual ~AnimatorBuilder();
|
||||
|
||||
virtual sk_sp<KeyframeAnimator> make(const AnimationBuilder&, const skjson::ArrayValue&) = 0;
|
||||
virtual sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder&, const skjson::ArrayValue&) = 0;
|
||||
|
||||
virtual bool parseValue(const AnimationBuilder&, const skjson::Value&) const = 0;
|
||||
|
||||
|
@ -14,14 +14,36 @@ namespace skottie::internal {
|
||||
|
||||
namespace {
|
||||
|
||||
// Scalar specialization: stores scalar values (floats) inline in keyframes.
|
||||
// Scalar specialization: stores scalar values (floats) inline in keyframes.
|
||||
class ScalarKeyframeAnimator final : public KeyframeAnimator {
|
||||
public:
|
||||
class Builder final : public KeyframeAnimatorBuilder {
|
||||
public:
|
||||
explicit Builder(ScalarValue* target) : fTarget(target) {}
|
||||
ScalarKeyframeAnimator(std::vector<Keyframe> kfs,
|
||||
std::vector<SkCubicMap> cms,
|
||||
ScalarValue* target_value)
|
||||
: INHERITED(std::move(kfs), std::move(cms))
|
||||
, fTarget(target_value) {}
|
||||
|
||||
sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder,
|
||||
private:
|
||||
|
||||
StateChanged onSeek(float t) override {
|
||||
const auto& lerp_info = this->getLERPInfo(t);
|
||||
const auto old_value = *fTarget;
|
||||
|
||||
*fTarget = Lerp(lerp_info.vrec0.flt, lerp_info.vrec1.flt, lerp_info.weight);
|
||||
|
||||
return *fTarget != old_value;
|
||||
}
|
||||
|
||||
ScalarValue* fTarget;
|
||||
|
||||
using INHERITED = KeyframeAnimator;
|
||||
};
|
||||
|
||||
class ScalarAnimatorBuilder final : public AnimatorBuilder {
|
||||
public:
|
||||
explicit ScalarAnimatorBuilder(ScalarValue* target) : fTarget(target) {}
|
||||
|
||||
sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder& abuilder,
|
||||
const skjson::ArrayValue& jkfs) override {
|
||||
SkASSERT(jkfs.size() > 0);
|
||||
if (!this->parseKeyframes(abuilder, jkfs)) {
|
||||
@ -47,34 +69,13 @@ public:
|
||||
ScalarValue* fTarget;
|
||||
};
|
||||
|
||||
private:
|
||||
ScalarKeyframeAnimator(std::vector<Keyframe> kfs,
|
||||
std::vector<SkCubicMap> cms,
|
||||
ScalarValue* target_value)
|
||||
: INHERITED(std::move(kfs), std::move(cms))
|
||||
, fTarget(target_value) {}
|
||||
|
||||
StateChanged onSeek(float t) override {
|
||||
const auto& lerp_info = this->getLERPInfo(t);
|
||||
const auto old_value = *fTarget;
|
||||
|
||||
*fTarget = Lerp(lerp_info.vrec0.flt, lerp_info.vrec1.flt, lerp_info.weight);
|
||||
|
||||
return *fTarget != old_value;
|
||||
}
|
||||
|
||||
ScalarValue* fTarget;
|
||||
|
||||
using INHERITED = KeyframeAnimator;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
bool AnimatablePropertyContainer::bind<ScalarValue>(const AnimationBuilder& abuilder,
|
||||
const skjson::ObjectValue* jprop,
|
||||
ScalarValue* v) {
|
||||
ScalarKeyframeAnimator::Builder builder(v);
|
||||
ScalarAnimatorBuilder builder(v);
|
||||
|
||||
return this->bindImpl(abuilder, jprop, builder);
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ template <>
|
||||
bool AnimatablePropertyContainer::bind<ShapeValue>(const AnimationBuilder& abuilder,
|
||||
const skjson::ObjectValue* jprop,
|
||||
ShapeValue* v) {
|
||||
VectorKeyframeAnimatorBuilder builder(v, parse_encoding_len, parse_encoding_data);
|
||||
VectorAnimatorBuilder builder(v, parse_encoding_len, parse_encoding_data);
|
||||
|
||||
return this->bindImpl(abuilder, jprop, builder);
|
||||
}
|
||||
|
@ -13,65 +13,15 @@
|
||||
namespace skottie::internal {
|
||||
|
||||
namespace {
|
||||
|
||||
class TextKeyframeAnimator final : public KeyframeAnimator {
|
||||
public:
|
||||
class Builder final : public KeyframeAnimatorBuilder {
|
||||
public:
|
||||
explicit Builder(TextValue* target) : fTarget(target) {}
|
||||
|
||||
sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder,
|
||||
const skjson::ArrayValue& jkfs) override {
|
||||
SkASSERT(jkfs.size() > 0);
|
||||
|
||||
fValues.reserve(jkfs.size());
|
||||
if (!this->parseKeyframes(abuilder, jkfs)) {
|
||||
return nullptr;
|
||||
}
|
||||
fValues.shrink_to_fit();
|
||||
|
||||
return sk_sp<TextKeyframeAnimator>(
|
||||
new TextKeyframeAnimator(std::move(fKFs),
|
||||
std::move(fCMs),
|
||||
std::move(fValues),
|
||||
fTarget));
|
||||
}
|
||||
|
||||
bool parseValue(const AnimationBuilder& abuilder, const skjson::Value& jv) const override {
|
||||
return Parse(jv, abuilder, fTarget);
|
||||
}
|
||||
|
||||
private:
|
||||
bool parseKFValue(const AnimationBuilder& abuilder,
|
||||
const skjson::ObjectValue&,
|
||||
const skjson::Value& jv,
|
||||
Keyframe::Value* v) override {
|
||||
TextValue val;
|
||||
if (!Parse(jv, abuilder, &val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: full deduping?
|
||||
if (fValues.empty() || val != fValues.back()) {
|
||||
fValues.push_back(std::move(val));
|
||||
}
|
||||
|
||||
v->idx = SkToU32(fValues.size() - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<TextValue> fValues;
|
||||
TextValue* fTarget;
|
||||
};
|
||||
|
||||
private:
|
||||
TextKeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms,
|
||||
std::vector<TextValue> vs, TextValue* target_value)
|
||||
: INHERITED(std::move(kfs), std::move(cms))
|
||||
, fValues(std::move(vs))
|
||||
, fTarget(target_value) {}
|
||||
|
||||
private:
|
||||
StateChanged onSeek(float t) override {
|
||||
const auto& lerp_info = this->getLERPInfo(t);
|
||||
|
||||
@ -90,13 +40,62 @@ private:
|
||||
using INHERITED = KeyframeAnimator;
|
||||
};
|
||||
|
||||
class TextAnimatorBuilder final : public AnimatorBuilder {
|
||||
public:
|
||||
explicit TextAnimatorBuilder(TextValue* target) : fTarget(target) {}
|
||||
|
||||
sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder& abuilder,
|
||||
const skjson::ArrayValue& jkfs) override {
|
||||
SkASSERT(jkfs.size() > 0);
|
||||
|
||||
fValues.reserve(jkfs.size());
|
||||
if (!this->parseKeyframes(abuilder, jkfs)) {
|
||||
return nullptr;
|
||||
}
|
||||
fValues.shrink_to_fit();
|
||||
|
||||
return sk_sp<TextKeyframeAnimator>(
|
||||
new TextKeyframeAnimator(std::move(fKFs),
|
||||
std::move(fCMs),
|
||||
std::move(fValues),
|
||||
fTarget));
|
||||
}
|
||||
|
||||
bool parseValue(const AnimationBuilder& abuilder, const skjson::Value& jv) const override {
|
||||
return Parse(jv, abuilder, fTarget);
|
||||
}
|
||||
|
||||
private:
|
||||
bool parseKFValue(const AnimationBuilder& abuilder,
|
||||
const skjson::ObjectValue&,
|
||||
const skjson::Value& jv,
|
||||
Keyframe::Value* v) override {
|
||||
TextValue val;
|
||||
if (!Parse(jv, abuilder, &val)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: full deduping?
|
||||
if (fValues.empty() || val != fValues.back()) {
|
||||
fValues.push_back(std::move(val));
|
||||
}
|
||||
|
||||
v->idx = SkToU32(fValues.size() - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<TextValue> fValues;
|
||||
TextValue* fTarget;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
bool AnimatablePropertyContainer::bind<TextValue>(const AnimationBuilder& abuilder,
|
||||
const skjson::ObjectValue* jprop,
|
||||
TextValue* v) {
|
||||
TextKeyframeAnimator::Builder builder(v);
|
||||
TextAnimatorBuilder builder(v);
|
||||
return this->bindImpl(abuilder, jprop, builder);
|
||||
}
|
||||
|
||||
|
@ -20,119 +20,12 @@ namespace {
|
||||
|
||||
// Spatial 2D specialization: stores SkV2s and optional contour interpolators externally.
|
||||
class Vec2KeyframeAnimator final : public KeyframeAnimator {
|
||||
public:
|
||||
struct SpatialValue {
|
||||
Vec2Value v2;
|
||||
sk_sp<SkContourMeasure> cmeasure;
|
||||
};
|
||||
|
||||
public:
|
||||
class Builder final : public KeyframeAnimatorBuilder {
|
||||
public:
|
||||
Builder(Vec2Value* vec_target, float* rot_target)
|
||||
: fVecTarget(vec_target)
|
||||
, fRotTarget(rot_target) {}
|
||||
|
||||
sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder,
|
||||
const skjson::ArrayValue& jkfs) override {
|
||||
SkASSERT(jkfs.size() > 0);
|
||||
|
||||
fValues.reserve(jkfs.size());
|
||||
if (!this->parseKeyframes(abuilder, jkfs)) {
|
||||
return nullptr;
|
||||
}
|
||||
fValues.shrink_to_fit();
|
||||
|
||||
return sk_sp<Vec2KeyframeAnimator>(
|
||||
new Vec2KeyframeAnimator(std::move(fKFs),
|
||||
std::move(fCMs),
|
||||
std::move(fValues),
|
||||
fVecTarget,
|
||||
fRotTarget));
|
||||
}
|
||||
|
||||
bool parseValue(const AnimationBuilder&, const skjson::Value& jv) const override {
|
||||
return Parse(jv, fVecTarget);
|
||||
}
|
||||
|
||||
private:
|
||||
void backfill_spatial(const SpatialValue& val) {
|
||||
SkASSERT(!fValues.empty());
|
||||
auto& prev_val = fValues.back();
|
||||
SkASSERT(!prev_val.cmeasure);
|
||||
|
||||
if (val.v2 == prev_val.v2) {
|
||||
// spatial interpolation only make sense for noncoincident values
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether v0 and v1 have the same direction AND ||v0||>=||v1||
|
||||
auto check_vecs = [](const SkV2& v0, const SkV2& v1) {
|
||||
const auto v0_len2 = v0.lengthSquared(),
|
||||
v1_len2 = v1.lengthSquared();
|
||||
|
||||
// check magnitude
|
||||
if (v0_len2 < v1_len2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// v0, v1 have the same direction iff dot(v0,v1) = ||v0||*||v1||
|
||||
// <=> dot(v0,v1)^2 = ||v0||^2 * ||v1||^2
|
||||
const auto dot = v0.dot(v1);
|
||||
return SkScalarNearlyEqual(dot * dot, v0_len2 * v1_len2);
|
||||
};
|
||||
|
||||
if (check_vecs(val.v2 - prev_val.v2, fTo) &&
|
||||
check_vecs(prev_val.v2 - val.v2, fTi)) {
|
||||
// Both control points lie on the [prev_val..val] segment
|
||||
// => we can power-reduce the Bezier "curve" to a straight line.
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, this looks like a legitimate spatial keyframe.
|
||||
SkPathBuilder p;
|
||||
p.moveTo (prev_val.v2.x , prev_val.v2.y);
|
||||
p.cubicTo(prev_val.v2.x + fTo.x, prev_val.v2.y + fTo.y,
|
||||
val.v2.x + fTi.x, val.v2.y + fTi.y,
|
||||
val.v2.x, val.v2.y);
|
||||
prev_val.cmeasure = SkContourMeasureIter(p.detach(), false).next();
|
||||
}
|
||||
|
||||
bool parseKFValue(const AnimationBuilder&,
|
||||
const skjson::ObjectValue& jkf,
|
||||
const skjson::Value& jv,
|
||||
Keyframe::Value* v) override {
|
||||
SpatialValue val;
|
||||
if (!Parse(jv, &val.v2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fPendingSpatial) {
|
||||
this->backfill_spatial(val);
|
||||
}
|
||||
|
||||
// Track the last keyframe spatial tangents (checked on next parseValue).
|
||||
fTi = ParseDefault<SkV2>(jkf["ti"], {0,0});
|
||||
fTo = ParseDefault<SkV2>(jkf["to"], {0,0});
|
||||
fPendingSpatial = fTi != SkV2{0,0} || fTo != SkV2{0,0};
|
||||
|
||||
if (fValues.empty() || val.v2 != fValues.back().v2 || fPendingSpatial) {
|
||||
fValues.push_back(std::move(val));
|
||||
}
|
||||
|
||||
v->idx = SkToU32(fValues.size() - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<SpatialValue> fValues;
|
||||
Vec2Value* fVecTarget; // required
|
||||
float* fRotTarget; // optional
|
||||
SkV2 fTi{0,0},
|
||||
fTo{0,0};
|
||||
bool fPendingSpatial = false;
|
||||
};
|
||||
|
||||
private:
|
||||
Vec2KeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms,
|
||||
std::vector<SpatialValue> vs, Vec2Value* vec_target, float* rot_target)
|
||||
: INHERITED(std::move(kfs), std::move(cms))
|
||||
@ -140,6 +33,7 @@ private:
|
||||
, fVecTarget(vec_target)
|
||||
, fRotTarget(rot_target) {}
|
||||
|
||||
private:
|
||||
StateChanged update(const Vec2Value& new_vec_value, const Vec2Value& new_tan_value) {
|
||||
auto changed = (new_vec_value != *fVecTarget);
|
||||
*fVecTarget = new_vec_value;
|
||||
@ -200,13 +94,119 @@ private:
|
||||
return this->update(Lerp(v0.v2, v1.v2, lerp_info.weight), tan);
|
||||
}
|
||||
|
||||
const std::vector<SpatialValue> fValues;
|
||||
const std::vector<Vec2KeyframeAnimator::SpatialValue> fValues;
|
||||
Vec2Value* fVecTarget;
|
||||
float* fRotTarget;
|
||||
|
||||
using INHERITED = KeyframeAnimator;
|
||||
};
|
||||
|
||||
class Vec2AnimatorBuilder final : public AnimatorBuilder {
|
||||
public:
|
||||
Vec2AnimatorBuilder(Vec2Value* vec_target, float* rot_target)
|
||||
: fVecTarget(vec_target)
|
||||
, fRotTarget(rot_target) {}
|
||||
|
||||
sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder& abuilder,
|
||||
const skjson::ArrayValue& jkfs) override {
|
||||
SkASSERT(jkfs.size() > 0);
|
||||
|
||||
fValues.reserve(jkfs.size());
|
||||
if (!this->parseKeyframes(abuilder, jkfs)) {
|
||||
return nullptr;
|
||||
}
|
||||
fValues.shrink_to_fit();
|
||||
|
||||
return sk_sp<Vec2KeyframeAnimator>(
|
||||
new Vec2KeyframeAnimator(std::move(fKFs),
|
||||
std::move(fCMs),
|
||||
std::move(fValues),
|
||||
fVecTarget,
|
||||
fRotTarget));
|
||||
}
|
||||
|
||||
bool parseValue(const AnimationBuilder&, const skjson::Value& jv) const override {
|
||||
return Parse(jv, fVecTarget);
|
||||
}
|
||||
|
||||
private:
|
||||
void backfill_spatial(const Vec2KeyframeAnimator::SpatialValue& val) {
|
||||
SkASSERT(!fValues.empty());
|
||||
auto& prev_val = fValues.back();
|
||||
SkASSERT(!prev_val.cmeasure);
|
||||
|
||||
if (val.v2 == prev_val.v2) {
|
||||
// spatial interpolation only make sense for noncoincident values
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether v0 and v1 have the same direction AND ||v0||>=||v1||
|
||||
auto check_vecs = [](const SkV2& v0, const SkV2& v1) {
|
||||
const auto v0_len2 = v0.lengthSquared(),
|
||||
v1_len2 = v1.lengthSquared();
|
||||
|
||||
// check magnitude
|
||||
if (v0_len2 < v1_len2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// v0, v1 have the same direction iff dot(v0,v1) = ||v0||*||v1||
|
||||
// <=> dot(v0,v1)^2 = ||v0||^2 * ||v1||^2
|
||||
const auto dot = v0.dot(v1);
|
||||
return SkScalarNearlyEqual(dot * dot, v0_len2 * v1_len2);
|
||||
};
|
||||
|
||||
if (check_vecs(val.v2 - prev_val.v2, fTo) &&
|
||||
check_vecs(prev_val.v2 - val.v2, fTi)) {
|
||||
// Both control points lie on the [prev_val..val] segment
|
||||
// => we can power-reduce the Bezier "curve" to a straight line.
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, this looks like a legitimate spatial keyframe.
|
||||
SkPathBuilder p;
|
||||
p.moveTo (prev_val.v2.x , prev_val.v2.y);
|
||||
p.cubicTo(prev_val.v2.x + fTo.x, prev_val.v2.y + fTo.y,
|
||||
val.v2.x + fTi.x, val.v2.y + fTi.y,
|
||||
val.v2.x, val.v2.y);
|
||||
prev_val.cmeasure = SkContourMeasureIter(p.detach(), false).next();
|
||||
}
|
||||
|
||||
bool parseKFValue(const AnimationBuilder&,
|
||||
const skjson::ObjectValue& jkf,
|
||||
const skjson::Value& jv,
|
||||
Keyframe::Value* v) override {
|
||||
Vec2KeyframeAnimator::SpatialValue val;
|
||||
if (!Parse(jv, &val.v2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fPendingSpatial) {
|
||||
this->backfill_spatial(val);
|
||||
}
|
||||
|
||||
// Track the last keyframe spatial tangents (checked on next parseValue).
|
||||
fTi = ParseDefault<SkV2>(jkf["ti"], {0,0});
|
||||
fTo = ParseDefault<SkV2>(jkf["to"], {0,0});
|
||||
fPendingSpatial = fTi != SkV2{0,0} || fTo != SkV2{0,0};
|
||||
|
||||
if (fValues.empty() || val.v2 != fValues.back().v2 || fPendingSpatial) {
|
||||
fValues.push_back(std::move(val));
|
||||
}
|
||||
|
||||
v->idx = SkToU32(fValues.size() - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Vec2KeyframeAnimator::SpatialValue> fValues;
|
||||
Vec2Value* fVecTarget; // required
|
||||
float* fRotTarget; // optional
|
||||
SkV2 fTi{0,0},
|
||||
fTo{0,0};
|
||||
bool fPendingSpatial = false;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool AnimatablePropertyContainer::bindAutoOrientable(const AnimationBuilder& abuilder,
|
||||
@ -218,7 +218,7 @@ bool AnimatablePropertyContainer::bindAutoOrientable(const AnimationBuilder& abu
|
||||
|
||||
if (!ParseDefault<bool>((*jprop)["s"], false)) {
|
||||
// Regular (static or keyframed) 2D value.
|
||||
Vec2KeyframeAnimator::Builder builder(v, orientation);
|
||||
Vec2AnimatorBuilder builder(v, orientation);
|
||||
return this->bindImpl(abuilder, jprop, builder);
|
||||
}
|
||||
|
||||
|
@ -142,14 +142,14 @@ private:
|
||||
|
||||
} // namespace
|
||||
|
||||
VectorKeyframeAnimatorBuilder::VectorKeyframeAnimatorBuilder(std::vector<float>* target,
|
||||
VectorAnimatorBuilder::VectorAnimatorBuilder(std::vector<float>* target,
|
||||
VectorLenParser parse_len,
|
||||
VectorDataParser parse_data)
|
||||
: fParseLen(parse_len)
|
||||
, fParseData(parse_data)
|
||||
, fTarget(target) {}
|
||||
|
||||
sk_sp<KeyframeAnimator> VectorKeyframeAnimatorBuilder::make(const AnimationBuilder& abuilder,
|
||||
sk_sp<KeyframeAnimator> VectorAnimatorBuilder::makeFromKeyframes(const AnimationBuilder& abuilder,
|
||||
const skjson::ArrayValue& jkfs) {
|
||||
SkASSERT(jkfs.size() > 0);
|
||||
|
||||
@ -186,7 +186,7 @@ sk_sp<KeyframeAnimator> VectorKeyframeAnimatorBuilder::make(const AnimationBuild
|
||||
fTarget));
|
||||
}
|
||||
|
||||
bool VectorKeyframeAnimatorBuilder::parseValue(const AnimationBuilder&,
|
||||
bool VectorAnimatorBuilder::parseValue(const AnimationBuilder&,
|
||||
const skjson::Value& jv) const {
|
||||
size_t vec_len;
|
||||
if (!this->fParseLen(jv, &vec_len)) {
|
||||
@ -197,7 +197,7 @@ bool VectorKeyframeAnimatorBuilder::parseValue(const AnimationBuilder&,
|
||||
return fParseData(jv, vec_len, fTarget->data());
|
||||
}
|
||||
|
||||
bool VectorKeyframeAnimatorBuilder::parseKFValue(const AnimationBuilder&,
|
||||
bool VectorAnimatorBuilder::parseKFValue(const AnimationBuilder&,
|
||||
const skjson::ObjectValue&,
|
||||
const skjson::Value& jv,
|
||||
Keyframe::Value* kfv) {
|
||||
@ -236,7 +236,7 @@ bool AnimatablePropertyContainer::bind<VectorValue>(const AnimationBuilder& abui
|
||||
|
||||
if (!ParseDefault<bool>((*jprop)["s"], false)) {
|
||||
// Regular (static or keyframed) vector value.
|
||||
VectorKeyframeAnimatorBuilder builder(
|
||||
VectorAnimatorBuilder builder(
|
||||
v,
|
||||
// Len parser.
|
||||
[](const skjson::Value& jv, size_t* len) -> bool {
|
||||
|
@ -14,14 +14,14 @@
|
||||
|
||||
namespace skottie::internal {
|
||||
|
||||
class VectorKeyframeAnimatorBuilder final : public KeyframeAnimatorBuilder {
|
||||
class VectorAnimatorBuilder final : public AnimatorBuilder {
|
||||
public:
|
||||
using VectorLenParser = bool(*)(const skjson::Value&, size_t*);
|
||||
using VectorDataParser = bool(*)(const skjson::Value&, size_t, float*);
|
||||
|
||||
VectorKeyframeAnimatorBuilder(std::vector<float>*, VectorLenParser, VectorDataParser);
|
||||
VectorAnimatorBuilder(std::vector<float>*, VectorLenParser, VectorDataParser);
|
||||
|
||||
sk_sp<KeyframeAnimator> make(const AnimationBuilder&, const skjson::ArrayValue&) override;
|
||||
sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder&, const skjson::ArrayValue&) override;
|
||||
|
||||
private:
|
||||
bool parseValue(const AnimationBuilder&, const skjson::Value&) const override;
|
||||
|
Loading…
Reference in New Issue
Block a user