mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Make sure to only dump menu files once
This commit is contained in:
parent
28011d6b64
commit
5d1df29542
@ -3,13 +3,17 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <typeindex>
|
||||||
|
|
||||||
|
#include "IZoneAssetDumperState.h"
|
||||||
#include "Utils/ClassUtils.h"
|
#include "Utils/ClassUtils.h"
|
||||||
#include "Obj/Gdt/GdtStream.h"
|
#include "Obj/Gdt/GdtStream.h"
|
||||||
#include "Zone/Zone.h"
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
class AssetDumpingContext
|
class AssetDumpingContext
|
||||||
{
|
{
|
||||||
|
std::unordered_map<std::type_index, std::unique_ptr<IZoneAssetDumperState>> m_zone_asset_dumper_states;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Zone* m_zone;
|
Zone* m_zone;
|
||||||
std::string m_base_path;
|
std::string m_base_path;
|
||||||
@ -18,4 +22,21 @@ public:
|
|||||||
AssetDumpingContext();
|
AssetDumpingContext();
|
||||||
|
|
||||||
_NODISCARD std::unique_ptr<std::ostream> OpenAssetFile(const std::string& fileName) const;
|
_NODISCARD std::unique_ptr<std::ostream> OpenAssetFile(const std::string& fileName) const;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* GetZoneAssetDumperState()
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of_v<IZoneAssetDumperState, T>, "T must inherit IZoneAssetDumperState");
|
||||||
|
// T must also have a public default constructor
|
||||||
|
|
||||||
|
const auto foundEntry = m_zone_asset_dumper_states.find(typeid(T));
|
||||||
|
if (foundEntry != m_zone_asset_dumper_states.end())
|
||||||
|
return dynamic_cast<T*>(foundEntry->second.get());
|
||||||
|
|
||||||
|
auto newState = std::make_unique<T>();
|
||||||
|
newState->SetZone(m_zone);
|
||||||
|
auto* newStatePtr = newState.get();
|
||||||
|
m_zone_asset_dumper_states.emplace(std::make_pair<std::type_index, std::unique_ptr<IZoneAssetDumperState>>(typeid(T), std::move(newState)));
|
||||||
|
return newStatePtr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
20
src/ObjWriting/Dumping/IZoneAssetDumperState.h
Normal file
20
src/ObjWriting/Dumping/IZoneAssetDumperState.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
|
class IZoneAssetDumperState
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
IZoneAssetDumperState() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~IZoneAssetDumperState() = default;
|
||||||
|
IZoneAssetDumperState(const IZoneAssetDumperState& other) = default;
|
||||||
|
IZoneAssetDumperState(IZoneAssetDumperState&& other) noexcept = default;
|
||||||
|
IZoneAssetDumperState& operator=(const IZoneAssetDumperState& other) = default;
|
||||||
|
IZoneAssetDumperState& operator=(IZoneAssetDumperState&& other) noexcept = default;
|
||||||
|
|
||||||
|
virtual void SetZone(Zone* zone)
|
||||||
|
{
|
||||||
|
// Do nothing by default
|
||||||
|
}
|
||||||
|
};
|
@ -3,46 +3,22 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "AssetDumperMenuList.h"
|
||||||
#include "ObjWriting.h"
|
#include "ObjWriting.h"
|
||||||
#include "Game/IW4/GameAssetPoolIW4.h"
|
#include "Game/IW4/GameAssetPoolIW4.h"
|
||||||
#include "Game/IW4/Menu/MenuDumperIW4.h"
|
#include "Game/IW4/Menu/MenuDumperIW4.h"
|
||||||
#include "Menu/AbstractMenuDumper.h"
|
#include "Menu/AbstractMenuDumper.h"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
const MenuList* AssetDumperMenuDef::GetParentMenuList(XAssetInfo<menuDef_t>* asset)
|
std::string AssetDumperMenuDef::GetPathForMenu(menu::MenuDumpingZoneState* zoneState, XAssetInfo<menuDef_t>* asset)
|
||||||
{
|
{
|
||||||
const auto* menu = asset->Asset();
|
const auto menuDumpingState = zoneState->m_menu_dumping_state_map.find(asset->Asset());
|
||||||
const auto* gameAssetPool = dynamic_cast<GameAssetPoolIW4*>(asset->m_zone->m_pools.get());
|
|
||||||
for (const auto* menuList : *gameAssetPool->m_menu_list)
|
|
||||||
{
|
|
||||||
const auto* menuListAsset = menuList->Asset();
|
|
||||||
|
|
||||||
for (auto menuIndex = 0; menuIndex < menuListAsset->menuCount; menuIndex++)
|
if (menuDumpingState == zoneState->m_menu_dumping_state_map.end())
|
||||||
{
|
|
||||||
if (menuListAsset->menus[menuIndex] == menu)
|
|
||||||
return menuListAsset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AssetDumperMenuDef::GetPathForMenu(XAssetInfo<menuDef_t>* asset)
|
|
||||||
{
|
|
||||||
const auto* list = GetParentMenuList(asset);
|
|
||||||
|
|
||||||
if (!list)
|
|
||||||
return "ui_mp/" + std::string(asset->Asset()->window.name) + ".menu";
|
return "ui_mp/" + std::string(asset->Asset()->window.name) + ".menu";
|
||||||
|
|
||||||
const fs::path p(list->name);
|
return menuDumpingState->second.m_path;
|
||||||
std::string parentPath;
|
|
||||||
if (p.has_parent_path())
|
|
||||||
parentPath = p.parent_path().string() + "/";
|
|
||||||
|
|
||||||
return parentPath + std::string(asset->Asset()->window.name) + ".menu";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetDumperMenuDef::ShouldDump(XAssetInfo<menuDef_t>* asset)
|
bool AssetDumperMenuDef::ShouldDump(XAssetInfo<menuDef_t>* asset)
|
||||||
@ -53,16 +29,17 @@ bool AssetDumperMenuDef::ShouldDump(XAssetInfo<menuDef_t>* asset)
|
|||||||
void AssetDumperMenuDef::DumpAsset(AssetDumpingContext& context, XAssetInfo<menuDef_t>* asset)
|
void AssetDumperMenuDef::DumpAsset(AssetDumpingContext& context, XAssetInfo<menuDef_t>* asset)
|
||||||
{
|
{
|
||||||
const auto* menu = asset->Asset();
|
const auto* menu = asset->Asset();
|
||||||
const auto menuFilePath = GetPathForMenu(asset);
|
auto* zoneState = context.GetZoneAssetDumperState<menu::MenuDumpingZoneState>();
|
||||||
|
|
||||||
if(ObjWriting::ShouldHandleAssetType(ASSET_TYPE_MENULIST))
|
if(!ObjWriting::ShouldHandleAssetType(ASSET_TYPE_MENULIST))
|
||||||
{
|
{
|
||||||
// Don't dump menu file separately if the name matches the menu list
|
// Make sure menu paths based on menu lists are created
|
||||||
const auto* menuListParent = GetParentMenuList(asset);
|
const auto* gameAssetPool = dynamic_cast<GameAssetPoolIW4*>(asset->m_zone->m_pools.get());
|
||||||
if (menuListParent && menuFilePath == menuListParent->name)
|
for (auto* menuListAsset : *gameAssetPool->m_menu_list)
|
||||||
return;
|
AssetDumperMenuList::CreateDumpingStateForMenuList(zoneState, menuListAsset->Asset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto menuFilePath = GetPathForMenu(zoneState, asset);
|
||||||
const auto assetFile = context.OpenAssetFile(menuFilePath);
|
const auto assetFile = context.OpenAssetFile(menuFilePath);
|
||||||
|
|
||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
#include "Dumping/AbstractAssetDumper.h"
|
#include "Dumping/AbstractAssetDumper.h"
|
||||||
#include "Game/IW4/IW4.h"
|
#include "Game/IW4/IW4.h"
|
||||||
|
#include "Menu/MenuDumpingZoneState.h"
|
||||||
|
|
||||||
namespace IW4
|
namespace IW4
|
||||||
{
|
{
|
||||||
class AssetDumperMenuDef final : public AbstractAssetDumper<menuDef_t>
|
class AssetDumperMenuDef final : public AbstractAssetDumper<menuDef_t>
|
||||||
{
|
{
|
||||||
static const MenuList* GetParentMenuList(XAssetInfo<menuDef_t>* asset);
|
static std::string GetPathForMenu(menu::MenuDumpingZoneState* zoneState, XAssetInfo<menuDef_t>* asset);
|
||||||
static std::string GetPathForMenu(XAssetInfo<menuDef_t>* asset);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ShouldDump(XAssetInfo<menuDef_t>* asset) override;
|
bool ShouldDump(XAssetInfo<menuDef_t>* asset) override;
|
||||||
|
@ -69,31 +69,21 @@ void AssetDumperMenuList::DumpFunctions(MenuDumper& menuDumper, const MenuList*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetDumperMenuList::DumpMenus(MenuDumper& menuDumper, const MenuList* menuList)
|
void AssetDumperMenuList::DumpMenus(MenuDumper& menuDumper, menu::MenuDumpingZoneState* zoneState, const MenuList* menuList)
|
||||||
{
|
{
|
||||||
const fs::path p(menuList->name);
|
|
||||||
|
|
||||||
std::string parentPath;
|
|
||||||
if (p.has_parent_path())
|
|
||||||
parentPath = p.parent_path().string() + "/";
|
|
||||||
|
|
||||||
for (auto menuNum = 0; menuNum < menuList->menuCount; menuNum++)
|
for (auto menuNum = 0; menuNum < menuList->menuCount; menuNum++)
|
||||||
{
|
{
|
||||||
const auto* menu = menuList->menus[menuNum];
|
const auto* menu = menuList->menus[menuNum];
|
||||||
const auto* menuAssetName = menu->window.name;
|
|
||||||
if (menuAssetName && menuAssetName[0] == ',')
|
|
||||||
menuAssetName = &menuAssetName[1];
|
|
||||||
|
|
||||||
std::ostringstream ss;
|
const auto menuDumpingState = zoneState->m_menu_dumping_state_map.find(menu);
|
||||||
ss << parentPath << menuAssetName << ".menu";
|
if(menuDumpingState == zoneState->m_menu_dumping_state_map.end())
|
||||||
|
continue;
|
||||||
const auto menuName = ss.str();
|
|
||||||
|
|
||||||
// If the menu was embedded directly as menu list write its data in the menu list file
|
// If the menu was embedded directly as menu list write its data in the menu list file
|
||||||
if (menuName == menuList->name)
|
if (menuDumpingState->second.m_alias_menu_list == menuList)
|
||||||
menuDumper.WriteMenu(menu);
|
menuDumper.WriteMenu(menu);
|
||||||
else
|
else
|
||||||
menuDumper.IncludeMenu(ss.str());
|
menuDumper.IncludeMenu(menuDumpingState->second.m_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +100,8 @@ void AssetDumperMenuList::DumpAsset(AssetDumpingContext& context, XAssetInfo<Men
|
|||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto* zoneState = context.GetZoneAssetDumperState<menu::MenuDumpingZoneState>();
|
||||||
|
|
||||||
MenuDumper menuDumper(*assetFile);
|
MenuDumper menuDumper(*assetFile);
|
||||||
|
|
||||||
menuDumper.Start();
|
menuDumper.Start();
|
||||||
@ -117,7 +109,71 @@ void AssetDumperMenuList::DumpAsset(AssetDumpingContext& context, XAssetInfo<Men
|
|||||||
if(!ObjWriting::Configuration.MenuLegacyMode)
|
if(!ObjWriting::Configuration.MenuLegacyMode)
|
||||||
DumpFunctions(menuDumper, menuList);
|
DumpFunctions(menuDumper, menuList);
|
||||||
|
|
||||||
DumpMenus(menuDumper, menuList);
|
DumpMenus(menuDumper, zoneState, menuList);
|
||||||
|
|
||||||
menuDumper.End();
|
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);
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "Dumping/AbstractAssetDumper.h"
|
#include "Dumping/AbstractAssetDumper.h"
|
||||||
#include "Game/IW4/IW4.h"
|
#include "Game/IW4/IW4.h"
|
||||||
#include "Game/IW4/Menu/MenuDumperIW4.h"
|
#include "Game/IW4/Menu/MenuDumperIW4.h"
|
||||||
|
#include "Menu/MenuDumpingZoneState.h"
|
||||||
|
|
||||||
namespace IW4
|
namespace IW4
|
||||||
{
|
{
|
||||||
@ -11,10 +12,16 @@ namespace IW4
|
|||||||
static std::vector<const ExpressionSupportingData*> GetAllUniqueExpressionSupportingData(const MenuList* menuList);
|
static std::vector<const ExpressionSupportingData*> GetAllUniqueExpressionSupportingData(const MenuList* menuList);
|
||||||
|
|
||||||
static void DumpFunctions(MenuDumper& menuDumper, const MenuList* menuList);
|
static void DumpFunctions(MenuDumper& menuDumper, const MenuList* menuList);
|
||||||
static void DumpMenus(MenuDumper& menuDumper, const MenuList* menuList);
|
static void DumpMenus(MenuDumper& menuDumper, menu::MenuDumpingZoneState* zoneState, const MenuList* menuList);
|
||||||
|
|
||||||
|
static std::string PathForMenu(const std::string& menuListParentPath, const menuDef_t* menu);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ShouldDump(XAssetInfo<MenuList>* asset) override;
|
bool ShouldDump(XAssetInfo<MenuList>* asset) override;
|
||||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<MenuList>* asset) override;
|
void DumpAsset(AssetDumpingContext& context, XAssetInfo<MenuList>* asset) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void CreateDumpingStateForMenuList(menu::MenuDumpingZoneState* zoneState, const MenuList* menuList);
|
||||||
|
void DumpPool(AssetDumpingContext& context, AssetPool<MenuList>* pool) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
14
src/ObjWriting/Menu/MenuDumpingZoneState.cpp
Normal file
14
src/ObjWriting/Menu/MenuDumpingZoneState.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include "MenuDumpingZoneState.h"
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
MenuDumpingZoneState::MenuDumpingState::MenuDumpingState(std::string path, const void* aliasMenuList)
|
||||||
|
: m_path(std::move(path)),
|
||||||
|
m_alias_menu_list(aliasMenuList)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuDumpingZoneState::CreateMenuDumpingState(const void* menuDef, std::string path, const void* aliasMenuList)
|
||||||
|
{
|
||||||
|
m_menu_dumping_state_map.emplace(std::make_pair(menuDef, MenuDumpingState(std::move(path), aliasMenuList)));
|
||||||
|
}
|
24
src/ObjWriting/Menu/MenuDumpingZoneState.h
Normal file
24
src/ObjWriting/Menu/MenuDumpingZoneState.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "Dumping/IZoneAssetDumperState.h"
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
class MenuDumpingZoneState final : public IZoneAssetDumperState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class MenuDumpingState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string m_path;
|
||||||
|
const void* m_alias_menu_list;
|
||||||
|
|
||||||
|
MenuDumpingState(std::string path, const void* aliasMenuList);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<const void*, MenuDumpingState> m_menu_dumping_state_map;
|
||||||
|
|
||||||
|
void CreateMenuDumpingState(const void* menuDef, std::string path, const void* aliasMenuList);
|
||||||
|
};
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user