4267: Add DoTooltip r=def- a=edg-l

Related to #4212

Example rendering a label:

![image](https://user-images.githubusercontent.com/15859336/139472955-65c00603-9f37-484a-9552-adde9ef99822.png)

![image](https://user-images.githubusercontent.com/15859336/139472972-b1fc2fe7-a84e-4eb5-aaa7-8e9522ec6b8a.png)


## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Edgar Luque <git@edgarluque.com>
This commit is contained in:
bors[bot] 2022-04-07 08:12:05 +00:00 committed by GitHub
commit 62c361fe29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 0 deletions

View file

@ -2833,3 +2833,63 @@ bool CMenus::HandleListInputs(const CUIRect &View, float &ScrollValue, const flo
return NewIndex != -1;
}
void CMenus::DoToolTip(const void *pID, const CUIRect *pNearRect, const char *pText, float WidthHint)
{
static int64_t HoverTime = -1;
if(!UI()->MouseInside(pNearRect))
{
if(pID == UI()->ActiveTooltipItem())
HoverTime = -1;
return;
}
UI()->SetActiveTooltipItem(pID);
if(HoverTime == -1)
HoverTime = time_get();
// Delay tooltip until 1 second passed.
if(HoverTime > time_get() - time_freq())
return;
const float MARGIN = 5.0f;
CUIRect Rect;
Rect.w = WidthHint;
if(WidthHint < 0.0f)
Rect.w = TextRender()->TextWidth(0, 14.0f, pText, -1, -1.0f) + 4.0f;
Rect.h = 30.0f;
CUIRect *pScreen = UI()->Screen();
// Try the top side.
if(pNearRect->y - Rect.h - MARGIN > pScreen->y)
{
Rect.x = clamp(UI()->MouseX() - Rect.w / 2.0f, MARGIN, pScreen->w - Rect.w - MARGIN);
Rect.y = pNearRect->y - Rect.h - MARGIN;
}
// Try the bottom side.
else if(pNearRect->y + pNearRect->h + MARGIN < pScreen->h)
{
Rect.x = clamp(UI()->MouseX() - Rect.w / 2.0f, MARGIN, pScreen->w - Rect.w - MARGIN);
Rect.y = pNearRect->y + pNearRect->h + MARGIN;
}
// Try the right side.
else if(pNearRect->x + pNearRect->w + MARGIN + Rect.w < pScreen->w)
{
Rect.x = pNearRect->x + pNearRect->w + MARGIN;
Rect.y = clamp(UI()->MouseY() - Rect.h / 2.0f, MARGIN, pScreen->h - Rect.h - MARGIN);
}
// Try the left side.
else if(pNearRect->x - Rect.w - MARGIN > pScreen->x)
{
Rect.x = pNearRect->x - Rect.w - MARGIN;
Rect.y = clamp(UI()->MouseY() - Rect.h / 2.0f, MARGIN, pScreen->h - Rect.h - MARGIN);
}
RenderTools()->DrawUIRect(&Rect, ColorRGBA(0.2, 0.2, 0.2, 0.80f), CUI::CORNER_ALL, 5.0f);
Rect.Margin(2.0f, &Rect);
UI()->DoLabel(&Rect, pText, 14.0f, TEXTALIGN_LEFT);
}

View file

@ -205,6 +205,15 @@ class CMenus : public CComponent
int UiLogicGetCurrentClickedItem();
/**
* Places and renders a tooltip near pNearRect.
* For now only works correctly with single line tooltips, since Text width calculation gets broken when there are multiple lines.
*
* @param pID The ID of the tooltip. Usually a reference to some g_Config value.
* @param pNearTo Place the tooltip near this rect.
* @param pText The text to display in the tooltip
*/
void DoToolTip(const void *pID, const CUIRect *pNearRect, const char *pText, float WidthHint = -1.0f);
// menus_settings_assets.cpp
public:
struct SCustomItem

View file

@ -530,6 +530,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
{
m_Dummy ^= 1;
}
DoToolTip(&m_Dummy, &DummyLabel, Localize("Toggle to edit your dummy settings."));
Dummy.HSplitTop(20.0f, &DummyLabel, &Dummy);
@ -1264,6 +1265,7 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_GfxHighDetail, Localize("High Detail"), g_Config.m_GfxHighDetail, &Button))
g_Config.m_GfxHighDetail ^= 1;
DoToolTip(&g_Config.m_GfxHighDetail, &Button, Localize("Allows maps to render with more detail."));
MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_GfxHighdpi, Localize("Use high DPI"), g_Config.m_GfxHighdpi, &Button))

View file

@ -57,6 +57,7 @@ CUI::CUI()
m_pActiveItem = 0;
m_pLastActiveItem = 0;
m_pBecomingHotItem = 0;
m_pActiveTooltipItem = 0;
m_MouseX = 0;
m_MouseY = 0;

View file

@ -194,6 +194,7 @@ class CUI
const void *m_pActiveItem;
const void *m_pLastActiveItem;
const void *m_pBecomingHotItem;
const void *m_pActiveTooltipItem;
float m_MouseX, m_MouseY; // in gui space
float m_MouseDeltaX, m_MouseDeltaY; // in gui space
float m_MouseWorldX, m_MouseWorldY; // in world space
@ -261,10 +262,12 @@ public:
if(pID)
m_pLastActiveItem = pID;
}
void SetActiveTooltipItem(const void *pID) { m_pActiveTooltipItem = pID; }
void ClearLastActiveItem() { m_pLastActiveItem = 0; }
const void *HotItem() const { return m_pHotItem; }
const void *NextHotItem() const { return m_pBecomingHotItem; }
const void *ActiveItem() const { return m_pActiveItem; }
const void *ActiveTooltipItem() const { return m_pActiveTooltipItem; }
const void *LastActiveItem() const { return m_pLastActiveItem; }
bool MouseInside(const CUIRect *pRect) const;