#pragma once #include #include #include "CScriptingEngine.h" #include "CScriptClassInfo.h" #include "CObjectFactory.h" template class CScriptClassesManager { public: using ClassInfoMap = std::unordered_map>; using ClassesList = std::vector; class CDeleterBase { public: virtual void Delete() = 0; virtual ~CDeleterBase() {} }; template class CDeleter : public CDeleterBase { public: CDeleter(CObjectFactory& _Factory, CFunctionBase* _Function, CFunctionBase* _FindFunction) : Factory(_Factory), Function(_Function), FindFunction(_FindFunction) {} ~CDeleter() { Delete(); } void Delete() override { Factory.OnTryCreateHandler.DeleteFunction(Function); Factory.OnTryFindHandler.DeleteFunction(FindFunction); } CObjectFactory& Factory; CFunctionBase* Function = nullptr; CFunctionBase* FindFunction = nullptr; }; template ClassInfoMap& GetClassInfoMap() { size_t hash = typeid(Base).hash_code(); if(HashClassInfos.find(hash) == HashClassInfos.end()) { HashClassInfos.insert({ hash, ClassInfoMap() }); } return HashClassInfos.find(hash)->second; } template CObjectFactoryBase& GetFactory() { size_t hash = typeid(Base).hash_code(); return HashFactories.find(hash)->second.get(); } template void SetFunction(CObjectFactory& factory) { size_t hash = typeid(Base).hash_code(); if(HashClassInfos.find(hash) == HashClassInfos.end()) { HashClassInfos.insert({ hash, ClassInfoMap() }); } if(HashFactories.find(hash) == HashFactories.end()) { HashFactories.insert({ hash, std::ref(factory) }); } factory.OnTryCreateHandler += [this, hash](const IdType& id) -> void* { auto it_hash = HashClassInfos.find(hash); if(it_hash == HashClassInfos.end()) { return nullptr; } auto& ClassInfos = it_hash->second; auto it = ClassInfos.find(id); if(it == ClassInfos.end()) { return nullptr; } return (void*)(new Generic(it->second.LuaKey, it->second.Functions, it->second.State)); }; factory.OnTryFindHandler += [this, hash](const IdType& id) -> bool { auto it_hash = HashClassInfos.find(hash); if(it_hash == HashClassInfos.end()) { return false; } auto& ClassInfos = it_hash->second; auto it = ClassInfos.find(id); if(it == ClassInfos.end()) { return false; } return true; }; CFunctionBase* func = factory.OnTryCreateHandler.GetLastFunctionRaw(); CFunctionBase* findfunc = factory.OnTryFindHandler.GetLastFunctionRaw(); Deleters.push_back(std::make_unique>(factory, func, findfunc)); } template void RegisterClassInfo(const CScriptClassInfo& info) { if(info.LuaKey.empty()) { return; } auto& info_map = GetClassInfoMap(); auto& factory = GetFactory(); if(info_map.find(info.LuaKey) != info_map.end()) { return; } info_map.insert({ info.LuaKey, info }); factory.AddScriptClass(info.LuaKey); } template bool IsClassRegistered(const IdType& className) const { size_t hash = typeid(Base).hash_code(); auto it = HashClassInfos.find(hash); if (it == HashClassInfos.end()) { return false; } return it->second.find(className) != it->second.end(); } template void UnregisterClassInfo(const IdType& id) { std::erase_if(GetClassInfoMap(), [&id](auto& kv) -> bool { return kv.second.LuaKey == id; }); auto& factory = GetFactory(); factory.RemoveScriptClass(id); } template void UnregisterClassesInfo(CScriptingEngine* engine) { std::erase_if(GetClassInfoMap(), [engine](auto& kv) -> bool { return kv.second.Engine == engine; }); } template void UnregisterClassesInfo(sol::state_view st) { std::erase_if(GetClassInfoMap(), [&st](auto& kv) -> bool { return kv.second.State == st; }); } template void ResetEngineClasses(CScriptingEngine* engine) { UnregisterClassesInfo(engine); } void UnregisterClassInfoEverywhere(const IdType& id) { for(auto& kv : HashClassInfos) { std::erase_if(kv.second, [&id](auto& kv) -> bool { return kv.second.LuaKey == id; }); } } void UnregisterClassesInfoEverywhere(CScriptingEngine* engine) { for(auto& kv : HashClassInfos) { std::erase_if(kv.second, [engine](auto& kv) -> bool { return kv.second.Engine == engine; }); } } void UnregisterClassesInfoEverywhere(sol::state_view st) { for(auto& kv : HashClassInfos) { std::erase_if(kv.second, [&st](auto& kv) -> bool { return kv.second.State == st; }); } } void ResetEngineClassesEverywhere(CScriptingEngine* engine) { UnregisterClassesInfoEverywhere(engine); } std::vector> Deleters; std::unordered_map HashClassInfos; std::unordered_map>> HashFactories; //std::unique_ptr Deleter; //ClassInfos; };