diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index a64c2f6992..d78cd83530 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3654,6 +3654,7 @@ STR_6453 :Copy version info STR_6454 :Can’t rename banner… STR_6455 :Can’t rename sign… STR_6456 :Giant Screenshot +STR_6457 :Report a bug on GitHub ############# # Scenarios # diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 564b7fc02b..a800039df6 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -6,7 +6,8 @@ - Feature: [#15164] Highlight elements selected by the Tile Inspector, tracks are currently not supported. - Feature: [#15165] [Plugin] Add the ability to create entities using "map.createEntity". - Feature: [#15194] [Plugin] Add guest properties, ride downtime and park casualty penalty. -- Feature: [#15294] New vehicle animation type: flying animal +- Feature: [#15195] Added a bug-report item in file dropdown menu. +- Feature: [#15294] New vehicle animation type: flying animal. - Fix: [#13465] Creating a scenario based on a won save game results in a scenario that’s instantly won. - Fix: [#14316] Closing the Track Designs Manager window causes broken state. - Fix: [#14667] “Extreme Hawaiian Island” has unpurchaseable land tiles (original bug). diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index a14e62993e..870ec0f40a 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -119,10 +121,12 @@ enum FILE_MENU_DDIDX { DDIDX_SCREENSHOT = 7, DDIDX_GIANT_SCREENSHOT = 8, // separator - DDIDX_QUIT_TO_MENU = 10, - DDIDX_EXIT_OPENRCT2 = 11, + DDIDX_FILE_BUG_ON_GITHUB = 10, // separator - DDIDX_UPDATE_AVAILABLE = 13, + DDIDX_QUIT_TO_MENU = 12, + DDIDX_EXIT_OPENRCT2 = 13, + // separator + DDIDX_UPDATE_AVAILABLE = 15, }; enum TOP_TOOLBAR_VIEW_MENU_DDIDX { @@ -423,60 +427,61 @@ static void window_top_toolbar_mouseup(rct_window* w, rct_widgetindex widgetInde */ static void window_top_toolbar_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget) { - int32_t numItems; + int32_t numItems = 0; switch (widgetIndex) { case WIDX_FILE_MENU: if (gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)) { - gDropdownItemsFormat[0] = STR_ABOUT; - gDropdownItemsFormat[1] = STR_OPTIONS; - gDropdownItemsFormat[2] = STR_SCREENSHOT; - gDropdownItemsFormat[3] = STR_GIANT_SCREENSHOT; - gDropdownItemsFormat[4] = STR_EMPTY; - gDropdownItemsFormat[5] = STR_QUIT_TRACK_DESIGNS_MANAGER; - gDropdownItemsFormat[6] = STR_EXIT_OPENRCT2; + gDropdownItemsFormat[numItems++] = STR_ABOUT; + gDropdownItemsFormat[numItems++] = STR_OPTIONS; + gDropdownItemsFormat[numItems++] = STR_SCREENSHOT; + gDropdownItemsFormat[numItems++] = STR_GIANT_SCREENSHOT; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_FILE_BUG_ON_GITHUB; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_QUIT_TRACK_DESIGNS_MANAGER; + gDropdownItemsFormat[numItems++] = STR_EXIT_OPENRCT2; if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) - gDropdownItemsFormat[5] = STR_QUIT_ROLLERCOASTER_DESIGNER; - - numItems = 7; + gDropdownItemsFormat[numItems++] = STR_QUIT_ROLLERCOASTER_DESIGNER; } else if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) { - gDropdownItemsFormat[0] = STR_LOAD_LANDSCAPE; - gDropdownItemsFormat[1] = STR_SAVE_LANDSCAPE; - gDropdownItemsFormat[2] = STR_EMPTY; - gDropdownItemsFormat[3] = STR_ABOUT; - gDropdownItemsFormat[4] = STR_OPTIONS; - gDropdownItemsFormat[5] = STR_SCREENSHOT; - gDropdownItemsFormat[6] = STR_GIANT_SCREENSHOT; - gDropdownItemsFormat[7] = STR_EMPTY; - gDropdownItemsFormat[8] = STR_QUIT_SCENARIO_EDITOR; - gDropdownItemsFormat[9] = STR_EXIT_OPENRCT2; - numItems = 10; + gDropdownItemsFormat[numItems++] = STR_LOAD_LANDSCAPE; + gDropdownItemsFormat[numItems++] = STR_SAVE_LANDSCAPE; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_ABOUT; + gDropdownItemsFormat[numItems++] = STR_OPTIONS; + gDropdownItemsFormat[numItems++] = STR_SCREENSHOT; + gDropdownItemsFormat[numItems++] = STR_GIANT_SCREENSHOT; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_FILE_BUG_ON_GITHUB; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_QUIT_SCENARIO_EDITOR; + gDropdownItemsFormat[numItems++] = STR_EXIT_OPENRCT2; } else { - gDropdownItemsFormat[0] = STR_NEW_GAME; - gDropdownItemsFormat[1] = STR_LOAD_GAME; - gDropdownItemsFormat[2] = STR_SAVE_GAME; - gDropdownItemsFormat[3] = STR_SAVE_GAME_AS; - gDropdownItemsFormat[4] = STR_EMPTY; - gDropdownItemsFormat[5] = STR_ABOUT; - gDropdownItemsFormat[6] = STR_OPTIONS; - gDropdownItemsFormat[7] = STR_SCREENSHOT; - gDropdownItemsFormat[8] = STR_GIANT_SCREENSHOT; - gDropdownItemsFormat[9] = STR_EMPTY; - gDropdownItemsFormat[10] = STR_QUIT_TO_MENU; - gDropdownItemsFormat[11] = STR_EXIT_OPENRCT2; - numItems = 12; + gDropdownItemsFormat[numItems++] = STR_NEW_GAME; + gDropdownItemsFormat[numItems++] = STR_LOAD_GAME; + gDropdownItemsFormat[numItems++] = STR_SAVE_GAME; + gDropdownItemsFormat[numItems++] = STR_SAVE_GAME_AS; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_ABOUT; + gDropdownItemsFormat[numItems++] = STR_OPTIONS; + gDropdownItemsFormat[numItems++] = STR_SCREENSHOT; + gDropdownItemsFormat[numItems++] = STR_GIANT_SCREENSHOT; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_FILE_BUG_ON_GITHUB; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_QUIT_TO_MENU; + gDropdownItemsFormat[numItems++] = STR_EXIT_OPENRCT2; if (OpenRCT2::GetContext()->HasNewVersionInfo()) { - gDropdownItemsFormat[12] = STR_EMPTY; - gDropdownItemsFormat[13] = STR_UPDATE_AVAILABLE; - numItems += 2; + gDropdownItemsFormat[numItems++] = STR_EMPTY; + gDropdownItemsFormat[numItems++] = STR_UPDATE_AVAILABLE; } } WindowDropdownShowText( @@ -582,6 +587,15 @@ static void window_top_toolbar_dropdown(rct_window* w, rct_widgetindex widgetInd case DDIDX_GIANT_SCREENSHOT: screenshot_giant(); break; + case DDIDX_FILE_BUG_ON_GITHUB: + { + std::string url = "https://github.com/OpenRCT2/OpenRCT2/issues/" + "new?assignees=&labels=bug&template=bug_report.yaml"; + auto versionStr = String::URLEncode(gVersionInfoFull); + url.append("&openrct2_build=" + versionStr); + OpenRCT2::GetContext()->GetUiContext()->OpenURL(url); + } + break; case DDIDX_QUIT_TO_MENU: { window_close_by_class(WC_MANAGE_TRACK_DESIGN); diff --git a/src/openrct2/core/String.cpp b/src/openrct2/core/String.cpp index bb773e5df9..a1e9ff1370 100644 --- a/src/openrct2/core/String.cpp +++ b/src/openrct2/core/String.cpp @@ -14,7 +14,10 @@ #endif // __MINGW32__ #include +#include #include +#include +#include #include #include #ifndef _WIN32 @@ -823,6 +826,31 @@ namespace String return trunc; } + + std::string URLEncode(std::string_view value) + { + std::ostringstream escaped; + escaped.fill('0'); + escaped << std::hex; + + for (auto c : value) + { + // Keep alphanumeric and other accepted characters intact + if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') + { + escaped << c; + } + else + { + // Any other characters are percent-escaped + escaped << std::uppercase; + escaped << '%' << std::setw(2) << int32_t(static_cast(c)); + escaped << std::nouppercase; + } + } + + return escaped.str(); + } } // namespace String char32_t CodepointView::iterator::GetNextCodepoint(const char* ch, const char** next) diff --git a/src/openrct2/core/String.hpp b/src/openrct2/core/String.hpp index d4ce69210e..8c590ee207 100644 --- a/src/openrct2/core/String.hpp +++ b/src/openrct2/core/String.hpp @@ -178,6 +178,8 @@ namespace String */ std::string_view UTF8Truncate(std::string_view v, size_t size); + // Escapes special characters in a string to the percentage equivalent that can be used in URLs. + std::string URLEncode(std::string_view value); } // namespace String class CodepointView diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 64b53a5e8f..66bf283cc2 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3909,6 +3909,8 @@ enum STR_SHORTCUT_GIANT_SCREENSHOT = 6456, + STR_FILE_BUG_ON_GITHUB = 6457, + // 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 };