2D_Engine/IP/IP.hpp

128 lines
3.2 KiB
C++

/********************\
| Copyright 2024, |
| Ulysse Cura |
\********************/
//////////////////////////////////////
// //
// Definition de l'Item Property. //
// //
//////////////////////////////////////
#ifndef ITEMPROPERTY_HPP
#define ITEMPROPERTY_HPP
#include <algorithm>
#include <array>
#include <bitset>
#include <stdexcept>
#include <iostream>
#include <memory>
#include <vector>
using std::bitset, std::array, std::vector, std::unique_ptr, std::make_unique, std::move, std::forward, std::runtime_error, std::sort;
class Property;
class Item;
using PropertyID = std::size_t;
inline PropertyID getPropertyTypeID()
{
static PropertyID lastID = 0;
return lastID++;
}
template<typename T> inline PropertyID getPropertyTypeID() noexcept
{
static PropertyID typeID = getPropertyTypeID();
return typeID;
}
constexpr std::size_t maxProperties = 32;
using PropertyBitSet = bitset<maxProperties>;
using PropertyArray = array<Property*, maxProperties>;
class Property {
public:
Item *item;
virtual void init() {}
virtual ~Property() {}
};
class Item {
public:
template <typename T, typename... TArgs>
T& addProperty(TArgs&&... args)
{
if(hasProperty<T>())
{
throw runtime_error("Vous ne pouvez pas mettre deux fois la même propriétée dans le même item.\n");
}
// Creation d'un pointeur du type donné avec les arguments necessaires
T *p(new T(forward<TArgs>(args)...));
// On donne au composant une reference de l'entitée
p->item = this;
// Création d'un unique_ptr et ajout du composant dans le vecteur et array associé
unique_ptr<Property> uPtr {p};
properties.emplace_back(move(uPtr));
propertyArray[getPropertyTypeID<T>()] = p;
propertyBitSet[getPropertyTypeID<T>()] = true;
// Initialisation du composant
p->init();
return *p;
}
template <typename T>
bool hasProperty() const {
// Vérifier d'abord si un type exact est présent
PropertyID id = getPropertyTypeID<T>();
if (propertyBitSet[id]) {
return true;
}
// Si non, vérifier dynamiquement tous les composants pour un type dérivé
for (const auto& p : properties) {
if (dynamic_cast<T*>(p.get())) {
return true;
}
}
return false;
}
template <typename T>
T& getProperty() const {
// Vérification rapide via le BitSet et l'accès direct au composant via l'array
PropertyID id = getPropertyTypeID<T>();
if (propertyBitSet[id]) {
return *static_cast<T*>(propertyArray[id]);
}
// Vérification polymorphique avec dynamic_cast
for (const auto& p : properties) {
if (T* t = dynamic_cast<T*>(p.get())) {
return *t;
}
}
throw runtime_error("Propriété non trouvé.\n");
}
private:
bool active {true};
vector<unique_ptr<Property>> properties;
PropertyArray propertyArray;
PropertyBitSet propertyBitSet;
};
#endif