mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-09-09 07:27:05 +00:00
* feat: IW3 menu dumping * fix: IW3 menu dumper preserve menu ownerdraw flag masks * fix: IW3 menu dumper preserve numeric script arguments Emit numeric tokens without quotes so the linker keeps colour arguments separate. Before: `"0.1" "0.1" "0.12" "0.5"` becomes `"0.10.10.120.5"` After: `0.1 0.1 0.12 0.5` This fixes `mouseExit` colour commands failing to clear menu hover borders. * fix: IW3 menu dumper preserve empty item text Keep explicit empty text distinct from null text when dumping menu items. This fixes CD-key values overflowing their input boxes. * test: cover IW3 menu dumper material case * test: cover IW3 menu list path precedence * chore: clang format * fix: reverse order of union to avoid edge case bug in zcg * feat: IW3 menu loading * fix: validate menu expression name table * chore: explain numeric token quoting in comment * refactor: simplify menu dump fallback path * chore: add more dynamic window flags * refactor: reuse IW3 menu window flag constants * refactor: use explicit menu item feature lookup * refactor: represent menu item text as optional * refactor: clarify shared IW3 and IW4 menu constants IW4 only extends the type enum so they can be shared * refactor: clarify IW3 menu zone state naming * fix: log IW3 menu conversion failures * refactor: align IW3 menu list loader with IW4 * refactor: align IW3 menu dumpers with IW4 * refactor: align IW3 menu converter with IW4 * chore: use default enum numeration for operationEnum * chore: small optimization on edit field capability initialization * fix: iw3 menu optimizations for rect not considering relative position to parent * chore: align iw3 menu converting closer to iw4 * chore: align iw3 menu dumping closer to iw4 * fix: not dumping menu flags properties correctly * chore: adjust iw3 expression dumping to work similar to iw4 * chore: adjust iw3 expression converting to work similar to iw4 * chore: use unordered_map for MenuExpressionMatchers --------- Co-authored-by: Jan Laupetin <[email protected]>
91 lines
3.8 KiB
C++
91 lines
3.8 KiB
C++
#include "Game/IW3/IW3.h"
|
|
#include "Game/IW3/Menu/MenuDumperIW3.h"
|
|
#include "Game/IW3/Menu/MenuListDumperIW3.h"
|
|
#include "Linker.h"
|
|
#include "OatTestPaths.h"
|
|
#include "SearchPath/MockOutputPath.h"
|
|
#include "SearchPath/MockSearchPath.h"
|
|
#include "SystemTestsPaths.h"
|
|
#include "ZoneLoading.h"
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
#include <filesystem>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
namespace fs = std::filesystem;
|
|
using namespace IW3;
|
|
using namespace std::literals;
|
|
|
|
namespace
|
|
{
|
|
TEST_CASE("Menu loading and dumping (IW3)", "[iw3][menu][system]")
|
|
{
|
|
const auto testDataPath = oat::paths::GetSystemTestsDirectory() / "Game/IW3/MenuRoundTrip";
|
|
const auto testDataPathString = testDataPath.string();
|
|
const auto outputPath = oat::paths::GetTempDirectory("MenuRoundTripIW3");
|
|
const auto outputPathString = outputPath.string();
|
|
|
|
const char* arguments[]{
|
|
"SystemTests",
|
|
"--verbose",
|
|
"--base-folder",
|
|
outputPathString.c_str(),
|
|
"--asset-search-path",
|
|
testDataPathString.c_str(),
|
|
"--source-search-path",
|
|
testDataPathString.c_str(),
|
|
"--output-folder",
|
|
outputPathString.c_str(),
|
|
"MenuRoundTripIW3",
|
|
};
|
|
|
|
LinkerArgs linkerArgs;
|
|
auto shouldContinue = true;
|
|
REQUIRE(linkerArgs.ParseArgs(std::size(arguments), arguments, shouldContinue));
|
|
REQUIRE(shouldContinue);
|
|
|
|
const auto linker = Linker::Create(std::move(linkerArgs));
|
|
REQUIRE(linker->Start());
|
|
|
|
const auto zonePath = outputPath / "MenuRoundTripIW3.ff";
|
|
auto maybeZone = ZoneLoading::LoadZone(zonePath.string(), std::nullopt);
|
|
REQUIRE(maybeZone);
|
|
auto zone = std::move(*maybeZone);
|
|
|
|
const auto* menuList = zone->m_pools.GetAsset<AssetMenuList>("ui_mp/menus.txt");
|
|
const auto* mainMenu = zone->m_pools.GetAsset<AssetMenu>("main");
|
|
const auto* popupMenu = zone->m_pools.GetAsset<AssetMenu>("popup");
|
|
REQUIRE(menuList);
|
|
REQUIRE(mainMenu);
|
|
REQUIRE(popupMenu);
|
|
REQUIRE(menuList->Asset()->menuCount == 2);
|
|
REQUIRE(mainMenu->Asset()->visibleExp.numEntries == 3);
|
|
REQUIRE(mainMenu->Asset()->window.dynamicFlags[0] & 0x10000);
|
|
REQUIRE(mainMenu->Asset()->items[0]->text != nullptr);
|
|
REQUIRE(mainMenu->Asset()->items[0]->text == ""s);
|
|
REQUIRE(mainMenu->Asset()->items[0]->window.dynamicFlags[0] & 0x10000);
|
|
REQUIRE(mainMenu->Asset()->items[0]->action == R"("setItemColor" "empty_text" "borderColor" "0.1" "0.1" "0.12" "0.5" ; )"s);
|
|
|
|
MockSearchPath objPath;
|
|
MockOutputPath dumpOutput;
|
|
AssetDumpingContext dumpingContext(*zone, "", dumpOutput, objPath, std::nullopt);
|
|
menu::MenuListDumperIW3 menuListDumper;
|
|
menuListDumper.Dump(dumpingContext);
|
|
menu::MenuDumperIW3 menuDumper;
|
|
menuDumper.Dump(dumpingContext);
|
|
|
|
const auto* dumpedMenuList = dumpOutput.GetMockedFile("ui_mp/menus.txt");
|
|
const auto* dumpedMainMenu = dumpOutput.GetMockedFile("ui_mp/main.menu");
|
|
const auto* dumpedPopupMenu = dumpOutput.GetMockedFile("ui_mp/popup.menu");
|
|
REQUIRE(dumpedMenuList);
|
|
REQUIRE(dumpedMainMenu);
|
|
REQUIRE(dumpedPopupMenu);
|
|
REQUIRE(dumpedMenuList->AsString().find("loadMenu { \"ui_mp/main.menu\" }") != std::string::npos);
|
|
REQUIRE(dumpedMenuList->AsString().find("loadMenu { \"ui_mp/popup.menu\" }") != std::string::npos);
|
|
REQUIRE(dumpedMainMenu->AsString().find("text \"\"") != std::string::npos);
|
|
REQUIRE(dumpedMainMenu->AsString().find("visible when(dvarbool(\"ui_show_main\"));") != std::string::npos);
|
|
REQUIRE(dumpedMainMenu->AsString().find("setItemColor empty_text borderColor 0.1 0.1 0.12 0.5;") != std::string::npos);
|
|
}
|
|
} // namespace
|