• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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