← Back to file list Raw

src/CScriptClassesManager.h

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