• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_render_spring_animation.h"
17 
18 #include "pipeline/rs_render_node.h"
19 #include "platform/common/rs_log.h"
20 
21 namespace OHOS {
22 namespace Rosen {
23 namespace {
24 constexpr static float SECOND_TO_MILLISECOND = 1e3;
25 constexpr static float MILLISECOND_TO_SECOND = 1e-3;
26 constexpr static float SECOND_TO_NANOSECOND = 1e9;
27 constexpr static float RESPONSE_THRESHOLD = 0.001f;
28 constexpr static float FRACTION_THRESHOLD = 0.001f;
29 } // namespace
30 
RSRenderSpringAnimation(AnimationId id,const PropertyId & propertyId,const std::shared_ptr<RSRenderPropertyBase> & originValue,const std::shared_ptr<RSRenderPropertyBase> & startValue,const std::shared_ptr<RSRenderPropertyBase> & endValue)31 RSRenderSpringAnimation::RSRenderSpringAnimation(AnimationId id, const PropertyId& propertyId,
32     const std::shared_ptr<RSRenderPropertyBase>& originValue,
33     const std::shared_ptr<RSRenderPropertyBase>& startValue,
34     const std::shared_ptr<RSRenderPropertyBase>& endValue)
35     : RSRenderPropertyAnimation(id, propertyId, originValue),
36     RSSpringModel<std::shared_ptr<RSRenderPropertyBase>>(),
37     startValue_(startValue), endValue_(endValue)
38 {
39     // spring model is not initialized, so we can't calculate estimated duration
40 }
41 
SetSpringParameters(float response,float dampingRatio,float blendDuration)42 void RSRenderSpringAnimation::SetSpringParameters(float response, float dampingRatio, float blendDuration)
43 {
44     response_ = response;
45     finalResponse_ = response;
46     dampingRatio_ = dampingRatio;
47     blendDuration_ = blendDuration * SECOND_TO_NANOSECOND; // convert to ns
48 }
49 
50 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel) const51 bool RSRenderSpringAnimation::Marshalling(Parcel& parcel) const
52 {
53     if (!RSRenderPropertyAnimation::Marshalling(parcel)) {
54         ROSEN_LOGE("RSRenderSpringAnimation::Marshalling, RenderPropertyAnimation failed");
55         return false;
56     }
57     if (!(RSRenderPropertyBase::Marshalling(parcel, startValue_) &&
58             RSRenderPropertyBase::Marshalling(parcel, endValue_))) {
59         ROSEN_LOGE("RSRenderSpringAnimation::Marshalling, MarshallingHelper failed");
60         return false;
61     }
62 
63     if (!(RSMarshallingHelper::Marshalling(parcel, response_) &&
64             RSMarshallingHelper::Marshalling(parcel, dampingRatio_) &&
65             RSMarshallingHelper::Marshalling(parcel, blendDuration_))) {
66         return false;
67     }
68 
69     return true;
70 }
71 
Unmarshalling(Parcel & parcel)72 RSRenderSpringAnimation* RSRenderSpringAnimation::Unmarshalling(Parcel& parcel)
73 {
74     auto* renderSpringAnimation = new RSRenderSpringAnimation();
75     if (!renderSpringAnimation->ParseParam(parcel)) {
76         ROSEN_LOGE("RSRenderSpringAnimation::Unmarshalling, failed");
77         delete renderSpringAnimation;
78         return nullptr;
79     }
80     return renderSpringAnimation;
81 }
82 
ParseParam(Parcel & parcel)83 bool RSRenderSpringAnimation::ParseParam(Parcel& parcel)
84 {
85     if (!RSRenderPropertyAnimation::ParseParam(parcel)) {
86         ROSEN_LOGE("RSRenderSpringAnimation::ParseParam, ParseParam Fail");
87         return false;
88     }
89 
90     if (!(RSRenderPropertyBase::Unmarshalling(parcel, startValue_) &&
91             RSRenderPropertyBase::Unmarshalling(parcel, endValue_))) {
92         return false;
93     }
94 
95     if (!(RSMarshallingHelper::Unmarshalling(parcel, response_) &&
96             RSMarshallingHelper::Unmarshalling(parcel, dampingRatio_) &&
97             RSMarshallingHelper::Unmarshalling(parcel, blendDuration_))) {
98         return false;
99     }
100     // copy response to final response
101     finalResponse_ = response_;
102 
103     return true;
104 }
105 #endif
106 
OnSetFraction(float fraction)107 void RSRenderSpringAnimation::OnSetFraction(float fraction)
108 {
109     // spring animation should not support set fraction
110     OnAnimate(fraction);
111 }
112 
OnAnimate(float fraction)113 void RSRenderSpringAnimation::OnAnimate(float fraction)
114 {
115     if (GetPropertyId() == 0) {
116         return;
117     } else if (ROSEN_EQ(fraction, 1.0f, FRACTION_THRESHOLD)) {
118         SetAnimationValue(endValue_);
119         prevMappedTime_ = GetDuration() * MILLISECOND_TO_SECOND;
120         return;
121     }
122     auto mappedTime = fraction * GetDuration() * MILLISECOND_TO_SECOND;
123     auto displacement = CalculateDisplacement(mappedTime);
124     SetAnimationValue(endValue_ + displacement);
125 
126     // keep the mapped time, this will be used to calculate instantaneous velocity
127     prevMappedTime_ = mappedTime;
128 }
129 
OnAttach()130 void RSRenderSpringAnimation::OnAttach()
131 {
132     auto target = GetTarget();
133     if (target == nullptr) {
134         ROSEN_LOGE("RSRenderSpringAnimation::OnAttach, target is nullptr");
135         return;
136     }
137     // check if any other spring animation running on this property
138     auto propertyId = GetPropertyId();
139     auto prevAnimation = target->GetAnimationManager().QuerySpringAnimation(propertyId);
140     target->GetAnimationManager().RegisterSpringAnimation(propertyId, GetAnimationId());
141 
142     // return if no other spring animation(s) running, or the other animation is finished
143     // meanwhile, align run time for both spring animations, prepare for status inheritance
144     if (prevAnimation == nullptr || prevAnimation->Animate(animationFraction_.GetLastFrameTime())) {
145         blendDuration_ = 0;
146         return;
147     }
148 
149     // extract spring status from previous spring animation
150     auto prevSpringAnimation = std::static_pointer_cast<RSRenderSpringAnimation>(prevAnimation);
151 
152     // inherit spring status from previous spring animation
153     InheritSpringStatus(prevSpringAnimation.get());
154     // inherit spring response
155     response_ = prevSpringAnimation->response_;
156     if (ROSEN_EQ(response_, finalResponse_, RESPONSE_THRESHOLD)) {
157         // if response is not changed, we can skip blend duration
158         blendDuration_ = 0;
159     } else if (blendDuration_ == 0) {
160         // if blend duration is not set, we can skip blend duration
161         response_ = finalResponse_;
162     } else if (ROSEN_EQ(finalResponse_, prevSpringAnimation->finalResponse_, RESPONSE_THRESHOLD)) {
163         // if previous spring is blending to the same final response, we can continue previous blending process
164         blendDuration_ = prevSpringAnimation->blendDuration_;
165     }
166 
167     // set previous spring animation to FINISHED
168     prevSpringAnimation->FinishOnCurrentPosition();
169 }
170 
OnDetach()171 void RSRenderSpringAnimation::OnDetach()
172 {
173     auto target = GetTarget();
174     if (target == nullptr) {
175         ROSEN_LOGE("RSRenderSpringAnimation::OnDetach, target is nullptr");
176         return;
177     }
178     auto propertyId = GetPropertyId();
179     auto id = GetAnimationId();
180     target->GetAnimationManager().UnregisterSpringAnimation(propertyId, id);
181 }
182 
OnInitialize(int64_t time)183 void RSRenderSpringAnimation::OnInitialize(int64_t time)
184 {
185     if (blendDuration_) {
186         auto lastFrameTime = animationFraction_.GetLastFrameTime();
187 
188         // reset animation fraction
189         InheritSpringStatus(this);
190         animationFraction_.ResetFraction();
191         prevMappedTime_ = 0.0f;
192 
193         // blend response by linear interpolation
194         uint64_t blendTime = (time - lastFrameTime) * animationFraction_.GetAnimationScale();
195         if (blendTime < blendDuration_) {
196             auto blendRatio = static_cast<float>(blendTime) / static_cast<float>(blendDuration_);
197             response_ += (finalResponse_ - response_) * blendRatio;
198             blendDuration_ -= blendTime;
199         } else {
200             // if blend duration is over, set response to final response
201             response_ = finalResponse_;
202             blendDuration_ = 0;
203         }
204     }
205 
206     // set the initial status of spring model
207     initialOffset_ = startValue_ - endValue_;
208     if (initialVelocity_ == nullptr) {
209         initialVelocity_ = initialOffset_ * 0.f;
210     }
211     CalculateSpringParameters();
212 
213     if (blendDuration_) {
214         // blend is still in progress, no need to estimate duration, use 300ms as default
215         SetDuration(300);
216     } else {
217         // blend finished, estimate duration until the spring system reaches rest
218         SetDuration(std::lroundf(EstimateDuration() * SECOND_TO_MILLISECOND));
219         // this will set needInitialize_ to false
220         RSRenderPropertyAnimation::OnInitialize(time);
221     }
222 }
223 
224 std::tuple<std::shared_ptr<RSRenderPropertyBase>, std::shared_ptr<RSRenderPropertyBase>>
GetSpringStatus() const225 RSRenderSpringAnimation::GetSpringStatus() const
226 {
227     // if animation is never started, return start value and initial velocity
228     if (ROSEN_EQ(prevMappedTime_, 0.0f, FRACTION_THRESHOLD)) {
229         return { startValue_, initialVelocity_ };
230     }
231 
232     auto displacement = lastValue_ - endValue_;
233 
234     // use average velocity over a small time interval to estimate instantaneous velocity
235     constexpr double TIME_INTERVAL = 1e-6f; // 1e-6f : 1 microsecond to seconds
236     auto velocity = (CalculateDisplacement(prevMappedTime_ + TIME_INTERVAL) - displacement) * (1 / TIME_INTERVAL);
237 
238     // return current position and velocity
239     return { lastValue_->Clone(), velocity };
240 }
241 
InheritSpringStatus(const RSRenderSpringAnimation * from)242 void RSRenderSpringAnimation::InheritSpringStatus(const RSRenderSpringAnimation* from)
243 {
244     // inherit spring status from another spring animation
245     std::tie(startValue_, initialVelocity_) = from->GetSpringStatus();
246     originValue_ = startValue_->Clone();
247     lastValue_ = startValue_->Clone();
248 }
249 } // namespace Rosen
250 } // namespace OHOS
251