• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "track_animation.h"
17 
18 #include <meta/ext/serialization/serializer.h>
19 
20 META_BEGIN_NAMESPACE()
21 
22 namespace Internal {
23 
GetParams()24 AnimationState::AnimationStateParams TrackAnimation::GetParams()
25 {
26     AnimationState::AnimationStateParams params;
27     params.owner = GetSelf<IAnimation>();
28     params.runningProperty = META_ACCESS_PROPERTY(Running);
29     params.progressProperty = META_ACCESS_PROPERTY(Progress);
30     params.totalDuration = META_ACCESS_PROPERTY(TotalDuration);
31     return params;
32 }
33 
Build(const IMetadata::Ptr & data)34 bool TrackAnimation::Build(const IMetadata::Ptr& data)
35 {
36     if (Super::Build(data)) {
37         TrackAnimationState::TrackDataParams params { META_ACCESS_PROPERTY(Timestamps) };
38         GetState().SetTrackDataParams(BASE_NS::move(params));
39 
40         auto updateKf = MakeCallback<IOnChanged>(this, &TrackAnimation::UpdateKeyframes);
41 
42         META_ACCESS_PROPERTY(Timestamps)->OnChanged()->AddHandler(updateKf);
43         constexpr BASE_NS::string_view name = "Keyframes";
44         keyframes_ = GetObjectRegistry().GetPropertyRegister().Create(ClassId::StackProperty, name);
45         if (keyframes_) {
46             keyframes_->OnChanged()->AddHandler(updateKf);
47             AddProperty(keyframes_);
48         }
49         UpdateKeyframes();
50         return keyframes_ != nullptr;
51     }
52     return false;
53 }
54 
Initialize()55 void TrackAnimation::Initialize()
56 {
57     ResetTrack();
58 }
59 
OnAnimationStateChanged(const IAnimationInternal::AnimationStateChangedInfo & info)60 void TrackAnimation::OnAnimationStateChanged(const IAnimationInternal::AnimationStateChangedInfo& info)
61 {
62     using AnimationTargetState = IAnimationInternal::AnimationTargetState;
63     if (auto p = GetTargetProperty()) {
64         switch (info.state) {
65             case AnimationTargetState::FINISHED:
66                 [[fallthrough]];
67             case AnimationTargetState::STOPPED:
68                 // Evaluate current value
69                 Evaluate();
70                 // Remove ourselves from the target property's stack
71                 RemoveModifier(p.stack);
72                 // Then set the correct keyframe value to the underlying property
73                 if (auto value = GetState().GetCurrentValue()) {
74                     PropertyLock lock { p.property };
75                     lock->SetValueAny(*value);
76                 }
77                 break;
78             case AnimationTargetState::RUNNING:
79                 // Evaluate current value
80                 Evaluate();
81                 // Add ourselves to the target property's stack
82                 p.stack->AddModifier(GetSelf<IModifier>());
83                 break;
84             case AnimationTargetState::PAUSED: {
85                 // Evaluate current value
86                 Evaluate();
87                 // Make sure we are in the target property's stack
88                 auto mymod = GetSelf<IModifier>();
89                 for (auto&& v : p.stack->GetModifiers({ ITrackAnimation::UID }, false)) {
90                     if (v == mymod) {
91                         mymod.reset();
92                     }
93                 }
94                 if (mymod) {
95                     p.stack->AddModifier(mymod);
96                 }
97             } break;
98             default:
99                 break;
100         }
101     }
102 }
103 
ProcessOnGet(IAny & value)104 EvaluationResult TrackAnimation::ProcessOnGet(IAny& value)
105 {
106     if (auto& currentValue = GetState().GetCurrentValue()) {
107         if (auto result = value.CopyFrom(*currentValue)) {
108             return result == AnyReturn::NOTHING_TO_DO ? EvaluationResult::EVAL_CONTINUE
109                                                       : EvaluationResult::EVAL_VALUE_CHANGED;
110         }
111     }
112     return EvaluationResult::EVAL_CONTINUE;
113 }
114 
Start()115 void TrackAnimation::Start()
116 {
117     GetState().Start();
118 }
119 
Stop()120 void TrackAnimation::Stop()
121 {
122     GetState().Stop();
123 }
124 
Pause()125 void TrackAnimation::Pause()
126 {
127     GetState().Pause();
128 }
129 
Restart()130 void TrackAnimation::Restart()
131 {
132     GetState().Restart();
133 }
134 
Finish()135 void TrackAnimation::Finish()
136 {
137     GetState().Finish();
138 }
139 
Seek(float position)140 void TrackAnimation::Seek(float position)
141 {
142     GetState().Seek(position);
143 }
144 
Step(const IClock::ConstPtr & clock)145 void TrackAnimation::Step(const IClock::ConstPtr& clock)
146 {
147     GetState().Step(clock);
148 }
149 
Evaluate()150 void TrackAnimation::Evaluate()
151 {
152     float progress = META_ACCESS_PROPERTY_VALUE(Progress);
153     if (auto curve = META_ACCESS_PROPERTY_VALUE(Curve)) {
154         progress = curve->Transform(progress);
155     }
156     const auto trackState = GetState().UpdateIndex(progress);
157     const PropertyAnimationState::EvaluationData data { GetState().GetCurrentValue(), GetState().GetCurrentTrackStart(),
158         GetState().GetCurrentTrackEnd(), trackState.second,
159         META_ACCESS_PROPERTY(KeyframeCurves)->GetValueAt(trackState.first) };
160     const auto status = GetState().EvaluateValue(data);
161     UpdateCurrentTrack(trackState.first);
162     if (status == AnyReturn::SUCCESS) {
163         NotifyChanged();
164         if (auto prop = GetTargetProperty()) {
165             PropertyLock lock { prop.property };
166             prop.stack->EvaluateAndStore();
167         }
168     }
169 }
170 
RemoveModifier(const IStackProperty::Ptr & stack)171 void TrackAnimation::RemoveModifier(const IStackProperty::Ptr& stack)
172 {
173     if (stack) {
174         stack->RemoveModifier(GetSelf<IModifier>());
175     }
176 }
177 
OnPropertyChanged(const TargetProperty & property,const IStackProperty::Ptr & previous)178 void TrackAnimation::OnPropertyChanged(const TargetProperty& property, const IStackProperty::Ptr& previous)
179 {
180     if (previous && GetState().IsRunning()) {
181         // Property changed while running, clean up previous property's stack
182         RemoveModifier(previous);
183         if (auto p = interface_cast<IProperty>(previous)) {
184             PropertyLock lock { p };
185             lock->SetValueAny(*GetState().GetCurrentValue());
186         }
187     }
188 
189     Initialize();
190 
191     if (auto p = GetTargetProperty()) {
192         PropertyLock lock { p.property };
193         auto& value = lock->GetValueAny();
194         bool alreadyCompatible = value.GetTypeId() == GetState().GetKeyframeItemTypeId();
195         if (!alreadyCompatible) {
196             IAny::Ptr array {};
197             if (!value.IsArray()) {
198                 // Clone the target property's value to an array of the value's underlying type
199                 array = value.Clone(AnyCloneOptions { CloneValueType::DEFAULT_VALUE, TypeIdRole::ARRAY });
200             } else {
201                 CORE_LOG_E("TrackAnimation: Cannot animate array types");
202             }
203             if (!array) {
204                 CORE_LOG_E("TrackAnimation: Failed to create an array of target property type");
205             }
206             if (auto kf = interface_pointer_cast<IArrayAny>(array)) {
207                 keyframes_->SetValue(*kf);
208             } else {
209                 keyframes_->ResetValue();
210             }
211         }
212     }
213 
214     UpdateValid();
215 }
216 
AddKeyframe(float timestamp,const IAny::ConstPtr & value)217 size_t TrackAnimation::AddKeyframe(float timestamp, const IAny::ConstPtr& value)
218 {
219     auto index = GetState().AddKeyframe(timestamp, value);
220     if (index != ITrackAnimation::INVALID_INDEX) {
221         keyframes_->NotifyChange();
222     }
223     return index;
224 }
225 
RemoveKeyframe(size_t index)226 bool TrackAnimation::RemoveKeyframe(size_t index)
227 {
228     bool success = false;
229     if (GetState().RemoveKeyframe(index)) {
230         keyframes_->NotifyChange();
231         success = true;
232     } else {
233         CORE_LOG_E("TrackAnimation: Cannot remove keyframe from index %u.", static_cast<uint32_t>(index));
234     }
235     return success;
236 }
237 
RemoveAllKeyframes()238 void TrackAnimation::RemoveAllKeyframes()
239 {
240     Stop();
241     META_ACCESS_PROPERTY(Timestamps)->Reset();
242     keyframes_->ResetValue();
243     UpdateValid();
244 }
245 
UpdateKeyframes()246 void TrackAnimation::UpdateKeyframes()
247 {
248     IArrayAny::Ptr kfArray;
249     if (auto stack = interface_cast<IStackProperty>(keyframes_)) {
250         // Get the topmost IArrayAny value, that should be our keyframe array
251         auto values = stack->GetValues({}, true);
252         for (auto it = values.rbegin(); it != values.rend(); ++it) {
253             if (auto arr = interface_pointer_cast<IArrayAny>(*it)) {
254                 kfArray = arr;
255                 break;
256             }
257         }
258     }
259     GetState().SetKeyframes(kfArray);
260     UpdateValid();
261 }
262 
UpdateValid()263 void TrackAnimation::UpdateValid()
264 {
265     bool valid = false;
266     auto timestamps = META_ACCESS_PROPERTY(Timestamps);
267 
268     if (const auto p = GetTargetProperty(); p && timestamps) {
269         valid = GetState().UpdateValid();
270     }
271 
272     if (valid != META_ACCESS_PROPERTY_VALUE(Valid)) {
273         if (!valid) {
274             Stop();
275             ResetTrack();
276         }
277         SetValue(META_ACCESS_PROPERTY(Valid), valid);
278     }
279 
280     GetState().ResetCurrentTrack();
281 }
282 
ResetTrack()283 void TrackAnimation::ResetTrack()
284 {
285     GetState().ResetCurrentTrack();
286     SetValue(META_ACCESS_PROPERTY(CurrentKeyframeIndex), -1);
287 }
288 
UpdateCurrentTrack(uint32_t index)289 void TrackAnimation::UpdateCurrentTrack(uint32_t index)
290 {
291     auto currentIndex = META_ACCESS_PROPERTY_VALUE(CurrentKeyframeIndex);
292     if (currentIndex != index) {
293         SetValue(META_ACCESS_PROPERTY(CurrentKeyframeIndex), index);
294         if (auto f = META_ACCESS_PROPERTY(KeyframeHandlers)->GetValueAt(index)) {
295             CallMetaFunction<void>(f);
296         }
297     }
298 }
299 
Export(IExportContext & c) const300 ReturnError TrackAnimation::Export(IExportContext& c) const
301 {
302     return Serializer(c) & AutoSerialize() & NamedValue("Keyframes", keyframes_);
303 }
Import(IImportContext & c)304 ReturnError TrackAnimation::Import(IImportContext& c)
305 {
306     return Serializer(c) & AutoSerialize() & NamedValue("Keyframes", keyframes_);
307 }
Finalize(IImportFunctions & f)308 ReturnError TrackAnimation::Finalize(IImportFunctions& f)
309 {
310     auto res = Super::Finalize(f);
311     if (res) {
312         UpdateKeyframes();
313     }
314     return res;
315 }
316 } // namespace Internal
317 
318 META_END_NAMESPACE()
319