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 (finishCallback->finishCallbackType_ == FinishCallbackType::TIME_INSENSITIVE || protocol.GetDuration() < 0) {
119         ROSEN_LOGI("RSImplicitAnimator::CloseImplicitAnimation, No implicit animations created, execute finish "
120                    "callback asynchronously");
121         RSUIDirector::PostTask([finishCallback]() { finishCallback->Execute(); });
122     } else {
123         // we are the only one who holds the finish callback, if the callback is timing sensitive, we need to create
124         // a delay task, in order to execute it on the right time.
125         ROSEN_LOGI("RSImplicitAnimator::CloseImplicitAnimation, No implicit animations created, execute finish "
126                    "callback on delay duration");
127         RSUIDirector::PostDelayTask(
128             [finishCallback]() { finishCallback->Execute(); }, static_cast<uint32_t>(protocol.GetDuration()));
129     }
130 }
131 
CloseImplicitAnimation()132 std::vector<std::shared_ptr<RSAnimation>> RSImplicitAnimator::CloseImplicitAnimation()
133 {
134     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
135         ROSEN_LOGD("Failed to close implicit animation, need to open implicit animation firstly!");
136         return {};
137     }
138 
139     // Special case: if implicit animation param type is CANCEL, we need to cancel all implicit animations
140     if (implicitAnimationParams_.top()->GetType() == ImplicitAnimationParamType::CANCEL) {
141         std::static_pointer_cast<RSImplicitCancelAnimationParam>(implicitAnimationParams_.top())->SyncProperties();
142     }
143 
144     const auto& finishCallback = std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
145     auto& currentAnimations = implicitAnimations_.top();
146     auto& currentKeyframeAnimations = keyframeAnimations_.top();
147     // if no implicit animation created by current implicit animation param, we need to take care of finish callback
148     if (currentAnimations.empty() && currentKeyframeAnimations.empty()) {
149         ProcessEmptyAnimations(finishCallback);
150         CloseImplicitAnimationInner();
151         return {};
152     }
153     std::vector<std::shared_ptr<RSAnimation>> resultAnimations;
154     [[maybe_unused]] auto& [isDurationKeyframe, totalDuration, currentDuration] = durationKeyframeParams_.top();
155     for (const auto& [animationInfo, keyframeAnimation] : currentKeyframeAnimations) {
156         auto target = RSNodeMap::Instance().GetNode<RSNode>(animationInfo.first);
157         if (target == nullptr) {
158             ROSEN_LOGE("Failed to start implicit keyframe animation[%{public}" PRIu64 "], target is null!",
159                 keyframeAnimation->GetId());
160             continue;
161         }
162         if (isDurationKeyframe) {
163             keyframeAnimation->SetDuration(totalDuration);
164         }
165         // this will actually create the RSRenderKeyframeAnimation
166         keyframeAnimation->SetFinishCallback(finishCallback);
167         if (isAddInteractiveAnimator_) {
168             interactiveImplicitAnimations_.top().emplace_back(keyframeAnimation, target->GetId());
169         }
170         target->AddAnimation(keyframeAnimation, !isAddInteractiveAnimator_);
171         resultAnimations.emplace_back(keyframeAnimation);
172     }
173 
174     for (const auto& [animation, nodeId] : currentAnimations) {
175         animation->SetFinishCallback(finishCallback);
176         resultAnimations.emplace_back(animation);
177         if (isAddInteractiveAnimator_) {
178             interactiveImplicitAnimations_.top().emplace_back(animation, nodeId);
179         }
180     }
181 
182     CloseImplicitAnimationInner();
183     return resultAnimations;
184 }
185 
CloseImplicitCancelAnimation()186 bool RSImplicitAnimator::CloseImplicitCancelAnimation()
187 {
188     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
189         ROSEN_LOGD("Failed to close cancel implicit animation, need to open implicit animation firstly!");
190         return false;
191     }
192     if (implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::CANCEL) {
193         ROSEN_LOGE("Failed to close cancel implicit animation, need to use the right fun 'CloseImplicitAnimation'!");
194         return false;
195     }
196 
197     bool ret =
198         std::static_pointer_cast<RSImplicitCancelAnimationParam>(implicitAnimationParams_.top())->SyncProperties();
199     const auto& finishCallback = std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
200     ProcessEmptyAnimations(finishCallback);
201     CloseImplicitAnimationInner();
202     return ret;
203 }
204 
OpenInterActiveImplicitAnimation(bool isAddImplictAnimation,const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve,std::shared_ptr<AnimationFinishCallback> && finishCallback)205 int RSImplicitAnimator::OpenInterActiveImplicitAnimation(bool isAddImplictAnimation,
206     const RSAnimationTimingProtocol& timingProtocol, const RSAnimationTimingCurve& timingCurve,
207     std::shared_ptr<AnimationFinishCallback>&& finishCallback)
208 {
209     isAddInteractiveAnimator_ = true;
210     interactiveImplicitAnimations_.push({});
211     return isAddImplictAnimation ?
212         OpenImplicitAnimation(timingProtocol, timingCurve, std::move(finishCallback), nullptr) : 0;
213 }
214 
CloseInterActiveImplicitAnimation(bool isAddImplictAnimation)215 std::vector<std::pair<std::shared_ptr<RSAnimation>, NodeId>> RSImplicitAnimator::CloseInterActiveImplicitAnimation(
216     bool isAddImplictAnimation)
217 {
218     if (interactiveImplicitAnimations_.empty()) {
219         ROSEN_LOGD("Failed to close interactive implicit animation, need to open implicit animation firstly!");
220         return {};
221     }
222     if (isAddImplictAnimation) {
223         if (globalImplicitParams_.empty()) {
224             ROSEN_LOGD("Failed to close interactive implicit animation, globalImplicitParams is empty!");
225             return {};
226         }
227 
228         auto& currentAnimations = implicitAnimations_.top();
229         const auto& finishCallback =
230             std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
231         for (const auto& [animation, nodeId] : currentAnimations) {
232             animation->SetFinishCallback(finishCallback);
233             interactiveImplicitAnimations_.top().emplace_back(animation, nodeId);
234         }
235     }
236 
237     auto& interactiveAnimations = interactiveImplicitAnimations_.top();
238     std::vector<std::pair<std::shared_ptr<RSAnimation>, NodeId>> resultAnimations;
239     for (const auto& [animation, nodeId] : interactiveAnimations) {
240         resultAnimations.emplace_back(animation, nodeId);
241     }
242 
243     if (isAddImplictAnimation) {
244         CloseImplicitAnimationInner();
245     }
246     interactiveImplicitAnimations_.pop();
247     isAddInteractiveAnimator_ = false;
248     return resultAnimations;
249 }
250 
BeginImplicitKeyFrameAnimation(float fraction,const RSAnimationTimingCurve & timingCurve)251 void RSImplicitAnimator::BeginImplicitKeyFrameAnimation(float fraction, const RSAnimationTimingCurve& timingCurve)
252 {
253     if (globalImplicitParams_.empty()) {
254         ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
255         return;
256     }
257 
258     if (timingCurve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
259         ROSEN_LOGE("Wrong type of timing curve!");
260         return;
261     }
262 
263     [[maybe_unused]] const auto& [protocol, unused_curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
264     if (protocol.GetDuration() <= 0) {
265         ROSEN_LOGD("Failed to begin keyframe implicit animation, total duration is 0!");
266         return;
267     }
268     auto keyframeAnimationParam =
269         std::make_shared<RSImplicitKeyframeAnimationParam>(protocol, timingCurve, fraction, 0);
270     PushImplicitParam(keyframeAnimationParam);
271 }
272 
BeginImplicitKeyFrameAnimation(float fraction)273 void RSImplicitAnimator::BeginImplicitKeyFrameAnimation(float fraction)
274 {
275     if (globalImplicitParams_.empty()) {
276         ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
277         return;
278     }
279 
280     BeginImplicitKeyFrameAnimation(fraction, std::get<RSAnimationTimingCurve>(globalImplicitParams_.top()));
281 }
282 
EndImplicitKeyFrameAnimation()283 void RSImplicitAnimator::EndImplicitKeyFrameAnimation()
284 {
285     if (implicitAnimationParams_.empty() ||
286         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::KEYFRAME) {
287         ROSEN_LOGD("Failed to end keyframe implicit animation, need to begin keyframe implicit animation firstly!");
288         return;
289     }
290 
291     PopImplicitParam();
292 }
293 
BeginImplicitDurationKeyFrameAnimation(int duration,const RSAnimationTimingCurve & timingCurve)294 void RSImplicitAnimator::BeginImplicitDurationKeyFrameAnimation(int duration, const RSAnimationTimingCurve& timingCurve)
295 {
296     if (globalImplicitParams_.empty()) {
297         ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
298         return;
299     }
300 
301     if (timingCurve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
302         ROSEN_LOGE("Wrong type of timing curve!");
303         return;
304     }
305 
306     [[maybe_unused]] const auto& [protocol, unused_curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
307     if (protocol.GetDuration() <= 0) {
308         ROSEN_LOGD("Failed to begin duration keyframe implicit animation, total duration is 0!");
309         return;
310     }
311     [[maybe_unused]] auto& [isDurationKeyframe, totalDuration, currentDuration] = durationKeyframeParams_.top();
312     isDurationKeyframe = true;
313     currentDuration = duration;
314     auto keyframeAnimationParam =
315         std::make_shared<RSImplicitKeyframeAnimationParam>(protocol, timingCurve, 0, duration);
316     PushImplicitParam(keyframeAnimationParam);
317 }
318 
EndImplicitDurationKeyFrameAnimation()319 void RSImplicitAnimator::EndImplicitDurationKeyFrameAnimation()
320 {
321     if (implicitAnimationParams_.empty() ||
322         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::KEYFRAME) {
323         ROSEN_LOGD("Failed to end keyframe implicit animation, need to begin keyframe implicit animation firstly!");
324         return;
325     }
326     [[maybe_unused]] auto& [isDurationKeyframe, totalDuration, currentDuration] = durationKeyframeParams_.top();
327     totalDuration += currentDuration;
328     currentDuration = 0;
329     PopImplicitParam();
330 }
331 
NeedImplicitAnimation()332 bool RSImplicitAnimator::NeedImplicitAnimation()
333 {
334     return !implicitAnimationDisabled_ && !implicitAnimationParams_.empty() &&
335            implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::INVALID;
336 }
337 
BeginImplicitCurveAnimation()338 void RSImplicitAnimator::BeginImplicitCurveAnimation()
339 {
340     // params sanity already checked in BeginImplicitAnimation, no need to check again.
341     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
342     auto curveAnimationParam = std::make_shared<RSImplicitCurveAnimationParam>(protocol, curve);
343     PushImplicitParam(curveAnimationParam);
344 }
345 
EndImplicitAnimation()346 void RSImplicitAnimator::EndImplicitAnimation()
347 {
348     if (implicitAnimationParams_.empty() ||
349         (implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::CANCEL &&
350         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::CURVE &&
351         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::SPRING &&
352         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::INTERPOLATING_SPRING)) {
353         ROSEN_LOGE("Failed to end implicit animation, need to begin implicit animation firstly!");
354         return;
355     }
356 
357     PopImplicitParam();
358 }
359 
BeginImplicitPathAnimation(const std::shared_ptr<RSMotionPathOption> & motionPathOption)360 void RSImplicitAnimator::BeginImplicitPathAnimation(const std::shared_ptr<RSMotionPathOption>& motionPathOption)
361 {
362     if (globalImplicitParams_.empty()) {
363         ROSEN_LOGE("Failed to begin path implicit animation, need to open implicit animation firstly!");
364         return;
365     }
366 
367     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
368     if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
369         ROSEN_LOGE("Wrong type of timing curve!");
370         return;
371     }
372 
373     if (protocol.GetDuration() <= 0) {
374         ROSEN_LOGE("Failed to begin path implicit animation, total duration is 0!");
375         return;
376     }
377     auto pathAnimationParam = std::make_shared<RSImplicitPathAnimationParam>(protocol, curve, motionPathOption);
378     PushImplicitParam(pathAnimationParam);
379 }
380 
EndImplicitPathAnimation()381 void RSImplicitAnimator::EndImplicitPathAnimation()
382 {
383     if (implicitAnimationParams_.empty() ||
384         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::PATH) {
385         ROSEN_LOGE("Failed to end path implicit animation, need to begin path implicit animation firstly!");
386         return;
387     }
388 
389     PopImplicitParam();
390 }
391 
BeginImplicitSpringAnimation()392 void RSImplicitAnimator::BeginImplicitSpringAnimation()
393 {
394     // params sanity already checked in BeginImplicitAnimation, no need to check again.
395     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
396     auto springParam = std::make_shared<RSImplicitSpringAnimationParam>(protocol, curve);
397     PushImplicitParam(springParam);
398 }
399 
BeginImplicitInterpolatingSpringAnimation()400 void RSImplicitAnimator::BeginImplicitInterpolatingSpringAnimation()
401 {
402     // params sanity already checked in BeginImplicitAnimation, no need to check again.
403     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
404     auto interpolatingSpringParam = std::make_shared<RSImplicitInterpolatingSpringAnimationParam>(protocol, curve);
405     PushImplicitParam(interpolatingSpringParam);
406 }
407 
BeginImplicitCancelAnimation()408 void RSImplicitAnimator::BeginImplicitCancelAnimation()
409 {
410     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
411     auto cancelImplicitParam = std::make_shared<RSImplicitCancelAnimationParam>(protocol);
412     PushImplicitParam(cancelImplicitParam);
413 }
414 
BeginImplicitTransition(const std::shared_ptr<const RSTransitionEffect> & effect,bool isTransitionIn)415 void RSImplicitAnimator::BeginImplicitTransition(
416     const std::shared_ptr<const RSTransitionEffect>& effect, bool isTransitionIn)
417 {
418     if (globalImplicitParams_.empty()) {
419         ROSEN_LOGE("Failed to begin implicit transition, need to open implicit transition firstly!");
420         return;
421     }
422 
423     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
424     if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
425         ROSEN_LOGE("Wrong type of timing curve!");
426         return;
427     }
428     auto transitionParam = std::make_shared<RSImplicitTransitionParam>(protocol, curve, effect, isTransitionIn);
429     PushImplicitParam(transitionParam);
430 }
431 
EndImplicitTransition()432 void RSImplicitAnimator::EndImplicitTransition()
433 {
434     if (implicitAnimationParams_.empty() ||
435         implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::TRANSITION) {
436         ROSEN_LOGE("Failed to end implicit transition, need to begin implicit transition firstly!");
437         return;
438     }
439 
440     PopImplicitParam();
441 }
442 
PushImplicitParam(const std::shared_ptr<RSImplicitAnimationParam> & implicitParam)443 void RSImplicitAnimator::PushImplicitParam(const std::shared_ptr<RSImplicitAnimationParam>& implicitParam)
444 {
445     implicitAnimationParams_.emplace(implicitParam);
446 }
447 
PopImplicitParam()448 void RSImplicitAnimator::PopImplicitParam()
449 {
450     if (implicitAnimationParams_.empty()) {
451         ROSEN_LOGE("Failed to pop implicit params, params stack is empty!");
452         return;
453     }
454 
455     implicitAnimationParams_.pop();
456 }
457 
CreateImplicitTransition(RSNode & target)458 void RSImplicitAnimator::CreateImplicitTransition(RSNode& target)
459 {
460     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
461         ROSEN_LOGE("Failed to create implicit transition, need to open implicit transition firstly!");
462         return;
463     }
464     auto& params = implicitAnimationParams_.top();
465     if (params->GetType() != ImplicitAnimationParamType::TRANSITION) {
466         ROSEN_LOGE("Failed to create transition, unknow type!");
467         return;
468     }
469     auto transitionImplicitParam = std::static_pointer_cast<RSImplicitTransitionParam>(params);
470     auto transition = transitionImplicitParam->CreateAnimation();
471     if (transition != nullptr) {
472         target.AddAnimation(transition);
473         implicitAnimations_.top().push_back({ transition, target.GetId() });
474     }
475     return;
476 }
477 
CancelImplicitAnimation(const std::shared_ptr<RSNode> & target,const std::shared_ptr<RSPropertyBase> & property)478 void RSImplicitAnimator::CancelImplicitAnimation(
479     const std::shared_ptr<RSNode>& target, const std::shared_ptr<RSPropertyBase>& property)
480 {
481     if (target == nullptr || property == nullptr) {
482         return;
483     }
484     if (!target->HasPropertyAnimation(property->GetId())) {
485         return;
486     }
487     auto params = implicitAnimationParams_.top();
488     if (params->GetType() != ImplicitAnimationParamType::CANCEL) {
489         return;
490     }
491     auto cancelImplicitParam = std::static_pointer_cast<RSImplicitCancelAnimationParam>(params);
492     cancelImplicitParam->AddPropertyToPendingSyncList(property);
493     return;
494 }
495 
SetPropertyValue(std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPropertyBase> & value)496 void RSImplicitAnimator::SetPropertyValue(
497     std::shared_ptr<RSPropertyBase> property, const std::shared_ptr<RSPropertyBase>& value)
498 {
499     if (property != nullptr) {
500         property->SetValue(value);
501     }
502 }
503 
CreateImplicitAnimation(const std::shared_ptr<RSNode> & target,std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)504 void RSImplicitAnimator::CreateImplicitAnimation(const std::shared_ptr<RSNode>& target,
505     std::shared_ptr<RSPropertyBase> property, const std::shared_ptr<RSPropertyBase>& startValue,
506     const std::shared_ptr<RSPropertyBase>& endValue)
507 {
508     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
509         ROSEN_LOGE("Failed to create implicit animation, need to open implicit animation firstly!");
510         return;
511     }
512 
513     if (target == nullptr || property == nullptr || startValue == nullptr || endValue == nullptr) {
514         return;
515     }
516 
517     [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
518     if (protocol.GetRepeatCount() == -1 && property->id_ == 0) {
519         ROSEN_LOGE("Failed to create infinite empty animation!");
520         return;
521     }
522 
523     std::shared_ptr<RSAnimation> animation;
524     auto params = implicitAnimationParams_.top();
525     auto& repeatCallback = std::get<std::shared_ptr<AnimationRepeatCallback>>(globalImplicitParams_.top());
526     switch (params->GetType()) {
527         case ImplicitAnimationParamType::CURVE: {
528             auto curveImplicitParam = static_cast<RSImplicitCurveAnimationParam*>(params.get());
529             animation = curveImplicitParam->CreateAnimation(property, startValue, endValue);
530             break;
531         }
532         case ImplicitAnimationParamType::KEYFRAME: {
533             auto keyframeImplicitParam = static_cast<RSImplicitKeyframeAnimationParam*>(params.get());
534             auto& keyframeAnimations = keyframeAnimations_.top();
535             auto keyframeIter = keyframeAnimations.find({ target->GetId(), property->GetId() });
536             [[maybe_unused]] auto& [isDurationKeyframe, totalDuration, unused] = durationKeyframeParams_.top();
537             SetPropertyValue(property, endValue);
538             if (keyframeIter == keyframeAnimations.end()) {
539                 animation = keyframeImplicitParam->CreateAnimation(property, isDurationKeyframe, totalDuration,
540                     startValue, endValue);
541                 keyframeAnimations[{ target->GetId(), property->GetId() }] = animation;
542             } else {
543                 if (isDurationKeyframe) {
544                     keyframeImplicitParam->AddKeyframe(keyframeIter->second, totalDuration, startValue, endValue);
545                 } else {
546                     keyframeImplicitParam->AddKeyframe(keyframeIter->second, startValue, endValue);
547                 }
548             }
549             break;
550         }
551         case ImplicitAnimationParamType::SPRING: {
552             auto springImplicitParam = static_cast<RSImplicitSpringAnimationParam*>(params.get());
553             animation = springImplicitParam->CreateAnimation(property, startValue, endValue);
554             const auto& finishCallback =
555                 std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
556             if (finishCallback && finishCallback->finishCallbackType_ == FinishCallbackType::LOGICALLY) {
557                 animation->SetZeroThreshold(property->GetThreshold());
558             }
559             break;
560         }
561         case ImplicitAnimationParamType::INTERPOLATING_SPRING: {
562             auto interpolatingSpringImplicitParam =
563                 static_cast<RSImplicitInterpolatingSpringAnimationParam*>(params.get());
564             animation = interpolatingSpringImplicitParam->CreateAnimation(property, startValue, endValue);
565             const auto& finishCallback =
566                 std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
567             if (finishCallback && finishCallback->finishCallbackType_ == FinishCallbackType::LOGICALLY) {
568                 animation->SetZeroThreshold(property->GetThreshold());
569             }
570             break;
571         }
572         case ImplicitAnimationParamType::PATH: {
573             auto pathImplicitParam = static_cast<RSImplicitPathAnimationParam*>(params.get());
574             animation = pathImplicitParam->CreateAnimation(property, startValue, endValue);
575             break;
576         }
577         case ImplicitAnimationParamType::TRANSITION: {
578             auto implicitTransitionParam = static_cast<RSImplicitTransitionParam*>(params.get());
579             animation = implicitTransitionParam->CreateAnimation(property, startValue, endValue);
580             break;
581         }
582         case ImplicitAnimationParamType::CANCEL: {
583             // CreateEmptyAnimation
584             if (property->id_ == 0) {
585                 auto curveImplicitParam = static_cast<RSImplicitCancelAnimationParam*>(params.get());
586                 animation = curveImplicitParam->CreateEmptyAnimation(property, startValue, endValue);
587                 break;
588             }
589 
590             // Create animation with CANCEL type will cancel all running animations of the given property and target.
591             // Note: We are currently in the process of refactoring and accidentally changed the order of animation
592             // callbacks. Originally, the order was OnChange before OnFinish, but we mistakenly changed it to OnFinish
593             // before OnChange. This change has caused some issues, and we need to revert it back to the original order.
594             // However, before fixing this, we discovered that there are some changes in arkui that rely on this 'bug'.
595             // If we change it back to the original order, it will break the list swipe animation. Therefore, we need
596             // to carefully consider the implications of this change before proceeding.
597             if (property->GetIsCustom()) {
598                 property->SetValue(endValue);                         // update set ui value
599                 property->UpdateCustomAnimation();                    // force sync RS value for custom property
600                 target->CancelAnimationByProperty(property->GetId()); // finish all ui animation
601             } else {
602                 target->FinishAnimationByProperty(property->GetId()); // finish all ui animation
603                 property->SetValue(endValue);                         // update set ui value
604                 property->UpdateOnAllAnimationFinish();               // force sync RS value for native property
605             }
606             return;
607         }
608         default:
609             ROSEN_LOGE("Failed to create animation, unknow type!");
610             break;
611     }
612 
613     if (animation == nullptr) {
614         ROSEN_LOGD("Failed to create animation!");
615         return;
616     }
617     if (repeatCallback != nullptr) {
618         animation->SetRepeatCallback(std::move(repeatCallback));
619         repeatCallback.reset();
620     }
621 
622     RSAnimationTraceUtils::GetInstance().addAnimationCreateTrace(
623         target->GetId(), target->GetNodeName(), property->GetId(),
624         animation->GetId(), static_cast<int>(params->GetType()), static_cast<int>(property->type_),
625         startValue->GetRenderProperty(), endValue->GetRenderProperty(), animation->GetStartDelay(),
626         animation->GetDuration(), protocol.GetRepeatCount());
627 
628     if (params->GetType() == ImplicitAnimationParamType::TRANSITION ||
629         params->GetType() == ImplicitAnimationParamType::KEYFRAME) {
630         // for transition this will create custom transition animation, there is no need to add it to target.
631         // for keyframe animations, we don't add it to target now, we will add it later in
632         // RSImplicitAnimator::CloseImplicitAnimation.
633         return;
634     }
635     target->AddAnimation(animation, !isAddInteractiveAnimator_);
636     implicitAnimations_.top().emplace_back(animation, target->GetId());
637     return;
638 }
639 
ExecuteWithoutAnimation(const std::function<void ()> & callback)640 void RSImplicitAnimator::ExecuteWithoutAnimation(const std::function<void()>& callback)
641 {
642     if (callback == nullptr) {
643         return;
644     }
645     // disable implicit animation and execute callback, restore previous state after callback.
646     auto implicitAnimationDisabled = implicitAnimationDisabled_;
647     implicitAnimationDisabled_ = true;
648     callback();
649     implicitAnimationDisabled_ = implicitAnimationDisabled;
650 }
651 
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)652 void RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity(const std::shared_ptr<RSNode>& target,
653     const std::shared_ptr<RSPropertyBase>& property, const std::shared_ptr<RSPropertyBase>& startValue,
654     const std::shared_ptr<RSPropertyBase>& endValue, const std::shared_ptr<RSPropertyBase>& velocity)
655 {
656     if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
657         ROSEN_LOGE("RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity:Failed to create implicit "
658                    "animation, need to open implicit animation firstly!");
659         return;
660     }
661 
662     if (target == nullptr || property == nullptr) {
663         ROSEN_LOGE(
664             "RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity:target node or property is a nullptr.");
665         return;
666     }
667 
668     std::shared_ptr<RSAnimation> animation;
669     auto params = implicitAnimationParams_.top();
670     if (!params || params->GetType() != ImplicitAnimationParamType::SPRING) {
671         ROSEN_LOGE(
672             "RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity:the parameters of animations are invalid.");
673         return;
674     }
675 
676     auto springImplicitParam = static_cast<RSImplicitSpringAnimationParam*>(params.get());
677     if (!springImplicitParam) {
678         ROSEN_LOGE("RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity:the parameter of spring animations "
679                    "is null.");
680         return;
681     }
682 
683     animation = springImplicitParam->CreateAnimation(property, startValue, endValue);
684     if (!animation) {
685         ROSEN_LOGE("RSImplicitAnimator::CreateImplicitAnimationWithInitialVelocity: failed to create animation.");
686         return;
687     }
688 
689     animation->SetInitialVelocity(velocity);
690     const auto& finishCallback = std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
691     if (finishCallback && finishCallback->finishCallbackType_ == FinishCallbackType::LOGICALLY) {
692         animation->SetZeroThreshold(property->GetThreshold());
693     }
694 
695     auto& repeatCallback = std::get<std::shared_ptr<AnimationRepeatCallback>>(globalImplicitParams_.top());
696     if (repeatCallback) {
697         animation->SetRepeatCallback(std::move(repeatCallback));
698         repeatCallback.reset();
699     }
700 
701     auto protocol = std::get<RSAnimationTimingProtocol>(globalImplicitParams_.top());
702     RSAnimationTraceUtils::GetInstance().addAnimationCreateTrace(
703         target->GetId(), target->GetNodeName(), property->GetId(),
704         animation->GetId(), static_cast<int>(params->GetType()), static_cast<int>(property->type_),
705         startValue->GetRenderProperty(), endValue->GetRenderProperty(), animation->GetStartDelay(),
706         animation->GetDuration(), protocol.GetRepeatCount());
707 
708     target->AddAnimation(animation);
709     implicitAnimations_.top().emplace_back(animation, target->GetId());
710 }
711 } // namespace Rosen
712 } // namespace OHOS
713