diff --git a/zecsy.hpp b/zecsy.hpp index cf1aa29..4c2279c 100644 --- a/zecsy.hpp +++ b/zecsy.hpp @@ -35,166 +35,6 @@ namespace zecsy */ using entities_set = std::set; - class component_storage final - { - public: - template - bool has(entity_id e) const; - - template - bool has(entity_id e) const; - - template - T& get(entity_id e); - - template - void set(entity_id e); - - template - void set(entity_id e, const T& comp); - - template - void set(entity_id e); - - template - void set(entity_id e, const First& comp0, const Second& comp1, - const Rest&... rest_comps); - - template - void remove(entity_id e); - - template - void remove(entity_id e); - - private: - using comp_id = size_t; - - struct component_pool - { - std::vector data; - std::vector free_list; // Reusable indices - std::unordered_map entity_to_index; - std::unordered_map index_to_entity; - }; - - std::unordered_map pools; - - template - static comp_id get_component_id() - { - static comp_id id = next_component_id++; - return id; - } - - static comp_id next_component_id; - }; - - inline component_storage::comp_id component_storage::next_component_id = 0; - - template - inline bool component_storage::has(entity_id e) const - { - auto id = get_component_id(); - if(pools.contains(id)) - { - return pools.at(id).entity_to_index.contains(e); - } - return false; - } - - template - inline T& component_storage::get(entity_id e) - { - auto id = get_component_id(); - if(!has(e)) - { - throw std::runtime_error( - std::format("Entity #{} doesn't have {}", e, typeid(T).name())); - } - - auto& pool = pools.at(id); - auto index = pool.entity_to_index.at(e); - return *reinterpret_cast(&pool.data[index * sizeof(T)]); - } - - template - inline void component_storage::set(entity_id e, const T& comp) - { - auto id = get_component_id(); - auto& pool = pools[id]; - - size_t index; - if(!pool.free_list.empty()) - { - index = pool.free_list.back(); - pool.free_list.pop_back(); - } - else - { - index = pool.data.size() / sizeof(T); - pool.data.resize(pool.data.size() + sizeof(T)); - } - - new(&pool.data[index * sizeof(T)]) T(comp); - pool.entity_to_index[e] = index; - pool.index_to_entity[index] = e; - } - - template - inline void component_storage::set(entity_id e) - { - set(e, T{}); - } - - template - inline void component_storage::remove(entity_id e) - { - auto id = get_component_id(); - if(!has(e)) - { - return; - } - - auto& pool = pools[id]; - auto index = pool.entity_to_index[e]; - - pool.free_list.push_back(index); - pool.entity_to_index.erase(e); - pool.index_to_entity.erase(index); - } - - template - inline bool component_storage::has(entity_id e) const - { - return has(e) && has(e) && (has(e) && ...); - } - - template - inline void component_storage::set(entity_id e) - { - set(e, First{}); - set(e, Second{}); - (set(e, Rest{}), ...); - } - - template - inline void component_storage::set(entity_id e, const First& comp0, - const Second& comp1, - const Rest&... rest_comps) - { - set(e, comp0); - set(e, comp1); - (set(e, rest_comps), ...); - } - - template - inline void component_storage::remove(entity_id e) - { - remove(e); - remove(e); - (remove(e), ...); - } - class system_scheduler final { public: @@ -248,19 +88,32 @@ namespace zecsy void destroy_entity(entity_id e); bool is_alive(entity_id e) const; - template + template + bool has(entity_id e) const; + + template bool has(entity_id e) const; template T& get(entity_id e); - template + template void set(entity_id e); - template - void set(entity_id e, const T&... comps); + template + void set(entity_id e, const T& comp); - template + template + void set(entity_id e); + + template + void set(entity_id e, const First& comp0, const Second& comp1, + const Rest&... rest_comps); + + template + void remove(entity_id e); + + template void remove(entity_id e); template @@ -269,9 +122,31 @@ namespace zecsy private: entities_set alive_entities; entity_id entity_counter = 0; - component_storage storage; + + using comp_id = size_t; + + struct component_pool + { + std::vector data; + std::vector free_list; // Reusable indices + std::unordered_map entity_to_index; + std::unordered_map index_to_entity; + }; + + std::unordered_map pools; + + template + static comp_id get_component_id() + { + static comp_id id = next_component_id++; + return id; + } + + static comp_id next_component_id; }; + inline world::comp_id world::next_component_id = 0; + inline entity_id world::make_entity() { auto id = ++entity_counter; @@ -289,34 +164,107 @@ namespace zecsy return alive_entities.contains(e); } - template + template inline bool world::has(entity_id e) const { - return storage.has(e); + auto id = get_component_id(); + if(pools.contains(id)) + { + return pools.at(id).entity_to_index.contains(e); + } + return false; } template inline T& world::get(entity_id e) { - return storage.get(e); + auto id = get_component_id(); + if(!has(e)) + { + throw std::runtime_error( + std::format("Entity #{} doesn't have {}", e, typeid(T).name())); + } + + auto& pool = pools.at(id); + auto index = pool.entity_to_index.at(e); + return *reinterpret_cast(&pool.data[index * sizeof(T)]); } - template + template + inline void world::set(entity_id e, const T& comp) + { + auto id = get_component_id(); + auto& pool = pools[id]; + + size_t index; + if(!pool.free_list.empty()) + { + index = pool.free_list.back(); + pool.free_list.pop_back(); + } + else + { + index = pool.data.size() / sizeof(T); + pool.data.resize(pool.data.size() + sizeof(T)); + } + + new(&pool.data[index * sizeof(T)]) T(comp); + pool.entity_to_index[e] = index; + pool.index_to_entity[index] = e; + } + + template inline void world::set(entity_id e) { - storage.set(e); + set(e, T{}); } - template - inline void world::set(entity_id e, const T&... comps) - { - storage.set(e, comps...); - } - - template + template inline void world::remove(entity_id e) { - storage.remove(e); + auto id = get_component_id(); + if(!has(e)) + { + return; + } + + auto& pool = pools[id]; + auto index = pool.entity_to_index[e]; + + pool.free_list.push_back(index); + pool.entity_to_index.erase(e); + pool.index_to_entity.erase(index); + } + + template + inline bool world::has(entity_id e) const + { + return has(e) && has(e) && (has(e) && ...); + } + + template + inline void world::set(entity_id e) + { + set(e, First{}); + set(e, Second{}); + (set(e, Rest{}), ...); + } + + template + inline void world::set(entity_id e, const First& comp0, const Second& comp1, + const Rest&... rest_comps) + { + set(e, comp0); + set(e, comp1); + (set(e, rest_comps), ...); + } + + template + inline void world::remove(entity_id e) + { + remove(e); + remove(e); + (remove(e), ...); } template