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 | void* target_value) { |
54 | if (!jprop) { |
55 | return false; |
56 | } |
57 | |
58 | const auto& jpropA = (*jprop)["a" ]; |
59 | const auto& jpropK = (*jprop)["k" ]; |
60 | |
61 | if (!(*jprop)["x" ].is<skjson::NullValue>()) { |
62 | abuilder.log(Logger::Level::kWarning, nullptr, "Unsupported expression." ); |
63 | } |
64 | |
65 | // Older Json versions don't have an "a" animation marker. |
66 | // For those, we attempt to parse both ways. |
67 | if (!ParseDefault<bool>(jpropA, false)) { |
68 | if (builder.parseValue(abuilder, jpropK, target_value)) { |
69 | // Static property. |
70 | return true; |
71 | } |
72 | |
73 | if (!jpropA.is<skjson::NullValue>()) { |
74 | abuilder.log(Logger::Level::kError, jprop, |
75 | "Could not parse (explicit) static property." ); |
76 | return false; |
77 | } |
78 | } |
79 | |
80 | // Keyframed property. |
81 | sk_sp<KeyframeAnimator> animator; |
82 | const skjson::ArrayValue* jkfs = jpropK; |
83 | if (jkfs && jkfs->size() > 0) { |
84 | animator = builder.make(abuilder, *jkfs, target_value); |
85 | } |
86 | |
87 | if (!animator) { |
88 | abuilder.log(Logger::Level::kError, jprop, "Could not parse keyframed property." ); |
89 | return false; |
90 | } |
91 | |
92 | if (animator->isConstant()) { |
93 | // If all keyframes are constant, there is no reason to treat this |
94 | // as an animated property - apply immediately and discard the animator. |
95 | animator->seek(0); |
96 | } else { |
97 | fAnimators.push_back(std::move(animator)); |
98 | } |
99 | |
100 | return true; |
101 | } |
102 | |
103 | } // namespace skottie::internal |
104 | |