• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "core/components/tween/tween_element.h"
17 
18 #include "base/geometry/transform_util.h"
19 #include "core/animation/curve_animation.h"
20 #include "core/common/frontend.h"
21 #include "core/components/clip/render_clip.h"
22 #include "core/components/display/display_component.h"
23 #include "core/components/positioned/positioned_element.h"
24 #include "core/components/shared_transition/shared_transition_element.h"
25 #include "core/components/transform/transform_component.h"
26 #include "core/components/tween/tween_component.h"
27 #include "core/pipeline/base/render_element.h"
28 
29 namespace OHOS::Ace {
30 namespace {
GetAnimatable(const RefPtr<Element> & contentElement)31 RefPtr<PropertyAnimatable> GetAnimatable(const RefPtr<Element>& contentElement)
32 {
33     if (!contentElement) {
34         LOGE("Get Animatable failed. content element is null.");
35         return nullptr;
36     }
37     return AceType::DynamicCast<PropertyAnimatable>(contentElement->GetRenderNode());
38 }
39 
SetTranslateProperties(const RefPtr<Animation<DimensionOffset>> & translateAnimation,TweenOption & option)40 void SetTranslateProperties(const RefPtr<Animation<DimensionOffset>>& translateAnimation, TweenOption& option)
41 {
42     if (option.GetCurve()) {
43         translateAnimation->SetCurve(option.GetCurve());
44     }
45     if (!translateAnimation->HasInitValue()) {
46         DimensionOffset beginPos = DimensionOffset(Dimension(), Dimension());
47         translateAnimation->SetInitValue(beginPos);
48     }
49 }
50 
SetScaleProperties(const RefPtr<Animation<float>> & scaleAnimation,TweenOption & option)51 void SetScaleProperties(const RefPtr<Animation<float>>& scaleAnimation, TweenOption& option)
52 {
53     if (option.GetCurve()) {
54         scaleAnimation->SetCurve(option.GetCurve());
55     }
56     if (!scaleAnimation->HasInitValue()) {
57         scaleAnimation->SetInitValue(1.0f);
58     }
59 }
60 
SetRotateProperties(const RefPtr<Animation<float>> & rotateAnimation,TweenOption & option)61 void SetRotateProperties(const RefPtr<Animation<float>>& rotateAnimation, TweenOption& option)
62 {
63     if (option.GetCurve()) {
64         rotateAnimation->SetCurve(option.GetCurve());
65     }
66     if (!rotateAnimation->HasInitValue()) {
67         rotateAnimation->SetInitValue(0.0f);
68     }
69 }
70 
ResetController(RefPtr<Animator> & controller)71 void ResetController(RefPtr<Animator>& controller)
72 {
73     if (!controller) {
74         LOGE("Reset Controller failed. controller is null.");
75         return;
76     }
77     if (controller->GetStatus() != Animator::Status::IDLE && controller->GetStatus() != Animator::Status::STOPPED) {
78         controller->Finish();
79     }
80     controller->ClearInterpolators();
81 }
82 
83 template<class T>
SetAnimationProperties(const RefPtr<Animation<T>> & animation,TweenOption & option)84 void SetAnimationProperties(const RefPtr<Animation<T>>& animation, TweenOption& option)
85 {
86     if (option.GetCurve()) {
87         animation->SetCurve(option.GetCurve());
88     }
89     if (!animation->HasInitValue()) {
90         animation->SetInitValue(T {});
91     }
92 }
93 
RenderTransformUpdate(WeakPtr<RenderTransform> & weakPtr,const TransformOperation & value)94 void RenderTransformUpdate(WeakPtr<RenderTransform>& weakPtr, const TransformOperation& value)
95 {
96     auto renderTransformNode = weakPtr.Upgrade();
97     if (renderTransformNode) {
98         switch (value.type_) {
99             case TransformOperationType::TRANSLATE:
100                 renderTransformNode->Translate(
101                     value.translateOperation_.dx, value.translateOperation_.dy, value.translateOperation_.dz);
102                 break;
103             case TransformOperationType::SKEW:
104                 renderTransformNode->Skew(value.skewOperation_.skewX, value.skewOperation_.skewY);
105                 break;
106             case TransformOperationType::ROTATE:
107                 renderTransformNode->Rotate(value.rotateOperation_.angle, value.rotateOperation_.dx,
108                     value.rotateOperation_.dy, value.rotateOperation_.dz);
109                 break;
110             case TransformOperationType::MATRIX:
111                 renderTransformNode->Matrix3D(value.matrix4_);
112                 break;
113             case TransformOperationType::SCALE:
114                 renderTransformNode->Scale(
115                     value.scaleOperation_.scaleX, value.scaleOperation_.scaleY, value.scaleOperation_.scaleZ);
116                 break;
117             case TransformOperationType::PERSPECTIVE:
118                 renderTransformNode->Perspective(value.perspectiveOperation_.distance);
119                 break;
120             case TransformOperationType::UNDEFINED:
121                 renderTransformNode->Translate(Dimension {}, Dimension {}, Dimension {});
122                 break;
123             default:
124                 LOGE("unsupported transform operation");
125                 break;
126         }
127     }
128 }
129 
TransformComponentUpdate(WeakPtr<TransformComponent> & transform,const TransformOperation & value)130 void TransformComponentUpdate(WeakPtr<TransformComponent>& transform, const TransformOperation& value)
131 {
132     auto transformComponent = transform.Upgrade();
133     if (transformComponent) {
134         transformComponent->ResetTransform();
135         switch (value.type_) {
136             case TransformOperationType::TRANSLATE:
137                 transformComponent->Translate(
138                     value.translateOperation_.dx, value.translateOperation_.dy, value.translateOperation_.dz);
139                 break;
140             case TransformOperationType::SKEW:
141                 transformComponent->Skew(value.skewOperation_.skewX, value.skewOperation_.skewY);
142                 break;
143             case TransformOperationType::ROTATE:
144                 transformComponent->Rotate(value.rotateOperation_.dx, value.rotateOperation_.dy,
145                     value.rotateOperation_.dz, value.rotateOperation_.angle);
146                 break;
147             case TransformOperationType::MATRIX:
148                 transformComponent->Matrix3d(value.matrix4_);
149                 break;
150             case TransformOperationType::SCALE:
151                 transformComponent->Scale(
152                     value.scaleOperation_.scaleX, value.scaleOperation_.scaleY, value.scaleOperation_.scaleZ);
153                 break;
154             case TransformOperationType::PERSPECTIVE:
155                 transformComponent->Perspective(value.perspectiveOperation_.distance);
156                 break;
157             case TransformOperationType::UNDEFINED:
158                 transformComponent->Translate(Dimension {}, Dimension {}, Dimension {});
159                 break;
160             default:
161                 LOGE("unsupported transform operation");
162                 break;
163         }
164     }
165 }
166 
RenderTransformOriginUpdate(const WeakPtr<RenderTransform> & weakPtr,const DimensionOffset & origin)167 void RenderTransformOriginUpdate(const WeakPtr<RenderTransform>& weakPtr, const DimensionOffset& origin)
168 {
169     auto renderTransformNode = weakPtr.Upgrade();
170     if (renderTransformNode) {
171         renderTransformNode->SetTransformOrigin(origin.GetX(), origin.GetY());
172         renderTransformNode->MarkNeedUpdateOrigin();
173     }
174 }
175 
CreateTransformAnimation(const RefPtr<RenderTransform> & renderTransformNode,const WeakPtr<TransformComponent> & transform,TweenOption & option)176 void CreateTransformAnimation(const RefPtr<RenderTransform>& renderTransformNode,
177     const WeakPtr<TransformComponent>& transform, TweenOption& option)
178 {
179     WeakPtr<RenderTransform> weak(renderTransformNode);
180 
181     for (const auto& animation : option.GetTransformAnimations()) {
182         if (animation) {
183             SetAnimationProperties(animation, option);
184             animation->AddListener(std::bind(RenderTransformUpdate, weak, std::placeholders::_1));
185             animation->AddListener(std::bind(TransformComponentUpdate, transform, std::placeholders::_1));
186         }
187     }
188 }
189 
OpacityAnimationListener(const WeakPtr<RenderDisplay> & weakRender,WeakPtr<DisplayComponent> & display,float value)190 void OpacityAnimationListener(
191     const WeakPtr<RenderDisplay>& weakRender, WeakPtr<DisplayComponent>& display, float value)
192 {
193     auto opacity = static_cast<uint8_t>(Round(value * UINT8_MAX));
194     if (value < 0.0f || value > 1.0f) {
195         opacity = UINT8_MAX;
196     }
197     auto renderDisplayNode = weakRender.Upgrade();
198     auto displayComponent = display.Upgrade();
199     if (renderDisplayNode) {
200         renderDisplayNode->UpdateOpacity(opacity);
201         if (displayComponent) {
202             displayComponent->SetOpacity((double) opacity / UINT8_MAX);
203         }
204     }
205 }
206 
CreateOpacityAnimation(const RefPtr<RenderDisplay> & renderDisplayNode,const WeakPtr<DisplayComponent> & display,TweenOption & option)207 void CreateOpacityAnimation(
208     const RefPtr<RenderDisplay>& renderDisplayNode, const WeakPtr<DisplayComponent>& display, TweenOption& option)
209 {
210     auto& opacityAnimation = option.GetOpacityAnimation();
211     if (!opacityAnimation) {
212         LOGD("create opacity animation with null. skip it.");
213         return;
214     }
215     if (!opacityAnimation->HasInitValue()) {
216         opacityAnimation->SetInitValue(UINT8_MAX);
217     }
218     WeakPtr<RenderDisplay> weakRender = renderDisplayNode;
219     opacityAnimation->AddListener(std::bind(OpacityAnimationListener, weakRender, display, std::placeholders::_1));
220 
221     if (option.GetCurve()) {
222         opacityAnimation->SetCurve(option.GetCurve());
223     }
224 }
225 
BindingTransformAnimationToController(RefPtr<Animator> & controller,TweenOption & option)226 bool BindingTransformAnimationToController(RefPtr<Animator>& controller, TweenOption& option)
227 {
228     bool needAnimation = false;
229     const auto& animations = option.GetTransformAnimations();
230     for (auto& animation : animations) {
231         if (animation) {
232             needAnimation = true;
233             controller->AddInterpolator(animation);
234         }
235     }
236     return needAnimation;
237 }
238 
239 } // namespace
240 
241 const LinearEnumMapNode<AnimationType,
242     void (*)(const RefPtr<Animation<float>>&, WeakPtr<RenderTransform>&, TweenOption&)>
243     TweenElement::transformFloatAnimationAddMap_[] = {
244         { AnimationType::SCALE,
245             [](const RefPtr<Animation<float>>& scaleAnimation, WeakPtr<RenderTransform>& weakRender,
__anon834c61920202() 246                 TweenOption& option) {
247                 SetScaleProperties(scaleAnimation, option);
248                 scaleAnimation->AddListener([weakRender, scaleAnimation](float value) {
249                     auto renderTransformNode = weakRender.Upgrade();
250                     if (renderTransformNode) {
251                         renderTransformNode->Scale(value);
252                     }
253                 });
254             } },
255         { AnimationType::SCALE_X,
256             [](const RefPtr<Animation<float>>& scaleXAnimation, WeakPtr<RenderTransform>& weakRender,
__anon834c61920402() 257                 TweenOption& option) {
258                 SetScaleProperties(scaleXAnimation, option);
259                 double maxScaleXY = option.GetMaxScaleXY();
260                 auto renderTransformNode = weakRender.Upgrade();
261                 if (renderTransformNode) {
262                     renderTransformNode->SetMaxScaleXY(maxScaleXY);
263                 }
264                 scaleXAnimation->AddListener([weakRender, scaleXAnimation](float value) {
265                     auto renderTransformNode = weakRender.Upgrade();
266                     if (renderTransformNode) {
267                         renderTransformNode->Scale(value, 1.0f);
268                     }
269                 });
270             } },
271         { AnimationType::SCALE_Y,
272             [](const RefPtr<Animation<float>>& scaleYAnimation, WeakPtr<RenderTransform>& weakRender,
__anon834c61920602() 273                 TweenOption& option) {
274                 SetScaleProperties(scaleYAnimation, option);
275                 scaleYAnimation->AddListener([weakRender, scaleYAnimation](float value) {
276                     auto renderTransformNode = weakRender.Upgrade();
277                     if (renderTransformNode) {
278                         renderTransformNode->Scale(1.0f, value);
279                     }
280                 });
281             } },
282         { AnimationType::ROTATE_Z,
283             [](const RefPtr<Animation<float>>& rotateZAnimation, WeakPtr<RenderTransform>& weakRender,
__anon834c61920802() 284                 TweenOption& option) {
285                 SetRotateProperties(rotateZAnimation, option);
286                 rotateZAnimation->AddListener([weakRender, rotateZAnimation](float value) {
287                     auto renderTransformNode = weakRender.Upgrade();
288                     if (renderTransformNode) {
289                         renderTransformNode->RotateZ(value);
290                     }
291                 });
292             } },
293         { AnimationType::ROTATE_X,
294             [](const RefPtr<Animation<float>>& rotateXAnimation, WeakPtr<RenderTransform>& weakRender,
__anon834c61920a02() 295                 TweenOption& option) {
296                 SetRotateProperties(rotateXAnimation, option);
297                 rotateXAnimation->AddListener([weakRender, rotateXAnimation](float value) {
298                     auto renderTransformNode = weakRender.Upgrade();
299                     if (renderTransformNode) {
300                         renderTransformNode->RotateX(value);
301                     }
302                 });
303             } },
304         { AnimationType::ROTATE_Y,
305             [](const RefPtr<Animation<float>>& rotateYAnimation, WeakPtr<RenderTransform>& weakRender,
__anon834c61920c02() 306                 TweenOption& option) {
307                 SetRotateProperties(rotateYAnimation, option);
308                 rotateYAnimation->AddListener([weakRender, rotateYAnimation](float value) {
309                     auto renderTransformNode = weakRender.Upgrade();
310                     if (renderTransformNode) {
311                         renderTransformNode->RotateY(value);
312                     }
313                 });
314             } }
315     };
316 
Update()317 void TweenElement::Update()
318 {
319     ComposedElement::Update();
320     if (!component_) {
321         return;
322     }
323     auto tweenComponent = AceType::DynamicCast<TweenComponent>(component_);
324     if (!tweenComponent) {
325         LOGE("Get TweenComponent failed.");
326         return;
327     }
328     shadow_ = tweenComponent->GetShadow();
329     positionParam_ = tweenComponent->GetPositionParam();
330 
331     if (tweenComponent->IsAnimationNameUpdated()) {
332         needUpdateKeyframes_ = true;
333         tweenComponent->DisableAnimationNameUpdated();
334     }
335     if (tweenComponent->IsOptionCssChanged()) {
336         needUpdateTweenOption_ = true;
337         option_ = tweenComponent->GetTweenOption();
338         tweenComponent->SetOptionCssChanged(false);
339     }
340     if (tweenComponent->IsOptionCustomChanged()) {
341         needUpdateTweenOptionCustom_ = true;
342         optionCustom_ = tweenComponent->GetCustomTweenOption();
343         tweenComponent->SetOptionCustomChanged(false);
344     }
345     if (tweenComponent->IsOperationCssChanged()) {
346         operation_ = tweenComponent->GetAnimationOperation();
347         tweenComponent->SetOperationCssChanged(false);
348     }
349     if (tweenComponent->IsOperationCustomChanged()) {
350         operationCustom_ = tweenComponent->GetCustomAnimationOperation();
351         tweenComponent->SetOperationCustomChanged(false);
352     }
353     auto pipelineContext = context_.Upgrade();
354     if (pipelineContext) {
355         RefPtr<Animator> controller = tweenComponent->GetAnimator();
356         if (controller) {
357             isComponentController_ = true;
358             if (!controller->HasScheduler()) {
359                 controller->AttachScheduler(context_);
360             }
361             controllerCustom_ = controller;
362             tweenComponent->SetAnimator(controllerCustom_);
363         }
364         if (!controller_) {
365             isDelegatedController_ = false;
366             controller_ = CREATE_ANIMATOR(context_);
367             tweenComponent->SetAnimator(controller_);
368             LOGD("set animator to component when update.");
369         }
370 
371         LOGD("add request to pipeline context.");
372         // If transform component exists, it also plays animation. RenderTransform can get correct value from component
373         // when Update(component).
374         if ((operation_ != AnimationOperation::NONE || operationCustom_ != AnimationOperation::NONE) &&
375             !transform_.Upgrade()) {
376             pipelineContext->AddPostAnimationFlushListener(AceType::Claim(this));
377         }
378         pipelineContext->AddPostFlushListener(AceType::Claim(this));
379     }
380 }
381 
~TweenElement()382 TweenElement::~TweenElement()
383 {
384     if (isComponentController_ && controllerCustom_) {
385         controllerCustom_->Stop();
386         controllerCustom_->ClearInterpolators();
387         controllerCustom_->ClearAllListeners();
388     }
389 }
390 
ApplyOperation(RefPtr<Animator> & controller,AnimationOperation & operation)391 void TweenElement::ApplyOperation(RefPtr<Animator>& controller, AnimationOperation& operation)
392 {
393     LOGD("apply operation: %{public}d", operation);
394     switch (operation) {
395         case AnimationOperation::PLAY:
396             controller->Play();
397             break;
398         case AnimationOperation::RUNNING:
399             controller->Play();
400             break;
401         case AnimationOperation::PAUSE:
402             controller->Pause();
403             break;
404         case AnimationOperation::CANCEL:
405             controller->Cancel();
406             break;
407         case AnimationOperation::FINISH:
408             controller->Finish();
409             break;
410         case AnimationOperation::REVERSE:
411             controller->Reverse();
412             break;
413         case AnimationOperation::NONE:
414         default:
415             break;
416     }
417 }
418 
OnPostFlush()419 void TweenElement::OnPostFlush()
420 {
421     if (skipPostFlush_) {
422         skipPostFlush_ = false;
423         return;
424     }
425     AddPreFlush();
426 }
427 
OnPostAnimationFlush()428 void TweenElement::OnPostAnimationFlush()
429 {
430     if (controller_) {
431         controller_->TriggerFrame(controller_->GetPlayedTime(), true);
432     }
433     if (controllerCustom_) {
434         controllerCustom_->TriggerFrame(controllerCustom_->GetPlayedTime(), true);
435     }
436 }
437 
OnPreFlush()438 void TweenElement::OnPreFlush()
439 {
440     if (!controller_ && !controllerCustom_) {
441         LOGD("empty controller, skip start tween.");
442         return;
443     }
444     SetWrapHidden(false);
445     if (isDelegatedController_ && !isComponentController_) {
446         LOGD("controller is set from outside. skip prepare animation.");
447         return;
448     }
449 
450     if (needUpdateKeyframes_ || (operation_ == AnimationOperation::PLAY && needUpdateTweenOption_)) {
451         ResetController(controller_);
452         ApplyKeyframes();
453         needUpdateKeyframes_ = false;
454     }
455 
456     if (needUpdateTweenOption_) {
457         ApplyOptions(controller_, option_);
458         needUpdateTweenOption_ = false;
459     }
460     if (needUpdateTweenOptionCustom_) {
461         ResetController(controllerCustom_);
462         ApplyKeyframes(controllerCustom_, optionCustom_, prepareIdCustom_);
463         ApplyOptions(controllerCustom_, optionCustom_);
464         needUpdateTweenOptionCustom_ = false;
465     }
466     if (operation_ != AnimationOperation::NONE || operationCustom_ != AnimationOperation::NONE) {
467         auto pipelineContext = context_.Upgrade();
468         if (!pipelineContext) {
469             return;
470         }
471     }
472 
473     LOGD("Start tween animation with operation: %{public}d, operationCustom: %{public}d", operation_, operationCustom_);
474     if (controller_) {
475         ApplyOperation(controller_, operation_);
476     }
477     if (controllerCustom_) {
478         ApplyOperation(controllerCustom_, operationCustom_);
479     }
480 
481     // reset operation to none.
482     operation_ = AnimationOperation::NONE;
483     operationCustom_ = AnimationOperation::NONE;
484 }
485 
IsNeedAnimation(RefPtr<Animator> & controller,TweenOption & option)486 bool TweenElement::IsNeedAnimation(RefPtr<Animator>& controller, TweenOption& option)
487 {
488     if (!controller) {
489         LOGE("add interpolator failed. controller is null.");
490         return false;
491     }
492     bool needAnimation = false;
493     auto& transformOffsetAnimations = option.GetTranslateAnimations();
494     for (auto&& [translate, animation] : transformOffsetAnimations) {
495         if (animation) {
496             needAnimation = true;
497             LOGD("add translate animation.");
498             controller->AddInterpolator(animation);
499         }
500     }
501     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
502     for (auto&& [transformFloat, animation] : transformFloatAnimations) {
503         if (animation) {
504             needAnimation = true;
505             LOGD("add transform float animation.");
506             controller->AddInterpolator(animation);
507         }
508     }
509     if (BindingTransformAnimationToController(controller, option)) {
510         needAnimation = true;
511     }
512     auto& transformOriginAnimation = option.GetTransformOriginAnimation();
513     if (transformOriginAnimation) {
514         controller->AddInterpolator(transformOriginAnimation);
515         // no need enable needAnimation, Transform Origin Animation only work when set transform animation.
516     }
517     auto& opacityAnimation = option.GetOpacityAnimation();
518     if (opacityAnimation) {
519         LOGD("add opacity animation.");
520         controller->AddInterpolator(opacityAnimation);
521         needAnimation = true;
522     }
523     auto& colorAnimation = option.GetColorAnimation();
524     if (colorAnimation) {
525         LOGD("add color animation.");
526         controller->AddInterpolator(colorAnimation);
527         needAnimation = true;
528     }
529     if (AddToAnimator(option.GetFloatPropertyAnimation(), controller, option)) {
530         needAnimation = true;
531     }
532     return needAnimation;
533 }
534 
BuildChild()535 RefPtr<Component> TweenElement::BuildChild()
536 {
537     RefPtr<TweenComponent> tween = AceType::DynamicCast<TweenComponent>(component_);
538     if (tween) {
539         RefPtr<DisplayComponent> displayComponent = AceType::DynamicCast<DisplayComponent>(tween->GetChild());
540         RefPtr<TransformComponent> transformComponent;
541         if (displayComponent) {
542             transformComponent = AceType::DynamicCast<TransformComponent>(displayComponent->GetChild());
543             if (!transformComponent) {
544                 transformComponent = AceType::MakeRefPtr<TransformComponent>();
545                 transformComponent->SetChild(displayComponent->GetChild());
546                 displayComponent->SetChild(transformComponent);
547             }
548         } else {
549             transformComponent = AceType::MakeRefPtr<TransformComponent>();
550             displayComponent = AceType::MakeRefPtr<DisplayComponent>(transformComponent);
551             transformComponent->SetChild(ComposedElement::BuildChild());
552         }
553         displayComponent->SetPositionType(positionParam_.type);
554         displayComponent->SetHasLeft(positionParam_.left.second);
555         displayComponent->SetHasRight(positionParam_.right.second);
556         displayComponent->SetHasTop(positionParam_.top.second);
557         displayComponent->SetHasBottom(positionParam_.bottom.second);
558         displayComponent->SetLeft(positionParam_.left.first);
559         displayComponent->SetRight(positionParam_.right.first);
560         displayComponent->SetTop(positionParam_.top.first);
561         displayComponent->SetBottom(positionParam_.bottom.first);
562         displayComponent->DisableLayer(tween->IsLeafNode());
563         transform_ = transformComponent;
564         display_ = displayComponent;
565         return displayComponent;
566     } else {
567         LOGE("no tween component found. return empty child.");
568         return nullptr;
569     }
570 }
571 
PerformBuild()572 void TweenElement::PerformBuild()
573 {
574     ComposedElement::PerformBuild();
575     auto tweenComponent = AceType::DynamicCast<TweenComponent>(component_);
576     if (!tweenComponent) {
577         LOGE("Get TweenComponent failed.");
578         return;
579     }
580     if (!tweenComponent->GetIsFirstFrameShow()) {
581         SetWrapHidden(true);
582     }
583 }
584 
CanUpdate(const RefPtr<Component> & newComponent)585 bool TweenElement::CanUpdate(const RefPtr<Component>& newComponent)
586 {
587     auto pipelineContext = context_.Upgrade();
588     if (pipelineContext && pipelineContext->GetIsDeclarative()) {
589         return ComposedElement::CanUpdate(newComponent);
590     }
591     // components of the same type are not updated.
592     return Element::CanUpdate(newComponent);
593 }
594 
CreateTranslateAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)595 void TweenElement::CreateTranslateAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
596 {
597     if (!option.HasTransformOffsetChanged()) {
598         LOGD("create translate animation with null. skip it.");
599         return;
600     }
601     auto& transformOffsetAnimations = option.GetTranslateAnimations();
602     WeakPtr<RenderTransform> weakRender = renderTransformNode;
603     static const LinearEnumMapNode<AnimationType,
604         void (*)(const RefPtr<Animation<DimensionOffset>>&, WeakPtr<RenderTransform>&, TweenOption&)>
605         translateAnimationAddMap[] = {
606             { AnimationType::TRANSLATE,
607                 [](const RefPtr<Animation<DimensionOffset>>& translateAnimation,
608                     WeakPtr<RenderTransform>& weakRender, TweenOption& option) {
609                     SetTranslateProperties(translateAnimation, option);
610                     translateAnimation->AddListener([weakRender](const DimensionOffset& value) {
611                         auto renderTransformNode = weakRender.Upgrade();
612                         if (renderTransformNode) {
613                             renderTransformNode->Translate(value.GetX(), value.GetY());
614                         }
615                     });
616                 } },
617             { AnimationType::TRANSLATE_X,
618                 [](const RefPtr<Animation<DimensionOffset>>& translateXAnimation, WeakPtr<RenderTransform>& weakRender,
619                     TweenOption& option) {
620                     SetTranslateProperties(translateXAnimation, option);
621                     translateXAnimation->AddListener([weakRender](const DimensionOffset& value) {
622                         auto renderTransformNode = weakRender.Upgrade();
623                         if (renderTransformNode) {
624                             renderTransformNode->Translate(value.GetX(), 0.0_px);
625                         }
626                     });
627                 } },
628             { AnimationType::TRANSLATE_Y,
629                 [](const RefPtr<Animation<DimensionOffset>>& translateYAnimation, WeakPtr<RenderTransform>& weakRender,
630                     TweenOption& option) {
631                     SetTranslateProperties(translateYAnimation, option);
632                     translateYAnimation->AddListener([weakRender](const DimensionOffset& value) {
633                         auto renderTransformNode = weakRender.Upgrade();
634                         if (renderTransformNode) {
635                             renderTransformNode->Translate(0.0_px, value.GetY());
636                         }
637                     });
638                 } }
639             };
640     size_t mapSize = ArraySize(translateAnimationAddMap);
641     auto iterTranslateAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE);
642     if (iterTranslateAnimation != transformOffsetAnimations.end()) {
643         auto translateAnimationIter =
644             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE);
645         if (translateAnimationIter != -1) {
646             auto& translateAnimation = iterTranslateAnimation->second;
647             translateAnimationAddMap[translateAnimationIter].value(translateAnimation, weakRender, option);
648         }
649     }
650 
651     auto iterTranslateXAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE_X);
652     if (iterTranslateXAnimation != transformOffsetAnimations.end()) {
653         auto translateXAnimationIter =
654             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE_X);
655         if (translateXAnimationIter != -1) {
656             auto& translateXAnimation = iterTranslateXAnimation->second;
657             translateAnimationAddMap[translateXAnimationIter].value(translateXAnimation, weakRender, option);
658         }
659     }
660 
661     auto iterTranslateYAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE_Y);
662     if (iterTranslateYAnimation != transformOffsetAnimations.end()) {
663         auto translateYAnimationIter =
664             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE_Y);
665         if (translateYAnimationIter != -1) {
666             auto& translateYAnimation = iterTranslateYAnimation->second;
667             translateAnimationAddMap[translateYAnimationIter].value(translateYAnimation, weakRender, option);
668         }
669     }
670 }
671 
CreateScaleAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)672 void TweenElement::CreateScaleAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
673 {
674     if (!option.HasTransformFloatChanged()) {
675         LOGD("create scale animation with null. skip it.");
676         return;
677     }
678     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
679     WeakPtr<RenderTransform> weakRender = renderTransformNode;
680     auto iterScaleAnimation = transformFloatAnimations.find(AnimationType::SCALE);
681     size_t mapSize = ArraySize(transformFloatAnimationAddMap_);
682     if (iterScaleAnimation != transformFloatAnimations.end()) {
683         auto scaleAnimationIter = BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE);
684         if (scaleAnimationIter != -1) {
685             auto& scaleAnimation = iterScaleAnimation->second;
686             transformFloatAnimationAddMap_[scaleAnimationIter].value(scaleAnimation, weakRender, option);
687         }
688     }
689 
690     auto iterScaleXAnimation = transformFloatAnimations.find(AnimationType::SCALE_X);
691     if (iterScaleXAnimation != transformFloatAnimations.end()) {
692         auto scaleXAnimationIter =
693             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE_X);
694         if (scaleXAnimationIter != -1) {
695             auto& scaleXAnimation = iterScaleXAnimation->second;
696             transformFloatAnimationAddMap_[scaleXAnimationIter].value(scaleXAnimation, weakRender, option);
697         }
698     }
699 
700     auto iterScaleYAnimation = transformFloatAnimations.find(AnimationType::SCALE_Y);
701     if (iterScaleYAnimation != transformFloatAnimations.end()) {
702         auto scaleYAnimationIter =
703             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE_Y);
704         if (scaleYAnimationIter != -1) {
705             auto& scaleYAnimation = iterScaleYAnimation->second;
706             transformFloatAnimationAddMap_[scaleYAnimationIter].value(scaleYAnimation, weakRender, option);
707         }
708     }
709 }
710 
CreateTransformOriginAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)711 void TweenElement::CreateTransformOriginAnimation(
712     const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
713 {
714     if (option.HasTransformOriginChanged()) {
715         renderTransformNode->SetTransformOrigin(option.GetTransformOriginX(), option.GetTransformOriginY());
716         auto animation = option.GetTransformOriginAnimation();
717         if (animation) {
718             animation->AddListener([weak = AceType::WeakClaim(AceType::RawPtr(renderTransformNode))](
719                                        const DimensionOffset& value) { RenderTransformOriginUpdate(weak, value); });
720 
721             if (option.GetCurve()) {
722                 animation->SetCurve(option.GetCurve());
723             }
724         }
725         option.SetTransformOriginChanged(false);
726     } else {
727         renderTransformNode->SetTransformOrigin(HALF_PERCENT, HALF_PERCENT);
728         renderTransformNode->MarkNeedUpdateOrigin();
729     }
730 }
731 
CreateRotateAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)732 void TweenElement::CreateRotateAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
733 {
734     if (!option.HasTransformFloatChanged()) {
735         LOGD("create rotate animation with null. skip it.");
736         return;
737     }
738     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
739     WeakPtr<RenderTransform> weakRender = renderTransformNode;
740     auto iterRotateZAnimation = transformFloatAnimations.find(AnimationType::ROTATE_Z);
741     size_t mapSize = ArraySize(transformFloatAnimationAddMap_);
742     if (iterRotateZAnimation != transformFloatAnimations.end()) {
743         auto rotateZAnimationIter =
744             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_Z);
745         if (rotateZAnimationIter != -1) {
746             auto& rotateZAnimation = iterRotateZAnimation->second;
747             transformFloatAnimationAddMap_[rotateZAnimationIter].value(rotateZAnimation, weakRender, option);
748         }
749     }
750 
751     auto iterRotateXAnimation = transformFloatAnimations.find(AnimationType::ROTATE_X);
752     if (iterRotateXAnimation != transformFloatAnimations.end()) {
753         auto rotateXAnimationIter =
754             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_X);
755         if (rotateXAnimationIter != -1) {
756             auto& rotateXAnimation = iterRotateXAnimation->second;
757             transformFloatAnimationAddMap_[rotateXAnimationIter].value(rotateXAnimation, weakRender, option);
758         }
759     }
760 
761     auto iterRotateYAnimation = transformFloatAnimations.find(AnimationType::ROTATE_Y);
762     if (iterRotateYAnimation != transformFloatAnimations.end()) {
763         auto rotateYAnimationIter =
764             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_Y);
765         if (rotateYAnimationIter != -1) {
766             auto& rotateYAnimation = iterRotateYAnimation->second;
767             transformFloatAnimationAddMap_[rotateYAnimationIter].value(rotateYAnimation, weakRender, option);
768         }
769     }
770 }
771 
CreateColorAnimation(const RefPtr<PropertyAnimatable> & animatable,TweenOption & option)772 void TweenElement::CreateColorAnimation(const RefPtr<PropertyAnimatable>& animatable, TweenOption& option)
773 {
774     if (!animatable) {
775         LOGE("create color animation failed. not a animatable child.");
776         return;
777     }
778     auto& colorAnimation = option.GetColorAnimation();
779     if (!colorAnimation) {
780         LOGD("create color animation with null. skip it.");
781         return;
782     }
783     PropertyAnimatableType propertyType;
784     if (option.GetIsBackground()) {
785         propertyType = PropertyAnimatableType::PROPERTY_BACK_DECORATION_COLOR;
786     } else {
787         propertyType = PropertyAnimatableType::PROPERTY_FRONT_DECORATION_COLOR;
788     }
789     CreatePropertyAnimation<ColorPropertyAnimatable, Color>(animatable, propertyType, option, colorAnimation);
790 }
791 
792 template<class U, class V>
CreatePropertyAnimation(const RefPtr<PropertyAnimatable> & propertyAnimatable,PropertyAnimatableType propertyType,const TweenOption & option,RefPtr<Animation<V>> & animation)793 bool TweenElement::CreatePropertyAnimation(const RefPtr<PropertyAnimatable>& propertyAnimatable,
794     PropertyAnimatableType propertyType, const TweenOption& option, RefPtr<Animation<V>>& animation)
795 {
796     if (!animation) {
797         LOGE("CreatePropertyAnimation failed, animation is null.");
798         return false;
799     }
800     typename U::Type initValue;
801     bool created =
802         PropertyAnimatable::AddPropertyAnimation<U, V>(propertyAnimatable, propertyType, animation, initValue);
803     if (!created) {
804         LOGE("create property animation failed. property: %{public}d", propertyType);
805         return false;
806     }
807     if (option.GetCurve()) {
808         animation->SetCurve(option.GetCurve());
809     }
810     if (!animation->HasInitValue()) {
811         animation->SetInitValue(initValue);
812     }
813     return true;
814 }
815 
816 template<class U>
AddToAnimator(const std::map<PropertyAnimatableType,U> & animations,RefPtr<Animator> & controller,TweenOption & option)817 bool TweenElement::AddToAnimator(
818     const std::map<PropertyAnimatableType, U>& animations, RefPtr<Animator>& controller, TweenOption& option)
819 {
820     bool needAnimation = false;
821     for (auto&& [property, animation] : animations) {
822         if (animation) {
823             needAnimation = true;
824             LOGD("add property animation. property: %{public}d", property);
825             controller->AddInterpolator(animation);
826         }
827     }
828     return needAnimation;
829 }
830 
SetController(const RefPtr<Animator> & controller)831 void TweenElement::SetController(const RefPtr<Animator>& controller)
832 {
833     if (!controller) {
834         LOGE("set controller failed. controller is empty.");
835         return;
836     }
837     LOGD("set controller");
838     if (!controller_->IsStopped()) {
839         controller_->Stop();
840     }
841     isDelegatedController_ = true;
842     controller_ = controller;
843 }
844 
GetOption() const845 const TweenOption& TweenElement::GetOption() const
846 {
847     return option_;
848 }
849 
SetOption(const TweenOption & option)850 void TweenElement::SetOption(const TweenOption& option)
851 {
852     LOGD("set tween option");
853     option_ = option;
854 }
855 
GetController() const856 const RefPtr<Animator>& TweenElement::GetController() const
857 {
858     return controller_;
859 }
860 
SetOpacity(uint8_t opacity)861 void TweenElement::SetOpacity(uint8_t opacity)
862 {
863     if (children_.empty()) {
864         LOGE("no child when set Opacity");
865         return;
866     }
867     const auto& child = children_.front();
868     if (!child) {
869         LOGE("child is null.");
870         return;
871     }
872     auto childElement = AceType::DynamicCast<RenderElement>(child);
873     if (!childElement) {
874         LOGE("child element is null.");
875         return;
876     }
877     const auto& displayRenderNode = AceType::DynamicCast<RenderDisplay>(childElement->GetRenderNode());
878     if (!displayRenderNode) {
879         LOGE("no display render node found.");
880         return;
881     }
882     LOGD("set Opacity. Opacity: %{public}d", opacity);
883     displayRenderNode->UpdateOpacity(opacity);
884 }
885 
SkipPostFlush()886 void TweenElement::SkipPostFlush()
887 {
888     skipPostFlush_ = true;
889 }
890 
AddPreFlush()891 void TweenElement::AddPreFlush()
892 {
893     auto pipelineContext = context_.Upgrade();
894     if (!pipelineContext) {
895         return;
896     }
897     pipelineContext->AddPreFlushListener(AceType::Claim(this));
898 }
899 
SetWrapHidden(bool hidden)900 void TweenElement::SetWrapHidden(bool hidden)
901 {
902     if (children_.empty()) {
903         LOGE("no child when set visible");
904         return;
905     }
906     const auto& child = children_.front();
907     if (!child) {
908         LOGE("child is null.");
909         return;
910     }
911     auto childElement = AceType::DynamicCast<RenderElement>(child);
912     if (!childElement) {
913         LOGE("child element is null.");
914         return;
915     }
916     const auto& displayRenderNode = AceType::DynamicCast<RenderDisplay>(childElement->GetRenderNode());
917     if (!displayRenderNode) {
918         LOGE("no display render node found.");
919         return;
920     }
921     displayRenderNode->UpdateHidden(hidden);
922 }
923 
SetTouchable(bool enable)924 void TweenElement::SetTouchable(bool enable)
925 {
926     LOGD("set tween touchable status: %{public}d", enable);
927 
928     if (children_.empty()) {
929         LOGW("get content child failed. no child yet.");
930         return;
931     }
932     const auto& child = children_.front();
933     if (!child || child->GetType() != RENDER_ELEMENT) {
934         LOGW("get content child failed. null child or not render child.");
935         return;
936     }
937     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
938     if (!transformElement) {
939         LOGE("Get RenderElement failed.");
940         return;
941     }
942     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
943     if (transformRenderNode) {
944         transformRenderNode->SetTouchable(enable);
945     }
946 }
947 
GetContentRender() const948 RefPtr<RenderNode> TweenElement::GetContentRender() const
949 {
950     auto contentElement = GetContentElement();
951     if (!contentElement) {
952         return nullptr;
953     }
954     return contentElement->GetRenderNode();
955 }
956 
ApplyKeyframes()957 bool TweenElement::ApplyKeyframes()
958 {
959     return ApplyKeyframes(controller_, option_, prepareId_);
960 }
961 
AddPrepareListener(RefPtr<Animator> & controller,const WeakPtr<RenderTransform> & weakTransform,BaseId::IdType & prepareId)962 void TweenElement::AddPrepareListener(
963     RefPtr<Animator>& controller, const WeakPtr<RenderTransform>& weakTransform, BaseId::IdType& prepareId)
964 {
965     if (!controller) {
966         LOGE("Add Prepare Listener failed. controller is null.");
967         return;
968     }
969     controller->RemovePrepareListener(prepareId);
970     prepareId =
971         controller->AddPrepareListener([weakTransform, weakContext = context_,
972                                            weakTween = AceType::WeakClaim(this),
973                                            needForceResetTransform =
974                                               controller->GetAllowRunningAsynchronously()]() {
975             // reset transform matrix at the start of every frame.
976             auto context = weakContext.Upgrade();
977             auto tween = weakTween.Upgrade();
978             auto transform = weakTransform.Upgrade();
979             if (context && tween && transform) {
980                 auto currentTimestamp = context->GetTimeFromExternalTimer();
981                 if (tween->currentTimestamp_ != currentTimestamp || tween->currentTimestamp_ == 0 ||
982                     needForceResetTransform) {
983                     transform->ResetTransform();
984                     tween->currentTimestamp_ = currentTimestamp;
985                 }
986             }
987         });
988 }
989 
ApplyKeyframes(RefPtr<Animator> & controller,TweenOption & option,BaseId::IdType & prepareId)990 bool TweenElement::ApplyKeyframes(RefPtr<Animator>& controller, TweenOption& option, BaseId::IdType& prepareId)
991 {
992     if (!controller) {
993         LOGW("controller is null.");
994         return false;
995     }
996     if (children_.empty()) {
997         LOGW("apply option failed. no child yet.");
998         return false;
999     }
1000     const auto& child = children_.front();
1001     if (!child || child->GetType() != RENDER_ELEMENT) {
1002         LOGW("apply option failed. null child or not render child.");
1003         return false;
1004     }
1005     LOGD("TweenElement: ApplyKeyframes.");
1006 
1007     const auto& displayRenderNode =
1008         AceType::DynamicCast<RenderDisplay>(AceType::DynamicCast<RenderElement>(child)->GetRenderNode());
1009     if (!displayRenderNode) {
1010         LOGE("display render node is null.");
1011         return false;
1012     }
1013     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
1014     if (!transformElement) {
1015         LOGE("transform element node is null.");
1016         return false;
1017     }
1018     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
1019     if (!transformRenderNode) {
1020         LOGE("transform render node is null.");
1021         return false;
1022     }
1023     if (shadow_.IsValid()) {
1024         displayRenderNode->SetShadow(shadow_);
1025         transformRenderNode->SetShadow(shadow_);
1026     }
1027 
1028     const auto& contentElement = AceType::DynamicCast<RenderElement>(transformElement)->GetFirstChild();
1029     auto animatable = GetAnimatable(contentElement);
1030     if (animatable) {
1031         CreateColorAnimation(animatable, option);
1032         CreatePropertyAnimationFloat(animatable, option);
1033     }
1034     CreateTransformAnimation(transformRenderNode, transform_, option);
1035     CreateTranslateAnimation(transformRenderNode, option);
1036     CreateScaleAnimation(transformRenderNode, option);
1037     CreateRotateAnimation(transformRenderNode, option);
1038     CreateTransformOriginAnimation(transformRenderNode, option);
1039     if (option.HasTransformOffsetChanged() || option.HasTransformFloatChanged() || option.HasTransformChanged()) {
1040         AddPrepareListener(controller, transformRenderNode, prepareId);
1041     }
1042     CreateOpacityAnimation(displayRenderNode, display_, option);
1043     return IsNeedAnimation(controller, option);
1044 }
1045 
ApplyOptions(RefPtr<Animator> & controller,TweenOption & option)1046 void TweenElement::ApplyOptions(RefPtr<Animator>& controller, TweenOption& option)
1047 {
1048     if (!controller) {
1049         LOGE("Apply Options failed. Controller is null.");
1050         return;
1051     }
1052     LOGD("apply options.");
1053     controller->SetDuration(option.GetDuration());
1054     controller->SetIteration(option.GetIteration());
1055     controller->SetStartDelay(option.GetDelay());
1056     controller->SetFillMode(option.GetFillMode());
1057     controller->SetTempo(option.GetTempo());
1058     controller->SetAnimationDirection(option.GetAnimationDirection());
1059     controller->SetAllowRunningAsynchronously(option.GetAllowRunningAsynchronously());
1060 
1061     for (const auto& [type, animation] : option.GetAnimatables()) {
1062         if (option.GetCurve()) {
1063             animation->SetCurve(option.GetCurve());
1064         }
1065         controller->AddInterpolator(animation);
1066     }
1067 }
1068 
ApplyOptions()1069 void TweenElement::ApplyOptions()
1070 {
1071     ApplyOptions(controller_, option_);
1072 }
1073 
GetContentElement() const1074 RefPtr<Element> TweenElement::GetContentElement() const
1075 {
1076     const auto& mountParent = GetContentParent();
1077     if (!mountParent) {
1078         LOGE("Get content element failed. content parent is null.");
1079         return nullptr;
1080     }
1081     return mountParent->GetFirstChild();
1082 }
1083 
GetContentParent() const1084 RefPtr<Element> TweenElement::GetContentParent() const
1085 {
1086     const auto child = GetFirstChild();
1087     if (!child) {
1088         LOGW("Get transformElement failed. null child.");
1089         return nullptr;
1090     }
1091     const auto& displayRenderNode =
1092         AceType::DynamicCast<RenderDisplay>(AceType::DynamicCast<RenderElement>(child)->GetRenderNode());
1093     if (!displayRenderNode) {
1094         LOGE("display render node is null.");
1095         return nullptr;
1096     }
1097     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
1098     if (!transformElement) {
1099         LOGE("Get transformElement failed. transform element is null");
1100         return nullptr;
1101     }
1102     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
1103     if (!transformRenderNode) {
1104         LOGE("Get transformElement failed. transform render node is null.");
1105         return nullptr;
1106     }
1107     return transformElement;
1108 }
1109 
CreatePropertyAnimationFloat(const RefPtr<PropertyAnimatable> & animatable,TweenOption & option)1110 void TweenElement::CreatePropertyAnimationFloat(const RefPtr<PropertyAnimatable>& animatable, TweenOption& option)
1111 {
1112     if (!animatable) {
1113         LOGE("Create property animation for float failed. animatable is null.");
1114         return;
1115     }
1116     auto& propertyFloatMap = option.GetFloatPropertyAnimation();
1117     if (propertyFloatMap.empty()) {
1118         LOGD("No property animation float found. skip it.");
1119         return;
1120     }
1121     for (auto&& [property, animation] : propertyFloatMap) {
1122         LOGD("Create animation float for property: %{public}d", property);
1123         CreatePropertyAnimation<FloatPropertyAnimatable, float>(animatable, property, option, animation);
1124     }
1125 }
1126 
1127 } // namespace OHOS::Ace
1128