#pragma once #include #include #include #include #include #include #include #include #include "U_Log.h" #include "CComponent.h" #include "CCallbackHandler.h" class CComponentsManager { public: ~CComponentsManager(); void Add(std::unique_ptr&& comp); bool IsComponentPresent(const std::string& type) const; std::unique_ptr& GetComponent(const std::string& type); CComponent* GetComponentRaw(const std::string& type); void CreateComponent(const std::string& type, bool instantInit = true); void Trace(const std::function& func); void ReverseTrace(const std::function& func); template void DeleteComponent() { auto curHash = typeid(ComponentType).hash_code(); auto _comp_ptr_it = hashCache.find(curHash); if(_comp_ptr_it == hashCache.end()) { return; } auto _comp_ptr = _comp_ptr_it->second; auto it = std::find_if(Items.begin(), Items.end(), [_comp_ptr](const auto& kv) -> bool { //return dynamic_cast(kv.second.get()); return kv.second.get() == _comp_ptr; }); if(it != Items.end()) { it->second->DeInit(); RemoveCache(it->second.get()); Items.erase(it); } } void DeleteComponent(const std::string& type); template void CreateComponent(bool instantInit = true) { Add(std::make_unique()); if(instantInit) { GetComponentTyped()->Init(); GetComponentTyped()->PostInit(); } } template bool IsComponentPresent() const { auto curHash = typeid(ComponentType).hash_code(); auto _comp_ptr_it = hashCache.find(curHash); if(_comp_ptr_it == hashCache.end()) { return false; } auto _comp_ptr = _comp_ptr_it->second; auto it = std::find_if(Items.begin(), Items.end(), [_comp_ptr](const auto& kv) -> bool { //return dynamic_cast(kv.second.get()); return kv.second.get() == _comp_ptr; }); return it != Items.end(); } template ComponentType* GetComponentTyped() { auto curHash = typeid(ComponentType).hash_code(); auto _comp_ptr_it = hashCache.find(curHash); if(_comp_ptr_it == hashCache.end()) { return nullptr; } auto _comp_ptr = _comp_ptr_it->second; return dynamic_cast(_comp_ptr); auto it = std::find_if(Items.begin(), Items.end(), [_comp_ptr](const auto& kv) -> bool { //if(!kv.second) { return false; } return dynamic_cast(kv.second.get()); }); if (it == Items.end()) { //throw std::runtime_error("Component with the specified type not found"); return nullptr; //unreachable } return dynamic_cast((*it).second.get()); } template ComponentType* GetComponentTyped(const std::string& type) { const auto& it = Items.find(type); //if (it == Items.end()) { throw std::runtime_error("No such component"); } if (it == Items.end()) { return nullptr; } if (ComponentType* casted = dynamic_cast(it->second.get())) { return casted; } else { //throw std::runtime_error("Component type mismatch"); return nullptr; } } CCallbackHandler OnComponentAdd; CCallbackHandler OnComponentInit; CCallbackHandler OnComponentPostInit; std::unordered_map> Items; void AddCache(const std::string& name, std::type_index _type, CComponent* _component); void RemoveCache(CComponent* component); private: std::vector getComponentsOrder(); std::unordered_map hashCache; std::unordered_map nameCache; };