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