From 43bcd2cf073acbca1fba97653ad5f8a62f797337 Mon Sep 17 00:00:00 2001 From: karst Date: Fri, 13 Jan 2023 23:46:16 +0100 Subject: [PATCH] Add tab to About window to show contributors.md Co-authored-by: Gymnasiast --- data/language/en-GB.txt | 5 +- src/openrct2-ui/windows/About.cpp | 77 +++++++++++++++++++++++++-- src/openrct2/PlatformEnvironment.cpp | 4 +- src/openrct2/PlatformEnvironment.h | 1 + src/openrct2/localisation/StringIds.h | 1 + 5 files changed, 82 insertions(+), 6 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 2e2b0fbcf0..07cffdf116 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3281,8 +3281,8 @@ STR_6133 :Access rides and scenery that have not yet been invented STR_6134 :Clear Scenery STR_6135 :Client sent invalid request STR_6136 :Server sent invalid request -STR_6137 :OpenRCT2, a free and open source clone of Roller Coaster Tycoon 2. -STR_6138 :OpenRCT2 is the work of many authors, a full list can be found in “contributors.md”. For more information, visit http://github.com/OpenRCT2/OpenRCT2 +STR_6137 :A free and open source recreation of and expansion to Roller Coaster Tycoon 2. +STR_6138 :For more information, visit http://github.com/OpenRCT2/OpenRCT2 STR_6139 :All product and company names belong to their respective holders. Use of them does not imply any affiliation with or endorsement by them. STR_6140 :Changelog… STR_6141 :RCT1 Bottom Toolbar @@ -3644,6 +3644,7 @@ STR_6538 :Shows regular paths in the queues dropdown of the Footpaths window. STR_6539 :Brake Closed STR_6540 :{WINDOW_COLOUR_2}Special thanks to the following companies for allowing their likeness: STR_6541 :{WINDOW_COLOUR_2}Rocky Mountain Construction Group, Josef Wiegand GmbH & Co. KG +STR_6542 :{WINDOW_COLOUR_2}Contributors ############# # Scenarios # diff --git a/src/openrct2-ui/windows/About.cpp b/src/openrct2-ui/windows/About.cpp index 251e3e6cfc..1f118a3dcd 100644 --- a/src/openrct2-ui/windows/About.cpp +++ b/src/openrct2-ui/windows/About.cpp @@ -6,12 +6,16 @@ * * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ + #include +#include #include #include #include #include +#include #include +#include #include #include #include @@ -31,6 +35,7 @@ enum { WINDOW_ABOUT_PAGE_OPENRCT2, WINDOW_ABOUT_PAGE_RCT2, + WINDOW_ABOUT_PAGE_CONTRIBUTORS, }; enum WindowAboutWidgetIdx { @@ -40,6 +45,7 @@ enum WindowAboutWidgetIdx { WIDX_PAGE_BACKGROUND, WIDX_TAB_ABOUT_OPENRCT2, WIDX_TAB_ABOUT_RCT2, + WIDX_TAB_ABOUT_CONTRIBUTORS, WIDX_PAGE_START, @@ -59,7 +65,8 @@ enum WindowAboutWidgetIdx { WINDOW_SHIM(WINDOW_TITLE, WW, WH), \ MakeWidget ({ 0, TABHEIGHT}, {WW, WH - TABHEIGHT}, WindowWidgetType::Frame, WindowColour::Secondary ), /* page background */ \ MakeRemapWidget({ 3, 17}, {91, TABHEIGHT - 16}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB_LARGE), /* about OpenRCT2 button */ \ - MakeRemapWidget({94, 17}, {91, TABHEIGHT - 16}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB_LARGE) /* about RCT2 button */ + MakeRemapWidget({94, 17}, {91, TABHEIGHT - 16}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB_LARGE), /* about RCT2 button */ \ + MakeRemapWidget({185, 17}, {91, TABHEIGHT - 16}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB_LARGE) /* Contributors button */ static Widget _windowAboutOpenRCT2Widgets[] = { WIDGETS_MAIN, @@ -70,7 +77,7 @@ static Widget _windowAboutOpenRCT2Widgets[] = { MakeWidget({168, 115 + 24}, {200, 14}, WindowWidgetType::Placeholder, WindowColour::Secondary, STR_UPDATE_AVAILABLE ), // "new version" button MakeWidget({168, 115 + 48}, {200, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_CHANGELOG_ELLIPSIS), // changelog button MakeWidget({168, 115 + 72}, {200, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_JOIN_DISCORD ), // "join discord" button - MakeWidget({10, 250}, {WW - 20, 50}, WindowWidgetType::LabelCentred, WindowColour::Secondary, STR_ABOUT_OPENRCT2_DESCRIPTION_2), // Contributors + MakeWidget({10, 250}, {WW - 20, 50}, WindowWidgetType::LabelCentred, WindowColour::Secondary, STR_ABOUT_OPENRCT2_DESCRIPTION_2), // More info MakeWidget({10, 300}, {WW - 20, 50}, WindowWidgetType::LabelCentred, WindowColour::Secondary, STR_ABOUT_OPENRCT2_DESCRIPTION_3), // Copyright MakeWidget({10, 350}, {WW - 20, 50}, WindowWidgetType::LabelCentred, WindowColour::Secondary, STR_ABOUT_SPECIAL_THANKS_1), // Special Thanks MakeWidget({10, 375}, {WW - 20, 50}, WindowWidgetType::LabelCentred, WindowColour::Secondary, STR_ABOUT_SPECIAL_THANKS_2), // Company names @@ -82,13 +89,37 @@ static Widget _windowAboutRCT2Widgets[] = { WIDGETS_END, }; +static Widget _windowAboutContributorsWidgets[] = { + WIDGETS_MAIN, + MakeWidget({10, 60}, {WW - 20, 282}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_BOTH ), // scroll area + WIDGETS_END, +}; + static Widget *_windowAboutPageWidgets[] = { _windowAboutOpenRCT2Widgets, _windowAboutRCT2Widgets, + _windowAboutContributorsWidgets, }; // clang-format on +static std::string GetContributorsPath() +{ + auto env = GetContext()->GetPlatformEnvironment(); + return env->GetFilePath(PATHID::CONTRIBUTORS); +} + +static const std::string GetContributorsText() +{ + auto path = GetContributorsPath(); + auto fs = std::ifstream(fs::u8path(path), std::ios::in); + if (!fs.is_open()) + { + throw std::runtime_error("Unable to open " + path); + } + return std::string((std::istreambuf_iterator(fs)), std::istreambuf_iterator()); +} + class AboutWindow final : public Window { public: @@ -109,6 +140,7 @@ public: break; case WIDX_TAB_ABOUT_OPENRCT2: case WIDX_TAB_ABOUT_RCT2: + case WIDX_TAB_ABOUT_CONTRIBUTORS: SetPage(widgetIndex - WIDX_TAB_ABOUT_OPENRCT2); break; case WIDX_JOIN_DISCORD: @@ -132,10 +164,12 @@ public: const auto& aboutOpenRCT2 = widgets[WIDX_TAB_ABOUT_OPENRCT2]; const auto& aboutRCT2 = widgets[WIDX_TAB_ABOUT_RCT2]; + const auto& aboutContributors = widgets[WIDX_TAB_ABOUT_CONTRIBUTORS]; int32_t y = windowPos.y + aboutOpenRCT2.midY() - 3; ScreenCoordsXY aboutOpenRCT2Coords(windowPos.x + aboutOpenRCT2.left + 45, y); ScreenCoordsXY aboutRCT2Coords(windowPos.x + aboutRCT2.left + 45, y); + ScreenCoordsXY aboutContributorsCoords(windowPos.x + aboutContributors.left + 45, y); // Draw tab names { @@ -150,6 +184,13 @@ public: DrawTextWrapped( &dpi, aboutRCT2Coords, 87, STR_WINDOW_COLOUR_2_STRINGID, ft, { COLOUR_AQUAMARINE, TextAlignment::CENTRE }); } + { + auto ft = Formatter(); + ft.Add(STR_TAB_CONTRIBUTORS); + DrawTextWrapped( + &dpi, aboutContributorsCoords, 87, STR_WINDOW_COLOUR_2_STRINGID, ft, + { COLOUR_AQUAMARINE, TextAlignment::CENTRE }); + } if (page == WINDOW_ABOUT_PAGE_OPENRCT2) { @@ -159,6 +200,10 @@ public: { DrawRCT2Info(dpi); } + else if (page == WINDOW_ABOUT_PAGE_CONTRIBUTORS) + { + DrawContributorsInfo(dpi); + } } private: @@ -172,7 +217,19 @@ private: pressed_widgets = 0; widgets = _windowAboutPageWidgets[p]; - pressed_widgets |= (p == WINDOW_ABOUT_PAGE_RCT2) ? (1uLL << WIDX_TAB_ABOUT_RCT2) : (1uLL << WIDX_TAB_ABOUT_OPENRCT2); + switch (p) + { + case WINDOW_ABOUT_PAGE_OPENRCT2: + pressed_widgets |= (1uLL << WIDX_TAB_ABOUT_OPENRCT2); + break; + case WINDOW_ABOUT_PAGE_RCT2: + pressed_widgets |= (1uLL << WIDX_TAB_ABOUT_RCT2); + break; + case WINDOW_ABOUT_PAGE_CONTRIBUTORS: + pressed_widgets |= (1uLL << WIDX_TAB_ABOUT_CONTRIBUTORS); + break; + } + WindowInitScrollWidgets(*this); Invalidate(); } @@ -243,6 +300,20 @@ private: // Licence } + + void DrawContributorsInfo(rct_drawpixelinfo& dpi) + { + int32_t yPage = windowPos.y + widgets[WIDX_PAGE_BACKGROUND].top + 5; + + auto screenCoords = ScreenCoordsXY{ windowPos.x + 15, yPage }; + + int32_t lineHeight = font_get_line_height(FontStyle::Medium); + + auto text = GetContributorsText(); + + screenCoords.y += lineHeight; + gfx_draw_string(&dpi, screenCoords, text.c_str(), { colours[0] }); + }; }; /** diff --git a/src/openrct2/PlatformEnvironment.cpp b/src/openrct2/PlatformEnvironment.cpp index 4996c1b48d..d5e4e977a3 100644 --- a/src/openrct2/PlatformEnvironment.cpp +++ b/src/openrct2/PlatformEnvironment.cpp @@ -135,6 +135,7 @@ private: case PATHID::SCORES_RCT2: return DIRBASE::RCT2; case PATHID::CHANGELOG: + case PATHID::CONTRIBUTORS: return DIRBASE::DOCUMENTATION; case PATHID::NETWORK_GROUPS: case PATHID::NETWORK_SERVERS: @@ -285,5 +286,6 @@ const u8string PlatformEnvironment::FileNames[] = { u8"scores.dat", // SCORES (LEGACY) u8"Saved Games" PATH_SEPARATOR "scores.dat", // SCORES (RCT2) u8"changelog.txt", // CHANGELOG - u8"plugin.store.json" // PLUGIN_STORE + u8"plugin.store.json", // PLUGIN_STORE + u8"contributors.md", // CONTRIBUTORS }; diff --git a/src/openrct2/PlatformEnvironment.h b/src/openrct2/PlatformEnvironment.h index 0e63d8be7d..01b2a00127 100644 --- a/src/openrct2/PlatformEnvironment.h +++ b/src/openrct2/PlatformEnvironment.h @@ -70,6 +70,7 @@ namespace OpenRCT2 SCORES_RCT2, // Scenario scores, rct2 (\Saved Games\scores.dat). CHANGELOG, // Notable changes to the game between versions, distributed with the game. PLUGIN_STORE, // Shared storage for plugins. + CONTRIBUTORS, // Who has provided work to the game (Contributors.md). }; /** diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 3c6f572229..f9c2562a0b 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3935,6 +3935,7 @@ enum : uint16_t STR_ABOUT_SPECIAL_THANKS_1 = 6540, STR_ABOUT_SPECIAL_THANKS_2 = 6541, + STR_TAB_CONTRIBUTORS = 6542, // 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