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         return;
213     }
214     if (!opacityAnimation->HasInitValue()) {
215         opacityAnimation->SetInitValue(UINT8_MAX);
216     }
217     WeakPtr<RenderDisplay> weakRender = renderDisplayNode;
218     opacityAnimation->AddListener(std::bind(OpacityAnimationListener, weakRender, display, std::placeholders::_1));
219 
220     if (option.GetCurve()) {
221         opacityAnimation->SetCurve(option.GetCurve());
222     }
223 }
224 
BindingTransformAnimationToController(RefPtr<Animator> & controller,TweenOption & option)225 bool BindingTransformAnimationToController(RefPtr<Animator>& controller, TweenOption& option)
226 {
227     bool needAnimation = false;
228     const auto& animations = option.GetTransformAnimations();
229     for (auto& animation : animations) {
230         if (animation) {
231             needAnimation = true;
232             controller->AddInterpolator(animation);
233         }
234     }
235     return needAnimation;
236 }
237 
238 } // namespace
239 
240 const LinearEnumMapNode<AnimationType,
241     void (*)(const RefPtr<Animation<float>>&, WeakPtr<RenderTransform>&, TweenOption&)>
242     TweenElement::transformFloatAnimationAddMap_[] = {
243         { AnimationType::SCALE,
244             [](const RefPtr<Animation<float>>& scaleAnimation, WeakPtr<RenderTransform>& weakRender,
__anonf1ba2b2b0202() 245                 TweenOption& option) {
246                 SetScaleProperties(scaleAnimation, option);
247                 scaleAnimation->AddListener([weakRender, scaleAnimation](float value) {
248                     auto renderTransformNode = weakRender.Upgrade();
249                     if (renderTransformNode) {
250                         renderTransformNode->Scale(value);
251                     }
252                 });
253             } },
254         { AnimationType::SCALE_X,
255             [](const RefPtr<Animation<float>>& scaleXAnimation, WeakPtr<RenderTransform>& weakRender,
__anonf1ba2b2b0402() 256                 TweenOption& option) {
257                 SetScaleProperties(scaleXAnimation, option);
258                 double maxScaleXY = option.GetMaxScaleXY();
259                 auto renderTransformNode = weakRender.Upgrade();
260                 if (renderTransformNode) {
261                     renderTransformNode->SetMaxScaleXY(maxScaleXY);
262                 }
263                 scaleXAnimation->AddListener([weakRender, scaleXAnimation](float value) {
264                     auto renderTransformNode = weakRender.Upgrade();
265                     if (renderTransformNode) {
266                         renderTransformNode->Scale(value, 1.0f);
267                     }
268                 });
269             } },
270         { AnimationType::SCALE_Y,
271             [](const RefPtr<Animation<float>>& scaleYAnimation, WeakPtr<RenderTransform>& weakRender,
__anonf1ba2b2b0602() 272                 TweenOption& option) {
273                 SetScaleProperties(scaleYAnimation, option);
274                 scaleYAnimation->AddListener([weakRender, scaleYAnimation](float value) {
275                     auto renderTransformNode = weakRender.Upgrade();
276                     if (renderTransformNode) {
277                         renderTransformNode->Scale(1.0f, value);
278                     }
279                 });
280             } },
281         { AnimationType::ROTATE_Z,
282             [](const RefPtr<Animation<float>>& rotateZAnimation, WeakPtr<RenderTransform>& weakRender,
__anonf1ba2b2b0802() 283                 TweenOption& option) {
284                 SetRotateProperties(rotateZAnimation, option);
285                 rotateZAnimation->AddListener([weakRender, rotateZAnimation](float value) {
286                     auto renderTransformNode = weakRender.Upgrade();
287                     if (renderTransformNode) {
288                         renderTransformNode->RotateZ(value);
289                     }
290                 });
291             } },
292         { AnimationType::ROTATE_X,
293             [](const RefPtr<Animation<float>>& rotateXAnimation, WeakPtr<RenderTransform>& weakRender,
__anonf1ba2b2b0a02() 294                 TweenOption& option) {
295                 SetRotateProperties(rotateXAnimation, option);
296                 rotateXAnimation->AddListener([weakRender, rotateXAnimation](float value) {
297                     auto renderTransformNode = weakRender.Upgrade();
298                     if (renderTransformNode) {
299                         renderTransformNode->RotateX(value);
300                     }
301                 });
302             } },
303         { AnimationType::ROTATE_Y,
304             [](const RefPtr<Animation<float>>& rotateYAnimation, WeakPtr<RenderTransform>& weakRender,
__anonf1ba2b2b0c02() 305                 TweenOption& option) {
306                 SetRotateProperties(rotateYAnimation, option);
307                 rotateYAnimation->AddListener([weakRender, rotateYAnimation](float value) {
308                     auto renderTransformNode = weakRender.Upgrade();
309                     if (renderTransformNode) {
310                         renderTransformNode->RotateY(value);
311                     }
312                 });
313             } }
314     };
315 
Update()316 void TweenElement::Update()
317 {
318     ComposedElement::Update();
319     if (!component_) {
320         return;
321     }
322     auto tweenComponent = AceType::DynamicCast<TweenComponent>(component_);
323     if (!tweenComponent) {
324         LOGE("Get TweenComponent failed.");
325         return;
326     }
327     shadow_ = tweenComponent->GetShadow();
328     positionParam_ = tweenComponent->GetPositionParam();
329 
330     if (tweenComponent->IsAnimationNameUpdated()) {
331         needUpdateKeyframes_ = true;
332         tweenComponent->DisableAnimationNameUpdated();
333     }
334     if (tweenComponent->IsOptionCssChanged()) {
335         needUpdateTweenOption_ = true;
336         option_ = tweenComponent->GetTweenOption();
337         tweenComponent->SetOptionCssChanged(false);
338     }
339     if (tweenComponent->IsOptionCustomChanged()) {
340         needUpdateTweenOptionCustom_ = true;
341         optionCustom_ = tweenComponent->GetCustomTweenOption();
342         tweenComponent->SetOptionCustomChanged(false);
343     }
344     if (tweenComponent->IsOperationCssChanged()) {
345         operation_ = tweenComponent->GetAnimationOperation();
346         tweenComponent->SetOperationCssChanged(false);
347     }
348     if (tweenComponent->IsOperationCustomChanged()) {
349         operationCustom_ = tweenComponent->GetCustomAnimationOperation();
350         tweenComponent->SetOperationCustomChanged(false);
351     }
352     auto pipelineContext = context_.Upgrade();
353     if (pipelineContext) {
354         RefPtr<Animator> controller = tweenComponent->GetAnimator();
355         if (controller) {
356             isComponentController_ = true;
357             if (!controller->HasScheduler()) {
358                 controller->AttachScheduler(context_);
359             }
360             controllerCustom_ = controller;
361             tweenComponent->SetAnimator(controllerCustom_);
362         }
363         if (!controller_) {
364             isDelegatedController_ = false;
365             controller_ = CREATE_ANIMATOR(context_);
366             tweenComponent->SetAnimator(controller_);
367         }
368 
369         // If transform component exists, it also plays animation. RenderTransform can get correct value from component
370         // when Update(component).
371         if ((operation_ != AnimationOperation::NONE || operationCustom_ != AnimationOperation::NONE) &&
372             !transform_.Upgrade()) {
373             pipelineContext->AddPostAnimationFlushListener(AceType::Claim(this));
374         }
375         pipelineContext->AddPostFlushListener(AceType::Claim(this));
376     }
377 }
378 
~TweenElement()379 TweenElement::~TweenElement()
380 {
381     if (isComponentController_ && controllerCustom_) {
382         controllerCustom_->Stop();
383         controllerCustom_->ClearInterpolators();
384         controllerCustom_->ClearAllListeners();
385     }
386 }
387 
ApplyOperation(RefPtr<Animator> & controller,AnimationOperation & operation)388 void TweenElement::ApplyOperation(RefPtr<Animator>& controller, AnimationOperation& operation)
389 {
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         return;
438     }
439     SetWrapHidden(false);
440     if (isDelegatedController_ && !isComponentController_) {
441         return;
442     }
443 
444     if (needUpdateKeyframes_ || (operation_ == AnimationOperation::PLAY && needUpdateTweenOption_)) {
445         ResetController(controller_);
446         ApplyKeyframes();
447         needUpdateKeyframes_ = false;
448     }
449 
450     if (needUpdateTweenOption_) {
451         ApplyOptions(controller_, option_);
452         needUpdateTweenOption_ = false;
453     }
454     if (needUpdateTweenOptionCustom_) {
455         ResetController(controllerCustom_);
456         ApplyKeyframes(controllerCustom_, optionCustom_, prepareIdCustom_);
457         ApplyOptions(controllerCustom_, optionCustom_);
458         needUpdateTweenOptionCustom_ = false;
459     }
460     if (operation_ != AnimationOperation::NONE || operationCustom_ != AnimationOperation::NONE) {
461         auto pipelineContext = context_.Upgrade();
462         if (!pipelineContext) {
463             return;
464         }
465     }
466 
467     if (controller_) {
468         ApplyOperation(controller_, operation_);
469     }
470     if (controllerCustom_) {
471         ApplyOperation(controllerCustom_, operationCustom_);
472     }
473 
474     // reset operation to none.
475     operation_ = AnimationOperation::NONE;
476     operationCustom_ = AnimationOperation::NONE;
477 }
478 
IsNeedAnimation(RefPtr<Animator> & controller,TweenOption & option)479 bool TweenElement::IsNeedAnimation(RefPtr<Animator>& controller, TweenOption& option)
480 {
481     if (!controller) {
482         LOGE("add interpolator failed. controller is null.");
483         return false;
484     }
485     bool needAnimation = false;
486     auto& transformOffsetAnimations = option.GetTranslateAnimations();
487     for (auto&& [translate, animation] : transformOffsetAnimations) {
488         if (animation) {
489             needAnimation = true;
490             controller->AddInterpolator(animation);
491         }
492     }
493     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
494     for (auto&& [transformFloat, animation] : transformFloatAnimations) {
495         if (animation) {
496             needAnimation = true;
497             controller->AddInterpolator(animation);
498         }
499     }
500     if (BindingTransformAnimationToController(controller, option)) {
501         needAnimation = true;
502     }
503     auto& transformOriginAnimation = option.GetTransformOriginAnimation();
504     if (transformOriginAnimation) {
505         controller->AddInterpolator(transformOriginAnimation);
506         // no need enable needAnimation, Transform Origin Animation only work when set transform animation.
507     }
508     auto& opacityAnimation = option.GetOpacityAnimation();
509     if (opacityAnimation) {
510         controller->AddInterpolator(opacityAnimation);
511         needAnimation = true;
512     }
513     auto& colorAnimation = option.GetColorAnimation();
514     if (colorAnimation) {
515         controller->AddInterpolator(colorAnimation);
516         needAnimation = true;
517     }
518     if (AddToAnimator(option.GetFloatPropertyAnimation(), controller, option)) {
519         needAnimation = true;
520     }
521     return needAnimation;
522 }
523 
BuildChild()524 RefPtr<Component> TweenElement::BuildChild()
525 {
526     RefPtr<TweenComponent> tween = AceType::DynamicCast<TweenComponent>(component_);
527     if (tween) {
528         RefPtr<DisplayComponent> displayComponent = AceType::DynamicCast<DisplayComponent>(tween->GetChild());
529         RefPtr<TransformComponent> transformComponent;
530         if (displayComponent) {
531             transformComponent = AceType::DynamicCast<TransformComponent>(displayComponent->GetChild());
532             if (!transformComponent) {
533                 transformComponent = AceType::MakeRefPtr<TransformComponent>();
534                 transformComponent->SetChild(displayComponent->GetChild());
535                 displayComponent->SetChild(transformComponent);
536             }
537         } else {
538             transformComponent = AceType::MakeRefPtr<TransformComponent>();
539             displayComponent = AceType::MakeRefPtr<DisplayComponent>(transformComponent);
540             transformComponent->SetChild(ComposedElement::BuildChild());
541         }
542         displayComponent->SetPositionType(positionParam_.type);
543         displayComponent->SetHasLeft(positionParam_.left.second);
544         displayComponent->SetHasRight(positionParam_.right.second);
545         displayComponent->SetHasTop(positionParam_.top.second);
546         displayComponent->SetHasBottom(positionParam_.bottom.second);
547         displayComponent->SetLeft(positionParam_.left.first);
548         displayComponent->SetRight(positionParam_.right.first);
549         displayComponent->SetTop(positionParam_.top.first);
550         displayComponent->SetBottom(positionParam_.bottom.first);
551         displayComponent->DisableLayer(tween->IsLeafNode());
552         transform_ = transformComponent;
553         display_ = displayComponent;
554         return displayComponent;
555     } else {
556         LOGE("no tween component found. return empty child.");
557         return nullptr;
558     }
559 }
560 
PerformBuild()561 void TweenElement::PerformBuild()
562 {
563     ComposedElement::PerformBuild();
564     auto tweenComponent = AceType::DynamicCast<TweenComponent>(component_);
565     if (!tweenComponent) {
566         LOGE("Get TweenComponent failed.");
567         return;
568     }
569     if (!tweenComponent->GetIsFirstFrameShow()) {
570         SetWrapHidden(true);
571     }
572 }
573 
CanUpdate(const RefPtr<Component> & newComponent)574 bool TweenElement::CanUpdate(const RefPtr<Component>& newComponent)
575 {
576     auto pipelineContext = context_.Upgrade();
577     if (pipelineContext && pipelineContext->GetIsDeclarative()) {
578         return ComposedElement::CanUpdate(newComponent);
579     }
580     // components of the same type are not updated.
581     return Element::CanUpdate(newComponent);
582 }
583 
CreateTranslateAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)584 void TweenElement::CreateTranslateAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
585 {
586     if (!option.HasTransformOffsetChanged()) {
587         return;
588     }
589     auto& transformOffsetAnimations = option.GetTranslateAnimations();
590     WeakPtr<RenderTransform> weakRender = renderTransformNode;
591     static const LinearEnumMapNode<AnimationType,
592         void (*)(const RefPtr<Animation<DimensionOffset>>&, WeakPtr<RenderTransform>&, TweenOption&)>
593         translateAnimationAddMap[] = {
594             { AnimationType::TRANSLATE,
595                 [](const RefPtr<Animation<DimensionOffset>>& translateAnimation,
596                     WeakPtr<RenderTransform>& weakRender, TweenOption& option) {
597                     SetTranslateProperties(translateAnimation, option);
598                     translateAnimation->AddListener([weakRender](const DimensionOffset& value) {
599                         auto renderTransformNode = weakRender.Upgrade();
600                         if (renderTransformNode) {
601                             renderTransformNode->Translate(value.GetX(), value.GetY());
602                         }
603                     });
604                 } },
605             { AnimationType::TRANSLATE_X,
606                 [](const RefPtr<Animation<DimensionOffset>>& translateXAnimation, WeakPtr<RenderTransform>& weakRender,
607                     TweenOption& option) {
608                     SetTranslateProperties(translateXAnimation, option);
609                     translateXAnimation->AddListener([weakRender](const DimensionOffset& value) {
610                         auto renderTransformNode = weakRender.Upgrade();
611                         if (renderTransformNode) {
612                             renderTransformNode->Translate(value.GetX(), 0.0_px);
613                         }
614                     });
615                 } },
616             { AnimationType::TRANSLATE_Y,
617                 [](const RefPtr<Animation<DimensionOffset>>& translateYAnimation, WeakPtr<RenderTransform>& weakRender,
618                     TweenOption& option) {
619                     SetTranslateProperties(translateYAnimation, option);
620                     translateYAnimation->AddListener([weakRender](const DimensionOffset& value) {
621                         auto renderTransformNode = weakRender.Upgrade();
622                         if (renderTransformNode) {
623                             renderTransformNode->Translate(0.0_px, value.GetY());
624                         }
625                     });
626                 } }
627             };
628     size_t mapSize = ArraySize(translateAnimationAddMap);
629     auto iterTranslateAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE);
630     if (iterTranslateAnimation != transformOffsetAnimations.end()) {
631         auto translateAnimationIter =
632             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE);
633         if (translateAnimationIter != -1) {
634             auto& translateAnimation = iterTranslateAnimation->second;
635             translateAnimationAddMap[translateAnimationIter].value(translateAnimation, weakRender, option);
636         }
637     }
638 
639     auto iterTranslateXAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE_X);
640     if (iterTranslateXAnimation != transformOffsetAnimations.end()) {
641         auto translateXAnimationIter =
642             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE_X);
643         if (translateXAnimationIter != -1) {
644             auto& translateXAnimation = iterTranslateXAnimation->second;
645             translateAnimationAddMap[translateXAnimationIter].value(translateXAnimation, weakRender, option);
646         }
647     }
648 
649     auto iterTranslateYAnimation = transformOffsetAnimations.find(AnimationType::TRANSLATE_Y);
650     if (iterTranslateYAnimation != transformOffsetAnimations.end()) {
651         auto translateYAnimationIter =
652             BinarySearchFindIndex(translateAnimationAddMap, mapSize, AnimationType::TRANSLATE_Y);
653         if (translateYAnimationIter != -1) {
654             auto& translateYAnimation = iterTranslateYAnimation->second;
655             translateAnimationAddMap[translateYAnimationIter].value(translateYAnimation, weakRender, option);
656         }
657     }
658 }
659 
CreateScaleAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)660 void TweenElement::CreateScaleAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
661 {
662     if (!option.HasTransformFloatChanged()) {
663         return;
664     }
665     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
666     WeakPtr<RenderTransform> weakRender = renderTransformNode;
667     auto iterScaleAnimation = transformFloatAnimations.find(AnimationType::SCALE);
668     size_t mapSize = ArraySize(transformFloatAnimationAddMap_);
669     if (iterScaleAnimation != transformFloatAnimations.end()) {
670         auto scaleAnimationIter = BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE);
671         if (scaleAnimationIter != -1) {
672             auto& scaleAnimation = iterScaleAnimation->second;
673             transformFloatAnimationAddMap_[scaleAnimationIter].value(scaleAnimation, weakRender, option);
674         }
675     }
676 
677     auto iterScaleXAnimation = transformFloatAnimations.find(AnimationType::SCALE_X);
678     if (iterScaleXAnimation != transformFloatAnimations.end()) {
679         auto scaleXAnimationIter =
680             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE_X);
681         if (scaleXAnimationIter != -1) {
682             auto& scaleXAnimation = iterScaleXAnimation->second;
683             transformFloatAnimationAddMap_[scaleXAnimationIter].value(scaleXAnimation, weakRender, option);
684         }
685     }
686 
687     auto iterScaleYAnimation = transformFloatAnimations.find(AnimationType::SCALE_Y);
688     if (iterScaleYAnimation != transformFloatAnimations.end()) {
689         auto scaleYAnimationIter =
690             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::SCALE_Y);
691         if (scaleYAnimationIter != -1) {
692             auto& scaleYAnimation = iterScaleYAnimation->second;
693             transformFloatAnimationAddMap_[scaleYAnimationIter].value(scaleYAnimation, weakRender, option);
694         }
695     }
696 }
697 
CreateTransformOriginAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)698 void TweenElement::CreateTransformOriginAnimation(
699     const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
700 {
701     if (option.HasTransformOriginChanged()) {
702         renderTransformNode->SetTransformOrigin(option.GetTransformOriginX(), option.GetTransformOriginY());
703         auto animation = option.GetTransformOriginAnimation();
704         if (animation) {
705             animation->AddListener([weak = AceType::WeakClaim(AceType::RawPtr(renderTransformNode))](
706                                        const DimensionOffset& value) { RenderTransformOriginUpdate(weak, value); });
707 
708             if (option.GetCurve()) {
709                 animation->SetCurve(option.GetCurve());
710             }
711         }
712         option.SetTransformOriginChanged(false);
713     } else {
714         renderTransformNode->SetTransformOrigin(HALF_PERCENT, HALF_PERCENT);
715         renderTransformNode->MarkNeedUpdateOrigin();
716     }
717 }
718 
CreateRotateAnimation(const RefPtr<RenderTransform> & renderTransformNode,TweenOption & option)719 void TweenElement::CreateRotateAnimation(const RefPtr<RenderTransform>& renderTransformNode, TweenOption& option)
720 {
721     if (!option.HasTransformFloatChanged()) {
722         return;
723     }
724     auto& transformFloatAnimations = option.GetTransformFloatAnimation();
725     WeakPtr<RenderTransform> weakRender = renderTransformNode;
726     auto iterRotateZAnimation = transformFloatAnimations.find(AnimationType::ROTATE_Z);
727     size_t mapSize = ArraySize(transformFloatAnimationAddMap_);
728     if (iterRotateZAnimation != transformFloatAnimations.end()) {
729         auto rotateZAnimationIter =
730             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_Z);
731         if (rotateZAnimationIter != -1) {
732             auto& rotateZAnimation = iterRotateZAnimation->second;
733             transformFloatAnimationAddMap_[rotateZAnimationIter].value(rotateZAnimation, weakRender, option);
734         }
735     }
736 
737     auto iterRotateXAnimation = transformFloatAnimations.find(AnimationType::ROTATE_X);
738     if (iterRotateXAnimation != transformFloatAnimations.end()) {
739         auto rotateXAnimationIter =
740             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_X);
741         if (rotateXAnimationIter != -1) {
742             auto& rotateXAnimation = iterRotateXAnimation->second;
743             transformFloatAnimationAddMap_[rotateXAnimationIter].value(rotateXAnimation, weakRender, option);
744         }
745     }
746 
747     auto iterRotateYAnimation = transformFloatAnimations.find(AnimationType::ROTATE_Y);
748     if (iterRotateYAnimation != transformFloatAnimations.end()) {
749         auto rotateYAnimationIter =
750             BinarySearchFindIndex(transformFloatAnimationAddMap_, mapSize, AnimationType::ROTATE_Y);
751         if (rotateYAnimationIter != -1) {
752             auto& rotateYAnimation = iterRotateYAnimation->second;
753             transformFloatAnimationAddMap_[rotateYAnimationIter].value(rotateYAnimation, weakRender, option);
754         }
755     }
756 }
757 
CreateColorAnimation(const RefPtr<PropertyAnimatable> & animatable,TweenOption & option)758 void TweenElement::CreateColorAnimation(const RefPtr<PropertyAnimatable>& animatable, TweenOption& option)
759 {
760     if (!animatable) {
761         LOGE("create color animation failed. not a animatable child.");
762         return;
763     }
764     auto& colorAnimation = option.GetColorAnimation();
765     if (!colorAnimation) {
766         return;
767     }
768     PropertyAnimatableType propertyType;
769     if (option.GetIsBackground()) {
770         propertyType = PropertyAnimatableType::PROPERTY_BACK_DECORATION_COLOR;
771     } else {
772         propertyType = PropertyAnimatableType::PROPERTY_FRONT_DECORATION_COLOR;
773     }
774     CreatePropertyAnimation<ColorPropertyAnimatable, Color>(animatable, propertyType, option, colorAnimation);
775 }
776 
777 template<class U, class V>
CreatePropertyAnimation(const RefPtr<PropertyAnimatable> & propertyAnimatable,PropertyAnimatableType propertyType,const TweenOption & option,RefPtr<Animation<V>> & animation)778 bool TweenElement::CreatePropertyAnimation(const RefPtr<PropertyAnimatable>& propertyAnimatable,
779     PropertyAnimatableType propertyType, const TweenOption& option, RefPtr<Animation<V>>& animation)
780 {
781     if (!animation) {
782         LOGE("CreatePropertyAnimation failed, animation is null.");
783         return false;
784     }
785     typename U::Type initValue;
786     bool created =
787         PropertyAnimatable::AddPropertyAnimation<U, V>(propertyAnimatable, propertyType, animation, initValue);
788     if (!created) {
789         LOGE("create property animation failed. property: %{public}d", propertyType);
790         return false;
791     }
792     if (option.GetCurve()) {
793         animation->SetCurve(option.GetCurve());
794     }
795     if (!animation->HasInitValue()) {
796         animation->SetInitValue(initValue);
797     }
798     return true;
799 }
800 
801 template<class U>
AddToAnimator(const std::map<PropertyAnimatableType,U> & animations,RefPtr<Animator> & controller,TweenOption & option)802 bool TweenElement::AddToAnimator(
803     const std::map<PropertyAnimatableType, U>& animations, RefPtr<Animator>& controller, TweenOption& option)
804 {
805     bool needAnimation = false;
806     for (auto&& [property, animation] : animations) {
807         if (animation) {
808             needAnimation = true;
809             controller->AddInterpolator(animation);
810         }
811     }
812     return needAnimation;
813 }
814 
SetController(const RefPtr<Animator> & controller)815 void TweenElement::SetController(const RefPtr<Animator>& controller)
816 {
817     if (!controller) {
818         LOGE("set controller failed. controller is empty.");
819         return;
820     }
821     if (!controller_->IsStopped()) {
822         controller_->Stop();
823     }
824     isDelegatedController_ = true;
825     controller_ = controller;
826 }
827 
GetOption() const828 const TweenOption& TweenElement::GetOption() const
829 {
830     return option_;
831 }
832 
SetOption(const TweenOption & option)833 void TweenElement::SetOption(const TweenOption& option)
834 {
835     option_ = option;
836 }
837 
GetController() const838 const RefPtr<Animator>& TweenElement::GetController() const
839 {
840     return controller_;
841 }
842 
SetOpacity(uint8_t opacity)843 void TweenElement::SetOpacity(uint8_t opacity)
844 {
845     if (children_.empty()) {
846         LOGE("no child when set Opacity");
847         return;
848     }
849     const auto& child = children_.front();
850     if (!child) {
851         LOGE("child is null.");
852         return;
853     }
854     auto childElement = AceType::DynamicCast<RenderElement>(child);
855     if (!childElement) {
856         LOGE("child element is null.");
857         return;
858     }
859     const auto& displayRenderNode = AceType::DynamicCast<RenderDisplay>(childElement->GetRenderNode());
860     if (!displayRenderNode) {
861         LOGE("no display render node found.");
862         return;
863     }
864     displayRenderNode->UpdateOpacity(opacity);
865 }
866 
SkipPostFlush()867 void TweenElement::SkipPostFlush()
868 {
869     skipPostFlush_ = true;
870 }
871 
AddPreFlush()872 void TweenElement::AddPreFlush()
873 {
874     auto pipelineContext = context_.Upgrade();
875     if (!pipelineContext) {
876         return;
877     }
878     pipelineContext->AddPreFlushListener(AceType::Claim(this));
879 }
880 
SetWrapHidden(bool hidden)881 void TweenElement::SetWrapHidden(bool hidden)
882 {
883     if (children_.empty()) {
884         LOGE("no child when set visible");
885         return;
886     }
887     const auto& child = children_.front();
888     if (!child) {
889         LOGE("child is null.");
890         return;
891     }
892     auto childElement = AceType::DynamicCast<RenderElement>(child);
893     if (!childElement) {
894         LOGE("child element is null.");
895         return;
896     }
897     const auto& displayRenderNode = AceType::DynamicCast<RenderDisplay>(childElement->GetRenderNode());
898     if (!displayRenderNode) {
899         LOGE("no display render node found.");
900         return;
901     }
902     displayRenderNode->UpdateHidden(hidden);
903 }
904 
SetTouchable(bool enable)905 void TweenElement::SetTouchable(bool enable)
906 {
907     if (children_.empty()) {
908         LOGW("get content child failed. no child yet.");
909         return;
910     }
911     const auto& child = children_.front();
912     if (!child || child->GetType() != RENDER_ELEMENT) {
913         LOGW("get content child failed. null child or not render child.");
914         return;
915     }
916     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
917     if (!transformElement) {
918         LOGE("Get RenderElement failed.");
919         return;
920     }
921     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
922     if (transformRenderNode) {
923         transformRenderNode->SetTouchable(enable);
924     }
925 }
926 
GetContentRender() const927 RefPtr<RenderNode> TweenElement::GetContentRender() const
928 {
929     auto contentElement = GetContentElement();
930     if (!contentElement) {
931         return nullptr;
932     }
933     return contentElement->GetRenderNode();
934 }
935 
ApplyKeyframes()936 bool TweenElement::ApplyKeyframes()
937 {
938     return ApplyKeyframes(controller_, option_, prepareId_);
939 }
940 
AddPrepareListener(RefPtr<Animator> & controller,const WeakPtr<RenderTransform> & weakTransform,BaseId::IdType & prepareId)941 void TweenElement::AddPrepareListener(
942     RefPtr<Animator>& controller, const WeakPtr<RenderTransform>& weakTransform, BaseId::IdType& prepareId)
943 {
944     if (!controller) {
945         LOGE("Add Prepare Listener failed. controller is null.");
946         return;
947     }
948     controller->RemovePrepareListener(prepareId);
949     prepareId =
950         controller->AddPrepareListener([weakTransform, weakContext = context_,
951                                            weakTween = AceType::WeakClaim(this),
952                                            needForceResetTransform =
953                                               controller->GetAllowRunningAsynchronously()]() {
954             // reset transform matrix at the start of every frame.
955             auto context = weakContext.Upgrade();
956             auto tween = weakTween.Upgrade();
957             auto transform = weakTransform.Upgrade();
958             if (context && tween && transform) {
959                 auto currentTimestamp = context->GetTimeFromExternalTimer();
960                 if (tween->currentTimestamp_ != currentTimestamp || tween->currentTimestamp_ == 0 ||
961                     needForceResetTransform) {
962                     transform->ResetTransform();
963                     tween->currentTimestamp_ = currentTimestamp;
964                 }
965             }
966         });
967 }
968 
ApplyKeyframes(RefPtr<Animator> & controller,TweenOption & option,BaseId::IdType & prepareId)969 bool TweenElement::ApplyKeyframes(RefPtr<Animator>& controller, TweenOption& option, BaseId::IdType& prepareId)
970 {
971     if (!controller) {
972         LOGW("controller is null.");
973         return false;
974     }
975     if (children_.empty()) {
976         LOGW("apply option failed. no child yet.");
977         return false;
978     }
979     const auto& child = children_.front();
980     if (!child || child->GetType() != RENDER_ELEMENT) {
981         LOGW("apply option failed. null child or not render child.");
982         return false;
983     }
984     const auto& displayRenderNode =
985         AceType::DynamicCast<RenderDisplay>(AceType::DynamicCast<RenderElement>(child)->GetRenderNode());
986     if (!displayRenderNode) {
987         LOGE("display render node is null.");
988         return false;
989     }
990     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
991     if (!transformElement) {
992         LOGE("transform element node is null.");
993         return false;
994     }
995     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
996     if (!transformRenderNode) {
997         LOGE("transform render node is null.");
998         return false;
999     }
1000     if (shadow_.IsValid()) {
1001         displayRenderNode->SetShadow(shadow_);
1002         transformRenderNode->SetShadow(shadow_);
1003     }
1004 
1005     const auto& contentElement = AceType::DynamicCast<RenderElement>(transformElement)->GetFirstChild();
1006     auto animatable = GetAnimatable(contentElement);
1007     if (animatable) {
1008         CreateColorAnimation(animatable, option);
1009         CreatePropertyAnimationFloat(animatable, option);
1010     }
1011     CreateTransformAnimation(transformRenderNode, transform_, option);
1012     CreateTranslateAnimation(transformRenderNode, option);
1013     CreateScaleAnimation(transformRenderNode, option);
1014     CreateRotateAnimation(transformRenderNode, option);
1015     CreateTransformOriginAnimation(transformRenderNode, option);
1016     if (option.HasTransformOffsetChanged() || option.HasTransformFloatChanged() || option.HasTransformChanged()) {
1017         AddPrepareListener(controller, transformRenderNode, prepareId);
1018     }
1019     CreateOpacityAnimation(displayRenderNode, display_, option);
1020     return IsNeedAnimation(controller, option);
1021 }
1022 
ApplyOptions(RefPtr<Animator> & controller,TweenOption & option)1023 void TweenElement::ApplyOptions(RefPtr<Animator>& controller, TweenOption& option)
1024 {
1025     if (!controller) {
1026         LOGE("Apply Options failed. Controller is null.");
1027         return;
1028     }
1029     controller->SetDuration(option.GetDuration());
1030     controller->SetIteration(option.GetIteration());
1031     controller->SetStartDelay(option.GetDelay());
1032     controller->SetFillMode(option.GetFillMode());
1033     controller->SetTempo(option.GetTempo());
1034     controller->SetAnimationDirection(option.GetAnimationDirection());
1035     controller->SetAllowRunningAsynchronously(option.GetAllowRunningAsynchronously());
1036 
1037     for (const auto& [type, animation] : option.GetAnimatables()) {
1038         if (option.GetCurve()) {
1039             animation->SetCurve(option.GetCurve());
1040         }
1041         controller->AddInterpolator(animation);
1042     }
1043 }
1044 
ApplyOptions()1045 void TweenElement::ApplyOptions()
1046 {
1047     ApplyOptions(controller_, option_);
1048 }
1049 
GetContentElement() const1050 RefPtr<Element> TweenElement::GetContentElement() const
1051 {
1052     const auto& mountParent = GetContentParent();
1053     if (!mountParent) {
1054         LOGE("Get content element failed. content parent is null.");
1055         return nullptr;
1056     }
1057     return mountParent->GetFirstChild();
1058 }
1059 
GetContentParent() const1060 RefPtr<Element> TweenElement::GetContentParent() const
1061 {
1062     const auto child = GetFirstChild();
1063     if (!child) {
1064         LOGW("Get transformElement failed. null child.");
1065         return nullptr;
1066     }
1067     const auto& displayRenderNode =
1068         AceType::DynamicCast<RenderDisplay>(AceType::DynamicCast<RenderElement>(child)->GetRenderNode());
1069     if (!displayRenderNode) {
1070         LOGE("display render node is null.");
1071         return nullptr;
1072     }
1073     const auto& transformElement = AceType::DynamicCast<RenderElement>(child)->GetFirstChild();
1074     if (!transformElement) {
1075         LOGE("Get transformElement failed. transform element is null");
1076         return nullptr;
1077     }
1078     const auto& transformRenderNode = AceType::DynamicCast<RenderTransform>(transformElement->GetRenderNode());
1079     if (!transformRenderNode) {
1080         LOGE("Get transformElement failed. transform render node is null.");
1081         return nullptr;
1082     }
1083     return transformElement;
1084 }
1085 
CreatePropertyAnimationFloat(const RefPtr<PropertyAnimatable> & animatable,TweenOption & option)1086 void TweenElement::CreatePropertyAnimationFloat(const RefPtr<PropertyAnimatable>& animatable, TweenOption& option)
1087 {
1088     if (!animatable) {
1089         LOGE("Create property animation for float failed. animatable is null.");
1090         return;
1091     }
1092     auto& propertyFloatMap = option.GetFloatPropertyAnimation();
1093     if (propertyFloatMap.empty()) {
1094         return;
1095     }
1096     for (auto&& [property, animation] : propertyFloatMap) {
1097         CreatePropertyAnimation<FloatPropertyAnimatable, float>(animatable, property, option, animation);
1098     }
1099 }
1100 
1101 } // namespace OHOS::Ace
1102