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 
16 #ifndef CORE_ECS_ANIMATIONSYSTEM_H
17 #define CORE_ECS_ANIMATIONSYSTEM_H
18 
19 #include <ComponentTools/component_query.h>
20 #include <PropertyTools/property_api_impl.h>
21 
22 #include <3d/ecs/systems/intf_animation_system.h>
23 #include <3d/namespace.h>
24 #include <base/containers/unique_ptr.h>
25 #include <base/containers/vector.h>
26 #include <core/ecs/entity.h>
27 #include <core/namespace.h>
28 #include <core/threading/intf_thread_pool.h>
29 
30 #include "ecs/components/initial_transform_component.h"
31 
32 CORE_BEGIN_NAMESPACE()
33 class IEcs;
34 class IPropertyApi;
35 class IPropertyHandle;
36 struct PropertyTypeDecl;
37 CORE_END_NAMESPACE()
38 
39 CORE3D_BEGIN_NAMESPACE()
40 class IAnimationPlayback;
41 class INameComponentManager;
42 class ISceneNode;
43 class IAnimationComponentManager;
44 class IAnimationInputComponentManager;
45 class IAnimationOutputComponentManager;
46 class IAnimationStateComponentManager;
47 class IAnimationTrackComponentManager;
48 class IInitialTransformComponentManager;
49 class AnimationPlayback;
50 struct AnimationTrackComponent;
51 struct AnimationOutputComponent;
52 struct AnimationStateComponent;
53 
54 class AnimationSystem final : public IAnimationSystem, CORE_NS::IEcs::ComponentListener {
55 public:
56     explicit AnimationSystem(CORE_NS::IEcs& ecs);
57     ~AnimationSystem() override = default;
58 
59     BASE_NS::string_view GetName() const override;
60     BASE_NS::Uid GetUid() const override;
61 
62     CORE_NS::IPropertyHandle* GetProperties() override;
63     const CORE_NS::IPropertyHandle* GetProperties() const override;
64     void SetProperties(const CORE_NS::IPropertyHandle&) override;
65 
66     bool IsActive() const override;
67     void SetActive(bool state) override;
68 
69     void Initialize() override;
70     bool Update(bool frameRenderingQueued, uint64_t time, uint64_t delta) override;
71     void Uninitialize() override;
72 
73     const CORE_NS::IEcs& GetECS() const override;
74 
75     // IAnimationSystem.
76     IAnimationPlayback* CreatePlayback(CORE_NS::Entity const& animationEntity, ISceneNode const& node) override;
77     IAnimationPlayback* CreatePlayback(const CORE_NS::Entity animationEntity,
78         const BASE_NS::array_view<const CORE_NS::Entity> targetEntities) override;
79     void DestroyPlayback(IAnimationPlayback* playback) override;
80 
81     size_t GetPlaybackCount() const override;
82     IAnimationPlayback* GetPlayback(size_t index) const override;
83 
84     struct Properties {
85         size_t minTaskSize;
86     };
87 
88     struct PropertyEntry;
89     struct InterpolationData;
90 
91 private:
92     struct Data {
93         // for checking the type of the data
94         const CORE_NS::PropertyTypeDecl* property;
95         // for accessing the data. data() include offset and size() equals sizeof(type)
96         BASE_NS::array_view<uint8_t> data;
97         // for calling WUnlock automatically when data is not needed
98         CORE_NS::ScopedHandle<uint8_t> handle;
99     };
100 
101     struct FrameData {
102         float currentOffset;
103         size_t currentFrameIndex;
104         size_t nextFrameIndex;
105     };
106 
107     struct TrackValues {
108         InitialTransformComponent initial;
109         InitialTransformComponent result;
110         float timePosition { 0.f };
111         float weight { 0.f };
112         bool stopped { true };
113         bool forward { true };
114         bool updated { false };
115     };
116 
117     class InitTask;
118     class AnimateTask;
119 
120     // IEcs::ComponentListener
121     void OnComponentEvent(EventType type, const CORE_NS::IComponentManager& componentManager,
122         BASE_NS::array_view<const CORE_NS::Entity> entities) override;
123     void OnAnimationComponentsCreated(BASE_NS::array_view<const CORE_NS::Entity> entities);
124     void OnAnimationComponentsUpdated(BASE_NS::array_view<const CORE_NS::Entity> entities);
125     void OnAnimationTrackComponentsUpdated(BASE_NS::array_view<const CORE_NS::Entity> entities);
126 
127     void UpdateAnimation(AnimationStateComponent& state, const AnimationComponent& animation,
128         const CORE_NS::ComponentQuery& trackQuery, float delta);
129     void InitializeTrackValues();
130     void ResetToInitialTrackValues();
131     void WriteUpdatedTrackValues();
132 
133     void InitializeTrackValues(BASE_NS::array_view<const uint32_t> resultIndices);
134     void ResetTargetProperties(BASE_NS::array_view<const uint32_t> resultIndices);
135     void Calculate(BASE_NS::array_view<const uint32_t> resultIndices);
136     void AnimateTracks(BASE_NS::array_view<const uint32_t> resultIndices);
137     void ApplyResults(BASE_NS::array_view<const uint32_t> resultIndices);
138 
139     const PropertyEntry& GetEntry(const AnimationTrackComponent& track);
140     void InitializeInitialDataComponent(CORE_NS::Entity trackEntity, const AnimationTrackComponent& animationTrack);
141 
142     CORE_NS::IEcs& ecs_;
143     bool active_ = true;
144     Properties systemProperties_ { 128U };
145     CORE_NS::PropertyApiImpl<Properties> systemPropertyApi_;
146 
147     BASE_NS::vector<BASE_NS::unique_ptr<AnimationPlayback>> animations_;
148 
149     IInitialTransformComponentManager& initialTransformManager_;
150     IAnimationComponentManager& animationManager_;
151     IAnimationInputComponentManager& inputManager_;
152     IAnimationOutputComponentManager& outputManager_;
153     IAnimationStateComponentManager& stateManager_;
154     IAnimationTrackComponentManager& animationTrackManager_;
155     INameComponentManager& nameManager_;
156 
157     CORE_NS::ComponentQuery trackQuery_;
158     CORE_NS::ComponentQuery animationQuery_;
159     uint32_t stateGeneration_ {};
160     uint32_t animationGeneration_ {};
161 
162     BASE_NS::vector<uint32_t> animationOrder_;
163     BASE_NS::vector<uint32_t> trackOrder_;
164     BASE_NS::vector<PropertyEntry> propertyCache_;
165 
166     CORE_NS::IThreadPool::Ptr threadPool_;
167 
168     size_t taskSize_ { 0U };
169     size_t tasks_ { 0U };
170     size_t remaining_ { 0U };
171 
172     uint64_t taskId_ { 0U };
173 
174     BASE_NS::vector<CORE_NS::IThreadPool::IResult::Ptr> taskResults_;
175 
176     BASE_NS::vector<InitTask> initTasks_;
177     uint64_t initTaskStart_ { 0U };
178     uint64_t initTaskCount_ { 0U };
179 
180     BASE_NS::vector<AnimateTask> animTasks_;
181     uint64_t animTaskStart_ { 0U };
182     uint64_t animTaskCount_ { 0U };
183 
184     BASE_NS::vector<TrackValues> trackValues_;
185     BASE_NS::vector<FrameData> frameIndices_;
186 };
187 
188 /** @ingroup group_ecs_systems_ianimation */
189 /** Return name of this system
190  */
GetName(const IAnimationSystem *)191 inline constexpr BASE_NS::string_view GetName(const IAnimationSystem*)
192 {
193     return "AnimationSystem";
194 }
195 CORE3D_END_NAMESPACE()
196 
197 #endif // CORE_ECS_ANIMATIONSYSTEM_H
198