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_animation_trace_utils.h"
19 #include "animation/rs_value_estimator.h"
20 #include "command/rs_animation_command.h"
21 #include "command/rs_message_processor.h"
22 #include "pipeline/rs_render_node.h"
23 #include "platform/common/rs_log.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 namespace {
28 constexpr float SECOND_TO_MILLISECOND = 1e3;
29 constexpr float MILLISECOND_TO_SECOND = 1e-3;
30 constexpr float FRAME_TIME_INTERVAL = 1.0f / 90.0f;
31 } // namespace
32
RSRenderInterpolatingSpringAnimation(AnimationId id,const PropertyId & propertyId,const std::shared_ptr<RSRenderPropertyBase> & originValue,const std::shared_ptr<RSRenderPropertyBase> & startValue,const std::shared_ptr<RSRenderPropertyBase> & endValue)33 RSRenderInterpolatingSpringAnimation::RSRenderInterpolatingSpringAnimation(AnimationId id, const PropertyId& propertyId,
34 const std::shared_ptr<RSRenderPropertyBase>& originValue, const std::shared_ptr<RSRenderPropertyBase>& startValue,
35 const std::shared_ptr<RSRenderPropertyBase>& endValue)
36 : RSRenderPropertyAnimation(id, propertyId, originValue), RSSpringModel<float>(), startValue_(startValue),
37 endValue_(endValue)
38 {
39 // spring model is not initialized, so we can't calculate estimated duration
40 }
41
DumpAnimationInfo(std::string & out) const42 void RSRenderInterpolatingSpringAnimation::DumpAnimationInfo(std::string& out) const
43 {
44 out.append("Type:RSRenderInterpolatingSpringAnimation");
45 DumpProperty(out);
46 RSPropertyType type = RSPropertyType::INVALID;
47 if (property_ != nullptr) {
48 type = property_->GetPropertyType();
49 }
50 out.append(", StartValue: ").append(RSAnimationTraceUtils::GetInstance().ParseRenderPropertyValue(startValue_));
51 out.append(", EndValue: ").append(RSAnimationTraceUtils::GetInstance().ParseRenderPropertyValue(endValue_));
52 }
53
SetSpringParameters(float response,float dampingRatio,float normalizedInitialVelocity,float minimumAmplitudeRatio)54 void RSRenderInterpolatingSpringAnimation::SetSpringParameters(
55 float response, float dampingRatio, float normalizedInitialVelocity, float minimumAmplitudeRatio)
56 {
57 response_ = response;
58 dampingRatio_ = std::clamp(dampingRatio, SPRING_MIN_DAMPING_RATIO, SPRING_MAX_DAMPING_RATIO);
59 normalizedInitialVelocity_ = normalizedInitialVelocity;
60 minimumAmplitudeRatio_ = minimumAmplitudeRatio;
61 }
62
SetZeroThreshold(float zeroThreshold)63 void RSRenderInterpolatingSpringAnimation::SetZeroThreshold(float zeroThreshold)
64 {
65 constexpr float ZERO = 0.0f;
66 if (zeroThreshold < ZERO) {
67 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::SetZeroThreshold: invalid threshold value.");
68 needLogicallyFinishCallback_ = false;
69 return;
70 }
71 zeroThreshold_ = zeroThreshold;
72 needLogicallyFinishCallback_ = true;
73 }
74
OnSetFraction(float fraction)75 void RSRenderInterpolatingSpringAnimation::OnSetFraction(float fraction)
76 {
77 if (valueEstimator_ == nullptr) {
78 return;
79 }
80 valueEstimator_->UpdateAnimationValue(fraction, GetAdditive());
81 SetValueFraction(fraction);
82 fractionChangeInfo_ = { true, fraction };
83 }
84
UpdateFractionAfterContinue()85 void RSRenderInterpolatingSpringAnimation::UpdateFractionAfterContinue()
86 {
87 auto& [bChangeFraction, valueFraction] = fractionChangeInfo_;
88 if (bChangeFraction) {
89 SetFractionInner(CalculateTimeFraction(valueFraction));
90 bChangeFraction = false;
91 valueFraction = 0.0f;
92 }
93 }
94
CalculateTimeFraction(float targetFraction)95 float RSRenderInterpolatingSpringAnimation::CalculateTimeFraction(float targetFraction)
96 {
97 int secondTime = std::ceil(static_cast<float>(GetDuration()) / SECOND_TO_MS);
98 if (secondTime <= 0) {
99 return FRACTION_MIN;
100 }
101 int64_t frameTimes = MAX_FRAME_TIME_FRACTION * secondTime;
102 float lastFraction = FRACTION_MIN;
103 for (int time = 1; time <= frameTimes; time++) {
104 float frameFraction = static_cast<float>(time) / frameTimes;
105 frameFraction = std::clamp(frameFraction, 0.0f, 1.0f);
106 auto mappedTime = frameFraction * GetDuration() * MILLISECOND_TO_SECOND;
107 float displacement = 1.0f + CalculateDisplacement(mappedTime);
108 if (lastFraction <= targetFraction && displacement >= targetFraction) {
109 return frameFraction;
110 }
111 lastFraction = displacement;
112 }
113 return FRACTION_MIN;
114 }
115
OnAnimate(float fraction)116 void RSRenderInterpolatingSpringAnimation::OnAnimate(float fraction)
117 {
118 if (valueEstimator_ == nullptr) {
119 ROSEN_LOGD("RSRenderInterpolatingSpringAnimation::OnAnimate, valueEstimator_ is nullptr.");
120 return;
121 }
122 if (GetPropertyId() == 0) {
123 // calculateAnimationValue_ is embedded modify for stat animate frame drop
124 calculateAnimationValue_ = false;
125 return;
126 } else if (ROSEN_EQ(fraction, 1.0f)) {
127 valueEstimator_->UpdateAnimationValue(1.0f, GetAdditive());
128 return;
129 }
130 auto mappedTime = fraction * GetDuration() * MILLISECOND_TO_SECOND;
131 float displacement = 1.0f + CalculateDisplacement(mappedTime);
132 SetValueFraction(displacement);
133 valueEstimator_->UpdateAnimationValue(displacement, GetAdditive());
134 if (GetNeedLogicallyFinishCallback() && (animationFraction_.GetRemainingRepeatCount() == 1)) {
135 auto interpolationValue = valueEstimator_->Estimate(displacement, startValue_, endValue_);
136 auto endValue = animationFraction_.GetCurrentIsReverseCycle() ? startValue_ : endValue_;
137 auto velocity = CalculateVelocity(mappedTime);
138 auto zeroValue = startValue_ - startValue_;
139 if (interpolationValue != nullptr && !interpolationValue->IsNearEqual(endValue, zeroThreshold_)) {
140 return;
141 }
142 if (velocity != nullptr && (velocity * FRAME_TIME_INTERVAL)->IsNearEqual(zeroValue, zeroThreshold_)) {
143 CallLogicallyFinishCallback();
144 needLogicallyFinishCallback_ = false;
145 }
146 }
147 }
148
OnInitialize(int64_t time)149 void RSRenderInterpolatingSpringAnimation::OnInitialize(int64_t time)
150 {
151 // set the initial status of spring model
152 initialOffset_ = -1.0f;
153 initialVelocity_ = initialOffset_ * (-normalizedInitialVelocity_);
154 CalculateSpringParameters();
155 // use duration calculated by spring model as animation duration
156 SetDuration(std::lroundf(EstimateDuration() * SECOND_TO_MILLISECOND));
157 // this will set needInitialize_ to false
158 RSRenderPropertyAnimation::OnInitialize(time);
159 }
160
InitValueEstimator()161 void RSRenderInterpolatingSpringAnimation::InitValueEstimator()
162 {
163 if (valueEstimator_ == nullptr) {
164 valueEstimator_ = property_->CreateRSValueEstimator(RSValueEstimatorType::CURVE_VALUE_ESTIMATOR);
165 }
166 if (valueEstimator_) {
167 valueEstimator_->InitCurveAnimationValue(property_, startValue_, endValue_, lastValue_);
168 } else {
169 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::InitValueEstimator, valueEstimator_ is nullptr.");
170 }
171 }
172
CalculateVelocity(float time) const173 std::shared_ptr<RSRenderPropertyBase> RSRenderInterpolatingSpringAnimation::CalculateVelocity(float time) const
174 {
175 if (valueEstimator_ == nullptr) {
176 ROSEN_LOGE("RSRenderInterpolatingSpringAnimation::CalculateVelocity, valueEstimator_ is nullptr.");
177 return nullptr;
178 }
179 constexpr float TIME_INTERVAL = 1e-6f; // 1e-6f : 1 microsecond
180 float currentDisplacement = 1.0f + CalculateDisplacement(time);
181 float nextDisplacement = 1.0f + CalculateDisplacement(time + TIME_INTERVAL);
182 auto velocity = (valueEstimator_->Estimate(nextDisplacement, startValue_, endValue_) -
183 valueEstimator_->Estimate(currentDisplacement, startValue_, endValue_)) * (1 / TIME_INTERVAL);
184
185 return velocity;
186 }
187
GetNeedLogicallyFinishCallback() const188 bool RSRenderInterpolatingSpringAnimation::GetNeedLogicallyFinishCallback() const
189 {
190 return needLogicallyFinishCallback_;
191 }
192
CallLogicallyFinishCallback() const193 void RSRenderInterpolatingSpringAnimation::CallLogicallyFinishCallback() const
194 {
195 NodeId targetId = GetTargetId();
196 AnimationId animationId = GetAnimationId();
197 uint64_t token = GetToken();
198
199 std::unique_ptr<RSCommand> command =
200 std::make_unique<RSAnimationCallback>(targetId, animationId, token, LOGICALLY_FINISHED);
201 RSMessageProcessor::Instance().AddUIMessage(ExtractPid(animationId), std::move(command));
202 }
203 } // namespace Rosen
204 } // namespace OHOS