From 0c7d8bdad498555628ac0ba3cc1c3aa5538645a0 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:45:40 -0400 Subject: [PATCH] Add in-game options button visibility configuration Default available options are:"On", "Opacity: 50%", and "Off" (hides the button entirely) --- src/configuration.cpp | 2 ++ src/frontend.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++ src/frontend.h | 2 ++ src/hci.cpp | 53 ++++++++++++++++++++++++++++++++++++------- src/warzoneconfig.cpp | 20 ++++++++++++++-- src/warzoneconfig.h | 4 +++- 6 files changed, 122 insertions(+), 11 deletions(-) diff --git a/src/configuration.cpp b/src/configuration.cpp index 8b0d1176eab..82576ebfc61 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -387,6 +387,7 @@ bool loadConfig() setShakeStatus(iniGetBool("shake", false).value()); war_setGroupsMenuEnabled(iniGetBool("groupmenu", true).value()); setGroupButtonEnabled(war_getGroupsMenuEnabled()); + war_setOptionsButtonVisibility(iniGetInteger("optionsButtonVisibility", war_getOptionsButtonVisibility()).value()); setCameraAccel(iniGetBool("cameraAccel", true).value()); setDrawShadows(iniGetBool("shadows", true).value()); war_setSoundEnabled(iniGetBool("sound", true).value()); @@ -687,6 +688,7 @@ bool saveConfig() iniSetBool("cameraAccel", getCameraAccel()); // camera acceleration iniSetInteger("shake", (int)getShakeStatus()); // screenshake iniSetInteger("groupmenu", (int)war_getGroupsMenuEnabled()); // groups menu + iniSetInteger("optionsButtonVisibility", (int)war_getOptionsButtonVisibility()); iniSetInteger("mouseflip", (int)(getInvertMouseStatus())); // flipmouse iniSetInteger("nomousewarp", (int)getMouseWarp()); // mouse warp iniSetInteger("coloredCursor", (int)war_GetColouredCursor()); diff --git a/src/frontend.cpp b/src/frontend.cpp index 99feb92db89..606dfb341fb 100644 --- a/src/frontend.cpp +++ b/src/frontend.cpp @@ -1062,6 +1062,53 @@ static std::shared_ptr makeShadowFilterSizeDropdown() return Margin(0, 10).wrap(dropdown); } +static std::shared_ptr makeOptionsButtonDropdown() +{ + std::vector> dropDownChoices = { + {WzString::fromUtf8(_("On")), 100}, + {WzString::fromUtf8(_("Opacity: 50%")), 50}, + {WzString::fromUtf8(_("Off")), 0} + }; + + // If current value (from config) is not one of the presets in dropDownChoices, add a "Custom" entry + size_t currentSettingIdx = 0; + uint8_t currValue = war_getOptionsButtonVisibility(); + auto it = std::find_if(dropDownChoices.begin(), dropDownChoices.end(), [currValue](const std::tuple& item) -> bool { + return std::get<1>(item) == currValue; + }); + if (it != dropDownChoices.end()) + { + currentSettingIdx = it - dropDownChoices.begin(); + } + else + { + dropDownChoices.push_back({WzString::fromUtf8(astringf("(Custom: %u)", currValue)), currValue}); + currentSettingIdx = dropDownChoices.size() - 1; + } + + auto dropdown = std::make_shared(); + dropdown->id = FRONTEND_INGAMEOPTIONS_BUTTON_DROPDOWN; + dropdown->setListHeight(FRONTEND_BUTHEIGHT * std::min(5, dropDownChoices.size())); + const auto paddingSize = 10; + + for (const auto& option : dropDownChoices) + { + auto item = makeTextButton(0, std::get<0>(option).toUtf8(), 0); + dropdown->addItem(Margin(0, paddingSize).wrap(item)); + } + + dropdown->setSelectedIndex(currentSettingIdx); + + dropdown->setCanChange([dropDownChoices](DropdownWidget &widget, size_t newIndex, std::shared_ptr newSelectedWidget) -> bool { + ASSERT_OR_RETURN(false, newIndex < dropDownChoices.size(), "Invalid index"); + auto newValue = std::get<1>(dropDownChoices.at(newIndex)); + war_setOptionsButtonVisibility(newValue); + return true; + }); + + return Margin(0, 10).wrap(dropdown); +} + // //////////////////////////////////////////////////////////////////////////// // Graphics Options void startGraphicsOptionsMenu() @@ -1163,6 +1210,11 @@ void startGraphicsOptionsMenu() grid->place({1, 1, false}, row, addMargin(makeTextButton(FRONTEND_GROUPS_R, graphicsOptionsGroupsMenuEnabled(), WBUT_SECONDARY))); row.start++; + // In-Game Options button + grid->place({0}, row, addMargin(makeTextButton(FRONTEND_INGAMEOPTIONS_BUTTON, _("Options Button"), WBUT_SECONDARY))); + grid->place({1, 1, false}, row, makeOptionsButtonDropdown()); + row.start++; + grid->setGeometry(0, 0, FRONTEND_BUTWIDTH, grid->idealHeight()); auto scrollableList = ScrollableListWidget::make(); diff --git a/src/frontend.h b/src/frontend.h index 18719feca5c..2a1e27562b4 100644 --- a/src/frontend.h +++ b/src/frontend.h @@ -310,6 +310,8 @@ enum FRONTEND_TERRAIN_SHADING_QUALITY_R, FRONTEND_GROUPS, FRONTEND_GROUPS_R, + FRONTEND_INGAMEOPTIONS_BUTTON, + FRONTEND_INGAMEOPTIONS_BUTTON_DROPDOWN, FRONTEND_AUDIO_AND_ZOOMOPTIONS = 23000, // Audio and Zoom Options Menu FRONTEND_3D_FX, // 3d sound volume diff --git a/src/hci.cpp b/src/hci.cpp index 490ebf68765..bb4f0aeed91 100644 --- a/src/hci.cpp +++ b/src/hci.cpp @@ -1,7 +1,7 @@ /* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive - Copyright (C) 2005-2020 Warzone 2100 Project + Copyright (C) 2005-2024 Warzone 2100 Project Warzone 2100 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -85,6 +85,7 @@ #include "screens/chatscreen.h" #include "screens/guidescreen.h" #include "hci/quickchat.h" +#include "warzoneconfig.h" // Empty edit window static bool secondaryWindowUp = false; @@ -2159,6 +2160,10 @@ class W_INGAMEOPTIONS_BUTTON : public W_BUTTON void display(int xOffset, int yOffset) override; std::string getTip() override; + +private: + uint8_t currentAlphaValue() const; + bool isHighlighted() const; }; std::shared_ptr W_INGAMEOPTIONS_BUTTON::make() @@ -2175,32 +2180,50 @@ void W_INGAMEOPTIONS_BUTTON::initialize() setGeometry(0, 0, RET_BUTWIDTH, RET_BUTHEIGHT); } +uint8_t W_INGAMEOPTIONS_BUTTON::currentAlphaValue() const +{ + uint32_t alphaPercentage = war_getOptionsButtonVisibility(); + + if (isHighlighted()) + { + alphaPercentage = 100; + } + + return static_cast((alphaPercentage * 255) / 100); +} + +bool W_INGAMEOPTIONS_BUTTON::isHighlighted() const +{ + return ((getState() & WBUT_HIGHLIGHT) != 0) || InGameOpUp; +} + void W_INGAMEOPTIONS_BUTTON::display(int xOffset, int yOffset) { const int x0 = xOffset + x(); const int y0 = yOffset + y(); bool butDisabled = getState() & WBUT_DISABLE; + uint8_t alphaValue = currentAlphaValue(); + if (butDisabled) { - iV_DrawImage2("image_reticule_grey.png", x0, y0, width(), height()); + iV_DrawImageTint(IntImages, IMAGE_RETICULE_GREY, x0, y0, pal_RGBA(255,255,255,alphaValue), Vector2f{width(), height()}); return; } bool Down = getState() & (WBUT_DOWN | WBUT_CLICKLOCK); if (Down) { - iV_DrawImage2("image_ingameoptions_down.png", x0, y0, width(), height()); + iV_DrawImageTint(IntImages, IMAGE_INGAMEOPTIONS_DOWN, x0, y0, pal_RGBA(255,255,255,alphaValue), Vector2f{width(), height()}); } else { - iV_DrawImage2("image_ingameoptions_up.png", x0, y0, width(), height()); + iV_DrawImageTint(IntImages, IMAGE_INGAMEOPTIONS_UP, x0, y0, pal_RGBA(255,255,255,alphaValue), Vector2f{width(), height()}); } - bool highlighted = ((getState() & WBUT_HIGHLIGHT) != 0) || InGameOpUp; - if (highlighted) + if (isHighlighted()) { - iV_DrawImage2("image_reticule_hilight.png", x0, y0, width(), height()); + iV_DrawImageTint(IntImages, IMAGE_RETICULE_HILIGHT, x0, y0, pal_RGBA(255,255,255,alphaValue), Vector2f{width(), height()}); } } @@ -2218,10 +2241,19 @@ std::string W_INGAMEOPTIONS_BUTTON::getTip() bool intAddInGameOptionsButton() { + bool hiddenOptionsButton = war_getOptionsButtonVisibility() == 0; + auto psExistingBut = widgGetFromID(psWScreen, IDRET_OPTIONS); if (psExistingBut != nullptr) { - psExistingBut->show(); + if (!hiddenOptionsButton) + { + psExistingBut->show(); + } + else + { + psExistingBut->hide(); + } return false; } @@ -2246,6 +2278,11 @@ bool intAddInGameOptionsButton() kf_addInGameOptions(); }); }); + + if (hiddenOptionsButton) + { + button->hide(); + } } return true; diff --git a/src/warzoneconfig.cpp b/src/warzoneconfig.cpp index de95984cae8..b2f4b3fe64a 100644 --- a/src/warzoneconfig.cpp +++ b/src/warzoneconfig.cpp @@ -1,7 +1,7 @@ /* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive - Copyright (C) 2005-2020 Warzone 2100 Project + Copyright (C) 2005-2024 Warzone 2100 Project Warzone 2100 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -97,8 +97,9 @@ struct WARZONE_GLOBALS uint32_t shadowFilterSize = 5; uint32_t shadowMapResolution = 0; // this defaults to 0, which causes the gfx backend to figure out a recommended default based on the system properties bool pointLightLighting = false; - // groups UI + // UI config bool groupsMenuEnabled = true; + uint8_t optionsButtonVisibility = 100; // run-time only settings (not persisted to config!) bool allowVulkanImplicitLayers = false; @@ -698,6 +699,21 @@ void war_runtimeOnlySetAllowVulkanImplicitLayers(bool allowed) // not persisted warGlobs.allowVulkanImplicitLayers = allowed; } +uint8_t war_getOptionsButtonVisibility() +{ + return warGlobs.optionsButtonVisibility; +} + +void war_setOptionsButtonVisibility(uint8_t val) +{ + val = std::min(val, 100); + if (val > 0) + { + val = std::max(val, 50); + } + warGlobs.optionsButtonVisibility = val; +} + bool war_getAllowVulkanImplicitLayers() { return warGlobs.allowVulkanImplicitLayers; diff --git a/src/warzoneconfig.h b/src/warzoneconfig.h index 6ebb79189c7..e302439d538 100644 --- a/src/warzoneconfig.h +++ b/src/warzoneconfig.h @@ -1,7 +1,7 @@ /* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive - Copyright (C) 2005-2020 Warzone 2100 Project + Copyright (C) 2005-2024 Warzone 2100 Project Warzone 2100 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -169,6 +169,8 @@ void war_setPointLightPerPixelLighting(bool perPixelEnabled); bool war_getGroupsMenuEnabled(); void war_setGroupsMenuEnabled(bool enabled); +uint8_t war_getOptionsButtonVisibility(); +void war_setOptionsButtonVisibility(uint8_t val); void war_runtimeOnlySetAllowVulkanImplicitLayers(bool allowed); // not persisted to config bool war_getAllowVulkanImplicitLayers();