-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from Laupetin/feature/iw5-menus
IW5 Menu writing & dumping improvements
- Loading branch information
Showing
47 changed files
with
2,189 additions
and
181 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuDef.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include "AssetLoaderMenuDef.h" | ||
|
||
#include <cstring> | ||
|
||
#include "ObjLoading.h" | ||
#include "Game/IW5/IW5.h" | ||
#include "Pool/GlobalAssetPool.h" | ||
|
||
using namespace IW5; | ||
|
||
void* AssetLoaderMenuDef::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) | ||
{ | ||
auto* menu = memory->Create<menuDef_t>(); | ||
memset(menu, 0, sizeof(menuDef_t)); | ||
menu->window.name = memory->Dup(assetName.c_str()); | ||
return menu; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#pragma once | ||
|
||
#include "Game/IW5/IW5.h" | ||
#include "AssetLoading/BasicAssetLoader.h" | ||
#include "SearchPath/ISearchPath.h" | ||
|
||
namespace IW5 | ||
{ | ||
class AssetLoaderMenuDef final : public BasicAssetLoader<ASSET_TYPE_MENU, menuDef_t> | ||
{ | ||
public: | ||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; | ||
}; | ||
} |
207 changes: 207 additions & 0 deletions
207
src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuList.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
#include "AssetLoaderMenuList.h" | ||
|
||
#include <cstring> | ||
#include <iostream> | ||
|
||
#include "ObjLoading.h" | ||
#include "Game/IW5/IW5.h" | ||
#include "Game/IW5/Menu/MenuConversionZoneStateIW5.h" | ||
#include "Game/IW5/Menu/MenuConverterIW5.h" | ||
#include "Parsing/Menu/MenuFileReader.h" | ||
#include "Pool/GlobalAssetPool.h" | ||
|
||
using namespace IW5; | ||
|
||
namespace IW5 | ||
{ | ||
class MenuLoader | ||
{ | ||
public: | ||
static bool ProcessParsedResults(const std::string& fileName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, menu::ParsingResult* parsingResult, | ||
menu::MenuAssetZoneState* zoneState, MenuConversionZoneState* conversionState, std::vector<menuDef_t*>& menus, | ||
std::vector<XAssetInfoGeneric*>& menuListDependencies) | ||
{ | ||
const auto menuCount = parsingResult->m_menus.size(); | ||
const auto functionCount = parsingResult->m_functions.size(); | ||
const auto menuLoadCount = parsingResult->m_menus_to_load.size(); | ||
auto totalItemCount = 0u; | ||
for (const auto& menu : parsingResult->m_menus) | ||
totalItemCount += menu->m_items.size(); | ||
|
||
std::cout << "Successfully read menu file \"" << fileName << "\" (" << menuLoadCount << " loads, " << menuCount << " menus, " << functionCount << " functions, " << totalItemCount << | ||
" items)\n"; | ||
|
||
// Add all functions to the zone state to make them available for all menus to be converted | ||
for (auto& function : parsingResult->m_functions) | ||
zoneState->AddFunction(std::move(function)); | ||
|
||
// Prepare a list of all menus of this file | ||
std::vector<XAssetInfo<menuDef_t>*> allMenusOfFile; | ||
allMenusOfFile.reserve(parsingResult->m_menus.size()); | ||
|
||
// Convert all menus and add them as assets | ||
for (auto& menu : parsingResult->m_menus) | ||
{ | ||
MenuConverter converter(ObjLoading::Configuration.MenuNoOptimization, searchPath, memory, manager); | ||
auto* menuAsset = converter.ConvertMenu(*menu); | ||
if (menuAsset == nullptr) | ||
{ | ||
std::cout << "Failed to convert menu file \"" << menu->m_name << "\"\n"; | ||
return false; | ||
} | ||
|
||
menus.push_back(menuAsset); | ||
auto* menuAssetInfo = manager->AddAsset(ASSET_TYPE_MENU, menu->m_name, menuAsset, std::move(converter.GetDependencies()), std::vector<scr_string_t>()); | ||
|
||
if (menuAssetInfo) | ||
{ | ||
allMenusOfFile.push_back(reinterpret_cast<XAssetInfo<menuDef_t>*>(menuAssetInfo)); | ||
menuListDependencies.push_back(menuAssetInfo); | ||
} | ||
|
||
zoneState->AddMenu(std::move(menu)); | ||
} | ||
|
||
// Register this file with all loaded menus | ||
conversionState->AddLoadedFile(fileName, std::move(allMenusOfFile)); | ||
|
||
return true; | ||
} | ||
|
||
static MenuList* CreateMenuListAsset(const std::string& assetName, MemoryManager* memory, const std::vector<menuDef_t*>& menus) | ||
{ | ||
auto* menuListAsset = memory->Create<MenuList>(); | ||
menuListAsset->name = memory->Dup(assetName.c_str()); | ||
menuListAsset->menuCount = static_cast<int>(menus.size()); | ||
|
||
if (menuListAsset->menuCount > 0) | ||
{ | ||
menuListAsset->menus = static_cast<menuDef_t**>(memory->Alloc(sizeof(uintptr_t) * menuListAsset->menuCount)); | ||
for (auto i = 0; i < menuListAsset->menuCount; i++) | ||
menuListAsset->menus[i] = menus[i]; | ||
} | ||
else | ||
menuListAsset->menus = nullptr; | ||
|
||
return menuListAsset; | ||
} | ||
|
||
static std::unique_ptr<menu::ParsingResult> ParseMenuFile(const std::string& menuFileName, ISearchPath* searchPath, const menu::MenuAssetZoneState* zoneState) | ||
{ | ||
const auto file = searchPath->Open(menuFileName); | ||
if (!file.IsOpen()) | ||
return nullptr; | ||
|
||
menu::MenuFileReader reader(*file.m_stream, menuFileName, menu::FeatureLevel::IW5, [searchPath](const std::string& filename, const std::string& sourceFile) -> std::unique_ptr<std::istream> | ||
{ | ||
auto foundFileToInclude = searchPath->Open(filename); | ||
if (!foundFileToInclude.IsOpen() || !foundFileToInclude.m_stream) | ||
return nullptr; | ||
|
||
return std::move(foundFileToInclude.m_stream); | ||
}); | ||
|
||
reader.IncludeZoneState(zoneState); | ||
reader.SetPermissiveMode(ObjLoading::Configuration.MenuPermissiveParsing); | ||
|
||
return reader.ReadMenuFile(); | ||
} | ||
}; | ||
} | ||
|
||
void* AssetLoaderMenuList::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) | ||
{ | ||
auto* menuList = memory->Create<MenuList>(); | ||
memset(menuList, 0, sizeof(MenuList)); | ||
menuList->name = memory->Dup(assetName.c_str()); | ||
return menuList; | ||
} | ||
|
||
bool AssetLoaderMenuList::CanLoadFromRaw() const | ||
{ | ||
return true; | ||
} | ||
|
||
bool BuildMenuFileQueue(std::deque<std::string>& menuLoadQueue, const std::string& menuListAssetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, menu::MenuAssetZoneState* zoneState, | ||
MenuConversionZoneState* conversionState, std::vector<menuDef_t*>& menus, std::vector<XAssetInfoGeneric*>& menuListDependencies) | ||
{ | ||
const auto alreadyLoadedMenuListFileMenus = conversionState->m_menus_by_filename.find(menuListAssetName); | ||
|
||
if (alreadyLoadedMenuListFileMenus == conversionState->m_menus_by_filename.end()) | ||
{ | ||
const auto menuListResult = MenuLoader::ParseMenuFile(menuListAssetName, searchPath, zoneState); | ||
if (menuListResult) | ||
{ | ||
MenuLoader::ProcessParsedResults(menuListAssetName, searchPath, memory, manager, menuListResult.get(), zoneState, conversionState, menus, menuListDependencies); | ||
|
||
for (const auto& menuToLoad : menuListResult->m_menus_to_load) | ||
menuLoadQueue.push_back(menuToLoad); | ||
|
||
zoneState->AddMenusToLoad(menuListAssetName, std::move(menuListResult->m_menus_to_load)); | ||
} | ||
else | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
void LoadMenuFileFromQueue(const std::string& menuFilePath, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, menu::MenuAssetZoneState* zoneState, | ||
MenuConversionZoneState* conversionState, std::vector<menuDef_t*>& menus, std::vector<XAssetInfoGeneric*>& menuListDependencies) | ||
{ | ||
const auto alreadyLoadedMenuFile = conversionState->m_menus_by_filename.find(menuFilePath); | ||
if (alreadyLoadedMenuFile != conversionState->m_menus_by_filename.end()) | ||
{ | ||
std::cout << "Already loaded \"" << menuFilePath << "\", skipping\n"; | ||
for (auto* menu : alreadyLoadedMenuFile->second) | ||
{ | ||
menus.push_back(menu->Asset()); | ||
menuListDependencies.push_back(menu); | ||
} | ||
return; | ||
} | ||
|
||
const auto menuFileResult = MenuLoader::ParseMenuFile(menuFilePath, searchPath, zoneState); | ||
if (menuFileResult) | ||
{ | ||
MenuLoader::ProcessParsedResults(menuFilePath, searchPath, memory, manager, menuFileResult.get(), zoneState, conversionState, menus, menuListDependencies); | ||
if (!menuFileResult->m_menus_to_load.empty()) | ||
std::cout << "WARNING: Menu file has menus to load even though it is not a menu list, ignoring: \"" << menuFilePath << "\"\n"; | ||
} | ||
else | ||
std::cerr << "Could not read menu file \"" << menuFilePath << "\"\n"; | ||
} | ||
|
||
bool AssetLoaderMenuList::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const | ||
{ | ||
std::vector<menuDef_t*> menus; | ||
std::vector<XAssetInfoGeneric*> menuListDependencies; | ||
|
||
auto* zoneState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<menu::MenuAssetZoneState>(); | ||
auto* conversionState = manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<MenuConversionZoneState>(); | ||
|
||
std::deque<std::string> menuLoadQueue; | ||
if (!BuildMenuFileQueue(menuLoadQueue, assetName, searchPath, memory, manager, zoneState, conversionState, menus, menuListDependencies)) | ||
return false; | ||
|
||
while(!menuLoadQueue.empty()) | ||
{ | ||
const auto& menuFileToLoad = menuLoadQueue.front(); | ||
|
||
LoadMenuFileFromQueue(menuFileToLoad, searchPath, memory, manager, zoneState, conversionState, menus, menuListDependencies); | ||
|
||
menuLoadQueue.pop_front(); | ||
} | ||
|
||
auto* menuListAsset = MenuLoader::CreateMenuListAsset(assetName, memory, menus); | ||
|
||
if (menuListAsset) | ||
manager->AddAsset(ASSET_TYPE_MENULIST, assetName, menuListAsset, menuListDependencies, std::vector<scr_string_t>()); | ||
|
||
return true; | ||
} | ||
|
||
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext* context) const | ||
{ | ||
context->GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData(); | ||
} |
18 changes: 18 additions & 0 deletions
18
src/ObjLoading/Game/IW5/AssetLoaders/AssetLoaderMenuList.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
|
||
#include "Game/IW5/IW5.h" | ||
#include "AssetLoading/BasicAssetLoader.h" | ||
#include "AssetLoading/IAssetLoadingManager.h" | ||
#include "SearchPath/ISearchPath.h" | ||
|
||
namespace IW5 | ||
{ | ||
class AssetLoaderMenuList final : public BasicAssetLoader<ASSET_TYPE_MENULIST, MenuList> | ||
{ | ||
public: | ||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; | ||
_NODISCARD bool CanLoadFromRaw() const override; | ||
bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override; | ||
void FinalizeAssetsForZone(AssetLoadingContext* context) const override; | ||
}; | ||
} |
Oops, something went wrong.