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 {
RSRenderSpringAnimation(AnimationId id,const PropertyId & propertyId,const std::shared_ptr<RSRenderPropertyBase> & originValue,const std::shared_ptr<RSRenderPropertyBase> & startValue,const std::shared_ptr<RSRenderPropertyBase> & endValue)23 RSRenderSpringAnimation::RSRenderSpringAnimation(AnimationId id, const PropertyId& propertyId,
24 const std::shared_ptr<RSRenderPropertyBase>& originValue,
25 const std::shared_ptr<RSRenderPropertyBase>& startValue,
26 const std::shared_ptr<RSRenderPropertyBase>& endValue)
27 : RSRenderPropertyAnimation(id, propertyId, originValue),
28 RSSpringModel<std::shared_ptr<RSRenderPropertyBase>>(),
29 startValue_(startValue), endValue_(endValue)
30 {
31 // spring model is not initialized, so we can't calculate estimated duration
32 }
33
SetSpringParameters(float response,float dampingRatio)34 void RSRenderSpringAnimation::SetSpringParameters(float response, float dampingRatio)
35 {
36 response_ = response;
37 dampingRatio_ = dampingRatio;
38 }
39
40 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel) const41 bool RSRenderSpringAnimation::Marshalling(Parcel& parcel) const
42 {
43 if (!RSRenderPropertyAnimation::Marshalling(parcel)) {
44 ROSEN_LOGE("RSRenderSpringAnimation::Marshalling, RenderPropertyAnimation failed");
45 return false;
46 }
47 if (!(RSRenderPropertyBase::Marshalling(parcel, startValue_) &&
48 RSRenderPropertyBase::Marshalling(parcel, endValue_))) {
49 ROSEN_LOGE("RSRenderSpringAnimation::Marshalling, MarshallingHelper failed");
50 return false;
51 }
52
53 if (!(RSMarshallingHelper::Marshalling(parcel, response_) &&
54 RSMarshallingHelper::Marshalling(parcel, dampingRatio_))) {
55 return false;
56 }
57
58 return true;
59 }
60
Unmarshalling(Parcel & parcel)61 RSRenderSpringAnimation* RSRenderSpringAnimation::Unmarshalling(Parcel& parcel)
62 {
63 auto* renderSpringAnimation = new RSRenderSpringAnimation();
64 if (!renderSpringAnimation->ParseParam(parcel)) {
65 ROSEN_LOGE("RSRenderSpringAnimation::Unmarshalling, failed");
66 delete renderSpringAnimation;
67 return nullptr;
68 }
69 return renderSpringAnimation;
70 }
71
ParseParam(Parcel & parcel)72 bool RSRenderSpringAnimation::ParseParam(Parcel& parcel)
73 {
74 if (!RSRenderPropertyAnimation::ParseParam(parcel)) {
75 ROSEN_LOGE("RSRenderSpringAnimation::ParseParam, ParseParam Fail");
76 return false;
77 }
78
79 if (!(RSRenderPropertyBase::Unmarshalling(parcel, startValue_) &&
80 RSRenderPropertyBase::Unmarshalling(parcel, endValue_))) {
81 return false;
82 }
83
84 if (!(RSMarshallingHelper::Unmarshalling(parcel, response_) &&
85 RSMarshallingHelper::Unmarshalling(parcel, dampingRatio_))) {
86 return false;
87 }
88
89 return true;
90 }
91 #endif
92
OnSetFraction(float fraction)93 void RSRenderSpringAnimation::OnSetFraction(float fraction)
94 {
95 // spring animation should not support set fraction
96 OnAnimate(fraction);
97 }
98
OnAnimate(float fraction)99 void RSRenderSpringAnimation::OnAnimate(float fraction)
100 {
101 if (GetPropertyId() == 0) {
102 return;
103 } else if (ROSEN_EQ(fraction, 1.0f)) {
104 SetAnimationValue(endValue_);
105 prevMappedTime_ = GetDuration() * MILLISECOND_TO_SECOND;
106 return;
107 }
108 auto mappedTime = fraction * GetDuration() * MILLISECOND_TO_SECOND;
109 auto displacement = CalculateDisplacement(mappedTime);
110 SetAnimationValue(endValue_ + displacement);
111
112 // keep the mapped time, this will be used to calculate instantaneous velocity
113 prevMappedTime_ = mappedTime;
114 }
115
OnAttach()116 void RSRenderSpringAnimation::OnAttach()
117 {
118 auto target = GetTarget();
119 if (target == nullptr) {
120 ROSEN_LOGE("RSRenderSpringAnimation::OnAttach, target is nullptr");
121 return;
122 }
123 // check if any other spring animation running on this property
124 auto propertyId = GetPropertyId();
125 auto prevAnimation = target->GetAnimationManager().QuerySpringAnimation(propertyId);
126 target->GetAnimationManager().RegisterSpringAnimation(propertyId, GetAnimationId());
127
128 // return if no other spring animation(s) running, or the other animation is finished
129 // meanwhile, align run time for both spring animations, prepare for status inheritance
130 if (prevAnimation == nullptr || prevAnimation->Animate(animationFraction_.GetLastFrameTime())) {
131 return;
132 }
133
134 // extract spring status from previous spring animation
135 auto prevSpringAnimation = std::static_pointer_cast<RSRenderSpringAnimation>(prevAnimation);
136 auto status = prevSpringAnimation->GetSpringStatus();
137
138 // inherit spring status from previous spring animation
139 startValue_ = std::get<0>(status);
140 originValue_ = startValue_->Clone();
141 lastValue_ = startValue_->Clone();
142 initialVelocity_ = std::get<1>(status);
143
144 // set previous spring animation to FINISHED
145 prevSpringAnimation->FinishOnCurrentPosition();
146 }
147
OnDetach()148 void RSRenderSpringAnimation::OnDetach()
149 {
150 auto target = GetTarget();
151 if (target == nullptr) {
152 ROSEN_LOGE("RSRenderSpringAnimation::OnDetach, target is nullptr");
153 return;
154 }
155 auto propertyId = GetPropertyId();
156 auto id = GetAnimationId();
157 target->GetAnimationManager().UnregisterSpringAnimation(propertyId, id);
158 }
159
OnInitialize()160 void RSRenderSpringAnimation::OnInitialize()
161 {
162 // set the initial status of spring model
163 initialOffset_ = startValue_ - endValue_;
164 if (initialVelocity_ == nullptr) {
165 initialVelocity_ = initialOffset_ * 0.f;
166 }
167 CalculateSpringParameters();
168 // use duration calculated by spring model as animation duration
169 SetDuration(std::lroundf(GetEstimatedDuration() * SECOND_TO_MILLISECOND));
170 }
171
172 std::tuple<std::shared_ptr<RSRenderPropertyBase>, std::shared_ptr<RSRenderPropertyBase>>
GetSpringStatus()173 RSRenderSpringAnimation::GetSpringStatus()
174 {
175 // if animation is never started, return start value and initial velocity
176 if (ROSEN_EQ(prevMappedTime_, 0.0f)) {
177 return { startValue_, initialVelocity_ };
178 }
179
180 auto displacement = lastValue_ - endValue_;
181
182 // use average velocity over a small time interval to estimate instantaneous velocity
183 constexpr double TIME_INTERVAL = 1e-6f; // 1e-6f : 1 microsecond to seconds
184 auto velocity = (CalculateDisplacement(prevMappedTime_ + TIME_INTERVAL) - displacement) * (1 / TIME_INTERVAL);
185
186 // return current position and velocity
187 return { lastValue_->Clone(), velocity };
188 }
189 } // namespace Rosen
190 } // namespace OHOS
191