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