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