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