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_render_animation.h"
17
18 #include "command/rs_animation_command.h"
19 #include "pipeline/rs_canvas_render_node.h"
20 #include "command/rs_message_processor.h"
21 #include "platform/common/rs_log.h"
22
23 namespace OHOS {
24 namespace Rosen {
RSRenderAnimation(AnimationId id)25 RSRenderAnimation::RSRenderAnimation(AnimationId id) : id_(id) {}
Marshalling(Parcel & parcel) const26 bool RSRenderAnimation::Marshalling(Parcel& parcel) const
27 {
28 // animationId, targetId
29 if (!(parcel.WriteUint64(id_))) {
30 ROSEN_LOGE("RSRenderAnimation::Marshalling, write id failed");
31 return false;
32 }
33 // RSAnimationTimingProtocol
34 if (!(parcel.WriteInt32(animationFraction_.GetDuration()) &&
35 parcel.WriteInt32(animationFraction_.GetStartDelay()) &&
36 parcel.WriteFloat(animationFraction_.GetSpeed()) &&
37 parcel.WriteInt32(animationFraction_.GetRepeatCount()) &&
38 parcel.WriteBool(animationFraction_.GetAutoReverse()) &&
39 parcel.WriteBool(animationFraction_.GetDirection()) &&
40 parcel.WriteInt32(static_cast<std::underlying_type<FillMode>::type>(animationFraction_.GetFillMode())) &&
41 parcel.WriteBool(animationFraction_.GetRepeatCallbackEnable()) &&
42 parcel.WriteInt32(animationFraction_.GetFrameRateRange().min_) &&
43 parcel.WriteInt32(animationFraction_.GetFrameRateRange().max_) &&
44 parcel.WriteInt32(animationFraction_.GetFrameRateRange().preferred_))) {
45 ROSEN_LOGE("RSRenderAnimation::Marshalling, write param failed");
46 return false;
47 }
48 return true;
49 }
50
ParseParam(Parcel & parcel)51 bool RSRenderAnimation::ParseParam(Parcel& parcel)
52 {
53 int32_t duration = 0;
54 int32_t startDelay = 0;
55 int32_t repeatCount = 0;
56 int32_t fillMode = 0;
57 float speed = 0.0;
58 bool autoReverse = false;
59 bool direction = false;
60 bool isRepeatCallbackEnable = false;
61 int fpsMin = 0;
62 int fpsMax = 0;
63 int fpsPreferred = 0;
64 if (!(parcel.ReadUint64(id_) && parcel.ReadInt32(duration) && parcel.ReadInt32(startDelay) &&
65 parcel.ReadFloat(speed) && parcel.ReadInt32(repeatCount) && parcel.ReadBool(autoReverse) &&
66 parcel.ReadBool(direction) && parcel.ReadInt32(fillMode) && parcel.ReadBool(isRepeatCallbackEnable) &&
67 parcel.ReadInt32(fpsMin) && parcel.ReadInt32(fpsMax) && parcel.ReadInt32(fpsPreferred))) {
68 ROSEN_LOGE("RSRenderAnimation::ParseParam, read param failed");
69 return false;
70 }
71 SetDuration(duration);
72 SetStartDelay(startDelay);
73 SetRepeatCount(repeatCount);
74 SetAutoReverse(autoReverse);
75 SetSpeed(speed);
76 SetDirection(direction);
77 SetFillMode(static_cast<FillMode>(fillMode));
78 SetRepeatCallbackEnable(isRepeatCallbackEnable);
79 SetFrameRateRange({fpsMin, fpsMax, fpsPreferred});
80 return true;
81 }
GetAnimationId() const82 AnimationId RSRenderAnimation::GetAnimationId() const
83 {
84 return id_;
85 }
86
IsStarted() const87 bool RSRenderAnimation::IsStarted() const
88 {
89 return state_ != AnimationState::INITIALIZED;
90 }
91
IsRunning() const92 bool RSRenderAnimation::IsRunning() const
93 {
94 return state_ == AnimationState::RUNNING;
95 }
96
IsPaused() const97 bool RSRenderAnimation::IsPaused() const
98 {
99 return state_ == AnimationState::PAUSED;
100 }
101
IsFinished() const102 bool RSRenderAnimation::IsFinished() const
103 {
104 return state_ == AnimationState::FINISHED;
105 }
106
GetPropertyId() const107 PropertyId RSRenderAnimation::GetPropertyId() const
108 {
109 return 0;
110 }
111
Attach(RSRenderNode * renderNode)112 void RSRenderAnimation::Attach(RSRenderNode* renderNode)
113 {
114 if (target_ != nullptr) {
115 Detach();
116 }
117 target_ = renderNode;
118 if (target_ != nullptr) {
119 targetId_ = target_->GetId();
120 target_->CheckGroupableAnimation(GetPropertyId(), true);
121 }
122 OnAttach();
123 Start();
124 needUpdateStartTime_ = false;
125 }
126
Detach()127 void RSRenderAnimation::Detach()
128 {
129 OnDetach();
130 if (target_ != nullptr) {
131 target_->CheckGroupableAnimation(GetPropertyId(), false);
132 }
133 target_ = nullptr;
134 }
135
GetTargetId() const136 NodeId RSRenderAnimation::GetTargetId() const
137 {
138 return targetId_;
139 }
140
Start()141 void RSRenderAnimation::Start()
142 {
143 if (IsStarted()) {
144 ROSEN_LOGE("Failed to start animation, animation has started!");
145 return;
146 }
147
148 state_ = AnimationState::RUNNING;
149 needUpdateStartTime_ = true;
150 ProcessFillModeOnStart(animationFraction_.GetStartFraction());
151 }
152
Finish()153 void RSRenderAnimation::Finish()
154 {
155 if (!IsPaused() && !IsRunning()) {
156 ROSEN_LOGE("Failed to finish animation, animation is not running!");
157 return;
158 }
159
160 state_ = AnimationState::FINISHED;
161 ProcessFillModeOnFinish(animationFraction_.GetEndFraction());
162 }
163
FinishOnCurrentPosition()164 void RSRenderAnimation::FinishOnCurrentPosition()
165 {
166 if (!IsPaused() && !IsRunning()) {
167 ROSEN_LOGE("Failed to finish animation, animation is not running!");
168 return;
169 }
170
171 state_ = AnimationState::FINISHED;
172 }
173
Pause()174 void RSRenderAnimation::Pause()
175 {
176 if (!IsRunning()) {
177 ROSEN_LOGE("Failed to pause animation, animation is not running!");
178 return;
179 }
180
181 state_ = AnimationState::PAUSED;
182 }
183
Resume()184 void RSRenderAnimation::Resume()
185 {
186 if (!IsPaused()) {
187 ROSEN_LOGE("Failed to resume animation, animation is not paused!");
188 return;
189 }
190
191 state_ = AnimationState::RUNNING;
192 needUpdateStartTime_ = true;
193 }
194
SetFraction(float fraction)195 void RSRenderAnimation::SetFraction(float fraction)
196 {
197 if (!IsPaused()) {
198 ROSEN_LOGE("Failed to set fraction, animation is not paused!");
199 return;
200 }
201
202 fraction = std::min(std::max(fraction, 0.0f), 1.0f);
203 OnSetFraction(fraction);
204 }
205
SetReversed(bool isReversed)206 void RSRenderAnimation::SetReversed(bool isReversed)
207 {
208 if (!IsPaused() && !IsRunning()) {
209 ROSEN_LOGE("Failed to reverse animation, animation is not running!");
210 return;
211 }
212
213 animationFraction_.SetDirectionAfterStart(isReversed ? ForwardDirection::REVERSE : ForwardDirection::NORMAL);
214 }
215
GetTarget() const216 RSRenderNode* RSRenderAnimation::GetTarget() const
217 {
218 return target_;
219 }
220
SetFractionInner(float fraction)221 void RSRenderAnimation::SetFractionInner(float fraction)
222 {
223 animationFraction_.UpdateRemainTimeFraction(fraction);
224 }
225
OnSetFraction(float fraction)226 void RSRenderAnimation::OnSetFraction(float fraction)
227 {
228 SetFractionInner(fraction);
229 }
230
ProcessFillModeOnStart(float startFraction)231 void RSRenderAnimation::ProcessFillModeOnStart(float startFraction)
232 {
233 auto fillMode = GetFillMode();
234 if (fillMode == FillMode::BACKWARDS || fillMode == FillMode::BOTH) {
235 OnAnimate(startFraction);
236 }
237 }
238
ProcessFillModeOnFinish(float endFraction)239 void RSRenderAnimation::ProcessFillModeOnFinish(float endFraction)
240 {
241 auto fillMode = GetFillMode();
242 if (fillMode == FillMode::FORWARDS || fillMode == FillMode::BOTH) {
243 OnAnimate(endFraction);
244 } else {
245 OnRemoveOnCompletion();
246 }
247 }
248
ProcessOnRepeatFinish()249 void RSRenderAnimation::ProcessOnRepeatFinish()
250 {
251 std::unique_ptr<RSCommand> command =
252 std::make_unique<RSAnimationCallback>(targetId_, id_, REPEAT_FINISHED);
253 RSMessageProcessor::Instance().AddUIMessage(ExtractPid(id_), command);
254 }
255
Animate(int64_t time)256 bool RSRenderAnimation::Animate(int64_t time)
257 {
258 if (!IsRunning()) {
259 return state_ == AnimationState::FINISHED;
260 }
261
262 // set start time and return
263 if (needUpdateStartTime_) {
264 SetStartTime(time);
265 return state_ == AnimationState::FINISHED;
266 }
267
268 // if time not changed since last frame, return
269 if (time == animationFraction_.GetLastFrameTime()) {
270 return state_ == AnimationState::FINISHED;
271 }
272
273 if (needInitialize_) {
274 // normally this only run once, but in spring animation with blendDuration, it may run multiple times
275 OnInitialize(time);
276 }
277
278 // convert time to fraction
279 auto [fraction, isInStartDelay, isFinished, isRepeatFinished] = animationFraction_.GetAnimationFraction(time);
280 if (isInStartDelay) {
281 ProcessFillModeOnStart(fraction);
282 ROSEN_LOGD("RSRenderAnimation::Animate, isInStartDelay is true");
283 return false;
284 }
285
286 OnAnimate(fraction);
287 if (isRepeatFinished) {
288 ProcessOnRepeatFinish();
289 }
290 if (isFinished) {
291 ProcessFillModeOnFinish(fraction);
292 ROSEN_LOGD("RSRenderAnimation::Animate, isFinished is true");
293 return true;
294 }
295 return isFinished;
296 }
297
SetStartTime(int64_t time)298 void RSRenderAnimation::SetStartTime(int64_t time)
299 {
300 animationFraction_.SetLastFrameTime(time);
301 needUpdateStartTime_ = false;
302 }
303 } // namespace Rosen
304 } // namespace OHOS
305