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