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