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