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