fix(menu): allow numeric dvar values (#927)

* fix(menu): allow numeric dvar values

* chore: use std format instead of stringstream

---------

Co-authored-by: Jan Laupetin <[email protected]>
This commit is contained in:
mo
2026-07-23 20:06:08 +02:00
committed by GitHub
co-authored by Jan Laupetin
parent b154ee95a4
commit 4421b94831
4 changed files with 50 additions and 2 deletions
@@ -2,6 +2,7 @@
#include "MenuExpressionMatchers.h" #include "MenuExpressionMatchers.h"
#include <format>
#include <sstream> #include <sstream>
using namespace menu; using namespace menu;
@@ -42,6 +43,22 @@ MatcherFactoryWrapper<SimpleParserValue> MenuMatcherFactory::Text() const
})); }));
} }
MatcherFactoryWrapper<SimpleParserValue> MenuMatcherFactory::TextOrNumeric() const
{
return Or({
Text(),
Numeric().Transform(
[](const token_list_t& tokens) -> SimpleParserValue
{
const auto& token = tokens[0].get();
if (token.m_type == SimpleParserValueType::INTEGER)
return SimpleParserValue::String(token.GetPos(), new std::string(std::to_string(token.IntegerValue())));
return SimpleParserValue::String(token.GetPos(), new std::string(std::format("{:g}", token.FloatingPointValue())));
}),
});
}
MatcherFactoryWrapper<SimpleParserValue> MenuMatcherFactory::TextNoChain() const MatcherFactoryWrapper<SimpleParserValue> MenuMatcherFactory::TextNoChain() const
{ {
return MatcherFactoryWrapper(Or({ return MatcherFactoryWrapper(Or({
@@ -25,6 +25,7 @@ namespace menu
[[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> StringChain() const; [[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> StringChain() const;
[[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> Text() const; [[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> Text() const;
[[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> TextOrNumeric() const;
[[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> TextNoChain() const; [[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> TextNoChain() const;
[[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> Numeric() const; [[nodiscard]] MatcherFactoryWrapper<SimpleParserValue> Numeric() const;
@@ -308,10 +308,10 @@ namespace menu::item_scope_sequences
create.KeywordIgnoreCase(std::move(keyName)).Capture(CAPTURE_FIRST_TOKEN), create.KeywordIgnoreCase(std::move(keyName)).Capture(CAPTURE_FIRST_TOKEN),
create.Char('{'), create.Char('{'),
create.Optional(create.And({ create.Optional(create.And({
create.Text().Capture(CAPTURE_VALUE), create.TextOrNumeric().Capture(CAPTURE_VALUE),
create.OptionalLoop(create.And({ create.OptionalLoop(create.And({
create.Char(';'), create.Char(';'),
create.Text().Capture(CAPTURE_VALUE), create.TextOrNumeric().Capture(CAPTURE_VALUE),
})), })),
})), })),
create.Char('}'), create.Char('}'),
@@ -301,6 +301,36 @@ namespace test::game::iw4::menu::parsing::it
REQUIRE(menu->items == nullptr); REQUIRE(menu->items == nullptr);
} }
TEST_CASE("MenuParsingIW4IT: Can use numeric focus dvar values", "[parsing][converting][menu][it]")
{
MenuParsingItHelper helper;
helper.AddFile(R"testmenu(
{
menuDef
{
name "NumericFocusDvar"
itemDef
{
focusDvar { 0; 1.5; -2 }
}
}
}
)testmenu");
const auto result = helper.RunIntegrationTest();
REQUIRE(result.HasBeenSuccessful());
const auto* menu = helper.GetMenuAsset("NumericFocusDvar");
REQUIRE(menu->itemCount == 1);
REQUIRE(menu->items != nullptr);
const auto* item = menu->items[0];
REQUIRE(item != nullptr);
REQUIRE(item->enableDvar == R"("0" "1.5" "-2" )"s);
REQUIRE(item->dvarFlags == ITEM_DVAR_FLAG_FOCUS);
}
TEST_CASE("MenuParsingIW4IT: Can specify event handler multiple times", "[parsing][converting][menu][it]") TEST_CASE("MenuParsingIW4IT: Can specify event handler multiple times", "[parsing][converting][menu][it]")
{ {
MenuParsingItHelper helper; MenuParsingItHelper helper;