← Back to file list Raw

src/CComponentsManager.h

#pragma once
#include <map>
#include <unordered_map>
#include <memory>
#include <algorithm>
#include <string>
#include <stdexcept>
#include <functional>
#include <typeindex>
#include "U_Log.h"
#include "CComponent.h"
#include "CCallbackHandler.h"
class CComponentsManager
{
public:
~CComponentsManager();
void Add(std::unique_ptr<CComponent>&& comp);
bool IsComponentPresent(const std::string& type) const;
std::unique_ptr<CComponent>& 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<void(CComponent* nod)>& func);
void ReverseTrace(const std::function<void(CComponent* nod)>& func);
template<typename ComponentType>
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<ComponentType*>(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<typename ComponentType>
void CreateComponent(bool instantInit = true)
{
Add(std::make_unique<ComponentType>());
if(instantInit)
{
GetComponentTyped<ComponentType>()->Init();
GetComponentTyped<ComponentType>()->PostInit();
}
}
template<typename ComponentType>
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<ComponentType*>(kv.second.get());
return kv.second.get() == _comp_ptr;
});
return it != Items.end();
}
template<typename ComponentType>
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<ComponentType*>(_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<ComponentType*>(kv.second.get());
});
if (it == Items.end())
{
//throw std::runtime_error("Component with the specified type not found");
return nullptr; //unreachable
}
return dynamic_cast<ComponentType*>((*it).second.get());
}
template<typename ComponentType>
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<ComponentType*>(it->second.get()))
{
return casted;
}
else
{
//throw std::runtime_error("Component type mismatch");
return nullptr;
}
}
CCallbackHandler<void, std::string> OnComponentAdd;
CCallbackHandler<void, std::string> OnComponentInit;
CCallbackHandler<void, std::string> OnComponentPostInit;
std::unordered_map<std::string, std::unique_ptr<CComponent>> Items;
void AddCache(const std::string& name, std::type_index _type, CComponent* _component);
void RemoveCache(CComponent* component);
private:
std::vector<CComponent*> getComponentsOrder();
std::unordered_map<size_t, CComponent*> hashCache;
std::unordered_map<std::string, CComponent*> nameCache;
};