2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-06-07 00:47:42 +00:00
OpenAssetTools/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperMenuList.cpp

180 lines
5.3 KiB
C++

#include "AssetDumperMenuList.h"
#include <cassert>
#include <filesystem>
#include <sstream>
#include <set>
#include "ObjWriting.h"
#include "Game/IW4/Menu/MenuDumperIW4.h"
#include "Menu/AbstractMenuDumper.h"
namespace fs = std::filesystem;
using namespace IW4;
std::vector<const ExpressionSupportingData*> AssetDumperMenuList::GetAllUniqueExpressionSupportingData(const MenuList* menuList)
{
std::vector<const ExpressionSupportingData*> result;
std::set<const ExpressionSupportingData*> alreadyAddedSupportingData;
if (menuList->menus == nullptr)
return result;
for(auto i = 0; i < menuList->menuCount; i++)
{
if(menuList->menus[i] == nullptr)
continue;
const auto* menu = menuList->menus[i];
if(menu->expressionData == nullptr)
continue;
if(alreadyAddedSupportingData.find(menu->expressionData) == alreadyAddedSupportingData.end())
{
result.push_back(menu->expressionData);
alreadyAddedSupportingData.emplace(menu->expressionData);
}
}
return result;
}
void AssetDumperMenuList::DumpFunctions(MenuDumper& menuDumper, const MenuList* menuList)
{
const auto allSupportingData = GetAllUniqueExpressionSupportingData(menuList);
auto functionIndex = 0u;
assert(allSupportingData.size() <= 1);
for (const auto* supportingData : allSupportingData)
{
if (supportingData->uifunctions.functions == nullptr)
continue;
for(auto i = 0; i < supportingData->uifunctions.totalFunctions; i++)
{
const auto* function = supportingData->uifunctions.functions[i];
if(function != nullptr)
{
std::stringstream ss;
ss << "FUNC_" << functionIndex;
menuDumper.WriteFunctionDef(ss.str(), function);
}
functionIndex++;
}
}
}
void AssetDumperMenuList::DumpMenus(MenuDumper& menuDumper, menu::MenuDumpingZoneState* zoneState, const MenuList* menuList)
{
for (auto menuNum = 0; menuNum < menuList->menuCount; menuNum++)
{
const auto* menu = menuList->menus[menuNum];
const auto menuDumpingState = zoneState->m_menu_dumping_state_map.find(menu);
if(menuDumpingState == zoneState->m_menu_dumping_state_map.end())
continue;
// If the menu was embedded directly as menu list write its data in the menu list file
if (menuDumpingState->second.m_alias_menu_list == menuList)
menuDumper.WriteMenu(menu);
else
menuDumper.IncludeMenu(menuDumpingState->second.m_path);
}
}
bool AssetDumperMenuList::ShouldDump(XAssetInfo<MenuList>* asset)
{
return true;
}
void AssetDumperMenuList::DumpAsset(AssetDumpingContext& context, XAssetInfo<MenuList>* asset)
{
const auto* menuList = asset->Asset();
const auto assetFile = context.OpenAssetFile(asset->m_name);
if (!assetFile)
return;
auto* zoneState = context.GetZoneAssetDumperState<menu::MenuDumpingZoneState>();
MenuDumper menuDumper(*assetFile);
menuDumper.Start();
if(!ObjWriting::Configuration.MenuLegacyMode)
DumpFunctions(menuDumper, menuList);
DumpMenus(menuDumper, zoneState, menuList);
menuDumper.End();
}
std::string AssetDumperMenuList::PathForMenu(const std::string& menuListParentPath, const menuDef_t* menu)
{
const auto* menuAssetName = menu->window.name;
if (!menuAssetName)
return "";
if (menuAssetName[0] == ',')
menuAssetName = &menuAssetName[1];
std::ostringstream ss;
ss << menuListParentPath << menuAssetName << ".menu";
return ss.str();
}
void AssetDumperMenuList::CreateDumpingStateForMenuList(menu::MenuDumpingZoneState* zoneState, const MenuList* menuList)
{
if (menuList->menuCount <= 0 || menuList->menus == nullptr || menuList->name == nullptr)
return;
const std::string menuListName(menuList->name);
const fs::path p(menuListName);
std::string parentPath;
if (p.has_parent_path())
parentPath = p.parent_path().string() + "/";
for(auto i = 0; i < menuList->menuCount; i++)
{
auto* menu = menuList->menus[i];
if(menu == nullptr)
continue;
auto existingState = zoneState->m_menu_dumping_state_map.find(menu);
if(existingState == zoneState->m_menu_dumping_state_map.end())
{
auto menuPath = PathForMenu(parentPath, menu);
const auto isTheSameAsMenuList = menuPath == menuListName;
zoneState->CreateMenuDumpingState(menu, std::move(menuPath), isTheSameAsMenuList ? menuList : nullptr);
}
else if(existingState->second.m_alias_menu_list == nullptr)
{
auto menuPath = PathForMenu(parentPath, menu);
const auto isTheSameAsMenuList = menuPath == menuListName;
if (isTheSameAsMenuList)
{
existingState->second.m_alias_menu_list = menuList;
existingState->second.m_path = std::move(menuPath);
}
}
}
}
void AssetDumperMenuList::DumpPool(AssetDumpingContext& context, AssetPool<MenuList>* pool)
{
auto* zoneState = context.GetZoneAssetDumperState<menu::MenuDumpingZoneState>();
for(auto* asset : *pool)
CreateDumpingStateForMenuList(zoneState, asset->Asset());
AbstractAssetDumper<MenuList>::DumpPool(context, pool);
}