• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "animation/rs_implicit_animator.h"
17 
18 #include "animation/rs_animation.h"
19 #include "animation/rs_animation_callback.h"
20 #include "animation/rs_animation_trace_utils.h"
21 #include "animation/rs_implicit_animation_param.h"
22 #include "animation/rs_path_animation.h"
23 #include "common/rs_optional_trace.h"
24 #include "modifier/rs_property.h"
25 #include "pipeline/rs_node_map.h"
26 #include "platform/common/rs_log.h"
27 #include "ui/rs_node.h"
28 #include "ui/rs_ui_director.h"
29 
30 namespace OHOS {
31 namespace Rosen {
OpenImplicitAnimation(const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve,std::shared_ptr<AnimationFinishCallback> && finishCallback,std::shared_ptr<AnimationRepeatCallback> && repeatCallback)32 int RSImplicitAnimator::OpenImplicitAnimation(const RSAnimationTimingProtocol& timingProtocol,
33     const RSAnimationTimingCurve& timingCurve, std::shared_ptr<AnimationFinishCallback>&& finishCallback,
34     std::shared_ptr<AnimationRepeatCallback>&& repeatCallback)
35 {
36     globalImplicitParams_.push({ timingProtocol, timingCurve, std::move(finishCallback),
37         std::move(repeatCallback) });
38     implicitAnimations_.push({});
39     keyframeAnimations_.push({});
40     durationKeyframeParams_.push({ false, 0, 0 });
41     switch (timingCurve.type_) {
42         case RSAnimationTimingCurve::CurveType::INTERPOLATING:
43             if (timingProtocol.GetDuration() <= 0) {
44                 // Special case: if duration is 0, we need to cancel existing implicit animations
45                 BeginImplicitCancelAnimation();
46             } else {
47                 // Begin default curve animation
48                 BeginImplicitCurveAnimation();
49             }
50             break;
51         case RSAnimationTimingCurve::CurveType::SPRING:
52             BeginImplicitSpringAnimation();
53             break;
54         case RSAnimationTimingCurve::CurveType::INTERPOLATING_SPRING:
55             BeginImplicitInterpolatingSpringAnimation();
56             break;
57         default:
58             ROSEN_LOGE("Wrong type of timing curve!");
59             return 0;
60     }
61     return static_cast<int>(globalImplicitParams_.size()) - 1;
62 }
63 
OpenImplicitAnimation(const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve,std::shared_ptr<AnimationFinishCallback> && finishCallback)64 int RSImplicitAnimator::OpenImplicitAnimation(const RSAnimationTimingProtocol& timingProtocol,
65     const RSAnimationTimingCurve& timingCurve, std::shared_ptr<AnimationFinishCallback>&& finishCallback)
66 {
67     return OpenImplicitAnimation(timingProtocol, timingCurve, std::move(finishCallback), nullptr);
68 }
69 
OpenImplicitAnimation(std::shared_ptr<AnimationFinishCallback> && finishCallback)70 int RSImplicitAnimator::OpenImplicitAnimation(std::shared_ptr<AnimationFinishCallback>&& finishCallback)
71 {
72     if (globalImplicitParams_.empty()) {
73         // if current implicit animation params is empty, use default params, if no animation created, call finish
74         // callback immediately
75         return OpenImplicitAnimation(
76             RSAnimationTimingProtocol::IMMEDIATE, RSAnimationTimingCurve::LINEAR, std::move(finishCallback));
77     } else {
78         // copy current implicit animation params and replace finish callback
79         [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
80         return OpenImplicitAnimation(protocol, curve, std::move(finishCallback));
81     }
82 }
83 
OpenImplicitAnimation(const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve)84 int RSImplicitAnimator::OpenImplicitAnimation(
85     const RSAnimationTimingProtocol& timingProtocol, const RSAnimationTimingCurve& timingCurve)
86 {
87     if (globalImplicitParams_.empty()) {
88         // current implicit animation params is empty, use empty
89         return OpenImplicitAnimation(timingProtocol, timingCurve, nullptr);
90     } else {
91         // copy current implicit animation callback and replace timing protocol and curve
92         [[maybe_unused]] const auto& [protocol, curve, callback, unused_repeatCallback] = globalImplicitParams_.top();
93         auto copyOfCallback = callback;
94         return OpenImplicitAnimation(timingProtocol, timingCurve, std::move(copyOfCallback));
95     }
96 }
97 
CloseImplicitAnimationInner()98 void RSImplicitAnimator::CloseImplicitAnimationInner()
99 {
100     globalImplicitParams_.pop();
101     implicitAnimations_.pop();
102     keyframeAnimations_.pop();
103     durationKeyframeParams_.pop();
104     EndImplicitAnimation();
105 }
106 
ProcessEmptyAnimations(const std::shared_ptr<AnimationFinishCallback> & finishCallback)107 void RSImplicitAnimator::ProcessEmptyAnimations(const std::shared_ptr<AnimationFinishCallback>& finishCallback)
108 {
109     // If finish callback either 1. is null or 2. is referenced by any animation or implicitly parameters, we don't
110     // do anything.
111     if (finishCallback.use_count() != 1) {
112         return;
113     }
114     RSAnimationTraceUtils::GetInstance().addAnimationNameTrace("ProcessEmptyAnimations");
115     auto protocol = std::get<RSAnimationTimingProtocol>(globalImplicitParams_.top());
116     // we are the only one who holds the finish callback, if the callback is NOT timing sensitive, we need to
117     // execute it asynchronously, in order to avoid timing issues.
118     if (!rsUIContext_.expired()) {
119         auto rsUIContext = rsUIContext_.lock();
120         if (finishCallback->finishCallbackType_ == FinishCallbackType::TIME_INSENSITIVE || protocol.GetDuration() < 0) {
121             ROSEN_LOGD("RSImplicitAnimator::CloseImplicitAnimation, No implicit animations created, execute finish "
122                        "callback asynchronously");
123             rsUIContext->PostTask([finishCallback]() { finishCallback->Execute(); });
124         } else {
125             // we are the only one who holds the finish callback, if the callback is timing sensitive, we need to create
126             // a delay task, in order to execute it on the right time.
127             ROSEN_LOGD("RSImplicitAnimator::CloseImplicitAnimation, No implicit animations created, execute finish "
128                        "callback on delay duration");
129             rsUIContext->PostDelayTask(
130                 [finishCallback]() { finishCallback->Execute(); }, static_cast<uint32_t>(protocol.GetDuration()));
131         }
132     } else {
133         if (finishCallback->finishCallbackType_ == FinishCallbackType::TIME_INSENSITIVE || protocol.GetDuration() < 0) {
134             ROSEN_LOGD("RSImplicitAnimator::CloseImplicitAnimation, No implicit animations created, execute finish "
135                        "callback asynchronously");
136             RSUIDirector::PostTask([finishCallback]() { finishCallback->Execute(); });
137         } else {
138             // we are the only one who holds the finish callback, if the callback is timing sensitive, we need to create
139             // a delay task, in order to execute it on the right time.
140             ROSEN_LOGD("RSImplicitAnimator::CloseImplicitAnimation, No implicit animations created, execute finish "
141                        "callback on delay duration");
142             RSUIDirector::PostDelayTask(
143                 [finishCallback]() { finishCallback->Execute(); }, static_cast<uint32_t>(protocol.GetDuration()));
144         }
145     }
146 }
147 
CloseImplicitAnimation()148 std::vector<std::shared_ptr<RSAnimation>> RSImplicitAnimator::CloseImplicitAnimation()
149 {
150     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
151         ROSEN_LOGD("Failed to close implicit animation, need to open implicit animation firstly!");
152         return {};
153     }
154 
155     // Special case: if implicit animation param type is CANCEL, we need to cancel all implicit animations
156     if (implicitAnimationParams_.top()->GetType() == ImplicitAnimationParamType::CANCEL) {
157         std::static_pointer_cast<RSImplicitCancelAnimationParam>(implicitAnimationParams_.top())->
158         SyncProperties(rsUIContext_.lock());
159     }
160 
161     const auto& finishCallback = std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
162     auto& currentAnimations = implicitAnimations_.top();
163     auto& currentKeyframeAnimations = keyframeAnimations_.top();
164     // if no implicit animation created by current implicit animation param, we need to take care of finish callback
165     if (currentAnimations.empty() && currentKeyframeAnimations.empty()) {
166         ProcessEmptyAnimations(finishCallback);
167         CloseImplicitAnimationInner();
168         return {};
169     }
170     bool hasUiAnimation = false;
171 
172     auto rsUIContext = rsUIContext_.lock();
173     std::vector<std::shared_ptr<RSAnimation>> resultAnimations;
174     [[maybe_unused]] auto& [isDurationKeyframe, totalDuration, currentDuration] = durationKeyframeParams_.top();
175     for (const auto& [animationInfo, keyframeAnimation] : currentKeyframeAnimations) {
176         auto target = rsUIContext ? rsUIContext->GetNodeMap().GetNode<RSNode>(animationInfo.first) :
177             RSNodeMap::Instance().GetNode<RSNode>(animationInfo.first);
178         if (target == nullptr) {
179             ROSEN_LOGE("Failed to start implicit keyframe animation[%{public}" PRIu64 "], target is null!",
180                 keyframeAnimation->GetId());
181             continue;
182         }
183         if (isDurationKeyframe) {
184             keyframeAnimation->SetDuration(totalDuration);
185         }
186         // this will actually create the RSRenderKeyframeAnimation
187         keyframeAnimation->SetFinishCallback(finishCallback);
188         if (isAddInteractiveAnimator_) {
189             interactiveImplicitAnimations_.top().emplace_back(keyframeAnimation, target->GetId());
190         }
191         target->AddAnimation(keyframeAnimation, !isAddInteractiveAnimator_);
192         resultAnimations.emplace_back(keyframeAnimation);
193         hasUiAnimation = hasUiAnimation || keyframeAnimation->IsUiAnimation();
194     }
195 
196     for (const auto& [animation, nodeId] : currentAnimations) {
197         animation->SetFinishCallback(finishCallback);
198         resultAnimations.emplace_back(animation);
199         if (isAddInteractiveAnimator_) {
200             interactiveImplicitAnimations_.top().emplace_back(animation, nodeId);
201         }
202         hasUiAnimation = hasUiAnimation || animation->IsUiAnimation();
203     }
204 
205     if (!hasUiAnimation) {
206         ProcessAnimationFinishCallbackGuaranteeTask();
207     }
208     CloseImplicitAnimationInner();
209     return resultAnimations;
210 }
211 
ProcessAnimationFinishCallbackGuaranteeTask()212 void RSImplicitAnimator::ProcessAnimationFinishCallbackGuaranteeTask()
213 {
214     constexpr float SECOND_TO_MILLISECOND = 1e3;
215     constexpr float MIN_DURATION = 1000.0f;
216     constexpr int MULTIPLES_DURATION = 2;
217     constexpr float BLEND_DURATION = 1.0f;
218 
219     const auto& [protocol, curve, finishCallback, unused] = globalImplicitParams_.top();
220     if (finishCallback == nullptr || protocol.GetRepeatCount() == -1) {
221         return;
222     }
223 
224     // estimate duration
225     float duration = 0;
226     if (curve.type_ == RSAnimationTimingCurve::CurveType::INTERPOLATING) {
227         // Interpolating curves
228         duration = protocol.GetDuration() * protocol.GetRepeatCount() + protocol.GetStartDelay();
229     } else if (const auto& params = curve.springParams_) {
230         // Spring curves
231         auto model = std::make_unique<RSSpringModel<float>>(params->response_, params->dampingRatio_, BLEND_DURATION,
232             params->initialVelocity_, params->minimumAmplitudeRatio_);
233         duration = std::lroundf(model->EstimateDuration() * SECOND_TO_MILLISECOND) * protocol.GetRepeatCount() +
234             protocol.GetStartDelay();
235     }
236     duration *= RSSystemProperties::GetAnimationScale();
237     if (duration < EPSILON) {
238         return;
239     }
240     auto callbackSafetyNetLambda = [weakCallback = std::weak_ptr<AnimationFinishCallback>(finishCallback),
241         type = curve.type_, duration]() -> void {
242         auto callback = weakCallback.lock();
243         if (callback && callback->IsValid() && !callback->HasAnimationBeenPaused()) {
244             ROSEN_LOGW("Animation finish callback is not executed in estimated time. params : type[%{public}d] "
245                        "duration[%{public}f]",
246                 type, duration);
247             callback->Execute();
248         }
249     };
250     auto estimateDuration = std::max(duration * MULTIPLES_DURATION, MIN_DURATION);
251     // Double-check the finish callback is called by the timing when the estimateDuration. This is a safety net
252     // to ensure that the callback is executed even if the timing is not triggered due to some reason.
253     RSUIDirector::PostDelayTask(callbackSafetyNetLambda, estimateDuration);
254 }
255 
CloseImplicitCancelAnimation()256 bool RSImplicitAnimator::CloseImplicitCancelAnimation()
257 {
258     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
259         ROSEN_LOGD("Failed to close cancel implicit animation, need to open implicit animation firstly!");
260         return false;
261     }
262     if (implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::CANCEL) {
263         ROSEN_LOGE("Failed to close cancel implicit animation, need to use the right fun 'CloseImplicitAnimation'!");
264         return false;
265     }
266 
267     bool ret =
268         std::static_pointer_cast<RSImplicitCancelAnimationParam>(implicitAnimationParams_.top())->
269         SyncProperties(rsUIContext_.lock());
270     const auto& finishCallback = std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
271     ProcessEmptyAnimations(finishCallback);
272     CloseImplicitAnimationInner();
273     return ret;
274 }
275 
OpenInterActiveImplicitAnimation(bool isAddImplictAnimation,const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve,std::shared_ptr<AnimationFinishCallback> && finishCallback)276 int RSImplicitAnimator::OpenInterActiveImplicitAnimation(bool isAddImplictAnimation,
277     const RSAnimationTimingProtocol& timingProtocol, const RSAnimationTimingCurve& timingCurve,
278     std::shared_ptr<AnimationFinishCallback>&& finishCallback)
279 {
280     isAddInteractiveAnimator_ = true;
281     interactiveImplicitAnimations_.push({});
282     return isAddImplictAnimation ?
283         OpenImplicitAnimation(timingProtocol, timingCurve, std::move(finishCallback), nullptr) : 0;
284 }
285 
CloseInterActiveImplicitAnimation(bool isAddImplictAnimation)286 std::vector<std::pair<std::shared_ptr<RSAnimation>, NodeId>> RSImplicitAnimator::CloseInterActiveImplicitAnimation(
287     bool isAddImplictAnimation)
288 {
289     if (interactiveImplicitAnimations_.empty()) {
290         ROSEN_LOGD("Failed to close interactive implicit animation, need to open implicit animation firstly!");
291         return {};
292     }
293     if (isAddImplictAnimation) {
294         if (globalImplicitParams_.empty()) {
295             ROSEN_LOGD("Failed to close interactive implicit animation, globalImplicitParams is empty!");
296             return {};
297         }
298 
299         auto& currentAnimations = implicitAnimations_.top();
300         const auto& finishCallback =
301             std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
302         for (const auto& [animation, nodeId] : currentAnimations) {
303             animation->SetFinishCallback(finishCallback);
304             interactiveImplicitAnimations_.top().emplace_back(animation, nodeId);
305         }
306     }
307 
308     auto& interactiveAnimations = interactiveImplicitAnimations_.top();
309     std::vector<std::pair<std::shared_ptr<RSAnimation>, NodeId>> resultAnimations;
310     for (const auto& [animation, nodeId] : interactiveAnimations) {
311         resultAnimations.emplace_back(animation, nodeId);
312     }
313 
314     if (isAddImplictAnimation) {
315         CloseImplicitAnimationInner();
316     }
317     interactiveImplicitAnimations_.pop();
318     isAddInteractiveAnimator_ = false;
319     return resultAnimations;
320 }
321 
BeginImplicitKeyFrameAnimation(float fraction,const RSAnimationTimingCurve & timingCurve)322 void RSImplicitAnimator::BeginImplicitKeyFrameAnimation(float fraction, const RSAnimationTimingCurve& timingCurve)
323 {
324     if (globalImplicitParams_.empty()) {
325         ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
326         return;
327     }
328 
329     if (timingCurve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
330         ROSEN_LOGE("Wrong type of timing curve!");
331         return;
332     }
333 
334     [[maybe_unused]] const auto& [protocol, unused_curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
335     if (protocol.GetDuration() <= 0) {
336         ROSEN_LOGD("Failed to begin keyframe implicit animation, total duration is 0!");
337         return;
338     }
339     auto keyframeAnimationParam =
340         std::make_shared<RSImplicitKeyframeAnimationParam>(protocol, timingCurve, fraction, 0);
341     PushImplicitParam(keyframeAnimationParam);
342 }
343 
BeginImplicitKeyFrameAnimation(float fraction)344 void RSImplicitAnimator::BeginImplicitKeyFrameAnimation(float fraction)
345 {
346     if (globalImplicitParams_.empty()) {
347         ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
348         return;
349     }
350 
351     BeginImplicitKeyFrameAnimation(fraction, std::get<RSAnimationTimingCurve>(globalImplicitParams_.top()));
352 }
353 
EndImplicitKeyFrameAnimation()354 void RSImplicitAnimator::EndImplicitKeyFrameAnimation()
355 {
356     if (implicitAnimationParams_.empty() ||
357         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::KEYFRAME) {
358         ROSEN_LOGD("Failed to end keyframe implicit animation, need to begin keyframe implicit animation firstly!");
359         return;
360     }
361 
362     PopImplicitParam();
363 }
364 
BeginImplicitDurationKeyFrameAnimation(int duration,const RSAnimationTimingCurve & timingCurve)365 void RSImplicitAnimator::BeginImplicitDurationKeyFrameAnimation(int duration, const RSAnimationTimingCurve& timingCurve)
366 {
367     if (globalImplicitParams_.empty()) {
368         ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
369         return;
370     }
371 
372     if (timingCurve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
373         ROSEN_LOGE("Wrong type of timing curve!");
374         return;
375     }
376 
377     [[maybe_unused]] const auto& [protocol, unused_curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
378     if (protocol.GetDuration() <= 0) {
379         ROSEN_LOGD("Failed to begin duration keyframe implicit animation, total duration is 0!");
380         return;
381     }
382     [[maybe_unused]] auto& [isDurationKeyframe, totalDuration, currentDuration] = durationKeyframeParams_.top();
383     isDurationKeyframe = true;
384     currentDuration = duration;
385     auto keyframeAnimationParam =
386         std::make_shared<RSImplicitKeyframeAnimationParam>(protocol, timingCurve, 0, duration);
387     PushImplicitParam(keyframeAnimationParam);
388 }
389 
EndImplicitDurationKeyFrameAnimation()390 void RSImplicitAnimator::EndImplicitDurationKeyFrameAnimation()
391 {
392     if (implicitAnimationParams_.empty() ||
393         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::KEYFRAME) {
394         ROSEN_LOGD("Failed to end keyframe implicit animation, need to begin keyframe implicit animation firstly!");
395         return;
396     }
397     [[maybe_unused]] auto& [isDurationKeyframe, totalDuration, currentDuration] = durationKeyframeParams_.top();
398     if (totalDuration > INT32_MAX - currentDuration) {
399         ROSEN_LOGD("RSImplicitAnimator::EndImplicitDurationKeyFrameAnimation, totalDuration overflow!");
400         totalDuration = INT32_MAX;
401     } else {
402         totalDuration += currentDuration;
403     }
404     currentDuration = 0;
405     PopImplicitParam();
406 }
407 
NeedImplicitAnimation()408 bool RSImplicitAnimator::NeedImplicitAnimation()
409 {
410     return !implicitAnimationDisabled_ && !implicitAnimationParams_.empty() &&
411            implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::INVALID;
412 }
413 
BeginImplicitCurveAnimation()414 void RSImplicitAnimator::BeginImplicitCurveAnimation()
415 {
416     // params sanity already checked in BeginImplicitAnimation, no need to check again.
417     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
418     auto curveAnimationParam = std::make_shared<RSImplicitCurveAnimationParam>(protocol, curve);
419     PushImplicitParam(curveAnimationParam);
420 }
421 
EndImplicitAnimation()422 void RSImplicitAnimator::EndImplicitAnimation()
423 {
424     if (implicitAnimationParams_.empty() ||
425         (implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::CANCEL &&
426         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::CURVE &&
427         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::SPRING &&
428         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::INTERPOLATING_SPRING)) {
429         ROSEN_LOGE("Failed to end implicit animation, need to begin implicit animation firstly!");
430         return;
431     }
432 
433     PopImplicitParam();
434 }
435 
BeginImplicitPathAnimation(const std::shared_ptr<RSMotionPathOption> & motionPathOption)436 void RSImplicitAnimator::BeginImplicitPathAnimation(const std::shared_ptr<RSMotionPathOption>& motionPathOption)
437 {
438     if (globalImplicitParams_.empty()) {
439         ROSEN_LOGE("Failed to begin path implicit animation, need to open implicit animation firstly!");
440         return;
441     }
442 
443     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
444     if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
445         ROSEN_LOGE("Wrong type of timing curve!");
446         return;
447     }
448 
449     if (protocol.GetDuration() <= 0) {
450         ROSEN_LOGE("Failed to begin path implicit animation, total duration is 0!");
451         return;
452     }
453     auto pathAnimationParam = std::make_shared<RSImplicitPathAnimationParam>(protocol, curve, motionPathOption);
454     PushImplicitParam(pathAnimationParam);
455 }
456 
EndImplicitPathAnimation()457 void RSImplicitAnimator::EndImplicitPathAnimation()
458 {
459     if (implicitAnimationParams_.empty() ||
460         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::PATH) {
461         ROSEN_LOGE("Failed to end path implicit animation, need to begin path implicit animation firstly!");
462         return;
463     }
464 
465     PopImplicitParam();
466 }
467 
BeginImplicitSpringAnimation()468 void RSImplicitAnimator::BeginImplicitSpringAnimation()
469 {
470     // params sanity already checked in BeginImplicitAnimation, no need to check again.
471     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
472     auto springParam = std::make_shared<RSImplicitSpringAnimationParam>(protocol, curve);
473     PushImplicitParam(springParam);
474 }
475 
BeginImplicitInterpolatingSpringAnimation()476 void RSImplicitAnimator::BeginImplicitInterpolatingSpringAnimation()
477 {
478     // params sanity already checked in BeginImplicitAnimation, no need to check again.
479     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
480     auto interpolatingSpringParam = std::make_shared<RSImplicitInterpolatingSpringAnimationParam>(protocol, curve);
481     PushImplicitParam(interpolatingSpringParam);
482 }
483 
BeginImplicitCancelAnimation()484 void RSImplicitAnimator::BeginImplicitCancelAnimation()
485 {
486     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
487     auto cancelImplicitParam = std::make_shared<RSImplicitCancelAnimationParam>(protocol);
488     PushImplicitParam(cancelImplicitParam);
489 }
490 
BeginImplicitTransition(const std::shared_ptr<const RSTransitionEffect> & effect,bool isTransitionIn)491 void RSImplicitAnimator::BeginImplicitTransition(
492     const std::shared_ptr<const RSTransitionEffect>& effect, bool isTransitionIn)
493 {
494     if (globalImplicitParams_.empty()) {
495         ROSEN_LOGE("Failed to begin implicit transition, need to open implicit transition firstly!");
496         return;
497     }
498 
499     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
500     if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
501         ROSEN_LOGE("Wrong type of timing curve!");
502         return;
503     }
504     auto transitionParam = std::make_shared<RSImplicitTransitionParam>(protocol, curve, effect, isTransitionIn);
505     PushImplicitParam(transitionParam);
506 }
507 
EndImplicitTransition()508 void RSImplicitAnimator::EndImplicitTransition()
509 {
510     if (implicitAnimationParams_.empty() ||
511         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::TRANSITION) {
512         ROSEN_LOGE("Failed to end implicit transition, need to begin implicit transition firstly!");
513         return;
514     }
515 
516     PopImplicitParam();
517 }
518 
PushImplicitParam(const std::shared_ptr<RSImplicitAnimationParam> & implicitParam)519 void RSImplicitAnimator::PushImplicitParam(const std::shared_ptr<RSImplicitAnimationParam>& implicitParam)
520 {
521     implicitAnimationParams_.emplace(implicitParam);
522 }
523 
PopImplicitParam()524 void RSImplicitAnimator::PopImplicitParam()
525 {
526     if (implicitAnimationParams_.empty()) {
527         ROSEN_LOGE("Failed to pop implicit params, params stack is empty!");
528         return;
529     }
530 
531     implicitAnimationParams_.pop();
532 }
533 
CreateImplicitTransition(RSNode & target)534 void RSImplicitAnimator::CreateImplicitTransition(RSNode& target)
535 {
536     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
537         ROSEN_LOGE("Failed to create implicit transition, need to open implicit transition firstly!");
538         return;
539     }
540     auto& params = implicitAnimationParams_.top();
541     if (params->GetType() != ImplicitAnimationParamType::TRANSITION) {
542         ROSEN_LOGE("Failed to create transition, unknow type!");
543         return;
544     }
545     auto transitionImplicitParam = std::static_pointer_cast<RSImplicitTransitionParam>(params);
546     auto transition = transitionImplicitParam->CreateAnimation();
547     if (transition != nullptr) {
548         target.AddAnimation(transition);
549         implicitAnimations_.top().push_back({ transition, target.GetId() });
550     }
551     return;
552 }
553 
CancelImplicitAnimation(const std::shared_ptr<RSNode> & target,const std::shared_ptr<RSPropertyBase> & property)554 void RSImplicitAnimator::CancelImplicitAnimation(
555     const std::shared_ptr<RSNode>& target, const std::shared_ptr<RSPropertyBase>& property)
556 {
557     if (target == nullptr || property == nullptr) {
558         return;
559     }
560     if (!target->HasPropertyAnimation(property->GetId())) {
561         return;
562     }
563     auto params = implicitAnimationParams_.top();
564     if (params->GetType() != ImplicitAnimationParamType::CANCEL) {
565         return;
566     }
567     auto cancelImplicitParam = std::static_pointer_cast<RSImplicitCancelAnimationParam>(params);
568     cancelImplicitParam->AddPropertyToPendingSyncList(property);
569     return;
570 }
571 
SetPropertyValue(std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPropertyBase> & value)572 void RSImplicitAnimator::SetPropertyValue(
573     std::shared_ptr<RSPropertyBase> property, const std::shared_ptr<RSPropertyBase>& value)
574 {
575     if (property != nullptr) {
576         property->SetValue(value);
577     }
578 }
579 
CreateImplicitAnimation(const std::shared_ptr<RSNode> & target,std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)580 void RSImplicitAnimator::CreateImplicitAnimation(const std::shared_ptr<RSNode>& target,
581     std::shared_ptr<RSPropertyBase> property, const std::shared_ptr<RSPropertyBase>& startValue,
582     const std::shared_ptr<RSPropertyBase>& endValue)
583 {
584     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
585         ROSEN_LOGE("Failed to create implicit animation, need to open implicit animation firstly!");
586         return;
587     }
588 
589     if (target == nullptr || property == nullptr || startValue == nullptr || endValue == nullptr) {
590         return;
591     }
592 
593     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
594     if (protocol.GetRepeatCount() == -1 && property->id_ == 0) {
595         ROSEN_LOGE("Failed to create infinite empty animation!");
596         return;
597     }
598 
599     std::shared_ptr<RSAnimation> animation;
600     auto params = implicitAnimationParams_.top();
601     auto& repeatCallback = std::get<std::shared_ptr<AnimationRepeatCallback>>(globalImplicitParams_.top());
602     switch (params->GetType()) {
603         case ImplicitAnimationParamType::CURVE: {
604             auto curveImplicitParam = static_cast<RSImplicitCurveAnimationParam*>(params.get());
605             animation = curveImplicitParam->CreateAnimation(property, startValue, endValue);
606             break;
607         }
608         case ImplicitAnimationParamType::KEYFRAME: {
609             auto keyframeImplicitParam = static_cast<RSImplicitKeyframeAnimationParam*>(params.get());
610             auto& keyframeAnimations = keyframeAnimations_.top();
611             auto keyframeIter = keyframeAnimations.find({ target->GetId(), property->GetId() });
612             [[maybe_unused]] auto& [isDurationKeyframe, totalDuration, unused] = durationKeyframeParams_.top();
613             SetPropertyValue(property, endValue);
614             if (keyframeIter == keyframeAnimations.end()) {
615                 animation = keyframeImplicitParam->CreateAnimation(property, isDurationKeyframe, totalDuration,
616                     startValue, endValue);
617                 keyframeAnimations[{ target->GetId(), property->GetId() }] = animation;
618             } else {
619                 if (isDurationKeyframe) {
620                     keyframeImplicitParam->AddKeyframe(keyframeIter->second, totalDuration, startValue, endValue);
621                 } else {
622                     keyframeImplicitParam->AddKeyframe(keyframeIter->second, startValue, endValue);
623                 }
624             }
625             break;
626         }
627         case ImplicitAnimationParamType::SPRING: {
628             auto springImplicitParam = static_cast<RSImplicitSpringAnimationParam*>(params.get());
629             animation = springImplicitParam->CreateAnimation(property, startValue, endValue);
630             const auto& finishCallback =
631                 std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
632             if (finishCallback && finishCallback->finishCallbackType_ == FinishCallbackType::LOGICALLY) {
633                 animation->SetZeroThreshold(property->GetThreshold());
634             }
635             break;
636         }
637         case ImplicitAnimationParamType::INTERPOLATING_SPRING: {
638             auto interpolatingSpringImplicitParam =
639                 static_cast<RSImplicitInterpolatingSpringAnimationParam*>(params.get());
640             animation = interpolatingSpringImplicitParam->CreateAnimation(property, startValue, endValue);
641             const auto& finishCallback =
642                 std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
643             if (finishCallback && finishCallback->finishCallbackType_ == FinishCallbackType::LOGICALLY) {
644                 animation->SetZeroThreshold(property->GetThreshold());
645             }
646             break;
647         }
648         case ImplicitAnimationParamType::PATH: {
649             auto pathImplicitParam = static_cast<RSImplicitPathAnimationParam*>(params.get());
650             animation = pathImplicitParam->CreateAnimation(property, startValue, endValue);
651             break;
652         }
653         case ImplicitAnimationParamType::TRANSITION: {
654             auto implicitTransitionParam = static_cast<RSImplicitTransitionParam*>(params.get());
655             animation = implicitTransitionParam->CreateAnimation(property, startValue, endValue);
656             break;
657         }
658         case ImplicitAnimationParamType::CANCEL: {
659             // CreateEmptyAnimation
660             if (property->id_ == 0) {
661                 auto curveImplicitParam = static_cast<RSImplicitCancelAnimationParam*>(params.get());
662                 animation = curveImplicitParam->CreateEmptyAnimation(property, startValue, endValue);
663                 break;
664             }
665 
666             // Create animation with CANCEL type will cancel all running animations of the given property and target.
667             // Note: We are currently in the process of refactoring and accidentally changed the order of animation
668             // callbacks. Originally, the order was OnChange before OnFinish, but we mistakenly changed it to OnFinish
669             // before OnChange. This change has caused some issues, and we need to revert it back to the original order.
670             // However, before fixing this, we discovered that there are some changes in arkui that rely on this 'bug'.
671             // If we change it back to the original order, it will break the list swipe animation. Therefore, we need
672             // to carefully consider the implications of this change before proceeding.
673             if (property->GetIsCustom()) {
674                 property->SetValue(endValue);                         // update set ui value
675                 property->UpdateCustomAnimation();                    // force sync RS value for custom property
676                 target->CancelAnimationByProperty(property->GetId()); // finish all ui animation
677             } else {
678                 target->FinishAnimationByProperty(property->GetId()); // finish all ui animation
679                 property->SetValue(endValue);                         // update set ui value
680                 property->UpdateOnAllAnimationFinish();               // force sync RS value for native property
681             }
682             return;
683         }
684         default:
685             ROSEN_LOGE("Failed to create animation, unknow type!");
686             break;
687     }
688 
689     if (animation == nullptr) {
690         ROSEN_LOGD("Failed to create animation!");
691         return;
692     }
693     if (repeatCallback != nullptr) {
694         animation->SetRepeatCallback(std::move(repeatCallback));
695         repeatCallback.reset();
696     }
697 
698     RSAnimationTraceUtils::GetInstance().addAnimationCreateTrace(
699         target->GetId(), target->GetNodeName(), property->GetId(),
700         animation->GetId(), static_cast<int>(params->GetType()), static_cast<int>(property->type_),
701         startValue->GetRenderProperty(), endValue->GetRenderProperty(), animation->GetStartDelay(),
702         animation->GetDuration(), protocol.GetRepeatCount());
703 
704     if (params->GetType() == ImplicitAnimationParamType::TRANSITION ||
705         params->GetType() == ImplicitAnimationParamType::KEYFRAME) {
706         // for transition this will create custom transition animation, there is no need to add it to target.
707         // for keyframe animations, we don't add it to target now, we will add it later in
708         // RSImplicitAnimator::CloseImplicitAnimation.
709         return;
710     }
711     target->AddAnimation(animation, !isAddInteractiveAnimator_);
712     implicitAnimations_.top().emplace_back(animation, target->GetId());
713     return;
714 }
715 
ExecuteWithoutAnimation(const std::function<void ()> & callback)716 void RSImplicitAnimator::ExecuteWithoutAnimation(const std::function<void()>& callback)
717 {
718     if (callback == nullptr) {
719         return;
720     }
721     // disable implicit animation and execute callback, restore previous state after callback.
722     auto implicitAnimationDisabled = implicitAnimationDisabled_;
723     implicitAnimationDisabled_ = true;
724     callback();
725     implicitAnimationDisabled_ = implicitAnimationDisabled;
726 }
727 
CreateImplicitAnimationWithInitialVelocity(const std::shared_ptr<RSNode> & target,const std::shared_ptr<RSPropertyBase> & property,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue,const std::shared_ptr<RSPropertyBase> & velocity)728 void RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity(const std::shared_ptr<RSNode>& target,
729     const std::shared_ptr<RSPropertyBase>& property, const std::shared_ptr<RSPropertyBase>& startValue,
730     const std::shared_ptr<RSPropertyBase>& endValue, const std::shared_ptr<RSPropertyBase>& velocity)
731 {
732     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
733         ROSEN_LOGE("RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity:Failed to create implicit "
734                    "animation, need to open implicit animation firstly!");
735         return;
736     }
737 
738     if (target == nullptr || property == nullptr) {
739         ROSEN_LOGE(
740             "RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity:target node or property is a nullptr.");
741         return;
742     }
743 
744     std::shared_ptr<RSAnimation> animation;
745     auto params = implicitAnimationParams_.top();
746     if (!params || params->GetType() != ImplicitAnimationParamType::SPRING) {
747         ROSEN_LOGE(
748             "RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity:the parameters of animations are invalid.");
749         return;
750     }
751 
752     auto springImplicitParam = static_cast<RSImplicitSpringAnimationParam*>(params.get());
753     if (!springImplicitParam) {
754         ROSEN_LOGE("RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity:the parameter of spring animations "
755                    "is null.");
756         return;
757     }
758 
759     animation = springImplicitParam->CreateAnimation(property, startValue, endValue);
760     if (!animation) {
761         ROSEN_LOGE("RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity: failed to create animation.");
762         return;
763     }
764 
765     animation->SetInitialVelocity(velocity);
766     const auto& finishCallback = std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
767     if (finishCallback && finishCallback->finishCallbackType_ == FinishCallbackType::LOGICALLY) {
768         animation->SetZeroThreshold(property->GetThreshold());
769     }
770 
771     auto& repeatCallback = std::get<std::shared_ptr<AnimationRepeatCallback>>(globalImplicitParams_.top());
772     if (repeatCallback) {
773         animation->SetRepeatCallback(std::move(repeatCallback));
774         repeatCallback.reset();
775     }
776 
777     auto protocol = std::get<RSAnimationTimingProtocol>(globalImplicitParams_.top());
778     RSAnimationTraceUtils::GetInstance().addAnimationCreateTrace(
779         target->GetId(), target->GetNodeName(), property->GetId(),
780         animation->GetId(), static_cast<int>(params->GetType()), static_cast<int>(property->type_),
781         startValue->GetRenderProperty(), endValue->GetRenderProperty(), animation->GetStartDelay(),
782         animation->GetDuration(), protocol.GetRepeatCount());
783 
784     target->AddAnimation(animation);
785     implicitAnimations_.top().emplace_back(animation, target->GetId());
786 }
787 } // namespace Rosen
788 } // namespace OHOS
789