blob: 22668252fddce9be51e7656ebb6ba0208a4cb373 [file] [log] [blame]
Florin Malita1b1dead2018-08-21 14:34:02 -04001/*
2 * Copyright 2018 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 "SkottiePriv.h"
9
10#include "SkJSON.h"
11#include "SkottieAnimator.h"
12#include "SkottieJson.h"
13#include "SkottieValue.h"
14#include "SkMakeUnique.h"
15#include "SkSGRenderNode.h"
16#include "SkSGScene.h"
17#include "SkTLazy.h"
18
19namespace skottie {
20namespace internal {
21
22sk_sp<sksg::RenderNode> AnimationBuilder::attachPrecompLayer(const skjson::ObjectValue& jlayer,
23 AnimatorScope* ascope) {
24 const skjson::ObjectValue* time_remap = jlayer["tm"];
25 const auto start_time = ParseDefault<float>(jlayer["st"], 0.0f),
26 stretch_time = ParseDefault<float>(jlayer["sr"], 1.0f);
27 const auto requires_time_mapping = !SkScalarNearlyEqual(start_time , 0) ||
28 !SkScalarNearlyEqual(stretch_time, 1) ||
29 time_remap;
30
31 AnimatorScope local_animators;
32 auto precomp_layer = this->attachAssetRef(jlayer,
33 requires_time_mapping ? &local_animators : ascope,
34 &AnimationBuilder::attachComposition);
35
36 // Applies a bias/scale/remap t-adjustment to child animators.
37 class CompTimeMapper final : public sksg::GroupAnimator {
38 public:
39 CompTimeMapper(sksg::AnimatorList&& layer_animators, float time_bias, float time_scale)
40 : INHERITED(std::move(layer_animators))
41 , fTimeBias(time_bias)
42 , fTimeScale(time_scale) {}
43
44 void onTick(float t) override {
45 // When time remapping is active, |t| is driven externally.
46 if (fRemappedTime.isValid()) {
47 t = *fRemappedTime.get();
48 }
49
50 this->INHERITED::onTick((t + fTimeBias) * fTimeScale);
51 }
52
53 void remapTime(float t) { fRemappedTime.set(t); }
54
55 private:
56 const float fTimeBias,
57 fTimeScale;
58 SkTLazy<float> fRemappedTime;
59
60 using INHERITED = sksg::GroupAnimator;
61 };
62
63 if (requires_time_mapping) {
64 const auto t_bias = -start_time,
65 t_scale = sk_ieee_float_divide(1, stretch_time);
66 auto time_mapper = skstd::make_unique<CompTimeMapper>(std::move(local_animators),
67 t_bias, t_scale);
68 if (time_remap) {
69 // The lambda below captures a raw pointer to the mapper object. That should be safe,
70 // because both the lambda and the mapper are scoped/owned by ctx->fAnimators.
71 auto* raw_mapper = time_mapper.get();
72 auto frame_rate = fFrameRate;
73 BindProperty<ScalarValue>(*time_remap, ascope,
74 [raw_mapper, frame_rate](const ScalarValue& t) {
75 raw_mapper->remapTime(t * frame_rate);
76 });
77 }
78 ascope->push_back(std::move(time_mapper));
79 }
80
81 return precomp_layer;
82}
83
84} // namespace internal
85} // namespace skottie