From 76ec4b8f4a55507c37df3d63d8f2331882ec8f35 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 21 Jun 2022 23:25:15 +0200 Subject: [PATCH] Improve console scrolling Moved auto scrolling logic to CTextLogger. Removed redundant code in CTextLogger. Added bool param to CTextLogger::RemoveLine to determine whether or not to lock the mutex (internal operations should not lock). Fixed issue where scrolling with cursor is not possible when auto-scroll is set or ScrollY is towards its max. Fixed copy button (copy all text in console via GUI, ctrl + a - ctrl + v alternative). --- r5dev/gameui/IConsole.cpp | 16 +--- r5dev/gameui/IConsole.h | 2 - r5dev/thirdparty/imgui/include/imgui_logger.h | 11 ++- r5dev/thirdparty/imgui/src/imgui_logger.cpp | 77 ++++++++----------- 4 files changed, 41 insertions(+), 65 deletions(-) diff --git a/r5dev/gameui/IConsole.cpp b/r5dev/gameui/IConsole.cpp index 9b32e5da..88414a92 100644 --- a/r5dev/gameui/IConsole.cpp +++ b/r5dev/gameui/IConsole.cpp @@ -31,8 +31,6 @@ CConsole::CConsole(void) memset(m_szInputBuf, '\0', sizeof(m_szInputBuf)); m_nHistoryPos = -1; - m_bAutoScroll = true; - m_bScrollToBottom = false; m_bInitialized = false; m_pszConsoleTitle = "Console"; @@ -231,9 +229,7 @@ void CConsole::BasePanel(void) if (m_bCopyToClipBoard) { - ImGui::LogToClipboard(); - ImGui::LogFinish(); - + m_Logger.Copy(true); m_bCopyToClipBoard = false; } @@ -243,12 +239,6 @@ void CConsole::BasePanel(void) m_nScrollBack = 0; } - if (m_bScrollToBottom || (m_bAutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) - { - ImGui::SetScrollHereY(1.0f); - m_bScrollToBottom = false; - } - /////////////////////////////////////////////////////////////////////// ImGui::EndChild(); ImGui::Separator(); @@ -314,7 +304,7 @@ void CConsole::BasePanel(void) //----------------------------------------------------------------------------- void CConsole::OptionsPanel(void) { - ImGui::Checkbox("Auto-Scroll", &m_bAutoScroll); + ImGui::Checkbox("Auto-Scroll", &m_Logger.m_bAutoScroll); ImGui::SameLine(); ImGui::PushItemWidth(100); @@ -596,7 +586,7 @@ void CConsole::ProcessCommand(const char* pszCommand) } } - m_bScrollToBottom = true; + m_Logger.m_bScrollToBottom = true; } //----------------------------------------------------------------------------- diff --git a/r5dev/gameui/IConsole.h b/r5dev/gameui/IConsole.h index bc086a7c..36244007 100644 --- a/r5dev/gameui/IConsole.h +++ b/r5dev/gameui/IConsole.h @@ -39,8 +39,6 @@ private: bool m_bInitialized = false; bool m_bDefaultTheme = false; bool m_bReclaimFocus = false; - bool m_bAutoScroll = true; - bool m_bScrollToBottom = false; bool m_bCopyToClipBoard = false; bool m_bSuggestActive = false; diff --git a/r5dev/thirdparty/imgui/include/imgui_logger.h b/r5dev/thirdparty/imgui/include/imgui_logger.h index 7d8a4903..3a73679d 100644 --- a/r5dev/thirdparty/imgui/include/imgui_logger.h +++ b/r5dev/thirdparty/imgui/include/imgui_logger.h @@ -128,7 +128,6 @@ public: int GetTotalFilterMatches() const; int GetTotalLines() const { return (int)m_Lines.size(); } - bool IsOverwrite() const { return m_Overwrite; } bool IsCursorPositionChanged() const { return m_bCursorPositionChanged; } Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); } @@ -164,10 +163,10 @@ public: void SelectAll(); bool HasSelection() const; - void RemoveLine(int aStart, int aEnd); - void RemoveLine(int aIndex); + void RemoveLine(int aStart, int aEnd, bool aInternal = false); + void RemoveLine(int aIndex, bool aInternal = false); - void Copy(); + void Copy(bool aCopyAll = false); private: struct EditorState @@ -210,8 +209,6 @@ private: std::mutex m_Mutex; int m_nTabSize; - bool m_Overwrite; - bool m_bWithinRender; bool m_bScrollToCursor; float m_flTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor. int m_nLeftMargin; @@ -231,5 +228,7 @@ private: float m_flLastClick; public: + bool m_bAutoScroll; + bool m_bScrollToBottom; ImGuiTextFilter m_itFilter; }; diff --git a/r5dev/thirdparty/imgui/src/imgui_logger.cpp b/r5dev/thirdparty/imgui/src/imgui_logger.cpp index 1aa751fe..7f275123 100644 --- a/r5dev/thirdparty/imgui/src/imgui_logger.cpp +++ b/r5dev/thirdparty/imgui/src/imgui_logger.cpp @@ -24,8 +24,8 @@ bool equals(InputIt1 first1, InputIt1 last1, CTextLogger::CTextLogger() : m_flLineSpacing(1.0f) , m_nTabSize(4) - , m_Overwrite(false) - , m_bWithinRender(false) + , m_bAutoScroll(true) + , m_bScrollToBottom(true) , m_bScrollToCursor(false) , m_flTextStart(0.f) , m_nLeftMargin(0) @@ -531,9 +531,10 @@ bool CTextLogger::IsOnWordBoundary(const Coordinates & aAt) const return isspace(line[cindex].m_Char) != isspace(line[cindex - 1].m_Char); } -void CTextLogger::RemoveLine(int aStart, int aEnd) +void CTextLogger::RemoveLine(int aStart, int aEnd, bool aInternal) { - m_Mutex.lock(); + if (!aInternal) + m_Mutex.lock(); assert(aEnd >= aStart); assert(m_Lines.size() > (size_t)(aEnd - aStart)); @@ -541,19 +542,22 @@ void CTextLogger::RemoveLine(int aStart, int aEnd) m_Lines.erase(m_Lines.begin() + aStart, m_Lines.begin() + aEnd); assert(!m_Lines.empty()); - m_Mutex.unlock(); + if (!aInternal) + m_Mutex.unlock(); } -void CTextLogger::RemoveLine(int aIndex) +void CTextLogger::RemoveLine(int aIndex, bool aInternal) { - m_Mutex.lock(); + if (!aInternal) + m_Mutex.lock(); assert(m_Lines.size() > 1); m_Lines.erase(m_Lines.begin() + aIndex); assert(!m_Lines.empty()); - m_Mutex.unlock(); + if (!aInternal) + m_Mutex.unlock(); } CTextLogger::Line& CTextLogger::InsertLine(int aIndex) @@ -626,8 +630,6 @@ void CTextLogger::HandleKeyboardInputs() MoveHome(shift); else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End))) MoveEnd(shift); - else if (!ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert))) - m_Overwrite ^= true; else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert))) Copy(); else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C))) @@ -718,8 +720,6 @@ void CTextLogger::HandleMouseInputs() void CTextLogger::Render() { m_Mutex.lock(); - - m_bWithinRender = true; m_bCursorPositionChanged = false; ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); @@ -802,22 +802,6 @@ void CTextLogger::Render() int cindex = GetCharacterIndex(m_State.m_CursorPosition); float cx = TextDistanceToLineStart(m_State.m_CursorPosition); - if (m_Overwrite && cindex < (int)line.size()) - { - Char c = line[cindex].m_Char; - if (c == '\t') - { - float x = (1.0f + std::floor((1.0f + cx) / (static_cast(m_nTabSize) * spaceSize))) * (static_cast(m_nTabSize) * spaceSize); - width = x - cx; - } - else - { - char buf2[2]; - buf2[0] = line[cindex].m_Char; - buf2[1] = '\0'; - width = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf2).x; - } - } const ImVec2 cstart(textScreenPos.x + cx, lineStartScreenPos.y); const ImVec2 cend(textScreenPos.x + cx + width, lineStartScreenPos.y + m_CharAdvance.y); @@ -908,19 +892,17 @@ void CTextLogger::Render() ImGui::Dummy(ImVec2((longest + 2), m_Lines.size() * m_CharAdvance.y)); - if (m_bScrollToCursor) + if (m_bScrollToBottom || (!m_bScrollToCursor && m_bAutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) { - EnsureCursorVisible(); - ImGui::SetWindowFocus(); - m_bScrollToCursor = false; + ImGui::SetScrollHereY(1.0f); + m_bScrollToBottom = false; } + m_bScrollToCursor = false; if (m_bHandleKeyboardInputs) ImGui::PopAllowKeyboardFocus(); ImGui::PopStyleVar(); - m_bWithinRender = false; - m_Mutex.unlock(); } @@ -1068,8 +1050,8 @@ void CTextLogger::MoveUp(int aAmount, bool aSelect) } else m_InteractiveStart = m_InteractiveEnd = m_State.m_CursorPosition; - SetSelection(m_InteractiveStart, m_InteractiveEnd); + SetSelection(m_InteractiveStart, m_InteractiveEnd); EnsureCursorVisible(); } } @@ -1326,13 +1308,13 @@ bool CTextLogger::HasSelection() const return m_State.m_SelectionEnd > m_State.m_SelectionStart; } -void CTextLogger::Copy() +void CTextLogger::Copy(bool aCopyAll) { - if (HasSelection()) + if (!aCopyAll && HasSelection()) { ImGui::SetClipboardText(GetSelectedText().c_str()); } - else + else if (!aCopyAll) { if (!m_Lines.empty()) { @@ -1344,6 +1326,16 @@ void CTextLogger::Copy() ImGui::SetClipboardText(str.c_str()); } } + else // Copy all lines to clipboard. + { + std::string str; + for (const Line& line: m_Lines) + { + for (const Glyph& g : line) + str.push_back(g.m_Char); + } + ImGui::SetClipboardText(str.c_str()); + } } std::string CTextLogger::GetText() const @@ -1387,7 +1379,8 @@ std::string CTextLogger::GetTextFromLine(const Line& aLine) const { std::string result; for (const Glyph& glyph : aLine) - result += glyph.m_Char; + result.push_back(glyph.m_Char); + return result; } @@ -1443,11 +1436,7 @@ float CTextLogger::TextDistanceToLineStart(const Coordinates& aFrom) const void CTextLogger::EnsureCursorVisible() { - if (!m_bWithinRender) - { - m_bScrollToCursor = true; - return; - } + m_bScrollToCursor = true; float scrollX = ImGui::GetScrollX(); float scrollY = ImGui::GetScrollY();