1 /*
2  * Copyright (c) 2021-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_keyframe_animation.h"
17 
18 #include "animation/rs_render_keyframe_animation.h"
19 #include "command/rs_animation_command.h"
20 #include "modifier/rs_property.h"
21 #include "transaction/rs_transaction_proxy.h"
22 #include "ui/rs_node.h"
23 #include "platform/common/rs_log.h"
24 
25 static constexpr int DURATION_MIN = 0;
26 static constexpr int DURATION_VALUE_INDEX = 2;
27 
28 namespace OHOS {
29 namespace Rosen {
RSKeyframeAnimation(std::shared_ptr<RSPropertyBase> property)30 RSKeyframeAnimation::RSKeyframeAnimation(std::shared_ptr<RSPropertyBase> property) : RSPropertyAnimation(property)
31 {}
32 
AddKeyFrame(float fraction,const std::shared_ptr<RSPropertyBase> & value,const RSAnimationTimingCurve & timingCurve)33 void RSKeyframeAnimation::AddKeyFrame(float fraction, const std::shared_ptr<RSPropertyBase>& value,
34     const RSAnimationTimingCurve& timingCurve)
35 {
36     if (fraction < FRACTION_MIN || fraction > FRACTION_MAX) {
37         return;
38     }
39 
40     if (IsStarted()) {
41         return;
42     }
43 
44     keyframes_.push_back({ fraction, value, timingCurve });
45 }
46 
AddKeyFrames(const std::vector<std::tuple<float,std::shared_ptr<RSPropertyBase>,RSAnimationTimingCurve>> & keyframes)47 void RSKeyframeAnimation::AddKeyFrames(
48     const std::vector<std::tuple<float, std::shared_ptr<RSPropertyBase>, RSAnimationTimingCurve>>& keyframes)
49 {
50     if (IsStarted()) {
51         return;
52     }
53 
54     keyframes_ = keyframes;
55 }
56 
AddKeyFrame(int startDuration,int endDuration,const std::shared_ptr<RSPropertyBase> & value,const RSAnimationTimingCurve & timingCurve)57 void RSKeyframeAnimation::AddKeyFrame(int startDuration, int endDuration,
58     const std::shared_ptr<RSPropertyBase>& value, const RSAnimationTimingCurve& timingCurve)
59 {
60     if (startDuration > endDuration) {
61         return;
62     }
63 
64     if (IsStarted()) {
65         return;
66     }
67 
68     durationKeyframes_.push_back({ startDuration, endDuration, value, timingCurve });
69 }
70 
SetDurationKeyframe(bool isDuration)71 void RSKeyframeAnimation::SetDurationKeyframe(bool isDuration)
72 {
73     isDurationKeyframe_ = isDuration;
74 }
75 
InitInterpolationValue()76 void RSKeyframeAnimation::InitInterpolationValue()
77 {
78     if (isDurationKeyframe_) {
79         if (durationKeyframes_.empty()) {
80             return;
81         }
82 
83         auto beginKeyframe = durationKeyframes_.front();
84         durationKeyframes_.insert(durationKeyframes_.begin(),
85             { DURATION_MIN, DURATION_MIN, GetOriginValue(), RSAnimationTimingCurve::LINEAR });
86 
87         startValue_ = std::get<DURATION_VALUE_INDEX>(durationKeyframes_.front());
88         endValue_ = std::get<DURATION_VALUE_INDEX>(durationKeyframes_.back());
89         RSPropertyAnimation::InitInterpolationValue();
90         return;
91     }
92 
93     if (keyframes_.empty()) {
94         return;
95     }
96 
97     auto beginKeyframe = keyframes_.front();
98     if (std::abs(std::get<FRACTION_INDEX>(beginKeyframe) - FRACTION_MIN) > EPSILON) {
99         keyframes_.insert(keyframes_.begin(), { FRACTION_MIN, GetOriginValue(), RSAnimationTimingCurve::LINEAR });
100     }
101 
102     startValue_ = std::get<VALUE_INDEX>(keyframes_.front());
103     endValue_ = std::get<VALUE_INDEX>(keyframes_.back());
104     RSPropertyAnimation::InitInterpolationValue();
105 }
106 
StartRenderAnimation(const std::shared_ptr<RSRenderKeyframeAnimation> & animation)107 void RSKeyframeAnimation::StartRenderAnimation(const std::shared_ptr<RSRenderKeyframeAnimation>& animation)
108 {
109     auto target = GetTarget().lock();
110     if (target == nullptr) {
111         ROSEN_LOGE("Failed to start keyframe animation, target is null!");
112         return;
113     }
114     auto transactionProxy = RSTransactionProxy::GetInstance();
115     if (transactionProxy == nullptr) {
116         ROSEN_LOGE("Failed to start keyframe animation, transaction proxy is null!");
117         return;
118     }
119 
120     std::unique_ptr<RSCommand> command = std::make_unique<RSAnimationCreateKeyframe>(target->GetId(), animation);
121     transactionProxy->AddCommand(command, target->IsRenderServiceNode(), target->GetFollowType(), target->GetId());
122     if (target->NeedForcedSendToRemote()) {
123         std::unique_ptr<RSCommand> commandForRemote =
124             std::make_unique<RSAnimationCreateKeyframe>(target->GetId(), animation);
125         transactionProxy->AddCommand(commandForRemote, true, target->GetFollowType(), target->GetId());
126     }
127 }
128 
StartUIAnimation(const std::shared_ptr<RSRenderKeyframeAnimation> & animation)129 void RSKeyframeAnimation::StartUIAnimation(const std::shared_ptr<RSRenderKeyframeAnimation>& animation)
130 {
131     StartCustomAnimation(animation);
132 }
133 
OnStart()134 void RSKeyframeAnimation::OnStart()
135 {
136     RSPropertyAnimation::OnStart();
137     if (keyframes_.empty() && durationKeyframes_.empty()) {
138         ROSEN_LOGE("Failed to start keyframe animation, keyframes is null!");
139         return;
140     }
141     auto animation = std::make_shared<RSRenderKeyframeAnimation>(GetId(), GetPropertyId(),
142         originValue_->GetRenderProperty());
143     animation->SetDurationKeyframe(isDurationKeyframe_);
144     animation->SetAdditive(GetAdditive());
145     UpdateParamToRenderAnimation(animation);
146     if (isDurationKeyframe_) {
147         for (const auto& [startDuration, endDuration, value, curve] : durationKeyframes_) {
148             animation->AddKeyframe(startDuration, endDuration, value->GetRenderProperty(),
149                 curve.GetInterpolator(GetDuration()));
150         }
151     } else {
152         for (const auto& [fraction, value, curve] : keyframes_) {
153             animation->AddKeyframe(fraction, value->GetRenderProperty(), curve.GetInterpolator(GetDuration()));
154         }
155     }
156     if (isCustom_) {
157         animation->AttachRenderProperty(property_->GetRenderProperty());
158         StartUIAnimation(animation);
159     } else {
160         StartRenderAnimation(animation);
161     }
162 }
163 } // namespace Rosen
164 } // namespace OHOS
165