• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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<PipelineContext> & context,int32_t index,double value)26 SimpleSpringNode::SimpleSpringNode(const WeakPtr<PipelineContext>& 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     }
82     SpringNode::EndToValue(endValue, velocity);
83     if (isRunning_) {
84         LOGD("EndToValue when running. index: %{public}d, endValue: %{public}.3lf, velocity: %{public}.3lf", index_,
85             endValue, velocity);
86         auto controlNode = adapter_->GetControlNode();
87         if (!controlNode) {
88             LOGE("End to value failed. control node is null. index: %{public}d", index_);
89             return;
90         }
91         if (controlNode->IsAnimateToEnd()) {
92             startTime_ = context->GetTimeFromExternalTimer() - static_cast<uint64_t>(FRAME_SCHEDULED);
93         } else {
94             startTime_ = context->GetTimeFromExternalTimer() - static_cast<uint64_t>(GetFrameDelta() * FRAME_SCHEDULED);
95         }
96         spring_->SetAccuracy(valueAccuracy_);
97         spring_->Reset(value_, endValue, velocity_, springProperty_);
98     } else {
99         LOGD("EndToValue first time. index: %{public}d, endValue: %{public}.3lf, velocity: %{public}.3lf", index_,
100             endValue, velocity);
101         startTime_ = context->GetTimeFromExternalTimer();
102         isRunning_ = true;
103         spring_->SetAccuracy(valueAccuracy_);
104         spring_->Reset(value_, endValue, velocity_, springProperty_);
105         OnAnimation();
106     }
107     NotifyNext(endValue, velocity);
108 }
109 
OnAnimation()110 void SimpleSpringNode::OnAnimation()
111 {
112     if (!isRunning_) {
113         return;
114     }
115     auto context = context_.Upgrade();
116     if (!context) {
117         LOGE("Animate failed, context is null. index: %{public}d", index_);
118         return;
119     }
120     if (!spring_) {
121         LOGE("Animate failed, spring is null. index: %{public}d", index_);
122         return;
123     }
124     int64_t delta = static_cast<int64_t>(context->GetTimeFromExternalTimer()) - static_cast<int64_t>(startTime_);
125     spring_->OnTimestampChanged(static_cast<double>(delta) / static_cast<double>(NANOS_TO_MILLS), 0.0f, false);
126     value_ = spring_->GetCurrentPosition();
127     velocity_ = spring_->GetCurrentVelocity();
128     if (spring_->IsCompleted()) {
129         isRunning_ = false;
130         value_ = spring_->GetEndValue();
131         velocity_ = 0.0;
132         // Node's animation update callback
133         OnUpdate(value_, velocity_);
134         NotifyUpdateListener(value_, velocity_);
135         OnEnd(value_);
136         scheduler_->Stop();
137     } else {
138         OnUpdate(value_, velocity_);
139         NotifyUpdateListener(value_, velocity_);
140         scheduler_->Start();
141     }
142 }
143 
Cancel()144 void SimpleSpringNode::Cancel()
145 {
146     scheduler_->Stop();
147     isRunning_ = false;
148     velocity_ = 0.0;
149     OnEnd(value_);
150 }
151 
ResetNode(double value,double velocity)152 void SimpleSpringNode::ResetNode(double value, double velocity)
153 {
154     LOGD("ResetNode. value: %{public}.3lf, velocity: %{public}.3lf", value, velocity);
155     value_ = value;
156     velocity_ = velocity;
157     OnUpdate(value_, velocity_);
158     NotifyUpdateListener(value_, velocity_);
159 }
160 
TransferParams(double stiffness,double damping)161 void SimpleSpringNode::TransferParams(double stiffness, double damping)
162 {
163     if (springProperty_) {
164         springProperty_->SetStiffness(stiffness);
165         springProperty_->SetDamping(damping);
166     }
167 }
168 
169 } // namespace OHOS::Ace