6680: Improve demo slice popup r=def- a=Robyt3

Show begin time, end time and length of demo cut in popup.

Replace demo slice error/confirm messages with generic popups.

Improve layout. Remove unnecessary empty space.

Screenshots:
- Popup:
  - Before:
![popup old](https://github.com/ddnet/ddnet/assets/23437060/b1e22fbb-b8b0-4e90-8c1b-a2866286e4f3)
  - After:
![popup new](https://github.com/ddnet/ddnet/assets/23437060/c057a2a8-7259-4512-bd2d-dca84567f841)
- Error:
  - Before:
![error old](https://github.com/ddnet/ddnet/assets/23437060/b77cd8d5-e127-4eab-bdcf-61323904b050)
  - After:
![error new](https://github.com/ddnet/ddnet/assets/23437060/afdde8c1-3f14-45c7-8c54-968d3bcb0f92)
- Confirm:
  - Before:
![confirm old](https://github.com/ddnet/ddnet/assets/23437060/fa31919f-00ca-4099-8e03-e26130ed8022)
  - After:
![confirm new](https://github.com/ddnet/ddnet/assets/23437060/54f7c268-f806-484b-a069-53cf12e88be1)

## Checklist

- [X] Tested the change ingame
- [X] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] 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: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
bors[bot] 2023-05-28 13:33:10 +00:00 committed by GitHub
commit 8b316d5045
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 152 additions and 124 deletions

View file

@ -443,6 +443,7 @@ protected:
void FetchAllHeaders();
void HandleDemoSeeking(float PositionToSeek, float TimeToSeek);
void RenderDemoPlayer(CUIRect MainView);
void RenderDemoPlayerSliceSavePopup(CUIRect MainView);
void RenderDemoList(CUIRect MainView);
void PopupConfirmDeleteDemo();
@ -646,7 +647,6 @@ public:
std::chrono::nanoseconds m_PopupWarningDuration;
int m_DemoPlayerState;
char m_aDemoPlayerPopupHint[256];
enum
{

View file

@ -112,107 +112,8 @@ void CMenus::DemoSeekTick(IDemoPlayer::ETickOffset TickOffset)
void CMenus::RenderDemoPlayer(CUIRect MainView)
{
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
const float SeekBarHeight = 15.0f;
const float ButtonbarHeight = 20.0f;
const float NameBarHeight = 20.0f;
const float Margins = 5.0f;
static int64_t s_LastSpeedChange = 0;
// render popups
if(m_DemoPlayerState == DEMOPLAYER_SLICE_SAVE)
{
CUIRect Screen = *UI()->Screen();
CUIRect Box, Part, Part2;
Box = Screen;
Box.Margin(150.0f, &Box);
// render the box
Box.Draw(ColorRGBA(0, 0, 0, 0.5f), IGraphics::CORNER_ALL, 15.0f);
Box.HSplitTop(20.f, 0, &Box);
Box.HSplitTop(24.f, &Part, &Box);
UI()->DoLabel(&Part, Localize("Select a name"), 24.f, TEXTALIGN_MC);
Box.HSplitTop(20.f, 0, &Box);
Box.HSplitTop(20.f, &Part, &Box);
Part.VMargin(20.f, &Part);
UI()->DoLabel(&Part, m_aDemoPlayerPopupHint, 20.f, TEXTALIGN_MC);
Box.HSplitTop(20.f, 0, &Box);
CUIRect Label, TextBox, Ok, Abort;
Box.HSplitBottom(20.f, &Box, 0);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VMargin(80.0f, &Part);
Part.VSplitMid(&Abort, &Ok);
Ok.VMargin(20.0f, &Ok);
Abort.VMargin(20.0f, &Abort);
static int s_RemoveChat = 0;
static CButtonContainer s_ButtonAbort;
if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
m_DemoPlayerState = DEMOPLAYER_NONE;
static CButtonContainer s_ButtonOk;
if(DoButton_Menu(&s_ButtonOk, Localize("Ok"), 0, &Ok) || UI()->ConsumeHotkey(CUI::HOTKEY_ENTER))
{
char aDemoName[IO_MAX_PATH_LENGTH];
DemoPlayer()->GetDemoName(aDemoName, sizeof(aDemoName));
str_append(aDemoName, ".demo", sizeof(aDemoName));
if(!str_endswith(m_DemoSliceInput.GetString(), ".demo"))
m_DemoSliceInput.Append(".demo");
if(str_comp(aDemoName, m_DemoSliceInput.GetString()) == 0)
str_copy(m_aDemoPlayerPopupHint, Localize("Please use a different name"));
else
{
char aPath[IO_MAX_PATH_LENGTH];
str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_DemoSliceInput.GetString());
IOHANDLE DemoFile = Storage()->OpenFile(aPath, IOFLAG_READ, IStorage::TYPE_SAVE);
const char *pStr = Localize("File already exists, do you want to overwrite it?");
if(DemoFile && str_comp(m_aDemoPlayerPopupHint, pStr) != 0)
{
io_close(DemoFile);
str_copy(m_aDemoPlayerPopupHint, pStr);
}
else
{
if(DemoFile)
io_close(DemoFile);
m_DemoPlayerState = DEMOPLAYER_NONE;
Client()->DemoSlice(aPath, CMenus::DemoFilterChat, &s_RemoveChat);
DemolistPopulate();
DemolistOnUpdate(false);
}
}
}
Box.HSplitTop(24.f, &Part, &Box);
Box.HSplitTop(10.f, 0, &Box);
Box.HSplitTop(24.f, &Part2, &Box);
Part2.VSplitLeft(60.0f, 0, &Label);
if(DoButton_CheckBox(&s_RemoveChat, Localize("Remove chat"), s_RemoveChat, &Label))
{
s_RemoveChat ^= 1;
}
Part.VSplitLeft(60.0f, 0, &Label);
Label.VSplitLeft(120.0f, 0, &TextBox);
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("New name:"), 18.0f, TEXTALIGN_ML);
if(UI()->DoEditBox(&m_DemoSliceInput, &TextBox, 12.0f))
{
m_aDemoPlayerPopupHint[0] = '\0';
}
}
// handle keyboard shortcuts independent of active menu
float PositionToSeek = -1.0f;
float TimeToSeek = 0.0f;
@ -294,7 +195,11 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
}
}
float TotalHeight = SeekBarHeight + ButtonbarHeight + NameBarHeight + Margins * 3;
const float SeekBarHeight = 15.0f;
const float ButtonbarHeight = 20.0f;
const float NameBarHeight = 20.0f;
const float Margins = 5.0f;
const float TotalHeight = SeekBarHeight + ButtonbarHeight + NameBarHeight + Margins * 3;
// render speed info
if(g_Config.m_ClDemoShowSpeed && time_get() - s_LastSpeedChange < time_freq() * 1)
@ -321,20 +226,18 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
return;
}
MainView.HSplitBottom(TotalHeight, 0, &MainView);
MainView.VSplitLeft(50.0f, 0, &MainView);
MainView.VSplitLeft(600.0f, &MainView, 0);
MainView.Draw(ms_ColorTabbarActive, IGraphics::CORNER_T, 10.0f);
MainView.Margin(5.0f, &MainView);
CUIRect DemoControls;
MainView.HSplitBottom(TotalHeight, nullptr, &DemoControls);
DemoControls.VSplitLeft(50.0f, nullptr, &DemoControls);
DemoControls.VSplitLeft(600.0f, &DemoControls, nullptr);
DemoControls.Draw(ms_ColorTabbarActive, IGraphics::CORNER_T, 10.0f);
CUIRect SeekBar, ButtonBar, NameBar, SpeedBar;
MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
ButtonBar.HSplitTop(Margins, 0, &ButtonBar);
DemoControls.Margin(5.0f, &DemoControls);
DemoControls.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
ButtonBar.HSplitTop(Margins, nullptr, &ButtonBar);
ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar);
NameBar.HSplitTop(4.0f, 0, &NameBar);
NameBar.HSplitTop(4.0f, nullptr, &NameBar);
// do seekbar
{
@ -483,7 +386,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_PlayPauseButton, &Button, pInfo->m_Paused ? Localize("Play the current demo") : Localize("Pause the current demo"));
// stop button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_ResetButton;
if(DoButton_FontIcon(&s_ResetButton, FONT_ICON_STOP, false, &Button, IGraphics::CORNER_ALL))
@ -494,7 +397,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_ResetButton, &Button, Localize("Stop the current demo"));
// one tick back
ButtonBar.VSplitLeft(Margins + 10.0f, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins + 10.0f, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneTickBackButton;
if(DoButton_FontIcon(&s_OneTickBackButton, FONT_ICON_CHEVRON_LEFT, 0, &Button, IGraphics::CORNER_ALL))
@ -502,7 +405,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_OneTickBackButton, &Button, Localize("Go back one tick"));
// one tick forward
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneTickForwardButton;
if(DoButton_FontIcon(&s_OneTickForwardButton, FONT_ICON_CHEVRON_RIGHT, 0, &Button, IGraphics::CORNER_ALL))
@ -543,7 +446,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_SliceBeginButton, &Button, Localize("Mark the beginning of a cut"));
// slice end button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_SliceEndButton;
if(DoButton_FontIcon(&s_SliceEndButton, FONT_ICON_RIGHT_TO_BRACKET, 0, &Button, IGraphics::CORNER_ALL))
@ -555,7 +458,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_SliceEndButton, &Button, Localize("Mark the end of a cut"));
// slice save button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_SliceSaveButton;
if(DoButton_FontIcon(&s_SliceSaveButton, FONT_ICON_ARROW_UP_RIGHT_FROM_SQUARE, 0, &Button, IGraphics::CORNER_ALL))
@ -565,7 +468,6 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
m_DemoSliceInput.Set(aDemoName);
m_DemoSliceInput.Append(".demo");
UI()->SetActiveItem(&m_DemoSliceInput);
m_aDemoPlayerPopupHint[0] = '\0';
m_DemoPlayerState = DEMOPLAYER_SLICE_SAVE;
}
GameClient()->m_Tooltips.DoToolTip(&s_SliceSaveButton, &Button, Localize("Export cut as a separate demo"));
@ -574,7 +476,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
const int Threshold = 10;
// one marker back
ButtonBar.VSplitLeft(Margins + 20.0f, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins + 20.0f, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneMarkerBackButton;
if(DoButton_FontIcon(&s_OneMarkerBackButton, FONT_ICON_BACKWARD_STEP, 0, &Button, IGraphics::CORNER_ALL))
@ -590,7 +492,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_OneMarkerBackButton, &Button, Localize("Go back one marker"));
// one marker forward
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneMarkerForwardButton;
if(DoButton_FontIcon(&s_OneMarkerForwardButton, FONT_ICON_FORWARD_STEP, 0, &Button, IGraphics::CORNER_ALL))
@ -615,7 +517,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
}
// toggle keyboard shortcuts button
ButtonBar.VSplitRight(Margins, &ButtonBar, 0);
ButtonBar.VSplitRight(Margins, &ButtonBar, nullptr);
ButtonBar.VSplitRight(ButtonbarHeight, &ButtonBar, &Button);
static CButtonContainer s_KeyboardShortcutsButton;
if(DoButton_FontIcon(&s_KeyboardShortcutsButton, FONT_ICON_KEYBOARD, 0, &Button, IGraphics::CORNER_ALL, g_Config.m_ClDemoKeyboardShortcuts != 0))
@ -631,7 +533,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
str_format(aBuf, sizeof(aBuf), Localize("Demofile: %s"), aDemoName);
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, NameBar.x, NameBar.y + (NameBar.h - (Button.h * 0.5f)) / 2.f, Button.h * 0.5f, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = MainView.w;
Cursor.m_LineWidth = DemoControls.w;
TextRender()->TextEx(&Cursor, aBuf, -1);
if(IncreaseDemoSpeed)
@ -646,6 +548,132 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
}
HandleDemoSeeking(PositionToSeek, TimeToSeek);
// render popups
if(m_DemoPlayerState != DEMOPLAYER_NONE)
{
// prevent element under the active popup from being activated
UI()->SetHotItem(nullptr);
}
if(m_DemoPlayerState == DEMOPLAYER_SLICE_SAVE)
{
RenderDemoPlayerSliceSavePopup(MainView);
}
UI()->RenderPopupMenus();
}
void CMenus::RenderDemoPlayerSliceSavePopup(CUIRect MainView)
{
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
CUIRect Box;
MainView.Margin(150.0f, &Box);
// background
Box.Draw(ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f), IGraphics::CORNER_ALL, 15.0f);
Box.Margin(24.0f, &Box);
// title
CUIRect Title;
Box.HSplitTop(24.0f, &Title, &Box);
Box.HSplitTop(20.0f, nullptr, &Box);
UI()->DoLabel(&Title, Localize("Export demo cut"), 24.0f, TEXTALIGN_MC);
// slice times
CUIRect SliceTimesBar, SliceInterval, SliceLength;
Box.HSplitTop(24.0f, &SliceTimesBar, &Box);
SliceTimesBar.VSplitMid(&SliceInterval, &SliceLength, 40.0f);
Box.HSplitTop(20.0f, nullptr, &Box);
const int64_t RealSliceBegin = g_Config.m_ClDemoSliceBegin == -1 ? 0 : (g_Config.m_ClDemoSliceBegin - pInfo->m_FirstTick);
const int64_t RealSliceEnd = (g_Config.m_ClDemoSliceEnd == -1 ? pInfo->m_LastTick : g_Config.m_ClDemoSliceEnd) - pInfo->m_FirstTick;
char aSliceBegin[32];
str_time(RealSliceBegin / SERVER_TICK_SPEED * 100, TIME_HOURS, aSliceBegin, sizeof(aSliceBegin));
char aSliceEnd[32];
str_time(RealSliceEnd / SERVER_TICK_SPEED * 100, TIME_HOURS, aSliceEnd, sizeof(aSliceEnd));
char aSliceLength[32];
str_time((RealSliceEnd - RealSliceBegin) / SERVER_TICK_SPEED * 100, TIME_HOURS, aSliceLength, sizeof(aSliceLength));
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "%s: %s %s", Localize("Cut interval"), aSliceBegin, aSliceEnd);
UI()->DoLabel(&SliceInterval, aBuf, 18.0f, TEXTALIGN_ML);
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Cut length"), aSliceLength);
UI()->DoLabel(&SliceLength, aBuf, 18.0f, TEXTALIGN_ML);
// file name
CUIRect NameLabel, NameBox;
Box.HSplitTop(24.0f, &NameLabel, &Box);
Box.HSplitTop(20.0f, nullptr, &Box);
NameLabel.VSplitLeft(150.0f, &NameLabel, &NameBox);
NameBox.VSplitLeft(20.0f, nullptr, &NameBox);
UI()->DoLabel(&NameLabel, Localize("New name:"), 18.0f, TEXTALIGN_ML);
UI()->DoEditBox(&m_DemoSliceInput, &NameBox, 12.0f);
// remove chat checkbox
static int s_RemoveChat = 0;
CUIRect RemoveChatCheckBox;
Box.HSplitTop(24.0f, &RemoveChatCheckBox, &Box);
Box.HSplitTop(20.0f, nullptr, &Box);
if(DoButton_CheckBox(&s_RemoveChat, Localize("Remove chat"), s_RemoveChat, &RemoveChatCheckBox))
{
s_RemoveChat ^= 1;
}
// buttons
CUIRect ButtonBar, AbortButton, OkButton;
Box.HSplitBottom(24.0f, &Box, &ButtonBar);
ButtonBar.VSplitMid(&AbortButton, &OkButton, 40.0f);
static CButtonContainer s_ButtonAbort;
if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &AbortButton) || (!UI()->IsPopupOpen() && UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE)))
m_DemoPlayerState = DEMOPLAYER_NONE;
static CUI::SConfirmPopupContext s_ConfirmPopupContext;
static CButtonContainer s_ButtonOk;
if(DoButton_Menu(&s_ButtonOk, Localize("Ok"), 0, &OkButton) || (!UI()->IsPopupOpen() && UI()->ConsumeHotkey(CUI::HOTKEY_ENTER)))
{
char aDemoName[IO_MAX_PATH_LENGTH];
DemoPlayer()->GetDemoName(aDemoName, sizeof(aDemoName));
str_append(aDemoName, ".demo", sizeof(aDemoName));
if(!str_endswith(m_DemoSliceInput.GetString(), ".demo"))
m_DemoSliceInput.Append(".demo");
if(str_comp(aDemoName, m_DemoSliceInput.GetString()) == 0)
{
static CUI::SMessagePopupContext s_MessagePopupContext;
s_MessagePopupContext.ErrorColor();
str_copy(s_MessagePopupContext.m_aMessage, Localize("Please use a different name"));
UI()->ShowPopupMessage(UI()->MouseX(), OkButton.y + OkButton.h + 5.0f, &s_MessagePopupContext);
}
else
{
char aPath[IO_MAX_PATH_LENGTH];
str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_DemoSliceInput.GetString());
if(Storage()->FileExists(aPath, IStorage::TYPE_SAVE))
{
s_ConfirmPopupContext.Reset();
s_ConfirmPopupContext.YesNoButtons();
str_copy(s_ConfirmPopupContext.m_aMessage, Localize("File already exists, do you want to overwrite it?"));
UI()->ShowPopupConfirm(UI()->MouseX(), OkButton.y + OkButton.h + 5.0f, &s_ConfirmPopupContext);
}
else
s_ConfirmPopupContext.m_Result = CUI::SConfirmPopupContext::CONFIRMED;
}
}
if(s_ConfirmPopupContext.m_Result == CUI::SConfirmPopupContext::CONFIRMED)
{
char aPath[IO_MAX_PATH_LENGTH];
str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_DemoSliceInput.GetString());
m_DemoPlayerState = DEMOPLAYER_NONE;
Client()->DemoSlice(aPath, CMenus::DemoFilterChat, &s_RemoveChat);
DemolistPopulate();
DemolistOnUpdate(false);
}
if(s_ConfirmPopupContext.m_Result != CUI::SConfirmPopupContext::UNSET)
{
s_ConfirmPopupContext.Reset();
}
}
int CMenus::DemolistFetchCallback(const CFsFileInfo *pInfo, int IsDir, int StorageType, void *pUser)

View file

@ -1281,7 +1281,7 @@ CUI::EPopupMenuFunctionResult CUI::PopupMessage(void *pContext, CUIRect View, bo
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) + 0.5f), SMessagePopupContext::POPUP_MAX_WIDTH);
float TextHeight = 0.0f;
STextSizeProperties TextSizeProps{};
TextSizeProps.m_pHeight = &TextHeight;
@ -1308,7 +1308,7 @@ void CUI::SConfirmPopupContext::YesNoButtons()
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) + 0.5f), SConfirmPopupContext::POPUP_MAX_WIDTH);
float TextHeight = 0.0f;
STextSizeProperties TextSizeProps{};
TextSizeProps.m_pHeight = &TextHeight;