• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "render_service_client/core/animation/rs_interactive_implict_animator.h"
17 
18 #include "core/animation/native_curve_helper.h"
19 #include "core/common/container.h"
20 #include "core/components_ng/animation/callback_thread_wrapper.h"
21 #include "core/pipeline_ng/pipeline_context.h"
22 #include "render_service_client/core/ui/rs_ui_director.h"
23 
24 namespace OHOS::Ace {
25 
26 namespace {
ToAnimationFinishCallbackType(const FinishCallbackType finishCallbackType)27 Rosen::FinishCallbackType ToAnimationFinishCallbackType(const FinishCallbackType finishCallbackType)
28 {
29     if (finishCallbackType == FinishCallbackType::LOGICALLY) {
30         return Rosen::FinishCallbackType::LOGICALLY;
31     } else if (finishCallbackType == FinishCallbackType::REMOVED) {
32         return Rosen::FinishCallbackType::TIME_SENSITIVE;
33     } else {
34         return Rosen::FinishCallbackType::TIME_SENSITIVE;
35     }
36 }
OptionToTimingProtocol(const AnimationOption & option)37 Rosen::RSAnimationTimingProtocol OptionToTimingProtocol(const AnimationOption& option)
38 {
39     Rosen::RSAnimationTimingProtocol timingProtocol;
40     timingProtocol.SetDuration(option.GetDuration());
41     timingProtocol.SetStartDelay(option.GetDelay());
42     timingProtocol.SetSpeed(option.GetTempo());
43     timingProtocol.SetRepeatCount(option.GetIteration());
44     timingProtocol.SetDirection(option.GetAnimationDirection() == AnimationDirection::NORMAL ||
45                                 option.GetAnimationDirection() == AnimationDirection::ALTERNATE);
46     timingProtocol.SetAutoReverse(option.GetAnimationDirection() == AnimationDirection::ALTERNATE ||
47                                   option.GetAnimationDirection() == AnimationDirection::ALTERNATE_REVERSE);
48     timingProtocol.SetFillMode(static_cast<Rosen::FillMode>(option.GetFillMode()));
49     timingProtocol.SetFinishCallbackType(ToAnimationFinishCallbackType(option.GetFinishCallbackType()));
50     timingProtocol.SetInterfaceName(option.GetAnimationInterfaceString());
51     auto rateRange = option.GetFrameRateRange();
52     if (rateRange) {
53         timingProtocol.SetFrameRateRange({ rateRange->min_, rateRange->max_, rateRange->preferred_, 0,
54             static_cast<Rosen::ComponentScene>(rateRange->componentScene_) });
55     }
56     return timingProtocol;
57 }
GetWrappedCallback(const std::function<void ()> & callback,bool once,const RefPtr<PipelineBase> & pipeline)58 std::function<void()> GetWrappedCallback(
59     const std::function<void()>& callback, bool once, const RefPtr<PipelineBase>& pipeline)
60 {
61     CHECK_NULL_RETURN(callback, nullptr);
62     auto instanceId = pipeline ? pipeline->GetInstanceId() : Container::CurrentIdSafelyWithCheck();
63     ContainerScope scope(instanceId);
64     auto taskExecutor = Container::CurrentTaskExecutor();
65     CHECK_NULL_RETURN(taskExecutor, callback);
66     NG::CallbackThreadWrapper callbackWrapper { taskExecutor, callback, once };
67     auto wrappedCallback = [callbackWrapper, instanceId]() mutable {
68         ContainerScope scope(instanceId);
69         auto taskExecutor = Container::CurrentTaskExecutor();
70         if (!taskExecutor) {
71             TAG_LOGW(AceLogTag::ACE_ANIMATION, "taskExecutor is nullptr");
72             return;
73         }
74         if (taskExecutor->WillRunOnCurrentThread(TaskExecutor::TaskType::UI)) {
75             callbackWrapper();
76             return;
77         }
78         taskExecutor->PostTask([callbackWrapper] () mutable { callbackWrapper(); }, TaskExecutor::TaskType::UI,
79             "ArkUIAnimationGetWrappedCallback", PriorityType::HIGH);
80     };
81     return wrappedCallback;
82 }
83 
GetRSUIContext(const RefPtr<PipelineBase> & context)84 std::shared_ptr<Rosen::RSUIContext> GetRSUIContext(const RefPtr<PipelineBase>& context)
85 {
86     return AnimationUtils::GetCurrentRSUIContext(context);
87 }
88 } // namespace
89 
90 class AnimationUtils::Animation {
91 private:
92     std::vector<std::shared_ptr<OHOS::Rosen::RSAnimation>> animations_;
93 
94     friend AnimationUtils;
95 };
96 
97 class AnimationUtils::InteractiveAnimation {
98 private:
99     std::shared_ptr<Rosen::RSInteractiveImplictAnimator> interactiveAnimation_;
100     friend AnimationUtils;
101 };
102 
SetNavGroupNodeTransAnimationCallback()103 void AnimationUtils::SetNavGroupNodeTransAnimationCallback()
104 {
105     auto pipelineContext = NG::PipelineContext::GetCurrentContext();
106     CHECK_NULL_VOID(pipelineContext);
107     auto navigationManger = pipelineContext->GetNavigationManager();
108     CHECK_NULL_VOID(navigationManger);
109     navigationManger->SetNodeAddAnimation(true);
110 }
111 
OpenImplicitAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback,const RefPtr<PipelineBase> & context)112 void AnimationUtils::OpenImplicitAnimation(const AnimationOption& option, const RefPtr<Curve>& curve,
113     const std::function<void()>& finishCallback, const RefPtr<PipelineBase>& context)
114 {
115     const auto& timingProtocol = OptionToTimingProtocol(option);
116     auto wrappedOnFinish = GetWrappedCallback(finishCallback, true, context);
117     auto rsUIContext = GetRSUIContext(context);
118     Rosen::RSNode::OpenImplicitAnimation(rsUIContext, timingProtocol,
119         NativeCurveHelper::ToNativeCurve(curve), wrappedOnFinish);
120 }
121 
CloseImplicitAnimation(const RefPtr<PipelineBase> & context)122 bool AnimationUtils::CloseImplicitAnimation(const RefPtr<PipelineBase>& context)
123 {
124     auto rsUIContext = GetRSUIContext(context);
125     auto animations = Rosen::RSNode::CloseImplicitAnimation(rsUIContext);
126     auto pipeline = context ? context : PipelineBase::GetCurrentContext();
127     SetNavGroupNodeTransAnimationCallback();
128     if (pipeline && !pipeline->GetOnShow()) {
129         pipeline->FlushMessages();
130     }
131     return !animations.empty();
132 }
133 
CloseImplicitCancelAnimation(const RefPtr<PipelineBase> & context)134 bool AnimationUtils::CloseImplicitCancelAnimation(const RefPtr<PipelineBase>& context)
135 {
136     auto rsUIContext = GetRSUIContext(context);
137     return Rosen::RSNode::CloseImplicitCancelAnimation(rsUIContext);
138 }
139 
CloseImplicitCancelAnimationReturnStatus(const RefPtr<PipelineBase> & context)140 CancelAnimationStatus AnimationUtils::CloseImplicitCancelAnimationReturnStatus(const RefPtr<PipelineBase>& context)
141 {
142     auto rsUIContext = GetRSUIContext(context);
143     auto status = Rosen::RSNode::CloseImplicitCancelAnimationReturnStatus(rsUIContext);
144     return static_cast<CancelAnimationStatus>(status);
145 }
146 
IsImplicitAnimationOpen(const RefPtr<PipelineBase> & context)147 bool AnimationUtils::IsImplicitAnimationOpen(const RefPtr<PipelineBase>& context)
148 {
149     auto rsUIContext = GetRSUIContext(context);
150     return Rosen::RSNode::IsImplicitAnimationOpen(rsUIContext);
151 }
152 
Animate(const AnimationOption & option,const PropertyCallback & callback,const FinishCallback & finishCallback,const RepeatCallback & repeatCallback,const RefPtr<PipelineBase> & context)153 void AnimationUtils::Animate(const AnimationOption& option, const PropertyCallback& callback,
154     const FinishCallback& finishCallback, const RepeatCallback& repeatCallback, const RefPtr<PipelineBase>& context)
155 {
156     const auto& timingProtocol = OptionToTimingProtocol(option);
157     auto wrappedOnFinish = GetWrappedCallback(finishCallback, true, context);
158     auto wrappedOnRepeat = GetWrappedCallback(repeatCallback, false, context);
159     auto rsUIContext = GetRSUIContext(context);
160     Rosen::RSNode::Animate(rsUIContext, timingProtocol, NativeCurveHelper::ToNativeCurve(option.GetCurve()), callback,
161         wrappedOnFinish, wrappedOnRepeat);
162     auto pipeline = context ? context : PipelineBase::GetCurrentContext();
163     SetNavGroupNodeTransAnimationCallback();
164     if (pipeline && !pipeline->GetOnShow()) {
165         pipeline->FlushMessages();
166     }
167 }
168 
AnimateWithCurrentOptions(const PropertyCallback & callback,const FinishCallback & finishCallback,bool timingSensitive,const RefPtr<PipelineBase> & context)169 void AnimationUtils::AnimateWithCurrentOptions(const PropertyCallback& callback, const FinishCallback& finishCallback,
170     bool timingSensitive, const RefPtr<PipelineBase>& context)
171 {
172     auto wrappedOnFinish = GetWrappedCallback(finishCallback, true, context);
173     auto rsUIContext = GetRSUIContext(context);
174     Rosen::RSNode::AnimateWithCurrentOptions(rsUIContext, callback, wrappedOnFinish, timingSensitive);
175 }
176 
AnimateWithCurrentCallback(const AnimationOption & option,const PropertyCallback & callback,const RefPtr<PipelineBase> & context)177 void AnimationUtils::AnimateWithCurrentCallback(const AnimationOption& option, const PropertyCallback& callback,
178     const RefPtr<PipelineBase>& context)
179 {
180     const auto& timingProtocol = OptionToTimingProtocol(option);
181     auto rsUIContext = GetRSUIContext(context);
182     Rosen::RSNode::AnimateWithCurrentCallback(rsUIContext,
183         timingProtocol, NativeCurveHelper::ToNativeCurve(option.GetCurve()), callback);
184 }
185 
AddKeyFrame(float fraction,const RefPtr<Curve> & curve,const PropertyCallback & callback,const RefPtr<PipelineBase> & context)186 void AnimationUtils::AddKeyFrame(float fraction, const RefPtr<Curve>& curve, const PropertyCallback& callback,
187     const RefPtr<PipelineBase>& context)
188 {
189     auto rsUIContext = GetRSUIContext(context);
190     Rosen::RSNode::AddKeyFrame(rsUIContext, fraction, NativeCurveHelper::ToNativeCurve(curve), callback);
191 }
192 
AddKeyFrame(float fraction,const PropertyCallback & callback,const RefPtr<PipelineBase> & context)193 void AnimationUtils::AddKeyFrame(float fraction, const PropertyCallback& callback,
194     const RefPtr<PipelineBase>& context)
195 {
196     auto rsUIContext = GetRSUIContext(context);
197     Rosen::RSNode::AddKeyFrame(rsUIContext, fraction, callback);
198 }
199 
AddDurationKeyFrame(int duration,const RefPtr<Curve> & curve,const PropertyCallback & callback,const RefPtr<PipelineBase> & context)200 void AnimationUtils::AddDurationKeyFrame(int duration, const RefPtr<Curve>& curve, const PropertyCallback& callback,
201     const RefPtr<PipelineBase>& context)
202 {
203     auto rsUIContext = GetRSUIContext(context);
204     Rosen::RSNode::AddDurationKeyFrame(rsUIContext, duration, NativeCurveHelper::ToNativeCurve(curve), callback);
205 }
206 
StartAnimation(const AnimationOption & option,const PropertyCallback & callback,const FinishCallback & finishCallback,const RepeatCallback & repeatCallback,const RefPtr<PipelineBase> & context)207 std::shared_ptr<AnimationUtils::Animation> AnimationUtils::StartAnimation(
208     const AnimationOption& option, const PropertyCallback& callback,
209     const FinishCallback& finishCallback, const RepeatCallback& repeatCallback, const RefPtr<PipelineBase>& context)
210 {
211     std::shared_ptr<AnimationUtils::Animation> animation = std::make_shared<AnimationUtils::Animation>();
212     CHECK_NULL_RETURN(animation, nullptr);
213     const auto& timingProtocol = OptionToTimingProtocol(option);
214     auto wrappedOnFinish = GetWrappedCallback(finishCallback, true, context);
215     auto wrappedOnRepeat = GetWrappedCallback(repeatCallback, false, context);
216     auto rsUIContext = GetRSUIContext(context);
217     animation->animations_ = Rosen::RSNode::Animate(rsUIContext, timingProtocol,
218         NativeCurveHelper::ToNativeCurve(option.GetCurve()), callback, wrappedOnFinish, wrappedOnRepeat);
219     auto pipeline = context ? context : PipelineBase::GetCurrentContext();
220     if (pipeline && !pipeline->GetOnShow()) {
221         pipeline->FlushMessages();
222     }
223     if (!animation->animations_.empty()) {
224         return animation;
225     }
226     return nullptr;
227 }
228 
StopAnimation(const std::shared_ptr<AnimationUtils::Animation> & animation)229 void AnimationUtils::StopAnimation(const std::shared_ptr<AnimationUtils::Animation>& animation)
230 {
231     CHECK_NULL_VOID(animation);
232     if (!animation->animations_.empty()) {
233         for (auto& ani : animation->animations_) {
234             ani->Finish();
235         }
236         animation->animations_.clear();
237     }
238 }
239 
BlendBgColorAnimation(RefPtr<NG::RenderContext> & renderContext,const Color & endColor,int32_t duration,const RefPtr<Curve> & curve)240 void AnimationUtils::BlendBgColorAnimation(
241     RefPtr<NG::RenderContext>& renderContext, const Color& endColor, int32_t duration, const RefPtr<Curve>& curve)
242 {
243     AnimationOption option = AnimationOption();
244     option.SetCurve(curve);
245     option.SetDuration(duration);
246     AnimationUtils::Animate(option, [context = renderContext, color = endColor]() { context->BlendBgColor(color); });
247 }
248 
PauseAnimation(const std::shared_ptr<AnimationUtils::Animation> & animation)249 void AnimationUtils::PauseAnimation(const std::shared_ptr<AnimationUtils::Animation>& animation)
250 {
251     CHECK_NULL_VOID(animation);
252     for (auto& ani : animation->animations_) {
253         ani->Pause();
254     }
255     auto pipeline = PipelineBase::GetCurrentContext();
256     if (pipeline && !pipeline->GetOnShow()) {
257         pipeline->FlushMessages();
258     }
259 }
260 
ResumeAnimation(const std::shared_ptr<AnimationUtils::Animation> & animation)261 void AnimationUtils::ResumeAnimation(const std::shared_ptr<AnimationUtils::Animation>& animation)
262 {
263     CHECK_NULL_VOID(animation);
264     if (animation->animations_.empty()) {
265         return;
266     }
267     auto pipeline = PipelineBase::GetCurrentContext();
268     if (pipeline) {
269         pipeline->RequestFrame();
270     }
271     for (auto& ani : animation->animations_) {
272         ani->Resume();
273     }
274 }
275 
ReverseAnimation(const std::shared_ptr<AnimationUtils::Animation> & animation)276 void AnimationUtils::ReverseAnimation(const std::shared_ptr<AnimationUtils::Animation>& animation)
277 {
278     CHECK_NULL_VOID(animation);
279     if (animation->animations_.empty()) {
280         return;
281     }
282     auto pipeline = PipelineBase::GetCurrentContext();
283     if (pipeline) {
284         pipeline->RequestFrame();
285     }
286     for (auto& ani : animation->animations_) {
287         ani->Reverse();
288     }
289 }
290 
ExecuteWithoutAnimation(const PropertyCallback & callback,const RefPtr<PipelineBase> & context)291 void AnimationUtils::ExecuteWithoutAnimation(const PropertyCallback& callback,
292     const RefPtr<PipelineBase>& context)
293 {
294     auto rsUIContext = GetRSUIContext(context);
295     Rosen::RSNode::ExecuteWithoutAnimation(callback, rsUIContext);
296 }
297 
CreateInteractiveAnimation(const InteractiveAnimationCallback & addCallback,const FinishCallback & callback)298 std::shared_ptr<AnimationUtils::InteractiveAnimation> AnimationUtils::CreateInteractiveAnimation(
299     const InteractiveAnimationCallback& addCallback, const FinishCallback& callback)
300 {
301     std::shared_ptr<AnimationUtils::InteractiveAnimation> interactiveAnimation =
302         std::make_shared<AnimationUtils::InteractiveAnimation>();
303     CHECK_NULL_RETURN(interactiveAnimation, nullptr);
304     auto wrappedOnFinish = GetWrappedCallback(callback, true, nullptr);
305     Rosen::RSAnimationTimingProtocol timingProtocol;
306     Rosen::RSAnimationTimingCurve curve;
307     interactiveAnimation->interactiveAnimation_ =
308         Rosen::RSInteractiveImplictAnimator::Create(timingProtocol, curve);
309     CHECK_NULL_RETURN(interactiveAnimation->interactiveAnimation_, nullptr);
310     if (addCallback) {
311         interactiveAnimation->interactiveAnimation_->AddAnimation(addCallback);
312     }
313     interactiveAnimation->interactiveAnimation_->SetFinishCallBack(wrappedOnFinish);
314     return interactiveAnimation;
315 }
316 
StartInteractiveAnimation(const std::shared_ptr<AnimationUtils::InteractiveAnimation> & interactiveAnimation)317 int32_t AnimationUtils::StartInteractiveAnimation(
318     const std::shared_ptr<AnimationUtils::InteractiveAnimation>& interactiveAnimation)
319 {
320     CHECK_NULL_RETURN(interactiveAnimation, -1);
321     CHECK_NULL_RETURN(interactiveAnimation->interactiveAnimation_, -1);
322     return interactiveAnimation->interactiveAnimation_->StartAnimation();
323 }
324 
ContinueInteractiveAnimation(const std::shared_ptr<AnimationUtils::InteractiveAnimation> & interactiveAnimation)325 void AnimationUtils::ContinueInteractiveAnimation(
326     const std::shared_ptr<AnimationUtils::InteractiveAnimation>& interactiveAnimation)
327 {
328     CHECK_NULL_VOID(interactiveAnimation);
329     CHECK_NULL_VOID(interactiveAnimation->interactiveAnimation_);
330     interactiveAnimation->interactiveAnimation_->ContinueAnimation();
331 }
332 
ReverseInteractiveAnimation(const std::shared_ptr<AnimationUtils::InteractiveAnimation> & interactiveAnimation)333 void AnimationUtils::ReverseInteractiveAnimation(
334     const std::shared_ptr<AnimationUtils::InteractiveAnimation>& interactiveAnimation)
335 {
336     CHECK_NULL_VOID(interactiveAnimation);
337     CHECK_NULL_VOID(interactiveAnimation->interactiveAnimation_);
338     interactiveAnimation->interactiveAnimation_->ReverseAnimation();
339 }
340 
UpdateInteractiveAnimation(const std::shared_ptr<AnimationUtils::InteractiveAnimation> & interactiveAnimation,float progress)341 void AnimationUtils::UpdateInteractiveAnimation(
342     const std::shared_ptr<AnimationUtils::InteractiveAnimation>& interactiveAnimation, float progress)
343 {
344     CHECK_NULL_VOID(interactiveAnimation);
345     CHECK_NULL_VOID(interactiveAnimation->interactiveAnimation_);
346     interactiveAnimation->interactiveAnimation_->PauseAnimation();
347     interactiveAnimation->interactiveAnimation_->SetFraction(progress);
348 }
349 
AddInteractiveAnimation(const std::shared_ptr<AnimationUtils::InteractiveAnimation> & interactiveAnimation,const std::function<void ()> & callback)350 void AnimationUtils::AddInteractiveAnimation(
351     const std::shared_ptr<AnimationUtils::InteractiveAnimation>& interactiveAnimation,
352     const std::function<void()>& callback)
353 {
354     CHECK_NULL_VOID(interactiveAnimation);
355     CHECK_NULL_VOID(interactiveAnimation->interactiveAnimation_);
356     interactiveAnimation->interactiveAnimation_->AddAnimation(callback);
357 }
358 
GetCurrentRSUIContext(RefPtr<PipelineBase> context)359 std::shared_ptr<Rosen::RSUIContext> AnimationUtils::GetCurrentRSUIContext(RefPtr<PipelineBase> context)
360 {
361     if (!context) {
362         context = PipelineBase::GetCurrentContextSafelyWithCheck();
363         CHECK_NULL_RETURN(context, nullptr);
364     }
365     auto window = context->GetWindow();
366     CHECK_NULL_RETURN(window, nullptr);
367     auto rsUIDirector = window->GetRSUIDirector();
368     CHECK_NULL_RETURN(rsUIDirector, nullptr);
369     return rsUIDirector->GetRSUIContext();
370 }
371 } // namespace OHOS::Ace
372