Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <map>
- #include <memory>
- #include <vector>
- #include <algorithm>
- #include <type_traits>
- using uInt = std::size_t;
- struct Entity {
- struct Params { using ownerType = Entity; };
- };
- struct RectComponent {
- struct Params
- {
- int width{};
- int height{};
- using ownerType = RectComponent;
- };
- RectComponent(Params&& p) :width(p.width), height{ p.height }{}
- private:
- int width{};
- int height{};
- };
- struct ConstraintComponent {
- struct Params
- {
- int val{};
- using ownerType = ConstraintComponent;
- };
- ConstraintComponent(Params&& p) :val(p.val) {}
- int val;
- };
- struct TextComponent {
- struct Params { using ownerType = TextComponent; };
- };
- template <typename... Args>
- class ECSVector
- {
- public:
- //vector wrapper
- template<typename T>
- class vector_wrapper
- {
- public:
- using const_iterator = typename std::vector<T>::const_iterator;
- size_t size()const { return _vec.size(); }
- size_t capacity()const { return _vec.capacity(); }
- bool empty()const { return _vec.empty(); }
- const_iterator cbegin() const { return _vec.cbegin(); };
- const_iterator cend() const { return _vec.cend(); };
- uInt idToSlot(uInt id)const { return _idToSlot[id]; }
- uInt slotToID(uInt slot)const { return _slotToID[slot]; }
- uInt totalIDsAmmount()const { return _idToSlot.size(); }
- uInt add(typename T::Params&& params) {
- // if there is a free ID, use that, otherwise generate a new one.
- uInt elementID{};
- if (_vec.size() < _slotToID.size()) {
- elementID = _slotToID[_vec.size()];
- }
- else {
- elementID = _vec.size();
- _slotToID.push_back(elementID);
- _idToSlot.push_back(elementID);
- }
- _vec.emplace_back(std::forward<typename T::Params>(params));
- return elementID;
- }
- void remove(uInt ID) {
- //check if ID is present.
- uInt leftElementID = ID;
- uInt rightElementID = _slotToID[_vec.size() - 1];
- uInt leftSlot = _idToSlot[leftElementID];
- uInt rightSlot = _idToSlot[rightElementID];
- //swap element with the back() element of the vector.
- std::swap(_vec[leftSlot], _vec[rightSlot]);
- //update mapping.
- std::swap(_idToSlot[leftElementID], _idToSlot[rightElementID]);
- std::swap(_slotToID[leftSlot], _slotToID[rightSlot]);
- _vec.pop_back();
- }
- private:
- std::vector<T> _vec;
- std::vector<uInt> _slotToID;
- std::vector<uInt> _idToSlot;
- };
- //ECS VECTOR CLASS
- ECSVector() {
- //allocate 1 vector for each type.
- (..., internal_AddVector<Args>());
- }
- template<typename T> vector_wrapper<T>& getVector() {
- static_assert ((... | std::is_same<T, Args>::value), "ECSVector::getVector<T> called with an invalid type");
- void* ptr = data[getTypeID<T>()].get();
- auto* vec = static_cast<vector_wrapper<T>*>(ptr);
- return *vec;
- }
- template<typename T> uInt add(typename T::Params&& params) {
- return getVector<T>().add(std::forward<typename T::Params>(params));
- }
- template<typename T> void remove(uInt id) {
- getVector<T>().remove(id);
- }
- void print_data_layout() {
- (..., print_vector<Args>());
- }
- private:
- std::map<uInt, std::shared_ptr<void>> data;
- template<typename T> uInt getTypeID() const {
- static uInt id = internal_GenerateTypeID();
- return id;
- }
- uInt internal_GenerateTypeID() const {
- static uInt typeIDCounter{};
- return typeIDCounter++;
- }
- template<typename T> void internal_AddVector() {
- data[getTypeID<T>()] = static_cast<std::shared_ptr<void>>(std::make_shared<vector_wrapper<T>>());
- }
- template<typename T> void print_vector()
- {
- auto& vec = getVector<T>();
- //print index
- if (vec.empty()) {
- return;
- }
- //std::cout << "typeId " << getTypeID<T>() << ":" << std::endl;
- std::cout << " Index: ";
- for (size_t i = 0; i < vec.totalIDsAmmount(); i++)
- {
- std::cout << i << " ";
- }
- std::cout << std::endl;
- std::cout << " [ ";
- for (size_t id = 0; id < vec.totalIDsAmmount(); id++)
- {
- std::cout << (id >= vec.size() ? "_" : "O");
- if (id + 1 != vec.totalIDsAmmount())
- std::cout << "| ";
- }
- std::cout << " ]" << std::endl;
- //print Element ID
- std::cout << "ElementID: ";
- for (size_t id = 0; id < vec.totalIDsAmmount(); id++)
- {
- std::cout << vec.slotToID(id) << " ";
- }
- std::cout << std::endl << std::endl << std::endl;
- }
- };
- ECSVector<
- Entity,
- RectComponent,
- ConstraintComponent,
- TextComponent
- > ECdata;
- template<typename... Args>
- void CreateEntity(Args&&... args)
- {
- (..., ECdata.add<typename Args::ownerType>(std::forward<Args>(args)));
- }
- int main()
- {
- CreateEntity(RectComponent::Params{ .width{300}, .height{400} },
- RectComponent::Params{ .width{300}, .height{400} },
- RectComponent::Params{ .width{300}, .height{400} },
- RectComponent::Params{ .width{300}, .height{400} },
- RectComponent::Params{ .width{300}, .height{400} }
- );
- ECdata.print_data_layout();
- ECdata.remove<RectComponent>(1);
- std::cout << "Element ID 1 removed!" << std::endl;
- ECdata.print_data_layout();
- ECdata.remove<RectComponent>(4);
- std::cout << "Element ID 4 removed!" << std::endl;
- ECdata.print_data_layout();
- ECdata.add<RectComponent>(RectComponent::Params{ .width{300}, .height{400} });
- std::cout << "Added component!" << std::endl;
- ECdata.print_data_layout();
- ECdata.add<RectComponent>(RectComponent::Params{ .width{300}, .height{400} });
- std::cout << "Added component!" << std::endl;
- ECdata.print_data_layout();
- ECdata.add<RectComponent>(RectComponent::Params{ .width{300}, .height{400} });
- std::cout << "Added component!" << std::endl;
- ECdata.print_data_layout();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement