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