mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Merge #3844
3844: Add UI Ex class to share common ui implementations r=def- a=Jupeyy Between menus and editor for example Currently only did DoEditBox, as this created crashes in the editor fixes #3395 It's copy and paste from the implementation of CMenus, except for 4 lines, which i'll mark below ## 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: Jupeyy <jupjopjap@gmail.com>
This commit is contained in:
commit
fbf3d6e943
|
@ -1840,6 +1840,8 @@ if(CLIENT)
|
|||
skin.h
|
||||
ui.cpp
|
||||
ui.h
|
||||
ui_ex.cpp
|
||||
ui_ex.h
|
||||
)
|
||||
set_src(GAME_EDITOR GLOB src/game/editor
|
||||
auto_map.cpp
|
||||
|
|
|
@ -610,251 +610,7 @@ int CMenus::DoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, bool
|
|||
|
||||
int CMenus::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners, const char *pEmptyText)
|
||||
{
|
||||
int Inside = UI()->MouseInside(pRect);
|
||||
bool ReturnValue = false;
|
||||
bool UpdateOffset = false;
|
||||
static int s_AtIndex = 0;
|
||||
static bool s_DoScroll = false;
|
||||
static float s_ScrollStart = 0.0f;
|
||||
|
||||
FontSize *= UI()->Scale();
|
||||
|
||||
if(UI()->LastActiveItem() == pID)
|
||||
{
|
||||
int Len = str_length(pStr);
|
||||
if(Len == 0)
|
||||
s_AtIndex = 0;
|
||||
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_V))
|
||||
{
|
||||
const char *Text = Input()->GetClipboardText();
|
||||
if(Text)
|
||||
{
|
||||
int Offset = str_length(pStr);
|
||||
int CharsLeft = StrSize - Offset;
|
||||
char *pCur = pStr + Offset;
|
||||
str_utf8_copy(pCur, Text, CharsLeft);
|
||||
for(int i = 0; i < CharsLeft; i++)
|
||||
{
|
||||
if(pCur[i] == 0)
|
||||
break;
|
||||
else if(pCur[i] == '\r')
|
||||
pCur[i] = ' ';
|
||||
else if(pCur[i] == '\n')
|
||||
pCur[i] = ' ';
|
||||
}
|
||||
s_AtIndex = str_length(pStr);
|
||||
ReturnValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_C))
|
||||
{
|
||||
Input()->SetClipboardText(pStr);
|
||||
}
|
||||
|
||||
/* TODO: Doesn't work, SetClipboardText doesn't retain the string quickly enough?
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_X))
|
||||
{
|
||||
Input()->SetClipboardText(pStr);
|
||||
pStr[0] = '\0';
|
||||
s_AtIndex = 0;
|
||||
ReturnValue = true;
|
||||
}
|
||||
*/
|
||||
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_U))
|
||||
{
|
||||
pStr[0] = '\0';
|
||||
s_AtIndex = 0;
|
||||
ReturnValue = true;
|
||||
}
|
||||
|
||||
if(Inside && UI()->MouseButton(0))
|
||||
{
|
||||
s_DoScroll = true;
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
int MxRel = (int)(UI()->MouseX() - pRect->x);
|
||||
|
||||
for(int i = 1; i <= Len; i++)
|
||||
{
|
||||
if(TextRender()->TextWidth(0, FontSize, pStr, i, std::numeric_limits<float>::max()) - *Offset > MxRel)
|
||||
{
|
||||
s_AtIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == Len)
|
||||
s_AtIndex = Len;
|
||||
}
|
||||
}
|
||||
else if(!UI()->MouseButton(0))
|
||||
s_DoScroll = false;
|
||||
else if(s_DoScroll)
|
||||
{
|
||||
// do scrolling
|
||||
if(UI()->MouseX() < pRect->x && s_ScrollStart - UI()->MouseX() > 10.0f)
|
||||
{
|
||||
s_AtIndex = maximum(0, s_AtIndex - 1);
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
UpdateOffset = true;
|
||||
}
|
||||
else if(UI()->MouseX() > pRect->x + pRect->w && UI()->MouseX() - s_ScrollStart > 10.0f)
|
||||
{
|
||||
s_AtIndex = minimum(Len, s_AtIndex + 1);
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
UpdateOffset = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < m_NumInputEvents; i++)
|
||||
{
|
||||
Len = str_length(pStr);
|
||||
int NumChars = Len;
|
||||
ReturnValue |= CLineInput::Manipulate(m_aInputEvents[i], pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
|
||||
}
|
||||
}
|
||||
|
||||
bool JustGotActive = false;
|
||||
|
||||
if(UI()->ActiveItem() == pID)
|
||||
{
|
||||
if(!UI()->MouseButton(0))
|
||||
{
|
||||
s_AtIndex = minimum(s_AtIndex, str_length(pStr));
|
||||
s_DoScroll = false;
|
||||
UI()->SetActiveItem(0);
|
||||
}
|
||||
}
|
||||
else if(UI()->HotItem() == pID)
|
||||
{
|
||||
if(UI()->MouseButton(0))
|
||||
{
|
||||
if(UI()->LastActiveItem() != pID)
|
||||
JustGotActive = true;
|
||||
UI()->SetActiveItem(pID);
|
||||
}
|
||||
}
|
||||
|
||||
if(Inside)
|
||||
{
|
||||
UI()->SetHotItem(pID);
|
||||
}
|
||||
|
||||
CUIRect Textbox = *pRect;
|
||||
RenderTools()->DrawUIRect(&Textbox, ColorRGBA(1, 1, 1, 0.5f), Corners, 3.0f);
|
||||
Textbox.VMargin(2.0f, &Textbox);
|
||||
Textbox.HMargin(2.0f, &Textbox);
|
||||
|
||||
const char *pDisplayStr = pStr;
|
||||
char aStars[128];
|
||||
|
||||
if(Hidden)
|
||||
{
|
||||
unsigned s = str_length(pDisplayStr);
|
||||
if(s >= sizeof(aStars))
|
||||
s = sizeof(aStars) - 1;
|
||||
for(unsigned int i = 0; i < s; ++i)
|
||||
aStars[i] = '*';
|
||||
aStars[s] = 0;
|
||||
pDisplayStr = aStars;
|
||||
}
|
||||
|
||||
char aDispEditingText[128 + IInput::INPUT_TEXT_SIZE + 2] = {0};
|
||||
int DispCursorPos = s_AtIndex;
|
||||
if(UI()->LastActiveItem() == pID && Input()->GetIMEEditingTextLength() > -1)
|
||||
{
|
||||
int EditingTextCursor = Input()->GetEditingCursor();
|
||||
str_copy(aDispEditingText, pDisplayStr, sizeof(aDispEditingText));
|
||||
char aEditingText[IInput::INPUT_TEXT_SIZE + 2];
|
||||
if(Hidden)
|
||||
{
|
||||
// Do not show editing text in password field
|
||||
str_copy(aEditingText, "[*]", sizeof(aEditingText));
|
||||
EditingTextCursor = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_format(aEditingText, sizeof(aEditingText), "[%s]", Input()->GetIMEEditingText());
|
||||
}
|
||||
int NewTextLen = str_length(aEditingText);
|
||||
int CharsLeft = (int)sizeof(aDispEditingText) - str_length(aDispEditingText) - 1;
|
||||
int FillCharLen = minimum(NewTextLen, CharsLeft);
|
||||
for(int i = str_length(aDispEditingText) - 1; i >= s_AtIndex; i--)
|
||||
aDispEditingText[i + FillCharLen] = aDispEditingText[i];
|
||||
for(int i = 0; i < FillCharLen; i++)
|
||||
aDispEditingText[s_AtIndex + i] = aEditingText[i];
|
||||
DispCursorPos = s_AtIndex + EditingTextCursor + 1;
|
||||
pDisplayStr = aDispEditingText;
|
||||
UpdateOffset = true;
|
||||
}
|
||||
|
||||
if(pDisplayStr[0] == '\0')
|
||||
{
|
||||
pDisplayStr = pEmptyText;
|
||||
TextRender()->TextColor(1, 1, 1, 0.75f);
|
||||
}
|
||||
|
||||
DispCursorPos = minimum(DispCursorPos, str_length(pDisplayStr));
|
||||
|
||||
// check if the text has to be moved
|
||||
if(UI()->LastActiveItem() == pID && !JustGotActive && (UpdateOffset || m_NumInputEvents))
|
||||
{
|
||||
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, DispCursorPos, std::numeric_limits<float>::max());
|
||||
if(w - *Offset > Textbox.w)
|
||||
{
|
||||
// move to the left
|
||||
float wt = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1, std::numeric_limits<float>::max());
|
||||
do
|
||||
{
|
||||
*Offset += minimum(wt - *Offset - Textbox.w, Textbox.w / 3);
|
||||
} while(w - *Offset > Textbox.w + 0.0001f);
|
||||
}
|
||||
else if(w - *Offset < 0.0f)
|
||||
{
|
||||
// move to the right
|
||||
do
|
||||
{
|
||||
*Offset = maximum(0.0f, *Offset - Textbox.w / 3);
|
||||
} while(w - *Offset < -0.0001f);
|
||||
}
|
||||
}
|
||||
UI()->ClipEnable(pRect);
|
||||
Textbox.x -= *Offset;
|
||||
|
||||
UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1);
|
||||
|
||||
TextRender()->TextColor(1, 1, 1, 1);
|
||||
|
||||
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
||||
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
||||
float OnePixelWidth = ((ScreenX1 - ScreenX0) / Graphics()->ScreenWidth());
|
||||
|
||||
// render the cursor
|
||||
if(UI()->LastActiveItem() == pID && !JustGotActive)
|
||||
{
|
||||
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, DispCursorPos, std::numeric_limits<float>::max());
|
||||
Textbox.x += w;
|
||||
|
||||
if((2 * time_get() / time_freq()) % 2)
|
||||
{
|
||||
Graphics()->TextureClear();
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(0, 0, 0, 0.3f);
|
||||
IGraphics::CQuadItem CursorTBack(Textbox.x - (OnePixelWidth * 2.0f) / 2.0f, Textbox.y, OnePixelWidth * 2 * 2.0f, Textbox.h);
|
||||
Graphics()->QuadsDrawTL(&CursorTBack, 1);
|
||||
Graphics()->SetColor(1, 1, 1, 1);
|
||||
IGraphics::CQuadItem CursorT(Textbox.x, Textbox.y + OnePixelWidth * 1.5f, OnePixelWidth * 2.0f, Textbox.h - OnePixelWidth * 1.5f * 2);
|
||||
Graphics()->QuadsDrawTL(&CursorT, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
}
|
||||
|
||||
Input()->SetEditingPosition(Textbox.x, Textbox.y + FontSize);
|
||||
}
|
||||
|
||||
UI()->ClipDisable();
|
||||
|
||||
return ReturnValue;
|
||||
return m_UIEx.DoEditBox(pID, pRect, pStr, StrSize, FontSize, Offset, Hidden, Corners, pEmptyText);
|
||||
}
|
||||
|
||||
int CMenus::DoClearableEditBox(void *pID, void *pClearID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners, const char *pEmptyText)
|
||||
|
@ -1432,6 +1188,8 @@ void CMenus::OnInit()
|
|||
if(g_Config.m_ClSkipStartMenu)
|
||||
m_ShowStart = false;
|
||||
|
||||
m_UIEx.Init(UI(), Kernel(), RenderTools());
|
||||
|
||||
m_RefreshButton.Init(UI());
|
||||
m_ConnectButton.Init(UI());
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <game/client/component.h>
|
||||
#include <game/client/ui.h>
|
||||
#include <game/client/ui_ex.h>
|
||||
#include <game/voting.h>
|
||||
|
||||
struct CServerProcess
|
||||
|
@ -70,6 +71,8 @@ class CMenus : public CComponent
|
|||
|
||||
char m_aLocalStringHelper[1024];
|
||||
|
||||
CUIEx m_UIEx;
|
||||
|
||||
float ButtonColorMulActive() { return 0.5f; }
|
||||
float ButtonColorMulHot() { return 1.5f; }
|
||||
float ButtonColorMulDefault() { return 1.0f; }
|
||||
|
|
274
src/game/client/ui_ex.cpp
Normal file
274
src/game/client/ui_ex.cpp
Normal file
|
@ -0,0 +1,274 @@
|
|||
#include "ui_ex.h"
|
||||
|
||||
#include <engine/client/input.h>
|
||||
#include <engine/keys.h>
|
||||
|
||||
#include <game/client/lineinput.h>
|
||||
#include <game/client/render.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
CUIEx::CUIEx(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools)
|
||||
{
|
||||
Init(pUI, pKernel, pRenderTools);
|
||||
}
|
||||
|
||||
void CUIEx::Init(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools)
|
||||
{
|
||||
m_pUI = pUI;
|
||||
m_pKernel = pKernel;
|
||||
m_pRenderTools = pRenderTools;
|
||||
|
||||
m_pInput = Kernel()->RequestInterface<IInput>();
|
||||
m_pGraphics = Kernel()->RequestInterface<IGraphics>();
|
||||
m_pTextRender = Kernel()->RequestInterface<ITextRender>();
|
||||
}
|
||||
|
||||
int CUIEx::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners, const char *pEmptyText)
|
||||
{
|
||||
int Inside = UI()->MouseInside(pRect);
|
||||
bool ReturnValue = false;
|
||||
bool UpdateOffset = false;
|
||||
static int s_AtIndex = 0;
|
||||
static bool s_DoScroll = false;
|
||||
static float s_ScrollStart = 0.0f;
|
||||
|
||||
FontSize *= UI()->Scale();
|
||||
|
||||
if(UI()->LastActiveItem() == pID)
|
||||
{
|
||||
int Len = str_length(pStr);
|
||||
if(Len == 0)
|
||||
s_AtIndex = 0;
|
||||
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_V))
|
||||
{
|
||||
const char *Text = Input()->GetClipboardText();
|
||||
if(Text)
|
||||
{
|
||||
int Offset = str_length(pStr);
|
||||
int CharsLeft = StrSize - Offset;
|
||||
char *pCur = pStr + Offset;
|
||||
str_utf8_copy(pCur, Text, CharsLeft);
|
||||
for(int i = 0; i < CharsLeft; i++)
|
||||
{
|
||||
if(pCur[i] == 0)
|
||||
break;
|
||||
else if(pCur[i] == '\r')
|
||||
pCur[i] = ' ';
|
||||
else if(pCur[i] == '\n')
|
||||
pCur[i] = ' ';
|
||||
}
|
||||
s_AtIndex = str_length(pStr);
|
||||
ReturnValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_C))
|
||||
{
|
||||
Input()->SetClipboardText(pStr);
|
||||
}
|
||||
|
||||
/* TODO: Doesn't work, SetClipboardText doesn't retain the string quickly enough?
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_X))
|
||||
{
|
||||
Input()->SetClipboardText(pStr);
|
||||
pStr[0] = '\0';
|
||||
s_AtIndex = 0;
|
||||
ReturnValue = true;
|
||||
}
|
||||
*/
|
||||
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_U))
|
||||
{
|
||||
pStr[0] = '\0';
|
||||
s_AtIndex = 0;
|
||||
ReturnValue = true;
|
||||
}
|
||||
|
||||
if(Inside && UI()->MouseButton(0))
|
||||
{
|
||||
s_DoScroll = true;
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
int MxRel = (int)(UI()->MouseX() - pRect->x);
|
||||
|
||||
for(int i = 1; i <= Len; i++)
|
||||
{
|
||||
if(TextRender()->TextWidth(0, FontSize, pStr, i, std::numeric_limits<float>::max()) - *Offset > MxRel)
|
||||
{
|
||||
s_AtIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == Len)
|
||||
s_AtIndex = Len;
|
||||
}
|
||||
}
|
||||
else if(!UI()->MouseButton(0))
|
||||
s_DoScroll = false;
|
||||
else if(s_DoScroll)
|
||||
{
|
||||
// do scrolling
|
||||
if(UI()->MouseX() < pRect->x && s_ScrollStart - UI()->MouseX() > 10.0f)
|
||||
{
|
||||
s_AtIndex = maximum(0, s_AtIndex - 1);
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
UpdateOffset = true;
|
||||
}
|
||||
else if(UI()->MouseX() > pRect->x + pRect->w && UI()->MouseX() - s_ScrollStart > 10.0f)
|
||||
{
|
||||
s_AtIndex = minimum(Len, s_AtIndex + 1);
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
UpdateOffset = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < Input()->NumEvents(); i++)
|
||||
{
|
||||
Len = str_length(pStr);
|
||||
int NumChars = Len;
|
||||
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
|
||||
}
|
||||
}
|
||||
|
||||
bool JustGotActive = false;
|
||||
|
||||
if(UI()->ActiveItem() == pID)
|
||||
{
|
||||
if(!UI()->MouseButton(0))
|
||||
{
|
||||
s_AtIndex = minimum(s_AtIndex, str_length(pStr));
|
||||
s_DoScroll = false;
|
||||
UI()->SetActiveItem(0);
|
||||
}
|
||||
}
|
||||
else if(UI()->HotItem() == pID)
|
||||
{
|
||||
if(UI()->MouseButton(0))
|
||||
{
|
||||
if(UI()->LastActiveItem() != pID)
|
||||
JustGotActive = true;
|
||||
UI()->SetActiveItem(pID);
|
||||
}
|
||||
}
|
||||
|
||||
if(Inside)
|
||||
{
|
||||
UI()->SetHotItem(pID);
|
||||
}
|
||||
|
||||
CUIRect Textbox = *pRect;
|
||||
RenderTools()->DrawUIRect(&Textbox, ColorRGBA(1, 1, 1, 0.5f), Corners, 3.0f);
|
||||
Textbox.VMargin(2.0f, &Textbox);
|
||||
Textbox.HMargin(2.0f, &Textbox);
|
||||
|
||||
const char *pDisplayStr = pStr;
|
||||
char aStars[128];
|
||||
|
||||
if(Hidden)
|
||||
{
|
||||
unsigned s = str_length(pDisplayStr);
|
||||
if(s >= sizeof(aStars))
|
||||
s = sizeof(aStars) - 1;
|
||||
for(unsigned int i = 0; i < s; ++i)
|
||||
aStars[i] = '*';
|
||||
aStars[s] = 0;
|
||||
pDisplayStr = aStars;
|
||||
}
|
||||
|
||||
char aDispEditingText[128 + IInput::INPUT_TEXT_SIZE + 2] = {0};
|
||||
int DispCursorPos = s_AtIndex;
|
||||
if(UI()->LastActiveItem() == pID && Input()->GetIMEEditingTextLength() > -1)
|
||||
{
|
||||
int EditingTextCursor = Input()->GetEditingCursor();
|
||||
str_copy(aDispEditingText, pDisplayStr, sizeof(aDispEditingText));
|
||||
char aEditingText[IInput::INPUT_TEXT_SIZE + 2];
|
||||
if(Hidden)
|
||||
{
|
||||
// Do not show editing text in password field
|
||||
str_copy(aEditingText, "[*]", sizeof(aEditingText));
|
||||
EditingTextCursor = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_format(aEditingText, sizeof(aEditingText), "[%s]", Input()->GetIMEEditingText());
|
||||
}
|
||||
int NewTextLen = str_length(aEditingText);
|
||||
int CharsLeft = (int)sizeof(aDispEditingText) - str_length(aDispEditingText) - 1;
|
||||
int FillCharLen = minimum(NewTextLen, CharsLeft);
|
||||
for(int i = str_length(aDispEditingText) - 1; i >= s_AtIndex; i--)
|
||||
aDispEditingText[i + FillCharLen] = aDispEditingText[i];
|
||||
for(int i = 0; i < FillCharLen; i++)
|
||||
aDispEditingText[s_AtIndex + i] = aEditingText[i];
|
||||
DispCursorPos = s_AtIndex + EditingTextCursor + 1;
|
||||
pDisplayStr = aDispEditingText;
|
||||
UpdateOffset = true;
|
||||
}
|
||||
|
||||
if(pDisplayStr[0] == '\0')
|
||||
{
|
||||
pDisplayStr = pEmptyText;
|
||||
TextRender()->TextColor(1, 1, 1, 0.75f);
|
||||
}
|
||||
|
||||
DispCursorPos = minimum(DispCursorPos, str_length(pDisplayStr));
|
||||
|
||||
// check if the text has to be moved
|
||||
if(UI()->LastActiveItem() == pID && !JustGotActive && (UpdateOffset || Input()->NumEvents()))
|
||||
{
|
||||
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, DispCursorPos, std::numeric_limits<float>::max());
|
||||
if(w - *Offset > Textbox.w)
|
||||
{
|
||||
// move to the left
|
||||
float wt = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1, std::numeric_limits<float>::max());
|
||||
do
|
||||
{
|
||||
*Offset += minimum(wt - *Offset - Textbox.w, Textbox.w / 3);
|
||||
} while(w - *Offset > Textbox.w + 0.0001f);
|
||||
}
|
||||
else if(w - *Offset < 0.0f)
|
||||
{
|
||||
// move to the right
|
||||
do
|
||||
{
|
||||
*Offset = maximum(0.0f, *Offset - Textbox.w / 3);
|
||||
} while(w - *Offset < -0.0001f);
|
||||
}
|
||||
}
|
||||
UI()->ClipEnable(pRect);
|
||||
Textbox.x -= *Offset;
|
||||
|
||||
UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1);
|
||||
|
||||
TextRender()->TextColor(1, 1, 1, 1);
|
||||
|
||||
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
||||
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
||||
float OnePixelWidth = ((ScreenX1 - ScreenX0) / Graphics()->ScreenWidth());
|
||||
|
||||
// render the cursor
|
||||
if(UI()->LastActiveItem() == pID && !JustGotActive)
|
||||
{
|
||||
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, DispCursorPos, std::numeric_limits<float>::max());
|
||||
Textbox.x += w;
|
||||
|
||||
if((2 * time_get() / time_freq()) % 2)
|
||||
{
|
||||
Graphics()->TextureClear();
|
||||
Graphics()->QuadsBegin();
|
||||
Graphics()->SetColor(0, 0, 0, 0.3f);
|
||||
IGraphics::CQuadItem CursorTBack(Textbox.x - (OnePixelWidth * 2.0f) / 2.0f, Textbox.y, OnePixelWidth * 2 * 2.0f, Textbox.h);
|
||||
Graphics()->QuadsDrawTL(&CursorTBack, 1);
|
||||
Graphics()->SetColor(1, 1, 1, 1);
|
||||
IGraphics::CQuadItem CursorT(Textbox.x, Textbox.y + OnePixelWidth * 1.5f, OnePixelWidth * 2.0f, Textbox.h - OnePixelWidth * 1.5f * 2);
|
||||
Graphics()->QuadsDrawTL(&CursorT, 1);
|
||||
Graphics()->QuadsEnd();
|
||||
}
|
||||
|
||||
Input()->SetEditingPosition(Textbox.x, Textbox.y + FontSize);
|
||||
}
|
||||
|
||||
UI()->ClipDisable();
|
||||
|
||||
return ReturnValue;
|
||||
}
|
41
src/game/client/ui_ex.h
Normal file
41
src/game/client/ui_ex.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef GAME_CLIENT_UI_EX_H
|
||||
#define GAME_CLIENT_UI_EX_H
|
||||
|
||||
#include "engine/kernel.h"
|
||||
#include <base/system.h>
|
||||
#include <game/client/ui.h>
|
||||
|
||||
class IInput;
|
||||
class ITextRender;
|
||||
class IKernel;
|
||||
class IGraphics;
|
||||
|
||||
class CRenderTools;
|
||||
|
||||
class CUIEx
|
||||
{
|
||||
CUI *m_pUI;
|
||||
IInput *m_pInput;
|
||||
ITextRender *m_pTextRender;
|
||||
IKernel *m_pKernel;
|
||||
IGraphics *m_pGraphics;
|
||||
CRenderTools *m_pRenderTools;
|
||||
|
||||
protected:
|
||||
CUI *UI() { return m_pUI; }
|
||||
IInput *Input() { return m_pInput; }
|
||||
ITextRender *TextRender() { return m_pTextRender; }
|
||||
IKernel *Kernel() { return m_pKernel; }
|
||||
IGraphics *Graphics() { return m_pGraphics; }
|
||||
CRenderTools *RenderTools() { return m_pRenderTools; }
|
||||
|
||||
public:
|
||||
CUIEx(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools);
|
||||
CUIEx() {}
|
||||
|
||||
void Init(CUI *pUI, IKernel *pKernel, CRenderTools *pRenderTools);
|
||||
|
||||
int DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden = false, int Corners = CUI::CORNER_ALL, const char *pEmptyText = "");
|
||||
};
|
||||
|
||||
#endif
|
|
@ -326,171 +326,9 @@ int CEditor::DoClearableEditBox(void *pID, void *pClearID, const CUIRect *pRect,
|
|||
return ReturnValue;
|
||||
}
|
||||
|
||||
// copied from gc_menu.cpp, should be more generalized
|
||||
//extern int ui_do_edit_box(void *id, const CUIRect *rect, char *str, int str_size, float font_size, bool hidden=false);
|
||||
int CEditor::DoEditBox(void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *Offset, bool Hidden, int Corners)
|
||||
{
|
||||
int Inside = UI()->MouseInside(pRect);
|
||||
bool ReturnValue = false;
|
||||
bool UpdateOffset = false;
|
||||
static int s_AtIndex = 0;
|
||||
static bool s_DoScroll = false;
|
||||
static float s_ScrollStart = 0.0f;
|
||||
|
||||
FontSize *= UI()->Scale();
|
||||
|
||||
if(UI()->LastActiveItem() == pID)
|
||||
{
|
||||
m_EditBoxActive = 2;
|
||||
int Len = str_length(pStr);
|
||||
if(Len == 0)
|
||||
s_AtIndex = 0;
|
||||
|
||||
if(Inside && UI()->MouseButton(0))
|
||||
{
|
||||
s_DoScroll = true;
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
int MxRel = (int)(UI()->MouseX() - pRect->x);
|
||||
|
||||
for(int i = 1; i <= Len; i++)
|
||||
{
|
||||
if(TextRender()->TextWidth(0, FontSize, pStr, i, std::numeric_limits<float>::max()) - *Offset > MxRel)
|
||||
{
|
||||
s_AtIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == Len)
|
||||
s_AtIndex = Len;
|
||||
}
|
||||
}
|
||||
else if(!UI()->MouseButton(0))
|
||||
s_DoScroll = false;
|
||||
else if(s_DoScroll)
|
||||
{
|
||||
// do scrolling
|
||||
if(UI()->MouseX() < pRect->x && s_ScrollStart - UI()->MouseX() > 10.0f)
|
||||
{
|
||||
s_AtIndex = maximum(0, s_AtIndex - 1);
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
UpdateOffset = true;
|
||||
}
|
||||
else if(UI()->MouseX() > pRect->x + pRect->w && UI()->MouseX() - s_ScrollStart > 10.0f)
|
||||
{
|
||||
s_AtIndex = minimum(Len, s_AtIndex + 1);
|
||||
s_ScrollStart = UI()->MouseX();
|
||||
UpdateOffset = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < Input()->NumEvents(); i++)
|
||||
{
|
||||
Len = str_length(pStr);
|
||||
int NumChars = Len;
|
||||
ReturnValue |= CLineInput::Manipulate(Input()->GetEvent(i), pStr, StrSize, StrSize, &Len, &s_AtIndex, &NumChars);
|
||||
}
|
||||
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_V))
|
||||
{
|
||||
const char *pClipboardText = Input()->GetClipboardText();
|
||||
if(pClipboardText)
|
||||
{
|
||||
str_append(pStr, pClipboardText, StrSize);
|
||||
str_sanitize_cc(pStr);
|
||||
s_AtIndex = str_length(pStr);
|
||||
ReturnValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_C) && pStr[0] != '\0')
|
||||
{
|
||||
Input()->SetClipboardText(pStr);
|
||||
}
|
||||
}
|
||||
|
||||
bool JustGotActive = false;
|
||||
|
||||
if(UI()->ActiveItem() == pID)
|
||||
{
|
||||
if(!UI()->MouseButton(0))
|
||||
{
|
||||
s_AtIndex = minimum(s_AtIndex, str_length(pStr));
|
||||
s_DoScroll = false;
|
||||
UI()->SetActiveItem(0);
|
||||
}
|
||||
}
|
||||
else if(UI()->HotItem() == pID)
|
||||
{
|
||||
if(UI()->MouseButton(0))
|
||||
{
|
||||
if(UI()->LastActiveItem() != pID)
|
||||
JustGotActive = true;
|
||||
UI()->SetActiveItem(pID);
|
||||
}
|
||||
}
|
||||
|
||||
if(Inside)
|
||||
UI()->SetHotItem(pID);
|
||||
|
||||
CUIRect Textbox = *pRect;
|
||||
RenderTools()->DrawUIRect(&Textbox, ColorRGBA(1, 1, 1, 0.5f), Corners, 3.0f);
|
||||
Textbox.VMargin(2.0f, &Textbox);
|
||||
|
||||
const char *pDisplayStr = pStr;
|
||||
char aStars[128];
|
||||
|
||||
if(Hidden)
|
||||
{
|
||||
unsigned s = str_length(pStr);
|
||||
if(s >= sizeof(aStars))
|
||||
s = sizeof(aStars) - 1;
|
||||
for(unsigned int i = 0; i < s; ++i)
|
||||
aStars[i] = '*';
|
||||
aStars[s] = 0;
|
||||
pDisplayStr = aStars;
|
||||
}
|
||||
|
||||
// check if the text has to be moved
|
||||
if(UI()->LastActiveItem() == pID && !JustGotActive && (UpdateOffset || Input()->NumEvents()))
|
||||
{
|
||||
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex, std::numeric_limits<float>::max());
|
||||
if(w - *Offset > Textbox.w)
|
||||
{
|
||||
// move to the left
|
||||
float wt = TextRender()->TextWidth(0, FontSize, pDisplayStr, -1, std::numeric_limits<float>::max());
|
||||
do
|
||||
{
|
||||
*Offset += minimum(wt - *Offset - Textbox.w, Textbox.w / 3);
|
||||
} while(w - *Offset > Textbox.w + 0.0001f);
|
||||
}
|
||||
else if(w - *Offset < 0.0f)
|
||||
{
|
||||
// move to the right
|
||||
do
|
||||
{
|
||||
*Offset = maximum(0.0f, *Offset - Textbox.w / 3);
|
||||
} while(w - *Offset < -0.0001f);
|
||||
}
|
||||
}
|
||||
UI()->ClipEnable(pRect);
|
||||
Textbox.x -= *Offset;
|
||||
|
||||
UI()->DoLabel(&Textbox, pDisplayStr, FontSize, -1, std::numeric_limits<float>::max());
|
||||
|
||||
// render the cursor
|
||||
if(UI()->LastActiveItem() == pID && !JustGotActive)
|
||||
{
|
||||
float w = TextRender()->TextWidth(0, FontSize, pDisplayStr, s_AtIndex, std::numeric_limits<float>::max());
|
||||
Textbox = *pRect;
|
||||
Textbox.VSplitLeft(2.0f, 0, &Textbox);
|
||||
Textbox.x += (w - *Offset - TextRender()->TextWidth(0, FontSize, "|", -1, std::numeric_limits<float>::max()) / 2);
|
||||
|
||||
if((2 * time_get() / time_freq()) % 2) // make it blink
|
||||
UI()->DoLabel(&Textbox, "|", FontSize, -1, std::numeric_limits<float>::max());
|
||||
}
|
||||
UI()->ClipDisable();
|
||||
|
||||
return ReturnValue;
|
||||
return m_UIEx.DoEditBox(pID, pRect, pStr, StrSize, FontSize, Offset, Hidden, Corners);
|
||||
}
|
||||
|
||||
float CEditor::ButtonColorMul(const void *pID)
|
||||
|
@ -6367,6 +6205,8 @@ void CEditor::Init()
|
|||
m_UI.SetGraphics(m_pGraphics, m_pTextRender);
|
||||
m_Map.m_pEditor = this;
|
||||
|
||||
m_UIEx.Init(UI(), Kernel(), RenderTools());
|
||||
|
||||
m_CheckerTexture = Graphics()->LoadTexture("editor/checker.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0);
|
||||
m_BackgroundTexture = Graphics()->LoadTexture("editor/background.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0);
|
||||
m_CursorTexture = Graphics()->LoadTexture("editor/cursor.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <game/client/render.h>
|
||||
#include <game/client/ui.h>
|
||||
#include <game/client/ui_ex.h>
|
||||
#include <game/mapitems.h>
|
||||
|
||||
#include <engine/editor.h>
|
||||
|
@ -639,6 +640,7 @@ class CEditor : public IEditor
|
|||
class IStorage *m_pStorage;
|
||||
CRenderTools m_RenderTools;
|
||||
CUI m_UI;
|
||||
CUIEx m_UIEx;
|
||||
|
||||
public:
|
||||
class IInput *Input() { return m_pInput; };
|
||||
|
|
Loading…
Reference in a new issue