#pragma once #include #include #include #include #include #include #include "CCallbackHandler.h" #include template class AbstractCreator { public: virtual ~AbstractCreator() = default; virtual Base* create() const = 0; }; template class Creator : public AbstractCreator { public: Base* create() const override { return new C(); } }; template class CObjectFactoryBase { public: virtual ~CObjectFactoryBase() = default; virtual std::vector GetRegisteredIds() const { return {}; } virtual std::vector GetRegisteredIdsNative() const { return {}; } virtual size_t GetIndexNative(const IdType& id) const { return 0; } virtual size_t GetIndex(const IdType& id) const { return 0; } IdType GetByID(size_t id) const { auto it = IdCache.find(id); if(it == IdCache.end()) { return {}; } return it->second; } void RecacheIds() { IdCache.clear(); auto ids = GetRegisteredIds(); for(auto& id : ids) { IdCache.emplace(GetIndex(id), id); } } void AddScriptClass(const IdType& id) { ScriptClasses.push_back(id); RecacheIds(); } void RemoveScriptClass(const IdType& id) { std::erase(ScriptClasses, id); RecacheIds(); } std::vector ScriptClasses; std::unordered_map IdCache; }; template class CObjectFactory : public CObjectFactoryBase //TODO exists && getcount aren't interacting with custom creation funcs { public: using PBase = CObjectFactoryBase; //as in Parent Base using AbstractFactory = std::unique_ptr>; using FactoryMap = std::unordered_map; CObjectFactory() = default; virtual ~CObjectFactory() = default; template void add(const IdType& id) { //std::lock_guard lock(factoryMutex); if (Factory.find(id) == Factory.end()) { Factory[id] = std::make_unique>(); PBase::RecacheIds(); } } template void replace(const IdType& id) //TODO script classes support { auto it = Factory.find(id); if(it != Factory.end()) { Factory.erase(it); } Factory[id] = std::make_unique>(); PBase::RecacheIds(); } Base* createRaw(const IdType& id) const { //std::lock_guard lock(factoryMutex); if(!OnTryCreateHandler.IsEmpty()) { Base* bs = nullptr; for(auto& func : OnTryCreateHandler.Functions) { bs = static_cast(func(id)); if(bs) { break; } } if(bs) { OnCreate(bs); return bs; } } auto it = Factory.find(id); if (it != Factory.end()) { Base* obj = it->second->create(); OnCreate(obj); return obj; } return nullptr; } template > PtrType create(const IdType& id) const { //std::lock_guard lock(factoryMutex); if(!OnTryCreateHandler.IsEmpty()) { Base* bs = nullptr; for(auto& func : OnTryCreateHandler.Functions) { bs = static_cast((*func)(id)); if(bs) { break; } } if(bs) { std::unique_ptr obj(bs); OnCreate(obj.get()); if constexpr (std::is_same_v>) { return std::shared_ptr(std::move(obj)); } return obj; } } auto it = Factory.find(id); if (it != Factory.end()) { std::unique_ptr obj(it->second->create()); OnCreate(obj.get()); if constexpr (std::is_same_v>) { return std::shared_ptr(std::move(obj)); } return obj; } return nullptr; } bool remove(const IdType& id) { //std::lock_guard lock(factoryMutex); return Factory.erase(id) > 0; } size_t GetCount() const { //std::lock_guard lock(factoryMutex); return Factory.size() + PBase::ScriptClasses.size(); } size_t GetCountNative() const { //std::lock_guard lock(factoryMutex); return Factory.size(); } size_t GetIndexNative(const IdType& id) const override { //std::lock_guard lock(factoryMutex); auto it = Factory.find(id); if (it != Factory.end()) { return std::distance(Factory.begin(), it); } return std::numeric_limits::max(); } size_t GetIndex(const IdType& id) const override { //std::lock_guard lock(factoryMutex); auto it = Factory.find(id); if (it != Factory.end()) { return std::distance(Factory.begin(), it); } else { auto it2 = std::find(PBase::ScriptClasses.begin(), PBase::ScriptClasses.end(), id); if(it2 != PBase::ScriptClasses.end()) { return Factory.size() + std::distance(PBase::ScriptClasses.begin(), it2); } } return std::numeric_limits::max(); } bool Exists(const IdType& id) const { //std::lock_guard lock(factoryMutex); if(!OnTryFindHandler.IsEmpty()) { for(auto& func : OnTryFindHandler.Functions) { if((*func)(id)) { return true; } } } return Factory.find(id) != Factory.end(); } std::vector GetRegisteredIds() const override { //std::lock_guard lock(factoryMutex); std::vector ids; for (const auto& pair : Factory) { ids.push_back(pair.first); } for(const auto& sclass : PBase::ScriptClasses) { ids.push_back(sclass); } return ids; } std::vector GetRegisteredIdsNative() const override { //std::lock_guard lock(factoryMutex); std::vector ids; for (const auto& pair : Factory) { ids.push_back(pair.first); } return ids; } CCallbackHandler OnCreate; CCallbackHandler OnTryCreateHandler; CCallbackHandler OnTryFindHandler; private: FactoryMap Factory; mutable std::mutex factoryMutex; };