• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "chain_animation.h"
17 
18 #include "core/pipeline/pipeline_base.h"
19 
20 namespace OHOS::Ace {
21 namespace {
22 constexpr int64_t NANOS_TO_MILLS = 1000000;
23 constexpr int32_t CHAIN_NODE_NUMBER = 15;
24 constexpr double DEFAULT_CHAIN_VALUE_ACCURACY = 0.5;
25 constexpr double DEFAULT_CHAIN_VALUE_VELOCITY_ACCURACY = 1000.0;
26 } // namespace
27 
ChainAnimationNode(int32_t index,float space,float maxSpace,float minSpace,RefPtr<SpringProperty> springProperty)28 ChainAnimationNode::ChainAnimationNode(
29     int32_t index, float space, float maxSpace, float minSpace, RefPtr<SpringProperty> springProperty)
30     : springProperty_(std::move(springProperty)), index_(index), space_(space), maxSpace_(maxSpace),
31       minSpace_(minSpace), curPosition_(space)
32 {
33     spring_ = AceType::MakeRefPtr<SpringMotion>(space, space, 0.0, springProperty_);
34     spring_->SetAccuracy(DEFAULT_CHAIN_VALUE_ACCURACY);
35     spring_->SetVelocityAccuracy(DEFAULT_CHAIN_VALUE_VELOCITY_ACCURACY);
36 }
37 
TickAnimation(float duration)38 bool ChainAnimationNode::TickAnimation(float duration)
39 {
40     spring_->OnTimestampChanged(duration, 0.0f, false);
41     curPosition_ = spring_->GetCurrentPosition();
42     curVelocity_ = spring_->GetCurrentVelocity();
43     return spring_->IsCompleted();
44 }
45 
SetDelta(float delta,float spaceDelta,float duration)46 void ChainAnimationNode::SetDelta(float delta, float spaceDelta, float duration)
47 {
48     spaceDelta = std::clamp(spaceDelta, minSpace_ - space_, maxSpace_ - space_);
49     spring_->OnTimestampChanged(duration, 0.0f, false);
50     curPosition_ = spring_->GetCurrentPosition();
51     curPosition_ = std::clamp(curPosition_ + delta, minSpace_ - spaceDelta, maxSpace_ - spaceDelta);
52     spring_->Reset(curPosition_, space_, curVelocity_, springProperty_);
53     spaceDelta_ = spaceDelta;
54 }
55 
GetDeltaPredict(float delta,float duration)56 float ChainAnimationNode::GetDeltaPredict(float delta, float duration)
57 {
58     spring_->OnTimestampChanged(duration, 0.0f, false);
59     float curPosition = spring_->GetCurrentPosition();
60     curPosition = std::clamp(curPosition + delta, minSpace_, maxSpace_);
61     return curPosition - space_;
62 }
63 
GetDelta() const64 float ChainAnimationNode::GetDelta() const
65 {
66     return curPosition_ - space_ + spaceDelta_;
67 }
68 
ChainAnimation(float space,float maxSpace,float minSpace,RefPtr<SpringProperty> springProperty)69 ChainAnimation::ChainAnimation(float space, float maxSpace, float minSpace, RefPtr<SpringProperty> springProperty)
70     : springProperty_(springProperty), space_(space), maxSpace_(maxSpace), minSpace_(minSpace)
71 {
72     for (int32_t i = 1; i < CHAIN_NODE_NUMBER; i++) {
73         nodes_.emplace(i, AceType::MakeRefPtr<ChainAnimationNode>(i, space, maxSpace, minSpace, springProperty));
74         nodes_.emplace(-i, AceType::MakeRefPtr<ChainAnimationNode>(-i, space, maxSpace, minSpace, springProperty));
75     }
76     auto&& callback = [weak = AceType::WeakClaim(this)](uint64_t duration) {
77         ACE_SCOPED_TRACE("ChainAnimation");
78         auto chain = weak.Upgrade();
79         CHECK_NULL_VOID(chain);
80         chain->TickAnimation();
81     };
82     scheduler_ = AceType::MakeRefPtr<Scheduler>(callback, PipelineBase::GetCurrentContext());
83 }
84 
SetDelta(float delta,float overOffset)85 void ChainAnimation::SetDelta(float delta, float overOffset)
86 {
87     auto context = PipelineBase::GetCurrentContext();
88     CHECK_NULL_VOID(context);
89     auto timestamp = context->GetVsyncTime();
90     double duration = 0.0;
91     if (timestamp > timestamp_) {
92         duration = static_cast<double>(timestamp - timestamp_) / static_cast<double>(NANOS_TO_MILLS);
93     }
94     float factor = (1 - conductivity_) * intensity_;
95     if (edgeEffect_ == ChainEdgeEffect::STRETCH) {
96         float spaceDelta = std::abs(overOffset) * edgeEffectIntensity_;
97         for (int32_t i = 1; i < CHAIN_NODE_NUMBER; i++) {
98             nodes_[i]->SetDelta(delta * factor, spaceDelta, static_cast<float>(duration));
99             nodes_[-i]->SetDelta(-delta * factor, spaceDelta, static_cast<float>(duration));
100             factor *= conductivity_;
101         }
102     } else {
103         float spaceDelta = overOffset * edgeEffectIntensity_;
104         for (int32_t i = 1; i < CHAIN_NODE_NUMBER; i++) {
105             nodes_[i]->SetDelta(delta * factor, -spaceDelta, static_cast<float>(duration));
106             nodes_[-i]->SetDelta(-delta * factor, spaceDelta, static_cast<float>(duration));
107             factor *= conductivity_;
108             spaceDelta *= conductivity_;
109         }
110     }
111     if (!scheduler_->IsActive() && !NearZero(delta)) {
112         scheduler_->Start();
113     }
114     timestamp_ = timestamp;
115 }
116 
HasSpaceDelta() const117 bool ChainAnimation::HasSpaceDelta() const
118 {
119     return !NearZero(nodes_.at(1)->GetSpaceDelta());
120 }
121 
ResetSpaceDelta()122 void ChainAnimation::ResetSpaceDelta()
123 {
124     for (int32_t i = 1; i < CHAIN_NODE_NUMBER; i++) {
125         nodes_[i]->SetSpaceDelta(0);
126         nodes_[-i]->SetSpaceDelta(0);
127     }
128 }
129 
TickAnimation()130 void ChainAnimation::TickAnimation()
131 {
132     auto context = PipelineBase::GetCurrentContext();
133     CHECK_NULL_VOID(context);
134     auto timestamp = context->GetVsyncTime();
135     double duration = 0.0;
136     if (timestamp > timestamp_) {
137         duration = static_cast<double>(timestamp - timestamp_) / static_cast<double>(NANOS_TO_MILLS);
138     }
139     auto finish = true;
140     for (int32_t i = 1; i < CHAIN_NODE_NUMBER; i++) {
141         finish = nodes_[i]->TickAnimation(duration) && finish;
142         finish = nodes_[-i]->TickAnimation(duration) && finish;
143     }
144     if (finish) {
145         scheduler_->Stop();
146     }
147     if (animationCallback_) {
148         animationCallback_();
149     }
150 }
151 
GetValue(int32_t index)152 float ChainAnimation::GetValue(int32_t index)
153 {
154     float value = 0.0f;
155     if (index > controlIndex_) {
156         for (int32_t i = 1; i <= index - controlIndex_ && i < CHAIN_NODE_NUMBER; i++) {
157             value += nodes_[i]->GetDelta();
158         }
159     } else if (index < controlIndex_) {
160         for (int32_t i = 1; i <= controlIndex_ - index && i < CHAIN_NODE_NUMBER; i++) {
161             value -= nodes_[-i]->GetDelta();
162         }
163     }
164     return value;
165 }
166 
GetValuePredict(int32_t index,float delta)167 float ChainAnimation::GetValuePredict(int32_t index, float delta)
168 {
169     auto context = PipelineBase::GetCurrentContext();
170     CHECK_NULL_RETURN(context, 0);
171     auto timestamp = context->GetVsyncTime();
172     double duration = 0.0;
173     if (timestamp > timestamp_) {
174         duration = static_cast<double>(timestamp - timestamp_) / static_cast<double>(NANOS_TO_MILLS);
175     }
176     float value = 0.0f;
177     float factor = (1 - conductivity_) * intensity_;
178     if (index > controlIndex_) {
179         for (int32_t i = 1; i <= index - controlIndex_ && i < CHAIN_NODE_NUMBER; i++) {
180             value += nodes_[i]->GetDeltaPredict(delta * factor, duration);
181             factor *= conductivity_;
182         }
183     } else if (index < controlIndex_) {
184         for (int32_t i = 1; i <= controlIndex_ - index && i < CHAIN_NODE_NUMBER; i++) {
185             value -= nodes_[-i]->GetDeltaPredict(-delta * factor, duration);
186             factor *= conductivity_;
187         }
188     }
189     return value;
190 }
191 
SetControlIndex(int32_t index)192 float ChainAnimation::SetControlIndex(int32_t index)
193 {
194     if (index == controlIndex_) {
195         return 0.0f;
196     }
197     float delta = GetValue(index);
198     if (scheduler_->IsActive()) {
199         std::map<int32_t, RefPtr<ChainAnimationNode>> tmpNodes;
200         int32_t dt = index - controlIndex_;
201         for (int32_t i = 1; i < CHAIN_NODE_NUMBER; i++) {
202             auto next = i + dt <= 0 ? i + dt - 1 : i + dt;
203             if (next > -CHAIN_NODE_NUMBER && next < CHAIN_NODE_NUMBER) {
204                 tmpNodes[i] = nodes_[next];
205                 tmpNodes[i]->SetIndex(i);
206             } else {
207                 tmpNodes.emplace(
208                     i, AceType::MakeRefPtr<ChainAnimationNode>(i, space_, maxSpace_, minSpace_, springProperty_));
209             }
210             auto prev = dt - i >= 0 ? dt - i + 1 : dt - i;
211             if (prev > -CHAIN_NODE_NUMBER && prev < CHAIN_NODE_NUMBER) {
212                 tmpNodes[-i] = nodes_[prev];
213                 tmpNodes[-i]->SetIndex(-i);
214             } else {
215                 tmpNodes.emplace(
216                     -i, AceType::MakeRefPtr<ChainAnimationNode>(-i, space_, maxSpace_, minSpace_, springProperty_));
217             }
218         }
219         nodes_.swap(tmpNodes);
220     }
221     controlIndex_ = index;
222     return delta;
223 }
224 
SetSpace(float space,float maxSpace,float minSpace)225 void ChainAnimation::SetSpace(float space, float maxSpace, float minSpace)
226 {
227     space_ = space;
228     maxSpace_ = maxSpace;
229     minSpace_ = minSpace;
230     for (int32_t i = 1; i < CHAIN_NODE_NUMBER; i++) {
231         nodes_[i]->SetSpace(space, maxSpace, minSpace);
232         nodes_[-i]->SetSpace(space, maxSpace, minSpace);
233     }
234 }
235 } // namespace OHOS::Ace
236