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:
bors[bot] 2021-09-15 21:22:04 +00:00 committed by GitHub
commit 79dbbe2ee2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 436 additions and 557 deletions

View file

@ -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))

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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);