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