diff --git a/src/ObjLoading/Parsing/Menu/Sequence/EventHandlerSetScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/EventHandlerSetScopeSequences.cpp index e9d4f2de..cb2eef8f 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/EventHandlerSetScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/EventHandlerSetScopeSequences.cpp @@ -14,7 +14,7 @@ using namespace menu; -namespace menu +namespace { enum class ExpectedScriptToken { @@ -195,14 +195,9 @@ namespace menu }); } }; -} // namespace menu -namespace menu::event_handler_set_scope_sequences -{ class SequenceCloseBlock final : public MenuFileParser::sequence_t { - static constexpr auto CAPTURE_TOKEN = 1; - public: SequenceCloseBlock() { @@ -922,9 +917,7 @@ namespace menu::event_handler_set_scope_sequences }); } }; -} // namespace menu::event_handler_set_scope_sequences - -using namespace event_handler_set_scope_sequences; +} // namespace EventHandlerSetScopeSequences::EventHandlerSetScopeSequences(std::vector>& allSequences, std::vector& scopeSequences) diff --git a/src/ObjLoading/Parsing/Menu/Sequence/FunctionScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/FunctionScopeSequences.cpp index e6b34d73..0ff087d7 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/FunctionScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/FunctionScopeSequences.cpp @@ -9,7 +9,7 @@ using namespace menu; -namespace menu::function_scope_sequences +namespace { class SequenceCloseBlock final : public MenuFileParser::sequence_t { @@ -69,9 +69,7 @@ namespace menu::function_scope_sequences } } }; -} // namespace menu::function_scope_sequences - -using namespace function_scope_sequences; +} // namespace FunctionScopeSequences::FunctionScopeSequences(std::vector>& allSequences, std::vector& scopeSequences) @@ -79,7 +77,7 @@ FunctionScopeSequences::FunctionScopeSequences(std::vector()); AddSequence(std::make_unique("name", diff --git a/src/ObjLoading/Parsing/Menu/Sequence/GlobalScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/GlobalScopeSequences.cpp index ec034cca..5a62a750 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/GlobalScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/GlobalScopeSequences.cpp @@ -5,7 +5,7 @@ using namespace menu; -namespace menu::global_scope_sequences +namespace { class SequenceCloseBlock final : public MenuFileParser::sequence_t { @@ -98,9 +98,7 @@ namespace menu::global_scope_sequences state->m_menus_to_load.emplace_back(menuNameToken.StringValue()); } }; -} // namespace menu::global_scope_sequences - -using namespace global_scope_sequences; +} // namespace GlobalScopeSequences::GlobalScopeSequences(std::vector>& allSequences, std::vector& scopeSequences) @@ -108,7 +106,7 @@ GlobalScopeSequences::GlobalScopeSequences(std::vector()); AddSequence(std::make_unique()); diff --git a/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp index fa3be032..20baf92a 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp @@ -12,148 +12,149 @@ #include "Parsing/Menu/MenuFileCommonOperations.h" #include +#include #include #include using namespace menu; -constexpr auto ITEM_TYPE_OWNERDRAW = 8; - -class ItemScopeOperations +namespace { - inline static const CommonItemFeatureType IW4_FEATURE_TYPE_BY_TYPE[0x18]{ - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_TEXT - CommonItemFeatureType::NONE, // ITEM_TYPE_BUTTON - CommonItemFeatureType::NONE, // ITEM_TYPE_RADIOBUTTON - CommonItemFeatureType::NONE, // ITEM_TYPE_CHECKBOX - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_EDITFIELD - CommonItemFeatureType::NONE, // ITEM_TYPE_COMBO - CommonItemFeatureType::LISTBOX, // ITEM_TYPE_LISTBOX - CommonItemFeatureType::NONE, // ITEM_TYPE_MODEL - CommonItemFeatureType::NONE, // ITEM_TYPE_OWNERDRAW - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_NUMERICFIELD - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_SLIDER - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_YESNO - CommonItemFeatureType::MULTI_VALUE, // ITEM_TYPE_MULTI - CommonItemFeatureType::ENUM_DVAR, // ITEM_TYPE_DVARENUM - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_BIND - CommonItemFeatureType::NONE, // ITEM_TYPE_MENUMODEL - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_VALIDFILEFIELD - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_DECIMALFIELD - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_UPREDITFIELD - CommonItemFeatureType::NONE, // ITEM_TYPE_GAME_MESSAGE_WINDOW - CommonItemFeatureType::NEWS_TICKER, // ITEM_TYPE_NEWS_TICKER - CommonItemFeatureType::NONE, // ITEM_TYPE_TEXT_SCROLL - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_EMAILFIELD - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_PASSWORDFIELD - }; + constexpr auto ITEM_TYPE_OWNERDRAW = 8; - inline static const CommonItemFeatureType IW5_FEATURE_TYPE_BY_TYPE[0x18]{ - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_TEXT - CommonItemFeatureType::NONE, // ITEM_TYPE_BUTTON - CommonItemFeatureType::NONE, // ITEM_TYPE_RADIOBUTTON - CommonItemFeatureType::NONE, // ITEM_TYPE_CHECKBOX - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_EDITFIELD - CommonItemFeatureType::NONE, // ITEM_TYPE_COMBO - CommonItemFeatureType::LISTBOX, // ITEM_TYPE_LISTBOX - CommonItemFeatureType::NONE, // ITEM_TYPE_MODEL - CommonItemFeatureType::NONE, // ITEM_TYPE_OWNERDRAW - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_NUMERICFIELD - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_SLIDER - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_YESNO - CommonItemFeatureType::MULTI_VALUE, // ITEM_TYPE_MULTI - CommonItemFeatureType::ENUM_DVAR, // ITEM_TYPE_DVARENUM - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_BIND - CommonItemFeatureType::NONE, // ITEM_TYPE_MENUMODEL - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_VALIDFILEFIELD - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_DECIMALFIELD - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_UPREDITFIELD - CommonItemFeatureType::NONE, // ITEM_TYPE_GAME_MESSAGE_WINDOW - CommonItemFeatureType::NEWS_TICKER, // ITEM_TYPE_NEWS_TICKER - CommonItemFeatureType::NONE, // ITEM_TYPE_TEXT_SCROLL - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_EMAILFIELD - CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_PASSWORDFIELD - }; - -public: - static void SetItemType(CommonItemDef& item, const FeatureLevel featureLevel, const TokenPos& pos, const int type) + class ItemScopeOperations { - if (type < 0) - throw ParsingException(pos, "Invalid item type"); + inline static const CommonItemFeatureType IW4_FEATURE_TYPE_BY_TYPE[0x18]{ + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_TEXT + CommonItemFeatureType::NONE, // ITEM_TYPE_BUTTON + CommonItemFeatureType::NONE, // ITEM_TYPE_RADIOBUTTON + CommonItemFeatureType::NONE, // ITEM_TYPE_CHECKBOX + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_EDITFIELD + CommonItemFeatureType::NONE, // ITEM_TYPE_COMBO + CommonItemFeatureType::LISTBOX, // ITEM_TYPE_LISTBOX + CommonItemFeatureType::NONE, // ITEM_TYPE_MODEL + CommonItemFeatureType::NONE, // ITEM_TYPE_OWNERDRAW + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_NUMERICFIELD + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_SLIDER + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_YESNO + CommonItemFeatureType::MULTI_VALUE, // ITEM_TYPE_MULTI + CommonItemFeatureType::ENUM_DVAR, // ITEM_TYPE_DVARENUM + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_BIND + CommonItemFeatureType::NONE, // ITEM_TYPE_MENUMODEL + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_VALIDFILEFIELD + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_DECIMALFIELD + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_UPREDITFIELD + CommonItemFeatureType::NONE, // ITEM_TYPE_GAME_MESSAGE_WINDOW + CommonItemFeatureType::NEWS_TICKER, // ITEM_TYPE_NEWS_TICKER + CommonItemFeatureType::NONE, // ITEM_TYPE_TEXT_SCROLL + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_EMAILFIELD + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_PASSWORDFIELD + }; - if (item.m_feature_type != CommonItemFeatureType::NONE) - throw ParsingException(pos, "Item type has already been set"); + inline static const CommonItemFeatureType IW5_FEATURE_TYPE_BY_TYPE[0x18]{ + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_TEXT + CommonItemFeatureType::NONE, // ITEM_TYPE_BUTTON + CommonItemFeatureType::NONE, // ITEM_TYPE_RADIOBUTTON + CommonItemFeatureType::NONE, // ITEM_TYPE_CHECKBOX + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_EDITFIELD + CommonItemFeatureType::NONE, // ITEM_TYPE_COMBO + CommonItemFeatureType::LISTBOX, // ITEM_TYPE_LISTBOX + CommonItemFeatureType::NONE, // ITEM_TYPE_MODEL + CommonItemFeatureType::NONE, // ITEM_TYPE_OWNERDRAW + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_NUMERICFIELD + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_SLIDER + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_YESNO + CommonItemFeatureType::MULTI_VALUE, // ITEM_TYPE_MULTI + CommonItemFeatureType::ENUM_DVAR, // ITEM_TYPE_DVARENUM + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_BIND + CommonItemFeatureType::NONE, // ITEM_TYPE_MENUMODEL + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_VALIDFILEFIELD + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_DECIMALFIELD + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_UPREDITFIELD + CommonItemFeatureType::NONE, // ITEM_TYPE_GAME_MESSAGE_WINDOW + CommonItemFeatureType::NEWS_TICKER, // ITEM_TYPE_NEWS_TICKER + CommonItemFeatureType::NONE, // ITEM_TYPE_TEXT_SCROLL + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_EMAILFIELD + CommonItemFeatureType::EDIT_FIELD, // ITEM_TYPE_PASSWORDFIELD + }; - item.m_type = type; - - switch (featureLevel) + public: + static void SetItemType(CommonItemDef& item, const FeatureLevel featureLevel, const TokenPos& pos, const int type) { - case FeatureLevel::IW4: - if (static_cast(type) >= std::extent_v) + if (type < 0) throw ParsingException(pos, "Invalid item type"); - item.m_feature_type = IW4_FEATURE_TYPE_BY_TYPE[static_cast(type)]; - break; - case FeatureLevel::IW5: - default: - if (static_cast(type) >= std::extent_v) - throw ParsingException(pos, "Invalid item type"); - item.m_feature_type = IW5_FEATURE_TYPE_BY_TYPE[static_cast(type)]; - break; + if (item.m_feature_type != CommonItemFeatureType::NONE) + throw ParsingException(pos, "Item type has already been set"); + + item.m_type = type; + + switch (featureLevel) + { + case FeatureLevel::IW4: + if (static_cast(type) >= std::extent_v) + throw ParsingException(pos, "Invalid item type"); + item.m_feature_type = IW4_FEATURE_TYPE_BY_TYPE[static_cast(type)]; + break; + + case FeatureLevel::IW5: + default: + if (static_cast(type) >= std::extent_v) + throw ParsingException(pos, "Invalid item type"); + item.m_feature_type = IW5_FEATURE_TYPE_BY_TYPE[static_cast(type)]; + break; + } + + switch (item.m_feature_type) + { + case CommonItemFeatureType::LISTBOX: + item.m_list_box_features = std::make_unique(); + break; + case CommonItemFeatureType::EDIT_FIELD: + item.m_edit_field_features = std::make_unique(); + break; + case CommonItemFeatureType::MULTI_VALUE: + item.m_multi_value_features = std::make_unique(); + break; + case CommonItemFeatureType::NEWS_TICKER: + item.m_news_ticker_features = std::make_unique(); + break; + default: + break; + } } - switch (item.m_feature_type) + static void EnsureHasListboxFeatures(const CommonItemDef& item, const TokenPos& pos) { - case CommonItemFeatureType::LISTBOX: - item.m_list_box_features = std::make_unique(); - break; - case CommonItemFeatureType::EDIT_FIELD: - item.m_edit_field_features = std::make_unique(); - break; - case CommonItemFeatureType::MULTI_VALUE: - item.m_multi_value_features = std::make_unique(); - break; - case CommonItemFeatureType::NEWS_TICKER: - item.m_news_ticker_features = std::make_unique(); - break; - default: - break; + if (item.m_feature_type != CommonItemFeatureType::LISTBOX || !item.m_list_box_features) + throw ParsingException(pos, "Item must have be listbox to use this declaration"); } - } - static void EnsureHasListboxFeatures(const CommonItemDef& item, const TokenPos& pos) - { - if (item.m_feature_type != CommonItemFeatureType::LISTBOX || !item.m_list_box_features) - throw ParsingException(pos, "Item must have be listbox to use this declaration"); - } + static void EnsureHasEditFieldFeatures(const CommonItemDef& item, const TokenPos& pos) + { + if (item.m_feature_type != CommonItemFeatureType::EDIT_FIELD || !item.m_edit_field_features) + throw ParsingException(pos, "Item must have be edit field to use this declaration"); + } - static void EnsureHasEditFieldFeatures(const CommonItemDef& item, const TokenPos& pos) - { - if (item.m_feature_type != CommonItemFeatureType::EDIT_FIELD || !item.m_edit_field_features) - throw ParsingException(pos, "Item must have be edit field to use this declaration"); - } + static void EnsureHasMultiValueFeatures(const CommonItemDef& item, const TokenPos& pos) + { + if (item.m_feature_type != CommonItemFeatureType::MULTI_VALUE || !item.m_multi_value_features) + throw ParsingException(pos, "Item must have be multi value to use this declaration"); + } - static void EnsureHasMultiValueFeatures(const CommonItemDef& item, const TokenPos& pos) - { - if (item.m_feature_type != CommonItemFeatureType::MULTI_VALUE || !item.m_multi_value_features) - throw ParsingException(pos, "Item must have be multi value to use this declaration"); - } + static void EnsureHasEnumDvarFeatures(const CommonItemDef& item, const TokenPos& pos) + { + if (item.m_feature_type != CommonItemFeatureType::ENUM_DVAR) + throw ParsingException(pos, "Item must have be enum dvar to use this declaration"); + } - static void EnsureHasEnumDvarFeatures(const CommonItemDef& item, const TokenPos& pos) - { - if (item.m_feature_type != CommonItemFeatureType::ENUM_DVAR) - throw ParsingException(pos, "Item must have be enum dvar to use this declaration"); - } + static void EnsureHasNewsTickerFeatures(const CommonItemDef& item, const TokenPos& pos) + { + if (item.m_feature_type != CommonItemFeatureType::NEWS_TICKER || !item.m_news_ticker_features) + throw ParsingException(pos, "Item must have be news ticker to use this declaration"); + } + }; - static void EnsureHasNewsTickerFeatures(const CommonItemDef& item, const TokenPos& pos) - { - if (item.m_feature_type != CommonItemFeatureType::NEWS_TICKER || !item.m_news_ticker_features) - throw ParsingException(pos, "Item must have be news ticker to use this declaration"); - } -}; - -namespace menu::item_scope_sequences -{ class SequenceCloseBlock final : public MenuFileParser::sequence_t { public: @@ -449,94 +450,106 @@ namespace menu::item_scope_sequences class SequenceColumns final : public MenuFileParser::sequence_t { - static constexpr auto TAG_COLUMN = 1; + static constexpr auto TAG_VALUE = 1; static constexpr auto CAPTURE_FIRST_TOKEN = 1; static constexpr auto CAPTURE_COLUMN_COUNT = 2; + static constexpr const char* SYNTAX_IW4 = " [alignment]"; + static constexpr auto BASE_COLUMN_COUNT_IW4 = 3; + + static constexpr const char* SYNTAX_IW5 = " [alignment]"; + static constexpr auto BASE_COLUMN_COUNT_IW5 = 5; + public: - explicit SequenceColumns(const FeatureLevel featureLevel) + explicit SequenceColumns() { const MenuMatcherFactory create(this); AddLabeledMatchers(MenuExpressionMatchers().Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); - if (featureLevel == FeatureLevel::IW5) - { - AddMatchers({ - create.KeywordIgnoreCase("columns").Capture(CAPTURE_FIRST_TOKEN), - create.Integer().Capture(CAPTURE_COLUMN_COUNT), - create.Loop(create.And({ - create.True().Tag(TAG_COLUMN), - create.IntExpression(), // xpos - create.IntExpression(), // ypos - create.IntExpression(), // width - create.IntExpression(), // height - create.IntExpression(), // maxChars - create.IntExpression(), // alignment - })), - }); - } - else - { - AddMatchers({ - create.KeywordIgnoreCase("columns").Capture(CAPTURE_FIRST_TOKEN), - create.Integer().Capture(CAPTURE_COLUMN_COUNT), - create.Loop(create.And({ - create.True().Tag(TAG_COLUMN), - create.IntExpression(), // xpos - create.IntExpression(), // width - create.IntExpression(), // maxChars - create.IntExpression(), // alignment - })), - }); - } + AddMatchers({ + create.KeywordIgnoreCase("columns").Capture(CAPTURE_FIRST_TOKEN), + create.Integer().Capture(CAPTURE_COLUMN_COUNT), + create.Loop(create.IntExpression().Tag(TAG_VALUE)), + }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { assert(state->m_current_item); - - ItemScopeOperations::EnsureHasListboxFeatures(*state->m_current_item, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos()); - assert(state->m_feature_level == FeatureLevel::IW4 || state->m_feature_level == FeatureLevel::IW5); - const auto& listBoxFeatures = state->m_current_item->m_list_box_features; - while (result.PeekAndRemoveIfTag(TAG_COLUMN) == TAG_COLUMN) + const auto& firstToken = result.NextCapture(CAPTURE_FIRST_TOKEN); + ItemScopeOperations::EnsureHasListboxFeatures(*state->m_current_item, firstToken.GetPos()); + + const auto columnCount = static_cast(result.NextCapture(CAPTURE_COLUMN_COUNT).IntegerValue()); + std::vector columnValues; + while (result.PeekAndRemoveIfTag(TAG_VALUE) == TAG_VALUE) + columnValues.emplace_back(MenuMatcherFactory::TokenIntExpressionValue(state, result)); + + size_t baseColumnCount; + const char* syntax; + bool hasHeightValues; + if (state->m_feature_level == FeatureLevel::IW4) { - int xPos = 0; - int yPos = 0; - int width = 0; - int height = 0; - int maxChars = 0; - int alignment = 0; + baseColumnCount = BASE_COLUMN_COUNT_IW4; + syntax = SYNTAX_IW4; + hasHeightValues = false; + } + else + { + assert(state->m_feature_level == FeatureLevel::IW5); + baseColumnCount = BASE_COLUMN_COUNT_IW5; + syntax = SYNTAX_IW5; + hasHeightValues = true; + } - if (state->m_feature_level == FeatureLevel::IW4) - { - xPos = MenuMatcherFactory::TokenIntExpressionValue(state, result); - width = MenuMatcherFactory::TokenIntExpressionValue(state, result); - maxChars = MenuMatcherFactory::TokenIntExpressionValue(state, result); - alignment = MenuMatcherFactory::TokenIntExpressionValue(state, result); - } - else if (state->m_feature_level == FeatureLevel::IW5) - { - xPos = MenuMatcherFactory::TokenIntExpressionValue(state, result); - yPos = MenuMatcherFactory::TokenIntExpressionValue(state, result); - width = MenuMatcherFactory::TokenIntExpressionValue(state, result); - height = MenuMatcherFactory::TokenIntExpressionValue(state, result); - maxChars = MenuMatcherFactory::TokenIntExpressionValue(state, result); - alignment = MenuMatcherFactory::TokenIntExpressionValue(state, result); - } + bool hasAlignmentSpecified; + if (columnValues.size() == columnCount * (baseColumnCount + 1)) + hasAlignmentSpecified = true; + else if (columnValues.size() == columnCount * baseColumnCount) + hasAlignmentSpecified = false; + else + throw ParsingException(firstToken.GetPos(), std::format("Each row must have the following syntax: {}", syntax)); - CommonItemFeaturesListBox::Column column{ - xPos, - yPos, - width, - height, - maxChars, - alignment, - }; - listBoxFeatures->m_columns.emplace_back(column); + const auto& listBoxFeatures = state->m_current_item->m_list_box_features; + + size_t valueIndex = 0u; + for (auto columnIndex = 0u; columnIndex < columnCount; columnIndex++) + { + const auto xPos = columnValues[valueIndex++]; + + int yPos; + if (hasHeightValues) + yPos = columnValues[valueIndex++]; + else + yPos = 0; + + const auto width = columnValues[valueIndex++]; + + int height; + if (hasHeightValues) + height = columnValues[valueIndex++]; + else + height = 0; + + const auto maxChars = columnValues[valueIndex++]; + + int alignment; + if (hasAlignmentSpecified) + alignment = columnValues[valueIndex++]; + else + alignment = 0; + + listBoxFeatures->m_columns.emplace_back(CommonItemFeaturesListBox::Column{ + .m_x_pos = xPos, + .m_y_pos = yPos, + .m_width = width, + .m_height = height, + .m_max_chars = maxChars, + .m_alignment = alignment, + }); } } }; @@ -573,7 +586,7 @@ namespace menu::item_scope_sequences auto newEventHandlerSet = std::make_unique(); state->m_current_event_handler_set = newEventHandlerSet.get(); state->m_current_nested_event_handler_set = newEventHandlerSet.get(); - state->m_current_item->m_key_handlers.emplace(std::make_pair(key, std::move(newEventHandlerSet))); + state->m_current_item->m_key_handlers.emplace(key, std::move(newEventHandlerSet)); } }; @@ -607,12 +620,10 @@ namespace menu::item_scope_sequences auto newEventHandlerSet = std::make_unique(); state->m_current_event_handler_set = newEventHandlerSet.get(); state->m_current_nested_event_handler_set = newEventHandlerSet.get(); - state->m_current_item->m_key_handlers.emplace(std::make_pair(keyValue, std::move(newEventHandlerSet))); + state->m_current_item->m_key_handlers.emplace(keyValue, std::move(newEventHandlerSet)); } }; -} // namespace menu::item_scope_sequences - -using namespace item_scope_sequences; +} // namespace ItemScopeSequences::ItemScopeSequences(std::vector>& allSequences, std::vector& scopeSequences) @@ -620,7 +631,7 @@ ItemScopeSequences::ItemScopeSequences(std::vector()); AddSequence(std::make_unique("name", @@ -746,32 +757,32 @@ void ItemScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive state->m_current_item->m_text_font = value; })); AddSequence(std::make_unique("backcolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_item->m_back_color = value; })); AddSequence(std::make_unique("forecolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_item->m_fore_color = value; })); AddSequence(std::make_unique("bordercolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_item->m_border_color = value; })); AddSequence(std::make_unique("outlinecolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_item->m_outline_color = value; })); AddSequence(std::make_unique("disablecolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_item->m_disable_color = value; })); AddSequence(std::make_unique("glowcolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_item->m_glow_color = value; })); @@ -1060,7 +1071,7 @@ void ItemScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive } // ============== ListBox ============== - AddSequence(std::make_unique(featureLevel)); + AddSequence(std::make_unique()); AddSequence(std::make_unique("notselectable", [](const MenuFileParserState* state, const TokenPos& pos) { diff --git a/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp index 8b8efced..e44b56e3 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp @@ -17,7 +17,7 @@ using namespace menu; -namespace menu::menu_scope_sequences +namespace { class SequenceCloseBlock final : public MenuFileParser::sequence_t { @@ -72,8 +72,6 @@ namespace menu::menu_scope_sequences class SequenceItemDef final : public MenuFileParser::sequence_t { - static constexpr auto CAPTURE_TOKEN = 1; - public: SequenceItemDef() { @@ -208,9 +206,7 @@ namespace menu::menu_scope_sequences state->m_current_menu->m_key_handlers.emplace(std::make_pair(keyValue, std::move(newEventHandlerSet))); } }; -} // namespace menu::menu_scope_sequences - -using namespace menu_scope_sequences; +} // namespace MenuScopeSequences::MenuScopeSequences(std::vector>& allSequences, std::vector& scopeSequences) @@ -218,7 +214,7 @@ MenuScopeSequences::MenuScopeSequences(std::vector()); AddSequence(std::make_unique()); @@ -294,27 +290,27 @@ void MenuScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive state->m_current_menu->m_border_size = value; })); AddSequence(std::make_unique("backcolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_menu->m_back_color = value; })); AddSequence(std::make_unique("forecolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_menu->m_fore_color = value; })); AddSequence(std::make_unique("bordercolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_menu->m_border_color = value; })); AddSequence(std::make_unique("focuscolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_menu->m_focus_color = value; })); AddSequence(std::make_unique("outlinecolor", - [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) + [](const MenuFileParserState* state, const TokenPos&, const CommonColor& value) { state->m_current_menu->m_outline_color = value; })); diff --git a/src/ObjLoading/Parsing/Menu/Sequence/NoScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/NoScopeSequences.cpp index 213e9143..9ff5a81d 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/NoScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/NoScopeSequences.cpp @@ -5,7 +5,7 @@ using namespace menu; -namespace menu::no_scope_sequences +namespace { class SequenceOpenGlobalScope final : public MenuFileParser::sequence_t { @@ -25,9 +25,7 @@ namespace menu::no_scope_sequences state->m_in_global_scope = true; } }; -} // namespace menu::no_scope_sequences - -using namespace no_scope_sequences; +} // namespace NoScopeSequences::NoScopeSequences(std::vector>& allSequences, std::vector& scopeSequences) @@ -35,7 +33,7 @@ NoScopeSequences::NoScopeSequences(std::vector()); } diff --git a/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp b/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp index c2282f74..ee63968c 100644 --- a/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp +++ b/test/ObjLoadingTests/Game/IW4/Menu/LoaderMenuListIW4Test.cpp @@ -331,6 +331,59 @@ namespace test::game::iw4::menu::parsing::it REQUIRE(item->dvarFlags == ITEM_DVAR_FLAG_FOCUS); } + TEST_CASE("MenuParsingIW4IT: Can omit list box column alignment", "[parsing][converting][menu][it]") + { + MenuParsingItHelper helper; + + helper.AddFile(R"testmenu( +{ + menuDef + { + name "ListBoxColumns" + itemDef + { + type 6 + // x, width, max chars + columns 1 22 190 64 + } + itemDef + { + type 6 + // x, width, max chars, alignment + columns 2 0 18 3 2 18 25 10 1 + } + } +} + )testmenu"); + + const auto result = helper.RunIntegrationTest(); + REQUIRE(result.HasBeenSuccessful()); + + const auto* menu = helper.GetMenuAsset("ListBoxColumns"); + REQUIRE(menu->itemCount == 2); + REQUIRE(menu->items != nullptr); + + const auto* columnsWithoutAlignment = menu->items[0]->typeData.listBox; + REQUIRE(columnsWithoutAlignment != nullptr); + REQUIRE(columnsWithoutAlignment->numColumns == 1); + CHECK(columnsWithoutAlignment->columnInfo[0].pos == 22); + CHECK(columnsWithoutAlignment->columnInfo[0].width == 190); + CHECK(columnsWithoutAlignment->columnInfo[0].maxChars == 64); + CHECK(columnsWithoutAlignment->columnInfo[0].alignment == 0); + + const auto* columnsWithAlignment = menu->items[1]->typeData.listBox; + REQUIRE(columnsWithAlignment != nullptr); + REQUIRE(columnsWithAlignment->numColumns == 2); + CHECK(columnsWithAlignment->columnInfo[0].pos == 0); + CHECK(columnsWithAlignment->columnInfo[0].width == 18); + CHECK(columnsWithAlignment->columnInfo[0].maxChars == 3); + CHECK(columnsWithAlignment->columnInfo[0].alignment == 2); + CHECK(columnsWithAlignment->columnInfo[1].pos == 18); + CHECK(columnsWithAlignment->columnInfo[1].width == 25); + CHECK(columnsWithAlignment->columnInfo[1].maxChars == 10); + CHECK(columnsWithAlignment->columnInfo[1].alignment == 1); + } + TEST_CASE("MenuParsingIW4IT: Can specify event handler multiple times", "[parsing][converting][menu][it]") { MenuParsingItHelper helper;