1/* 2 * Copyright 2020 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "modules/skottie/src/SkottieJson.h" 9#include "modules/skottie/src/SkottieValue.h" 10#include "modules/skottie/src/animator/Animator.h" 11#include "modules/skottie/src/animator/KeyframeAnimator.h" 12 13namespace skottie::internal { 14 15namespace { 16 17 // Scalar specialization: stores scalar values (floats) inline in keyframes. 18class ScalarKeyframeAnimator final : public KeyframeAnimator { 19public: 20 ScalarKeyframeAnimator(std::vector<Keyframe> kfs, 21 std::vector<SkCubicMap> cms, 22 ScalarValue* target_value) 23 : INHERITED(std::move(kfs), std::move(cms)) 24 , fTarget(target_value) {} 25 26private: 27 28 StateChanged onSeek(float t) override { 29 const auto& lerp_info = this->getLERPInfo(t); 30 const auto old_value = *fTarget; 31 32 *fTarget = Lerp(lerp_info.vrec0.flt, lerp_info.vrec1.flt, lerp_info.weight); 33 34 return *fTarget != old_value; 35 } 36 37 ScalarValue* fTarget; 38 39 using INHERITED = KeyframeAnimator; 40}; 41 42 // Scalar specialization: stores scalar values (floats). 43class ScalarExpressionAnimator final : public Animator { 44public: 45 ScalarExpressionAnimator(sk_sp<ExpressionEvaluator<ScalarValue>> expression_evaluator, 46 ScalarValue* target_value) 47 : fExpressionEvaluator(std::move(expression_evaluator)) 48 , fTarget(target_value) {} 49 50private: 51 52 StateChanged onSeek(float t) override { 53 auto old_value = *fTarget; 54 55 *fTarget = fExpressionEvaluator->evaluate(t); 56 57 return *fTarget != old_value; 58 } 59 60 sk_sp<ExpressionEvaluator<ScalarValue>> fExpressionEvaluator; 61 ScalarValue* fTarget; 62}; 63 64class ScalarAnimatorBuilder final : public AnimatorBuilder { 65 public: 66 explicit ScalarAnimatorBuilder(ScalarValue* target) 67 : INHERITED(Keyframe::Value::Type::kScalar) 68 , fTarget(target) {} 69 70 sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder& abuilder, 71 const skjson::ArrayValue& jkfs) override { 72 SkASSERT(jkfs.size() > 0); 73 if (!this->parseKeyframes(abuilder, jkfs)) { 74 return nullptr; 75 } 76 77 return sk_sp<ScalarKeyframeAnimator>( 78 new ScalarKeyframeAnimator(std::move(fKFs), std::move(fCMs), fTarget)); 79 } 80 81 sk_sp<Animator> makeFromExpression(ExpressionManager& em, const char* expr) override { 82 sk_sp<ExpressionEvaluator<ScalarValue>> expression_evaluator = 83 em.createNumberExpressionEvaluator(expr); 84 return sk_make_sp<ScalarExpressionAnimator>(expression_evaluator, fTarget); 85 } 86 87 88 bool parseValue(const AnimationBuilder&, const skjson::Value& jv) const override { 89 return Parse(jv, fTarget); 90 } 91 92 private: 93 bool parseKFValue(const AnimationBuilder&, 94 const skjson::ObjectValue&, 95 const skjson::Value& jv, 96 Keyframe::Value* v) override { 97 return Parse(jv, &v->flt); 98 } 99 100 ScalarValue* fTarget; 101 102 using INHERITED = AnimatorBuilder; 103 }; 104 105} // namespace 106 107template <> 108bool AnimatablePropertyContainer::bind<ScalarValue>(const AnimationBuilder& abuilder, 109 const skjson::ObjectValue* jprop, 110 ScalarValue* v) { 111 ScalarAnimatorBuilder builder(v); 112 113 return this->bindImpl(abuilder, jprop, builder); 114} 115 116} // namespace skottie::internal 117