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 "pipeline/rs_canvas_render_node.h"
19 #include "platform/common/rs_log.h"
20
21 namespace OHOS {
22 namespace Rosen {
RSRenderAnimation(AnimationId id)23 RSRenderAnimation::RSRenderAnimation(AnimationId id) : id_(id) {}
Marshalling(Parcel & parcel) const24 bool RSRenderAnimation::Marshalling(Parcel& parcel) const
25 {
26 // animationId, targetId
27 if (!(parcel.WriteUint64(id_))) {
28 ROSEN_LOGE("RSRenderAnimation::Marshalling, write id failed");
29 return false;
30 }
31 // RSAnimationTimingProtocol
32 if (!(parcel.WriteInt32(animationFraction_.GetDuration()) &&
33 parcel.WriteInt32(animationFraction_.GetStartDelay()) &&
34 parcel.WriteFloat(animationFraction_.GetSpeed()) &&
35 parcel.WriteInt32(animationFraction_.GetRepeatCount()) &&
36 parcel.WriteBool(animationFraction_.GetAutoReverse()) &&
37 parcel.WriteBool(animationFraction_.GetDirection()) &&
38 parcel.WriteInt32(static_cast<std::underlying_type<FillMode>::type>(animationFraction_.GetFillMode())))) {
39 ROSEN_LOGE("RSRenderAnimation::Marshalling, write param failed");
40 return false;
41 }
42 return true;
43 }
44
ParseParam(Parcel & parcel)45 bool RSRenderAnimation::ParseParam(Parcel& parcel)
46 {
47 int32_t duration = 0;
48 int32_t startDelay = 0;
49 int32_t repeatCount = 0;
50 int32_t fillMode = 0;
51 float speed = 0.0;
52 bool autoReverse = false;
53 bool direction = false;
54 if (!(parcel.ReadUint64(id_) && parcel.ReadInt32(duration) && parcel.ReadInt32(startDelay) &&
55 parcel.ReadFloat(speed) && parcel.ReadInt32(repeatCount) && parcel.ReadBool(autoReverse) &&
56 parcel.ReadBool(direction) && parcel.ReadInt32(fillMode))) {
57 ROSEN_LOGE("RSRenderAnimation::ParseParam, read param failed");
58 return false;
59 }
60 SetDuration(duration);
61 SetStartDelay(startDelay);
62 SetRepeatCount(repeatCount);
63 SetAutoReverse(autoReverse);
64 SetSpeed(speed);
65 SetDirection(direction);
66 SetFillMode(static_cast<FillMode>(fillMode));
67 return true;
68 }
GetAnimationId() const69 AnimationId RSRenderAnimation::GetAnimationId() const
70 {
71 return id_;
72 }
73
IsStarted() const74 bool RSRenderAnimation::IsStarted() const
75 {
76 return state_ != AnimationState::INITIALIZED;
77 }
78
IsRunning() const79 bool RSRenderAnimation::IsRunning() const
80 {
81 return state_ == AnimationState::RUNNING;
82 }
83
IsPaused() const84 bool RSRenderAnimation::IsPaused() const
85 {
86 return state_ == AnimationState::PAUSED;
87 }
88
IsFinished() const89 bool RSRenderAnimation::IsFinished() const
90 {
91 return state_ == AnimationState::FINISHED;
92 }
93
GetPropertyId() const94 PropertyId RSRenderAnimation::GetPropertyId() const
95 {
96 return 0;
97 }
98
Attach(RSRenderNode * renderNode)99 void RSRenderAnimation::Attach(RSRenderNode* renderNode)
100 {
101 if (target_ != nullptr) {
102 Detach();
103 }
104 target_ = renderNode;
105 if (target_ != nullptr) {
106 targetId_ = target_->GetId();
107 }
108 OnAttach();
109 Start();
110 needUpdateStartTime_ = false;
111 }
112
Detach()113 void RSRenderAnimation::Detach()
114 {
115 OnDetach();
116 target_ = nullptr;
117 }
118
GetTargetId() const119 NodeId RSRenderAnimation::GetTargetId() const
120 {
121 return targetId_;
122 }
123
Start()124 void RSRenderAnimation::Start()
125 {
126 if (IsStarted()) {
127 ROSEN_LOGE("Failed to start animation, animation has started!");
128 return;
129 }
130
131 state_ = AnimationState::RUNNING;
132 needUpdateStartTime_ = true;
133 ProcessFillModeOnStart(animationFraction_.GetStartFraction());
134 }
135
Finish()136 void RSRenderAnimation::Finish()
137 {
138 if (!IsPaused() && !IsRunning()) {
139 ROSEN_LOGE("Failed to finish animation, animation is not running!");
140 return;
141 }
142
143 state_ = AnimationState::FINISHED;
144 ProcessFillModeOnFinish(animationFraction_.GetEndFraction());
145 }
146
FinishOnCurrentPosition()147 void RSRenderAnimation::FinishOnCurrentPosition()
148 {
149 if (!IsPaused() && !IsRunning()) {
150 ROSEN_LOGE("Failed to finish animation, animation is not running!");
151 return;
152 }
153
154 state_ = AnimationState::FINISHED;
155 }
156
Pause()157 void RSRenderAnimation::Pause()
158 {
159 if (!IsRunning()) {
160 ROSEN_LOGE("Failed to pause animation, animation is not running!");
161 return;
162 }
163
164 state_ = AnimationState::PAUSED;
165 }
166
Resume()167 void RSRenderAnimation::Resume()
168 {
169 if (!IsPaused()) {
170 ROSEN_LOGE("Failed to resume animation, animation is not paused!");
171 return;
172 }
173
174 state_ = AnimationState::RUNNING;
175 needUpdateStartTime_ = true;
176 }
177
SetFraction(float fraction)178 void RSRenderAnimation::SetFraction(float fraction)
179 {
180 if (!IsPaused()) {
181 ROSEN_LOGE("Failed to set fraction, animation is not paused!");
182 return;
183 }
184
185 fraction = std::min(std::max(fraction, 0.0f), 1.0f);
186 OnSetFraction(fraction);
187 }
188
SetReversed(bool isReversed)189 void RSRenderAnimation::SetReversed(bool isReversed)
190 {
191 if (!IsPaused() && !IsRunning()) {
192 ROSEN_LOGE("Failed to reverse animation, animation is not running!");
193 return;
194 }
195
196 animationFraction_.SetDirectionAfterStart(isReversed ? ForwardDirection::REVERSE : ForwardDirection::NORMAL);
197 }
198
GetTarget() const199 RSRenderNode* RSRenderAnimation::GetTarget() const
200 {
201 return target_;
202 }
203
SetFractionInner(float fraction)204 void RSRenderAnimation::SetFractionInner(float fraction)
205 {
206 animationFraction_.UpdateRemainTimeFraction(fraction);
207 }
208
OnSetFraction(float fraction)209 void RSRenderAnimation::OnSetFraction(float fraction)
210 {
211 SetFractionInner(fraction);
212 }
213
ProcessFillModeOnStart(float startFraction)214 void RSRenderAnimation::ProcessFillModeOnStart(float startFraction)
215 {
216 auto fillMode = GetFillMode();
217 if (fillMode == FillMode::BACKWARDS || fillMode == FillMode::BOTH) {
218 OnAnimate(startFraction);
219 }
220 }
221
ProcessFillModeOnFinish(float endFraction)222 void RSRenderAnimation::ProcessFillModeOnFinish(float endFraction)
223 {
224 auto fillMode = GetFillMode();
225 if (fillMode == FillMode::FORWARDS || fillMode == FillMode::BOTH) {
226 OnAnimate(endFraction);
227 } else {
228 OnRemoveOnCompletion();
229 }
230 }
231
Animate(int64_t time)232 bool RSRenderAnimation::Animate(int64_t time)
233 {
234 if (!IsRunning()) {
235 ROSEN_LOGI("RSRenderAnimation::Animate, IsRunning is false!");
236 return state_ == AnimationState::FINISHED;
237 }
238
239 // set start time and return
240 if (needUpdateStartTime_) {
241 SetStartTime(time);
242 return state_ == AnimationState::FINISHED;
243 }
244
245 // if time not changed since last frame, return
246 if (time == animationFraction_.GetLastFrameTime()) {
247 return state_ == AnimationState::FINISHED;
248 }
249
250 if (needInitialize_) {
251 OnInitialize();
252 needInitialize_ = false;
253 }
254
255 bool isInStartDelay = false;
256 bool isFinished = false;
257 float fraction = animationFraction_.GetAnimationFraction(time, isInStartDelay, isFinished);
258 if (isInStartDelay) {
259 ProcessFillModeOnStart(fraction);
260 ROSEN_LOGI("RSRenderAnimation::Animate, isInStartDelay is true");
261 return false;
262 }
263
264 OnAnimate(fraction);
265 if (isFinished) {
266 ProcessFillModeOnFinish(fraction);
267 ROSEN_LOGD("RSRenderAnimation::Animate, isFinished is true");
268 return true;
269 }
270 return isFinished;
271 }
272
SetStartTime(int64_t time)273 void RSRenderAnimation::SetStartTime(int64_t time)
274 {
275 animationFraction_.SetLastFrameTime(time);
276 needUpdateStartTime_ = false;
277 }
278 } // namespace Rosen
279 } // namespace OHOS
280