#include "MenuScopeSequences.h" #include #include "Generic/GenericBoolPropertySequence.h" #include "Generic/GenericColorPropertySequence.h" #include "Generic/GenericExpressionPropertySequence.h" #include "Generic/GenericFloatingPointPropertySequence.h" #include "Generic/GenericIntPropertySequence.h" #include "Generic/GenericKeywordPropertySequence.h" #include "Generic/GenericMenuEventHandlerSetPropertySequence.h" #include "Generic/GenericStringPropertySequence.h" #include "Parsing/Menu/Matcher/MenuMatcherFactory.h" #include "Parsing/Menu/Domain/CommonMenuTypes.h" #include "Parsing/Menu/Matcher/MenuExpressionMatchers.h" using namespace menu; namespace menu::menu_scope_sequences { class SequenceCloseBlock final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_TOKEN = 1; public: SequenceCloseBlock() { const MenuMatcherFactory create(this); AddMatchers({ create.Char('}').Capture(CAPTURE_TOKEN) }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { if (state->m_current_menu->m_name.empty()) throw ParsingException(result.NextCapture(CAPTURE_TOKEN).GetPos(), "Menu must have a name"); const auto existingMenu = state->m_menus_by_name.find(state->m_current_menu->m_name); if (existingMenu == state->m_menus_by_name.end()) { state->m_menus_by_name.emplace(std::make_pair(state->m_current_menu->m_name, state->m_current_menu)); state->m_current_menu = nullptr; } else { std::ostringstream ss; ss << "Menu with name \"" << state->m_current_menu->m_name << "\" already exists"; throw ParsingException(result.NextCapture(CAPTURE_TOKEN).GetPos(), ss.str()); } } }; class SequenceItemDef final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_TOKEN = 1; public: SequenceItemDef() { const MenuMatcherFactory create(this); AddMatchers({ create.Keyword("itemDef"), create.Char('{') }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { auto newItemDef = std::make_unique(); state->m_current_item = newItemDef.get(); state->m_current_menu->m_items.emplace_back(std::move(newItemDef)); } }; class SequenceRect final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_ALIGN_HORIZONTAL = 5; static constexpr auto CAPTURE_ALIGN_VERTICAL = 6; public: SequenceRect() { const MenuMatcherFactory create(this); AddLabeledMatchers(MenuExpressionMatchers().Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); AddMatchers({ create.KeywordIgnoreCase("rect"), create.NumericExpression(), // x 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) })) }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { assert(state->m_current_menu); const auto x = MenuMatcherFactory::TokenNumericExpressionValue(result); const auto y = MenuMatcherFactory::TokenNumericExpressionValue(result); const auto w = MenuMatcherFactory::TokenNumericExpressionValue(result); const auto h = MenuMatcherFactory::TokenNumericExpressionValue(result); CommonRect rect { x, y, w, h, 0, 0 }; if (result.HasNextCapture(CAPTURE_ALIGN_HORIZONTAL) && result.HasNextCapture(CAPTURE_ALIGN_VERTICAL)) { rect.horizontalAlign = result.NextCapture(CAPTURE_ALIGN_HORIZONTAL).IntegerValue(); rect.verticalAlign = result.NextCapture(CAPTURE_ALIGN_VERTICAL).IntegerValue(); } state->m_current_menu->m_rect = rect; } }; class SequenceExecKey final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_KEY = 1; public: SequenceExecKey() { const MenuMatcherFactory create(this); AddMatchers({ create.KeywordIgnoreCase("execKey"), create.String().Capture(CAPTURE_KEY), create.Char('{') }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { assert(state->m_current_menu); const auto& keyToken = result.NextCapture(CAPTURE_KEY); const auto& keyValue = keyToken.StringValue(); if (keyValue.empty() || keyValue.size() > 1) throw ParsingException(keyToken.GetPos(), "Key handler string must have exactly one character"); const auto key = static_cast(static_cast(keyValue[0])); 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_menu->m_key_handlers.emplace(std::make_pair(key, std::move(newEventHandlerSet))); } }; class SequenceExecKeyInt final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_KEY = 1; public: SequenceExecKeyInt() { const MenuMatcherFactory create(this); AddMatchers({ create.KeywordIgnoreCase("execKeyInt"), create.Integer().Capture(CAPTURE_KEY), create.Char('{') }); } protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { assert(state->m_current_menu); const auto& keyToken = result.NextCapture(CAPTURE_KEY); const auto& keyValue = keyToken.IntegerValue(); if (keyValue < 0) throw ParsingException(keyToken.GetPos(), "Key handler value must be positive"); 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_menu->m_key_handlers.emplace(std::make_pair(keyValue, std::move(newEventHandlerSet))); } }; } using namespace menu_scope_sequences; MenuScopeSequences::MenuScopeSequences(std::vector>& allSequences, std::vector& scopeSequences) : AbstractScopeSequenceHolder(allSequences, scopeSequences) { } void MenuScopeSequences::AddSequences(FeatureLevel featureLevel) { AddSequence(std::make_unique()); AddSequence(std::make_unique()); AddSequence(std::make_unique("name", [](const MenuFileParserState* state, const TokenPos&, const std::string& value) { state->m_current_menu->m_name = value; })); AddSequence(std::make_unique("fullScreen", [](const MenuFileParserState* state, const TokenPos&, const bool value) { state->m_current_menu->m_full_screen = value; })); AddSequence(std::make_unique("screenSpace", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_screen_space = true; })); AddSequence(std::make_unique("decoration", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_decoration = true; })); AddSequence(std::make_unique()); // rect480 // rect720 // pos480 // pos720 AddSequence(std::make_unique("style", [](const MenuFileParserState* state, const TokenPos&, const int value) { state->m_current_menu->m_style = value; })); AddSequence(GenericExpressionPropertySequence::WithKeywordAndBool("visible", [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_visible_expression = std::move(value); })); AddSequence(std::make_unique("onOpen", [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_on_open = std::move(value); })); AddSequence(std::make_unique("onClose", [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_on_close = std::move(value); })); AddSequence(std::make_unique("onRequestClose", [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_on_request_close = std::move(value); })); AddSequence(std::make_unique("onESC", [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_on_esc = std::move(value); })); AddSequence(std::make_unique("border", [](const MenuFileParserState* state, const TokenPos&, const int value) { state->m_current_menu->m_border = value; })); AddSequence(std::make_unique("borderSize", [](const MenuFileParserState* state, const TokenPos&, const double value) { state->m_current_menu->m_border_size = value; })); AddSequence(std::make_unique("backcolor", [](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) { state->m_current_menu->m_fore_color = value; })); AddSequence(std::make_unique("bordercolor", [](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) { state->m_current_menu->m_focus_color = value; })); AddSequence(std::make_unique("outlinecolor", [](const MenuFileParserState* state, const TokenPos&, const CommonColor value) { state->m_current_menu->m_outline_color = value; })); AddSequence(std::make_unique("background", [](const MenuFileParserState* state, const TokenPos&, const std::string& value) { state->m_current_menu->m_background = value; })); AddSequence(std::make_unique("ownerdraw", [](const MenuFileParserState* state, const TokenPos&, const int value) { state->m_current_menu->m_owner_draw = value; })); AddSequence(std::make_unique("ownerdrawFlag", [](const MenuFileParserState* state, const TokenPos&, const int value) { state->m_current_menu->m_owner_draw_flags |= value; })); AddSequence(std::make_unique("outOfBoundsClick", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_out_of_bounds_click = true; })); AddSequence(std::make_unique("soundLoop", [](const MenuFileParserState* state, const TokenPos&, const std::string& value) { state->m_current_menu->m_sound_loop = value; })); AddSequence(GenericExpressionPropertySequence::WithKeywords({"exp", "rect", "X"}, [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_rect_x_exp = std::move(value); })); AddSequence(GenericExpressionPropertySequence::WithKeywords({"exp", "rect", "Y"}, [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_rect_y_exp = std::move(value); })); AddSequence(GenericExpressionPropertySequence::WithKeywords({"exp", "rect", "W"}, [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_rect_w_exp = std::move(value); })); AddSequence(GenericExpressionPropertySequence::WithKeywords({"exp", "rect", "H"}, [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) { state->m_current_menu->m_rect_h_exp = std::move(value); })); AddSequence(std::make_unique("popup", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_popup = true; })); AddSequence(std::make_unique("fadeClamp", [](const MenuFileParserState* state, const TokenPos&, const double value) { state->m_current_menu->m_fade_clamp = value; })); AddSequence(std::make_unique("fadeCycle", [](const MenuFileParserState* state, const TokenPos&, const int value) { state->m_current_menu->m_fade_cycle = value; })); AddSequence(std::make_unique("fadeAmount", [](const MenuFileParserState* state, const TokenPos&, const double value) { state->m_current_menu->m_fade_amount = value; })); AddSequence(std::make_unique("fadeInAmount", [](const MenuFileParserState* state, const TokenPos&, const double value) { state->m_current_menu->m_fade_in_amount = value; })); AddSequence(std::make_unique()); AddSequence(std::make_unique()); AddSequence(std::make_unique("blurWorld", [](const MenuFileParserState* state, const TokenPos&, const double value) { state->m_current_menu->m_blur_radius = value; })); AddSequence(std::make_unique("legacySplitScreenScale", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_legacy_split_screen_scale = true; })); AddSequence(std::make_unique("hiddenDuringScope", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_hidden_during_scope = true; })); AddSequence(std::make_unique("hiddenDuringFlashbang", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_hidden_during_flashbang = true; })); AddSequence(std::make_unique("hiddenDuringUI", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_hidden_during_ui = true; })); AddSequence(std::make_unique("allowedBinding", [](const MenuFileParserState* state, const TokenPos&, const std::string& value) { state->m_current_menu->m_allowed_binding = value; })); AddSequence(std::make_unique("textOnlyFocus", [](const MenuFileParserState* state, const TokenPos&) { state->m_current_menu->m_text_only_focus = true; })); }