IW4 dump simple menu file fields

This commit is contained in:
Jan 2021-08-27 23:08:05 +02:00
parent 636034d87c
commit 163ac55fed
9 changed files with 561 additions and 2 deletions

View File

@ -1314,6 +1314,21 @@ namespace IW4
char vertAlign; char vertAlign;
}; };
enum WindowDefStaticFlag : unsigned int
{
WINDOW_FLAG_DECORATION = 0x100000,
WINDOW_FLAG_HORIZONTAL_SCROLL = 0x200000,
WINDOW_FLAG_OUT_OF_BOUNDS_CLICK = 0x2000000,
WINDOW_FLAG_SCREEN_SPACE = 0x400000,
WINDOW_FLAG_AUTO_WRAPPED = 0x800000,
WINDOW_FLAG_POPUP = 0x1000000,
WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE = 0x4000000,
WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG = 0x10000000,
WINDOW_FLAG_HIDDEN_DURING_SCOPE = 0x20000000,
WINDOW_FLAG_HIDDEN_DURING_UI = 0x40000000,
WINDOW_FLAG_TEXT_ONLY_FOCUS = 0x80000000,
};
struct windowDef_t struct windowDef_t
{ {
const char* name; const char* name;
@ -1336,6 +1351,21 @@ namespace IW4
Material* background; Material* background;
}; };
enum ItemDefFlag : unsigned int
{
ITEM_FLAG_SAVE_GAME_INFO = 0x1,
ITEM_FLAG_CINEMATIC_SUBTITLE = 0x2,
};
enum ItemDefDvarFlag
{
ITEM_DVAR_FLAG_ENABLE = 0x1,
ITEM_DVAR_FLAG_DISABLE = 0x2,
ITEM_DVAR_FLAG_SHOW = 0x4,
ITEM_DVAR_FLAG_HIDE = 0x8,
ITEM_DVAR_FLAG_FOCUS = 0x10,
};
enum ItemDefType enum ItemDefType
{ {
ITEM_TYPE_TEXT = 0x0, ITEM_TYPE_TEXT = 0x0,

View File

View File

@ -0,0 +1,375 @@
#include "AssetDumperMenuDef.h"
#include <filesystem>
#include <ostream>
#include <cmath>
#include "Game/IW4/GameAssetPoolIW4.h"
#include "Menu/MenuDumper.h"
namespace fs = std::filesystem;
using namespace IW4;
class MenuDumperIw4 : public MenuDumper
{
static constexpr auto MENU_KEY_SPACING = 28u;
static const inline std::string BOOL_VALUE_TRUE = "1";
static const inline std::string BOOL_VALUE_FALSE = "0";
static constexpr inline float COLOR_0000[4]{0.0f, 0.0f, 0.0f, 0.0f};
static constexpr inline float COLOR_1111[4]{1.0f, 1.0f, 1.0f, 1.0f};
static const std::string& BoolValue(const bool value)
{
return value ? BOOL_VALUE_TRUE : BOOL_VALUE_FALSE;
}
void WriteKey(const std::string& keyName) const
{
m_stream << keyName;
if (keyName.size() < MENU_KEY_SPACING)
{
const auto spacingLength = MENU_KEY_SPACING - keyName.size();
for (auto i = 0u; i < spacingLength; i++)
m_stream << " ";
}
}
void WriteStringProperty(const std::string& propertyKey, const std::string& propertyValue) const
{
if (propertyValue.empty())
return;
Indent();
WriteKey(propertyKey);
m_stream << "\"" << propertyValue << "\"\n";
}
void WriteStringProperty(const std::string& propertyKey, const char* propertyValue) const
{
if (propertyValue == nullptr || propertyValue[0] == '\0')
return;
Indent();
WriteKey(propertyKey);
m_stream << "\"" << propertyValue << "\"\n";
}
void WriteBoolProperty(const std::string& propertyKey, const bool propertyValue, const bool defaultValue) const
{
if (propertyValue == defaultValue)
return;
Indent();
WriteKey(propertyKey);
m_stream << BoolValue(propertyValue) << "\n";
}
void WriteIntProperty(const std::string& propertyKey, const int propertyValue, const int defaultValue) const
{
if (propertyValue == defaultValue)
return;
Indent();
WriteKey(propertyKey);
m_stream << propertyValue << "\n";
}
void WriteFloatProperty(const std::string& propertyKey, const float propertyValue, const float defaultValue) const
{
if (std::fabs(propertyValue - defaultValue) < std::numeric_limits<float>::epsilon())
return;
Indent();
WriteKey(propertyKey);
m_stream << propertyValue << "\n";
}
void WriteColorProperty(const std::string& propertyKey, const float (&propertyValue)[4], const float (&defaultValue)[4]) const
{
if (std::fabs(propertyValue[0] - defaultValue[0]) < std::numeric_limits<float>::epsilon()
&& std::fabs(propertyValue[1] - defaultValue[1]) < std::numeric_limits<float>::epsilon()
&& std::fabs(propertyValue[2] - defaultValue[2]) < std::numeric_limits<float>::epsilon()
&& std::fabs(propertyValue[3] - defaultValue[3]) < std::numeric_limits<float>::epsilon())
{
return;
}
Indent();
WriteKey(propertyKey);
m_stream << propertyValue[0] << " " << propertyValue[1] << " " << propertyValue[2] << " " << propertyValue[3] << "\n";
}
void WriteKeywordProperty(const std::string& propertyKey, const bool shouldWrite) const
{
if (!shouldWrite)
return;
Indent();
WriteKey(propertyKey);
m_stream << "\n";
}
void WriteFlagsProperty(const std::string& propertyKey, const int flagsValue) const
{
for (auto i = 0u; i < sizeof(flagsValue) * 8; i++)
{
if (flagsValue & (1 << i))
{
Indent();
WriteKey(propertyKey);
m_stream << i << "\n";
}
}
}
void WriteRectProperty(const std::string& propertyKey, const rectDef_s& rect) const
{
Indent();
WriteKey(propertyKey);
m_stream << rect.x << " " << rect.y << " " << rect.w << " " << rect.h << " " << static_cast<int>(rect.horzAlign) << " " << static_cast<int>(rect.vertAlign) << "\n";
}
void WriteMaterialProperty(const std::string& propertyKey, const Material* materialValue) const
{
if (materialValue == nullptr)
return;
WriteStringProperty(propertyKey, materialValue->info.name);
}
void WriteSoundAliasProperty(const std::string& propertyKey, const snd_alias_list_t* soundAliasValue) const
{
if (soundAliasValue == nullptr)
return;
WriteStringProperty(propertyKey, soundAliasValue->aliasName);
}
void WriteStatementProperty(const std::string& propertyKey, const Statement_s* statementValue, const bool isBooleanStatement) const
{
if (statementValue == nullptr)
return;
Indent();
WriteKey(propertyKey);
m_stream << "\n";
}
void WriteMenuEventHandlerSetProperty(const std::string& propertyKey, const MenuEventHandlerSet* eventHandlerValue) const
{
if (eventHandlerValue == nullptr)
return;
Indent();
WriteKey(propertyKey);
m_stream << "\n";
}
void WriteItemKeyHandlerProperty(const ItemKeyHandler* itemKeyHandlerValue) const
{
}
void WriteItemData(const itemDef_s* item)
{
WriteStringProperty("name", item->window.name);
WriteStringProperty("text", item->text);
WriteKeywordProperty("textsavegame", item->itemFlags & ITEM_FLAG_SAVE_GAME_INFO);
WriteKeywordProperty("textcinematicsubtitle", item->itemFlags & ITEM_FLAG_CINEMATIC_SUBTITLE);
WriteStringProperty("group", item->window.group);
WriteRectProperty("rect", item->window.rect);
WriteIntProperty("style", item->window.style, 0);
WriteKeywordProperty("decoration", item->window.staticFlags & WINDOW_FLAG_DECORATION);
WriteIntProperty("type", item->type, ITEM_TYPE_TEXT);
WriteIntProperty("border", item->window.border, 0);
WriteFloatProperty("borderSize", item->window.borderSize, 0.0f);
WriteStatementProperty("visible", item->visibleExp, true);
WriteStatementProperty("disabled", item->disabledExp, true);
WriteIntProperty("ownerDraw", item->window.ownerDraw, 0);
WriteIntProperty("align", item->alignment, 0);
WriteIntProperty("textalign", item->textAlignMode, 0);
WriteFloatProperty("textalignx", item->textalignx, 0.0f);
WriteFloatProperty("textaligny", item->textaligny, 0.0f);
WriteFloatProperty("textscale", item->textscale, 0.0f);
WriteIntProperty("textstyle", item->textStyle, 0);
WriteIntProperty("textfont", item->fontEnum, 0);
WriteColorProperty("backcolor", item->window.backColor, COLOR_0000);
WriteColorProperty("forecolor", item->window.foreColor, COLOR_1111);
WriteColorProperty("bordercolor", item->window.borderColor, COLOR_0000);
WriteColorProperty("outlinecolor", item->window.outlineColor, COLOR_0000);
WriteColorProperty("disablecolor", item->window.disableColor, COLOR_0000);
WriteColorProperty("disablecolor", item->glowColor, COLOR_0000);
WriteMaterialProperty("background", item->window.background);
WriteMenuEventHandlerSetProperty("onFocus", item->onFocus);
WriteMenuEventHandlerSetProperty("leaveFocus", item->leaveFocus);
WriteMenuEventHandlerSetProperty("mouseEnter", item->mouseEnter);
WriteMenuEventHandlerSetProperty("mouseExit", item->mouseExit);
WriteMenuEventHandlerSetProperty("mouseEnterText", item->mouseEnterText);
WriteMenuEventHandlerSetProperty("mouseExitText", item->mouseExitText);
WriteMenuEventHandlerSetProperty("action", item->action);
WriteMenuEventHandlerSetProperty("accept", item->accept);
WriteFloatProperty("special", item->special, 0.0f);
WriteSoundAliasProperty("focusSound", item->focusSound);
WriteFlagsProperty("ownerdrawFlag", item->window.ownerDrawFlags);
WriteStringProperty("dvarTest", item->dvarTest);
if(item->dvarFlags & ITEM_DVAR_FLAG_ENABLE)
WriteStringProperty("enableDvar", item->enableDvar);
else if(item->dvarFlags & ITEM_DVAR_FLAG_DISABLE)
WriteStringProperty("disableDvar", item->enableDvar);
else if(item->dvarFlags & ITEM_DVAR_FLAG_SHOW)
WriteStringProperty("showDvar", item->enableDvar);
else if(item->dvarFlags & ITEM_DVAR_FLAG_HIDE)
WriteStringProperty("hideDvar", item->enableDvar);
else if(item->dvarFlags & ITEM_DVAR_FLAG_FOCUS)
WriteStringProperty("focusDvar", item->enableDvar);
WriteItemKeyHandlerProperty(item->onKey);
WriteStatementProperty("exp text", item->textExp, false);
WriteStatementProperty("exp material", item->materialExp, false);
WriteStatementProperty("exp disabled", item->disabledExp, false);
// floatexpressions
WriteIntProperty("gamemsgwindowindex", item->gameMsgWindowIndex, 0);
WriteIntProperty("gamemsgwindowmode", item->gameMsgWindowMode, 0);
// decodeEffect
}
void WriteItemDefs(const itemDef_s* const* itemDefs, const size_t itemCount)
{
for(auto i = 0u; i < itemCount; i++)
{
Indent();
m_stream << "itemDef\n";
Indent();
m_stream << "{\n";
IncIndent();
WriteItemData(itemDefs[i]);
DecIndent();
Indent();
m_stream << "}\n";
}
}
void WriteMenuData(const menuDef_t* menu)
{
WriteStringProperty("name", menu->window.name);
WriteBoolProperty("fullscreen", menu->fullScreen, false);
WriteKeywordProperty("screenSpace", menu->window.staticFlags & WINDOW_FLAG_SCREEN_SPACE);
WriteKeywordProperty("decoration", menu->window.staticFlags & WINDOW_FLAG_DECORATION);
WriteRectProperty("rect", menu->window.rect);
WriteIntProperty("style", menu->window.style, 0);
WriteIntProperty("border", menu->window.border, 0);
WriteFloatProperty("borderSize", menu->window.borderSize, 0.0f);
WriteColorProperty("backcolor", menu->window.backColor, COLOR_0000);
WriteColorProperty("forecolor", menu->window.foreColor, COLOR_1111);
WriteColorProperty("bordercolor", menu->window.borderColor, COLOR_0000);
WriteColorProperty("focuscolor", menu->focusColor, COLOR_0000);
WriteMaterialProperty("background", menu->window.background);
WriteIntProperty("ownerdraw", menu->window.ownerDraw, 0);
WriteFlagsProperty("ownerdrawFlag", menu->window.ownerDrawFlags);
WriteKeywordProperty("outOfBoundsClick", menu->window.staticFlags & WINDOW_FLAG_OUT_OF_BOUNDS_CLICK);
WriteStringProperty("soundLoop", menu->soundName);
WriteKeywordProperty("popup", menu->window.staticFlags & WINDOW_FLAG_POPUP);
WriteFloatProperty("fadeClamp", menu->fadeClamp, 0.0f);
WriteIntProperty("fadeCycle", menu->fadeCycle, 0);
WriteFloatProperty("fadeAmount", menu->fadeAmount, 0.0f);
WriteFloatProperty("fadeInAmount", menu->fadeInAmount, 0.0f);
WriteFloatProperty("blurWorld", menu->blurRadius, 0.0f);
WriteKeywordProperty("legacySplitScreenScale", menu->window.staticFlags & WINDOW_FLAG_LEGACY_SPLIT_SCREEN_SCALE);
WriteKeywordProperty("hiddenDuringScope", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_SCOPE);
WriteKeywordProperty("hiddenDuringFlashbang", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_FLASH_BANG);
WriteKeywordProperty("hiddenDuringUI", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_UI);
WriteStringProperty("allowedBinding", menu->allowedBinding);
WriteKeywordProperty("textOnlyFocus", menu->window.staticFlags & WINDOW_FLAG_TEXT_ONLY_FOCUS);
WriteStatementProperty("visible", menu->visibleExp, true);
WriteStatementProperty("exp rect X", menu->rectXExp, false);
WriteStatementProperty("exp rect Y", menu->rectYExp, false);
WriteStatementProperty("exp rect W", menu->rectWExp, false);
WriteStatementProperty("exp rect H", menu->rectHExp, false);
WriteStatementProperty("exp openSound", menu->openSoundExp, false);
WriteStatementProperty("exp closeSound", menu->closeSoundExp, false);
WriteMenuEventHandlerSetProperty("onOpen", menu->onOpen);
WriteMenuEventHandlerSetProperty("onClose", menu->onClose);
WriteMenuEventHandlerSetProperty("onRequestClose", menu->onCloseRequest);
WriteMenuEventHandlerSetProperty("onESC", menu->onESC);
WriteItemKeyHandlerProperty(menu->onKey);
WriteItemDefs(menu->items, menu->itemCount);
}
public:
explicit MenuDumperIw4(std::ostream& stream)
: MenuDumper(stream)
{
}
void WriteMenu(const menuDef_t* menu)
{
Indent();
m_stream << "menuDef\n";
Indent();
m_stream << "{\n";
IncIndent();
WriteMenuData(menu);
DecIndent();
Indent();
m_stream << "}\n";
}
};
const MenuList* AssetDumperMenuDef::GetParentMenuList(XAssetInfo<menuDef_t>* asset)
{
const auto* menu = 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 (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";
const fs::path p(list->name);
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)
{
return true;
}
void AssetDumperMenuDef::DumpAsset(AssetDumpingContext& context, XAssetInfo<menuDef_t>* asset)
{
const auto* menu = asset->Asset();
const auto assetFile = context.OpenAssetFile(GetPathForMenu(asset));
if (!assetFile)
return;
MenuDumperIw4 menuDumper(*assetFile);
menuDumper.Start();
menuDumper.WriteMenu(menu);
menuDumper.End();
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW4/IW4.h"
namespace IW4
{
class AssetDumperMenuDef final : public AbstractAssetDumper<menuDef_t>
{
static const MenuList* GetParentMenuList(XAssetInfo<menuDef_t>* asset);
static std::string GetPathForMenu(XAssetInfo<menuDef_t>* asset);
protected:
bool ShouldDump(XAssetInfo<menuDef_t>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<menuDef_t>* asset) override;
};
}

View File

@ -0,0 +1,51 @@
#include "AssetDumperMenuList.h"
#include <filesystem>
#include <sstream>
#include "Menu/MenuDumper.h"
namespace fs = std::filesystem;
using namespace IW4;
bool AssetDumperMenuList::ShouldDump(XAssetInfo<MenuList>* asset)
{
const auto* menuList = asset->Asset();
const fs::path p(asset->Asset()->name);
const auto extension = p.extension().string();
if (extension == ".menu" && menuList->menuCount == 1)
return false;
return true;
}
void AssetDumperMenuList::DumpAsset(AssetDumpingContext& context, XAssetInfo<MenuList>* asset)
{
const auto* menuList = asset->Asset();
const auto assetFile = context.OpenAssetFile(asset->m_name);
const fs::path p(asset->Asset()->name);
if (!assetFile)
return;
std::string parentPath;
if(p.has_parent_path())
parentPath = p.parent_path().string() + "/";
MenuDumper menuDumper(*assetFile);
menuDumper.Start();
for(auto menuNum = 0; menuNum < menuList->menuCount; menuNum++)
{
const auto* menu = menuList->menus[menuNum];
std::ostringstream ss;
ss << parentPath << menu->window.name << ".menu";
menuDumper.IncludeMenu(ss.str());
}
menuDumper.End();
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "Dumping/AbstractAssetDumper.h"
#include "Game/IW4/IW4.h"
namespace IW4
{
class AssetDumperMenuList final : public AbstractAssetDumper<MenuList>
{
protected:
bool ShouldDump(XAssetInfo<MenuList>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<MenuList>* asset) override;
};
}

View File

@ -7,6 +7,8 @@
#include "AssetDumpers/AssetDumperGfxImage.h" #include "AssetDumpers/AssetDumperGfxImage.h"
#include "AssetDumpers/AssetDumperLoadedSound.h" #include "AssetDumpers/AssetDumperLoadedSound.h"
#include "AssetDumpers/AssetDumperLocalizeEntry.h" #include "AssetDumpers/AssetDumperLocalizeEntry.h"
#include "AssetDumpers/AssetDumperMenuDef.h"
#include "AssetDumpers/AssetDumperMenuList.h"
#include "AssetDumpers/AssetDumperRawFile.h" #include "AssetDumpers/AssetDumperRawFile.h"
#include "AssetDumpers/AssetDumperStringTable.h" #include "AssetDumpers/AssetDumperStringTable.h"
#include "AssetDumpers/AssetDumperVehicle.h" #include "AssetDumpers/AssetDumperVehicle.h"
@ -53,8 +55,8 @@ bool ZoneDumper::DumpZone(AssetDumpingContext& context) const
// DUMP_ASSET_POOL(AssetDumperGfxWorld, m_gfx_world) // DUMP_ASSET_POOL(AssetDumperGfxWorld, m_gfx_world)
// DUMP_ASSET_POOL(AssetDumperGfxLightDef, m_gfx_light_def) // DUMP_ASSET_POOL(AssetDumperGfxLightDef, m_gfx_light_def)
// DUMP_ASSET_POOL(AssetDumperFont_s, m_font) // DUMP_ASSET_POOL(AssetDumperFont_s, m_font)
// DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list) DUMP_ASSET_POOL(AssetDumperMenuList, m_menu_list)
// DUMP_ASSET_POOL(AssetDumpermenuDef_t, m_menu_def) DUMP_ASSET_POOL(AssetDumperMenuDef, m_menu_def)
DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize) DUMP_ASSET_POOL(AssetDumperLocalizeEntry, m_localize)
DUMP_ASSET_POOL(AssetDumperWeapon, m_weapon) DUMP_ASSET_POOL(AssetDumperWeapon, m_weapon)
// DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals) // DUMP_ASSET_POOL(AssetDumperSndDriverGlobals, m_snd_driver_globals)

View File

@ -0,0 +1,47 @@
#include "MenuDumper.h"
MenuDumper::MenuDumper(std::ostream& stream)
: m_stream(stream),
m_indent(0u)
{
}
void MenuDumper::IncIndent()
{
m_indent++;
}
void MenuDumper::DecIndent()
{
if (m_indent > 0)
m_indent--;
}
void MenuDumper::Indent() const
{
for (auto i = 0u; i < m_indent; i++)
m_stream << " ";
}
void MenuDumper::Start()
{
Indent();
m_stream << "{\n";
IncIndent();
}
void MenuDumper::End()
{
for (auto i = 0u; i < m_indent; i++)
{
DecIndent();
Indent();
m_stream << "}\n";
}
}
void MenuDumper::IncludeMenu(const std::string& menuPath) const
{
Indent();
m_stream << "loadMenu { \"" << menuPath << "\" }\n";
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <string>
#include <ostream>
class MenuDumper
{
protected:
std::ostream& m_stream;
size_t m_indent;
void IncIndent();
void DecIndent();
void Indent() const;
public:
explicit MenuDumper(std::ostream& stream);
void Start();
void End();
void IncludeMenu(const std::string& menuPath) const;
};