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
21 #include <3d/ecs/systems/intf_animation_system.h>
22 #include <3d/namespace.h>
23 #include <base/containers/unique_ptr.h>
24 #include <base/containers/vector.h>
25 #include <core/ecs/entity.h>
26 #include <core/namespace.h>
27 #include <core/property_tools/property_api_impl.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 enum class TrackState : uint8_t {
108 PLAYING,
109 PAUSED,
110 STOPPING,
111 STOPPED,
112 };
113 struct TrackValues {
114 InitialTransformComponent initial;
115 InitialTransformComponent result;
116 float timePosition { 0.f };
117 float weight { 0.f };
118 TrackState state { TrackState::STOPPED };
119 bool forward { true };
120 bool updated { false };
121 };
122
123 class InitTask;
124 class FrameIndexTask;
125 class AnimateTask;
126
127 // IEcs::ComponentListener
128 void OnComponentEvent(EventType type, const CORE_NS::IComponentManager& componentManager,
129 BASE_NS::array_view<const CORE_NS::Entity> entities) override;
130 void OnAnimationComponentsCreated(BASE_NS::array_view<const CORE_NS::Entity> entities);
131 void OnAnimationComponentsUpdated(BASE_NS::array_view<const CORE_NS::Entity> entities);
132 void OnAnimationTrackComponentsUpdated(BASE_NS::array_view<const CORE_NS::Entity> entities);
133
134 void UpdateAnimationStates(uint64_t delta);
135 void UpdateAnimation(AnimationStateComponent& state, const AnimationComponent& animation,
136 const CORE_NS::ComponentQuery& trackQuery, float delta);
137 void InitializeTrackValues();
138 void AnimateTrackValues();
139 void ResetToInitialTrackValues();
140 void WriteUpdatedTrackValues();
141
142 void InitializeTrackValues(BASE_NS::array_view<const uint32_t> resultIndices);
143 void ResetTargetProperties(BASE_NS::array_view<const uint32_t> resultIndices);
144 void CalculateFrameIndices(BASE_NS::array_view<const uint32_t> resultIndices);
145 void AnimateTracks(BASE_NS::array_view<const uint32_t> resultIndices);
146 void ApplyResults(BASE_NS::array_view<const uint32_t> resultIndices);
147
148 const PropertyEntry& GetEntry(const AnimationTrackComponent& track);
149 void InitializeInitialDataComponent(CORE_NS::Entity trackEntity, const AnimationTrackComponent& animationTrack);
150
151 CORE_NS::IEcs& ecs_;
152 bool active_ = true;
153 Properties systemProperties_ { 128U };
154 CORE_NS::PropertyApiImpl<Properties> systemPropertyApi_;
155
156 BASE_NS::vector<BASE_NS::unique_ptr<AnimationPlayback>> animations_;
157
158 IInitialTransformComponentManager& initialTransformManager_;
159 IAnimationComponentManager& animationManager_;
160 IAnimationInputComponentManager& inputManager_;
161 IAnimationOutputComponentManager& outputManager_;
162 IAnimationStateComponentManager& stateManager_;
163 IAnimationTrackComponentManager& animationTrackManager_;
164 INameComponentManager& nameManager_;
165
166 CORE_NS::ComponentQuery trackQuery_;
167 CORE_NS::ComponentQuery animationQuery_;
168 uint32_t stateGeneration_ {};
169 uint32_t animationGeneration_ {};
170
171 BASE_NS::vector<uint32_t> animationOrder_;
172 BASE_NS::vector<uint32_t> trackOrder_;
173 BASE_NS::vector<PropertyEntry> propertyCache_;
174
175 CORE_NS::IThreadPool::Ptr threadPool_;
176
177 size_t taskSize_ { 0U };
178 size_t tasks_ { 0U };
179 size_t remaining_ { 0U };
180
181 uint64_t taskId_ { 0U };
182
183 BASE_NS::vector<CORE_NS::IThreadPool::IResult::Ptr> taskResults_;
184
185 BASE_NS::vector<InitTask> initTasks_;
186 uint64_t initTaskStart_ { 0U };
187
188 BASE_NS::vector<FrameIndexTask> frameIndexTasks_;
189
190 BASE_NS::vector<AnimateTask> animTasks_;
191 uint64_t animTaskStart_ { 0U };
192
193 BASE_NS::vector<TrackValues> trackValues_;
194 BASE_NS::vector<FrameData> frameIndices_;
195 };
196
197 /** @ingroup group_ecs_systems_ianimation */
198 /** Return name of this system
199 */
GetName(const IAnimationSystem *)200 inline constexpr BASE_NS::string_view GetName(const IAnimationSystem*)
201 {
202 return "AnimationSystem";
203 }
204 CORE3D_END_NAMESPACE()
205
206 #endif // CORE_ECS_ANIMATIONSYSTEM_H
207