From f5c987ce59966de068ed8d66797568f596e46e9e Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 25 Dec 2023 19:35:03 +0100 Subject: [PATCH] Add unit tests for menu item rect --- .../Menu/Sequence/ItemScopeSequences.cpp | 23 ++-- .../Menu/Sequence/ItemScopeSequencesTests.cpp | 128 ++++++++++++++++++ 2 files changed, 138 insertions(+), 13 deletions(-) diff --git a/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp index 032caeb3..0ba34791 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp @@ -189,8 +189,7 @@ namespace menu::item_scope_sequences class SequenceRect final : public MenuFileParser::sequence_t { - static constexpr auto CAPTURE_ALIGN_HORIZONTAL = 1; - static constexpr auto CAPTURE_ALIGN_VERTICAL = 2; + static constexpr auto TAG_ALIGN = 1; public: SequenceRect() @@ -204,10 +203,12 @@ namespace menu::item_scope_sequences create.NumericExpression(), // y create.NumericExpression(), // w create.NumericExpression(), // h - create.Optional(create.And({ - create.Integer().Capture(CAPTURE_ALIGN_HORIZONTAL), - create.Integer().Capture(CAPTURE_ALIGN_VERTICAL), - })), + create.Optional(create + .And({ + create.IntExpression(), // Align horizontal + create.IntExpression(), // Align vertical + }) + .Tag(TAG_ALIGN)), }); } @@ -222,10 +223,10 @@ namespace menu::item_scope_sequences const auto h = MenuMatcherFactory::TokenNumericExpressionValue(state, result); CommonRect rect{x, y, w, h, 0, 0}; - if (result.HasNextCapture(CAPTURE_ALIGN_HORIZONTAL) && result.HasNextCapture(CAPTURE_ALIGN_VERTICAL)) + if (result.PeekAndRemoveIfTag(TAG_ALIGN) == TAG_ALIGN) { - rect.horizontalAlign = result.NextCapture(CAPTURE_ALIGN_HORIZONTAL).IntegerValue(); - rect.verticalAlign = result.NextCapture(CAPTURE_ALIGN_VERTICAL).IntegerValue(); + rect.horizontalAlign = MenuMatcherFactory::TokenIntExpressionValue(state, result); + rect.verticalAlign = MenuMatcherFactory::TokenIntExpressionValue(state, result); } state->m_current_item->m_rect = rect; @@ -259,10 +260,6 @@ namespace menu::item_scope_sequences class SequenceDecodeEffect final : public MenuFileParser::sequence_t { - static constexpr auto CAPTURE_LETTER_TIME = 1; - static constexpr auto CAPTURE_DECAY_START_TIME = 2; - static constexpr auto CAPTURE_DECAY_DURATION = 3; - public: SequenceDecodeEffect() { diff --git a/test/ObjLoadingTests/Parsing/Menu/Sequence/ItemScopeSequencesTests.cpp b/test/ObjLoadingTests/Parsing/Menu/Sequence/ItemScopeSequencesTests.cpp index d3fd9c41..4be3355d 100644 --- a/test/ObjLoadingTests/Parsing/Menu/Sequence/ItemScopeSequencesTests.cpp +++ b/test/ObjLoadingTests/Parsing/Menu/Sequence/ItemScopeSequencesTests.cpp @@ -4,8 +4,10 @@ #include #include +#include using namespace menu; +using namespace Catch::Matchers; namespace test::parsing::menu::sequence::item { @@ -62,6 +64,132 @@ namespace test::parsing::menu::sequence::item } }; + TEST_CASE("ItemScopeSequences: Rect works with only x,y,w,h as ints", "[parsing][sequence][menu]") + { + ItemSequenceTestsHelper helper(FeatureLevel::IW4, false); + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Identifier(pos, new std::string("rect")), + SimpleParserValue::Integer(pos, 20), + SimpleParserValue::Integer(pos, 40), + SimpleParserValue::Integer(pos, 100), + SimpleParserValue::Integer(pos, 520), + SimpleParserValue::EndOfFile(pos), + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 5); + + const auto* item = helper.m_state->m_current_item; + REQUIRE(item); + + REQUIRE_THAT(item->m_rect.x, WithinRel(20.0)); + REQUIRE_THAT(item->m_rect.y, WithinRel(40.0)); + REQUIRE_THAT(item->m_rect.w, WithinRel(100.0)); + REQUIRE_THAT(item->m_rect.h, WithinRel(520.0)); + REQUIRE(item->m_rect.horizontalAlign == 0); + REQUIRE(item->m_rect.verticalAlign == 0); + } + + TEST_CASE("ItemScopeSequences: Rect works with only x,y,w,h as floats", "[parsing][sequence][menu]") + { + ItemSequenceTestsHelper helper(FeatureLevel::IW4, false); + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Identifier(pos, new std::string("rect")), + SimpleParserValue::FloatingPoint(pos, 20.2), + SimpleParserValue::FloatingPoint(pos, 40.4), + SimpleParserValue::FloatingPoint(pos, 100.6), + SimpleParserValue::FloatingPoint(pos, 520.8), + SimpleParserValue::EndOfFile(pos), + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 5); + + const auto* item = helper.m_state->m_current_item; + REQUIRE(item); + + REQUIRE_THAT(item->m_rect.x, WithinRel(20.2)); + REQUIRE_THAT(item->m_rect.y, WithinRel(40.4)); + REQUIRE_THAT(item->m_rect.w, WithinRel(100.6)); + REQUIRE_THAT(item->m_rect.h, WithinRel(520.8)); + } + + TEST_CASE("ItemScopeSequences: Rect supports expressions", "[parsing][sequence][menu]") + { + ItemSequenceTestsHelper helper(FeatureLevel::IW4, false); + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Identifier(pos, new std::string("rect")), + SimpleParserValue::Character(pos, '('), + SimpleParserValue::FloatingPoint(pos, 20.2), + SimpleParserValue::Character(pos, '+'), + SimpleParserValue::Integer(pos, 40), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::Character(pos, '('), + SimpleParserValue::FloatingPoint(pos, 40.2), + SimpleParserValue::Character(pos, '-'), + SimpleParserValue::FloatingPoint(pos, 1.4), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::Character(pos, '('), + SimpleParserValue::FloatingPoint(pos, 100.6), + SimpleParserValue::Character(pos, '+'), + SimpleParserValue::FloatingPoint(pos, 2.0), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::Character(pos, '('), + SimpleParserValue::FloatingPoint(pos, 5.0), + SimpleParserValue::Character(pos, '*'), + SimpleParserValue::FloatingPoint(pos, 1.5), + SimpleParserValue::Character(pos, ')'), + SimpleParserValue::EndOfFile(pos), + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 21); + + const auto* item = helper.m_state->m_current_item; + REQUIRE(item); + + REQUIRE_THAT(item->m_rect.x, WithinRel(60.2)); + REQUIRE_THAT(item->m_rect.y, WithinRel(38.8)); + REQUIRE_THAT(item->m_rect.w, WithinRel(102.6)); + REQUIRE_THAT(item->m_rect.h, WithinRel(7.5)); + } + + TEST_CASE("ItemScopeSequences: Rect can specify align", "[parsing][sequence][menu]") + { + ItemSequenceTestsHelper helper(FeatureLevel::IW4, false); + const TokenPos pos; + helper.Tokens({ + SimpleParserValue::Identifier(pos, new std::string("rect")), + SimpleParserValue::FloatingPoint(pos, 20.2), + SimpleParserValue::FloatingPoint(pos, 40.4), + SimpleParserValue::FloatingPoint(pos, 100.6), + SimpleParserValue::FloatingPoint(pos, 520.8), + SimpleParserValue::Integer(pos, 1), + SimpleParserValue::Integer(pos, 2), + SimpleParserValue::EndOfFile(pos), + }); + + const auto result = helper.PerformTest(); + + REQUIRE(result); + REQUIRE(helper.m_consumed_token_count == 7); + + const auto* item = helper.m_state->m_current_item; + REQUIRE(item); + + REQUIRE(item->m_rect.horizontalAlign == 1); + REQUIRE(item->m_rect.verticalAlign == 2); + } + TEST_CASE("ItemScopeSequences: Simple dvarStrList works", "[parsing][sequence][menu]") { ItemSequenceTestsHelper helper(FeatureLevel::IW4, false);