Advertisement
Guest User

Untitled

a guest
Dec 4th, 2019
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.60 KB | None | 0 0
  1. #include <iostream>
  2. #include <map>
  3. #include <memory>
  4. #include <vector>
  5. #include <algorithm>
  6. #include <type_traits>
  7. using uInt = std::size_t;
  8.  
  9. struct Entity {
  10.     struct Params { using ownerType = Entity; };
  11. };
  12.  
  13. struct RectComponent {
  14.  
  15.     struct Params
  16.     {
  17.         int width{};
  18.         int height{};
  19.         using ownerType = RectComponent;
  20.     };
  21.  
  22.     RectComponent(Params&& p) :width(p.width), height{ p.height }{}
  23.  
  24. private:
  25.     int width{};
  26.     int height{};
  27. };
  28.  
  29. struct ConstraintComponent {
  30.     struct Params
  31.     {
  32.         int val{};
  33.         using ownerType = ConstraintComponent;
  34.     };
  35.     ConstraintComponent(Params&& p) :val(p.val) {}
  36.     int val;
  37. };
  38.  
  39. struct TextComponent {
  40.     struct Params { using ownerType = TextComponent; };
  41. };
  42.  
  43. template <typename... Args>
  44. class ECSVector
  45. {
  46. public:
  47.  
  48.     //vector wrapper
  49.     template<typename T>
  50.     class vector_wrapper
  51.     {
  52.     public:
  53.  
  54.         using const_iterator = typename std::vector<T>::const_iterator;
  55.  
  56.         size_t size()const { return _vec.size(); }
  57.         size_t capacity()const { return _vec.capacity(); }
  58.         bool empty()const { return _vec.empty(); }
  59.         const_iterator cbegin() const { return _vec.cbegin(); };
  60.         const_iterator cend() const { return _vec.cend(); };
  61.         uInt idToSlot(uInt id)const { return _idToSlot[id]; }
  62.         uInt slotToID(uInt slot)const { return _slotToID[slot]; }
  63.         uInt totalIDsAmmount()const { return _idToSlot.size(); }
  64.  
  65.         uInt add(typename T::Params&& params) {
  66.  
  67.             // if there is a free ID, use that, otherwise generate a new one.
  68.             uInt elementID{};
  69.             if (_vec.size() < _slotToID.size()) {
  70.                 elementID = _slotToID[_vec.size()];
  71.             }
  72.             else {
  73.                 elementID = _vec.size();
  74.                 _slotToID.push_back(elementID);
  75.                 _idToSlot.push_back(elementID);
  76.             }
  77.             _vec.emplace_back(std::forward<typename T::Params>(params));
  78.             return elementID;
  79.         }
  80.  
  81.         void remove(uInt ID) {
  82.  
  83.             //check if ID is present.
  84.  
  85.             uInt leftElementID = ID;
  86.             uInt rightElementID = _slotToID[_vec.size() - 1];
  87.  
  88.             uInt leftSlot = _idToSlot[leftElementID];
  89.             uInt rightSlot = _idToSlot[rightElementID];
  90.  
  91.             //swap element with the back() element of the vector.
  92.             std::swap(_vec[leftSlot], _vec[rightSlot]);
  93.  
  94.             //update mapping.
  95.             std::swap(_idToSlot[leftElementID], _idToSlot[rightElementID]);
  96.             std::swap(_slotToID[leftSlot], _slotToID[rightSlot]);
  97.  
  98.             _vec.pop_back();
  99.         }
  100.  
  101.     private:
  102.         std::vector<T> _vec;
  103.         std::vector<uInt> _slotToID;
  104.         std::vector<uInt> _idToSlot;
  105.     };
  106.  
  107.     //ECS VECTOR CLASS
  108.  
  109.     ECSVector() {
  110.         //allocate 1 vector for each type.
  111.         (..., internal_AddVector<Args>());
  112.     }
  113.  
  114.     template<typename T> vector_wrapper<T>& getVector() {
  115.         static_assert ((... | std::is_same<T, Args>::value), "ECSVector::getVector<T> called with an invalid type");
  116.         void* ptr = data[getTypeID<T>()].get();
  117.         auto* vec = static_cast<vector_wrapper<T>*>(ptr);
  118.         return *vec;
  119.     }
  120.  
  121.     template<typename T> uInt add(typename T::Params&& params) {
  122.         return getVector<T>().add(std::forward<typename T::Params>(params));
  123.     }
  124.  
  125.     template<typename T> void remove(uInt id) {
  126.         getVector<T>().remove(id);
  127.     }
  128.  
  129.     void print_data_layout() {
  130.         (..., print_vector<Args>());
  131.     }
  132.  
  133.  
  134. private:
  135.     std::map<uInt, std::shared_ptr<void>> data;
  136.  
  137.     template<typename T> uInt getTypeID() const {
  138.         static uInt id = internal_GenerateTypeID();
  139.         return id;
  140.     }
  141.  
  142.     uInt internal_GenerateTypeID() const {
  143.         static uInt typeIDCounter{};
  144.         return typeIDCounter++;
  145.     }
  146.  
  147.     template<typename T> void internal_AddVector() {
  148.         data[getTypeID<T>()] = static_cast<std::shared_ptr<void>>(std::make_shared<vector_wrapper<T>>());
  149.     }
  150.  
  151.     template<typename T> void print_vector()
  152.     {
  153.  
  154.         auto& vec = getVector<T>();
  155.  
  156.         //print index
  157.         if (vec.empty()) {
  158.             return;
  159.         }
  160.  
  161.         //std::cout << "typeId " << getTypeID<T>() << ":" << std::endl;
  162.         std::cout << "    Index: ";
  163.         for (size_t i = 0; i < vec.totalIDsAmmount(); i++)
  164.         {
  165.             std::cout << i << "  ";
  166.         }
  167.         std::cout << std::endl;
  168.  
  169.         std::cout << "         [ ";
  170.         for (size_t id = 0; id < vec.totalIDsAmmount(); id++)
  171.         {
  172.             std::cout << (id >= vec.size() ? "_" : "O");
  173.        
  174.             if (id + 1 != vec.totalIDsAmmount())
  175.                 std::cout << "| ";
  176.         }
  177.         std::cout << " ]" << std::endl;
  178.  
  179.         //print Element ID
  180.         std::cout << "ElementID: ";
  181.         for (size_t id = 0; id < vec.totalIDsAmmount(); id++)
  182.         {
  183.             std::cout << vec.slotToID(id) << "  ";
  184.         }
  185.  
  186.         std::cout << std::endl << std::endl << std::endl;
  187.     }
  188.  
  189. };
  190.  
  191. ECSVector<
  192.     Entity,
  193.     RectComponent,
  194.     ConstraintComponent,
  195.     TextComponent
  196. > ECdata;
  197.  
  198. template<typename... Args>
  199. void CreateEntity(Args&&... args)
  200. {
  201.     (..., ECdata.add<typename Args::ownerType>(std::forward<Args>(args)));
  202. }
  203.  
  204. int main()
  205. {
  206.     CreateEntity(RectComponent::Params{ .width{300}, .height{400} },
  207.                  RectComponent::Params{ .width{300}, .height{400} },
  208.                  RectComponent::Params{ .width{300}, .height{400} },
  209.                  RectComponent::Params{ .width{300}, .height{400} },
  210.                  RectComponent::Params{ .width{300}, .height{400} }
  211.     );
  212.     ECdata.print_data_layout();
  213.     ECdata.remove<RectComponent>(1);
  214.     std::cout << "Element ID 1 removed!" << std::endl;
  215.     ECdata.print_data_layout();
  216.     ECdata.remove<RectComponent>(4);
  217.     std::cout << "Element ID 4 removed!" << std::endl;
  218.     ECdata.print_data_layout();
  219.     ECdata.add<RectComponent>(RectComponent::Params{ .width{300}, .height{400} });
  220.     std::cout << "Added component!" << std::endl;
  221.     ECdata.print_data_layout();
  222.     ECdata.add<RectComponent>(RectComponent::Params{ .width{300}, .height{400} });
  223.     std::cout << "Added component!" << std::endl;
  224.     ECdata.print_data_layout();
  225.     ECdata.add<RectComponent>(RectComponent::Params{ .width{300}, .height{400} });
  226.     std::cout << "Added component!" << std::endl;
  227.     ECdata.print_data_layout();
  228.     return 0;
  229. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement