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