diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp index 42d29e00..99463e21 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp @@ -22,42 +22,86 @@ bool AssetLoaderMenuList::CanLoadFromRaw() const return true; } +bool AssetLoaderMenuList::ShouldLoadMenuFile(const std::string& menuFilePath, menu::MenuAssetZoneState* zoneState) +{ + const auto alreadyLoadedFile = zoneState->m_loaded_files.find(menuFilePath); + if (alreadyLoadedFile == zoneState->m_loaded_files.end()) + { + zoneState->m_loaded_files.emplace(menuFilePath); + return true; + } + + return false; +} + +void AssetLoaderMenuList::AddMenuFilesToLoadToQueue(std::deque& queue, const menu::ParsingResult* parsingResult, menu::MenuAssetZoneState* zoneState) +{ + for(const auto& menuFileToLoad : parsingResult->m_menus_to_load) + { + if(ShouldLoadMenuFile(menuFileToLoad, zoneState)) + { + queue.push_back(menuFileToLoad); + } + } +} + +void AssetLoaderMenuList::ProcessParsedResults(const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, menu::ParsingResult* parsingResult, + menu::MenuAssetZoneState* zoneState) +{ + std::cout << "Successfully read menu list \"" << assetName << "\":\n"; + + std::cout << " " << parsingResult->m_menus_to_load.size() << " menus to load:\n"; + for (const auto& menuToLoad : parsingResult->m_menus_to_load) + std::cout << " " << menuToLoad << "\n"; + + std::cout << " " << parsingResult->m_menus.size() << " menus:\n"; + for (const auto& menu : parsingResult->m_menus) + std::cout << " " << menu->m_name << " (" << menu->m_items.size() << " items)\n"; + + std::cout << " " << parsingResult->m_functions.size() << " functions:\n"; + for (const auto& function : parsingResult->m_functions) + std::cout << " " << function->m_name << "\n"; +} + bool AssetLoaderMenuList::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const { - const auto file = searchPath->Open(assetName); - if (!file.IsOpen()) - return false; + std::deque menuFileQueue; - menu::MenuFileReader reader(*file.m_stream, assetName, menu::FeatureLevel::IW4, [searchPath](const std::string& filename, const std::string& sourceFile) -> std::unique_ptr + auto* zoneState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState(); + menuFileQueue.push_back(assetName); + + while (!menuFileQueue.empty()) { - auto foundFileToInclude = searchPath->Open(filename); - if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream) - return nullptr; + const auto& nextMenuFile = menuFileQueue.front(); + const auto file = searchPath->Open(nextMenuFile); + if (!file.IsOpen()) + { + std::cout << "Failed to open menu file \"" << nextMenuFile << "\"\n"; + return false; + } - return std::move(foundFileToInclude.m_stream); - }); + menu::MenuFileReader reader(*file.m_stream, nextMenuFile, menu::FeatureLevel::IW4, [searchPath](const std::string& filename, const std::string& sourceFile) -> std::unique_ptr + { + auto foundFileToInclude = searchPath->Open(filename); + if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream) + return nullptr; - reader.IncludeZoneState(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState()); + return std::move(foundFileToInclude.m_stream); + }); - const auto menuFileResult = reader.ReadMenuFile(); - if(menuFileResult) - { - std::cout << "Successfully read menu list \"" << assetName << "\":\n"; + reader.IncludeZoneState(zoneState); - std::cout << " " << menuFileResult->m_menus_to_load.size() << " menus to load:\n"; - for (const auto& menuToLoad : menuFileResult->m_menus_to_load) - std::cout << " " << menuToLoad << "\n"; + const auto menuFileResult = reader.ReadMenuFile(); + if (menuFileResult) + { + ProcessParsedResults(nextMenuFile, memory, manager, menuFileResult.get(), zoneState); + AddMenuFilesToLoadToQueue(menuFileQueue, menuFileResult.get(), zoneState); + } + else + std::cout << "Could not read menu list \"" << nextMenuFile << "\"\n"; - std::cout << " " << menuFileResult->m_menus.size() << " menus:\n"; - for (const auto& menu : menuFileResult->m_menus) - std::cout << " " << menu->m_name << " (" << menu->m_items.size() << " items)\n"; - - std::cout << " " << menuFileResult->m_functions.size() << " functions:\n"; - for (const auto& function : menuFileResult->m_functions) - std::cout << " " << function->m_name << "\n"; + menuFileQueue.pop_front(); } - else - std::cout << "Could not read menu list \"" << assetName << "\"\n"; return true; } diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.h b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.h index 7afab37f..dfcec233 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.h +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.h @@ -1,14 +1,22 @@ #pragma once +#include + #include "Game/IW4/IW4.h" #include "AssetLoading/BasicAssetLoader.h" #include "AssetLoading/IAssetLoadingManager.h" +#include "Parsing/Menu/MenuAssetZoneState.h" +#include "Parsing/Menu/Domain/MenuParsingResult.h" #include "SearchPath/ISearchPath.h" namespace IW4 { class AssetLoaderMenuList final : public BasicAssetLoader { + static bool ShouldLoadMenuFile(const std::string& menuFilePath, menu::MenuAssetZoneState* zoneState); + static void AddMenuFilesToLoadToQueue(std::deque& queue, const menu::ParsingResult* parsingResult, menu::MenuAssetZoneState* zoneState); + static void ProcessParsedResults(const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, menu::ParsingResult* parsingResult, menu::MenuAssetZoneState* zoneState); + public: _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; _NODISCARD bool CanLoadFromRaw() const override; diff --git a/src/ObjLoading/Parsing/Menu/MenuAssetZoneState.h b/src/ObjLoading/Parsing/Menu/MenuAssetZoneState.h index bef83dda..79d503ce 100644 --- a/src/ObjLoading/Parsing/Menu/MenuAssetZoneState.h +++ b/src/ObjLoading/Parsing/Menu/MenuAssetZoneState.h @@ -1,5 +1,8 @@ #pragma once +#include +#include + #include "AssetLoading/IZoneAssetLoaderState.h" #include "Domain/CommonFunctionDef.h" #include "Domain/CommonMenuDef.h" @@ -9,6 +12,7 @@ namespace menu class MenuAssetZoneState final : public IZoneAssetLoaderState { public: + std::set m_loaded_files; std::vector> m_functions; std::vector> m_menus;