• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/animation/simple_spring_node.h"
17 
18 namespace OHOS::Ace {
19 namespace {
20 
21 constexpr int32_t FRAME_SCHEDULED = 16;
22 constexpr int64_t NANOS_TO_MILLS = 1000000;
23 
24 } // namespace
25 
SimpleSpringNode(const WeakPtr<PipelineBase> & context,int32_t index,double value)26 SimpleSpringNode::SimpleSpringNode(const WeakPtr<PipelineBase>& context, int32_t index, double value)
27     : SpringNode(index), context_(context), value_(value)
28 {
29     springProperty_ = AceType::MakeRefPtr<SpringProperty>();
30     spring_ = AceType::MakeRefPtr<SpringMotion>(0.0, 0.0, 0.0, springProperty_);
31     spring_->SetAccuracy(valueAccuracy_);
32     auto&& callback = [weak = AceType::WeakClaim(this)](uint64_t duration) {
33         auto node = weak.Upgrade();
34         if (!node || !node->adapter_) {
35             LOGE("Empty node or adapter, skip tick callback.");
36             return;
37         }
38         auto context = node->context_.Upgrade();
39         if (!context) {
40             return;
41         }
42         node->adapter_->TickAnimation(context->GetTimeFromExternalTimer());
43     };
44     scheduler_ = AceType::MakeRefPtr<Scheduler>(callback, context);
45 }
46 
SetValue(double value)47 void SimpleSpringNode::SetValue(double value)
48 {
49     SpringNode::SetValue(value);
50     value_ = value;
51     OnUpdate(value_, velocity_);
52     NotifyUpdateListener(value_, velocity_);
53     NotifyNext(value_, velocity_);
54 }
55 
NotifyNext(double endValue,double initVelocity)56 void SimpleSpringNode::NotifyNext(double endValue, double initVelocity)
57 {
58     if (!adapter_) {
59         LOGE("Notify next failed. Adapter is null. index: %{public}d", index_);
60         return;
61     }
62     if (this != AceType::RawPtr(adapter_->GetControlNode())) {
63         return;
64     }
65     auto currentNode = adapter_->GetNext(AceType::WeakClaim(this).Upgrade());
66     while (currentNode) {
67         currentNode->EndToValue(endValue, initVelocity);
68         currentNode = adapter_->GetNext(currentNode);
69     }
70 }
71 
EndToValue(double endValue,double velocity)72 void SimpleSpringNode::EndToValue(double endValue, double velocity)
73 {
74     if (!adapter_) {
75         LOGE("End to value failed. adapter is null. index: %{public}d", index_);
76         return;
77     }
78     auto context = context_.Upgrade();
79     if (!context) {
80         LOGE("End to value failed, context is null. index: %{public}d", index_);
81         return;
82     }
83     SpringNode::EndToValue(endValue, velocity);
84     if (isRunning_) {
85         LOGD("EndToValue when running. index: %{public}d, endValue: %{public}.3lf, velocity: %{public}.3lf", index_,
86             endValue, velocity);
87         auto controlNode = adapter_->GetControlNode();
88         if (!controlNode) {
89             LOGE("End to value failed. control node is null. index: %{public}d", index_);
90             return;
91         }
92         if (controlNode->IsAnimateToEnd()) {
93             startTime_ = context->GetTimeFromExternalTimer() - static_cast<uint64_t>(FRAME_SCHEDULED);
94         } else {
95             startTime_ = context->GetTimeFromExternalTimer() - static_cast<uint64_t>(GetFrameDelta() * FRAME_SCHEDULED);
96         }
97         spring_->SetAccuracy(valueAccuracy_);
98         spring_->Reset(value_, endValue, velocity_, springProperty_);
99     } else {
100         LOGD("EndToValue first time. index: %{public}d, endValue: %{public}.3lf, velocity: %{public}.3lf", index_,
101             endValue, velocity);
102         startTime_ = context->GetTimeFromExternalTimer();
103         isRunning_ = true;
104         spring_->SetAccuracy(valueAccuracy_);
105         spring_->Reset(value_, endValue, velocity_, springProperty_);
106         OnAnimation();
107     }
108     NotifyNext(endValue, velocity);
109 }
110 
OnAnimation()111 void SimpleSpringNode::OnAnimation()
112 {
113     if (!isRunning_) {
114         return;
115     }
116     auto context = context_.Upgrade();
117     if (!context) {
118         LOGE("Animate failed, context is null. index: %{public}d", index_);
119         return;
120     }
121     if (!spring_) {
122         LOGE("Animate failed, spring is null. index: %{public}d", index_);
123         return;
124     }
125     int64_t delta = static_cast<int64_t>(context->GetTimeFromExternalTimer()) - static_cast<int64_t>(startTime_);
126     spring_->OnTimestampChanged(static_cast<double>(delta) / static_cast<double>(NANOS_TO_MILLS), 0.0f, false);
127     value_ = spring_->GetCurrentPosition();
128     velocity_ = spring_->GetCurrentVelocity();
129     if (spring_->IsCompleted()) {
130         isRunning_ = false;
131         value_ = spring_->GetEndValue();
132         velocity_ = 0.0;
133         // Node's animation update callback
134         OnUpdate(value_, velocity_);
135         NotifyUpdateListener(value_, velocity_);
136         OnEnd(value_);
137         scheduler_->Stop();
138     } else {
139         OnUpdate(value_, velocity_);
140         NotifyUpdateListener(value_, velocity_);
141         scheduler_->Start();
142     }
143 }
144 
Cancel()145 void SimpleSpringNode::Cancel()
146 {
147     scheduler_->Stop();
148     isRunning_ = false;
149     velocity_ = 0.0;
150     OnEnd(value_);
151 }
152 
ResetNode(double value,double velocity)153 void SimpleSpringNode::ResetNode(double value, double velocity)
154 {
155     LOGD("ResetNode. value: %{public}.3lf, velocity: %{public}.3lf", value, velocity);
156     value_ = value;
157     velocity_ = velocity;
158     OnUpdate(value_, velocity_);
159     NotifyUpdateListener(value_, velocity_);
160 }
161 
TransferParams(double stiffness,double damping)162 void SimpleSpringNode::TransferParams(double stiffness, double damping)
163 {
164     if (springProperty_) {
165         springProperty_->SetStiffness(stiffness);
166         springProperty_->SetDamping(damping);
167     }
168 }
169 
170 } // namespace OHOS::Ace