From 717e265c193193fed0d49cd21be4396baa3304a1 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 1 Oct 2022 13:06:20 +0100 Subject: [PATCH] Add checkboxes to asset pack window --- data/language/en-GB.txt | 2 + src/openrct2-ui/windows/AssetPacks.cpp | 178 ++++++++++++++++++++----- src/openrct2/localisation/StringIds.h | 2 + 3 files changed, 147 insertions(+), 35 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 740cc28723..8df376085a 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3625,6 +3625,8 @@ STR_6517 :One or more objects in this park require RCT1 linked for proper dis STR_6518 :{BLACK}Hover over a scenario to view its description and objective. Click it to start playing. STR_6519 :Extras STR_6520 :Asset Packs +STR_6521 :Low Priority +STR_6522 :High Priority ############# # Scenarios # diff --git a/src/openrct2-ui/windows/AssetPacks.cpp b/src/openrct2-ui/windows/AssetPacks.cpp index e0a577e8b9..fe94ef86a8 100644 --- a/src/openrct2-ui/windows/AssetPacks.cpp +++ b/src/openrct2-ui/windows/AssetPacks.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,8 @@ static rct_widget WindowAssetPacksWidgets[] = { class AssetPacksWindow final : public Window { private: + static constexpr int32_t ItemHeight = SCROLLABLE_ROW_HEIGHT + 1; + static constexpr int32_t ItemCheckBoxSize = ItemHeight - 3; std::optional _highlightedIndex; std::optional _selectedIndex; @@ -91,8 +95,8 @@ public: auto assetPackManager = GetContext()->GetAssetPackManager(); if (assetPackManager != nullptr) { - auto numAssetPacks = assetPackManager->GetCount(); - result.height = static_cast(numAssetPacks * SCROLLABLE_ROW_HEIGHT); + auto numAssetPacks = assetPackManager->GetCount() + 2; // Add 2 for separators + result.height = static_cast(numAssetPacks * ItemHeight); } if (_highlightedIndex) @@ -106,26 +110,39 @@ public: void OnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override { - const auto index = screenCoords.y / SCROLLABLE_ROW_HEIGHT; - if (index < 0 || static_cast(index) >= GetNumAssetPacks()) - return; + auto isCheckBox = false; + auto index = GetAssetPackIndexFromPosition(screenCoords, isCheckBox); - if (_selectedIndex != static_cast(index)) + // Click on checkbox + if (index && isCheckBox) { - _selectedIndex = static_cast(index); + auto assetPackManager = GetContext()->GetAssetPackManager(); + if (assetPackManager != nullptr) + { + auto assetPack = assetPackManager->GetAssetPack(*index); + if (assetPack != nullptr) + { + assetPack->SetEnabled(!assetPack->IsEnabled()); + Invalidate(); + } + } + } + + // Select item + if (_selectedIndex != index) + { + _selectedIndex = index; Invalidate(); } } void OnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override { - const auto index = screenCoords.y / SCROLLABLE_ROW_HEIGHT; - if (index < 0 || static_cast(index) >= GetNumAssetPacks()) - return; - - if (_highlightedIndex != static_cast(index)) + auto isCheckBox = false; + auto index = GetAssetPackIndexFromPosition(screenCoords, isCheckBox); + if (_highlightedIndex != index) { - _highlightedIndex = static_cast(index); + _highlightedIndex = index; Invalidate(); } } @@ -185,40 +202,131 @@ public: return; auto numAssetPacks = assetPackManager->GetCount(); - for (size_t i = 0; i < numAssetPacks; i++) + for (size_t i = 0; i <= numAssetPacks + 1; i++) { if (y > dpi.y + dpi.height) break; if (y + 11 < dpi.y) continue; - auto assetPack = assetPackManager->GetAssetPack(i); - if (assetPack != nullptr) + if (i == 0 || i == numAssetPacks + 1) { - auto stringId = STR_BLACK_STRING; - auto fillRectangle = ScreenRect{ { 0, y }, { listWidth, y + SCROLLABLE_ROW_HEIGHT - 1 } }; - if (i == _selectedIndex) - { - gfx_fill_rect(&dpi, fillRectangle, ColourMapA[colours[1]].mid_dark); - stringId = STR_WINDOW_COLOUR_2_STRINGID; - } - else if (i == _highlightedIndex) - { - gfx_fill_rect(&dpi, fillRectangle, ColourMapA[colours[1]].mid_dark); - } - - auto ft = Formatter(); - ft.Add(assetPack->IsEnabled() ? STR_TOGGLE_OPTION_CHECKED : STR_TOGGLE_OPTION); - ft.Add(STR_STRING); - ft.Add(assetPack->Name.c_str()); - DrawTextEllipsised(&dpi, { 0, y }, listWidth, stringId, ft); + auto text = i == 0 ? STR_LOW_PRIORITY : STR_HIGH_PRIORITY; + PaintSeperator(dpi, { 0, y }, { listWidth, y + ItemHeight - 1 }, text); } + else + { + auto assetPackIndex = i - 1; + auto assetPack = assetPackManager->GetAssetPack(assetPackIndex); + if (assetPack != nullptr) + { + auto stringId = STR_BLACK_STRING; + auto fillRectangle = ScreenRect{ { 0, y }, { listWidth, y + ItemHeight - 1 } }; + if (assetPackIndex == _selectedIndex) + { + gfx_fill_rect(&dpi, fillRectangle, ColourMapA[colours[1]].mid_dark); + stringId = STR_WINDOW_COLOUR_2_STRINGID; + } + else if (assetPackIndex == _highlightedIndex) + { + gfx_fill_rect(&dpi, fillRectangle, ColourMapA[colours[1]].mid_dark); + } - y += SCROLLABLE_ROW_HEIGHT; + auto ft = Formatter(); + ft.Add(STR_STRING); + ft.Add(assetPack->Name.c_str()); + DrawTextEllipsised(&dpi, { 16, y + 1 }, listWidth, stringId, ft); + + auto checkboxSize = ItemHeight - 3; + PaintCheckbox( + dpi, { { 2, y + 1 }, { 2 + checkboxSize + 1, y + 1 + checkboxSize } }, assetPack->IsEnabled()); + } + } + y += ItemHeight; } } private: + void PaintSeperator(rct_drawpixelinfo& dpi, const ScreenCoordsXY& pos, const ScreenSize& size, StringId text) const + { + auto hasText = text != STR_NONE; + auto left = pos.x + 4; + auto right = pos.x + size.width - 4; + auto centreX = size.width / 2; + auto lineY0 = pos.y + 5; + auto lineY1 = lineY0 + 1; + + auto baseColour = colours[1]; + auto lightColour = ColourMapA[baseColour].lighter; + auto darkColour = ColourMapA[baseColour].mid_dark; + + if (hasText) + { + // Draw string + Formatter ft; + ft.Add(text); + DrawTextBasic(&dpi, { centreX, pos.y }, STR_STRINGID, ft, { baseColour, TextAlignment::CENTRE }); + + // Get string dimensions + format_string(gCommonStringFormatBuffer, sizeof(gCommonStringFormatBuffer), STR_STRING, ft.Data()); + int32_t categoryStringHalfWidth = (gfx_get_string_width(gCommonStringFormatBuffer, FontSpriteBase::MEDIUM) / 2) + 4; + int32_t strLeft = centreX - categoryStringHalfWidth; + int32_t strRight = centreX + categoryStringHalfWidth; + + // Draw light horizontal rule + auto lightLineLeftTop1 = ScreenCoordsXY{ left, lineY0 }; + auto lightLineRightBottom1 = ScreenCoordsXY{ strLeft, lineY0 }; + gfx_draw_line(&dpi, { lightLineLeftTop1, lightLineRightBottom1 }, lightColour); + + auto lightLineLeftTop2 = ScreenCoordsXY{ strRight, lineY0 }; + auto lightLineRightBottom2 = ScreenCoordsXY{ right, lineY0 }; + gfx_draw_line(&dpi, { lightLineLeftTop2, lightLineRightBottom2 }, lightColour); + + // Draw dark horizontal rule + auto darkLineLeftTop1 = ScreenCoordsXY{ left, lineY1 }; + auto darkLineRightBottom1 = ScreenCoordsXY{ strLeft, lineY1 }; + gfx_draw_line(&dpi, { darkLineLeftTop1, darkLineRightBottom1 }, darkColour); + + auto darkLineLeftTop2 = ScreenCoordsXY{ strRight, lineY1 }; + auto darkLineRightBottom2 = ScreenCoordsXY{ right, lineY1 }; + gfx_draw_line(&dpi, { darkLineLeftTop2, darkLineRightBottom2 }, darkColour); + } + else + { + // Draw light horizontal rule + auto lightLineLeftTop1 = ScreenCoordsXY{ left, lineY0 }; + auto lightLineRightBottom1 = ScreenCoordsXY{ right, lineY0 }; + gfx_draw_line(&dpi, { lightLineLeftTop1, lightLineRightBottom1 }, lightColour); + + // Draw dark horizontal rule + auto darkLineLeftTop1 = ScreenCoordsXY{ left, lineY1 }; + auto darkLineRightBottom1 = ScreenCoordsXY{ right, lineY1 }; + gfx_draw_line(&dpi, { darkLineLeftTop1, darkLineRightBottom1 }, darkColour); + } + } + + void PaintCheckbox(rct_drawpixelinfo& dpi, const ScreenRect& rect, bool checked) + { + gfx_fill_rect_inset(&dpi, rect, colours[1], INSET_RECT_F_E0); + if (checked) + { + auto checkmark = Formatter(); + checkmark.Add(STR_STRING); + checkmark.Add(CheckBoxMarkString); + DrawTextBasic(&dpi, ScreenCoordsXY{ rect.GetLeft() + 1, rect.GetTop() }, STR_WINDOW_COLOUR_2_STRINGID, checkmark); + } + } + + std::optional GetAssetPackIndexFromPosition(const ScreenCoordsXY& pos, bool& isCheckBox) + { + const auto index = (pos.y / ItemHeight) - 1; + if (index < 0 || static_cast(index) >= GetNumAssetPacks()) + return {}; + + isCheckBox = pos.x >= 2 && pos.x <= 2 + ItemCheckBoxSize + 1; + return static_cast(index); + } + size_t GetNumAssetPacks() const { auto assetPackManager = GetContext()->GetAssetPackManager(); @@ -276,7 +384,7 @@ private: (*_selectedIndex)--; Invalidate(); } - else if (*_selectedIndex < assetPackManager->GetCount() - 1) + else if (direction > 0 && *_selectedIndex < assetPackManager->GetCount() - 1) { assetPackManager->Swap(*_selectedIndex, *_selectedIndex + 1); (*_selectedIndex)++; diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 5d84e522de..97a0df4d10 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3908,6 +3908,8 @@ enum : uint16_t STR_SCENARIO_CATEGORY_EXTRAS_PARKS = 6519, STR_ASSET_PACKS = 6520, + STR_LOW_PRIORITY = 6521, + STR_HIGH_PRIORITY = 6522, // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working /* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings