From ee06cccbe1bb1a07d14665a4ed2810fb0bd9c5fb Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Sat, 3 Sep 2022 11:08:23 +0200 Subject: [PATCH] gets rid of the macros, we use a tuple instead, with a mechanism to assign an index to each type. so the tuple is only defined in the cpp, but we can still have template functions in the header that can ge tthe index with the type --- apps/openmw/mwworld/esmstore.cpp | 168 ++++++++++++++----------------- apps/openmw/mwworld/esmstore.hpp | 38 ++++--- apps/openmw/mwworld/store.hpp | 4 +- 3 files changed, 94 insertions(+), 116 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 38dd2c4190..00606939a3 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -130,68 +131,6 @@ namespace } -template -struct StoreIndexToRecordType { - - typedef void recordType; -}; - -static int sRecordTypeCounter = 0; - -#define OPENMW_ESM_ADD_STORE_TYPE(__Type, __REC_NAME,__ID_NUM) template<> const int MWWorld::SRecordType<__Type>::sStoreIndex = sRecordTypeCounter ++; \ -template<> struct StoreIndexToRecordType<__ID_NUM > {typedef __Type recordType;}; \ - -OPENMW_ESM_ADD_STORE_TYPE(ESM::Activator,ESM::REC_ACTI,0); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Potion,ESM::REC_ALCH,1); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Apparatus,ESM::REC_APPA,2); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Armor, ESM::REC_ARMO , 3); -OPENMW_ESM_ADD_STORE_TYPE(ESM::BodyPart, ESM::REC_BODY , 4); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Book, ESM::REC_BOOK , 5); -OPENMW_ESM_ADD_STORE_TYPE(ESM::BirthSign, ESM::REC_BSGN , 6); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Class, ESM::REC_CLAS , 7); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Clothing, ESM::REC_CLOT , 8); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Container, ESM::REC_CONT , 9); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Creature, ESM::REC_CREA , 10); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Dialogue, ESM::REC_DIAL , 11); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Door, ESM::REC_DOOR , 12); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Enchantment, ESM::REC_ENCH , 13); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Faction, ESM::REC_FACT , 14); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Global, ESM::REC_GLOB , 15); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Ingredient, ESM::REC_INGR , 16); -OPENMW_ESM_ADD_STORE_TYPE(ESM::CreatureLevList, ESM::REC_LEVC , 17); -OPENMW_ESM_ADD_STORE_TYPE(ESM::ItemLevList, ESM::REC_LEVI , 18); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Light, ESM::REC_LIGH , 19); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Lockpick, ESM::REC_LOCK , 20); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Miscellaneous, ESM::REC_MISC , 21); -OPENMW_ESM_ADD_STORE_TYPE(ESM::NPC, ESM::REC_NPC_ , 22); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Probe, ESM::REC_PROB , 23); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Race, ESM::REC_RACE , 24); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Region, ESM::REC_REGN , 25); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Repair, ESM::REC_REPA , 26); -OPENMW_ESM_ADD_STORE_TYPE(ESM::SoundGenerator, ESM::REC_SNDG , 27); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Sound, ESM::REC_SOUN , 28); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Spell, ESM::REC_SPEL , 29); -OPENMW_ESM_ADD_STORE_TYPE(ESM::StartScript, ESM::REC_SSCR , 30); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Static, ESM::REC_STAT , 31); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Weapon, ESM::REC_WEAP , 32); -OPENMW_ESM_ADD_STORE_TYPE(ESM::GameSetting, ESM::REC_GMST , 33); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Script, ESM::REC_SCPT , 34); - -// Lists that need special rules -OPENMW_ESM_ADD_STORE_TYPE(ESM::Cell, ESM::REC_CELL , 35); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Land, ESM::REC_LAND , 36); -OPENMW_ESM_ADD_STORE_TYPE(ESM::LandTexture, ESM::REC_LTEX , 37); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Pathgrid, ESM::REC_PGRD , 38); - -OPENMW_ESM_ADD_STORE_TYPE(ESM::MagicEffect, ESM::REC_MGEF , 39); -OPENMW_ESM_ADD_STORE_TYPE(ESM::Skill, ESM::REC_SKIL , 40); - -// Special entry which is hardcoded and not loaded from an ESM -OPENMW_ESM_ADD_STORE_TYPE(ESM::Attribute, ESM::REC_INTERNAL_PLAYER , 41); - -static const int sRecordTypeCount = sRecordTypeCounter; -constexpr int sRecordIndexCount = 42; - template constexpr void constexpr_for(F&& f) { @@ -210,10 +149,54 @@ namespace MWWorld struct ESMStoreImp { - //These 3 don't inherit from store base - Store mMagicEffect; - Store mSkills; - Store mAttributes; + std::tuple < + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + Store, + + // Lists that need special rules + Store, + Store, + Store, + Store, + + Store, + Store, + + // Special entry which is hardcoded and not loaded from an ESM + Store> mStores; std::map mRecNameToStore; std::unordered_map mStoreToRecName; @@ -284,23 +267,32 @@ namespace MWWorld return ptr; } - ESMStoreImp(ESMStore& store) + template + static int AssignStoreToIndex(ESMStore& stores, Store& store) { - } + const int storeIndex = ESMStore::getTypeIndex(); + assert(ESMStore::getTypeIndex() == storeIndex); + if (stores.mStores.size() <= storeIndex) + stores.mStores.resize(storeIndex + 1); - template - static void createStore(ESMStore& stores) - { + assert(&store == &std::get>(stores.mStoreImp->mStores)); + + stores.mStores[storeIndex] = &store; if constexpr (std::is_convertible*, DynamicStore*>::value) { - int storeIndex = SRecordType::sStoreIndex; - stores.mStores[storeIndex] = std::make_unique>(); + stores.mDynamicStores.push_back(&store); constexpr ESM::RecNameInts recName = T::sRecordId; if constexpr (recName != ESM::REC_INTERNAL_PLAYER) { - stores.mStoreImp->mRecNameToStore[recName] = stores.mStores[storeIndex].get(); + stores.mStoreImp->mRecNameToStore[recName] = &store; } } + return 0; + } + + ESMStoreImp(ESMStore& store) + { + } void SetupAfterStoresCreation(ESMStore& store) @@ -336,15 +328,8 @@ namespace MWWorld ESMStore::ESMStore() { - mStores.resize(sRecordTypeCount); - assert(sRecordTypeCounter == sRecordIndexCount); //Otherwise something wen wrong with assigning index to stores mStoreImp = std::make_unique(*this); - - constexpr_for<0, sRecordIndexCount,1> ([this](auto storeIndex) - { - ESMStoreImp::createStore::recordType>(*this); - }); - + std::apply([this](auto& ...x){std::make_tuple(ESMStoreImp::AssignStoreToIndex(*this, x)...);} , mStoreImp->mStores); mDynamicCount = 0; mStoreImp->SetupAfterStoresCreation(*this); getWritable().setCells(getWritable()); @@ -356,7 +341,7 @@ namespace MWWorld void ESMStore::clearDynamic() { - for (const auto& store : mStores) + for (const auto& store : mDynamicStores) store->clearDynamic(); movePlayerRecord(); @@ -451,6 +436,13 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialo } } +static int sTypeIndexCounter = 0; + +int& ESMStore::getTypeIndexCounter() +{ + return sTypeIndexCounter; +} + ESM::LuaScriptsCfg ESMStore::getLuaScriptsCfg() const { ESM::LuaScriptsCfg cfg; @@ -827,14 +819,4 @@ void ESMStore::removeMissingObjects(Store& store) template<> const ESM::Door* ESMStore::overrideRecord(const ESM::Door &toInsert) { return ESMStoreImp::esm3overrideRecord(*this, toInsert); } template<> const ESM::ItemLevList* ESMStore::overrideRecord(const ESM::ItemLevList &toInsert) { return ESMStoreImp::esm3overrideRecord(*this, toInsert); } template<> const ESM::NPC* ESMStore::overrideRecord(const ESM::NPC &toInsert) { return ESMStoreImp::esm3overrideRecord(*this, toInsert); } - - template <> const Store& ESMStore::get() const { return mStoreImp->mMagicEffect; } - template <> Store& ESMStore::getWritable() { return mStoreImp->mMagicEffect; } - - template <> const Store& ESMStore::get() const { return mStoreImp->mSkills; } - template <> Store& ESMStore::getWritable() { return mStoreImp->mSkills; } - - template <> const Store& ESMStore::get() const { return mStoreImp->mAttributes; } - template <> Store& ESMStore::getWritable() { return mStoreImp->mAttributes; } - } // end namespace diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index a097ac6a7f..b4d6e86386 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -26,26 +26,33 @@ namespace ESM namespace MWWorld { struct ESMStoreImp; - template struct SRecordType - { - static const int sStoreIndex; - }; class ESMStore { friend struct ESMStoreImp; //This allows StoreImp to extend esmstore without beeing included everywhere + + static int& getTypeIndexCounter(); + + template + static int getTypeIndex() + { + static int index = getTypeIndexCounter()++; + return index; + } + std::unique_ptr mStoreImp; std::unordered_map mRefCount; - std::vector> mStores; + std::vector mStores; + std::vector mDynamicStores; unsigned int mDynamicCount; mutable std::unordered_map, Misc::StringUtils::CiHash, Misc::StringUtils::CiEqual> mSpellListCache; template - Store& getWritable() {return static_cast&>(*mStores[SRecordType::sStoreIndex]);} + Store& getWritable() {return static_cast&>(*mStores[getTypeIndex()]);} /// Validate entries in store after setup void validate(); @@ -65,14 +72,14 @@ namespace MWWorld ESM::LuaScriptsCfg getLuaScriptsCfg() const; /// \todo replace with SharedIterator - typedef std::vector>::const_iterator iterator; + typedef std::vector::const_iterator iterator; iterator begin() const { - return mStores.begin(); + return mDynamicStores.begin(); } iterator end() const { - return mStores.end(); + return mDynamicStores.end(); } /// Look up the given ID in 'all'. Returns 0 if not found. @@ -94,7 +101,7 @@ namespace MWWorld void load(ESM::ESMReader &esm, Loading::Listener* listener, ESM::Dialogue*& dialogue); template - const Store& get() const {return static_cast&>(*mStores[SRecordType::sStoreIndex]);} + const Store& get() const {return static_cast&>(*mStores[getTypeIndex()]);} /// Insert a custom record (i.e. with a generated ID that will not clash will pre-existing records) template @@ -129,17 +136,6 @@ namespace MWWorld /// @return The shared spell list to use for this actor and whether or not it has already been initialized. std::pair, bool> getSpellList(const std::string& id) const; }; - - //Special cases these aren't DynamicStore, but IndexedStore - template <> const Store& ESMStore::get() const; - template <> Store& ESMStore::getWritable(); - - template <> const Store& ESMStore::get() const; - template <> Store& ESMStore::getWritable(); - - template <> const Store& ESMStore::get() const; - template <> Store& ESMStore::getWritable(); - } #endif diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 2501881803..7d1defad94 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -45,7 +45,7 @@ namespace MWWorld class StoreBase {}; //Empty interface to be parent of all store types - class DynamicStore : StoreBase + class DynamicStore : public StoreBase { public: virtual ~DynamicStore() {} @@ -69,7 +69,7 @@ namespace MWWorld }; template - class IndexedStore : StoreBase + class IndexedStore : public StoreBase { protected: typedef typename std::map Static;