128 lines
3.2 KiB
C++
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
|