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/animator/Animator.h" |
9 | |
10 | #include "modules/skottie/src/SkottieJson.h" |
11 | #include "modules/skottie/src/SkottiePriv.h" |
12 | #include "modules/skottie/src/animator/KeyframeAnimator.h" |
13 | |
14 | namespace skottie::internal { |
15 | |
16 | Animator::StateChanged AnimatablePropertyContainer::onSeek(float t) { |
17 | // The very first seek must trigger a sync, to ensure proper SG setup. |
18 | bool changed = !fHasSynced; |
19 | |
20 | for (const auto& animator : fAnimators) { |
21 | changed |= animator->seek(t); |
22 | } |
23 | |
24 | if (changed) { |
25 | this->onSync(); |
26 | fHasSynced = true; |
27 | } |
28 | |
29 | return changed; |
30 | } |
31 | |
32 | void AnimatablePropertyContainer::attachDiscardableAdapter( |
33 | sk_sp<AnimatablePropertyContainer> child) { |
34 | if (!child) { |
35 | return; |
36 | } |
37 | |
38 | if (child->isStatic()) { |
39 | child->seek(0); |
40 | return; |
41 | } |
42 | |
43 | fAnimators.push_back(child); |
44 | } |
45 | |
46 | void AnimatablePropertyContainer::shrink_to_fit() { |
47 | fAnimators.shrink_to_fit(); |
48 | } |
49 | |
50 | bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder, |
51 | const skjson::ObjectValue* jprop, |
52 | KeyframeAnimatorBuilder& builder) { |
53 | if (!jprop) { |
54 | return false; |
55 | } |
56 | |
57 | const auto& jpropA = (*jprop)["a" ]; |
58 | const auto& jpropK = (*jprop)["k" ]; |
59 | |
60 | if (!(*jprop)["x" ].is<skjson::NullValue>()) { |
61 | abuilder.log(Logger::Level::kWarning, nullptr, "Unsupported expression." ); |
62 | } |
63 | |
64 | // Older Json versions don't have an "a" animation marker. |
65 | // For those, we attempt to parse both ways. |
66 | if (!ParseDefault<bool>(jpropA, false)) { |
67 | if (builder.parseValue(abuilder, jpropK)) { |
68 | // Static property. |
69 | return true; |
70 | } |
71 | |
72 | if (!jpropA.is<skjson::NullValue>()) { |
73 | abuilder.log(Logger::Level::kError, jprop, |
74 | "Could not parse (explicit) static property." ); |
75 | return false; |
76 | } |
77 | } |
78 | |
79 | // Keyframed property. |
80 | sk_sp<KeyframeAnimator> animator; |
81 | const skjson::ArrayValue* jkfs = jpropK; |
82 | if (jkfs && jkfs->size() > 0) { |
83 | animator = builder.make(abuilder, *jkfs); |
84 | } |
85 | |
86 | if (!animator) { |
87 | abuilder.log(Logger::Level::kError, jprop, "Could not parse keyframed property." ); |
88 | return false; |
89 | } |
90 | |
91 | if (animator->isConstant()) { |
92 | // If all keyframes are constant, there is no reason to treat this |
93 | // as an animated property - apply immediately and discard the animator. |
94 | animator->seek(0); |
95 | } else { |
96 | fAnimators.push_back(std::move(animator)); |
97 | } |
98 | |
99 | return true; |
100 | } |
101 | |
102 | } // namespace skottie::internal |
103 | |