1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_ADAPTER_ROSEN_TRANSITION_EFFECT_IMPL_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_ADAPTER_ROSEN_TRANSITION_EFFECT_IMPL_H
18 
19 #include "modifier/rs_property.h"
20 #include "modifier/rs_property_modifier.h"
21 
22 #include "core/components_ng/render/adapter/rosen_transition_effect.h"
23 #include "core/components_ng/render/animation_utils.h"
24 
25 namespace OHOS::Ace::NG {
26 // Identity transition effect, do nothing and execute immediately.
27 class RosenIdentityTransitionEffect final : public RosenTransitionEffect {
28 public:
29     RosenIdentityTransitionEffect();
30     ~RosenIdentityTransitionEffect() override = default;
31 
32     // Identity transition effect ignores external animation option.
SetAnimationOption(const std::shared_ptr<AnimationOption> & option)33     void SetAnimationOption(const std::shared_ptr<AnimationOption>& option) override {}
HasDisappearTransition()34     bool HasDisappearTransition() const override
35     {
36         return false;
37     }
38 
39 private:
40     DECLARE_ACE_TYPE(RosenIdentityTransitionEffect, RosenTransitionEffect);
41     ACE_DISALLOW_COPY_AND_MOVE(RosenIdentityTransitionEffect);
42 };
43 
44 // Template class for single property transition effect, applying identity and active value to target property/modifier.
45 template<typename Modifier, typename PropertyType>
46 class PropertyTransitionEffectTemplate : public RosenTransitionEffect {
47 public:
PropertyTransitionEffectTemplate()48     PropertyTransitionEffectTemplate() : RosenTransitionEffect() {}
PropertyTransitionEffectTemplate(PropertyType identityProperty,PropertyType activeValue)49     PropertyTransitionEffectTemplate(PropertyType identityProperty, PropertyType activeValue)
50         : RosenTransitionEffect(), identityValue_(identityProperty), activeValue_(activeValue)
51     {}
52     ~PropertyTransitionEffectTemplate() override = default;
53 
54     void SetIdentityValue(PropertyType identityValue);
55     void SetActiveValue(PropertyType activeValue);
56 
SetKeyframes(const std::vector<std::pair<float,PropertyType>> & keyframes)57     void SetKeyframes(const std::vector<std::pair<float, PropertyType>>& keyframes)
58     {
59         keyframes_ = keyframes;
60     }
61 
62 protected:
63     void OnAttach(const RefPtr<RosenRenderContext>& context, bool activeTransition) override;
64     void OnDetach(RosenRenderContext* context) override;
OnAppear()65     void OnAppear() override
66     {
67         isActive_ = false;
68         if (keyframes_.empty()) {
69             property_->Set(identityValue_);
70             return;
71         }
72         for (auto it = keyframes_.begin(); it != keyframes_.end(); ++it) {
73             AnimationUtils::AddKeyFrame(it->first, [this, &it]() { property_->Set(it->second); });
74         }
75         AnimationUtils::AddKeyFrame(1.0f, [this]() { property_->Set(identityValue_); });
76     }
OnDisappear(bool activeTransition)77     void OnDisappear(bool activeTransition) override
78     {
79         if (!activeTransition) {
80             return;
81         }
82         isActive_ = true;
83         if (keyframes_.empty()) {
84             property_->Set(activeValue_);
85             return;
86         }
87         // PLANNING: maybe we need to reverse the keyframes in disappearing animation.
88         for (auto it = keyframes_.begin(); it != keyframes_.end(); ++it) {
89             AnimationUtils::AddKeyFrame(it->first, [this, &it]() { property_->Set(it->second); });
90         }
91         AnimationUtils::AddKeyFrame(1.0f, [this]() { property_->Set(activeValue_); });
92     }
93 
94 private:
95     std::shared_ptr<Modifier> modifier_;
96     std::shared_ptr<Rosen::RSAnimatableProperty<PropertyType>> property_;
97     PropertyType identityValue_ {};
98     PropertyType activeValue_ {};
99     std::vector<std::pair<float, PropertyType>> keyframes_;
100     bool isActive_ = false;
101 
102     DECLARE_ACE_TYPE(PropertyTransitionEffectTemplate, RosenTransitionEffect);
103     ACE_DISALLOW_COPY_AND_MOVE(PropertyTransitionEffectTemplate);
104 };
105 
106 using RosenOpacityTransitionEffect = PropertyTransitionEffectTemplate<Rosen::RSAlphaModifier, float>;
107 template<>
108 RosenOpacityTransitionEffect::PropertyTransitionEffectTemplate();
109 
110 // Set pivot during transition effect.
111 class RosenPivotTransitionEffect final : public RosenTransitionEffect {
112 public:
113     RosenPivotTransitionEffect() = default;
114     RosenPivotTransitionEffect(const Dimension& centerX, const Dimension& centerY,
115         const Dimension& centerZ = Dimension(0.0));
116     ~RosenPivotTransitionEffect() override = default;
117 
118     void SetPivot(const Dimension& centerX, const Dimension& centerY, const Dimension& centerZ = Dimension(0.0,
119         DimensionUnit::VP));
120 
121 private:
122     void OnUpdateTransitionContext(
123         const RefPtr<RosenRenderContext>& context, const RectF& selfRect, const SizeF& viewSize) override;
124 
125     Dimension centerX_ { 0.5_pct };
126     Dimension centerY_ { 0.5_pct };
127     Dimension centerZ_ { 0.0_vp };
128     DECLARE_ACE_TYPE(RosenPivotTransitionEffect, RosenTransitionEffect);
129     ACE_DISALLOW_COPY_AND_MOVE(RosenPivotTransitionEffect);
130 };
131 
132 // Asymmetric transition effect, support in and out chaining with different transition effects.
133 class RosenAsymmetricTransitionEffect : public RosenTransitionEffect {
134 public:
RosenAsymmetricTransitionEffect()135     RosenAsymmetricTransitionEffect() : RosenTransitionEffect() {}
136     RosenAsymmetricTransitionEffect(
137         const RefPtr<RosenTransitionEffect>& transitionIn, const RefPtr<RosenTransitionEffect>& transitionOut);
138     ~RosenAsymmetricTransitionEffect() override = default;
139 
140     void SetTransitionInEffect(const RefPtr<RosenTransitionEffect>& transitionIn);
141     void SetTransitionOutEffect(const RefPtr<RosenTransitionEffect>& transitionOut);
GetTransitionInEffect()142     RefPtr<RosenTransitionEffect> GetTransitionInEffect()
143     {
144         return transitionIn_;
145     }
GetTransitionOutEffect()146     RefPtr<RosenTransitionEffect> GetTransitionOutEffect()
147     {
148         return transitionOut_;
149     }
150     bool HasDisappearTransition() const override;
151 
152 protected:
153     void OnAttach(const RefPtr<RosenRenderContext>& context, bool activeTransition) override;
154     void OnDetach(RosenRenderContext* context) override;
155     void OnAppear() override;
156     void OnDisappear(bool activeTransition) override;
157     void OnUpdateTransitionContext(
158         const RefPtr<RosenRenderContext>& context, const RectF& selfRect, const SizeF& viewSize) override;
159 
160     RefPtr<RosenTransitionEffect> transitionIn_;
161     RefPtr<RosenTransitionEffect> transitionOut_;
162 
163 private:
164     DECLARE_ACE_TYPE(RosenAsymmetricTransitionEffect, RosenTransitionEffect);
165     ACE_DISALLOW_COPY_AND_MOVE(RosenAsymmetricTransitionEffect);
166 };
167 
168 using InternalTranslateEffect = PropertyTransitionEffectTemplate<Rosen::RSTranslateModifier, Rosen::Vector2f>;
169 template<>
170 InternalTranslateEffect::PropertyTransitionEffectTemplate();
171 
172 // Move in and out to (same) screen edge.
173 class RosenMoveTransitionEffect final : public InternalTranslateEffect {
174 public:
RosenMoveTransitionEffect(TransitionEdge transitionEdge)175     explicit RosenMoveTransitionEffect(TransitionEdge transitionEdge) : edge_(transitionEdge) {}
176     ~RosenMoveTransitionEffect() override = default;
177 
178     void SetMoveEffect(TransitionEdge edge);
179 
180 private:
181     void OnUpdateTransitionContext(
182         const RefPtr<RosenRenderContext>& context, const RectF& selfRect, const SizeF& viewSize) override;
183     TransitionEdge edge_;
184     DECLARE_ACE_TYPE(RosenMoveTransitionEffect, InternalTranslateEffect);
185     ACE_DISALLOW_COPY_AND_MOVE(RosenMoveTransitionEffect);
186 };
187 
188 // Move in and out to different screen edge.
189 class RosenAsyncMoveTransitionEffect final : public RosenAsymmetricTransitionEffect {
190 public:
191     RosenAsyncMoveTransitionEffect(TransitionEdge inEdge, TransitionEdge outEdge);
192     ~RosenAsyncMoveTransitionEffect() override = default;
193 
194 private:
195     DECLARE_ACE_TYPE(RosenAsyncMoveTransitionEffect, RosenAsymmetricTransitionEffect);
196     ACE_DISALLOW_COPY_AND_MOVE(RosenAsyncMoveTransitionEffect);
197 };
198 
199 // Move in and out to different direction, by node size.
200 class RosenSlideTransitionEffect final : public RosenAsymmetricTransitionEffect {
201 public:
202     RosenSlideTransitionEffect();
203     RosenSlideTransitionEffect(TransitionEdge inEdge, TransitionEdge outEdge);
204     ~RosenSlideTransitionEffect() override = default;
205 
206 private:
207     void OnUpdateTransitionContext(
208         const RefPtr<RosenRenderContext>& context, const RectF& selfRect, const SizeF& viewSize) override;
209     static Rosen::Vector2f GetTranslateValue(TransitionEdge edge, const RectF& rect);
210     TransitionEdge inEdge_;
211     TransitionEdge outEdge_;
212     DECLARE_ACE_TYPE(RosenSlideTransitionEffect, RosenAsymmetricTransitionEffect);
213     ACE_DISALLOW_COPY_AND_MOVE(RosenSlideTransitionEffect);
214 };
215 
216 // Helper class for compositing transition effects.
217 template<typename... effects>
218 class RosenCompositeTransitionEffect : public RosenTransitionEffect {
219 public:
220     RosenCompositeTransitionEffect() = default;
221     ~RosenCompositeTransitionEffect() override = default;
222 
223 protected:
224     std::tuple<effects...> effects_;
225 
OnAttach(const RefPtr<RosenRenderContext> & context,bool activeTransition)226     void OnAttach(const RefPtr<RosenRenderContext>& context, bool activeTransition) override
227     {
228         std::apply([&](auto&&... effect) { (effect.Attach(context, activeTransition), ...); }, effects_);
229     }
OnDetach(RosenRenderContext * context)230     void OnDetach(RosenRenderContext* context) override
231     {
232         std::apply([&](auto&&... effect) { (effect.Detach(context), ...); }, effects_);
233     }
OnAppear()234     void OnAppear() override
235     {
236         std::apply([&](auto&&... effect) { (effect.Appear(), ...); }, effects_);
237     }
OnDisappear(bool activeTransition)238     void OnDisappear(bool activeTransition) override
239     {
240         std::apply([&](auto&&... effect) { (effect.Disappear(activeTransition), ...); }, effects_);
241     }
OnUpdateTransitionContext(const RefPtr<RosenRenderContext> & context,const RectF & selfRect,const SizeF & viewSize)242     void OnUpdateTransitionContext(
243         const RefPtr<RosenRenderContext>& context, const RectF& selfRect, const SizeF& viewSize) override
244     {
245         std::apply(
246             [&](auto&&... effect) { (effect.UpdateTransitionContext(context, selfRect, viewSize), ...); }, effects_);
247     }
248 
249 private:
250     DECLARE_ACE_TYPE(RosenCompositeTransitionEffect, RosenTransitionEffect);
251     ACE_DISALLOW_COPY_AND_MOVE(RosenCompositeTransitionEffect);
252 };
253 
254 using InternalTranslateZEffect = PropertyTransitionEffectTemplate<Rosen::RSTranslateZModifier, float>;
255 template<>
256 InternalTranslateZEffect::PropertyTransitionEffectTemplate();
257 // 3D Translate effect that accepts Dimension.
258 class RosenTranslateTransitionEffect final
259     : public RosenCompositeTransitionEffect<InternalTranslateEffect, InternalTranslateZEffect> {
260 public:
RosenTranslateTransitionEffect(const TranslateOptions & option)261     explicit RosenTranslateTransitionEffect(const TranslateOptions& option) : translateValue_(option) {}
262     ~RosenTranslateTransitionEffect() override = default;
263 
264     void SetTranslateEffect(const TranslateOptions& option);
265 
266 private:
267     void OnUpdateTransitionContext(
268         const RefPtr<RosenRenderContext>& context, const RectF& selfRect, const SizeF& viewSize) override;
269     TranslateOptions translateValue_;
270     DECLARE_ACE_TYPE(RosenTranslateTransitionEffect, RosenCompositeTransitionEffect);
271     ACE_DISALLOW_COPY_AND_MOVE(RosenTranslateTransitionEffect);
272 };
273 
274 // 3D rotation composite effect with pivot.
275 using InternalRotationXEffect = PropertyTransitionEffectTemplate<Rosen::RSRotationXModifier, float>;
276 using InternalRotationYEffect = PropertyTransitionEffectTemplate<Rosen::RSRotationYModifier, float>;
277 using InternalRotationZEffect = PropertyTransitionEffectTemplate<Rosen::RSRotationModifier, float>;
278 template<>
279 InternalRotationXEffect::PropertyTransitionEffectTemplate();
280 template<>
281 InternalRotationYEffect::PropertyTransitionEffectTemplate();
282 template<>
283 InternalRotationZEffect::PropertyTransitionEffectTemplate();
284 class RosenRotation3DTransitionEffect final
285     : public RosenCompositeTransitionEffect<InternalRotationXEffect, InternalRotationYEffect, InternalRotationZEffect,
286           RosenPivotTransitionEffect> {
287 public:
288     explicit RosenRotation3DTransitionEffect(const RotateOptions& options);
289     ~RosenRotation3DTransitionEffect() override = default;
290 
291     void SetRotateEffect(const RotateOptions& options);
292 
293 private:
294     DECLARE_ACE_TYPE(RosenRotation3DTransitionEffect, RosenCompositeTransitionEffect);
295     ACE_DISALLOW_COPY_AND_MOVE(RosenRotation3DTransitionEffect);
296 };
297 
298 using InternalScaleEffect = PropertyTransitionEffectTemplate<Rosen::RSScaleModifier, Rosen::Vector2f>;
299 template<>
300 InternalScaleEffect::PropertyTransitionEffectTemplate();
301 // 2D scale composite effect with pivot.
302 class RosenScaleTransitionEffect final
303     : public RosenCompositeTransitionEffect<InternalScaleEffect, RosenPivotTransitionEffect> {
304 public:
305     explicit RosenScaleTransitionEffect(const ScaleOptions& options);
306     ~RosenScaleTransitionEffect() override = default;
307 
308     void SetScaleEffect(const ScaleOptions& options);
309 
310 private:
311     DECLARE_ACE_TYPE(RosenScaleTransitionEffect, RosenCompositeTransitionEffect);
312     ACE_DISALLOW_COPY_AND_MOVE(RosenScaleTransitionEffect);
313 };
314 
315 class RosenSlideSwitchTransitionEffect final
316     : public RosenCompositeTransitionEffect<RosenSlideTransitionEffect, InternalScaleEffect> {
317 public:
318     RosenSlideSwitchTransitionEffect();
319     ~RosenSlideSwitchTransitionEffect() override = default;
320     void SetAnimationOption(const std::shared_ptr<AnimationOption>& option) override;
321 
322 private:
323     DECLARE_ACE_TYPE(RosenSlideSwitchTransitionEffect, RosenCompositeTransitionEffect);
324     ACE_DISALLOW_COPY_AND_MOVE(RosenSlideSwitchTransitionEffect);
325 };
326 } // namespace OHOS::Ace::NG
327 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PAINTS_ADAPTER_ROSEN_TRANSITION_EFFECT_IMPL_H
328