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 #ifndef META_SRC_ANIMATION_H
16 #define META_SRC_ANIMATION_H
17
18 #include <meta/api/make_callback.h>
19 #include <meta/ext/event_util.h>
20 #include <meta/interface/animation/builtin_animations.h>
21 #include <meta/interface/animation/intf_animation.h>
22 #include <meta/interface/intf_containable.h>
23 #include <meta/interface/serialization/intf_serializable.h>
24
25 #include "../object.h"
26 #include "animation_state.h"
27 #include "staggered_animation_state.h"
28
META_BEGIN_NAMESPACE()29 META_BEGIN_NAMESPACE()
30
31 namespace Internal {
32
33 /**
34 * @brief A base class which can be used by generic animation implementations.
35 */
36 template<class BaseAnimationInterface>
37 class BaseAnimationFwd : public IntroduceInterfaces<MetaObject, BaseAnimationInterface, INotifyOnChange, IAttachment,
38 IContainable, IMutableContainable, IAnimationInternal> {
39 static_assert(BASE_NS::is_convertible_v<BaseAnimationInterface*, IAnimation*>,
40 "BaseAnimationInterface of BaseAnimationFwd must inherit from IAnimation");
41
42 using MyBase = IntroduceInterfaces<MetaObject, BaseAnimationInterface, INotifyOnChange, IAttachment, IContainable,
43 IMutableContainable, IAnimationInternal>;
44 META_OBJECT_NO_CLASSINFO(BaseAnimationFwd, MyBase)
45
46 protected:
47 BaseAnimationFwd() = default;
48 ~BaseAnimationFwd() override = default;
49
50 protected: // IObject
51 BASE_NS::string GetName() const override
52 {
53 return META_ACCESS_PROPERTY_VALUE(Name);
54 }
55
56 protected: // ILifecycle
57 bool Build(const IMetadata::Ptr& data) override
58 {
59 if (Super::Build(data)) {
60 META_ACCESS_PROPERTY(Name)->SetDefaultValue(Super::GetName());
61 return GetState().Initialize(BASE_NS::move(GetParams()));
62 }
63 return false;
64 }
65 void Destroy() override
66 {
67 GetState().Uninitialize();
68 Super::Destroy();
69 }
70
71 virtual AnimationState::AnimationStateParams GetParams() = 0;
72
73 protected: // IContainable
74 IObject::Ptr GetParent() const override
75 {
76 return parent_.lock();
77 }
78
79 protected: // IMutableContainable
80 void SetParent(const IObject::Ptr& parent) override
81 {
82 parent_ = parent;
83 }
84
85 protected: // IAttach
86 bool Attach(const IObject::Ptr& attachment, const IObject::Ptr& dataContext) override
87 {
88 return GetState().Attach(attachment, dataContext);
89 }
90 bool Detach(const IObject::Ptr& attachment) override
91 {
92 return GetState().Detach(attachment);
93 }
94
95 protected: // IAnimationInternal
96 void ResetClock() override
97 {
98 GetState().ResetClock();
99 }
100
101 bool Move(const IAnimationInternal::MoveParams& move) override
102 {
103 return GetState().Move(move).changed;
104 }
105
106 void OnAnimationStateChanged(const IAnimationInternal::AnimationStateChangedInfo& info) override
107 {
108 Evaluate();
109 }
110 void OnEvaluationNeeded() override
111 {
112 Evaluate();
113 }
114
115 protected: // IAttachment
116 bool Attaching(const IAttach::Ptr& target, const IObject::Ptr& dataContext) override
117 {
118 SetValue(META_ACCESS_PROPERTY(AttachedTo), target);
119 SetValue(META_ACCESS_PROPERTY(DataContext), dataContext);
120 return true;
121 }
122 bool Detaching(const IAttach::Ptr& target) override
123 {
124 SetValue(META_ACCESS_PROPERTY(AttachedTo), {});
125 SetValue(META_ACCESS_PROPERTY(DataContext), {});
126 return true;
127 }
128
129 protected: // IAnimation
130 void Step(const IClock::ConstPtr& clock) override
131 {
132 GetState().Step(clock);
133 }
134
135 protected: // INotifyOnChange
136 void NotifyChanged()
137 {
138 Invoke<IOnChanged>(EventOnChanged(MetadataQuery::EXISTING));
139 }
140
141 protected:
142 virtual void Evaluate() = 0;
143 virtual Internal::AnimationState& GetState() noexcept = 0;
144
145 public:
146 META_BEGIN_STATIC_DATA()
147 META_STATIC_PROPERTY_DATA(INamed, BASE_NS::string, Name)
148 META_STATIC_PROPERTY_DATA(IAttachment, IObject::WeakPtr, DataContext)
149 META_STATIC_PROPERTY_DATA(IAttachment, IAttach::WeakPtr, AttachedTo)
150 META_STATIC_PROPERTY_DATA(IAnimation, bool, Enabled, true)
151 META_STATIC_PROPERTY_DATA(IAnimation, bool, Valid, {}, DEFAULT_PROPERTY_FLAGS_NO_SER)
152 META_STATIC_PROPERTY_DATA(IAnimation, TimeSpan, TotalDuration, {}, DEFAULT_PROPERTY_FLAGS_NO_SER)
153 META_STATIC_PROPERTY_DATA(IAnimation, bool, Running, {}, DEFAULT_PROPERTY_FLAGS_NO_SER)
154 META_STATIC_PROPERTY_DATA(IAnimation, float, Progress, {}, DEFAULT_PROPERTY_FLAGS_NO_SER)
155 META_STATIC_PROPERTY_DATA(IAnimation, IAnimationController::WeakPtr, Controller, {}, DEFAULT_PROPERTY_FLAGS_NO_SER)
156 META_STATIC_PROPERTY_DATA(IAnimation, ICurve1D::Ptr, Curve)
157 META_STATIC_EVENT_DATA(IAnimation, IOnChanged, OnFinished)
158 META_STATIC_EVENT_DATA(IAnimation, IOnChanged, OnStarted)
159 META_STATIC_EVENT_DATA(INotifyOnChange, IOnChanged, OnChanged)
160 META_END_STATIC_DATA()
161
162 META_IMPLEMENT_PROPERTY(BASE_NS::string, Name)
163 META_IMPLEMENT_READONLY_PROPERTY(IObject::WeakPtr, DataContext)
164 META_IMPLEMENT_READONLY_PROPERTY(IAttach::WeakPtr, AttachedTo)
165 META_IMPLEMENT_PROPERTY(bool, Enabled)
166 META_IMPLEMENT_READONLY_PROPERTY(bool, Valid)
167 META_IMPLEMENT_READONLY_PROPERTY(TimeSpan, TotalDuration)
168 META_IMPLEMENT_READONLY_PROPERTY(bool, Running)
169 META_IMPLEMENT_READONLY_PROPERTY(float, Progress)
170 META_IMPLEMENT_PROPERTY(IAnimationController::WeakPtr, Controller)
171 META_IMPLEMENT_PROPERTY(ICurve1D::Ptr, Curve)
172 META_IMPLEMENT_EVENT(IOnChanged, OnFinished)
173 META_IMPLEMENT_EVENT(IOnChanged, OnStarted)
174 META_IMPLEMENT_EVENT(IOnChanged, OnChanged)
175
176 private:
177 IObject::WeakPtr parent_;
178 };
179
180 template<class BaseAnimationInterface>
181 class BaseStartableAnimationFwd
182 : public IntroduceInterfaces<BaseAnimationFwd<BaseAnimationInterface>, IStartableAnimation> {
183 using Super = IntroduceInterfaces<BaseAnimationFwd<BaseAnimationInterface>, IStartableAnimation>;
184 using Super::GetState;
185
186 protected: // IStartableAnimation
187 void Pause() override
188 {
189 GetState().Pause();
190 }
191 void Restart() override
192 {
193 GetState().Restart();
194 }
195 void Seek(float position) override
196 {
197 GetState().Seek(position);
198 }
199 void Start() override
200 {
201 GetState().Start();
202 }
203 void Stop() override
204 {
205 GetState().Stop();
206 }
207 void Finish() override
208 {
209 GetState().Finish();
210 }
211 };
212
213 /**
214 * @brief A base class which can be used by animation container implementations.
215 */
216 template<class BaseAnimationInterface>
217 class BaseAnimationContainerFwd : public IntroduceInterfaces<BaseStartableAnimationFwd<BaseAnimationInterface>,
218 IContainer, ILockable, IIterable, IImportFinalize> {
219 static_assert(BASE_NS::is_convertible_v<BaseAnimationInterface*, IStaggeredAnimation*>,
220 "BaseAnimationInterface of BaseAnimationContainerFwd must inherit from IStaggeredAnimation");
221 using Super = IntroduceInterfaces<BaseStartableAnimationFwd<BaseAnimationInterface>, IContainer, ILockable,
222 IIterable, IImportFinalize>;
223 using IContainer::SizeType;
224
225 public: // ILockable
226 void Lock() const override
227 {
228 if (auto lockable = interface_cast<ILockable>(&GetContainer())) {
229 lockable->Lock();
230 }
231 }
232 void Unlock() const override
233 {
234 if (auto lockable = interface_cast<ILockable>(&GetContainer())) {
235 lockable->Unlock();
236 }
237 }
238 void LockShared() const override
239 {
240 if (auto lockable = interface_cast<ILockable>(&GetContainer())) {
241 lockable->LockShared();
242 }
243 }
244 void UnlockShared() const override
245 {
246 if (auto lockable = interface_cast<ILockable>(&GetContainer())) {
247 lockable->UnlockShared();
248 }
249 }
250
251 protected:
252 Internal::StaggeredAnimationState& GetState() noexcept override = 0;
253
254 ReturnError Finalize(IImportFunctions&) override
255 {
256 GetState().ChildrenChanged();
257 return GenericError::SUCCESS;
258 }
259
260 public: // IIterable
261 IterationResult Iterate(const IterationParameters& params) override
262 {
263 auto iterable = interface_cast<IIterable>(&GetContainer());
264 return iterable ? iterable->Iterate(params) : IterationResult::FAILED;
265 }
266 IterationResult Iterate(const IterationParameters& params) const override
267 {
268 const auto iterable = interface_cast<IIterable>(&GetContainer());
269 return iterable ? iterable->Iterate(params) : IterationResult::FAILED;
270 }
271
272 public: // IContainer
273 bool Add(const IObject::Ptr& object) override
274 {
275 return GetContainer().Add(object);
276 }
277 bool Insert(SizeType index, const IObject::Ptr& object) override
278 {
279 return GetContainer().Insert(index, object);
280 }
281 bool Remove(SizeType index) override
282 {
283 return GetContainer().Remove(index);
284 }
285 bool Remove(const IObject::Ptr& child) override
286 {
287 return GetContainer().Remove(child);
288 }
289 bool Move(SizeType fromIndex, SizeType toIndex) override
290 {
291 return GetContainer().Move(fromIndex, toIndex);
292 }
293 bool Move(const IObject::Ptr& child, SizeType toIndex) override
294 {
295 return GetContainer().Move(child, toIndex);
296 }
297 bool Replace(const IObject::Ptr& child, const IObject::Ptr& replaceWith, bool addAlways) override
298 {
299 return GetContainer().Replace(child, replaceWith, addAlways);
300 }
301 BASE_NS::vector<IObject::Ptr> GetAll() const override
302 {
303 return GetContainer().GetAll();
304 }
305 void RemoveAll() override
306 {
307 GetContainer().RemoveAll();
308 }
309 IObject::Ptr GetAt(SizeType index) const override
310 {
311 return GetContainer().GetAt(index);
312 }
313 SizeType GetSize() const override
314 {
315 return GetContainer().GetSize();
316 }
317 BASE_NS::vector<IObject::Ptr> FindAll(const IContainer::FindOptions& options) const override
318 {
319 return GetContainer().FindAll(options);
320 }
321 IObject::Ptr FindAny(const IContainer::FindOptions& options) const override
322 {
323 return GetContainer().FindAny(options);
324 }
325 IObject::Ptr FindByName(BASE_NS::string_view name) const override
326 {
327 return GetContainer().FindByName(name);
328 }
329 bool IsAncestorOf(const IObject::ConstPtr& object) const override
330 {
331 return GetContainer().IsAncestorOf(object);
332 }
333
334 META_FORWARD_EVENT(IEvent, OnContainerChanged, GetContainer().EventOnContainerChanged)
335
336 protected: // IStaggeredAnimation
337 void AddAnimation(const IAnimation::Ptr& animation) override
338 {
339 GetContainer().Add(animation);
340 }
341 void RemoveAnimation(const IAnimation::Ptr& animation) override
342 {
343 GetContainer().Remove(animation);
344 }
345 BASE_NS::vector<IAnimation::Ptr> GetAnimations() const override
346 {
347 return GetContainer().template GetAll<IAnimation>();
348 }
349
350 protected:
351 virtual IContainer& GetContainer() noexcept = 0;
352 virtual const IContainer& GetContainer() const noexcept = 0;
353 };
354
355 /**
356 * @brief A base class which can be used by property animation implementations.
357 */
358 template<class BaseAnimationInterface>
359 class BasePropertyAnimationFwd : public IntroduceInterfaces<BaseAnimationFwd<BaseAnimationInterface>,
360 IPropertyAnimation, IModifier, IImportFinalize> {
361 static_assert(BASE_NS::is_convertible_v<BaseAnimationInterface*, ITimedAnimation*>,
362 "BaseAnimationInterface of BasePropertyAnimationFwd must inherit from ITimedAnimation");
363
364 using MyBase =
365 IntroduceInterfaces<BaseAnimationFwd<BaseAnimationInterface>, IPropertyAnimation, IModifier, IImportFinalize>;
366 META_OBJECT_NO_CLASSINFO(BasePropertyAnimationFwd, MyBase)
367
368 protected:
369 BasePropertyAnimationFwd() = default;
370 ~BasePropertyAnimationFwd() override = default;
371
372 protected: // ILifecycle
373 bool Build(const IMetadata::Ptr& data) override
374 {
375 if (Super::Build(data)) {
376 META_ACCESS_PROPERTY(Property)->OnChanged()->AddHandler(
377 MakeCallback<IOnChanged>(this, &BasePropertyAnimationFwd::PropertyChanged));
378 return true;
379 }
380 return false;
381 }
382
383 public:
384 META_BEGIN_STATIC_DATA()
385 META_STATIC_PROPERTY_DATA(IPropertyAnimation, IProperty::WeakPtr, Property)
386 META_STATIC_PROPERTY_DATA(ITimedAnimation, TimeSpan, Duration)
387 META_END_STATIC_DATA()
388 META_IMPLEMENT_PROPERTY(IProperty::WeakPtr, Property)
389 META_IMPLEMENT_PROPERTY(TimeSpan, Duration)
390
391 protected: // IModifier
392 EvaluationResult ProcessOnGet(IAny& value) override
393 {
394 return EvaluationResult::EVAL_CONTINUE;
395 }
396 EvaluationResult ProcessOnSet(IAny& value, const IAny& current) override
397 {
398 return EvaluationResult::EVAL_CONTINUE;
399 }
400 bool IsCompatible(const TypeId& id) const override
401 {
402 if (auto p = GetTargetProperty()) {
403 return META_NS::IsCompatible(p.property->GetValue(), id);
404 }
405 return false;
406 }
407 Internal::PropertyAnimationState& GetState() noexcept override = 0;
408
409 protected:
410 ReturnError Finalize(IImportFunctions&) override
411 {
412 GetState().UpdateTotalDuration();
413 auto p = GetTargetProperty();
414 GetState().SetInterpolator(p ? p.property->GetTypeId() : TypeId {});
415 SetValue(Super::META_ACCESS_PROPERTY(Valid), p);
416 return GenericError::SUCCESS;
417 }
418
419 protected:
420 struct TargetProperty {
421 IProperty::Ptr property;
422 IStackProperty::Ptr stack;
423 operator bool() const noexcept
424 {
425 return property && stack;
426 }
427 };
428
429 void PropertyChanged()
430 {
431 auto p = GetTargetProperty();
432 this->GetState().SetInterpolator(p ? p.property->GetTypeId() : TypeId {});
433 SetValue(Super::META_ACCESS_PROPERTY(Valid), p);
434 OnPropertyChanged(p, property_.lock());
435 property_ = p.stack;
436 }
437
438 virtual void OnPropertyChanged(const TargetProperty& property, const IStackProperty::Ptr& previous) = 0;
439
440 TargetProperty GetTargetProperty() const noexcept
441 {
442 auto p = META_ACCESS_PROPERTY_VALUE(Property).lock();
443 return { p, interface_pointer_cast<IStackProperty>(p) };
444 }
445
446 private:
447 IStackProperty::WeakPtr property_;
448 };
449
450 /**
451 * @brief A base class which can be used by property animation implementations.
452 */
453 template<class BaseAnimationInterface>
454 class PropertyAnimationFwd : public BasePropertyAnimationFwd<BaseAnimationInterface> {
455 using Super = BasePropertyAnimationFwd<BaseAnimationInterface>;
456
457 protected:
458 PropertyAnimationFwd() = default;
459 ~PropertyAnimationFwd() override = default;
460
461 protected:
462 // Note covariance
463 Internal::PropertyAnimationState& GetState() noexcept override
464 {
465 return state_;
466 }
467
468 private:
469 Internal::PropertyAnimationState state_;
470 };
471
472 } // namespace Internal
473
474 META_END_NAMESPACE()
475
476 #endif // META_SRC_ANIMATION_H
477