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