ddnet/src/game/client/components/tooltips.cpp

121 lines
3 KiB
C++
Raw Normal View History

#include "tooltips.h"
#include <game/client/render.h>
#include <game/client/ui.h>
CTooltips::CTooltips()
{
2022-04-18 07:34:21 +00:00
OnReset();
}
void CTooltips::OnReset()
{
m_HoverTime = -1;
2022-04-18 07:34:21 +00:00
m_Tooltips.clear();
}
void CTooltips::SetActiveTooltip(CTooltip &Tooltip)
{
if(m_ActiveTooltip.has_value())
2022-04-18 07:34:21 +00:00
return;
m_ActiveTooltip.emplace(Tooltip);
m_HoverTime = time_get();
}
inline void CTooltips::ClearActiveTooltip()
{
m_ActiveTooltip.reset();
}
void CTooltips::DoToolTip(const void *pID, const CUIRect *pNearRect, const char *pText, float WidthHint)
{
2022-04-18 07:34:21 +00:00
uintptr_t ID = reinterpret_cast<uintptr_t>(pID);
const auto result = m_Tooltips.emplace(ID, CTooltip{
*pNearRect,
pText,
WidthHint,
false});
CTooltip &Tooltip = result.first->second;
2022-04-18 07:34:21 +00:00
if(!result.second)
2022-04-18 07:34:21 +00:00
{
Tooltip.m_Rect = *pNearRect; // update in case of window resize
Tooltip.m_pText = pText; // update in case of language change
2022-04-18 07:34:21 +00:00
}
Tooltip.m_OnScreen = true;
if(UI()->MouseInside(&Tooltip.m_Rect))
2022-04-18 07:34:21 +00:00
{
SetActiveTooltip(Tooltip);
2022-04-18 07:34:21 +00:00
}
}
void CTooltips::OnRender()
{
if(m_ActiveTooltip.has_value())
2022-04-18 07:34:21 +00:00
{
CTooltip &Tooltip = m_ActiveTooltip.value();
2022-04-18 07:34:21 +00:00
if(!UI()->MouseInside(&Tooltip.m_Rect))
{
Tooltip.m_OnScreen = false;
2022-04-18 07:34:21 +00:00
ClearActiveTooltip();
return;
}
if(!Tooltip.m_OnScreen)
return;
2022-04-18 07:34:21 +00:00
// Delay tooltip until 1 second passed.
if(m_HoverTime > time_get() - time_freq())
2022-04-18 07:34:21 +00:00
return;
constexpr float FontSize = 14.0f;
constexpr float Margin = 5.0f;
constexpr float Padding = 5.0f;
2022-04-18 07:34:21 +00:00
const STextBoundingBox BoundingBox = TextRender()->TextBoundingBox(FontSize, Tooltip.m_pText, -1, Tooltip.m_WidthHint);
2022-04-18 07:34:21 +00:00
CUIRect Rect;
Rect.w = BoundingBox.m_W + 2 * Padding;
Rect.h = BoundingBox.m_H + 2 * Padding;
2022-04-18 07:34:21 +00:00
const CUIRect *pScreen = UI()->Screen();
Rect.w = minimum(Rect.w, pScreen->w - 2 * Margin);
Rect.h = minimum(Rect.h, pScreen->h - 2 * Margin);
2022-04-18 07:34:21 +00:00
// Try the top side.
if(Tooltip.m_Rect.y - Rect.h - Margin > pScreen->y)
2022-04-18 07:34:21 +00:00
{
Rect.x = clamp(UI()->MouseX() - Rect.w / 2.0f, Margin, pScreen->w - Rect.w - Margin);
Rect.y = Tooltip.m_Rect.y - Rect.h - Margin;
2022-04-18 07:34:21 +00:00
}
// Try the bottom side.
else if(Tooltip.m_Rect.y + Tooltip.m_Rect.h + Margin < pScreen->h)
2022-04-18 07:34:21 +00:00
{
Rect.x = clamp(UI()->MouseX() - Rect.w / 2.0f, Margin, pScreen->w - Rect.w - Margin);
Rect.y = Tooltip.m_Rect.y + Tooltip.m_Rect.h + Margin;
2022-04-18 07:34:21 +00:00
}
// Try the right side.
else if(Tooltip.m_Rect.x + Tooltip.m_Rect.w + Margin + Rect.w < pScreen->w)
2022-04-18 07:34:21 +00:00
{
Rect.x = Tooltip.m_Rect.x + Tooltip.m_Rect.w + Margin;
Rect.y = clamp(UI()->MouseY() - Rect.h / 2.0f, Margin, pScreen->h - Rect.h - Margin);
2022-04-18 07:34:21 +00:00
}
// Try the left side.
else if(Tooltip.m_Rect.x - Rect.w - Margin > pScreen->x)
2022-04-18 07:34:21 +00:00
{
Rect.x = Tooltip.m_Rect.x - Rect.w - Margin;
Rect.y = clamp(UI()->MouseY() - Rect.h / 2.0f, Margin, pScreen->h - Rect.h - Margin);
2022-04-18 07:34:21 +00:00
}
Rect.Draw(ColorRGBA(0.2f, 0.2f, 0.2f, 0.8f), IGraphics::CORNER_ALL, Padding);
Rect.Margin(Padding, &Rect);
SLabelProperties Props;
Props.m_MaxWidth = Tooltip.m_WidthHint;
UI()->DoLabel(&Rect, Tooltip.m_pText, FontSize, TEXTALIGN_ML, Props);
Tooltip.m_OnScreen = false;
2022-04-18 07:34:21 +00:00
}
}