mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Smooth console completion scrolling
This commit is contained in:
parent
96c1e930f8
commit
f0c74f72ba
|
@ -147,6 +147,7 @@ void CGameConsole::CInstance::ClearHistory()
|
|||
void CGameConsole::CInstance::Reset()
|
||||
{
|
||||
m_CompletionRenderOffset = 0.0f;
|
||||
m_CompletionRenderOffsetChange = 0.0f;
|
||||
}
|
||||
|
||||
void CGameConsole::CInstance::ExecuteLine(const char *pLine)
|
||||
|
@ -533,25 +534,29 @@ struct CCompletionOptionRenderInfo
|
|||
CTextCursor m_Cursor;
|
||||
const char *m_pCurrentCmd;
|
||||
int m_WantedCompletion;
|
||||
int m_EnumCount;
|
||||
float m_Offset;
|
||||
float *m_pOffsetChange;
|
||||
float m_Width;
|
||||
float m_TotalWidth;
|
||||
};
|
||||
|
||||
void CGameConsole::PossibleCommandsRenderCallback(int Index, const char *pStr, void *pUser)
|
||||
{
|
||||
CCompletionOptionRenderInfo *pInfo = static_cast<CCompletionOptionRenderInfo *>(pUser);
|
||||
|
||||
if(pInfo->m_EnumCount == pInfo->m_WantedCompletion)
|
||||
if(Index == pInfo->m_WantedCompletion)
|
||||
{
|
||||
float tw = pInfo->m_pSelf->TextRender()->TextWidth(pInfo->m_Cursor.m_pFont, pInfo->m_Cursor.m_FontSize, pStr, -1, -1.0f);
|
||||
pInfo->m_pSelf->Graphics()->DrawRect(pInfo->m_Cursor.m_X - 2.5f, pInfo->m_Cursor.m_Y - 4.f / 2.f, tw + 5.f, pInfo->m_Cursor.m_FontSize + 4.f, ColorRGBA(229.0f / 255.0f, 185.0f / 255.0f, 4.0f / 255.0f, 0.85f), IGraphics::CORNER_ALL, pInfo->m_Cursor.m_FontSize / 3.f);
|
||||
float TextWidth = pInfo->m_pSelf->TextRender()->TextWidth(pInfo->m_Cursor.m_pFont, pInfo->m_Cursor.m_FontSize, pStr, -1, -1.0f);
|
||||
const CUIRect Rect = {pInfo->m_Cursor.m_X - 2.5f, pInfo->m_Cursor.m_Y - 4.f / 2.f, TextWidth + 5.f, pInfo->m_Cursor.m_FontSize + 4.f};
|
||||
Rect.Draw(ColorRGBA(229.0f / 255.0f, 185.0f / 255.0f, 4.0f / 255.0f, 0.85f), IGraphics::CORNER_ALL, pInfo->m_Cursor.m_FontSize / 3.f);
|
||||
|
||||
// scroll when out of sight
|
||||
if(pInfo->m_Cursor.m_X < 3.0f)
|
||||
pInfo->m_Offset = 0.0f;
|
||||
else if(pInfo->m_Cursor.m_X + tw > pInfo->m_Width)
|
||||
pInfo->m_Offset -= pInfo->m_Width / 2;
|
||||
const bool MoveLeft = Rect.x - *pInfo->m_pOffsetChange < 0.0f;
|
||||
const bool MoveRight = Rect.x + Rect.w - *pInfo->m_pOffsetChange > pInfo->m_Width;
|
||||
if(MoveLeft && !MoveRight)
|
||||
*pInfo->m_pOffsetChange -= -Rect.x + pInfo->m_Width / 4.0f;
|
||||
else if(!MoveLeft && MoveRight)
|
||||
*pInfo->m_pOffsetChange += Rect.x + Rect.w - pInfo->m_Width + pInfo->m_Width / 4.0f;
|
||||
|
||||
pInfo->m_pSelf->TextRender()->TextColor(0.05f, 0.05f, 0.05f, 1);
|
||||
pInfo->m_pSelf->TextRender()->TextEx(&pInfo->m_Cursor, pStr, -1);
|
||||
|
@ -576,8 +581,8 @@ void CGameConsole::PossibleCommandsRenderCallback(int Index, const char *pStr, v
|
|||
}
|
||||
}
|
||||
|
||||
pInfo->m_EnumCount++;
|
||||
pInfo->m_Cursor.m_X += 7.0f;
|
||||
pInfo->m_TotalWidth = pInfo->m_Cursor.m_X + pInfo->m_Offset;
|
||||
}
|
||||
|
||||
void CGameConsole::OnRender()
|
||||
|
@ -761,28 +766,30 @@ void CGameConsole::OnRender()
|
|||
CCompletionOptionRenderInfo Info;
|
||||
Info.m_pSelf = this;
|
||||
Info.m_WantedCompletion = pConsole->m_CompletionChosen;
|
||||
Info.m_EnumCount = 0;
|
||||
Info.m_Offset = pConsole->m_CompletionRenderOffset;
|
||||
Info.m_pOffsetChange = &pConsole->m_CompletionRenderOffsetChange;
|
||||
Info.m_Width = Screen.w;
|
||||
Info.m_TotalWidth = 0.0f;
|
||||
Info.m_pCurrentCmd = pConsole->m_aCompletionBuffer;
|
||||
TextRender()->SetCursor(&Info.m_Cursor, InitialX + Info.m_Offset, InitialY + RowHeight + 2.0f, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
|
||||
TextRender()->SetCursor(&Info.m_Cursor, InitialX - Info.m_Offset, InitialY + RowHeight + 2.0f, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
|
||||
Info.m_Cursor.m_LineWidth = std::numeric_limits<float>::max();
|
||||
m_pConsole->PossibleCommands(Info.m_pCurrentCmd, pConsole->m_CompletionFlagmask, m_ConsoleType != CGameConsole::CONSOLETYPE_LOCAL && Client()->RconAuthed() && Client()->UseTempRconCommands(), PossibleCommandsRenderCallback, &Info);
|
||||
const int NumCommands = m_pConsole->PossibleCommands(Info.m_pCurrentCmd, pConsole->m_CompletionFlagmask, m_ConsoleType != CGameConsole::CONSOLETYPE_LOCAL && Client()->RconAuthed() && Client()->UseTempRconCommands(), PossibleCommandsRenderCallback, &Info);
|
||||
pConsole->m_CompletionRenderOffset = Info.m_Offset;
|
||||
|
||||
if(Info.m_EnumCount <= 0 && pConsole->m_IsCommand)
|
||||
if(NumCommands <= 0 && pConsole->m_IsCommand)
|
||||
{
|
||||
const bool TuningCompletion = IsTuningCommandPrefix(Info.m_pCurrentCmd);
|
||||
int NumArguments = 0;
|
||||
if(TuningCompletion)
|
||||
{
|
||||
Info.m_WantedCompletion = pConsole->m_CompletionChosenArgument;
|
||||
Info.m_EnumCount = 0;
|
||||
Info.m_TotalWidth = 0.0f;
|
||||
Info.m_pCurrentCmd = pConsole->m_aCompletionBufferArgument;
|
||||
m_pClient->m_aTuning[g_Config.m_ClDummy].PossibleTunings(Info.m_pCurrentCmd, PossibleCommandsRenderCallback, &Info);
|
||||
NumArguments = m_pClient->m_aTuning[g_Config.m_ClDummy].PossibleTunings(Info.m_pCurrentCmd, PossibleCommandsRenderCallback, &Info);
|
||||
pConsole->m_CompletionRenderOffset = Info.m_Offset;
|
||||
}
|
||||
|
||||
if(Info.m_EnumCount <= 0 && pConsole->m_IsCommand)
|
||||
if(NumArguments <= 0 && pConsole->m_IsCommand)
|
||||
{
|
||||
char aBuf[512];
|
||||
str_format(aBuf, sizeof(aBuf), "Help: %s ", pConsole->m_aCommandHelp);
|
||||
|
@ -792,6 +799,8 @@ void CGameConsole::OnRender()
|
|||
TextRender()->TextEx(&Info.m_Cursor, aBuf, -1);
|
||||
}
|
||||
}
|
||||
|
||||
UI()->DoSmoothScrollLogic(&pConsole->m_CompletionRenderOffset, &pConsole->m_CompletionRenderOffsetChange, Info.m_Width, Info.m_TotalWidth);
|
||||
}
|
||||
|
||||
pConsole->m_BacklogLock.lock();
|
||||
|
|
|
@ -50,6 +50,7 @@ class CGameConsole : public CComponent
|
|||
int m_CompletionChosenArgument;
|
||||
int m_CompletionFlagmask;
|
||||
float m_CompletionRenderOffset;
|
||||
float m_CompletionRenderOffsetChange;
|
||||
|
||||
char m_aUser[32];
|
||||
bool m_UserGot;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <base/math.h>
|
||||
#include <base/system.h>
|
||||
|
||||
#include <engine/client.h>
|
||||
#include <engine/graphics.h>
|
||||
#include <engine/input.h>
|
||||
#include <engine/keys.h>
|
||||
|
@ -83,6 +84,7 @@ float CUI::ms_FontmodHeight = 0.8f;
|
|||
|
||||
void CUI::Init(IKernel *pKernel)
|
||||
{
|
||||
m_pClient = pKernel->RequestInterface<IClient>();
|
||||
m_pGraphics = pKernel->RequestInterface<IGraphics>();
|
||||
m_pInput = pKernel->RequestInterface<IInput>();
|
||||
m_pTextRender = pKernel->RequestInterface<ITextRender>();
|
||||
|
@ -372,6 +374,35 @@ int CUI::DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *
|
|||
return 1;
|
||||
}
|
||||
|
||||
void CUI::DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange, float ViewPortSize, float TotalSize, float ScrollSpeed)
|
||||
{
|
||||
// instant scrolling if distance too long
|
||||
if(absolute(*pScrollOffsetChange) > ViewPortSize)
|
||||
{
|
||||
*pScrollOffset += *pScrollOffsetChange;
|
||||
*pScrollOffsetChange = 0.0f;
|
||||
}
|
||||
// smooth scrolling
|
||||
if(*pScrollOffsetChange)
|
||||
{
|
||||
const float Delta = *pScrollOffsetChange * clamp(Client()->RenderFrameTime() * ScrollSpeed, 0.0f, 1.0f);
|
||||
*pScrollOffset += Delta;
|
||||
*pScrollOffsetChange -= Delta;
|
||||
}
|
||||
// clamp to first item
|
||||
if(*pScrollOffset < 0.0f)
|
||||
{
|
||||
*pScrollOffset = 0.0f;
|
||||
*pScrollOffsetChange = 0.0f;
|
||||
}
|
||||
// clamp to last item
|
||||
if(TotalSize > ViewPortSize && *pScrollOffset > TotalSize - ViewPortSize)
|
||||
{
|
||||
*pScrollOffset = TotalSize - ViewPortSize;
|
||||
*pScrollOffsetChange = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float CUI::DoTextLabel(float x, float y, float w, float h, const char *pText, float Size, int Align, const SLabelProperties &LabelProps)
|
||||
{
|
||||
float AlignedSize = 0;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class IClient;
|
||||
class IGraphics;
|
||||
class IKernel;
|
||||
|
||||
|
@ -203,6 +204,7 @@ class CUI
|
|||
std::vector<CUIRect> m_vClips;
|
||||
void UpdateClipping();
|
||||
|
||||
IClient *m_pClient;
|
||||
IGraphics *m_pGraphics;
|
||||
IInput *m_pInput;
|
||||
ITextRender *m_pTextRender;
|
||||
|
@ -218,6 +220,7 @@ public:
|
|||
|
||||
void Init(IKernel *pKernel);
|
||||
void InitInputs(IInput::CEvent *pInputEventsArray, int *pInputEventCount);
|
||||
IClient *Client() const { return m_pClient; }
|
||||
IGraphics *Graphics() const { return m_pGraphics; }
|
||||
IInput *Input() const { return m_pInput; }
|
||||
ITextRender *TextRender() const { return m_pTextRender; }
|
||||
|
@ -306,6 +309,7 @@ public:
|
|||
|
||||
int DoButtonLogic(const void *pID, int Checked, const CUIRect *pRect);
|
||||
int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY);
|
||||
void DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange, float ViewPortSize, float TotalSize, float ScrollSpeed = 10.0f);
|
||||
|
||||
float DoTextLabel(float x, float y, float w, float h, 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