Motor OpenGL
Cargando...
Buscando...
Nada coincide
entity.h
1#pragma once
2#include "component.h"
3#include <utility>
4#include <vector>
5#include <type_traits>
6#ifdef _DEBUG
7#include <iostream>
8#endif // _DEBUG
9
10#include <core/serialize/JsonSerializer.h>
11#include <core/serialize/Serializable.h>
12#include <core/register/ComponentRegistry.h>
13
14namespace cme {
15 class Scene;
16}
17
18namespace ec
19{
20 class EntityManager;
21 class Entity : public cme::Serializable, public std::enable_shared_from_this<Entity>
22 {
23 public:
24 Entity(ent::groupID groupID, cme::Scene* _scenePtr, std::string name)
25 : _alive(true)
26 , _active(true)
27 , _groupID(ec::ent::None)
28 , _scene(_scenePtr)
29 , _updateComponents(0, nullptr)
30 , _renderComponents(0, nullptr)
31 , _components(ec::comp::NUM_COMPONENTS, nullptr)
32 , _name(name)
33 {
34#ifdef _DEBUG
35 LOG_INFO("Creating entity");
36#endif // _DEBUG
37 _groupID = groupID;
38 };
39
41 virtual ~Entity()
42 {
43 for (auto c : _components) { delete c; }
44 _updateComponents.clear();
45 _renderComponents.clear();
46 _components.clear();
47 }
48
50 Entity(const Entity&) = delete;
51
53 Entity& operator=(const Entity&) = delete;
54
55 protected:
57 ec::ent::groupID _groupID;
58
59 private:
60 bool _alive;
61 bool _active;
62 cme::Scene* _scene;
63
64 std::string _name;
65 public:
67 std::vector<UpdateComponent*> _updateComponents;
68
70 std::vector<RenderComponent*> _renderComponents;
71
73 std::vector<Component*> _components;
74
75 std::string& name() { return _name; }
76
77 inline void update() {
78 for (auto* comp : _updateComponents) {
79 comp->update();
80 }
81 }
82
83 void render() {
84 for (auto* comp : _renderComponents) {
85 comp->render();
86 }
87 }
88
89 void serialize(cme::JsonSerializer& s) const {
90 // 1. Añadimos una nueva entidad al array de entidades
92 // 2. Guardamos sus datos básicos
93 s.write("name", this->_name); // Asumiendo que tu entidad tiene nombre
94 // 3. Abrimos el array de componentes
95 s.beginArray("components");
96 for (auto component : _components) {
97 if (!component) continue;
98 // Por cada componente, metemos un nuevo objeto en el array
100 s.write("type", component->serializeID());
101
102 s.beginScope("data");
103 component->serialize(s); // Aquí llama al Transform, MeshRenderer, etc.
104 s.endScope();
105
106 s.endScope(); // Cerramos el objeto de este componente
107 }
108
109 s.endScope(); // Cerramos el array "components"
110 s.endScope(); // Cerramos el objeto de la entidad
111 }
112
113 void deserialize(cme::JsonSerializer& s) {
114 s.beginArray("components");
115 size_t numComp = s.getArraySize();
116 for (size_t k = 0; k < numComp; k++) {
117 s.enterElement(k);
118 std::string compKey = s.readString("type");
119 auto comp = cme::ComponentRegistry::create(compKey);
120 if (!comp) {
121 LOG_ERROR(std::format("El componente es nulo, la key no existe. KEY: {}", compKey));
122 continue;
123 }
124
125 this->addComponent(comp);
126 s.beginScope("data");
127 comp->deserialize(s);
128 s.endScope();
129
130 s.endScope();
131 }
132 s.endScope(); // Salimos de los componentes
133 }
134
141 template<typename T, typename... Ts>
142 inline T* addComponent(Ts&&... args)
143 {
144 // Comprobar en tiempo de ejecucion si T es un componente
145 static_assert(std::is_base_of<Component, T>::value, "No es un componente"); // La putada es que no te dice donde has puesto mal...
146
147 // Obtener el ID del componente T, si no esta registrado
148 constexpr comp::cmpID id = static_cast<comp::cmpID>(ec::getComponentID<T>);
149
150 // Quitar el componente
151 removeComponent<T>();
152
153 // Crear el componente y asignarlo en el vector del componentes
154 T* component = new T(std::forward<Ts>(args)...);
155 _components[id] = component;
156
157 //se comprueba si es un componente de render para meterlo en el vector correspondiente
158 if constexpr (std::is_base_of_v<RenderComponent, T>) {
159 _renderComponents.push_back(static_cast<RenderComponent*>(component));
160 }
161
162 if constexpr (std::is_base_of_v<UpdateComponent, T>) {
163 _updateComponents.push_back(static_cast<UpdateComponent*>(component));
164 component->setUpdateIterator(std::prev(_updateComponents.end()));
165 }
166
167
168 // Asignar el owner del componente
169 component->setContext(shared_from_this());
170
171 // Inicializar el componente
172 component->initComponent();
173
174 // Devolver el componente
175 return component;
176 }
177
180 void addComponent(ec::Component* component) {
181 if (!component) return;
182
183 ec::cmpID_t id = component->getID();
184
185 // Borrar si ya existe
186 delete _components[id];
187 _components[id] = component;
188
189 // Registrar en render/update si aplica
190 if (auto* r = component->getAsRender()) {
191 _renderComponents.push_back(r);
192 }
193 if (auto* u = component->getAsUpdate()) {
194 _updateComponents.push_back(u);
195 u->setUpdateIterator(std::prev(_updateComponents.end()));
196 }
197
198 component->setContext(shared_from_this());
199 component->initComponent();
200 }
201
204 template<typename T>
205 inline void removeComponent()
206 {
207 // Comprobar en tiempo de ejecucion si T es un componente
208 static_assert(std::is_base_of<Component, T>::value, "No es un componente");
209
210 // Obtener el ID del componente T, si no esta registrado
211 constexpr comp::cmpID id = static_cast<comp::cmpID>(ec::getComponentID<T>);
212
213 auto component = _components[id];
214
215
216 /*
217 Aqui deberia poder comprobar que componente especial es, y borrarlo de su lista correspondiente mediante el iterador, pero no me sale...
218 */
219
220 //if constexpr (std::is_base_of_v<UpdateComponent, T>)
221 //{
222 // static_cast<UpdateComponent*>(component);
223 // _updateComponents.erase(component->getUpdateIterator());
224 //}
225
226 delete _components[id];
227 _components[id] = nullptr;
228 }
229
233 template<typename T>
234 inline bool hasComponent()
235 {
236 static_assert(std::is_base_of<Component, T>::value, "No es un componente");
237 constexpr comp::cmpID id = static_cast<comp::cmpID>(ec::getComponentID<T>);
238 return _components[id] != nullptr;
239 }
240
244 template<typename T>
245 inline T* getComponent()
246 {
247 static_assert(std::is_base_of<Component, T>::value, "No es un componente");
248 constexpr comp::cmpID id = static_cast<comp::cmpID>(ec::getComponentID<T>);
249 return static_cast<T*>(_components[id]);
250 }
251
254 inline void setGroup(ec::ent::groupID id) { _groupID = id; }
255
256 inline cme::Scene* getScene() {
257 return _scene;
258 }
259
262 bool isAlive() { return _alive; }
263
266 bool& active() { return _active; }
267
270 std::vector<UpdateComponent*>& getUpdateComponent() {
271 return _updateComponents;
272 }
273
276 std::vector<RenderComponent*>& getRenderComponent() {
277 return _renderComponents;
278 }
279 };
280}; // namespace ec
static ec::Component * create(const std::string &name)
Crea un componente dado su tipo.
Definition ComponentRegistry.h:30
void beginScope(const std::string &key)
Cambia de scope para leer o escribir en el json.
Definition JsonSerializer.cpp:11
void pushObjectToArray()
Agrega un nuevo objeto al array en el scope actual y entra en ese nuevo objeto, permitiendo agregar p...
Definition JsonSerializer.cpp:37
std::string readString(const std::string &key) const
Lee y devuelve un valor de tipo string asociado a la clave especificada.
Definition JsonSerializer.cpp:127
void enterElement(size_t index)
Entra en un elemento específico del array en el scope actual.
Definition JsonSerializer.cpp:55
void endScope()
Vuelve al scope anterior.
Definition JsonSerializer.cpp:20
void write(const std::string &key, float value)
Escribe un valor en el scope actual.
Definition JsonSerializer.cpp:83
void beginArray(const std::string &key)
Inicia un nuevo array en el scope actual con la clave dada, permitiendo agregar elementos a ese array...
Definition JsonSerializer.cpp:27
size_t getArraySize() const
Obtiene el tamaño del array en el scope actual.
Definition JsonSerializer.cpp:48
void setContext(std::weak_ptr< ec::Entity > ent)
Hacer saber al componente quien le controla.
Definition component.h:42