1 /*
2  * Copyright (c) 2021 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 "core/animation/simple_spring_chain.h"
17 
18 namespace OHOS::Ace {
19 namespace {
20 
21 constexpr double DEFAULT_CHAIN_STIFFNESS = 228.0;
22 constexpr double DEFAULT_CHAIN_DAMPING = 30.0;
23 const RefPtr<SpringProperty> DEFAULT_OVER_SPRING_PROPERTY =
24     AceType::MakeRefPtr<SpringProperty>(1.0, DEFAULT_CHAIN_STIFFNESS, DEFAULT_CHAIN_DAMPING);
25 constexpr double DEFAULT_FRICTION = 1.0;
26 constexpr int32_t DEFAULT_CHAIN_FRAME_DELTA = 1;
27 
28 } // namespace
29 
SimpleSpringChain(const RefPtr<SpringAdapter> & springAdapter)30 SimpleSpringChain::SimpleSpringChain(const RefPtr<SpringAdapter>& springAdapter)
31 {
32     if (springAdapter) {
33         springAdapter_ = springAdapter;
34     } else {
35         springAdapter_ = AceType::MakeRefPtr<SimpleSpringAdapter>();
36     }
37     springAdapter_->SetObserve(AceType::WeakClaim(this));
38     stiffnessTransfer_ = AceType::MakeRefPtr<ExpParamTransfer>(1.0);
39     dampingTransfer_ = AceType::MakeRefPtr<ExpParamTransfer>(0.0);
40     controlStiffness_ = DEFAULT_CHAIN_STIFFNESS;
41     controlDamping_ = DEFAULT_CHAIN_DAMPING;
42     frameDelta_ = DEFAULT_CHAIN_FRAME_DELTA;
43 }
44 
OnNodeAdd(RefPtr<SpringNode> & node)45 void SimpleSpringChain::OnNodeAdd(RefPtr<SpringNode>& node)
46 {
47     if (!node) {
48         return;
49     }
50     SetParams(node);
51 }
52 
OnNodeDelete(RefPtr<SpringNode> & node)53 void SimpleSpringChain::OnNodeDelete(RefPtr<SpringNode>& node)
54 {
55     if (!node) {
56         return;
57     }
58     auto next = springAdapter_->GetNext(node);
59     while (next) {
60         next->SetIndex(next->GetIndex() - 1);
61         SetParams(next);
62         next = springAdapter_->GetNext(next);
63     }
64 }
65 
SetDeltaValue(double delta)66 void SimpleSpringChain::SetDeltaValue(double delta)
67 {
68     for (int32_t index = 0; index < springAdapter_->GetSize(); index++) {
69         auto node = springAdapter_->GetNode(index);
70         if (node) {
71             node->SetDeltaValue(delta);
72         }
73     }
74 }
75 
SetValue(double value)76 void SimpleSpringChain::SetValue(double value)
77 {
78     auto node = springAdapter_->GetControlNode();
79     if (node) {
80         node->SetValue(value);
81     }
82 }
83 
FlushAnimation()84 void SimpleSpringChain::FlushAnimation()
85 {
86     // flush from control to edge.
87     springAdapter_->FlushAnimation();
88 }
89 
EndToPosition(double value,double velocity)90 void SimpleSpringChain::EndToPosition(double value, double velocity)
91 {
92     auto node = springAdapter_->GetControlNode();
93     if (node) {
94         node->EndToValue(value, velocity);
95     }
96 }
97 
Cancel()98 void SimpleSpringChain::Cancel()
99 {
100     auto currentNode = springAdapter_->GetControlNode();
101     for (int32_t idx = 0; idx < springAdapter_->GetSize(); idx++) {
102         if (currentNode) {
103             currentNode->Cancel();
104             currentNode = springAdapter_->GetNext(currentNode);
105         } else {
106             LOGW("Node size mismatch. size: %{public}d, current size: %{public}d", springAdapter_->GetSize(), idx + 1);
107             break;
108         }
109     }
110 }
111 
TransferParamsInternal()112 void SimpleSpringChain::TransferParamsInternal()
113 {
114     for (int32_t idx = 0; idx < springAdapter_->GetSize(); idx++) {
115         auto currentNode = springAdapter_->GetNode(idx);
116         SetParams(currentNode);
117     }
118 }
119 
SetParams(RefPtr<SpringNode> & node)120 void SimpleSpringChain::SetParams(RefPtr<SpringNode>& node)
121 {
122     int32_t index = node->GetIndex();
123     auto controlNode = springAdapter_->GetControlNode();
124     if (!controlNode) {
125         controlNode = node;
126     }
127     int32_t delta = std::abs(index - controlNode->GetIndex());
128     double transferStiffness = stiffnessTransfer_->Transfer(controlStiffness_, delta);
129     double transferDamping = dampingTransfer_->Transfer(controlDamping_, delta);
130     node->TransferParams(transferStiffness, transferDamping);
131     node->SetFrameDelta(frameDelta_);
132     node->SetDecoration(decoration_);
133     // make sure minDecoration <= decoration <= maxDecoration
134     node->SetMinDecoration(std::min(minDecoration_, decoration_));
135     node->SetMaxDecoration(std::max(maxDecoration_, decoration_));
136     if (!node->GetAdapter()) {
137         node->SetAdapter(springAdapter_);
138     }
139 }
140 
GetDefaultOverSpringProperty()141 const RefPtr<SpringProperty>& SpringChainProperty::GetDefaultOverSpringProperty()
142 {
143     return DEFAULT_OVER_SPRING_PROPERTY;
144 }
145 
GetDefaultFriction()146 double SpringChainProperty::GetDefaultFriction()
147 {
148     return DEFAULT_FRICTION;
149 }
150 
151 } // namespace OHOS::Ace