diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 98f7b8ab41..93e737885a 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -4,6 +4,7 @@ - Improved: [#18632, #21306] Land ownership and construction rights are now shown on top of the water. - Improved: [#20951] Activate OpenRCT2 window after using native file dialog on macOS. - Improved: [#21184] The construction marker for rides, paths and large scenery is now shown on top of the water. +- Improved: [#21192] Tooltips will now follow the cursor. - Improved: [#21227] Entrance style dropdown is now sorted alphabetically everywhere. - Change: [#21200] Raise maximum lift speeds of the Reverser Coaster, Side Friction Coaster, and Virginia Reel for RCT1 parity. - Change: [#21225] Raise maximum allowed misc entities to 1600. diff --git a/src/openrct2-ui/windows/Tooltip.cpp b/src/openrct2-ui/windows/Tooltip.cpp index a88b550338..a842bc4ea9 100644 --- a/src/openrct2-ui/windows/Tooltip.cpp +++ b/src/openrct2-ui/windows/Tooltip.cpp @@ -40,13 +40,20 @@ public: TooltipWindow(const OpenRCT2String& message, ScreenCoordsXY screenCoords) { int32_t textWidth = FormatTextForTooltip(message); - width = textWidth + 3; - height = ((_tooltipNumLines + 1) * FontGetLineHeight(FontStyle::Small)) + 4; + int32_t textHeight = ((_tooltipNumLines + 1) * FontGetLineHeight(FontStyle::Small)); + + width = textWidth + 5; + height = textHeight + 4; widgets = _tooltipWidgets; widgets[WIDX_BACKGROUND].right = width; widgets[WIDX_BACKGROUND].bottom = height; + UpdatePosition(screenCoords); + } + + void UpdatePosition(ScreenCoordsXY screenCoords) + { int32_t screenWidth = ContextGetWidth(); int32_t screenHeight = ContextGetHeight(); screenCoords.x = std::clamp(screenCoords.x - (width / 2), 0, screenWidth - width); @@ -54,15 +61,29 @@ public: // TODO The cursor size will be relative to the window DPI. // The amount to offset the y should be adjusted. - int32_t max_y = screenHeight - height; - screenCoords.y += 26; // Normally, we'd display the tooltip 26 lower - if (screenCoords.y > max_y) - // If y is too large, the tooltip could be forced below the cursor if we'd just clamped y, - // so we'll subtract a bit more - screenCoords.y -= height + 40; - screenCoords.y = std::clamp(screenCoords.y, 22, max_y); + const int32_t cursorHeight = 20; + const int32_t cursorMargin = 4; + const int32_t cursorOffset = cursorHeight + cursorMargin; - windowPos = screenCoords; + const int32_t maxY = screenHeight - height; + + if (screenCoords.y + cursorOffset > maxY) + { + // Display the tooltip above the cursor if there is not enough space below. + screenCoords.y -= (height + cursorMargin); + } + else + { + // Display the tooltip under the cursor if there is enough space below. + screenCoords.y += cursorOffset; + } + + screenCoords.y = std::clamp(screenCoords.y, cursorOffset, maxY); + + if (windowPos != screenCoords) + { + WindowSetPosition(*this, screenCoords); + } } void OnOpen() override @@ -72,7 +93,7 @@ public: void OnUpdate() override { - ResetTooltipNotShown(); + UpdatePosition(gTooltipCursor); } void OnDraw(DrawPixelInfo& dpi) override @@ -172,9 +193,6 @@ void WindowTooltipOpen(WindowBase* widgetWindow, WidgetIndex widgetIndex, const else { auto stringId = widget->tooltip; - if (stringId == STR_NONE) - return; - gTooltipWidget.window_classification = widgetWindow->classification; gTooltipWidget.window_number = widgetWindow->number; gTooltipWidget.widget_index = widgetIndex;