diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index a4d760c681..45b5541601 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3700,6 +3700,8 @@ STR_6625 :Invalid colour STR_6626 :Animation is backwards STR_6627 :Track speed too high! STR_6628 :Can only be placed on path edges! +STR_6629 :Align toolbar buttons horizontally centred +STR_6630 :This setting will align toolbar the buttons horizontally in the centre of the screen. The traditional way of aligning them is to in left and right corner. ############# # Scenarios # diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 93c91721e3..7327a6a4bd 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.4.12 (in development) ------------------------------------------------------------------------ +- Feature: [#622] Add option to align the top toolbar buttons horizontally centred (off by default). - Feature: [#21714] [Plugin] Costume assignment is now tailored to each staff type. - Feature: [#21913] [Plugin] Allow precise and safe control of peep animations. - Improved: [#21981] Rendering performance of the map window has been improved considerably. diff --git a/src/openrct2-ui/interface/Widget.cpp b/src/openrct2-ui/interface/Widget.cpp index 729c260976..577cd9ca73 100644 --- a/src/openrct2-ui/interface/Widget.cpp +++ b/src/openrct2-ui/interface/Widget.cpp @@ -9,8 +9,6 @@ #include "Widget.h" -#include "Window.h" - #include #include #include @@ -567,13 +565,13 @@ static void WidgetCaptionDraw(DrawPixelInfo& dpi, WindowBase& w, WidgetIndex wid int32_t width = widget->width() - 4; if ((widget + 1)->type == WindowWidgetType::CloseBox) { - width -= CloseButtonWidth; + width -= kCloseButtonWidth; if ((widget + 2)->type == WindowWidgetType::CloseBox) - width -= CloseButtonWidth; + width -= kCloseButtonWidth; } topLeft.x += width / 2; if (Config::Get().interface.WindowButtonsOnTheLeft) - topLeft.x += CloseButtonWidth; + topLeft.x += kCloseButtonWidth; DrawTextEllipsised( dpi, topLeft, width, widget->text, Formatter::Common(), diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index eb16115823..5a28c969f0 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -828,7 +828,7 @@ void WindowAlignTabs(WindowBase* w, WidgetIndex start_tab_id, WidgetIndex end_ta ScreenCoordsXY WindowGetViewportSoundIconPos(WindowBase& w) { - const uint8_t buttonOffset = (Config::Get().interface.WindowButtonsOnTheLeft) ? CloseButtonWidth + 2 : 0; + const uint8_t buttonOffset = (Config::Get().interface.WindowButtonsOnTheLeft) ? kCloseButtonWidth + 2 : 0; return w.windowPos + ScreenCoordsXY{ 2 + buttonOffset, 2 }; } diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index 6a01166012..94e0cbb896 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -169,6 +169,7 @@ enum WindowOptionsWidgetIdx { WIDX_THEMES_DROPDOWN, WIDX_THEMES_BUTTON, WIDX_TOOLBAR_BUTTONS_GROUP, + WIDX_TOOLBAR_BUTTONS_CENTRED, WIDX_TOOLBAR_BUTTONS_SHOW_FOR_LABEL, WIDX_TOOLBAR_SHOW_FINANCES, WIDX_TOOLBAR_SHOW_RESEARCH, @@ -337,15 +338,18 @@ static Widget window_options_controls_and_interface_widgets[] = { MakeWidget({155, THEMES_GROUP_START + 30}, {145, 13}, WindowWidgetType::Button, WindowColour::Secondary, STR_EDIT_THEMES_BUTTON, STR_EDIT_THEMES_BUTTON_TIP), // Themes button #undef THEMES_GROUP_START #define TOOLBAR_GROUP_START 215 - MakeWidget({ 5, TOOLBAR_GROUP_START + 0}, {300, 92}, WindowWidgetType::Groupbox, WindowColour::Secondary, STR_TOOLBAR_BUTTONS_GROUP ), // Toolbar buttons group - MakeWidget({ 10, TOOLBAR_GROUP_START + 14}, {280, 12}, WindowWidgetType::Label, WindowColour::Secondary, STR_SHOW_TOOLBAR_BUTTONS_FOR ), - MakeWidget({ 24, TOOLBAR_GROUP_START + 31}, {122, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_FINANCES_BUTTON_ON_TOOLBAR, STR_FINANCES_BUTTON_ON_TOOLBAR_TIP ), // Finances - MakeWidget({ 24, TOOLBAR_GROUP_START + 46}, {122, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_RESEARCH_BUTTON_ON_TOOLBAR, STR_RESEARCH_BUTTON_ON_TOOLBAR_TIP ), // Research - MakeWidget({155, TOOLBAR_GROUP_START + 31}, {145, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_CHEATS_BUTTON_ON_TOOLBAR, STR_CHEATS_BUTTON_ON_TOOLBAR_TIP ), // Cheats - MakeWidget({155, TOOLBAR_GROUP_START + 46}, {145, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR, STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR_TIP), // Recent messages - MakeWidget({ 24, TOOLBAR_GROUP_START + 61}, {162, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_MUTE_BUTTON_ON_TOOLBAR, STR_MUTE_BUTTON_ON_TOOLBAR_TIP ), // Mute - MakeWidget({155, TOOLBAR_GROUP_START + 61}, {145, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_CHAT_BUTTON_ON_TOOLBAR, STR_CHAT_BUTTON_ON_TOOLBAR_TIP ), // Chat - MakeWidget({ 24, TOOLBAR_GROUP_START + 76}, {122, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_ZOOM_BUTTON_ON_TOOLBAR, STR_ZOOM_BUTTON_ON_TOOLBAR_TIP ), // Zoom + + + MakeWidget({ 5, TOOLBAR_GROUP_START + 0}, {300,107}, WindowWidgetType::Groupbox, WindowColour::Secondary, STR_TOOLBAR_BUTTONS_GROUP ), // Toolbar buttons group + MakeWidget({ 10, TOOLBAR_GROUP_START + 14}, {280, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary, STR_OPTIONS_TOOLBAR_BUTTONS_CENTRED, STR_OPTIONS_TOOLBAR_BUTTONS_CENTRED_TIP), + MakeWidget({ 10, TOOLBAR_GROUP_START + 31}, {280, 12}, WindowWidgetType::Label, WindowColour::Secondary, STR_SHOW_TOOLBAR_BUTTONS_FOR ), + MakeWidget({ 24, TOOLBAR_GROUP_START + 46}, {122, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_FINANCES_BUTTON_ON_TOOLBAR, STR_FINANCES_BUTTON_ON_TOOLBAR_TIP ), // Finances + MakeWidget({ 24, TOOLBAR_GROUP_START + 61}, {122, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_RESEARCH_BUTTON_ON_TOOLBAR, STR_RESEARCH_BUTTON_ON_TOOLBAR_TIP ), // Research + MakeWidget({155, TOOLBAR_GROUP_START + 46}, {145, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_CHEATS_BUTTON_ON_TOOLBAR, STR_CHEATS_BUTTON_ON_TOOLBAR_TIP ), // Cheats + MakeWidget({155, TOOLBAR_GROUP_START + 61}, {145, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR, STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR_TIP), // Recent messages + MakeWidget({ 24, TOOLBAR_GROUP_START + 76}, {162, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_MUTE_BUTTON_ON_TOOLBAR, STR_MUTE_BUTTON_ON_TOOLBAR_TIP ), // Mute + MakeWidget({155, TOOLBAR_GROUP_START + 76}, {145, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_CHAT_BUTTON_ON_TOOLBAR, STR_CHAT_BUTTON_ON_TOOLBAR_TIP ), // Chat + MakeWidget({ 24, TOOLBAR_GROUP_START + 91}, {122, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary , STR_ZOOM_BUTTON_ON_TOOLBAR, STR_ZOOM_BUTTON_ON_TOOLBAR_TIP ), // Zoom kWidgetsEnd, #undef TOOLBAR_GROUP_START }; @@ -1534,6 +1538,14 @@ static Widget *window_options_page_widgets[] = { #pragma endregion #pragma region Controls tab events + void ToggleToolbarSetting(bool& setting) + { + setting ^= true; + Config::Save(); + Invalidate(); + WindowInvalidateByClass(WindowClass::TopToolbar); + } + void ControlsMouseUp(WidgetIndex widgetIndex) { switch (widgetIndex) @@ -1557,47 +1569,29 @@ static Widget *window_options_page_widgets[] = { Config::Save(); Invalidate(); break; + case WIDX_TOOLBAR_BUTTONS_CENTRED: + ToggleToolbarSetting(Config::Get().interface.ToolbarButtonsCentred); + break; case WIDX_TOOLBAR_SHOW_FINANCES: - Config::Get().interface.ToolbarShowFinances ^= 1; - Config::Save(); - Invalidate(); - WindowInvalidateByClass(WindowClass::TopToolbar); + ToggleToolbarSetting(Config::Get().interface.ToolbarShowFinances); break; case WIDX_TOOLBAR_SHOW_RESEARCH: - Config::Get().interface.ToolbarShowResearch ^= 1; - Config::Save(); - Invalidate(); - WindowInvalidateByClass(WindowClass::TopToolbar); + ToggleToolbarSetting(Config::Get().interface.ToolbarShowResearch); break; case WIDX_TOOLBAR_SHOW_CHEATS: - Config::Get().interface.ToolbarShowCheats ^= 1; - Config::Save(); - Invalidate(); - WindowInvalidateByClass(WindowClass::TopToolbar); + ToggleToolbarSetting(Config::Get().interface.ToolbarShowCheats); break; case WIDX_TOOLBAR_SHOW_NEWS: - Config::Get().interface.ToolbarShowNews ^= 1; - Config::Save(); - Invalidate(); - WindowInvalidateByClass(WindowClass::TopToolbar); + ToggleToolbarSetting(Config::Get().interface.ToolbarShowNews); break; case WIDX_TOOLBAR_SHOW_MUTE: - Config::Get().interface.ToolbarShowMute ^= 1; - Config::Save(); - Invalidate(); - WindowInvalidateByClass(WindowClass::TopToolbar); + ToggleToolbarSetting(Config::Get().interface.ToolbarShowMute); break; case WIDX_TOOLBAR_SHOW_CHAT: - Config::Get().interface.ToolbarShowChat ^= 1; - Config::Save(); - Invalidate(); - WindowInvalidateByClass(WindowClass::TopToolbar); + ToggleToolbarSetting(Config::Get().interface.ToolbarShowChat); break; case WIDX_TOOLBAR_SHOW_ZOOM: - Config::Get().interface.ToolbarShowZoom ^= 1; - Config::Save(); - Invalidate(); - WindowInvalidateByClass(WindowClass::TopToolbar); + ToggleToolbarSetting(Config::Get().interface.ToolbarShowZoom); break; case WIDX_WINDOW_BUTTONS_ON_THE_LEFT: Config::Get().interface.WindowButtonsOnTheLeft ^= 1; @@ -1662,6 +1656,7 @@ static Widget *window_options_page_widgets[] = { SetCheckboxValue(WIDX_TRAP_CURSOR, Config::Get().general.TrapCursor); SetCheckboxValue(WIDX_INVERT_DRAG, Config::Get().general.InvertViewportDrag); SetCheckboxValue(WIDX_ZOOM_TO_CURSOR, Config::Get().general.ZoomToCursor); + SetCheckboxValue(WIDX_TOOLBAR_BUTTONS_CENTRED, Config::Get().interface.ToolbarButtonsCentred); SetCheckboxValue(WIDX_TOOLBAR_SHOW_FINANCES, Config::Get().interface.ToolbarShowFinances); SetCheckboxValue(WIDX_TOOLBAR_SHOW_RESEARCH, Config::Get().interface.ToolbarShowResearch); SetCheckboxValue(WIDX_TOOLBAR_SHOW_CHEATS, Config::Get().interface.ToolbarShowCheats); diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index e038f352ee..5336c39ba3 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -209,78 +209,89 @@ namespace OpenRCT2::Ui::Windows #pragma region Toolbar_widget_ordering // clang-format off -// from left to right -static constexpr int32_t left_aligned_widgets_order[] = { - WIDX_PAUSE, - WIDX_FASTFORWARD, - WIDX_FILE_MENU, - WIDX_MUTE, - WIDX_NETWORK, - WIDX_CHAT, - WIDX_CHEATS, - WIDX_DEBUG, + static constexpr std::array kWidgetOrderLeftGroup = { + WIDX_PAUSE, + WIDX_FASTFORWARD, + WIDX_FILE_MENU, + WIDX_MUTE, + WIDX_NETWORK, + WIDX_CHAT, + WIDX_CHEATS, + WIDX_DEBUG, - WIDX_SEPARATOR, + WIDX_SEPARATOR, - WIDX_ZOOM_OUT, - WIDX_ZOOM_IN, - WIDX_ROTATE, - WIDX_VIEW_MENU, - WIDX_MAP, -}; + WIDX_ZOOM_OUT, + WIDX_ZOOM_IN, + WIDX_ROTATE, + WIDX_VIEW_MENU, + WIDX_MAP, + }; -// from right to left -static constexpr int32_t right_aligned_widgets_order[] = { - WIDX_NEWS, - WIDX_GUESTS, - WIDX_STAFF, - WIDX_PARK, - WIDX_RIDES, - WIDX_RESEARCH, - WIDX_FINANCES, + static constexpr std::array kWidgetOrderRightGroup = { + WIDX_CLEAR_SCENERY, + WIDX_LAND, + WIDX_WATER, + WIDX_SCENERY, + WIDX_PATH, + WIDX_CONSTRUCT_RIDE, - WIDX_SEPARATOR, + WIDX_SEPARATOR, - WIDX_CONSTRUCT_RIDE, - WIDX_PATH, - WIDX_SCENERY, - WIDX_WATER, - WIDX_LAND, - WIDX_CLEAR_SCENERY, -}; + WIDX_FINANCES, + WIDX_RESEARCH, + WIDX_RIDES, + WIDX_PARK, + WIDX_STAFF, + WIDX_GUESTS, + WIDX_NEWS, + }; + + static constexpr size_t _totalToolbarElements = kWidgetOrderLeftGroup.size() + kWidgetOrderRightGroup.size(); + + // Make a combined version of both halves of the toolbar, with a separator halfway. + static constexpr std::array kWidgetOrderCombined = []() { + std::array combined; + + auto halfWayPoint = std::copy(kWidgetOrderLeftGroup.begin(), kWidgetOrderLeftGroup.end(), combined.begin()); + *halfWayPoint = WIDX_SEPARATOR; + std::copy(kWidgetOrderRightGroup.begin(), kWidgetOrderRightGroup.end(), halfWayPoint + 1); + + return combined; + }(); #pragma endregion -static Widget _topToolbarWidgets[] = { - MakeRemapWidget({ 0, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TOOLBAR_PAUSE, STR_PAUSE_GAME_TIP ), // Pause - MakeRemapWidget({ 60, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TOOLBAR_FILE, STR_DISC_AND_GAME_OPTIONS_TIP ), // File menu - MakeRemapWidget({250, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_G2_TOOLBAR_MUTE, STR_TOOLBAR_MUTE_TIP ), // Mute - MakeRemapWidget({100, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ZOOM_OUT, STR_ZOOM_OUT_TIP ), // Zoom out - MakeRemapWidget({130, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ZOOM_IN, STR_ZOOM_IN_TIP ), // Zoom in - MakeRemapWidget({160, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ROTATE, STR_ROTATE_TIP ), // Rotate camera - MakeRemapWidget({190, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_VIEW, STR_VIEW_OPTIONS_TIP ), // Transparency menu - MakeRemapWidget({220, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_MAP, STR_SHOW_MAP_TIP ), // Map - MakeRemapWidget({267, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_LAND, STR_ADJUST_LAND_TIP ), // Land - MakeRemapWidget({297, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_WATER, STR_ADJUST_WATER_TIP ), // Water - MakeRemapWidget({327, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_SCENERY, STR_PLACE_SCENERY_TIP ), // Scenery - MakeRemapWidget({357, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_FOOTPATH, STR_BUILD_FOOTPATH_TIP ), // Path - MakeRemapWidget({387, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_CONSTRUCT_RIDE, STR_BUILD_RIDE_TIP ), // Construct ride - MakeRemapWidget({490, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_RIDES, STR_RIDES_IN_PARK_TIP ), // Rides - MakeRemapWidget({520, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_PARK, STR_PARK_INFORMATION_TIP ), // Park - MakeRemapWidget({550, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_STAFF_TIP ), // Staff - MakeRemapWidget({560, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_GUESTS, STR_GUESTS_TIP ), // Guests - MakeRemapWidget({560, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_CLEAR_SCENERY, STR_CLEAR_SCENERY_TIP ), // Clear scenery - MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_GAME_SPEED_TIP ), // Fast forward - MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_CHEATS_TIP ), // Cheats - MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_DEBUG_TIP ), // Debug - MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_SCENARIO_OPTIONS_FINANCIAL_TIP), // Finances - MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_FINANCES_RESEARCH_TIP ), // Research - MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_SHOW_RECENT_MESSAGES_TIP ), // News - MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_G2_TOOLBAR_MULTIPLAYER, STR_SHOW_MULTIPLAYER_STATUS_TIP ), // Network - MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_TOOLBAR_CHAT_TIP ), // Chat - MakeWidget ({ 0, 0}, {10, 1}, WindowWidgetType::Empty, WindowColour::Primary ), // Artificial widget separator - kWidgetsEnd, -}; + static Widget _topToolbarWidgets[] = { + MakeRemapWidget({ 0, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TOOLBAR_PAUSE, STR_PAUSE_GAME_TIP ), // Pause + MakeRemapWidget({ 60, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TOOLBAR_FILE, STR_DISC_AND_GAME_OPTIONS_TIP ), // File menu + MakeRemapWidget({250, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_G2_TOOLBAR_MUTE, STR_TOOLBAR_MUTE_TIP ), // Mute + MakeRemapWidget({100, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ZOOM_OUT, STR_ZOOM_OUT_TIP ), // Zoom out + MakeRemapWidget({130, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ZOOM_IN, STR_ZOOM_IN_TIP ), // Zoom in + MakeRemapWidget({160, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ROTATE, STR_ROTATE_TIP ), // Rotate camera + MakeRemapWidget({190, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_VIEW, STR_VIEW_OPTIONS_TIP ), // Transparency menu + MakeRemapWidget({220, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_MAP, STR_SHOW_MAP_TIP ), // Map + MakeRemapWidget({267, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_LAND, STR_ADJUST_LAND_TIP ), // Land + MakeRemapWidget({297, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_WATER, STR_ADJUST_WATER_TIP ), // Water + MakeRemapWidget({327, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_SCENERY, STR_PLACE_SCENERY_TIP ), // Scenery + MakeRemapWidget({357, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_FOOTPATH, STR_BUILD_FOOTPATH_TIP ), // Path + MakeRemapWidget({387, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_CONSTRUCT_RIDE, STR_BUILD_RIDE_TIP ), // Construct ride + MakeRemapWidget({490, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_RIDES, STR_RIDES_IN_PARK_TIP ), // Rides + MakeRemapWidget({520, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_PARK, STR_PARK_INFORMATION_TIP ), // Park + MakeRemapWidget({550, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_STAFF_TIP ), // Staff + MakeRemapWidget({560, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_GUESTS, STR_GUESTS_TIP ), // Guests + MakeRemapWidget({560, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_CLEAR_SCENERY, STR_CLEAR_SCENERY_TIP ), // Clear scenery + MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_GAME_SPEED_TIP ), // Fast forward + MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_CHEATS_TIP ), // Cheats + MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_DEBUG_TIP ), // Debug + MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_SCENARIO_OPTIONS_FINANCIAL_TIP), // Finances + MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_FINANCES_RESEARCH_TIP ), // Research + MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_SHOW_RECENT_MESSAGES_TIP ), // News + MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_G2_TOOLBAR_MULTIPLAYER, STR_SHOW_MULTIPLAYER_STATUS_TIP ), // Network + MakeRemapWidget({ 30, 0}, {30, kTopToolbarHeight + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_TOOLBAR_CHAT_TIP ), // Chat + MakeWidget ({ 0, 0}, {10, 1}, WindowWidgetType::Empty, WindowColour::Primary ), // Artificial widget separator + kWidgetsEnd, + }; // clang-format on static void ScenarioSelectCallback(const utf8* path); @@ -2916,11 +2927,8 @@ static Widget _topToolbarWidgets[] = { } } - void OnPrepareDraw() override + void ResetWidgetToDefaultState() { - int32_t x, widgetIndex, widgetWidth, firstAlignment; - Widget* widget; - // Enable / disable buttons widgets[WIDX_PAUSE].type = WindowWidgetType::TrnBtn; widgets[WIDX_FILE_MENU].type = WindowWidgetType::TrnBtn; @@ -2949,7 +2957,10 @@ static Widget _topToolbarWidgets[] = { : WindowWidgetType::Empty; widgets[WIDX_NEWS].type = WindowWidgetType::TrnBtn; widgets[WIDX_NETWORK].type = WindowWidgetType::TrnBtn; + } + void HideDisabledButtons() + { if (!Config::Get().interface.ToolbarShowMute) widgets[WIDX_MUTE].type = WindowWidgetType::Empty; @@ -2978,46 +2989,54 @@ static Widget _topToolbarWidgets[] = { if ((GetGameState().Park.Flags & PARK_FLAGS_NO_MONEY) || !Config::Get().interface.ToolbarShowFinances) widgets[WIDX_FINANCES].type = WindowWidgetType::Empty; + } - if (gScreenFlags & SCREEN_FLAGS_EDITOR) + void ApplyEditorMode() + { + if ((gScreenFlags & SCREEN_FLAGS_EDITOR) == 0) { - widgets[WIDX_PARK].type = WindowWidgetType::Empty; - widgets[WIDX_STAFF].type = WindowWidgetType::Empty; - widgets[WIDX_GUESTS].type = WindowWidgetType::Empty; - widgets[WIDX_FINANCES].type = WindowWidgetType::Empty; - widgets[WIDX_RESEARCH].type = WindowWidgetType::Empty; - widgets[WIDX_NEWS].type = WindowWidgetType::Empty; - widgets[WIDX_NETWORK].type = WindowWidgetType::Empty; - - auto& gameState = GetGameState(); - if (gameState.EditorStep != EditorStep::LandscapeEditor) - { - widgets[WIDX_LAND].type = WindowWidgetType::Empty; - widgets[WIDX_WATER].type = WindowWidgetType::Empty; - } - - if (gameState.EditorStep != EditorStep::RollercoasterDesigner) - { - widgets[WIDX_RIDES].type = WindowWidgetType::Empty; - widgets[WIDX_CONSTRUCT_RIDE].type = WindowWidgetType::Empty; - widgets[WIDX_FASTFORWARD].type = WindowWidgetType::Empty; - } - - if (gameState.EditorStep != EditorStep::LandscapeEditor - && gameState.EditorStep != EditorStep::RollercoasterDesigner) - { - widgets[WIDX_MAP].type = WindowWidgetType::Empty; - widgets[WIDX_SCENERY].type = WindowWidgetType::Empty; - widgets[WIDX_PATH].type = WindowWidgetType::Empty; - widgets[WIDX_CLEAR_SCENERY].type = WindowWidgetType::Empty; - - widgets[WIDX_ZOOM_OUT].type = WindowWidgetType::Empty; - widgets[WIDX_ZOOM_IN].type = WindowWidgetType::Empty; - widgets[WIDX_ROTATE].type = WindowWidgetType::Empty; - widgets[WIDX_VIEW_MENU].type = WindowWidgetType::Empty; - } + return; } + widgets[WIDX_PARK].type = WindowWidgetType::Empty; + widgets[WIDX_STAFF].type = WindowWidgetType::Empty; + widgets[WIDX_GUESTS].type = WindowWidgetType::Empty; + widgets[WIDX_FINANCES].type = WindowWidgetType::Empty; + widgets[WIDX_RESEARCH].type = WindowWidgetType::Empty; + widgets[WIDX_NEWS].type = WindowWidgetType::Empty; + widgets[WIDX_NETWORK].type = WindowWidgetType::Empty; + + auto& gameState = GetGameState(); + if (gameState.EditorStep != EditorStep::LandscapeEditor) + { + widgets[WIDX_LAND].type = WindowWidgetType::Empty; + widgets[WIDX_WATER].type = WindowWidgetType::Empty; + } + + if (gameState.EditorStep != EditorStep::RollercoasterDesigner) + { + widgets[WIDX_RIDES].type = WindowWidgetType::Empty; + widgets[WIDX_CONSTRUCT_RIDE].type = WindowWidgetType::Empty; + widgets[WIDX_FASTFORWARD].type = WindowWidgetType::Empty; + } + + if (gameState.EditorStep != EditorStep::LandscapeEditor + && gameState.EditorStep != EditorStep::RollercoasterDesigner) + { + widgets[WIDX_MAP].type = WindowWidgetType::Empty; + widgets[WIDX_SCENERY].type = WindowWidgetType::Empty; + widgets[WIDX_PATH].type = WindowWidgetType::Empty; + widgets[WIDX_CLEAR_SCENERY].type = WindowWidgetType::Empty; + + widgets[WIDX_ZOOM_OUT].type = WindowWidgetType::Empty; + widgets[WIDX_ZOOM_IN].type = WindowWidgetType::Empty; + widgets[WIDX_ROTATE].type = WindowWidgetType::Empty; + widgets[WIDX_VIEW_MENU].type = WindowWidgetType::Empty; + } + } + + void ApplyNetworkMode() + { switch (NetworkGetMode()) { case NETWORK_MODE_NONE: @@ -3031,85 +3050,10 @@ static Widget _topToolbarWidgets[] = { widgets[WIDX_FASTFORWARD].type = WindowWidgetType::Empty; break; } + } - // Align left hand side toolbar buttons - firstAlignment = 1; - x = 0; - for (size_t i = 0; i < std::size(left_aligned_widgets_order); ++i) - { - widgetIndex = left_aligned_widgets_order[i]; - widget = &widgets[widgetIndex]; - if (widget->type == WindowWidgetType::Empty && widgetIndex != WIDX_SEPARATOR) - continue; - - if (firstAlignment && widgetIndex == WIDX_SEPARATOR) - continue; - - widgetWidth = widget->width(); - widget->left = x; - x += widgetWidth; - widget->right = x; - x += 1; - firstAlignment = 0; - } - - // Align right hand side toolbar buttons if necessary - int32_t screenWidth = ContextGetWidth(); - firstAlignment = 1; - x = std::max(640, screenWidth); - for (size_t i = 0; i < std::size(right_aligned_widgets_order); ++i) - { - widgetIndex = right_aligned_widgets_order[i]; - widget = &widgets[widgetIndex]; - if (widget->type == WindowWidgetType::Empty && widgetIndex != WIDX_SEPARATOR) - continue; - - if (firstAlignment && widgetIndex == WIDX_SEPARATOR) - continue; - - widgetWidth = widget->width(); - x -= 1; - widget->right = x; - x -= widgetWidth; - widget->left = x; - firstAlignment = 0; - } - - // Footpath button pressed down - if (WindowFindByClass(WindowClass::Footpath) == nullptr) - pressed_widgets &= ~(1uLL << WIDX_PATH); - else - pressed_widgets |= (1uLL << WIDX_PATH); - - bool paused = (gGamePaused & GAME_PAUSED_NORMAL); - if (paused || _waitingForPause) - { - pressed_widgets |= (1uLL << WIDX_PAUSE); - if (paused) - _waitingForPause = false; - } - else - pressed_widgets &= ~(1uLL << WIDX_PAUSE); - - if (!OpenRCT2::Audio::gGameSoundsOff) - widgets[WIDX_MUTE].image = ImageId(SPR_G2_TOOLBAR_MUTE, FilterPaletteID::PaletteNull); - else - widgets[WIDX_MUTE].image = ImageId(SPR_G2_TOOLBAR_UNMUTE, FilterPaletteID::PaletteNull); - - // Set map button to the right image. - if (widgets[WIDX_MAP].type != WindowWidgetType::Empty) - { - static constexpr uint32_t _imageIdByRotation[] = { - SPR_G2_MAP_NORTH, - SPR_G2_MAP_WEST, - SPR_G2_MAP_SOUTH, - SPR_G2_MAP_EAST, - }; - - uint32_t mapImageId = _imageIdByRotation[GetCurrentRotation()]; - widgets[WIDX_MAP].image = ImageId(mapImageId, FilterPaletteID::PaletteNull); - } - + void ApplyZoomState() + { // Zoomed out/in disable. Not sure where this code is in the original. const auto* mainWindow = WindowGetMain(); if (mainWindow == nullptr || mainWindow->viewport == nullptr) @@ -3132,6 +3076,139 @@ static Widget _topToolbarWidgets[] = { } } + void ApplyPausedState() + { + bool paused = (gGamePaused & GAME_PAUSED_NORMAL); + if (paused || _waitingForPause) + { + pressed_widgets |= (1uLL << WIDX_PAUSE); + if (paused) + _waitingForPause = false; + } + else + pressed_widgets &= ~(1uLL << WIDX_PAUSE); + } + + void ApplyMapRotation() + { + // Set map button to the right image. + if (widgets[WIDX_MAP].type != WindowWidgetType::Empty) + { + static constexpr uint32_t _imageIdByRotation[] = { + SPR_G2_MAP_NORTH, + SPR_G2_MAP_WEST, + SPR_G2_MAP_SOUTH, + SPR_G2_MAP_EAST, + }; + + uint32_t mapImageId = _imageIdByRotation[GetCurrentRotation()]; + widgets[WIDX_MAP].image = ImageId(mapImageId, FilterPaletteID::PaletteNull); + } + } + + void ApplyAudioState() + { + if (!OpenRCT2::Audio::gGameSoundsOff) + widgets[WIDX_MUTE].image = ImageId(SPR_G2_TOOLBAR_MUTE, FilterPaletteID::PaletteNull); + else + widgets[WIDX_MUTE].image = ImageId(SPR_G2_TOOLBAR_UNMUTE, FilterPaletteID::PaletteNull); + } + + void ApplyFootpathPressed() + { + // Footpath button pressed down + if (WindowFindByClass(WindowClass::Footpath) == nullptr) + pressed_widgets &= ~(1uLL << WIDX_PATH); + else + pressed_widgets |= (1uLL << WIDX_PATH); + } + + // TODO: look into using std::span + template uint16_t GetToolbarWidth(T toolbarItems) + { + bool firstItem = true; + auto totalWidth = 0; + for (auto widgetIndex : toolbarItems) + { + auto* widget = &widgets[widgetIndex]; + if (widget->type == WindowWidgetType::Empty && widgetIndex != WIDX_SEPARATOR) + continue; + + if (firstItem && widgetIndex == WIDX_SEPARATOR) + continue; + + totalWidth += widget->width() + 1; + firstItem = false; + } + return totalWidth; + } + + // TODO: look into using std::span + template void AlignButtons(T toolbarItems, uint16_t xPos) + { + bool firstItem = true; + for (auto widgetIndex : toolbarItems) + { + auto* widget = &widgets[widgetIndex]; + if (widget->type == WindowWidgetType::Empty && widgetIndex != WIDX_SEPARATOR) + continue; + + if (firstItem && widgetIndex == WIDX_SEPARATOR) + continue; + + auto widgetWidth = widget->width(); + widget->left = xPos; + xPos += widgetWidth; + widget->right = xPos; + xPos += 1; + + firstItem = false; + } + } + + void AlignButtonsLeftRight() + { + // Align left hand side toolbar buttons + AlignButtons(kWidgetOrderLeftGroup, 0); + + // Align right hand side toolbar buttons + auto totalWidth = GetToolbarWidth(kWidgetOrderRightGroup); + auto xPos = ContextGetWidth() - totalWidth; + AlignButtons(kWidgetOrderRightGroup, xPos); + } + + void AlignButtonsCentre() + { + // First, we figure out how much space we'll be needing + auto totalWidth = GetToolbarWidth(kWidgetOrderCombined); + + // We'll start from the centre of the UI... + auto xPos = (ContextGetWidth() - totalWidth) / 2; + + // And finally, align the buttons in the centre + AlignButtons(kWidgetOrderCombined, xPos); + } + + void OnPrepareDraw() override + { + ResetWidgetToDefaultState(); + HideDisabledButtons(); + ApplyEditorMode(); + + ApplyPausedState(); + ApplyAudioState(); + ApplyNetworkMode(); + + ApplyZoomState(); + ApplyMapRotation(); + ApplyFootpathPressed(); + + if (!Config::Get().interface.ToolbarButtonsCentred) + AlignButtonsLeftRight(); + else + AlignButtonsCentre(); + } + void OnDraw(DrawPixelInfo& dpi) override { const auto& gameState = GetGameState(); diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index 42d719f34d..06a775aa27 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -335,6 +335,7 @@ namespace OpenRCT2::Config if (reader->ReadSection("interface")) { auto model = &_config.interface; + model->ToolbarButtonsCentred = reader->GetBoolean("toolbar_buttons_centred", false); model->ToolbarShowFinances = reader->GetBoolean("toolbar_show_finances", true); model->ToolbarShowResearch = reader->GetBoolean("toolbar_show_research", true); model->ToolbarShowCheats = reader->GetBoolean("toolbar_show_cheats", false); @@ -357,6 +358,7 @@ namespace OpenRCT2::Config { auto model = &_config.interface; writer->WriteSection("interface"); + writer->WriteBoolean("toolbar_buttons_centred", model->ToolbarButtonsCentred); writer->WriteBoolean("toolbar_show_finances", model->ToolbarShowFinances); writer->WriteBoolean("toolbar_show_research", model->ToolbarShowResearch); writer->WriteBoolean("toolbar_show_cheats", model->ToolbarShowCheats); diff --git a/src/openrct2/config/Config.h b/src/openrct2/config/Config.h index b65fc3348e..de86f0a7e0 100644 --- a/src/openrct2/config/Config.h +++ b/src/openrct2/config/Config.h @@ -119,6 +119,7 @@ namespace OpenRCT2::Config struct Interface { + bool ToolbarButtonsCentred; bool ToolbarShowFinances; bool ToolbarShowResearch; bool ToolbarShowCheats; diff --git a/src/openrct2/interface/Widget.h b/src/openrct2/interface/Widget.h index 2f387ee342..2f395de441 100644 --- a/src/openrct2/interface/Widget.h +++ b/src/openrct2/interface/Widget.h @@ -9,7 +9,11 @@ #pragma once -#include "Window.h" +#include + +struct WindowBase; + +using WidgetIndex = int16_t; enum class WindowWidgetType : uint8_t { @@ -39,6 +43,18 @@ enum class WindowWidgetType : uint8_t Last = 26, }; +constexpr uint8_t kCloseButtonWidth = 10; + +constexpr int32_t kScrollableRowHeight = 12; +constexpr uint8_t kListRowHeight = 12; +constexpr uint8_t kTableCellHeight = 12; +constexpr uint8_t kButtonFaceHeight = 12; +constexpr uint8_t kSpinnerHeight = 12; +constexpr uint8_t kDropdownHeight = 12; + +constexpr uint16_t kTextInputSize = 1024; +constexpr uint16_t kTopToolbarHeight = 27; + enum { SCROLL_HORIZONTAL = (1 << 0), diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index cb8dcc9397..20acef0871 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -1849,11 +1849,11 @@ void WindowBase::ResizeFrame() if (Config::Get().interface.WindowButtonsOnTheLeft) { widgets[2].left = 2; - widgets[2].right = 2 + CloseButtonWidth; + widgets[2].right = 2 + kCloseButtonWidth; } else { - widgets[2].left = width - 3 - CloseButtonWidth; + widgets[2].left = width - 3 - kCloseButtonWidth; widgets[2].right = width - 3; } } diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index 061031569e..e1b64c8d62 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -18,6 +18,7 @@ #include "../windows/TileInspectorGlobals.h" #include "../world/Location.hpp" #include "../world/ScenerySelection.h" +#include "Widget.h" #include "WindowClasses.h" #include "ZoomLevel.h" @@ -39,20 +40,7 @@ enum class CursorID : uint8_t; enum class RideConstructionState : uint8_t; enum class CloseWindowModifier : uint8_t; -constexpr uint8_t CloseButtonWidth = 10; - -constexpr int32_t kScrollableRowHeight = 12; -constexpr uint8_t kListRowHeight = 12; -constexpr uint8_t kTableCellHeight = 12; -constexpr uint8_t kButtonFaceHeight = 12; -constexpr uint8_t kSpinnerHeight = 12; -constexpr uint8_t kDropdownHeight = 12; - -constexpr uint16_t kTextInputSize = 1024; -constexpr uint16_t kTopToolbarHeight = 27; - using rct_windownumber = uint16_t; -using WidgetIndex = int16_t; struct WindowIdentifier { diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 96850e4f0e..92107db8a1 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3856,6 +3856,9 @@ enum : uint16_t STR_CAN_ONLY_BE_PLACED_ON_PATH_EDGES = 6628, + STR_OPTIONS_TOOLBAR_BUTTONS_CENTRED = 6629, + STR_OPTIONS_TOOLBAR_BUTTONS_CENTRED_TIP = 6630, + // 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 }; diff --git a/src/openrct2/paint/Painter.cpp b/src/openrct2/paint/Painter.cpp index bab73fd697..f887082363 100644 --- a/src/openrct2/paint/Painter.cpp +++ b/src/openrct2/paint/Painter.cpp @@ -18,6 +18,7 @@ #include "../drawing/Text.h" #include "../interface/Chat.h" #include "../interface/InteractiveConsole.h" +#include "../interface/Widget.h" #include "../localisation/FormatCodes.h" #include "../localisation/Formatting.h" #include "../localisation/Language.h" @@ -119,16 +120,23 @@ void Painter::PaintFPS(DrawPixelInfo& dpi) if (!ShouldShowFPS()) return; - ScreenCoordsXY screenCoords(_uiContext->GetWidth() / 2, 2); - MeasureFPS(); char buffer[64]{}; FormatStringToBuffer(buffer, sizeof(buffer), "{OUTLINE}{WHITE}{INT32}", _currentFPS); + const int32_t stringWidth = GfxGetStringWidth(buffer, FontStyle::Medium); - // Draw Text - int32_t stringWidth = GfxGetStringWidth(buffer, FontStyle::Medium); + // Figure out where counter should be rendered + ScreenCoordsXY screenCoords(_uiContext->GetWidth() / 2, 2); screenCoords.x = screenCoords.x - (stringWidth / 2); + + // Move counter below toolbar if buttons are centred + const bool isTitle = gScreenFlags == SCREEN_FLAGS_TITLE_DEMO; + if (!isTitle && Config::Get().interface.ToolbarButtonsCentred) + { + screenCoords.y = kTopToolbarHeight + 3; + } + DrawText(dpi, screenCoords, { COLOUR_WHITE }, buffer); // Make area dirty so the text doesn't get drawn over the last