• 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,
__anon5900b1650202() 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,
__anon5900b1650402() 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,
__anon5900b1650602() 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,
__anon5900b1650802() 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,
__anon5900b1650a02() 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,
__anon5900b1650c02() 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         }
363         if (!controller_) {
364             isDelegatedController_ = false;
365             controller_ = AceType::MakeRefPtr<Animator>(context_);
366             LOGD("set animator to component when update.");
367         }
368 
369         LOGD("add request to pipeline context.");
370         if (operation_ == AnimationOperation::PAUSE || operation_ == AnimationOperation::FINISH
371             || operationCustom_ == AnimationOperation::PAUSE || operationCustom_ == AnimationOperation::FINISH) {
372             pipelineContext->AddPostAnimationFlushListener(AceType::Claim(this));
373         }
374         pipelineContext->AddPostFlushListener(AceType::Claim(this));
375     }
376 }
377 
~TweenElement()378 TweenElement::~TweenElement()
379 {
380     if (isComponentController_ && controllerCustom_) {
381         controllerCustom_->ClearInterpolators();
382         controllerCustom_->ClearAllListeners();
383         controllerCustom_->Stop();
384     }
385 }
386 
ApplyOperation(RefPtr<Animator> & controller,AnimationOperation & operation)387 void TweenElement::ApplyOperation(RefPtr<Animator>& controller, AnimationOperation& operation)
388 {
389     LOGD("apply operation: %{public}d", operation);
390     switch (operation) {
391         case AnimationOperation::PLAY:
392             controller->Play();
393             break;
394         case AnimationOperation::RUNNING:
395             controller->Play();
396             break;
397         case AnimationOperation::PAUSE:
398             controller->Pause();
399             break;
400         case AnimationOperation::CANCEL:
401             controller->Cancel();
402             break;
403         case AnimationOperation::FINISH:
404             controller->Finish();
405             break;
406         case AnimationOperation::REVERSE:
407             controller->Reverse();
408             break;
409         case AnimationOperation::NONE:
410         default:
411             break;
412     }
413 }
414 
OnPostFlush()415 void TweenElement::OnPostFlush()
416 {
417     if (skipPostFlush_) {
418         skipPostFlush_ = false;
419         return;
420     }
421     AddPreFlush();
422 }
423 
OnPostAnimationFlush()424 void TweenElement::OnPostAnimationFlush()
425 {
426     if (controller_) {
427         controller_->TriggerFrame(controller_->GetPlayedTime(), true);
428     }
429     if (controllerCustom_) {
430         controllerCustom_->TriggerFrame(controllerCustom_->GetPlayedTime(), true);
431     }
432 }
433 
OnPreFlush()434 void TweenElement::OnPreFlush()
435 {
436     if (!controller_ && !controllerCustom_) {
437         LOGD("empty controller, skip start tween.");
438         return;
439     }
440     SetWrapHidden(false);
441     if (isDelegatedController_ && !isComponentController_) {
442         LOGD("controller is set from outside. skip prepare animation.");
443         return;
444     }
445 
446     if (needUpdateKeyframes_ || (operation_ == AnimationOperation::PLAY && needUpdateTweenOption_)) {
447         ResetController(controller_);
448         ApplyKeyframes();
449         needUpdateKeyframes_ = false;
450     }
451 
452     if (needUpdateTweenOption_) {
453         ApplyOptions(controller_, option_);
454         needUpdateTweenOption_ = false;
455     }
456     if (needUpdateTweenOptionCustom_) {
457         ResetController(controllerCustom_);
458         ApplyKeyframes(controllerCustom_, optionCustom_, prepareIdCustom_);
459         ApplyOptions(controllerCustom_, optionCustom_);
460         needUpdateTweenOptionCustom_ = false;
461     }
462     if (operation_ != AnimationOperation::NONE || operationCustom_ != AnimationOperation::NONE) {
463         auto pipelineContext = context_.Upgrade();
464         if (!pipelineContext) {
465             return;
466         }
467     }
468 
469     LOGD("Start tween animation with operation: %{public}d, operationCustom: %{public}d", operation_, operationCustom_);
470     if (controller_) {
471         ApplyOperation(controller_, operation_);
472     }
473     if (controllerCustom_) {
474         ApplyOperation(controllerCustom_, operationCustom_);
475     }
476 
477     // reset operation to none.
478     operation_ = AnimationOperation::NONE;
479     operationCustom_ = AnimationOperation::NONE;
480 }
481 
IsNeedAnimation(RefPtr<Animator> & controller,TweenOption & option)482 bool TweenElement::IsNeedAnimation(RefPtr<Animator>& controller, TweenOption& option)
483 {
484     if (!controller) {
485         LOGE("add interpolator failed. controller is null.");
486         return false;
487     }
488     bool needAnimation = false;
489     auto& transformOffsetAnimations = option.GetTranslateAnimations();
490     for (auto&& [translate, animation] : transformOffsetAnimations) {
491         if (animation) {
492             needAnimation = true;
493             LOGD("add translate animation.");
494             controller->AddInterpolator(animation);
495         }
496     }
497     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
498     for (auto&& [transformFloat, animation] : transformFloatAnimations) {
499         if (animation) {
500             needAnimation = true;
501             LOGD("add transform float animation.");
502             controller->AddInterpolator(animation);
503         }
504     }
505     if (BindingTransformAnimationToController(controller, option)) {
506         needAnimation = true;
507     }
508     auto& transformOriginAnimation = option.GetTransformOriginAnimation();
509     if (transformOriginAnimation) {
510         controller->AddInterpolator(transformOriginAnimation);
511         // no need enable needAnimation, Transform Origin Animation only work when set transform animation.
512     }
513     auto& opacityAnimation = option.GetOpacityAnimation();
514     if (opacityAnimation) {
515         LOGD("add opacity animation.");
516         controller->AddInterpolator(opacityAnimation);
517         needAnimation = true;
518     }
519     auto& colorAnimation = option.GetColorAnimation();
520     if (colorAnimation) {
521         LOGD("add color animation.");
522         controller->AddInterpolator(colorAnimation);
523         needAnimation = true;
524     }
525     if (AddToAnimator(option.GetFloatPropertyAnimation(), controller, option)) {
526         needAnimation = true;
527     }
528     return needAnimation;
529 }
530 
BuildChild()531 RefPtr<Component> TweenElement::BuildChild()
532 {
533     RefPtr<TweenComponent> tween = AceType::DynamicCast<TweenComponent>(component_);
534     if (tween) {
535         RefPtr<DisplayComponent> displayComponent = AceType::DynamicCast<DisplayComponent>(tween->GetChild());
536         RefPtr<TransformComponent> transformComponent;
537         if (displayComponent) {
538             transformComponent = AceType::DynamicCast<TransformComponent>(displayComponent->GetChild());
539             if (!transformComponent) {
540                 transformComponent = AceType::MakeRefPtr<TransformComponent>();
541                 transformComponent->SetChild(displayComponent->GetChild());
542                 displayComponent->SetChild(transformComponent);
543             }
544         } else {
545             transformComponent = AceType::MakeRefPtr<TransformComponent>();
546             displayComponent = AceType::MakeRefPtr<DisplayComponent>(transformComponent);
547             transformComponent->SetChild(ComposedElement::BuildChild());
548         }
549         displayComponent->SetPositionType(positionParam_.type);
550         displayComponent->SetHasLeft(positionParam_.left.second);
551         displayComponent->SetHasRight(positionParam_.right.second);
552         displayComponent->SetHasTop(positionParam_.top.second);
553         displayComponent->SetHasBottom(positionParam_.bottom.second);
554         displayComponent->SetLeft(positionParam_.left.first);
555         displayComponent->SetRight(positionParam_.right.first);
556         displayComponent->SetTop(positionParam_.top.first);
557         displayComponent->SetBottom(positionParam_.bottom.first);
558         displayComponent->DisableLayer(tween->IsLeafNode());
559         transform_ = transformComponent;
560         display_ = displayComponent;
561         return displayComponent;
562     } else {
563         LOGE("no tween component found. return empty child.");
564         return nullptr;
565     }
566 }
567 
PerformBuild()568 void TweenElement::PerformBuild()
569 {
570     ComposedElement::PerformBuild();
571     auto tweenComponent = AceType::DynamicCast<TweenComponent>(component_);
572     if (!tweenComponent) {
573         LOGE("Get TweenComponent failed.");
574         return;
575     }
576     if (!tweenComponent->GetIsFirstFrameShow()) {
577         SetWrapHidden(true);
578     }
579 }
580 
CanUpdate(const RefPtr<Component> & newComponent)581 bool TweenElement::CanUpdate(const RefPtr<Component>& newComponent)
582 {
583     auto pipelineContext = context_.Upgrade();
584     if (pipelineContext && pipelineContext->GetIsDeclarative()) {
585         return ComposedElement::CanUpdate(newComponent);
586     }
587     // components of the same type are not updated.
588     return Element::CanUpdate(newComponent);
589 }
590 
CreateTranslateAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)591 void TweenElement::CreateTranslateAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
592 {
593     if (!option.HasTransformOffsetChanged()) {
594         LOGD("create translate animation with null. skip it.");
595         return;
596     }
597     auto& transformOffsetAnimations = option.GetTranslateAnimations();
598     WeakPtr<RenderTransform> weakRender = renderTransformNode;
599     static const LinearEnumMapNode<AnimationType,
600         void (*)(const RefPtr<Animation<DimensionOffset>>&, WeakPtr<RenderTransform>&, TweenOption&)>
601         translateAnimationAddMap[] = {
602             { AnimationType::TRANSLATE,
603                 [](const RefPtr<Animation<DimensionOffset>>& translateAnimation,
604                     WeakPtr<RenderTransform>& weakRender, TweenOption& option) {
605                     SetTranslateProperties(translateAnimation, option);
606                     translateAnimation->AddListener([weakRender](const DimensionOffset& value) {
607                         auto renderTransformNode = weakRender.Upgrade();
608                         if (renderTransformNode) {
609                             renderTransformNode->Translate(value.GetX(), value.GetY());
610                         }
611                     });
612                 } },
613             { AnimationType::TRANSLATE_X,
614                 [](const RefPtr<Animation<DimensionOffset>>& translateXAnimation, WeakPtr<RenderTransform>& weakRender,
615                     TweenOption& option) {
616                     SetTranslateProperties(translateXAnimation, option);
617                     translateXAnimation->AddListener([weakRender](const DimensionOffset& value) {
618                         auto renderTransformNode = weakRender.Upgrade();
619                         if (renderTransformNode) {
620                             renderTransformNode->Translate(value.GetX(), 0.0_px);
621                         }
622                     });
623                 } },
624             { AnimationType::TRANSLATE_Y,
625                 [](const RefPtr<Animation<DimensionOffset>>& translateYAnimation, WeakPtr<RenderTransform>& weakRender,
626                     TweenOption& option) {
627                     SetTranslateProperties(translateYAnimation, option);
628                     translateYAnimation->AddListener([weakRender](const DimensionOffset& value) {
629                         auto renderTransformNode = weakRender.Upgrade();
630                         if (renderTransformNode) {
631                             renderTransformNode->Translate(0.0_px, value.GetY());
632                         }
633                     });
634                 } }
635             };
636     size_t mapSize = ArraySize(translateAnimationAddMap);
637     auto iterTranslateAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE);
638     if (iterTranslateAnimation != transformOffsetAnimations.end()) {
639         auto translateAnimationIter =
640             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE);
641         if (translateAnimationIter != -1) {
642             auto& translateAnimation = iterTranslateAnimation->second;
643             translateAnimationAddMap[translateAnimationIter].value(translateAnimation, weakRender, option);
644         }
645     }
646 
647     auto iterTranslateXAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE_X);
648     if (iterTranslateXAnimation != transformOffsetAnimations.end()) {
649         auto translateXAnimationIter =
650             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE_X);
651         if (translateXAnimationIter != -1) {
652             auto& translateXAnimation = iterTranslateXAnimation->second;
653             translateAnimationAddMap[translateXAnimationIter].value(translateXAnimation, weakRender, option);
654         }
655     }
656 
657     auto iterTranslateYAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE_Y);
658     if (iterTranslateYAnimation != transformOffsetAnimations.end()) {
659         auto translateYAnimationIter =
660             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE_Y);
661         if (translateYAnimationIter != -1) {
662             auto& translateYAnimation = iterTranslateYAnimation->second;
663             translateAnimationAddMap[translateYAnimationIter].value(translateYAnimation, weakRender, option);
664         }
665     }
666 }
667 
CreateScaleAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)668 void TweenElement::CreateScaleAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
669 {
670     if (!option.HasTransformFloatChanged()) {
671         LOGD("create scale animation with null. skip it.");
672         return;
673     }
674     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
675     WeakPtr<RenderTransform> weakRender = renderTransformNode;
676     auto iterScaleAnimation = transformFloatAnimations.find(AnimationType::SCALE);
677     size_t mapSize = ArraySize(transformFloatAnimationAddMap_);
678     if (iterScaleAnimation != transformFloatAnimations.end()) {
679         auto scaleAnimationIter = BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE);
680         if (scaleAnimationIter != -1) {
681             auto& scaleAnimation = iterScaleAnimation->second;
682             transformFloatAnimationAddMap_[scaleAnimationIter].value(scaleAnimation, weakRender, option);
683         }
684     }
685 
686     auto iterScaleXAnimation = transformFloatAnimations.find(AnimationType::SCALE_X);
687     if (iterScaleXAnimation != transformFloatAnimations.end()) {
688         auto scaleXAnimationIter =
689             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE_X);
690         if (scaleXAnimationIter != -1) {
691             auto& scaleXAnimation = iterScaleXAnimation->second;
692             transformFloatAnimationAddMap_[scaleXAnimationIter].value(scaleXAnimation, weakRender, option);
693         }
694     }
695 
696     auto iterScaleYAnimation = transformFloatAnimations.find(AnimationType::SCALE_Y);
697     if (iterScaleYAnimation != transformFloatAnimations.end()) {
698         auto scaleYAnimationIter =
699             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE_Y);
700         if (scaleYAnimationIter != -1) {
701             auto& scaleYAnimation = iterScaleYAnimation->second;
702             transformFloatAnimationAddMap_[scaleYAnimationIter].value(scaleYAnimation, weakRender, option);
703         }
704     }
705 }
706 
CreateTransformOriginAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)707 void TweenElement::CreateTransformOriginAnimation(
708     const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
709 {
710     if (option.HasTransformOriginChanged()) {
711         renderTransformNode->SetTransformOrigin(option.GetTransformOriginX(), option.GetTransformOriginY());
712         auto animation = option.GetTransformOriginAnimation();
713         if (animation) {
714             animation->AddListener([weak = AceType::WeakClaim(AceType::RawPtr(renderTransformNode))](
715                                        const DimensionOffset& value) { RenderTransformOriginUpdate(weak, value); });
716 
717             if (option.GetCurve()) {
718                 animation->SetCurve(option.GetCurve());
719             }
720         }
721         option.SetTransformOriginChanged(false);
722     } else {
723         renderTransformNode->SetTransformOrigin(HALF_PERCENT, HALF_PERCENT);
724         renderTransformNode->MarkNeedUpdateOrigin();
725     }
726 }
727 
CreateRotateAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)728 void TweenElement::CreateRotateAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
729 {
730     if (!option.HasTransformFloatChanged()) {
731         LOGD("create rotate animation with null. skip it.");
732         return;
733     }
734     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
735     WeakPtr<RenderTransform> weakRender = renderTransformNode;
736     auto iterRotateZAnimation = transformFloatAnimations.find(AnimationType::ROTATE_Z);
737     size_t mapSize = ArraySize(transformFloatAnimationAddMap_);
738     if (iterRotateZAnimation != transformFloatAnimations.end()) {
739         auto rotateZAnimationIter =
740             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_Z);
741         if (rotateZAnimationIter != -1) {
742             auto& rotateZAnimation = iterRotateZAnimation->second;
743             transformFloatAnimationAddMap_[rotateZAnimationIter].value(rotateZAnimation, weakRender, option);
744         }
745     }
746 
747     auto iterRotateXAnimation = transformFloatAnimations.find(AnimationType::ROTATE_X);
748     if (iterRotateXAnimation != transformFloatAnimations.end()) {
749         auto rotateXAnimationIter =
750             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_X);
751         if (rotateXAnimationIter != -1) {
752             auto& rotateXAnimation = iterRotateXAnimation->second;
753             transformFloatAnimationAddMap_[rotateXAnimationIter].value(rotateXAnimation, weakRender, option);
754         }
755     }
756 
757     auto iterRotateYAnimation = transformFloatAnimations.find(AnimationType::ROTATE_Y);
758     if (iterRotateYAnimation != transformFloatAnimations.end()) {
759         auto rotateYAnimationIter =
760             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_Y);
761         if (rotateYAnimationIter != -1) {
762             auto& rotateYAnimation = iterRotateYAnimation->second;
763             transformFloatAnimationAddMap_[rotateYAnimationIter].value(rotateYAnimation, weakRender, option);
764         }
765     }
766 }
767 
CreateColorAnimation(const RefPtr<PropertyAnimatable> & animatable,TweenOption & option)768 void TweenElement::CreateColorAnimation(const RefPtr<PropertyAnimatable>& animatable, TweenOption& option)
769 {
770     if (!animatable) {
771         LOGE("create color animation failed. not a animatable child.");
772         return;
773     }
774     auto& colorAnimation = option.GetColorAnimation();
775     if (!colorAnimation) {
776         LOGE("create color animation with null. skip it.");
777         return;
778     }
779     PropertyAnimatableType propertyType;
780     if (option.GetIsBackground()) {
781         propertyType = PropertyAnimatableType::PROPERTY_BACK_DECORATION_COLOR;
782     } else {
783         propertyType = PropertyAnimatableType::PROPERTY_FRONT_DECORATION_COLOR;
784     }
785     CreatePropertyAnimation<ColorPropertyAnimatable, Color>(animatable, propertyType, option, colorAnimation);
786 }
787 
788 template<class U, class V>
CreatePropertyAnimation(const RefPtr<PropertyAnimatable> & propertyAnimatable,PropertyAnimatableType propertyType,const TweenOption & option,RefPtr<Animation<V>> & animation)789 bool TweenElement::CreatePropertyAnimation(const RefPtr<PropertyAnimatable>& propertyAnimatable,
790     PropertyAnimatableType propertyType, const TweenOption& option, RefPtr<Animation<V>>& animation)
791 {
792     if (!animation) {
793         LOGE("CreatePropertyAnimation failed, animation is null.");
794         return false;
795     }
796     typename U::Type initValue;
797     bool created =
798         PropertyAnimatable::AddPropertyAnimation<U, V>(propertyAnimatable, propertyType, animation, initValue);
799     if (!created) {
800         LOGE("create property animation failed. property: %{public}d", propertyType);
801         return false;
802     }
803     if (option.GetCurve()) {
804         animation->SetCurve(option.GetCurve());
805     }
806     if (!animation->HasInitValue()) {
807         animation->SetInitValue(initValue);
808     }
809     return true;
810 }
811 
812 template<class U>
AddToAnimator(const std::map<PropertyAnimatableType,U> & animations,RefPtr<Animator> & controller,TweenOption & option)813 bool TweenElement::AddToAnimator(
814     const std::map<PropertyAnimatableType, U>& animations, RefPtr<Animator>& controller, TweenOption& option)
815 {
816     bool needAnimation = false;
817     for (auto&& [property, animation] : animations) {
818         if (animation) {
819             needAnimation = true;
820             LOGD("add property animation. property: %{public}d", property);
821             controller->AddInterpolator(animation);
822         }
823     }
824     return needAnimation;
825 }
826 
SetController(const RefPtr<Animator> & controller)827 void TweenElement::SetController(const RefPtr<Animator>& controller)
828 {
829     if (!controller) {
830         LOGE("set controller failed. controller is empty.");
831         return;
832     }
833     LOGD("set controller");
834     if (!controller_->IsStopped()) {
835         controller_->Stop();
836     }
837     isDelegatedController_ = true;
838     controller_ = controller;
839 }
840 
GetOption() const841 const TweenOption& TweenElement::GetOption() const
842 {
843     return option_;
844 }
845 
SetOption(const TweenOption & option)846 void TweenElement::SetOption(const TweenOption& option)
847 {
848     LOGD("set tween option");
849     option_ = option;
850 }
851 
GetController() const852 const RefPtr<Animator>& TweenElement::GetController() const
853 {
854     return controller_;
855 }
856 
SetOpacity(uint8_t opacity)857 void TweenElement::SetOpacity(uint8_t opacity)
858 {
859     if (children_.empty()) {
860         LOGE("no child when set Opacity");
861         return;
862     }
863     const auto& child = children_.front();
864     if (!child) {
865         LOGE("child is null.");
866         return;
867     }
868     auto childElement = AceType::DynamicCast<RenderElement>(child);
869     if (!childElement) {
870         LOGE("child element is null.");
871         return;
872     }
873     const auto& displayRenderNode = AceType::DynamicCast<RenderDisplay>(childElement->GetRenderNode());
874     if (!displayRenderNode) {
875         LOGE("no display render node found.");
876         return;
877     }
878     LOGD("set Opacity. Opacity: %{public}d", opacity);
879     displayRenderNode->UpdateOpacity(opacity);
880 }
881 
SkipPostFlush()882 void TweenElement::SkipPostFlush()
883 {
884     skipPostFlush_ = true;
885 }
886 
AddPreFlush()887 void TweenElement::AddPreFlush()
888 {
889     auto pipelineContext = context_.Upgrade();
890     if (!pipelineContext) {
891         return;
892     }
893     pipelineContext->AddPreFlushListener(AceType::Claim(this));
894 }
895 
SetWrapHidden(bool hidden)896 void TweenElement::SetWrapHidden(bool hidden)
897 {
898     if (children_.empty()) {
899         LOGE("no child when set visible");
900         return;
901     }
902     const auto& child = children_.front();
903     if (!child) {
904         LOGE("child is null.");
905         return;
906     }
907     auto childElement = AceType::DynamicCast<RenderElement>(child);
908     if (!childElement) {
909         LOGE("child element is null.");
910         return;
911     }
912     const auto& displayRenderNode = AceType::DynamicCast<RenderDisplay>(childElement->GetRenderNode());
913     if (!displayRenderNode) {
914         LOGE("no display render node found.");
915         return;
916     }
917     displayRenderNode->UpdateHidden(hidden);
918 }
919 
SetTouchable(bool enable)920 void TweenElement::SetTouchable(bool enable)
921 {
922     LOGD("set tween touchable status: %{public}d", enable);
923 
924     if (children_.empty()) {
925         LOGW("get content child failed. no child yet.");
926         return;
927     }
928     const auto& child = children_.front();
929     if (!child || child->GetType() != RENDER_ELEMENT) {
930         LOGW("get content child failed. null child or not render child.");
931         return;
932     }
933     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
934     if (!transformElement) {
935         LOGE("Get RenderElement failed.");
936         return;
937     }
938     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
939     if (transformRenderNode) {
940         transformRenderNode->SetTouchable(enable);
941     }
942 }
943 
GetContentRender() const944 RefPtr<RenderNode> TweenElement::GetContentRender() const
945 {
946     auto contentElement = GetContentElement();
947     if (!contentElement) {
948         return nullptr;
949     }
950     return contentElement->GetRenderNode();
951 }
952 
ApplyKeyframes()953 bool TweenElement::ApplyKeyframes()
954 {
955     return ApplyKeyframes(controller_, option_, prepareId_);
956 }
957 
AddPrepareListener(RefPtr<Animator> & controller,const WeakPtr<RenderTransform> & weakTransform,BaseId::IdType & prepareId)958 void TweenElement::AddPrepareListener(
959     RefPtr<Animator>& controller, const WeakPtr<RenderTransform>& weakTransform, BaseId::IdType& prepareId)
960 {
961     if (!controller) {
962         LOGE("Add Prepare Listener failed. controller is null.");
963         return;
964     }
965     controller->RemovePrepareListener(prepareId);
966     prepareId =
967         controller->AddPrepareListener([weakTransform, weakContext = context_,
968                                            weakTween = AceType::WeakClaim(this),
969                                            needForceResetTransform =
970                                               controller->GetAllowRunningAsynchronously()]() {
971             // reset transform matrix at the start of every frame.
972             auto context = weakContext.Upgrade();
973             auto tween = weakTween.Upgrade();
974             auto transform = weakTransform.Upgrade();
975             if (context && tween && transform) {
976                 auto currentTimestamp = context->GetTimeFromExternalTimer();
977                 if (tween->currentTimestamp_ != currentTimestamp || tween->currentTimestamp_ == 0 ||
978                     needForceResetTransform) {
979                     transform->ResetTransform();
980                     tween->currentTimestamp_ = currentTimestamp;
981                 }
982             }
983         });
984 }
985 
ApplyKeyframes(RefPtr<Animator> & controller,TweenOption & option,BaseId::IdType & prepareId)986 bool TweenElement::ApplyKeyframes(RefPtr<Animator>& controller, TweenOption& option, BaseId::IdType& prepareId)
987 {
988     if (!controller) {
989         LOGW("controller is null.");
990         return false;
991     }
992     if (children_.empty()) {
993         LOGW("apply option failed. no child yet.");
994         return false;
995     }
996     const auto& child = children_.front();
997     if (!child || child->GetType() != RENDER_ELEMENT) {
998         LOGW("apply option failed. null child or not render child.");
999         return false;
1000     }
1001     LOGD("TweenElement: ApplyKeyframes.");
1002 
1003     const auto& displayRenderNode =
1004         AceType::DynamicCast<RenderDisplay>(AceType::DynamicCast<RenderElement>(child)->GetRenderNode());
1005     if (!displayRenderNode) {
1006         LOGE("display render node is null.");
1007         return false;
1008     }
1009     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
1010     if (!transformElement) {
1011         LOGE("transform element node is null.");
1012         return false;
1013     }
1014     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
1015     if (!transformRenderNode) {
1016         LOGE("transform render node is null.");
1017         return false;
1018     }
1019     if (shadow_.IsValid()) {
1020         displayRenderNode->SetShadow(shadow_);
1021         transformRenderNode->SetShadow(shadow_);
1022     }
1023 
1024     const auto& contentElement = AceType::DynamicCast<RenderElement>(transformElement)->GetFirstChild();
1025     auto animatable = GetAnimatable(contentElement);
1026     if (animatable) {
1027         CreateColorAnimation(animatable, option);
1028         CreatePropertyAnimationFloat(animatable, option);
1029     }
1030     CreateTransformAnimation(transformRenderNode, transform_, option);
1031     CreateTranslateAnimation(transformRenderNode, option);
1032     CreateScaleAnimation(transformRenderNode, option);
1033     CreateRotateAnimation(transformRenderNode, option);
1034     CreateTransformOriginAnimation(transformRenderNode, option);
1035     if (option.HasTransformOffsetChanged() || option.HasTransformFloatChanged() || option.HasTransformChanged()) {
1036         AddPrepareListener(controller, transformRenderNode, prepareId);
1037     }
1038     CreateOpacityAnimation(displayRenderNode, display_, option);
1039     return IsNeedAnimation(controller, option);
1040 }
1041 
ApplyOptions(RefPtr<Animator> & controller,TweenOption & option)1042 void TweenElement::ApplyOptions(RefPtr<Animator>& controller, TweenOption& option)
1043 {
1044     if (!controller) {
1045         LOGE("Apply Options failed. Controller is null.");
1046         return;
1047     }
1048     LOGD("apply options.");
1049     controller->SetDuration(option.GetDuration());
1050     controller->SetIteration(option.GetIteration());
1051     controller->SetStartDelay(option.GetDelay());
1052     controller->SetFillMode(option.GetFillMode());
1053     controller->SetTempo(option.GetTempo());
1054     controller->SetAnimationDirection(option.GetAnimationDirection());
1055     controller->SetAllowRunningAsynchronously(option.GetAllowRunningAsynchronously());
1056 
1057     for (const auto& [type, animation] : option.GetAnimatables()) {
1058         if (option.GetCurve()) {
1059             animation->SetCurve(option.GetCurve());
1060         }
1061         controller->AddInterpolator(animation);
1062     }
1063 }
1064 
ApplyOptions()1065 void TweenElement::ApplyOptions()
1066 {
1067     ApplyOptions(controller_, option_);
1068 }
1069 
GetContentElement() const1070 RefPtr<Element> TweenElement::GetContentElement() const
1071 {
1072     const auto& mountParent = GetContentParent();
1073     if (!mountParent) {
1074         LOGE("Get content element failed. content parent is null.");
1075         return nullptr;
1076     }
1077     return mountParent->GetFirstChild();
1078 }
1079 
GetContentParent() const1080 RefPtr<Element> TweenElement::GetContentParent() const
1081 {
1082     const auto child = GetFirstChild();
1083     if (!child) {
1084         LOGW("Get transformElement failed. null child.");
1085         return nullptr;
1086     }
1087     const auto& displayRenderNode =
1088         AceType::DynamicCast<RenderDisplay>(AceType::DynamicCast<RenderElement>(child)->GetRenderNode());
1089     if (!displayRenderNode) {
1090         LOGE("display render node is null.");
1091         return nullptr;
1092     }
1093     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
1094     if (!transformElement) {
1095         LOGE("Get transformElement failed. transform element is null");
1096         return nullptr;
1097     }
1098     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
1099     if (!transformRenderNode) {
1100         LOGE("Get transformElement failed. transform render node is null.");
1101         return nullptr;
1102     }
1103     return transformElement;
1104 }
1105 
CreatePropertyAnimationFloat(const RefPtr<PropertyAnimatable> & animatable,TweenOption & option)1106 void TweenElement::CreatePropertyAnimationFloat(const RefPtr<PropertyAnimatable>& animatable, TweenOption& option)
1107 {
1108     if (!animatable) {
1109         LOGE("Create property animation for float failed. animatable is null.");
1110         return;
1111     }
1112     auto& propertyFloatMap = option.GetFloatPropertyAnimation();
1113     if (propertyFloatMap.empty()) {
1114         LOGD("No property animation float found. skip it.");
1115         return;
1116     }
1117     for (auto&& [property, animation] : propertyFloatMap) {
1118         LOGD("Create animation float for property: %{public}d", property);
1119         CreatePropertyAnimation<FloatPropertyAnimatable, float>(animatable, property, option, animation);
1120     }
1121 }
1122 
1123 } // namespace OHOS::Ace
1124