mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Merge #4151
4151: Copy ingame console like in ATH r=def- a=BloodWod-513 The idea is taken from the implementation of this in ATH client <!-- What is the motivation for the changes of this pull request --> ## 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> Co-authored-by: BloodWod-513 <dayn_2013@mail.ru>
This commit is contained in:
commit
79dbbe2ee2
|
@ -109,6 +109,21 @@ void CInput::MouseModeRelative()
|
|||
SDL_GetRelativeMouseState(0x0, 0x0);
|
||||
}
|
||||
|
||||
void CInput::NativeMousePos(int *x, int *y) const
|
||||
{
|
||||
int nx = 0, ny = 0;
|
||||
SDL_GetMouseState(&nx, &ny);
|
||||
|
||||
*x = nx;
|
||||
*y = ny;
|
||||
}
|
||||
|
||||
bool CInput::NativeMousePressed(int index)
|
||||
{
|
||||
int i = SDL_GetMouseState(NULL, NULL);
|
||||
return (i & SDL_BUTTON(index)) != 0;
|
||||
}
|
||||
|
||||
int CInput::MouseDoubleClick()
|
||||
{
|
||||
if(m_ReleaseDelta >= 0 && m_ReleaseDelta < (time_freq() / 3))
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
virtual void MouseRelative(float *x, float *y);
|
||||
virtual void MouseModeAbsolute();
|
||||
virtual void MouseModeRelative();
|
||||
virtual void NativeMousePos(int *x, int *y) const;
|
||||
virtual bool NativeMousePressed(int index);
|
||||
virtual int MouseDoubleClick();
|
||||
virtual const char *GetClipboardText();
|
||||
virtual void SetClipboardText(const char *Text);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -68,6 +68,8 @@ public:
|
|||
virtual void Clear() = 0;
|
||||
|
||||
//
|
||||
virtual void NativeMousePos(int *mx, int *my) const = 0;
|
||||
virtual bool NativeMousePressed(int index) = 0;
|
||||
virtual void MouseModeRelative() = 0;
|
||||
virtual void MouseModeAbsolute() = 0;
|
||||
virtual int MouseDoubleClick() = 0;
|
||||
|
|
|
@ -35,6 +35,16 @@ enum
|
|||
|
||||
class CFont;
|
||||
|
||||
enum ETextCursorSelectionMode
|
||||
{
|
||||
// ignore any kind of selection
|
||||
TEXT_CURSOR_SELECTION_MODE_NONE = 0,
|
||||
// calculates the selection based on the mouse press and release cursor position
|
||||
TEXT_CURSOR_SELECTION_MODE_CALCULATE,
|
||||
// sets the selection based on the character start and end count(these values have to be decoded character offsets)
|
||||
TEXT_CURSOR_SELECTION_MODE_SET,
|
||||
};
|
||||
|
||||
class CTextCursor
|
||||
{
|
||||
public:
|
||||
|
@ -55,6 +65,19 @@ public:
|
|||
CFont *m_pFont;
|
||||
float m_FontSize;
|
||||
float m_AlignedFontSize;
|
||||
|
||||
ETextCursorSelectionMode m_CalculateSelectionMode;
|
||||
|
||||
// these coordinates are repsected if selection mode is set to calculate @see ETextCursorSelectionMode
|
||||
int m_PressMouseX;
|
||||
int m_PressMouseY;
|
||||
int m_ReleaseMouseX;
|
||||
int m_ReleaseMouseY;
|
||||
|
||||
// note m_SelectionStart can be bigger than m_SelectionEnd, depending on how the mouse cursor was dragged
|
||||
// also note, that these are the character offsets decoded
|
||||
int m_SelectionStart;
|
||||
int m_SelectionEnd;
|
||||
};
|
||||
|
||||
struct STextRenderColor
|
||||
|
@ -111,6 +134,7 @@ public:
|
|||
|
||||
ColorRGBA DefaultTextColor() { return ColorRGBA(1, 1, 1, 1); }
|
||||
ColorRGBA DefaultTextOutlineColor() { return ColorRGBA(0, 0, 0, 0.3f); }
|
||||
ColorRGBA DefaultSelectionColor() { return ColorRGBA(0, 0, 1.0f, 1.0f); }
|
||||
|
||||
//
|
||||
virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) = 0;
|
||||
|
@ -119,7 +143,6 @@ public:
|
|||
// just deletes and creates text container
|
||||
virtual void RecreateTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText, int Length = -1) = 0;
|
||||
virtual void RecreateTextContainerSoft(CTextCursor *pCursor, int TextContainerIndex, const char *pText, int Length = -1) = 0;
|
||||
virtual void SetTextContainerSelection(int TextContainerIndex, const char *pText, int CursorPos, int SelectionStart, int SelectionEnd) = 0;
|
||||
virtual void DeleteTextContainer(int TextContainerIndex) = 0;
|
||||
|
||||
virtual void UploadTextContainer(int TextContainerIndex) = 0;
|
||||
|
@ -131,17 +154,22 @@ public:
|
|||
virtual int AdjustFontSize(const char *pText, int TextLength, int MaxSize, int MaxWidth) = 0;
|
||||
virtual int CalculateTextWidth(const char *pText, int TextLength, int FontWidth, int FontHeight) = 0;
|
||||
|
||||
virtual bool SelectionToUTF8OffSets(const char *pText, int SelStart, int SelEnd, int &OffUTF8Start, int &OffUTF8End) = 0;
|
||||
|
||||
// old foolish interface
|
||||
virtual void TextColor(float r, float g, float b, float a) = 0;
|
||||
virtual void TextColor(ColorRGBA rgb) = 0;
|
||||
virtual void TextOutlineColor(float r, float g, float b, float a) = 0;
|
||||
virtual void TextOutlineColor(ColorRGBA rgb) = 0;
|
||||
virtual void TextSelectionColor(float r, float g, float b, float a) = 0;
|
||||
virtual void TextSelectionColor(ColorRGBA rgb) = 0;
|
||||
virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, float LineWidth) = 0;
|
||||
virtual float TextWidth(void *pFontSetV, float Size, const char *pText, int StrLength, float LineWidth, float *pAlignedHeight = NULL, float *pMaxCharacterHeightInLine = NULL) = 0;
|
||||
virtual int TextLineCount(void *pFontSetV, float Size, const char *pText, float LineWidth) = 0;
|
||||
|
||||
virtual ColorRGBA GetTextColor() = 0;
|
||||
virtual ColorRGBA GetTextOutlineColor() = 0;
|
||||
virtual ColorRGBA GetTextSelectionColor() = 0;
|
||||
|
||||
virtual void OnWindowResize() = 0;
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include <game/client/gameclient.h>
|
||||
|
||||
#include <base/math.h>
|
||||
|
||||
#include "console.h"
|
||||
|
||||
CGameConsole::CInstance::CInstance(int Type)
|
||||
|
@ -277,9 +279,11 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
|
|||
else if(Event.m_Key == KEY_PAGEUP)
|
||||
{
|
||||
++m_BacklogActPage;
|
||||
m_pGameConsole->m_HasSelection = false;
|
||||
}
|
||||
else if(Event.m_Key == KEY_PAGEDOWN)
|
||||
{
|
||||
m_pGameConsole->m_HasSelection = false;
|
||||
--m_BacklogActPage;
|
||||
if(m_BacklogActPage < 0)
|
||||
m_BacklogActPage = 0;
|
||||
|
@ -289,10 +293,12 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event)
|
|||
else if(Event.m_Key == KEY_HOME && m_Input.GetString()[0] == '\0')
|
||||
{
|
||||
m_BacklogActPage = INT_MAX;
|
||||
m_pGameConsole->m_HasSelection = false;
|
||||
}
|
||||
else if(Event.m_Key == KEY_END && m_Input.GetString()[0] == '\0')
|
||||
{
|
||||
m_BacklogActPage = 0;
|
||||
m_pGameConsole->m_HasSelection = false;
|
||||
}
|
||||
else if(Event.m_Key == KEY_LSHIFT)
|
||||
{
|
||||
|
@ -355,6 +361,8 @@ void CGameConsole::CInstance::PrintLine(const char *pLine, ColorRGBA PrintColor)
|
|||
pEntry->m_PrintColor = PrintColor;
|
||||
mem_copy(pEntry->m_aText, pLine, Len);
|
||||
pEntry->m_aText[Len] = 0;
|
||||
if(m_pGameConsole->m_ConsoleType == m_Type)
|
||||
m_pGameConsole->m_NewLineCounter++;
|
||||
}
|
||||
|
||||
CGameConsole::CGameConsole() :
|
||||
|
@ -650,6 +658,11 @@ void CGameConsole::OnRender()
|
|||
float OffsetY = 0.0f;
|
||||
float LineOffset = 1.0f;
|
||||
|
||||
bool WantsSelectionCopy = false;
|
||||
if(Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyPress(KEY_C))
|
||||
WantsSelectionCopy = true;
|
||||
std::string SelectionString;
|
||||
|
||||
for(int Page = 0; Page <= pConsole->m_BacklogActPage; ++Page, OffsetY = 0.0f)
|
||||
{
|
||||
while(pEntry)
|
||||
|
@ -662,7 +675,7 @@ void CGameConsole::OnRender()
|
|||
TextRender()->SetCursor(&Cursor, 0.0f, 0.0f, FontSize, 0);
|
||||
Cursor.m_LineWidth = Screen.w - 10;
|
||||
TextRender()->TextEx(&Cursor, pEntry->m_aText, -1);
|
||||
pEntry->m_YOffset = Cursor.m_Y + Cursor.m_FontSize + LineOffset;
|
||||
pEntry->m_YOffset = Cursor.m_Y + Cursor.m_AlignedFontSize + LineOffset;
|
||||
}
|
||||
OffsetY += pEntry->m_YOffset;
|
||||
|
||||
|
@ -670,17 +683,74 @@ void CGameConsole::OnRender()
|
|||
if(y - OffsetY <= RowHeight)
|
||||
break;
|
||||
|
||||
if(!m_MouseIsPress && Input()->NativeMousePressed(1))
|
||||
{
|
||||
m_MouseIsPress = true;
|
||||
Input()->NativeMousePos(&m_MousePressX, &m_MousePressY);
|
||||
m_MousePressX = (m_MousePressX / (float)Graphics()->ScreenWidth()) * Screen.w;
|
||||
m_MousePressY = (m_MousePressY / (float)Graphics()->ScreenHeight()) * Screen.h;
|
||||
}
|
||||
if(m_MouseIsPress)
|
||||
{
|
||||
Input()->NativeMousePos(&m_MouseCurX, &m_MouseCurY);
|
||||
m_MouseCurX = (m_MouseCurX / (float)Graphics()->ScreenWidth()) * Screen.w;
|
||||
m_MouseCurY = (m_MouseCurY / (float)Graphics()->ScreenHeight()) * Screen.h;
|
||||
}
|
||||
if(m_MouseIsPress && !Input()->NativeMousePressed(1))
|
||||
{
|
||||
m_MouseIsPress = false;
|
||||
}
|
||||
|
||||
// just render output from actual backlog page (render bottom up)
|
||||
if(Page == pConsole->m_BacklogActPage)
|
||||
{
|
||||
if(m_NewLineCounter > 0 && (m_HasSelection || m_MouseIsPress))
|
||||
{
|
||||
m_MousePressY -= OffsetY;
|
||||
if(!m_MouseIsPress)
|
||||
m_MouseCurY -= OffsetY;
|
||||
}
|
||||
TextRender()->SetCursor(&Cursor, 0.0f, y - OffsetY, FontSize, TEXTFLAG_RENDER);
|
||||
Cursor.m_LineWidth = Screen.w - 10.0f;
|
||||
Cursor.m_CalculateSelectionMode = (m_MouseIsPress || (m_CurSelStart != m_CurSelEnd) || m_HasSelection) ? TEXT_CURSOR_SELECTION_MODE_CALCULATE : TEXT_CURSOR_SELECTION_MODE_NONE;
|
||||
Cursor.m_PressMouseX = m_MousePressX;
|
||||
Cursor.m_PressMouseY = m_MousePressY;
|
||||
Cursor.m_ReleaseMouseX = m_MouseCurX;
|
||||
Cursor.m_ReleaseMouseY = m_MouseCurY;
|
||||
TextRender()->TextEx(&Cursor, pEntry->m_aText, -1);
|
||||
if(Cursor.m_CalculateSelectionMode == TEXT_CURSOR_SELECTION_MODE_CALCULATE)
|
||||
{
|
||||
m_CurSelStart = minimum(Cursor.m_SelectionStart, Cursor.m_SelectionEnd);
|
||||
m_CurSelEnd = maximum(Cursor.m_SelectionStart, Cursor.m_SelectionEnd);
|
||||
}
|
||||
if(m_CurSelStart != m_CurSelEnd)
|
||||
{
|
||||
if(WantsSelectionCopy)
|
||||
{
|
||||
bool HasNewLine = false;
|
||||
if(!SelectionString.empty())
|
||||
HasNewLine = true;
|
||||
int OffUTF8Start = 0;
|
||||
int OffUTF8End = 0;
|
||||
if(TextRender()->SelectionToUTF8OffSets(pEntry->m_aText, m_CurSelStart, m_CurSelEnd, OffUTF8Start, OffUTF8End))
|
||||
{
|
||||
SelectionString.insert(0, (std::string(&pEntry->m_aText[OffUTF8Start], OffUTF8End - OffUTF8Start) + (HasNewLine ? "\n" : "")));
|
||||
}
|
||||
}
|
||||
m_HasSelection = true;
|
||||
}
|
||||
}
|
||||
pEntry = pConsole->m_Backlog.Prev(pEntry);
|
||||
|
||||
// reset color
|
||||
TextRender()->TextColor(1, 1, 1, 1);
|
||||
if(m_NewLineCounter > 0)
|
||||
--m_NewLineCounter;
|
||||
}
|
||||
|
||||
if(WantsSelectionCopy && !SelectionString.empty())
|
||||
{
|
||||
Input()->SetClipboardText(SelectionString.c_str());
|
||||
}
|
||||
|
||||
// actual backlog page number is too high, render last available page (current checked one, render top down)
|
||||
|
@ -773,7 +843,8 @@ void CGameConsole::Toggle(int Type)
|
|||
Input()->SetIMEState(false);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_ConsoleType != Type)
|
||||
m_HasSelection = false;
|
||||
m_ConsoleType = Type;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,16 @@ class CGameConsole : public CComponent
|
|||
float m_StateChangeEnd;
|
||||
float m_StateChangeDuration;
|
||||
|
||||
bool m_MouseIsPress = false;
|
||||
int m_MousePressX = 0;
|
||||
int m_MousePressY = 0;
|
||||
int m_MouseCurX = 0;
|
||||
int m_MouseCurY = 0;
|
||||
int m_CurSelStart = 0;
|
||||
int m_CurSelEnd = 0;
|
||||
bool m_HasSelection = false;
|
||||
int m_NewLineCounter = 0;
|
||||
|
||||
void Toggle(int Type);
|
||||
void Dump(int Type);
|
||||
|
||||
|
|
Loading…
Reference in a new issue