From 8a1fe03358ddce991394a684ca5ce1c93c78255d Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 23 Aug 2023 23:08:50 +0200 Subject: [PATCH] Add base for IW5 menu parsing --- .../Game/IW5/Menu/MenuConverterIW5.cpp | 4 + .../Parsing/Menu/Domain/CommonItemDef.h | 3 + .../Parsing/Menu/Domain/CommonMenuDef.h | 2 + .../Menu/Sequence/ItemScopeSequences.cpp | 141 +++++++++++++----- .../Menu/Sequence/MenuScopeSequences.cpp | 26 +++- .../Game/IW5/Menu/MenuDumperIW5.cpp | 56 +++++-- src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h | 1 + 7 files changed, 175 insertions(+), 58 deletions(-) diff --git a/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.cpp b/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.cpp index 53a92840..1a2ff51d 100644 --- a/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.cpp +++ b/src/ObjLoading/Game/IW5/Menu/MenuConverterIW5.cpp @@ -848,6 +848,7 @@ namespace IW5 listBox->onDoubleClick = ConvertEventHandlerSet(commonListBox->m_on_double_click.get(), &parentMenu, &commonItem); ConvertColor(listBox->selectBorder, commonListBox->m_select_border); listBox->selectIcon = ConvertMaterial(commonListBox->m_select_icon, &parentMenu, &commonItem); + listBox->elementHeightExp = ConvertOrApplyStatement(listBox->elementHeight, commonListBox->m_element_height_expression.get(), &parentMenu, &commonItem); listBox->numColumns = static_cast(std::min(std::extent_v, commonListBox->m_columns.size())); for (auto i = 0; i < listBox->numColumns; i++) @@ -971,6 +972,7 @@ namespace IW5 ConvertColor(item->glowColor, commonItem.m_glow_color); item->window.background = ConvertMaterial(commonItem.m_background, &parentMenu, &commonItem); item->onFocus = ConvertEventHandlerSet(commonItem.m_on_focus.get(), &parentMenu, &commonItem); + item->hasFocus = ConvertEventHandlerSet(commonItem.m_has_focus.get(), &parentMenu, &commonItem); item->leaveFocus = ConvertEventHandlerSet(commonItem.m_on_leave_focus.get(), &parentMenu, &commonItem); item->mouseEnter = ConvertEventHandlerSet(commonItem.m_on_mouse_enter.get(), &parentMenu, &commonItem); item->mouseExit = ConvertEventHandlerSet(commonItem.m_on_mouse_exit.get(), &parentMenu, &commonItem); @@ -983,6 +985,7 @@ namespace IW5 item->enableDvar = ConvertEnableDvar(commonItem, item->dvarFlags); item->onKey = ConvertKeyHandler(commonItem.m_key_handlers, &parentMenu, &commonItem); item->textExp = ConvertOrApplyStatement(item->text, commonItem.m_text_expression.get(), &parentMenu, &commonItem); + item->textAlignYExp = ConvertOrApplyStatement(item->textaligny, commonItem.m_text_align_y_expression.get(), &parentMenu, &commonItem); item->materialExp = ConvertOrApplyStatement(item->window.background, commonItem.m_material_expression.get(), &parentMenu, &commonItem); item->disabledExp = ConvertExpression(commonItem.m_disabled_expression.get(), &parentMenu, &commonItem); item->floatExpressions = ConvertFloatExpressions(&commonItem, item, &parentMenu, item->floatExpressionCount); @@ -1103,6 +1106,7 @@ namespace IW5 menuData->onClose = ConvertEventHandlerSet(commonMenu.m_on_close.get(), &commonMenu); menuData->onCloseRequest = ConvertEventHandlerSet(commonMenu.m_on_request_close.get(), &commonMenu); menuData->onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu); + menuData->onFocusDueToClose = ConvertEventHandlerSet(commonMenu.m_on_focus_due_to_close.get(), &commonMenu); menuData->onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu); menu->items = ConvertMenuItems(commonMenu, menu->itemCount); menuData->expressionData = m_conversion_zone_state->m_supporting_data; diff --git a/src/ObjLoading/Parsing/Menu/Domain/CommonItemDef.h b/src/ObjLoading/Parsing/Menu/Domain/CommonItemDef.h index 7adbd3a2..8960b4a2 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/CommonItemDef.h +++ b/src/ObjLoading/Parsing/Menu/Domain/CommonItemDef.h @@ -44,6 +44,7 @@ namespace menu std::string m_select_icon; std::unique_ptr m_on_double_click; + std::unique_ptr m_element_height_expression; std::vector m_columns; }; @@ -136,6 +137,7 @@ namespace menu std::unique_ptr m_visible_expression; std::unique_ptr m_disabled_expression; std::unique_ptr m_text_expression; + std::unique_ptr m_text_align_y_expression; std::unique_ptr m_material_expression; std::unique_ptr m_rect_x_exp; std::unique_ptr m_rect_y_exp; @@ -145,6 +147,7 @@ namespace menu ColorExpressions m_glowcolor_expressions; ColorExpressions m_backcolor_expressions; std::unique_ptr m_on_focus; + std::unique_ptr m_has_focus; std::unique_ptr m_on_leave_focus; std::unique_ptr m_on_mouse_enter; std::unique_ptr m_on_mouse_exit; diff --git a/src/ObjLoading/Parsing/Menu/Domain/CommonMenuDef.h b/src/ObjLoading/Parsing/Menu/Domain/CommonMenuDef.h index 18663ff4..43a8872b 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/CommonMenuDef.h +++ b/src/ObjLoading/Parsing/Menu/Domain/CommonMenuDef.h @@ -29,6 +29,7 @@ namespace menu int m_owner_draw = 0; int m_owner_draw_flags = 0; std::string m_sound_loop; + std::unique_ptr m_sound_loop_exp; double m_fade_clamp = 0; int m_fade_cycle = 0; double m_fade_amount = 0; @@ -46,6 +47,7 @@ namespace menu std::unique_ptr m_on_close; std::unique_ptr m_on_request_close; std::unique_ptr m_on_esc; + std::unique_ptr m_on_focus_due_to_close; std::multimap> m_key_handlers; bool m_full_screen = false; diff --git a/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp index 22a64e3a..336b1182 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp @@ -45,6 +45,34 @@ class ItemScopeOperations CommonItemFeatureType::EDIT_FIELD // ITEM_TYPE_PASSWORDFIELD }; + 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) { @@ -66,8 +94,10 @@ public: case FeatureLevel::IW5: default: - assert(false); - throw ParsingException(pos, "Unimplemented item types for feature level"); + 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) @@ -431,26 +461,46 @@ namespace menu::item_scope_sequences { static constexpr auto CAPTURE_FIRST_TOKEN = 1; static constexpr auto CAPTURE_COLUMN_COUNT = 2; - static constexpr auto CAPTURE_POS = 3; - static constexpr auto CAPTURE_WIDTH = 4; - static constexpr auto CAPTURE_MAX_CHARS = 5; - static constexpr auto CAPTURE_ALIGNMENT = 6; + static constexpr auto CAPTURE_X_POS = 3; + static constexpr auto CAPTURE_Y_POS = 4; + static constexpr auto CAPTURE_WIDTH = 5; + static constexpr auto CAPTURE_HEIGHT = 6; + static constexpr auto CAPTURE_MAX_CHARS = 7; + static constexpr auto CAPTURE_ALIGNMENT = 8; public: - SequenceColumns() + explicit SequenceColumns(const FeatureLevel featureLevel) { const MenuMatcherFactory create(this); - AddMatchers({ - create.KeywordIgnoreCase("columns").Capture(CAPTURE_FIRST_TOKEN), - create.Integer().Capture(CAPTURE_COLUMN_COUNT), - create.Loop(create.And({ - create.Integer().Capture(CAPTURE_POS), - create.Integer().Capture(CAPTURE_WIDTH), - create.Integer().Capture(CAPTURE_MAX_CHARS), - create.Integer().Capture(CAPTURE_ALIGNMENT), - })), - }); + if (featureLevel == FeatureLevel::IW5) + { + AddMatchers({ + create.KeywordIgnoreCase("columns").Capture(CAPTURE_FIRST_TOKEN), + create.Integer().Capture(CAPTURE_COLUMN_COUNT), + create.Loop(create.And({ + create.Integer().Capture(CAPTURE_X_POS), + create.Integer().Capture(CAPTURE_Y_POS), + create.Integer().Capture(CAPTURE_WIDTH), + create.Integer().Capture(CAPTURE_HEIGHT), + create.Integer().Capture(CAPTURE_MAX_CHARS), + create.Integer().Capture(CAPTURE_ALIGNMENT), + })), + }); + } + else + { + AddMatchers({ + create.KeywordIgnoreCase("columns").Capture(CAPTURE_FIRST_TOKEN), + create.Integer().Capture(CAPTURE_COLUMN_COUNT), + create.Loop(create.And({ + create.Integer().Capture(CAPTURE_X_POS), + create.Integer().Capture(CAPTURE_WIDTH), + create.Integer().Capture(CAPTURE_MAX_CHARS), + create.Integer().Capture(CAPTURE_ALIGNMENT), + })), + }); + } } protected: @@ -461,14 +511,14 @@ namespace menu::item_scope_sequences ItemScopeOperations::EnsureHasListboxFeatures(*state->m_current_item, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos()); const auto& listBoxFeatures = state->m_current_item->m_list_box_features; - while (result.HasNextCapture(CAPTURE_POS)) + while (result.HasNextCapture(CAPTURE_X_POS)) { CommonItemFeaturesListBox::Column column { - result.NextCapture(CAPTURE_POS).IntegerValue(), - 0, + result.NextCapture(CAPTURE_X_POS).IntegerValue(), + state->m_feature_level == FeatureLevel::IW5 ? result.NextCapture(CAPTURE_Y_POS).IntegerValue() : 0, result.NextCapture(CAPTURE_WIDTH).IntegerValue(), - 0, + state->m_feature_level == FeatureLevel::IW5 ? result.NextCapture(CAPTURE_HEIGHT).IntegerValue() : 0, result.NextCapture(CAPTURE_MAX_CHARS).IntegerValue(), result.NextCapture(CAPTURE_ALIGNMENT).IntegerValue() }; @@ -681,36 +731,28 @@ void ItemScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive { state->m_current_item->m_background = value; })); - AddSequence(std::make_unique("onFocus", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("onFocus", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_item->m_on_focus; })); - AddSequence(std::make_unique("leaveFocus", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("leaveFocus", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_item->m_on_leave_focus; })); - AddSequence(std::make_unique("mouseEnter", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("mouseEnter", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_item->m_on_mouse_enter; })); - AddSequence(std::make_unique("mouseExit", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("mouseExit", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_item->m_on_mouse_exit; })); - AddSequence(std::make_unique("mouseEnterText", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("mouseEnterText", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_item->m_on_mouse_enter_text; })); - AddSequence(std::make_unique("mouseExitText", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("mouseExitText", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_item->m_on_mouse_exit_text; })); - AddSequence(std::make_unique("action", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("action", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_item->m_on_action; })); - AddSequence(std::make_unique("accept", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("accept", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_item->m_on_accept; })); // special @@ -854,8 +896,19 @@ void ItemScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive state->m_current_item->m_backcolor_expressions.m_rgb_exp = std::move(value); })); + if (featureLevel == FeatureLevel::IW5) + { + AddSequence(std::make_unique("hasFocus", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { + return state->m_current_item->m_has_focus; + })); + AddSequence(GenericExpressionPropertySequence::WithKeywords({"exp", "textaligny"}, [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) + { + state->m_current_item->m_text_align_y_expression = std::move(value); + })); + } + // ============== ListBox ============== - AddSequence(std::make_unique()); + AddSequence(std::make_unique(featureLevel)); AddSequence(std::make_unique("notselectable", [](const MenuFileParserState* state, const TokenPos& pos) { ItemScopeOperations::EnsureHasListboxFeatures(*state->m_current_item, pos); @@ -891,8 +944,7 @@ void ItemScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive ItemScopeOperations::EnsureHasListboxFeatures(*state->m_current_item, pos); state->m_current_item->m_list_box_features->m_element_style = value; })); - AddSequence(std::make_unique("doubleclick", [](const MenuFileParserState* state, const TokenPos& pos) -> std::unique_ptr& - { + AddSequence(std::make_unique("doubleclick", [](const MenuFileParserState* state, const TokenPos& pos) -> std::unique_ptr& { ItemScopeOperations::EnsureHasListboxFeatures(*state->m_current_item, pos); return state->m_current_item->m_list_box_features->m_on_double_click; })); @@ -907,6 +959,15 @@ void ItemScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive state->m_current_item->m_list_box_features->m_select_icon = value; })); + if (featureLevel == FeatureLevel::IW5) + { + AddSequence(GenericExpressionPropertySequence::WithKeywords({"exp", "elementheight"}, [](const MenuFileParserState* state, const TokenPos& pos, std::unique_ptr value) + { + ItemScopeOperations::EnsureHasListboxFeatures(*state->m_current_item, pos); + state->m_current_item->m_list_box_features->m_element_height_expression = std::move(value); + })); + } + // ============== Edit Field ============== AddSequence(std::make_unique()); AddSequence(std::make_unique("localvar", [](const MenuFileParserState* state, const TokenPos& pos, const std::string& value) diff --git a/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp index 9f6a379b..22a6a20e 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp @@ -258,20 +258,16 @@ void MenuScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive { state->m_current_menu->m_visible_expression = std::move(value); })); - AddSequence(std::make_unique("onOpen", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("onOpen", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_menu->m_on_open; })); - AddSequence(std::make_unique("onClose", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("onClose", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_menu->m_on_close; })); - AddSequence(std::make_unique("onRequestClose", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("onRequestClose", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_menu->m_on_request_close; })); - AddSequence(std::make_unique("onESC", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& - { + AddSequence(std::make_unique("onESC", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { return state->m_current_menu->m_on_esc; })); AddSequence(std::make_unique("border", [](const MenuFileParserState* state, const TokenPos&, const int value) @@ -396,5 +392,19 @@ void MenuScopeSequences::AddSequences(FeatureLevel featureLevel, bool permissive { state->m_current_menu->m_text_only_focus = true; })); + + + if (featureLevel == FeatureLevel::IW5) + { + AddSequence(GenericExpressionPropertySequence::WithKeywords({"exp", "soundLoop"}, [](const MenuFileParserState* state, const TokenPos&, std::unique_ptr value) + { + state->m_current_menu->m_sound_loop_exp = std::move(value); + })); + AddSequence(std::make_unique("onFocusDueToClose", [](const MenuFileParserState* state, const TokenPos&) -> std::unique_ptr& { + return state->m_current_menu->m_on_focus_due_to_close; + })); + } + + AddSequence(std::make_unique()); } diff --git a/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.cpp b/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.cpp index 11898b54..5ca1cce1 100644 --- a/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.cpp +++ b/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.cpp @@ -492,6 +492,31 @@ void MenuDumper::WriteFloatExpressionsProperty(const ItemFloatExpression* floatE } } +void MenuDumper::WriteMultiTokenStringProperty(const std::string& propertyKey, const char* value) const +{ + if (!value) + return; + + Indent(); + WriteKey(propertyKey); + + const auto tokenList = CreateScriptTokenList(value); + + auto firstToken = true; + m_stream << "{ "; + for (const auto& token : tokenList) + { + if (firstToken) + firstToken = false; + else + m_stream << ";"; + m_stream << "\"" << token << "\""; + } + if (!firstToken) + m_stream << " "; + m_stream << "}\n"; +} + void MenuDumper::WriteColumnProperty(const std::string& propertyKey, const listBoxDef_s* listBox) const { if (listBox->numColumns <= 0) @@ -533,7 +558,7 @@ void MenuDumper::WriteListBoxProperties(const itemDef_s* item) WriteMenuEventHandlerSetProperty("doubleclick", listBox->onDoubleClick); WriteColorProperty("selectBorder", listBox->selectBorder, COLOR_0000); WriteMaterialProperty("selectIcon", listBox->selectIcon); - WriteStatementProperty("exp elementHeight", listBox->elementHeightExp, false); + WriteStatementProperty("exp elementheight", listBox->elementHeightExp, false); } void MenuDumper::WriteDvarFloatProperty(const std::string& propertyKey, const itemDef_s* item, const editFieldDef_s* editField) const @@ -659,9 +684,15 @@ void MenuDumper::WriteItemData(const itemDef_s* item) WriteIntProperty("type", item->type, ITEM_TYPE_TEXT); WriteIntProperty("border", item->window.border, 0); WriteFloatProperty("borderSize", item->window.borderSize, 0.0f); - WriteStatementProperty("visible", item->visibleExp, true); + + if (item->visibleExp) + WriteStatementProperty("visible", item->visibleExp, true); + else if (item->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) + WriteIntProperty("visible", 1, 0); + WriteStatementProperty("disabled", item->disabledExp, true); - WriteIntProperty("ownerDraw", item->window.ownerDraw, 0); + WriteIntProperty("ownerdraw", item->window.ownerDraw, 0); + WriteFlagsProperty("ownerdrawFlag", item->window.ownerDrawFlags); WriteIntProperty("align", item->alignment, 0); WriteIntProperty("textalign", item->textAlignMode, 0); WriteFloatProperty("textalignx", item->textalignx, 0.0f); @@ -687,19 +718,18 @@ void MenuDumper::WriteItemData(const itemDef_s* item) WriteMenuEventHandlerSetProperty("accept", item->accept); // WriteFloatProperty("special", item->special, 0.0f); WriteSoundAliasProperty("focusSound", item->focusSound); - WriteFlagsProperty("ownerdrawFlag", item->window.ownerDrawFlags); WriteStringProperty("dvarTest", item->dvarTest); if (item->dvarFlags & ITEM_DVAR_FLAG_ENABLE) - WriteStringProperty("enableDvar", item->enableDvar); + WriteMultiTokenStringProperty("enableDvar", item->enableDvar); else if (item->dvarFlags & ITEM_DVAR_FLAG_DISABLE) - WriteStringProperty("disableDvar", item->enableDvar); + WriteMultiTokenStringProperty("disableDvar", item->enableDvar); else if (item->dvarFlags & ITEM_DVAR_FLAG_SHOW) - WriteStringProperty("showDvar", item->enableDvar); + WriteMultiTokenStringProperty("showDvar", item->enableDvar); else if (item->dvarFlags & ITEM_DVAR_FLAG_HIDE) - WriteStringProperty("hideDvar", item->enableDvar); + WriteMultiTokenStringProperty("hideDvar", item->enableDvar); else if (item->dvarFlags & ITEM_DVAR_FLAG_FOCUS) - WriteStringProperty("focusDvar", item->enableDvar); + WriteMultiTokenStringProperty("focusDvar", item->enableDvar); WriteItemKeyHandlerProperty(item->onKey); WriteStatementProperty("exp text", item->textExp, false); @@ -744,6 +774,7 @@ void MenuDumper::WriteMenuData(const menuDef_t* menu) WriteColorProperty("forecolor", menu->window.foreColor, COLOR_1111); WriteColorProperty("bordercolor", menu->window.borderColor, COLOR_0000); WriteColorProperty("focuscolor", menu->data->focusColor, COLOR_0000); + WriteColorProperty("outlinecolor", menu->window.outlineColor, COLOR_0000); WriteMaterialProperty("background", menu->window.background); WriteIntProperty("ownerdraw", menu->window.ownerDraw, 0); WriteFlagsProperty("ownerdrawFlag", menu->window.ownerDrawFlags); @@ -761,7 +792,12 @@ void MenuDumper::WriteMenuData(const menuDef_t* menu) WriteKeywordProperty("hiddenDuringUI", menu->window.staticFlags & WINDOW_FLAG_HIDDEN_DURING_UI); WriteStringProperty("allowedBinding", menu->data->allowedBinding); WriteKeywordProperty("textOnlyFocus", menu->window.staticFlags & WINDOW_FLAG_TEXT_ONLY_FOCUS); - WriteStatementProperty("visible", menu->data->visibleExp, true); + + if (menu->data->visibleExp) + WriteStatementProperty("visible", menu->data->visibleExp, true); + else if (menu->window.dynamicFlags[0] & WINDOW_FLAG_VISIBLE) + WriteIntProperty("visible", 1, 0); + WriteStatementProperty("exp rect X", menu->data->rectXExp, false); WriteStatementProperty("exp rect Y", menu->data->rectYExp, false); WriteStatementProperty("exp rect W", menu->data->rectWExp, false); diff --git a/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h b/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h index 1ead711f..b9fe76a8 100644 --- a/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h +++ b/src/ObjWriting/Game/IW5/Menu/MenuDumperIW5.h @@ -29,6 +29,7 @@ namespace IW5 void WriteSoundAliasProperty(const std::string& propertyKey, const snd_alias_list_t* soundAliasValue) const; void WriteDecodeEffectProperty(const std::string& propertyKey, const itemDef_s* item) const; void WriteItemKeyHandlerProperty(const ItemKeyHandler* itemKeyHandlerValue); + void WriteMultiTokenStringProperty(const std::string& propertyKey, const char* value) const; void WriteFloatExpressionsProperty(const ItemFloatExpression* floatExpressions, int floatExpressionCount) const; void WriteColumnProperty(const std::string& propertyKey, const listBoxDef_s* listBox) const;