Implements a shutdown mechanism for components and entities, ensuring proper resource release and preventing memory leaks. This change introduces a virtual `Shutdown` method to the `Component` class, allowing derived components to release specific resources when they are removed from an entity or when the entity is destroyed. The `Entity` class now calls the `Shutdown` method on all its components during its own release process. The `EntityManager` now calls the `release()` method when destroying an entity. This enhancement ensures that resources, such as FMOD sound objects and channels in the `AudioComponent`, are properly released, preventing potential resource leaks and improving the stability of the engine.
210 lines
6.0 KiB
C++
210 lines
6.0 KiB
C++
#pragma once
|
|
#include "component.h"
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <WICTextureLoader.h>
|
|
#include <d3d11.h>
|
|
|
|
#include "camera_class.h"
|
|
#include <Fmod/core/inc/fmod.hpp>
|
|
|
|
namespace ecs {
|
|
/**
|
|
* Type alias for a unique identifier for an entity.
|
|
*/
|
|
using EntityID = uint32_t;
|
|
|
|
class Entity : public std::enable_shared_from_this<Entity> {
|
|
public:
|
|
/**
|
|
* Builder for an Entity with a unique ID.
|
|
*/
|
|
explicit Entity(EntityID id) : m_ID(id) {}
|
|
~Entity() = default;
|
|
|
|
/**
|
|
* No copy constructor or assignment operator to prevent copying.
|
|
*/
|
|
Entity(const Entity&) = delete;
|
|
Entity& operator=(const Entity&) = delete;
|
|
|
|
/**
|
|
* Move constructor and assignment operator to allow moving entities.
|
|
*/
|
|
Entity(Entity&&) = default;
|
|
Entity& operator=(Entity&&) = default;
|
|
|
|
/**
|
|
* Get the unique identifier for the entity.
|
|
* @return The unique ID of the entity.
|
|
*/
|
|
EntityID GetID() const { return m_ID; }
|
|
|
|
/**
|
|
* Add a component of type T to the entity.
|
|
* If the component already exists, it returns the existing component.
|
|
* @tparam T
|
|
* @param args Arguments to construct the component.
|
|
* @return A shared pointer to the added or existing component.
|
|
*/
|
|
template<typename T, typename... Args>
|
|
std::shared_ptr<T> AddComponent(Args&&... args) {
|
|
static_assert(std::is_base_of<Component, T>::value, "T must derive from Component");
|
|
|
|
ComponentTypeID typeID = GetComponentTypeID<T>();
|
|
|
|
// Vérifier si le composant existe déjà
|
|
if (m_Components.find(typeID) != m_Components.end()) {
|
|
return std::static_pointer_cast<T>(m_Components[typeID]);
|
|
}
|
|
|
|
// Créer et ajouter le composant
|
|
auto component = std::make_shared<T>(std::forward<Args>(args)...);
|
|
m_Components[typeID] = component;
|
|
|
|
component->SetParent(shared_from_this());
|
|
|
|
|
|
// Initialiser le composant
|
|
component->Initialize();
|
|
|
|
return component;
|
|
}
|
|
|
|
/**
|
|
* Get a component of type T from the entity.
|
|
* @tparam T
|
|
* @return A shared pointer to the component if it exists, nullptr otherwise.
|
|
*/
|
|
template<typename T>
|
|
std::shared_ptr<T> GetComponent() {
|
|
static_assert(std::is_base_of<Component, T>::value, "T must derive from Component");
|
|
|
|
ComponentTypeID typeID = GetComponentTypeID<T>();
|
|
|
|
auto it = m_Components.find(typeID);
|
|
if (it != m_Components.end()) {
|
|
return std::static_pointer_cast<T>(it->second);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
* Check if the entity has a component of type T.
|
|
* @tparam T
|
|
* @return true if the entity has the component, false otherwise.
|
|
*/
|
|
template<typename T>
|
|
bool HasComponent() const {
|
|
static_assert(std::is_base_of<Component, T>::value, "T must derive from Component");
|
|
|
|
ComponentTypeID typeID = GetComponentTypeID<T>();
|
|
return m_Components.find(typeID) != m_Components.end();
|
|
}
|
|
|
|
/**
|
|
* Remove a component of type T from the entity.
|
|
* @tparam T
|
|
*/
|
|
template<typename T>
|
|
void RemoveComponent() {
|
|
static_assert(std::is_base_of<Component, T>::value, "T must derive from Component");
|
|
|
|
ComponentTypeID typeID = GetComponentTypeID<T>();
|
|
auto it = m_Components.find(typeID);
|
|
|
|
if (it != m_Components.end()) {
|
|
m_Components.erase(it);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update all components of the entity.
|
|
* @param deltaTime
|
|
*/
|
|
void UpdateComponents(float deltaTime) {
|
|
for (auto& [typeID, component] : m_Components) {
|
|
component->Update(deltaTime);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all components of the entity.
|
|
* @return A constant reference to the map of components.
|
|
*/
|
|
const std::unordered_map<ComponentTypeID, ComponentPtr>& GetAllComponents() const {
|
|
return m_Components;
|
|
}
|
|
|
|
/**
|
|
* Set the main camera of the scene to be used by components like AudioComponent.
|
|
* @param camera
|
|
*/
|
|
void SetCamera(camera_class* camera) {m_camera = camera; }
|
|
|
|
/**
|
|
* Get the main camera of the scene.
|
|
* @return A pointer to the main camera.
|
|
*/
|
|
camera_class* GetCamera() const { return m_camera; }
|
|
|
|
/**
|
|
* Set the FMOD sound system to be used by components like AudioComponent.
|
|
* @param soundSystem
|
|
*/
|
|
void SetSoundSystem(FMOD::System* soundSystem) {m_soundSystem = soundSystem; }
|
|
/**
|
|
* Get the FMOD sound system.
|
|
* @return A pointer to the FMOD sound system.
|
|
*/
|
|
FMOD::System* GetSoundSystem() const { return m_soundSystem; }
|
|
|
|
/**
|
|
* Release all data associated with the entity.
|
|
* This includes clearing all components and resetting the camera and sound system pointers.
|
|
*/
|
|
void release()
|
|
{
|
|
// call shutdown on all components if needed
|
|
for (auto& [typeID, component] : m_Components) {
|
|
// If components had a shutdown method, we would call it here
|
|
component->Shutdown();
|
|
}
|
|
m_Components.clear();
|
|
m_camera = nullptr;
|
|
m_soundSystem = nullptr;
|
|
}
|
|
|
|
void SetDevice (ID3D11Device* dev) { device = dev; }
|
|
void SetContext(ID3D11DeviceContext* ctx) { context = ctx; }
|
|
ID3D11Device* GetDevice() const { return device; }
|
|
ID3D11DeviceContext* GetContext() const { return context; }
|
|
|
|
private:
|
|
|
|
/**
|
|
* Unique identifier for the entity.
|
|
*/
|
|
EntityID m_ID;
|
|
/**
|
|
* Map to hold components associated with the entity.
|
|
* The key is the type ID of the component, and the value is a shared pointer to the component.
|
|
*/
|
|
std::unordered_map<ComponentTypeID, ComponentPtr> m_Components;
|
|
|
|
// camera
|
|
camera_class* m_camera = nullptr;
|
|
|
|
// FMOD sound system
|
|
FMOD::System* m_soundSystem = nullptr;
|
|
|
|
ID3D11Device* device;
|
|
ID3D11DeviceContext* context;
|
|
};
|
|
|
|
} // namespace ecs
|