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