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 42SCENE_BEGIN_NAMESPACE() 43 44class 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> { 47public: 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 104public: // 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 171private: 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 185class 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> { 188public: 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 217public: 218 void SetSceneHolder(SceneHolder::Ptr& sceneHolder) 219 { 220 sceneHolder_ = sceneHolder; 221 SetCommonListener(sceneHolder->GetCommonEcsListener()); 222 } 223 224 SceneHolder::Ptr GetSceneHolder() 225 { 226 return sceneHolder_.lock(); 227 } 228 229 // from IEcsProxyObject 230 void SetCommonListener(BASE_NS::shared_ptr<SCENE_NS::EcsListener> ecsListener) override 231 { 232 ecsListener_ = ecsListener; 233 } 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 275public: // 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 */ 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 */ 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 314protected: 315 bool Build(const META_NS::IMetadata::Ptr& data) override; 316 317private: 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 382void RegisterEcsAnimationObjectType(); 383void UnregisterEcsAnimationObjectType(); 384 385SCENE_END_NAMESPACE() 386 387#endif // SCENE_PLUGIN_ECS_ANIMATION_H 388