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 SCENE_PLUGIN_ECS_ANIMATION_H
16 #define SCENE_PLUGIN_ECS_ANIMATION_H
17 
18 #undef InterlockedIncrement
19 #undef InterlockedDecrement
20 
21 #include <optional>
22 #include <scene_plugin/interface/intf_ecs_animation.h>
23 
24 #include <3d/ecs/components/animation_component.h>
25 #include <3d/ecs/components/animation_input_component.h>
26 #include <3d/ecs/components/animation_output_component.h>
27 #include <3d/ecs/components/animation_track_component.h>
28 #include <3d/ecs/components/name_component.h>
29 #include <core/ecs/intf_component_manager.h>
30 #include <core/ecs/intf_ecs.h>
31 
32 #include <meta/base/shared_ptr.h>
33 #include <meta/ext/animation/interpolator.h>
34 #include <meta/ext/attachment/attachment.h>
35 #include <meta/ext/object_container.h>
36 #include <meta/ext/event_impl.h>
37 #include <meta/interface/animation/builtin_animations.h>
38 #include <meta/interface/intf_container.h>
39 
40 #include "scene_holder.h"
41 
SCENE_BEGIN_NAMESPACE()42 SCENE_BEGIN_NAMESPACE()
43 
44 class EcsTrackAnimation final : public META_NS::ObjectFwd<EcsTrackAnimation, ClassId::EcsTrackAnimation, META_NS::ClassId::Object,
45           IEcsTrackAnimation, META_NS::IStartableAnimation, META_NS::ITrackAnimation, META_NS::IPropertyAnimation,
46           META_NS::IContainable, META_NS::IMutableContainable, SCENE_NS::IEcsProxyObject, META_NS::ITimedAnimation> {
47 public:
48     // From INamed
49     META_IMPLEMENT_PROPERTY(BASE_NS::string, Name)
50 
51     // From ITrackAnimation
52     META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(ITrackAnimation, float, Timestamps, {})
53     META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(ITrackAnimation, META_NS::IFunction::Ptr, KeyframeHandlers)
54     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(ITrackAnimation, uint32_t, CurrentKeyframeIndex, -1)
55     META_IMPLEMENT_INTERFACE_PROPERTY(IPropertyAnimation, META_NS::IProperty::WeakPtr, Property, {})
56     META_IMPLEMENT_INTERFACE_ARRAY_PROPERTY(ITrackAnimation, META_NS::ICurve1D::Ptr, KeyframeCurves, {})
57     META_NS::IProperty::Ptr Keyframes() const override;
58     size_t AddKeyframe(float timestamp, const META_NS::IAny::ConstPtr& value) override;
59     bool RemoveKeyframe(size_t index) override;
60     void RemoveAllKeyframes() override;
61 
62     // From IAnimation
63     META_IMPLEMENT_INTERFACE_PROPERTY(IAnimation, bool, Enabled, true)
64     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAnimation, bool, Valid, false, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
65     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAnimation, META_NS::TimeSpan, TotalDuration,
66         META_NS::TimeSpan::Milliseconds(500), META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
67     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAnimation, bool, Running, false, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
68     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAnimation, float, Progress, 0, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
69     META_IMPLEMENT_INTERFACE_PROPERTY(IAnimation, META_NS::ICurve1D::Ptr, Curve)
70     META_IMPLEMENT_INTERFACE_PROPERTY(
71         IAnimation, META_NS::IAnimationController::WeakPtr, Controller, {}, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
72 
73     // From IAnimationWithModifiableDuration
74     META_IMPLEMENT_INTERFACE_PROPERTY(IAnimation, META_NS::TimeSpan, Duration, META_NS::TimeSpan::Milliseconds(500))
75 
76     bool Build(const META_NS::IMetadata::Ptr& data) override;
77 
78     void Seek(float position) override;
79     void Step(const META_NS::IClock::ConstPtr& clock) override;
80     void Start() override;
81     void Stop() override;
82     void Pause() override;
83     void Restart() override;
84     void Finish() override;
85 
86     META_IMPLEMENT_EVENT(META_NS::IOnChanged, OnFinished)
87     META_IMPLEMENT_EVENT(META_NS::IOnChanged, OnStarted)
88 
89     void SetEntity(CORE_NS::Entity entity) override
90     {
91         entity_ = entity;
92         if (auto ecsListener = ecsListener_.lock()) {
93             if (auto animationTrackManager =
94                     CORE_NS::GetManager<CORE3D_NS::IAnimationTrackComponentManager>(*ecsListener->ecs_)) {
95                 ecsListener->AddEntity(entity, GetSelf<SCENE_NS::IEcsProxyObject>(), *animationTrackManager);
96             }
97             if (auto animationInputManager =
98                     CORE_NS::GetManager<CORE3D_NS::IAnimationInputComponentManager>(*ecsListener->ecs_)) {
99                 ecsListener->AddEntity(entity, GetSelf<SCENE_NS::IEcsProxyObject>(), *animationInputManager);
100             }
101         }
102     }
103 
104 public: // from IEcsProxyObject
105     void SetCommonListener(BASE_NS::shared_ptr<SCENE_NS::EcsListener> ecsListener) override
106     {
107         ecsListener_ = ecsListener;
108     }
109 
110     void DoEntityEvent(CORE_NS::IEcs::EntityListener::EventType type, const CORE_NS::Entity& entity) override
111     {
112         if (auto parent = interface_pointer_cast<SCENE_NS::IEcsProxyObject>(GetParent())) {
113             parent->DoEntityEvent(type, entity);
114         }
115     }
116 
117     void DoComponentEvent(CORE_NS::IEcs::ComponentListener::EventType type,
118         const CORE_NS::IComponentManager& componentManager, const CORE_NS::Entity& entity) override
119     {
120         if (auto parent = interface_pointer_cast<SCENE_NS::IEcsProxyObject>(GetParent())) {
121             parent->DoComponentEvent(type, componentManager, entity);
122         }
123     }
124 
125     CORE_NS::Entity GetEntity() const override
126     {
127         return entity_;
128     }
129 
130     void SetSuperInstance(const IObject::Ptr& aggr, const IObject::Ptr& super) override
131     {
132         ObjectFwd::SetSuperInstance(aggr, super);
133         containable_ = interface_cast<IContainable>(super);
134         mutableContainable_ = interface_cast<IMutableContainable>(super);
135     }
136 
137     void SetParent(const IObject::Ptr& parent) override
138     {
139         if (mutableContainable_) {
140             mutableContainable_->SetParent(parent);
141         } else {
142             parent_ = parent;
143         }
144     }
145 
146     IObject::Ptr GetParent() const override
147     {
148         if (containable_) {
149             return containable_->GetParent();
150         }
151         return parent_.lock();
152     }
153 
154     void Destroy() override
155     {
156         if (auto ecsListener = ecsListener_.lock()) {
157             if (!ecsListener->ecs_) {
158                 return;
159             }
160             if (auto animationTrackManager =
161                     CORE_NS::GetManager<CORE3D_NS::IAnimationTrackComponentManager>(*ecsListener->ecs_)) {
162                 ecsListener->RemoveEntity(entity_, GetSelf<SCENE_NS::IEcsProxyObject>(), *animationTrackManager);
163             }
164             if (auto animationInputManager =
165                     CORE_NS::GetManager<CORE3D_NS::IAnimationInputComponentManager>(*ecsListener->ecs_)) {
166                 ecsListener->RemoveEntity(entity_, GetSelf<SCENE_NS::IEcsProxyObject>(), *animationInputManager);
167             }
168         }
169     }
170 
171 private:
172     CORE_NS::Entity entity_;
173     BASE_NS::string name_;
174     META_NS::IProperty::Ptr keyframes_;
175 
176     mutable META_NS::EventImpl<META_NS::IOnChanged> onFinished_;
177     mutable META_NS::EventImpl<META_NS::IOnChanged> onStarted_;
178 
179     BASE_NS::weak_ptr<SCENE_NS::EcsListener> ecsListener_;
180     META_NS::IContainable* containable_ {};
181     META_NS::IMutableContainable* mutableContainable_ {};
182     META_NS::IObject::WeakPtr parent_;
183 };
184 
185 class EcsAnimation final : public META_NS::ObjectContainerFwd<EcsAnimation, ClassId::EcsAnimation, IEcsAnimation,
186                                 META_NS::IParallelAnimation, META_NS::ITimedAnimation, META_NS::IStartableAnimation,
187                                SCENE_NS::IEcsProxyObject, META_NS::IAttachment> {
188 public:
189     // From IEcsAnimation
190     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(
191         IEcsAnimation, bool, ReadOnly, false, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
192 
193     // From INamed
194     META_IMPLEMENT_INTERFACE_PROPERTY(INamed, BASE_NS::string, Name, {})
195 
196     // From IAnimation
197     META_IMPLEMENT_INTERFACE_PROPERTY(IAnimation, bool, Enabled, true)
198     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAnimation, bool, Valid, false, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
199     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAnimation, META_NS::TimeSpan, TotalDuration,
200         META_NS::TimeSpan::Milliseconds(500), META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
201     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAnimation, bool, Running, false, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
202     META_IMPLEMENT_INTERFACE_READONLY_PROPERTY(IAnimation, float, Progress, 0, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
203     META_IMPLEMENT_INTERFACE_PROPERTY(IAnimation, META_NS::ICurve1D::Ptr, Curve)
204     META_IMPLEMENT_INTERFACE_PROPERTY(
205         IAnimation, META_NS::IAnimationController::WeakPtr, Controller, {}, META_NS::DEFAULT_PROPERTY_FLAGS_NO_SER)
206     META_IMPLEMENT_READONLY_PROPERTY(META_NS::IObject::WeakPtr, DataContext)
207     META_IMPLEMENT_READONLY_PROPERTY(META_NS::IAttach::WeakPtr, AttachedTo)
208 
209     META_IMPLEMENT_INTERFACE_PROPERTY(
210         ITimedAnimation, META_NS::TimeSpan, Duration, META_NS::TimeSpan::Milliseconds(500))
211 
212     void AddAnimation(const IAnimation::Ptr&) override;
213     void RemoveAnimation(const IAnimation::Ptr&) override;
214 
215     BASE_NS::vector<IAnimation::Ptr> GetAnimations() const override;
216 
217 public:
SetSceneHolder(SceneHolder::Ptr & sceneHolder)218     void SetSceneHolder(SceneHolder::Ptr& sceneHolder)
219     {
220         sceneHolder_ = sceneHolder;
221         SetCommonListener(sceneHolder->GetCommonEcsListener());
222     }
223 
GetSceneHolder()224     SceneHolder::Ptr GetSceneHolder()
225     {
226         return sceneHolder_.lock();
227     }
228 
229     // from IEcsProxyObject
SetCommonListener(BASE_NS::shared_ptr<SCENE_NS::EcsListener> ecsListener)230     void SetCommonListener(BASE_NS::shared_ptr<SCENE_NS::EcsListener> ecsListener) override
231     {
232         ecsListener_ = ecsListener;
233     }
DoEntityEvent(CORE_NS::IEcs::EntityListener::EventType,const CORE_NS::Entity & entity)234     void DoEntityEvent(CORE_NS::IEcs::EntityListener::EventType, const CORE_NS::Entity& entity) override {}
235     void DoComponentEvent(CORE_NS::IEcs::ComponentListener::EventType type,
236         const CORE_NS::IComponentManager& componentManager, const CORE_NS::Entity& entity) override;
237 
238     // From Object
239     BASE_NS::string GetName() const override;
240 
241     bool SetRootEntity(CORE_NS::Entity entity) override;
242     CORE_NS::Entity GetRootEntity() const override;
243 
244     void SetEntity(CORE_NS::IEcs& ecs, CORE_NS::Entity entity) override;
245     CORE_NS::Entity GetEntity() const override;
246 
247     void SetDuration(uint32_t ms) override;
248 
249     bool Retarget(CORE_NS::Entity entity) override;
250 
251     void Seek(float position) override;
252     void Step(const META_NS::IClock::ConstPtr& clock) override;
253     void Start() override;
254     void Stop() override;
255     void Pause() override;
256     void Restart() override;
257     void Finish() override;
258 
259     META_IMPLEMENT_EVENT(META_NS::IOnChanged, OnFinished)
260     META_IMPLEMENT_EVENT(META_NS::IOnChanged, OnStarted)
261 
262     void AddKey(IEcsTrackAnimation::Ptr track, float time) override;
263     void RemoveKey(IEcsTrackAnimation::Ptr track, uint32_t index) override;
264     void UpdateKey(IEcsTrackAnimation::Ptr track, uint32_t oldKeyIndex, uint32_t newKeyIndex, float time) override;
265 
266     IEcsTrackAnimation::Ptr CreateAnimationTrack(
267         CORE_NS::Entity rootEntity, CORE_NS::Entity target, BASE_NS::string_view property) override;
268     IEcsTrackAnimation::Ptr GetAnimationTrack(CORE_NS::Entity target, BASE_NS::string_view property) override;
269     void DestroyAnimationTrack(IEcsTrackAnimation::Ptr track) override;
270     void DestroyAllAnimationTracks() override;
271     void Destroy() override;
272 
273     BASE_NS::vector<CORE_NS::EntityReference> GetAllRelatedEntities() const override;
274 
275 public: // ISerialization
276     //todo
277     //bool Export(
278     //    META_NS::Serialization::IExportContext& context, META_NS::Serialization::ClassPrimitive& value) const override;
279 
280     //bool Import(
281     //    META_NS::Serialization::IImportContext& context, const META_NS::Serialization::ClassPrimitive& value) override;
282 
283     /**
284      * @brief Called by the framework when an the attachment is being attached to an IObject. If this
285      *        function succeeds, the object is attached to the target.
286      * @param object The IObject instance the attachment is attached to.
287      * @param dataContext The data context for this attachment.
288      * @note The data context can be the same object as the object being attached to, or
289      *       something else. It is up to the attachment to decide how to handle them.
290      * @return The implementation should return true if the attachment can be attached to target object.
291      *         If the attachment cannot be added, the implementation should return false.
292      */
Attaching(const IAttach::Ptr & target,const IObject::Ptr & dataContext)293     bool Attaching(const IAttach::Ptr& target, const IObject::Ptr& dataContext) override
294     {
295         META_ACCESS_PROPERTY(AttachedTo)->SetValue(target);
296         META_ACCESS_PROPERTY(DataContext)->SetValue(dataContext);
297         return true;
298     }
299     /**
300      * @brief Detach the attachment from an object.
301      * @param object The object to attach to.
302      * @return If the attachment can be detached from the target, the implementation should return true.
303      *         If detaching is not possible, the implementation should return false. In such a case the
304      *         target may choose to not remove the attachment. During for example object destruction,
305      *         the target will ignore the return value.
306      */
Detaching(const IAttach::Ptr & target)307     bool Detaching(const IAttach::Ptr& target) override
308     {
309         META_ACCESS_PROPERTY(AttachedTo)->SetValue({});
310         META_ACCESS_PROPERTY(DataContext)->SetValue({});
311         return true;
312     }
313 
314 protected:
315     bool Build(const META_NS::IMetadata::Ptr& data) override;
316 
317 private:
318     struct Data {
319         inline explicit operator bool()
320         {
321             return (property != nullptr) && !data.empty();
322         };
323 
324         const CORE_NS::PropertyTypeDecl* property { nullptr };
325         BASE_NS::vector<uint8_t> data;
326     };
327 
328     CORE_NS::Entity TryResolveAnimationRoot();
329 
330     Data GetProperty(BASE_NS::Uid componentUid, CORE_NS::Entity entity, BASE_NS::string property) const;
331     void SetKeyFrameData(CORE_NS::Entity animationTrack, float timeStamp, BASE_NS::vector<uint8_t> valueData);
332     void UpdateTimestamps(IEcsTrackAnimation& track, CORE_NS::Entity timestampEntity);
333 
334     // Return the highest timestamp from the keyframes of the animation track.
335     float GetTrackDuration(CORE_NS::Entity animationTrack);
336     void UpdateAnimationTrackDuration(CORE_NS::Entity animationTrack);
337 
338     void SetProgress(float progress);
339     void SetTime(uint32_t value);
340 
341     void OnDestroyAnimationTrack(IEcsTrackAnimation::Ptr track);
342 
343     void OnAnimationStateChanged(CORE_NS::IEcs::ComponentListener::EventType event);
344     void OnAnimationNameChanged(CORE_NS::IEcs::ComponentListener::EventType event);
345     void OnAnimationChanged(CORE_NS::IEcs::ComponentListener::EventType event);
346     void OnAnimationTracksChanged(CORE_NS::IEcs::ComponentListener::EventType event, CORE_NS::Entity entity);
347     void OnAnimationInputsChanged(CORE_NS::IEcs::ComponentListener::EventType event, CORE_NS::Entity entity);
348 
349     void OnNamePropertyChanged();
350     void OnDurationPropertyChanged();
351     void OnProgressPropertyChanged();
352 
353     void OnAnimationTrackChanged(IEcsTrackAnimation& track, CORE_NS::Entity trackEntity);
354     void OnAnimationTimestampsChanged(IEcsTrackAnimation& track, CORE_NS::Entity timestampEntity);
355 
356     bool IsAnimationTrackArrayModified();
357     void GatherAnimationTracks();
358 
359     CORE_NS::IEcs* ecs_ { nullptr };
360     CORE_NS::EntityReference entity_ {};
361     CORE_NS::Entity root_ {};
362 
363     CORE3D_NS::IAnimationComponentManager* animationManager_ { nullptr };
364     CORE3D_NS::IAnimationTrackComponentManager* animationTrackManager_ { nullptr };
365     CORE3D_NS::IAnimationInputComponentManager* animationInputManager_ { nullptr };
366     CORE3D_NS::IAnimationOutputComponentManager* animationOutputManager_ { nullptr };
367     CORE_NS::IComponentManager* animationStateManager_ { nullptr };
368     CORE3D_NS::INameComponentManager* nameManager_ { nullptr };
369 
370     bool updateGuard_ { false };
371 
372     int32_t repeatCount_ { 1 };
373     std::optional<META_NS::TimeSpan> lastFrameTime_ {};
374 
375     mutable META_NS::EventImpl<META_NS::IOnChanged> onFinished_;
376     mutable META_NS::EventImpl<META_NS::IOnChanged> onStarted_;
377 
378     SceneHolder::WeakPtr sceneHolder_;
379     BASE_NS::weak_ptr<SCENE_NS::EcsListener> ecsListener_;
380 };
381 
382 void RegisterEcsAnimationObjectType();
383 void UnregisterEcsAnimationObjectType();
384 
385 SCENE_END_NAMESPACE()
386 
387 #endif // SCENE_PLUGIN_ECS_ANIMATION_H
388