diff --git a/tests/zecsy.cpp b/tests/zecsy.cpp index cfa96b5..5aa7360 100644 --- a/tests/zecsy.cpp +++ b/tests/zecsy.cpp @@ -113,3 +113,19 @@ TEST_CASE("Retrieve a component from an entity and verify its data matches what REQUIRE(e.get().value == "super-zecsy!"); } + +TEST_CASE("Remove a component from an entity and verify it is no longer attached") +{ + world w; + + auto e = w.make_entity(); + e.set(ChoosenOne{}); + REQUIRE_NOTHROW(e.remove()); + + REQUIRE_FALSE(e.has()); + + e.set(ChoosenOne{}); + REQUIRE_NOTHROW(w.remove(e)); + + REQUIRE_FALSE(w.has(e)); +} diff --git a/zecsy.hpp b/zecsy.hpp index ac3e2a2..a314799 100644 --- a/zecsy.hpp +++ b/zecsy.hpp @@ -2,10 +2,10 @@ #include #include #include +#include #include #include #include -#include #ifndef MAX_ZECSY_ENTITIES #define MAX_ZECSY_ENTITIES 65536 @@ -38,6 +38,9 @@ namespace zecsy template void set(const T& comp = T{}); + + template + void remove(); private: entity_id id = 0; class world* w = nullptr; @@ -56,6 +59,9 @@ namespace zecsy template void set(entity_id e, const T& comp = T{}); + + template + void remove(entity_id e); private: using comp_index = std::type_index; using comp_to_bitset = std::unordered_map; @@ -67,9 +73,13 @@ namespace zecsy using comp_to_storage = std::unordered_map>; + using comp_to_reusable_ids = std::unordered_map>; + comp_to_bitset bitset_dict; comp_to_entity_dict entity_dict; comp_to_storage storage_dict; + comp_to_reusable_ids reusable_id_queues; }; class world final @@ -93,6 +103,9 @@ namespace zecsy template void set(entity_id e, const T& comp = T{}); + + template + void remove(entity_id e); private: zecsy_bits entities_bitset; entity_id entity_counter = 0; @@ -196,14 +209,28 @@ namespace zecsy auto& storage = storage_dict[typeid(T)]; - size_t T_size = sizeof(T); - size_t old_size = storage.size(); + auto& reusable_ids = reusable_id_queues[typeid(T)]; - storage.resize(old_size + T_size); - void* ptr = &storage[0] + old_size; - new(ptr) T(comp); + if(reusable_ids.empty()) + { + size_t T_size = sizeof(T); + size_t old_size = storage.size(); - entity_dict[typeid(T)][e] = old_size / T_size; + storage.resize(old_size + T_size); + void* ptr = &storage[0] + old_size; + new(ptr) T(comp); + + entity_dict[typeid(T)][e] = old_size / T_size; + return; + } + + auto index = reusable_ids.front(); + reusable_ids.pop(); + + auto ptr = reinterpret_cast(&storage[0]); + new(ptr + index) T(comp); + + entity_dict[typeid(T)][e] = index; } template @@ -217,4 +244,29 @@ namespace zecsy { w->set(id, comp); } + + template + inline void component_storage::remove(entity_id e) + { + if(!has(e)) + { + return; + } + + bitset_dict[typeid(T)].reset(e); + reusable_id_queues[typeid(T)].push(entity_dict[typeid(T)][e]); + entity_dict[typeid(T)].erase(e); + } + + template + inline void world::remove(entity_id e) + { + storage.remove(e); + } + + template + inline void entity::remove() + { + w->remove(id); + } };