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