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