1 /*
2 * Copyright (c) 2021-2022 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_path_animation.h"
21 #include "pipeline/rs_node_map.h"
22 #include "animation/rs_implicit_animation_param.h"
23 #include "platform/common/rs_log.h"
24 #include "ui/rs_node.h"
25 #include "modifier/rs_property.h"
26
27 namespace OHOS {
28 namespace Rosen {
OpenImplicitAnimation(const RSAnimationTimingProtocol & timingProtocol,const RSAnimationTimingCurve & timingCurve,const std::function<void ()> & finishCallback)29 void RSImplicitAnimator::OpenImplicitAnimation(const RSAnimationTimingProtocol& timingProtocol,
30 const RSAnimationTimingCurve& timingCurve, const std::function<void()>& finishCallback)
31 {
32 globalImplicitParams_.push({ timingProtocol, timingCurve, finishCallback });
33 implicitAnimations_.push({});
34 keyframeAnimations_.push({});
35 switch (timingCurve.type_) {
36 case RSAnimationTimingCurve::CurveType::INTERPOLATING:
37 BeginImplicitCurveAnimation();
38 break;
39 case RSAnimationTimingCurve::CurveType::SPRING:
40 BeginImplicitSpringAnimation();
41 break;
42 default:
43 ROSEN_LOGE("Wrong type of timing curve!");
44 return;
45 }
46 }
47
CloseImplicitAnimation()48 std::vector<std::shared_ptr<RSAnimation>> RSImplicitAnimator::CloseImplicitAnimation()
49 {
50 std::vector<std::pair<std::shared_ptr<RSAnimation>, NodeId>> currentAnimations;
51 if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
52 ROSEN_LOGE("Failed to close implicit animation, need to open implicit animation firstly!");
53 return {};
54 }
55
56 auto finishCallback = std::get<std::function<void()>>(globalImplicitParams_.top());
57 if (implicitAnimations_.top().empty()) {
58 ROSEN_LOGD("No implicit animations created!");
59 if (finishCallback == nullptr) {
60 globalImplicitParams_.pop();
61 implicitAnimations_.pop();
62 keyframeAnimations_.pop();
63 EndImplicitAnimation();
64 return {};
65 } else {
66 CreateEmptyAnimation();
67 }
68 }
69 currentAnimations = implicitAnimations_.top();
70
71 for (const auto& [animationInfo, keyframeAnimation] : keyframeAnimations_.top()) {
72 auto target = RSNodeMap::Instance().GetNode<RSNode>(animationInfo.first);
73 if (target == nullptr) {
74 ROSEN_LOGE("Failed to start implicit keyframe animation[%" PRIu64 "], target is null!",
75 keyframeAnimation->GetId());
76 continue;
77 }
78
79 target->AddAnimation(keyframeAnimation);
80 }
81
82 std::shared_ptr<AnimationFinishCallback> animationFinishCallback;
83 if (finishCallback != nullptr) {
84 animationFinishCallback = std::make_shared<AnimationFinishCallback>(finishCallback);
85 }
86
87 std::vector<std::shared_ptr<RSAnimation>> resultAnimations;
88 for (const auto& [animation, nodeId] : currentAnimations) {
89 if (animation == nullptr) {
90 continue;
91 }
92
93 if (animationFinishCallback != nullptr) {
94 animation->SetFinishCallback(animationFinishCallback);
95 }
96
97 resultAnimations.emplace_back(animation);
98 }
99
100 globalImplicitParams_.pop();
101 implicitAnimations_.pop();
102 keyframeAnimations_.pop();
103 EndImplicitAnimation();
104 return resultAnimations;
105 }
106
BeginImplicitKeyFrameAnimation(float fraction,const RSAnimationTimingCurve & timingCurve)107 void RSImplicitAnimator::BeginImplicitKeyFrameAnimation(float fraction, const RSAnimationTimingCurve& timingCurve)
108 {
109 if (globalImplicitParams_.empty()) {
110 ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
111 return;
112 }
113
114 if (timingCurve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
115 ROSEN_LOGE("Wrong type of timing curve!");
116 return;
117 }
118
119 auto paramsTuple = globalImplicitParams_.top();
120 auto keyframeAnimationParam = std::make_shared<RSImplicitKeyframeAnimationParam>(
121 std::get<RSAnimationTimingProtocol>(paramsTuple), timingCurve, fraction);
122 PushImplicitParam(keyframeAnimationParam);
123 }
124
BeginImplicitKeyFrameAnimation(float fraction)125 void RSImplicitAnimator::BeginImplicitKeyFrameAnimation(float fraction)
126 {
127 if (globalImplicitParams_.empty()) {
128 ROSEN_LOGE("Failed to begin keyframe implicit animation, need to open implicit animation firstly!");
129 return;
130 }
131
132 BeginImplicitKeyFrameAnimation(fraction, std::get<RSAnimationTimingCurve>(globalImplicitParams_.top()));
133 }
134
EndImplicitKeyFrameAnimation()135 void RSImplicitAnimator::EndImplicitKeyFrameAnimation()
136 {
137 if (implicitAnimationParams_.empty() ||
138 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::KEYFRAME) {
139 ROSEN_LOGE("Failed to end keyframe implicit animation, need to begin keyframe implicit animation firstly!");
140 return;
141 }
142
143 PopImplicitParam();
144 }
145
NeedImplicitAnimation()146 bool RSImplicitAnimator::NeedImplicitAnimation()
147 {
148 return !implicitAnimationParams_.empty();
149 }
150
BeginImplicitCurveAnimation()151 void RSImplicitAnimator::BeginImplicitCurveAnimation()
152 {
153 if (globalImplicitParams_.empty()) {
154 ROSEN_LOGE("Failed to begin curve implicit animation, need to open implicit animation firstly!");
155 return;
156 }
157
158 [[maybe_unused]] auto& [protocol, curve, unused] = globalImplicitParams_.top();
159 if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
160 ROSEN_LOGE("Wrong type of timing curve!");
161 return;
162 }
163 auto curveAnimationParam = std::make_shared<RSImplicitCurveAnimationParam>(protocol, curve);
164 PushImplicitParam(curveAnimationParam);
165 }
166
EndImplicitAnimation()167 void RSImplicitAnimator::EndImplicitAnimation()
168 {
169 if (implicitAnimationParams_.empty() ||
170 (implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::CURVE &&
171 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::SPRING)) {
172 ROSEN_LOGE("Failed to end implicit animation, need to begin implicit animation firstly!");
173 return;
174 }
175
176 PopImplicitParam();
177 }
178
BeginImplicitPathAnimation(const std::shared_ptr<RSMotionPathOption> & motionPathOption)179 void RSImplicitAnimator::BeginImplicitPathAnimation(const std::shared_ptr<RSMotionPathOption>& motionPathOption)
180 {
181 if (globalImplicitParams_.empty()) {
182 ROSEN_LOGE("Failed to begin path implicit animation, need to open implicit animation firstly!");
183 return;
184 }
185
186 [[maybe_unused]] auto& [protocol, curve, unused] = globalImplicitParams_.top();
187 if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
188 ROSEN_LOGE("Wrong type of timing curve!");
189 return;
190 }
191 auto pathAnimationParam = std::make_shared<RSImplicitPathAnimationParam>(protocol, curve, motionPathOption);
192 PushImplicitParam(pathAnimationParam);
193 }
194
EndImplicitPathAnimation()195 void RSImplicitAnimator::EndImplicitPathAnimation()
196 {
197 if (implicitAnimationParams_.empty() ||
198 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::PATH) {
199 ROSEN_LOGE("Failed to end path implicit animation, need to begin path implicit animation firstly!");
200 return;
201 }
202
203 PopImplicitParam();
204 }
205
BeginImplicitSpringAnimation()206 void RSImplicitAnimator::BeginImplicitSpringAnimation()
207 {
208 if (globalImplicitParams_.empty()) {
209 ROSEN_LOGE("Failed to begin implicit transition, need to open implicit transition firstly!");
210 return;
211 }
212
213 [[maybe_unused]] auto& [protocol, curve, unused] = globalImplicitParams_.top();
214 if (curve.type_ != RSAnimationTimingCurve::CurveType::SPRING) {
215 ROSEN_LOGE("Wrong type of timing curve!");
216 return;
217 }
218 auto springParam = std::make_shared<RSImplicitSpringAnimationParam>(protocol, curve);
219 PushImplicitParam(springParam);
220 }
221
BeginImplicitTransition(const std::shared_ptr<const RSTransitionEffect> & effect)222 void RSImplicitAnimator::BeginImplicitTransition(const std::shared_ptr<const RSTransitionEffect>& effect)
223 {
224 if (globalImplicitParams_.empty()) {
225 ROSEN_LOGE("Failed to begin implicit transition, need to open implicit transition firstly!");
226 return;
227 }
228
229 [[maybe_unused]] auto& [protocol, curve, unused] = globalImplicitParams_.top();
230 if (curve.type_ != RSAnimationTimingCurve::CurveType::INTERPOLATING) {
231 ROSEN_LOGE("Wrong type of timing curve!");
232 return;
233 }
234 auto transitionParam = std::make_shared<RSImplicitTransitionParam>(protocol, curve, effect);
235 PushImplicitParam(transitionParam);
236 }
237
EndImplicitTransition()238 void RSImplicitAnimator::EndImplicitTransition()
239 {
240 if (implicitAnimationParams_.empty() ||
241 implicitAnimationParams_.top()->GetType() != ImplicitAnimationParamType::TRANSITION) {
242 ROSEN_LOGE("Failed to end implicit transition, need to begin implicit transition firstly!");
243 return;
244 }
245
246 PopImplicitParam();
247 }
248
PushImplicitParam(const std::shared_ptr<RSImplicitAnimationParam> & implicitParam)249 void RSImplicitAnimator::PushImplicitParam(const std::shared_ptr<RSImplicitAnimationParam>& implicitParam)
250 {
251 implicitAnimationParams_.emplace(implicitParam);
252 }
253
PopImplicitParam()254 void RSImplicitAnimator::PopImplicitParam()
255 {
256 if (implicitAnimationParams_.empty()) {
257 ROSEN_LOGE("Failed to pop implicit params, params stack is empty!");
258 return;
259 }
260
261 implicitAnimationParams_.pop();
262 }
263
CreateImplicitTransition(RSNode & target,bool isTransitionIn)264 std::shared_ptr<RSAnimation> RSImplicitAnimator::CreateImplicitTransition(RSNode& target, bool isTransitionIn)
265 {
266 if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
267 ROSEN_LOGE("Failed to create implicit transition, need to open implicit transition firstly!");
268 return {};
269 }
270 std::shared_ptr<RSAnimation> transition = nullptr;
271 auto params = implicitAnimationParams_.top();
272 switch (params->GetType()) {
273 case ImplicitAnimationParamType::TRANSITION: {
274 auto transitionImplicitParam = std::static_pointer_cast<RSImplicitTransitionParam>(params);
275 transition = transitionImplicitParam->CreateAnimation(isTransitionIn);
276 break;
277 }
278 default:
279 break;
280 }
281 if (transition != nullptr) {
282 target.AddAnimation(transition);
283 implicitAnimations_.top().push_back({ transition, target.GetId() });
284 }
285 return transition;
286 }
287
CreateEmptyAnimation()288 void RSImplicitAnimator::CreateEmptyAnimation()
289 {
290 auto target = RSNodeMap::Instance().GetAnimationFallbackNode();
291 if (target == nullptr) {
292 ROSEN_LOGE("RSImplicitAnimator::CreateEmptyAnimation, target is nullptr");
293 return;
294 }
295 std::shared_ptr<RSAnimatableProperty<float>> property = std::make_shared<RSAnimatableProperty<float>>(0.f);
296 property->id_ = 0;
297 auto startValue = std::make_shared<RSAnimatableProperty<float>>(0.f);
298 auto endValue = std::make_shared<RSAnimatableProperty<float>>(0.f);
299 CreateImplicitAnimation(target, property, startValue, endValue);
300 return;
301 }
302
SetPropertyValue(std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPropertyBase> & value)303 void RSImplicitAnimator::SetPropertyValue(std::shared_ptr<RSPropertyBase> property,
304 const std::shared_ptr<RSPropertyBase>& value)
305 {
306 if (property != nullptr) {
307 property->SetValue(value);
308 }
309 }
310
CreateImplicitAnimation(const std::shared_ptr<RSNode> & target,std::shared_ptr<RSPropertyBase> property,const std::shared_ptr<RSPropertyBase> & startValue,const std::shared_ptr<RSPropertyBase> & endValue)311 std::shared_ptr<RSAnimation> RSImplicitAnimator::CreateImplicitAnimation(const std::shared_ptr<RSNode>& target,
312 std::shared_ptr<RSPropertyBase> property, const std::shared_ptr<RSPropertyBase>& startValue,
313 const std::shared_ptr<RSPropertyBase>& endValue)
314 {
315 if (globalImplicitParams_.empty() || implicitAnimations_.empty() || keyframeAnimations_.empty()) {
316 ROSEN_LOGE("Failed to create implicit animation, need to open implicit animation firstly!");
317 return {};
318 }
319
320 if (target == nullptr || property == nullptr) {
321 return {};
322 }
323
324 std::shared_ptr<RSAnimation> animation;
325 auto params = implicitAnimationParams_.top();
326 switch (params->GetType()) {
327 case ImplicitAnimationParamType::CURVE: {
328 auto curveImplicitParam = static_cast<RSImplicitCurveAnimationParam*>(params.get());
329 animation = curveImplicitParam->CreateAnimation(property, startValue, endValue);
330 break;
331 }
332 case ImplicitAnimationParamType::KEYFRAME: {
333 auto keyframeImplicitParam = static_cast<RSImplicitKeyframeAnimationParam*>(params.get());
334 auto& keyframeAnimations = keyframeAnimations_.top();
335 auto keyframeIter = keyframeAnimations.find({ target->GetId(), property->GetId() });
336 SetPropertyValue(property, endValue);
337 if (keyframeIter == keyframeAnimations.end()) {
338 animation = keyframeImplicitParam->CreateAnimation(property, startValue, endValue);
339 keyframeAnimations[{ target->GetId(), property->GetId() }] = animation;
340 } else {
341 keyframeImplicitParam->AddKeyframe(keyframeIter->second, startValue, endValue);
342 return keyframeIter->second;
343 }
344 break;
345 }
346 case ImplicitAnimationParamType::SPRING: {
347 auto springImplicitParam = static_cast<RSImplicitSpringAnimationParam*>(params.get());
348 animation = springImplicitParam->CreateAnimation(property, startValue, endValue);
349 break;
350 }
351 case ImplicitAnimationParamType::PATH: {
352 auto pathImplicitParam = static_cast<RSImplicitPathAnimationParam*>(params.get());
353 animation = pathImplicitParam->CreateAnimation(property, startValue, endValue);
354 break;
355 }
356 default:
357 ROSEN_LOGE("Failed to create animation, unknow type!");
358 break;
359 }
360
361 if (animation == nullptr) {
362 ROSEN_LOGE("Failed to create animation!");
363 return nullptr;
364 }
365
366 if (params->GetType() != ImplicitAnimationParamType::KEYFRAME) {
367 target->AddAnimation(animation);
368 }
369
370 implicitAnimations_.top().push_back({ animation, target->GetId() });
371 return animation;
372 }
373 } // namespace Rosen
374 } // namespace OHOS
375