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