1 | /* |
2 | * Copyright 2019 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/effects/Effects.h" |
9 | |
10 | #include "modules/skottie/src/SkottieJson.h" |
11 | #include "modules/skottie/src/Transform.h" |
12 | #include "modules/sksg/include/SkSGOpacityEffect.h" |
13 | #include "modules/sksg/include/SkSGTransform.h" |
14 | |
15 | namespace skottie { |
16 | namespace internal { |
17 | |
18 | namespace { |
19 | |
20 | class TransformEffectAdapter final : public DiscardableAdapterBase<TransformEffectAdapter, |
21 | sksg::OpacityEffect> { |
22 | public: |
23 | TransformEffectAdapter(const AnimationBuilder& abuilder, |
24 | const skjson::ObjectValue* jopacity, |
25 | const skjson::ObjectValue* jscale_uniform, |
26 | const skjson::ObjectValue* jscale_width, |
27 | const skjson::ObjectValue* jscale_height, |
28 | sk_sp<TransformAdapter2D> tadapter, |
29 | sk_sp<sksg::RenderNode> child) |
30 | : INHERITED(sksg::OpacityEffect::Make(std::move(child))) |
31 | , fTransformAdapter(std::move(tadapter)) { |
32 | this->bind(abuilder, jopacity , fOpacity ); |
33 | this->bind(abuilder, jscale_uniform, fUniformScale); |
34 | this->bind(abuilder, jscale_width , fScaleWidth ); |
35 | this->bind(abuilder, jscale_height , fScaleHeight ); |
36 | |
37 | this->attachDiscardableAdapter(fTransformAdapter); |
38 | } |
39 | |
40 | private: |
41 | void onSync() override { |
42 | this->node()->setOpacity(fOpacity * 0.01f); |
43 | |
44 | // In uniform mode, the scale is based solely in ScaleHeight. |
45 | const auto scale = SkVector::Make(SkScalarRoundToInt(fUniformScale) ? fScaleHeight |
46 | : fScaleWidth, |
47 | fScaleHeight); |
48 | |
49 | // NB: this triggers an transform adapter -> SG sync. |
50 | fTransformAdapter->setScale(scale); |
51 | } |
52 | |
53 | const sk_sp<TransformAdapter2D> fTransformAdapter; |
54 | |
55 | ScalarValue fOpacity = 100, |
56 | fUniformScale = 0, // bool |
57 | fScaleWidth = 100, |
58 | fScaleHeight = 100; |
59 | |
60 | using INHERITED = DiscardableAdapterBase<TransformEffectAdapter, sksg::OpacityEffect>; |
61 | }; |
62 | |
63 | } // anonymous ns |
64 | |
65 | sk_sp<sksg::RenderNode> EffectBuilder::attachTransformEffect(const skjson::ArrayValue& jprops, |
66 | sk_sp<sksg::RenderNode> layer) const { |
67 | enum : size_t { |
68 | kAnchorPoint_Index = 0, |
69 | kPosition_Index = 1, |
70 | kUniformScale_Index = 2, |
71 | kScaleHeight_Index = 3, |
72 | kScaleWidth_Index = 4, |
73 | kSkew_Index = 5, |
74 | kSkewAxis_Index = 6, |
75 | kRotation_Index = 7, |
76 | kOpacity_Index = 8, |
77 | // kUseCompShutterAngle_Index = 9, |
78 | // kShutterAngle_Index = 10, |
79 | // kSampling_Index = 11, |
80 | }; |
81 | |
82 | auto transform_adapter = TransformAdapter2D::Make(*fBuilder, |
83 | GetPropValue(jprops, kAnchorPoint_Index), |
84 | GetPropValue(jprops, kPosition_Index), |
85 | nullptr, // scale is handled externally |
86 | GetPropValue(jprops, kRotation_Index), |
87 | GetPropValue(jprops, kSkew_Index), |
88 | GetPropValue(jprops, kSkewAxis_Index)); |
89 | if (!transform_adapter) { |
90 | return nullptr; |
91 | } |
92 | |
93 | auto transform_effect_node = sksg::TransformEffect::Make(std::move(layer), |
94 | transform_adapter->node()); |
95 | return fBuilder->attachDiscardableAdapter<TransformEffectAdapter> |
96 | (*fBuilder, |
97 | GetPropValue(jprops, kOpacity_Index), |
98 | GetPropValue(jprops, kUniformScale_Index), |
99 | GetPropValue(jprops, kScaleWidth_Index), |
100 | GetPropValue(jprops, kScaleHeight_Index), |
101 | std::move(transform_adapter), |
102 | std::move(transform_effect_node) |
103 | ); |
104 | } |
105 | |
106 | } // namespace internal |
107 | } // namespace skottie |
108 | |