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 switch (timingCurve.type_) {
39 case RSAnimationTimingCurve::CurveType::INTERPOLATING:
40 BeginImplicitCurveAnimation();
41 break;
42 case RSAnimationTimingCurve::CurveType::SPRING:
43 BeginImplicitSpringAnimation();
44 break;
45 case RSAnimationTimingCurve::CurveType::INTERPOLATING_SPRING:
46 BeginImplicitInterpolatingSpringAnimation();
47 break;
48 default:
49 ROSEN_LOGE("Wrong type of timing curve!");
50 return 0;
51 }
52 return static_cast<int>(globalImplicitParams_.size()) - 1;
53 }
54
OpenImplicitAnimation(const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve,std::shared_ptr<AnimationFinishCallback> && finishCallback)55 int RSImplicitAnimator::OpenImplicitAnimation(const RSAnimationTimingProtocol& timingProtocol,
56 const RSAnimationTimingCurve& timingCurve, std::shared_ptr<AnimationFinishCallback>&& finishCallback)
57 {
58 return OpenImplicitAnimation(timingProtocol, timingCurve, std::move(finishCallback), nullptr);
59 }
60
OpenImplicitAnimation(std::shared_ptr<AnimationFinishCallback> && finishCallback)61 int RSImplicitAnimator::OpenImplicitAnimation(std::shared_ptr<AnimationFinishCallback>&& finishCallback)
62 {
63 if (globalImplicitParams_.empty()) {
64 // if current implicit animation params is empty, use default params, if no animation created, call finish
65 // callback immediately
66 return OpenImplicitAnimation(
67 RSAnimationTimingProtocol::IMMEDIATE, RSAnimationTimingCurve::LINEAR, std::move(finishCallback));
68 } else {
69 // copy current implicit animation params and replace finish callback
70 [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
71 return OpenImplicitAnimation(protocol, curve, std::move(finishCallback));
72 }
73 }
74
OpenImplicitAnimation(const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve)75 int RSImplicitAnimator::OpenImplicitAnimation(
76 const RSAnimationTimingProtocol& timingProtocol, const RSAnimationTimingCurve& timingCurve)
77 {
78 if (globalImplicitParams_.empty()) {
79 // current implicit animation params is empty, use empty
80 return OpenImplicitAnimation(timingProtocol, timingCurve, nullptr);
81 } else {
82 // copy current implicit animation callback and replace timing protocol and curve
83 [[maybe_unused]] const auto& [protocol, curve, callback, unused_repeatCallback] = globalImplicitParams_.top();
84 auto copyOfCallback = callback;
85 return OpenImplicitAnimation(timingProtocol, timingCurve, std::move(copyOfCallback));
86 }
87 }
88
CloseImplicitAnimation()89 std::vector<std::shared_ptr<RSAnimation>> RSImplicitAnimator::CloseImplicitAnimation()
90 {
91 if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
92 ROSEN_LOGE("Failed to close implicit animation, need to open implicit animation firstly!");
93 return {};
94 }
95
96 const auto& finishCallback = std::get<const std::shared_ptr<AnimationFinishCallback>>(globalImplicitParams_.top());
97 auto& currentAnimations = implicitAnimations_.top();
98 auto& currentKeyframeAnimations = keyframeAnimations_.top();
99 // if no implicit animation created
100 if (currentAnimations.empty() && currentKeyframeAnimations.empty()) {
101 // If finish callback either 1. is null or 2. is referenced by any animation or implicitly parameters, we don't
102 // do anything.
103 if (finishCallback.use_count() != 1) {
104 globalImplicitParams_.pop();
105 implicitAnimations_.pop();
106 keyframeAnimations_.pop();
107 EndImplicitAnimation();
108 return {};
109 }
110 // we are the only one who holds the finish callback, if the callback is NOT timing sensitive, we need to
111 // execute it asynchronously, in order to avoid timing issues.
112 if (finishCallback->isTimingSensitive_ == false) {
113 ROSEN_LOGD("RSImplicitAnimator::CloseImplicitAnimation, No implicit animations created, execute finish "
114 "callback asynchronously");
115 RSUIDirector::PostTask([finishCallback]() { finishCallback->Execute(); });
116 globalImplicitParams_.pop();
117 implicitAnimations_.pop();
118 keyframeAnimations_.pop();
119 EndImplicitAnimation();
120 return {};
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 }
128
129 std::vector<std::shared_ptr<RSAnimation>> resultAnimations;
130 for (const auto& [animationInfo, keyframeAnimation] : currentKeyframeAnimations) {
131 auto target = RSNodeMap::Instance().GetNode<RSNode>(animationInfo.first);
132 if (target == nullptr) {
133 ROSEN_LOGE("Failed to start implicit keyframe animation[%" PRIu64 "], target is null!",
134 keyframeAnimation->GetId());
135 continue;
136 }
137 // this will actually create the RSRenderKeyframeAnimation
138 target->AddAnimation(keyframeAnimation);
139 keyframeAnimation->SetFinishCallback(finishCallback);
140 resultAnimations.emplace_back(keyframeAnimation);
141 }
142
143 for (const auto& [animation, nodeId] : currentAnimations) {
144 animation->SetFinishCallback(finishCallback);
145 resultAnimations.emplace_back(animation);
146 }
147
148 globalImplicitParams_.pop();
149 implicitAnimations_.pop();
150 keyframeAnimations_.pop();
151 EndImplicitAnimation();
152 return resultAnimations;
153 }
154
BeginImplicitKeyFrameAnimation(float fraction,const RSAnimationTimingCurve & timingCurve)155 void RSImplicitAnimator::BeginImplicitKeyFrameAnimation(float fraction, const RSAnimationTimingCurve& timingCurve)
156 {
157 if (globalImplicitParams_.empty()) {
158 ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
159 return;
160 }
161
162 if (timingCurve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
163 ROSEN_LOGE("Wrong type of timing curve!");
164 return;
165 }
166
167 [[maybe_unused]] const auto& [protocol, unused_curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
168 auto keyframeAnimationParam = std::make_shared<RSImplicitKeyframeAnimationParam>(protocol, timingCurve, fraction);
169 PushImplicitParam(keyframeAnimationParam);
170 }
171
BeginImplicitKeyFrameAnimation(float fraction)172 void RSImplicitAnimator::BeginImplicitKeyFrameAnimation(float fraction)
173 {
174 if (globalImplicitParams_.empty()) {
175 ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
176 return;
177 }
178
179 BeginImplicitKeyFrameAnimation(fraction, std::get<RSAnimationTimingCurve>(globalImplicitParams_.top()));
180 }
181
EndImplicitKeyFrameAnimation()182 void RSImplicitAnimator::EndImplicitKeyFrameAnimation()
183 {
184 if (implicitAnimationParams_.empty() ||
185 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::KEYFRAME) {
186 ROSEN_LOGE("Failed to end keyframe implicit animation, need to begin keyframe implicit animation firstly!");
187 return;
188 }
189
190 PopImplicitParam();
191 }
192
NeedImplicitAnimation()193 bool RSImplicitAnimator::NeedImplicitAnimation()
194 {
195 return !implicitAnimationDisabled_ && !implicitAnimationParams_.empty();
196 }
197
BeginImplicitCurveAnimation()198 void RSImplicitAnimator::BeginImplicitCurveAnimation()
199 {
200 // params sanity already checked in BeginImplicitAnimation, no need to check again.
201 [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
202 auto curveAnimationParam = std::make_shared<RSImplicitCurveAnimationParam>(protocol, curve);
203 PushImplicitParam(curveAnimationParam);
204 }
205
EndImplicitAnimation()206 void RSImplicitAnimator::EndImplicitAnimation()
207 {
208 if (implicitAnimationParams_.empty() ||
209 (implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::CURVE &&
210 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::SPRING &&
211 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::INTERPOLATING_SPRING)) {
212 ROSEN_LOGE("Failed to end implicit animation, need to begin implicit animation firstly!");
213 return;
214 }
215
216 PopImplicitParam();
217 }
218
BeginImplicitPathAnimation(const std::shared_ptr<RSMotionPathOption> & motionPathOption)219 void RSImplicitAnimator::BeginImplicitPathAnimation(const std::shared_ptr<RSMotionPathOption>& motionPathOption)
220 {
221 if (globalImplicitParams_.empty()) {
222 ROSEN_LOGE("Failed to begin path implicit animation, need to open implicit animation firstly!");
223 return;
224 }
225
226 [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
227 if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
228 ROSEN_LOGE("Wrong type of timing curve!");
229 return;
230 }
231 auto pathAnimationParam = std::make_shared<RSImplicitPathAnimationParam>(protocol, curve, motionPathOption);
232 PushImplicitParam(pathAnimationParam);
233 }
234
EndImplicitPathAnimation()235 void RSImplicitAnimator::EndImplicitPathAnimation()
236 {
237 if (implicitAnimationParams_.empty() ||
238 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::PATH) {
239 ROSEN_LOGE("Failed to end path implicit animation, need to begin path implicit animation firstly!");
240 return;
241 }
242
243 PopImplicitParam();
244 }
245
BeginImplicitSpringAnimation()246 void RSImplicitAnimator::BeginImplicitSpringAnimation()
247 {
248 // params sanity already checked in BeginImplicitAnimation, no need to check again.
249 [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
250 auto springParam = std::make_shared<RSImplicitSpringAnimationParam>(protocol, curve);
251 PushImplicitParam(springParam);
252 }
253
BeginImplicitInterpolatingSpringAnimation()254 void RSImplicitAnimator::BeginImplicitInterpolatingSpringAnimation()
255 {
256 // params sanity already checked in BeginImplicitAnimation, no need to check again.
257 [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
258 auto interpolatingSpringParam = std::make_shared<RSImplicitInterpolatingSpringAnimationParam>(protocol, curve);
259 PushImplicitParam(interpolatingSpringParam);
260 }
261
BeginImplicitTransition(const std::shared_ptr<const RSTransitionEffect> & effect,bool isTransitionIn)262 void RSImplicitAnimator::BeginImplicitTransition(
263 const std::shared_ptr<const RSTransitionEffect>& effect, bool isTransitionIn)
264 {
265 if (globalImplicitParams_.empty()) {
266 ROSEN_LOGE("Failed to begin implicit transition, need to open implicit transition firstly!");
267 return;
268 }
269
270 [[maybe_unused]] const auto& [protocol, curve, unused, unused_repeatCallback] = globalImplicitParams_.top();
271 if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
272 ROSEN_LOGE("Wrong type of timing curve!");
273 return;
274 }
275 auto transitionParam = std::make_shared<RSImplicitTransitionParam>(protocol, curve, effect, isTransitionIn);
276 PushImplicitParam(transitionParam);
277 }
278
EndImplicitTransition()279 void RSImplicitAnimator::EndImplicitTransition()
280 {
281 if (implicitAnimationParams_.empty() ||
282 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::TRANSITION) {
283 ROSEN_LOGE("Failed to end implicit transition, need to begin implicit transition firstly!");
284 return;
285 }
286
287 PopImplicitParam();
288 }
289
PushImplicitParam(const std::shared_ptr<RSImplicitAnimationParam> & implicitParam)290 void RSImplicitAnimator::PushImplicitParam(const std::shared_ptr<RSImplicitAnimationParam>& implicitParam)
291 {
292 implicitAnimationParams_.emplace(implicitParam);
293 }
294
PopImplicitParam()295 void RSImplicitAnimator::PopImplicitParam()
296 {
297 if (implicitAnimationParams_.empty()) {
298 ROSEN_LOGE("Failed to pop implicit params, params stack is empty!");
299 return;
300 }
301
302 implicitAnimationParams_.pop();
303 }
304
CreateImplicitTransition(RSNode & target)305 void RSImplicitAnimator::CreateImplicitTransition(RSNode& target)
306 {
307 if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
308 ROSEN_LOGE("Failed to create implicit transition, need to open implicit transition firstly!");
309 return;
310 }
311 auto& params = implicitAnimationParams_.top();
312 if (params->GetType() != ImplicitAnimationParamType::TRANSITION) {
313 ROSEN_LOGE("Failed to create transition, unknow type!");
314 return;
315 }
316 auto transitionImplicitParam = std::static_pointer_cast<RSImplicitTransitionParam>(params);
317 auto transition = transitionImplicitParam->CreateAnimation();
318 if (transition != nullptr) {
319 target.AddAnimation(transition);
320 implicitAnimations_.top().push_back({ transition, target.GetId() });
321 }
322 return;
323 }
324
CreateEmptyAnimation()325 void RSImplicitAnimator::CreateEmptyAnimation()
326 {
327 auto target = RSNodeMap::Instance().GetAnimationFallbackNode();
328 if (target == nullptr) {
329 ROSEN_LOGE("RSImplicitAnimator::CreateEmptyAnimation, target is nullptr");
330 return;
331 }
332 std::shared_ptr<RSAnimatableProperty<float>> property = std::make_shared<RSAnimatableProperty<float>>(0.f);
333 property->id_ = 0;
334 // The spring animation will stop when the oscillation amplitude is less than 1/256. Setting this end value is to
335 // make the spring animation stop at an appropriate time and call the callback function.
336 auto endValue = std::make_shared<RSAnimatableProperty<float>>(100.0); // 100: for spring animation stop timing
337 auto startValue = std::make_shared<RSAnimatableProperty<float>>(0.f);
338 CreateImplicitAnimation(target, property, startValue, endValue);
339 return;
340 }
341
SetPropertyValue(std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPropertyBase> & value)342 void RSImplicitAnimator::SetPropertyValue(
343 std::shared_ptr<RSPropertyBase> property, const std::shared_ptr<RSPropertyBase>& value)
344 {
345 if (property != nullptr) {
346 property->SetValue(value);
347 }
348 }
349
CreateImplicitAnimation(const std::shared_ptr<RSNode> & target,std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)350 void RSImplicitAnimator::CreateImplicitAnimation(const std::shared_ptr<RSNode>& target,
351 std::shared_ptr<RSPropertyBase> property, const std::shared_ptr<RSPropertyBase>& startValue,
352 const std::shared_ptr<RSPropertyBase>& endValue)
353 {
354 if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
355 ROSEN_LOGE("Failed to create implicit animation, need to open implicit animation firstly!");
356 return;
357 }
358
359 if (target == nullptr || property == nullptr) {
360 return;
361 }
362
363 std::shared_ptr<RSAnimation> animation;
364 auto params = implicitAnimationParams_.top();
365 auto& repeatCallback = std::get<std::shared_ptr<AnimationRepeatCallback>>(globalImplicitParams_.top());
366 switch (params->GetType()) {
367 case ImplicitAnimationParamType::CURVE: {
368 auto curveImplicitParam = static_cast<RSImplicitCurveAnimationParam*>(params.get());
369 animation = curveImplicitParam->CreateAnimation(property, startValue, endValue);
370 break;
371 }
372 case ImplicitAnimationParamType::KEYFRAME: {
373 auto keyframeImplicitParam = static_cast<RSImplicitKeyframeAnimationParam*>(params.get());
374 auto& keyframeAnimations = keyframeAnimations_.top();
375 auto keyframeIter = keyframeAnimations.find({ target->GetId(), property->GetId() });
376 SetPropertyValue(property, endValue);
377 if (keyframeIter == keyframeAnimations.end()) {
378 animation = keyframeImplicitParam->CreateAnimation(property, startValue, endValue);
379 keyframeAnimations[{ target->GetId(), property->GetId() }] = animation;
380 } else {
381 keyframeImplicitParam->AddKeyframe(keyframeIter->second, startValue, endValue);
382 }
383 if (animation == nullptr) {
384 ROSEN_LOGE("Failed to create animation!");
385 return;
386 }
387 if (repeatCallback != nullptr) {
388 animation->SetRepeatCallback(std::move(repeatCallback));
389 repeatCallback.reset();
390 }
391 // for keyframe animations, we don't add it to target now, we will add it later in
392 // RSImplicitAnimator::CloseImplicitAnimation.
393 return;
394 }
395 case ImplicitAnimationParamType::SPRING: {
396 auto springImplicitParam = static_cast<RSImplicitSpringAnimationParam*>(params.get());
397 animation = springImplicitParam->CreateAnimation(property, startValue, endValue);
398 break;
399 }
400 case ImplicitAnimationParamType::INTERPOLATING_SPRING: {
401 auto interpolatingSpringImplicitParam =
402 static_cast<RSImplicitInterpolatingSpringAnimationParam*>(params.get());
403 animation = interpolatingSpringImplicitParam->CreateAnimation(property, startValue, endValue);
404 break;
405 }
406 case ImplicitAnimationParamType::PATH: {
407 auto pathImplicitParam = static_cast<RSImplicitPathAnimationParam*>(params.get());
408 animation = pathImplicitParam->CreateAnimation(property, startValue, endValue);
409 break;
410 }
411 case ImplicitAnimationParamType::TRANSITION: {
412 auto implicitTransitionParam = static_cast<RSImplicitTransitionParam*>(params.get());
413 animation = implicitTransitionParam->CreateAnimation(property, startValue, endValue);
414 if (animation == nullptr) {
415 ROSEN_LOGE("Failed to create animation!");
416 return;
417 }
418 if (repeatCallback != nullptr) {
419 animation->SetRepeatCallback(std::move(repeatCallback));
420 repeatCallback.reset();
421 }
422 // this will create custom transition animation, there is no need to add it to target.
423 return;
424 }
425 default:
426 ROSEN_LOGE("Failed to create animation, unknow type!");
427 break;
428 }
429
430 if (animation == nullptr) {
431 ROSEN_LOGE("Failed to create animation!");
432 return;
433 }
434 if (repeatCallback != nullptr) {
435 animation->SetRepeatCallback(std::move(repeatCallback));
436 repeatCallback.reset();
437 }
438 target->AddAnimation(animation);
439 implicitAnimations_.top().emplace_back(animation, target->GetId());
440
441 return;
442 }
443
ExecuteWithoutAnimation(const std::function<void ()> & callback)444 void RSImplicitAnimator::ExecuteWithoutAnimation(const std::function<void()>& callback)
445 {
446 if (callback == nullptr) {
447 return;
448 }
449 // disable implicit animation and execute callback, restore previous state after callback.
450 auto implicitAnimationDisabled = implicitAnimationDisabled_;
451 implicitAnimationDisabled_ = true;
452 callback();
453 implicitAnimationDisabled_ = implicitAnimationDisabled;
454 }
455 } // namespace Rosen
456 } // namespace OHOS
457