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 API_CORE_ECS_IECS_H
17 #define API_CORE_ECS_IECS_H
18
19 #include <cstdint>
20
21 #include <base/containers/refcnt_ptr.h>
22 #include <base/containers/vector.h>
23 #include <base/namespace.h>
24 #include <core/ecs/entity.h>
25 #include <core/ecs/intf_entity_manager.h>
26 #include <core/namespace.h>
27 #include <core/threading/intf_thread_pool.h>
28
29 BASE_BEGIN_NAMESPACE()
30 struct Uid;
31 template<class T>
32 class array_view;
33 BASE_END_NAMESPACE()
34
35 CORE_BEGIN_NAMESPACE()
36 class IClassFactory;
37 class ISystem;
38 class IComponentManager;
39 struct SystemTypeInfo;
40 struct ComponentManagerTypeInfo;
41
42 /** \addtogroup group_ecs_iecs
43 * @{
44 */
45 /** IEcs */
46 class IEcs {
47 public:
48 /**
49 * Mode that controls how the engine will be used to render a frame. This can be used to skip rendering altogether
50 * when the scene contents have not changed, lowering the GPU and CPU load and saving battery life.
51 */
52 enum RenderMode {
53 /**
54 * In addition to render requests also re-render when the scene is detected to be dirty. The scene is
55 * considered dirty if any component in an entity has been changed, added or removed or rendering is
56 * explicitly requestedthrough RequestRender().
57 */
58 RENDER_IF_DIRTY,
59
60 /**
61 * Render every frame regardless of calls to RequestRender(). This mode will still take v-sync count into
62 * account.
63 */
64 RENDER_ALWAYS,
65 };
66
67 /** Listener for ECS Entity events. */
68 class EntityListener {
69 public:
70 using EventType = IEntityManager::EventType;
71 /** Entities added to processing. */
72 virtual void OnEntityEvent(EventType type, BASE_NS::array_view<const Entity> entities) = 0;
73
74 protected:
75 virtual ~EntityListener() = default;
76 };
77
78 /** Listener for ECS Component events. */
79 class ComponentListener {
80 public:
81 enum class EventType : uint8_t {
82 /** Component created to entity
83 */
84 CREATED,
85 /** Component in entity modified
86 */
87 MODIFIED,
88 /** Component destroyed from entity
89 */
90 DESTROYED
91 };
92 /** Entities added to processing. */
93 virtual void OnComponentEvent(
94 EventType type, const IComponentManager& componentManager, BASE_NS::array_view<const Entity> entities) = 0;
95
96 protected:
97 virtual ~ComponentListener() = default;
98 };
99
100 /** Gets entity manager for ECS.
101 */
102 virtual IEntityManager& GetEntityManager() = 0;
103
104 /** Get components of entity.
105 @param entity Entity where we get components.
106 @param result List where entitys components are written in.
107 */
108 virtual void GetComponents(Entity entity, BASE_NS::vector<IComponentManager*>& result) = 0;
109
110 /** Get systems of this ECS.
111 */
112 virtual BASE_NS::vector<ISystem*> GetSystems() const = 0;
113
114 /** Get one particular system from systems list.
115 * @param uid UID of the system we want to get.
116 */
117 virtual ISystem* GetSystem(const BASE_NS::Uid& uid) const = 0;
118
119 /** Get component managers of this ECS.
120 */
121 virtual BASE_NS::vector<IComponentManager*> GetComponentManagers() const = 0;
122
123 /** Get one particular component manager from component managers list.
124 * @param uid UID of the component manager we want to get.
125 */
126 virtual IComponentManager* GetComponentManager(const BASE_NS::Uid& uid) const = 0;
127
128 /** Clone an entity. Creates a new entity with copies of all components of this entity.
129 * NOTE: Does not clone children of the entity. NodeSystem can be used to clone whole hierarchies
130 * @param entity Entity to be cloned.
131 */
132 virtual Entity CloneEntity(Entity entity) = 0;
133
134 /** Garbage collect entities.
135 */
136 virtual void ProcessEvents() = 0;
137
138 /** Starts all systems.
139 */
140 virtual void Initialize() = 0;
141
142 /** Updates all systems.
143 * @param time Current program time (in us).
144 * @param delta Time it took since last frame (in us).
145 * @return True if rendering is required.
146 */
147 virtual bool Update(uint64_t time, uint64_t delta) = 0;
148
149 /** Stops all systems and removes all entities and components.
150 */
151 virtual void Uninitialize() = 0;
152
153 /** Add an instance of "componentManagerTypeInfo" to "system.
154 @param componentManagerTypeInfo Component manager type that is added to manager list.
155 */
156 virtual IComponentManager* CreateComponentManager(const ComponentManagerTypeInfo& componentManagerTypeInfo) = 0;
157
158 /** Add an instance of "systemInfo" to "system".
159 * @param systemInfo System type that is instantiated to systems list.
160 */
161 virtual ISystem* CreateSystem(const SystemTypeInfo& systemInfo) = 0;
162
163 /** Add listener for Entity events.
164 */
165 virtual void AddListener(EntityListener& listener) = 0;
166
167 /** Remove Entity event listener.
168 */
169 virtual void RemoveListener(EntityListener& listener) = 0;
170
171 /** Add listener for global component events.
172 */
173 virtual void AddListener(ComponentListener& listener) = 0;
174
175 /** Remove global component event listener.
176 */
177 virtual void RemoveListener(ComponentListener& listener) = 0;
178
179 /** Add listener for specific component manager events.
180 */
181 virtual void AddListener(IComponentManager& manager, ComponentListener& listener) = 0;
182
183 /** Remove specific component manager event listener.
184 */
185 virtual void RemoveListener(IComponentManager& manager, ComponentListener& listener) = 0;
186
187 /** Mark ECS dirty and queue current frame for rendering.
188 */
189 virtual void RequestRender() = 0;
190
191 /** Set render mode, either render only when dirty or render always.
192 * @param renderMode Rendering mode.
193 */
194 virtual void SetRenderMode(RenderMode renderMode) = 0;
195
196 /** Retrieve current render mode.
197 */
198 virtual RenderMode GetRenderMode() = 0;
199
200 /** Check if scene requires rendering after Update() has been called.
201 */
202 virtual bool NeedRender() const = 0;
203
204 /** Get access to interface registry
205 */
206 virtual IClassFactory& GetClassFactory() const = 0;
207
208 /** Get access to a thread pool.
209 */
210 virtual const IThreadPool::Ptr& GetThreadPool() const = 0;
211
212 /** Get scaling factor used for the delta time passed to ISystem::Update.
213 */
214 virtual float GetTimeScale() const = 0;
215
216 /** Set scaling factor used for the delta time passed to ISystem::Update.
217 * @param scale Time scaling factor.
218 */
219 virtual void SetTimeScale(float scale) = 0;
220
221 using Ptr = BASE_NS::refcnt_ptr<IEcs>;
222
223 protected:
224 virtual void Ref() noexcept = 0;
225 virtual void Unref() noexcept = 0;
226
227 friend Ptr;
228
229 IEcs() = default;
230 IEcs(const IEcs&) = delete;
231 IEcs(IEcs&&) = delete;
232 IEcs& operator=(const IEcs&) = delete;
233 IEcs& operator=(IEcs&&) = delete;
234 virtual ~IEcs() = default;
235 };
236
237 // Helper method to fetch managers by name
238 /** Get manager */
239 template<class T>
GetManager(const CORE_NS::IEcs & ecs)240 T* GetManager(const CORE_NS::IEcs& ecs)
241 {
242 return static_cast<T*>(ecs.GetComponentManager(T::UID));
243 }
244
245 /** Get system */
246 template<class T>
GetSystem(const CORE_NS::IEcs & ecs)247 T* GetSystem(const CORE_NS::IEcs& ecs)
248 {
249 return static_cast<T*>(ecs.GetSystem(T::UID));
250 }
251 /** @} */
252 CORE_END_NAMESPACE()
253
254 #endif // API_CORE_ECS_IECS_H
255