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_path_animation.h"
17 
18 #include "animation/rs_value_estimator.h"
19 #include "pipeline/rs_canvas_render_node.h"
20 #include "platform/common/rs_log.h"
21 #include "render/rs_path.h"
22 #include "rs_profiler.h"
23 
24 namespace OHOS {
25 namespace Rosen {
RSRenderPathAnimation(AnimationId id,const PropertyId & propertyId,const std::shared_ptr<RSRenderPropertyBase> & originPosition,const std::shared_ptr<RSRenderPropertyBase> & startPosition,const std::shared_ptr<RSRenderPropertyBase> & endPosition,float originRotation,const std::shared_ptr<RSPath> & animationPath)26 RSRenderPathAnimation::RSRenderPathAnimation(AnimationId id, const PropertyId& propertyId,
27     const std::shared_ptr<RSRenderPropertyBase>& originPosition,
28     const std::shared_ptr<RSRenderPropertyBase>& startPosition,
29     const std::shared_ptr<RSRenderPropertyBase>& endPosition, float originRotation,
30     const std::shared_ptr<RSPath>& animationPath) : RSRenderPropertyAnimation(id, propertyId, originPosition),
31     originRotation_(originRotation), startValue_(startPosition), endValue_(endPosition),
32     animationPath_(animationPath)
33 {}
34 
DumpAnimationType(std::string & out) const35 void RSRenderPathAnimation::DumpAnimationType(std::string& out) const
36 {
37     out += "Type:RSRenderPathAnimation";
38 }
39 
SetInterpolator(const std::shared_ptr<RSInterpolator> & interpolator)40 void RSRenderPathAnimation::SetInterpolator(const std::shared_ptr<RSInterpolator>& interpolator)
41 {
42     interpolator_ = interpolator;
43 }
44 
GetInterpolator() const45 const std::shared_ptr<RSInterpolator>& RSRenderPathAnimation::GetInterpolator() const
46 {
47     return interpolator_;
48 }
49 
SetRotationMode(const RotationMode & rotationMode)50 void RSRenderPathAnimation::SetRotationMode(const RotationMode& rotationMode)
51 {
52     if (IsStarted()) {
53         ROSEN_LOGE("Failed to enable rotate, path animation has started!");
54         return;
55     }
56 
57     rotationMode_ = rotationMode;
58 }
59 
GetRotationMode() const60 RotationMode RSRenderPathAnimation::GetRotationMode() const
61 {
62     return rotationMode_;
63 }
64 
SetBeginFraction(float fraction)65 void RSRenderPathAnimation::SetBeginFraction(float fraction)
66 {
67     if (IsStarted()) {
68         ROSEN_LOGE("Failed to set begin fraction, path animation has started!");
69         return;
70     }
71 
72     if (fraction < FRACTION_MIN || fraction > FRACTION_MAX || fraction > endFraction_) {
73         ROSEN_LOGE("Failed to set begin fraction, invalid value:%{public}f", fraction);
74         return;
75     }
76 
77     beginFraction_ = fraction;
78 }
79 
GetBeginFraction() const80 float RSRenderPathAnimation::GetBeginFraction() const
81 {
82     return beginFraction_;
83 }
84 
SetEndFraction(float fraction)85 void RSRenderPathAnimation::SetEndFraction(float fraction)
86 {
87     if (IsStarted()) {
88         ROSEN_LOGE("Failed to set end fraction, path animation has started!");
89         return;
90     }
91 
92     if (fraction < FRACTION_MIN || fraction > FRACTION_MAX || fraction < beginFraction_) {
93         ROSEN_LOGE("Failed to set end fraction, invalid value:%{public}f", fraction);
94         return;
95     }
96 
97     endFraction_ = fraction;
98 }
99 
GetEndFraction() const100 float RSRenderPathAnimation::GetEndFraction() const
101 {
102     return endFraction_;
103 }
104 
SetIsNeedPath(const bool isNeedPath)105 void RSRenderPathAnimation::SetIsNeedPath(const bool isNeedPath)
106 {
107     isNeedPath_ = isNeedPath;
108 }
109 
SetPathNeedAddOrigin(bool needAddOrigin)110 void RSRenderPathAnimation::SetPathNeedAddOrigin(bool needAddOrigin)
111 {
112     if (IsStarted()) {
113         ROSEN_LOGE("Failed to set need Add Origin, path animation has started!");
114         return;
115     }
116 
117     needAddOrigin_ = needAddOrigin;
118 }
119 
SetRotationId(const PropertyId id)120 void RSRenderPathAnimation::SetRotationId(const PropertyId id)
121 {
122     rotationId_ = id;
123 }
124 
Marshalling(Parcel & parcel) const125 bool RSRenderPathAnimation::Marshalling(Parcel& parcel) const
126 {
127     if (!RSRenderPropertyAnimation::Marshalling(parcel)) {
128         ROSEN_LOGE("RSRenderPathAnimation::Marshalling, RenderPropertyAnimation failed");
129         return false;
130     }
131     if (!(parcel.WriteFloat(originRotation_) && parcel.WriteFloat(beginFraction_) && parcel.WriteFloat(endFraction_) &&
132             RSMarshallingHelper::Marshalling(parcel, animationPath_) &&
133             parcel.WriteInt32(static_cast<std::underlying_type<RotationMode>::type>(rotationMode_)) &&
134             parcel.WriteBool(isNeedPath_) && parcel.WriteBool(needAddOrigin_) && interpolator_ != nullptr &&
135             interpolator_->Marshalling(parcel) && RSRenderPropertyBase::Marshalling(parcel, startValue_) &&
136             RSRenderPropertyBase::Marshalling(parcel, endValue_) && parcel.WriteUint64(rotationId_))) {
137         ROSEN_LOGE("RSRenderPathAnimation::Marshalling, write failed");
138         return false;
139     }
140     return true;
141 }
142 
Unmarshalling(Parcel & parcel)143 RSRenderPathAnimation* RSRenderPathAnimation::Unmarshalling(Parcel& parcel)
144 {
145     RSRenderPathAnimation* renderPathAnimation = new RSRenderPathAnimation();
146 
147     if (!renderPathAnimation->ParseParam(parcel)) {
148         ROSEN_LOGE("RSRenderPathAnimation::Unmarshalling, Parse RenderProperty Fail");
149         delete renderPathAnimation;
150         return nullptr;
151     }
152     return renderPathAnimation;
153 }
154 
ParseParam(Parcel & parcel)155 bool RSRenderPathAnimation::ParseParam(Parcel& parcel)
156 {
157     if (!RSRenderPropertyAnimation::ParseParam(parcel)) {
158         ROSEN_LOGE("RSRenderPathAnimation::ParseParam, Parse RenderProperty Fail");
159         return false;
160     }
161 
162     int32_t rotationMode = 0;
163     bool isNeedPath = true;
164     if (!(parcel.ReadFloat(originRotation_) && parcel.ReadFloat(beginFraction_) &&
165             parcel.ReadFloat(endFraction_) && RSMarshallingHelper::Unmarshalling(parcel, animationPath_) &&
166             parcel.ReadInt32(rotationMode) && parcel.ReadBool(isNeedPath) && parcel.ReadBool(needAddOrigin_))) {
167         ROSEN_LOGE("RSRenderPathAnimation::ParseParam, Parse PathAnimation Failed");
168         return false;
169     }
170 
171     std::shared_ptr<RSInterpolator> interpolator(RSInterpolator::Unmarshalling(parcel));
172     if (interpolator == nullptr) {
173         ROSEN_LOGE("RSRenderPathAnimation::ParseParam, Unmarshalling interpolator failed");
174         return false;
175     }
176 
177     if (!(RSRenderPropertyBase::Unmarshalling(parcel, startValue_) &&
178             RSRenderPropertyBase::Unmarshalling(parcel, endValue_) && parcel.ReadUint64(rotationId_))) {
179         ROSEN_LOGE("RSRenderPathAnimation::ParseParam, Parse values failed");
180         return false;
181     }
182     RS_PROFILER_PATCH_NODE_ID(parcel, rotationId_);
183     SetInterpolator(interpolator);
184     SetRotationMode(static_cast<RotationMode>(rotationMode));
185     SetIsNeedPath(isNeedPath);
186     return true;
187 }
188 
OnAnimate(float fraction)189 void RSRenderPathAnimation::OnAnimate(float fraction)
190 {
191     if (animationPath_ == nullptr) {
192         ROSEN_LOGE("Failed to animate motion path, path is null!");
193         return;
194     }
195 
196     Vector2f position;
197     float tangent = 0.0;
198     GetPosTanValue(fraction, position, tangent);
199     auto valueVector2f = std::static_pointer_cast<RSRenderAnimatableProperty<Vector2f>>(GetOriginValue());
200     if (GetOriginValue()->GetPropertyType() == RSRenderPropertyType::PROPERTY_VECTOR2F) {
201         UpdateVector2fPathValue(position);
202         SetPathValue(position, tangent);
203         return;
204     }
205 
206     if (!isNeedPath_) {
207         if (valueEstimator_ == nullptr) {
208             return;
209         }
210         valueEstimator_->UpdateAnimationValue(interpolator_->Interpolate(fraction), GetAdditive());
211         return;
212     }
213 
214     auto vector4fValueEstimator = std::static_pointer_cast<RSCurveValueEstimator<Vector4f>>(valueEstimator_);
215     if (vector4fValueEstimator != nullptr) {
216         auto animationValue =
217             vector4fValueEstimator->GetAnimationValue(interpolator_->Interpolate(fraction), GetAdditive());
218         UpdateVector4fPathValue(animationValue, position);
219         SetPathValue(animationValue, tangent);
220     }
221 }
222 
OnRemoveOnCompletion()223 void RSRenderPathAnimation::OnRemoveOnCompletion()
224 {
225     auto target = GetTarget();
226     if (target == nullptr) {
227         ROSEN_LOGE("Failed to remove on completion, target is null!");
228         return;
229     }
230 
231     target->GetMutableRenderProperties().SetRotation(originRotation_);
232     RSRenderPropertyAnimation::OnRemoveOnCompletion();
233 }
234 
OnAttach()235 void RSRenderPathAnimation::OnAttach()
236 {
237     auto target = GetTarget();
238     if (target == nullptr) {
239         ROSEN_LOGE("RSRenderPathAnimation::OnAttach, target is nullptr");
240         return;
241     }
242     // check if any other path animation running on this property
243     auto propertyId = GetPropertyId();
244     auto prevAnimation = target->GetAnimationManager().QueryPathAnimation(propertyId);
245     target->GetAnimationManager().RegisterPathAnimation(propertyId, GetAnimationId());
246 
247     // return if no other path animation(s) running
248     if (prevAnimation == nullptr) {
249         return;
250     }
251 
252     // set previous path animation to FINISHED
253     prevAnimation->Finish();
254 }
255 
OnDetach()256 void RSRenderPathAnimation::OnDetach()
257 {
258     auto target = GetTarget();
259     if (target == nullptr) {
260         ROSEN_LOGE("RSRenderPathAnimation::OnDetach, target is nullptr");
261         return;
262     }
263     auto propertyId = GetPropertyId();
264     auto id = GetAnimationId();
265     target->GetAnimationManager().UnregisterPathAnimation(propertyId, id);
266 }
267 
SetPathValue(const Vector2f & value,float tangent)268 void RSRenderPathAnimation::SetPathValue(const Vector2f& value, float tangent)
269 {
270     SetRotationValue(tangent);
271     auto animatableProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Vector2f>>(property_);
272     if (animatableProperty != nullptr) {
273         animatableProperty->Set(value);
274     }
275 }
276 
SetPathValue(const Vector4f & value,float tangent)277 void RSRenderPathAnimation::SetPathValue(const Vector4f& value, float tangent)
278 {
279     SetRotationValue(tangent);
280     auto animatableProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Vector4f>>(property_);
281     if (animatableProperty != nullptr) {
282         animatableProperty->Set(value);
283     }
284 }
285 
SetRotationValue(const float tangent)286 void RSRenderPathAnimation::SetRotationValue(const float tangent)
287 {
288     switch (GetRotationMode()) {
289         case RotationMode::ROTATE_AUTO:
290             SetRotation(tangent);
291             break;
292         case RotationMode::ROTATE_AUTO_REVERSE:
293             SetRotation(tangent + 180.0f);
294             break;
295         case RotationMode::ROTATE_NONE:
296             break;
297         default:
298             ROSEN_LOGE("Unknow rotate mode!");
299             break;
300     }
301 }
302 
SetRotation(const float tangent)303 void RSRenderPathAnimation::SetRotation(const float tangent)
304 {
305     auto target = GetTarget();
306     if (target == nullptr) {
307         ROSEN_LOGE("Failed to set rotation value, target is null!");
308         return;
309     }
310 
311     auto modifier = target->GetModifier(rotationId_);
312     if (modifier != nullptr) {
313         auto property = std::static_pointer_cast<RSRenderProperty<float>>(modifier->GetProperty());
314         if (property != nullptr) {
315             property->Set(tangent);
316         }
317     }
318 }
319 
GetPosTanValue(float fraction,Vector2f & position,float & tangent)320 void RSRenderPathAnimation::GetPosTanValue(float fraction, Vector2f& position, float& tangent)
321 {
322     float distance = animationPath_->GetDistance();
323     float progress = GetBeginFraction() * (FRACTION_MAX - fraction) + GetEndFraction() * fraction;
324     animationPath_->GetPosTan(distance * progress, position, tangent);
325 }
326 
UpdateVector2fPathValue(Vector2f & value)327 void RSRenderPathAnimation::UpdateVector2fPathValue(Vector2f& value)
328 {
329     if (needAddOrigin_) {
330         auto animatableProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Vector2f>>(GetOriginValue());
331         if (animatableProperty) {
332             value += animatableProperty->Get();
333         }
334     }
335 }
336 
UpdateVector4fPathValue(Vector4f & value,const Vector2f & position)337 void RSRenderPathAnimation::UpdateVector4fPathValue(Vector4f& value, const Vector2f& position)
338 {
339     value[0] = position[0];
340     value[1] = position[1];
341     if (needAddOrigin_) {
342         auto animatableProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Vector4f>>(GetOriginValue());
343         if (animatableProperty) {
344             value[0] += animatableProperty->Get()[0];
345             value[1] += animatableProperty->Get()[1];
346         }
347     }
348 }
349 
InitValueEstimator()350 void RSRenderPathAnimation::InitValueEstimator()
351 {
352     if (valueEstimator_ == nullptr) {
353         valueEstimator_ = property_->CreateRSValueEstimator(RSValueEstimatorType::CURVE_VALUE_ESTIMATOR);
354     }
355 
356     if (valueEstimator_ == nullptr) {
357         ROSEN_LOGE("RSRenderPathAnimation::InitValueEstimator, valueEstimator_ is nullptr.");
358         return;
359     }
360     valueEstimator_->InitCurveAnimationValue(property_, startValue_, endValue_, lastValue_);
361 }
362 } // namespace Rosen
363 } // namespace OHOS
364