1 /*
2 * Copyright (c) 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_interpolating_spring_animation.h"
17
18 #include "animation/rs_value_estimator.h"
19 #include "command/rs_animation_command.h"
20 #include "command/rs_message_processor.h"
21 #include "pipeline/rs_render_node.h"
22 #include "platform/common/rs_log.h"
23
24 namespace OHOS {
25 namespace Rosen {
26 namespace {
27 constexpr float SECOND_TO_MILLISECOND = 1e3;
28 constexpr float MILLISECOND_TO_SECOND = 1e-3;
29 constexpr float FRAME_TIME_INTERVAL = 1.0f / 90.0f;
30 } // namespace
31
RSRenderInterpolatingSpringAnimation(AnimationId id,const PropertyId & propertyId,const std::shared_ptr<RSRenderPropertyBase> & originValue,const std::shared_ptr<RSRenderPropertyBase> & startValue,const std::shared_ptr<RSRenderPropertyBase> & endValue)32 RSRenderInterpolatingSpringAnimation::RSRenderInterpolatingSpringAnimation(AnimationId id, const PropertyId& propertyId,
33 const std::shared_ptr<RSRenderPropertyBase>& originValue, const std::shared_ptr<RSRenderPropertyBase>& startValue,
34 const std::shared_ptr<RSRenderPropertyBase>& endValue)
35 : RSRenderPropertyAnimation(id, propertyId, originValue), RSSpringModel<float>(), startValue_(startValue),
36 endValue_(endValue)
37 {
38 // spring model is not initialized, so we can't calculate estimated duration
39 }
40
DumpAnimationType(std::string & out) const41 void RSRenderInterpolatingSpringAnimation::DumpAnimationType(std::string& out) const
42 {
43 out += "Type:RSRenderInterpolatingSpringAnimation";
44 }
45
SetSpringParameters(float response,float dampingRatio,float normalizedInitialVelocity,float minimumAmplitudeRatio)46 void RSRenderInterpolatingSpringAnimation::SetSpringParameters(
47 float response, float dampingRatio, float normalizedInitialVelocity, float minimumAmplitudeRatio)
48 {
49 response_ = response;
50 dampingRatio_ = dampingRatio;
51 normalizedInitialVelocity_ = normalizedInitialVelocity;
52 minimumAmplitudeRatio_ = minimumAmplitudeRatio;
53 }
54
SetZeroThreshold(float zeroThreshold)55 void RSRenderInterpolatingSpringAnimation::SetZeroThreshold(float zeroThreshold)
56 {
57 constexpr float ZERO = 0.0f;
58 if (zeroThreshold < ZERO) {
59 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::SetZeroThreshold: invalid threshold value.");
60 needLogicallyFinishCallback_ = false;
61 return;
62 }
63 zeroThreshold_ = zeroThreshold;
64 needLogicallyFinishCallback_ = true;
65 }
66
67 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel) const68 bool RSRenderInterpolatingSpringAnimation::Marshalling(Parcel& parcel) const
69 {
70 if (!RSRenderPropertyAnimation::Marshalling(parcel)) {
71 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::Marshalling, RenderPropertyAnimation failed");
72 return false;
73 }
74 if (!(RSRenderPropertyBase::Marshalling(parcel, startValue_) &&
75 RSRenderPropertyBase::Marshalling(parcel, endValue_))) {
76 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::Marshalling, MarshallingHelper failed");
77 return false;
78 }
79
80 if (!(RSMarshallingHelper::Marshalling(parcel, response_) &&
81 RSMarshallingHelper::Marshalling(parcel, dampingRatio_) &&
82 RSMarshallingHelper::Marshalling(parcel, normalizedInitialVelocity_) &&
83 RSMarshallingHelper::Marshalling(parcel, minimumAmplitudeRatio_) &&
84 RSMarshallingHelper::Marshalling(parcel, needLogicallyFinishCallback_) &&
85 RSMarshallingHelper::Marshalling(parcel, zeroThreshold_))) {
86 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::Marshalling, invalid parametter failed");
87 return false;
88 }
89
90 return true;
91 }
92
Unmarshalling(Parcel & parcel)93 RSRenderInterpolatingSpringAnimation* RSRenderInterpolatingSpringAnimation::Unmarshalling(Parcel& parcel)
94 {
95 auto* renderInterpolatingSpringAnimation = new RSRenderInterpolatingSpringAnimation();
96 if (!renderInterpolatingSpringAnimation->ParseParam(parcel)) {
97 ROSEN_LOGE("RenderInterpolatingSpringAnimation::Unmarshalling, failed");
98 delete renderInterpolatingSpringAnimation;
99 return nullptr;
100 }
101 return renderInterpolatingSpringAnimation;
102 }
103
ParseParam(Parcel & parcel)104 bool RSRenderInterpolatingSpringAnimation::ParseParam(Parcel& parcel)
105 {
106 if (!RSRenderPropertyAnimation::ParseParam(parcel)) {
107 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::ParseParam, ParseParam Fail");
108 return false;
109 }
110
111 if (!(RSRenderPropertyBase::Unmarshalling(parcel, startValue_) &&
112 RSRenderPropertyBase::Unmarshalling(parcel, endValue_))) {
113 return false;
114 }
115
116 if (!(RSMarshallingHelper::Unmarshalling(parcel, response_) &&
117 RSMarshallingHelper::Unmarshalling(parcel, dampingRatio_) &&
118 RSMarshallingHelper::Unmarshalling(parcel, normalizedInitialVelocity_) &&
119 RSMarshallingHelper::Unmarshalling(parcel, minimumAmplitudeRatio_) &&
120 RSMarshallingHelper::Unmarshalling(parcel, needLogicallyFinishCallback_) &&
121 RSMarshallingHelper::Unmarshalling(parcel, zeroThreshold_))) {
122 return false;
123 }
124
125 return true;
126 }
127 #endif
128
OnSetFraction(float fraction)129 void RSRenderInterpolatingSpringAnimation::OnSetFraction(float fraction)
130 {
131 if (valueEstimator_ == nullptr) {
132 return;
133 }
134 valueEstimator_->UpdateAnimationValue(fraction, GetAdditive());
135 SetValueFraction(fraction);
136 fractionChangeInfo_ = { true, fraction };
137 }
138
UpdateFractionAfterContinue()139 void RSRenderInterpolatingSpringAnimation::UpdateFractionAfterContinue()
140 {
141 auto& [bChangeFraction, valueFraction] = fractionChangeInfo_;
142 if (bChangeFraction) {
143 SetFractionInner(CalculateTimeFraction(valueFraction));
144 bChangeFraction = false;
145 valueFraction = 0.0f;
146 }
147 }
148
CalculateTimeFraction(float targetFraction)149 float RSRenderInterpolatingSpringAnimation::CalculateTimeFraction(float targetFraction)
150 {
151 int secondTime = std::ceil(static_cast<float>(GetDuration()) / SECOND_TO_MS);
152 if (secondTime <= 0) {
153 return FRACTION_MIN;
154 }
155 int64_t frameTimes = MAX_FRAME_TIME_FRACTION * secondTime;
156 float lastFraction = FRACTION_MIN;
157 for (int time = 1; time <= frameTimes; time++) {
158 float frameFraction = static_cast<float>(time) / frameTimes;
159 frameFraction = std::clamp(frameFraction, 0.0f, 1.0f);
160 auto mappedTime = frameFraction * GetDuration() * MILLISECOND_TO_SECOND;
161 float displacement = 1.0f + CalculateDisplacement(mappedTime);
162 if (lastFraction <= targetFraction && displacement >= targetFraction) {
163 return frameFraction;
164 }
165 lastFraction = displacement;
166 }
167 return FRACTION_MIN;
168 }
169
OnAnimate(float fraction)170 void RSRenderInterpolatingSpringAnimation::OnAnimate(float fraction)
171 {
172 if (valueEstimator_ == nullptr) {
173 ROSEN_LOGD("RSRenderInterpolatingSpringAnimation::OnAnimate, valueEstimator_ is nullptr.");
174 return;
175 }
176 if (GetPropertyId() == 0) {
177 // calculateAnimationValue_ is embedded modify for stat animate frame drop
178 calculateAnimationValue_ = false;
179 return;
180 } else if (ROSEN_EQ(fraction, 1.0f)) {
181 valueEstimator_->UpdateAnimationValue(1.0f, GetAdditive());
182 return;
183 }
184 auto mappedTime = fraction * GetDuration() * MILLISECOND_TO_SECOND;
185 float displacement = 1.0f + CalculateDisplacement(mappedTime);
186 SetValueFraction(displacement);
187 valueEstimator_->UpdateAnimationValue(displacement, GetAdditive());
188 if (GetNeedLogicallyFinishCallback() && (animationFraction_.GetRemainingRepeatCount() == 1)) {
189 auto interpolationValue = valueEstimator_->Estimate(displacement, startValue_, endValue_);
190 auto endValue = animationFraction_.GetCurrentIsReverseCycle() ? startValue_ : endValue_;
191 auto velocity = CalculateVelocity(mappedTime);
192 auto zeroValue = startValue_ - startValue_;
193 if (interpolationValue != nullptr && !interpolationValue->IsNearEqual(endValue, zeroThreshold_)) {
194 return;
195 }
196 if (velocity != nullptr && (velocity * FRAME_TIME_INTERVAL)->IsNearEqual(zeroValue, zeroThreshold_)) {
197 CallLogicallyFinishCallback();
198 needLogicallyFinishCallback_ = false;
199 }
200 }
201 }
202
OnInitialize(int64_t time)203 void RSRenderInterpolatingSpringAnimation::OnInitialize(int64_t time)
204 {
205 // set the initial status of spring model
206 initialOffset_ = -1.0f;
207 initialVelocity_ = initialOffset_ * (-normalizedInitialVelocity_);
208 CalculateSpringParameters();
209 // use duration calculated by spring model as animation duration
210 SetDuration(std::lroundf(EstimateDuration() * SECOND_TO_MILLISECOND));
211 // this will set needInitialize_ to false
212 RSRenderPropertyAnimation::OnInitialize(time);
213 }
214
InitValueEstimator()215 void RSRenderInterpolatingSpringAnimation::InitValueEstimator()
216 {
217 if (valueEstimator_ == nullptr) {
218 valueEstimator_ = property_->CreateRSValueEstimator(RSValueEstimatorType::CURVE_VALUE_ESTIMATOR);
219 }
220 if (valueEstimator_) {
221 valueEstimator_->InitCurveAnimationValue(property_, startValue_, endValue_, lastValue_);
222 } else {
223 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::InitValueEstimator, valueEstimator_ is nullptr.");
224 }
225 }
226
CalculateVelocity(float time) const227 std::shared_ptr<RSRenderPropertyBase> RSRenderInterpolatingSpringAnimation::CalculateVelocity(float time) const
228 {
229 if (valueEstimator_ == nullptr) {
230 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::CalculateVelocity, valueEstimator_ is nullptr.");
231 return nullptr;
232 }
233 constexpr float TIME_INTERVAL = 1e-6f; // 1e-6f : 1 microsecond
234 float currentDisplacement = 1.0f + CalculateDisplacement(time);
235 float nextDisplacement = 1.0f + CalculateDisplacement(time + TIME_INTERVAL);
236 auto velocity = (valueEstimator_->Estimate(nextDisplacement, startValue_, endValue_) -
237 valueEstimator_->Estimate(currentDisplacement, startValue_, endValue_)) * (1 / TIME_INTERVAL);
238
239 return velocity;
240 }
241
GetNeedLogicallyFinishCallback() const242 bool RSRenderInterpolatingSpringAnimation::GetNeedLogicallyFinishCallback() const
243 {
244 return needLogicallyFinishCallback_;
245 }
246
CallLogicallyFinishCallback() const247 void RSRenderInterpolatingSpringAnimation::CallLogicallyFinishCallback() const
248 {
249 NodeId targetId = GetTargetId();
250 AnimationId animationId = GetAnimationId();
251
252 std::unique_ptr<RSCommand> command =
253 std::make_unique<RSAnimationCallback>(targetId, animationId, LOGICALLY_FINISHED);
254 RSMessageProcessor::Instance().AddUIMessage(ExtractPid(animationId), std::move(command));
255 }
256 } // namespace Rosen
257 } // namespace OHOS