mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-13 03:28:19 +00:00
Fix Y Alignment by respecting cursor height independent of character height
This commit is contained in:
parent
1112c9e6b7
commit
0b1960c532
|
@ -839,18 +839,20 @@ public:
|
||||||
TextEx(&Cursor, pText, -1);
|
TextEx(&Cursor, pText, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
float TextWidth(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0, float *pHeight = nullptr, float *pAlignedFontSize = nullptr, float *pMaxCharacterHeightInLine = nullptr) override
|
float TextWidth(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0, const STextSizeProperties &TextSizeProps = {}) override
|
||||||
{
|
{
|
||||||
CTextCursor Cursor;
|
CTextCursor Cursor;
|
||||||
SetCursor(&Cursor, 0, 0, Size, Flags);
|
SetCursor(&Cursor, 0, 0, Size, Flags);
|
||||||
Cursor.m_LineWidth = LineWidth;
|
Cursor.m_LineWidth = LineWidth;
|
||||||
TextEx(&Cursor, pText, StrLength);
|
TextEx(&Cursor, pText, StrLength);
|
||||||
if(pHeight != nullptr)
|
if(TextSizeProps.m_pHeight != nullptr)
|
||||||
*pHeight = Cursor.Height();
|
*TextSizeProps.m_pHeight = Cursor.Height();
|
||||||
if(pAlignedFontSize != nullptr)
|
if(TextSizeProps.m_pAlignedFontSize != nullptr)
|
||||||
*pAlignedFontSize = Cursor.m_AlignedFontSize;
|
*TextSizeProps.m_pAlignedFontSize = Cursor.m_AlignedFontSize;
|
||||||
if(pMaxCharacterHeightInLine != nullptr)
|
if(TextSizeProps.m_pMaxCharacterHeightInLine != nullptr)
|
||||||
*pMaxCharacterHeightInLine = Cursor.m_MaxCharacterHeight;
|
*TextSizeProps.m_pMaxCharacterHeightInLine = Cursor.m_MaxCharacterHeight;
|
||||||
|
if(TextSizeProps.m_pLineCount != nullptr)
|
||||||
|
*TextSizeProps.m_pLineCount = Cursor.m_LineCount;
|
||||||
return Cursor.m_LongestLineWidth;
|
return Cursor.m_LongestLineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,14 @@ struct STextContainerIndex
|
||||||
void Reset() { m_Index = -1; }
|
void Reset() { m_Index = -1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct STextSizeProperties
|
||||||
|
{
|
||||||
|
float *m_pHeight = nullptr;
|
||||||
|
float *m_pAlignedFontSize = nullptr;
|
||||||
|
float *m_pMaxCharacterHeightInLine = nullptr;
|
||||||
|
int *m_pLineCount = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
class ITextRender : public IInterface
|
class ITextRender : public IInterface
|
||||||
{
|
{
|
||||||
MACRO_INTERFACE("textrender", 0)
|
MACRO_INTERFACE("textrender", 0)
|
||||||
|
@ -279,7 +287,7 @@ public:
|
||||||
virtual void TextSelectionColor(float r, float g, float b, float a) = 0;
|
virtual void TextSelectionColor(float r, float g, float b, float a) = 0;
|
||||||
virtual void TextSelectionColor(ColorRGBA rgb) = 0;
|
virtual void TextSelectionColor(ColorRGBA rgb) = 0;
|
||||||
virtual void Text(float x, float y, float Size, const char *pText, float LineWidth = -1.0f) = 0;
|
virtual void Text(float x, float y, float Size, const char *pText, float LineWidth = -1.0f) = 0;
|
||||||
virtual float TextWidth(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0, float *pHeight = nullptr, float *pAlignedFontSize = nullptr, float *pMaxCharacterHeightInLine = nullptr) = 0;
|
virtual float TextWidth(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0, const STextSizeProperties &TextSizeProps = {}) = 0;
|
||||||
virtual STextBoundingBox TextBoundingBox(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0) = 0;
|
virtual STextBoundingBox TextBoundingBox(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0) = 0;
|
||||||
|
|
||||||
virtual ColorRGBA GetTextColor() const = 0;
|
virtual ColorRGBA GetTextColor() const = 0;
|
||||||
|
|
|
@ -547,11 +547,24 @@ void CUI::DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static vec2 CalcFontSizeAndBoundingBox(ITextRender *pTextRender, const char *pText, int Flags, float &Size, float MaxWidth, const SLabelProperties &LabelProps)
|
struct SCursorAndBoundingBox
|
||||||
{
|
{
|
||||||
|
vec2 m_TextSize;
|
||||||
|
float m_BiggestCharacterHeight;
|
||||||
|
int m_LineCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
static SCursorAndBoundingBox CalcFontSizeCursorHeightAndBoundingBox(ITextRender *pTextRender, const char *pText, int Flags, float &Size, float MaxWidth, const SLabelProperties &LabelProps)
|
||||||
|
{
|
||||||
|
float TextBoundingHeight = 0.0f;
|
||||||
float TextHeight = 0.0f;
|
float TextHeight = 0.0f;
|
||||||
|
int LineCount = 0;
|
||||||
float MaxTextWidth = LabelProps.m_MaxWidth != -1 ? LabelProps.m_MaxWidth : MaxWidth;
|
float MaxTextWidth = LabelProps.m_MaxWidth != -1 ? LabelProps.m_MaxWidth : MaxWidth;
|
||||||
float TextWidth = pTextRender->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, &TextHeight);
|
STextSizeProperties TextSizeProps{};
|
||||||
|
TextSizeProps.m_pHeight = &TextHeight;
|
||||||
|
TextSizeProps.m_pMaxCharacterHeightInLine = &TextBoundingHeight;
|
||||||
|
TextSizeProps.m_pLineCount = &LineCount;
|
||||||
|
float TextWidth = pTextRender->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, TextSizeProps);
|
||||||
while(TextWidth > MaxTextWidth + 0.001f)
|
while(TextWidth > MaxTextWidth + 0.001f)
|
||||||
{
|
{
|
||||||
if(!LabelProps.m_EnableWidthCheck)
|
if(!LabelProps.m_EnableWidthCheck)
|
||||||
|
@ -559,12 +572,16 @@ static vec2 CalcFontSizeAndBoundingBox(ITextRender *pTextRender, const char *pTe
|
||||||
if(Size < 4.0f)
|
if(Size < 4.0f)
|
||||||
break;
|
break;
|
||||||
Size -= 1.0f;
|
Size -= 1.0f;
|
||||||
TextWidth = pTextRender->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, &TextHeight);
|
TextWidth = pTextRender->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, TextSizeProps);
|
||||||
}
|
}
|
||||||
return vec2(TextWidth, TextHeight);
|
SCursorAndBoundingBox Res{};
|
||||||
|
Res.m_TextSize = vec2(TextWidth, TextHeight);
|
||||||
|
Res.m_BiggestCharacterHeight = TextBoundingHeight;
|
||||||
|
Res.m_LineCount = LineCount;
|
||||||
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 CUI::CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align)
|
vec2 CUI::CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align, const float *pBiggestCharHeight)
|
||||||
{
|
{
|
||||||
vec2 Cursor(pRect->x, pRect->y);
|
vec2 Cursor(pRect->x, pRect->y);
|
||||||
|
|
||||||
|
@ -581,7 +598,7 @@ vec2 CUI::CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align)
|
||||||
const int VerticalAlign = Align & TEXTALIGN_MASK_VERTICAL;
|
const int VerticalAlign = Align & TEXTALIGN_MASK_VERTICAL;
|
||||||
if(VerticalAlign == TEXTALIGN_MIDDLE)
|
if(VerticalAlign == TEXTALIGN_MIDDLE)
|
||||||
{
|
{
|
||||||
Cursor.y += (pRect->h - TextSize.y) / 2.0f;
|
Cursor.y += pBiggestCharHeight != nullptr ? ((pRect->h - *pBiggestCharHeight) / 2.0f - (TextSize.y - *pBiggestCharHeight)) : (pRect->h - TextSize.y) / 2.0f;
|
||||||
}
|
}
|
||||||
else if(VerticalAlign == TEXTALIGN_BOTTOM)
|
else if(VerticalAlign == TEXTALIGN_BOTTOM)
|
||||||
{
|
{
|
||||||
|
@ -594,8 +611,8 @@ vec2 CUI::CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align)
|
||||||
void CUI::DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps)
|
void CUI::DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps)
|
||||||
{
|
{
|
||||||
const int Flags = LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0;
|
const int Flags = LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0;
|
||||||
const vec2 TextBounds = CalcFontSizeAndBoundingBox(TextRender(), pText, Flags, Size, pRect->w, LabelProps);
|
const SCursorAndBoundingBox TextBounds = CalcFontSizeCursorHeightAndBoundingBox(TextRender(), pText, Flags, Size, pRect->w, LabelProps);
|
||||||
const vec2 CursorPos = CalcAlignedCursorPos(pRect, TextBounds, Align);
|
const vec2 CursorPos = CalcAlignedCursorPos(pRect, TextBounds.m_TextSize, Align, TextBounds.m_LineCount == 1 ? &TextBounds.m_BiggestCharacterHeight : nullptr);
|
||||||
|
|
||||||
CTextCursor Cursor;
|
CTextCursor Cursor;
|
||||||
TextRender()->SetCursor(&Cursor, CursorPos.x, CursorPos.y, Size, TEXTFLAG_RENDER | Flags);
|
TextRender()->SetCursor(&Cursor, CursorPos.x, CursorPos.y, Size, TEXTFLAG_RENDER | Flags);
|
||||||
|
@ -606,7 +623,7 @@ void CUI::DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align
|
||||||
void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps, int StrLen, const CTextCursor *pReadCursor)
|
void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps, int StrLen, const CTextCursor *pReadCursor)
|
||||||
{
|
{
|
||||||
const int Flags = pReadCursor ? (pReadCursor->m_Flags & ~TEXTFLAG_RENDER) : LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0;
|
const int Flags = pReadCursor ? (pReadCursor->m_Flags & ~TEXTFLAG_RENDER) : LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0;
|
||||||
const vec2 TextBounds = CalcFontSizeAndBoundingBox(TextRender(), pText, Flags, Size, pRect->w, LabelProps);
|
const SCursorAndBoundingBox TextBounds = CalcFontSizeCursorHeightAndBoundingBox(TextRender(), pText, Flags, Size, pRect->w, LabelProps);
|
||||||
|
|
||||||
CTextCursor Cursor;
|
CTextCursor Cursor;
|
||||||
if(pReadCursor)
|
if(pReadCursor)
|
||||||
|
@ -615,7 +632,7 @@ void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, cons
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const vec2 CursorPos = CalcAlignedCursorPos(pRect, TextBounds, Align);
|
const vec2 CursorPos = CalcAlignedCursorPos(pRect, TextBounds.m_TextSize, Align);
|
||||||
TextRender()->SetCursor(&Cursor, CursorPos.x, CursorPos.y, Size, TEXTFLAG_RENDER | Flags);
|
TextRender()->SetCursor(&Cursor, CursorPos.x, CursorPos.y, Size, TEXTFLAG_RENDER | Flags);
|
||||||
}
|
}
|
||||||
Cursor.m_LineWidth = LabelProps.m_MaxWidth;
|
Cursor.m_LineWidth = LabelProps.m_MaxWidth;
|
||||||
|
@ -798,7 +815,9 @@ bool CUI::DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float
|
||||||
bool ReturnValue = DoEditBox(pLineInput, &EditBox, FontSize, Corners & ~IGraphics::CORNER_R);
|
bool ReturnValue = DoEditBox(pLineInput, &EditBox, FontSize, Corners & ~IGraphics::CORNER_R);
|
||||||
|
|
||||||
ClearButton.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.33f * ButtonColorMul(pLineInput->GetClearButtonId())), Corners & ~IGraphics::CORNER_L, 3.0f);
|
ClearButton.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.33f * ButtonColorMul(pLineInput->GetClearButtonId())), Corners & ~IGraphics::CORNER_L, 3.0f);
|
||||||
|
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
||||||
DoLabel(&ClearButton, "×", ClearButton.h * CUI::ms_FontmodHeight * 0.8f, TEXTALIGN_MC);
|
DoLabel(&ClearButton, "×", ClearButton.h * CUI::ms_FontmodHeight * 0.8f, TEXTALIGN_MC);
|
||||||
|
TextRender()->SetRenderFlags(0);
|
||||||
if(DoButtonLogic(pLineInput->GetClearButtonId(), 0, &ClearButton))
|
if(DoButtonLogic(pLineInput->GetClearButtonId(), 0, &ClearButton))
|
||||||
{
|
{
|
||||||
pLineInput->Clear();
|
pLineInput->Clear();
|
||||||
|
@ -1177,7 +1196,9 @@ void CUI::ShowPopupMessage(float X, float Y, SMessagePopupContext *pContext)
|
||||||
{
|
{
|
||||||
const float TextWidth = minimum(std::ceil(TextRender()->TextWidth(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, -1.0f)), SMessagePopupContext::POPUP_MAX_WIDTH);
|
const float TextWidth = minimum(std::ceil(TextRender()->TextWidth(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, -1.0f)), SMessagePopupContext::POPUP_MAX_WIDTH);
|
||||||
float TextHeight = 0.0f;
|
float TextHeight = 0.0f;
|
||||||
TextRender()->TextWidth(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, TextWidth, 0, &TextHeight);
|
STextSizeProperties TextSizeProps{};
|
||||||
|
TextSizeProps.m_pHeight = &TextHeight;
|
||||||
|
TextRender()->TextWidth(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, TextWidth, 0, TextSizeProps);
|
||||||
pContext->m_pUI = this;
|
pContext->m_pUI = this;
|
||||||
DoPopupMenu(pContext, X, Y, TextWidth + 10.0f, TextHeight + 10.0f, pContext, PopupMessage);
|
DoPopupMenu(pContext, X, Y, TextWidth + 10.0f, TextHeight + 10.0f, pContext, PopupMessage);
|
||||||
}
|
}
|
||||||
|
@ -1202,7 +1223,9 @@ void CUI::ShowPopupConfirm(float X, float Y, SConfirmPopupContext *pContext)
|
||||||
{
|
{
|
||||||
const float TextWidth = minimum(std::ceil(TextRender()->TextWidth(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, -1.0f)), SConfirmPopupContext::POPUP_MAX_WIDTH);
|
const float TextWidth = minimum(std::ceil(TextRender()->TextWidth(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, -1.0f)), SConfirmPopupContext::POPUP_MAX_WIDTH);
|
||||||
float TextHeight = 0.0f;
|
float TextHeight = 0.0f;
|
||||||
TextRender()->TextWidth(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, TextWidth, 0, &TextHeight);
|
STextSizeProperties TextSizeProps{};
|
||||||
|
TextSizeProps.m_pHeight = &TextHeight;
|
||||||
|
TextRender()->TextWidth(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, TextWidth, 0, TextSizeProps);
|
||||||
const float PopupHeight = TextHeight + SConfirmPopupContext::POPUP_BUTTON_HEIGHT + SConfirmPopupContext::POPUP_BUTTON_SPACING + 10.0f;
|
const float PopupHeight = TextHeight + SConfirmPopupContext::POPUP_BUTTON_HEIGHT + SConfirmPopupContext::POPUP_BUTTON_SPACING + 10.0f;
|
||||||
pContext->m_pUI = this;
|
pContext->m_pUI = this;
|
||||||
pContext->m_Result = SConfirmPopupContext::UNSET;
|
pContext->m_Result = SConfirmPopupContext::UNSET;
|
||||||
|
|
|
@ -433,7 +433,7 @@ public:
|
||||||
int DoDraggableButtonLogic(const void *pID, int Checked, const CUIRect *pRect, bool *pClicked, bool *pAbrupted);
|
int DoDraggableButtonLogic(const void *pID, int Checked, const CUIRect *pRect, bool *pClicked, bool *pAbrupted);
|
||||||
int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY);
|
int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY);
|
||||||
void DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange, float ViewPortSize, float TotalSize, bool SmoothClamp = false, float ScrollSpeed = 10.0f);
|
void DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange, float ViewPortSize, float TotalSize, bool SmoothClamp = false, float ScrollSpeed = 10.0f);
|
||||||
static vec2 CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align);
|
static vec2 CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align, const float *pBiggestCharHeight = nullptr);
|
||||||
|
|
||||||
void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps = {});
|
void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps = {});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue