From 3f74b4a2b6909c55fa460dc6a10e15ab2963a566 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:16:31 +0100 Subject: [PATCH] ImGui: heavy optimizations to text logger (WIP) This code originated from an imgui code editor, where it would make sense to have per-character colors. But for the console, we only ever do 1 color per line. Just store the string and one color instance, this also allows us to just take the string instead of manually reconstructing it which is very slow. The code now also only stores 32bits for color (per line) instead of 128 bits (ImVec4) as we only ever need to convert it once. As a result, a bunch of rendering code could be dropped, and the pass filter is now also very fast as we don't need to reconstruct the string to check for the filter, we just pass a char* in which doesn't cost any perf. --- src/core/logger.cpp | 2 +- src/gameui/IConsole.cpp | 17 +- src/gameui/IConsole.h | 4 +- src/thirdparty/imgui/misc/imgui_logger.cpp | 568 +++++++++------------ src/thirdparty/imgui/misc/imgui_logger.h | 64 ++- 5 files changed, 282 insertions(+), 373 deletions(-) diff --git a/src/core/logger.cpp b/src/core/logger.cpp index d98b0825..ebc1ba08 100644 --- a/src/core/logger.cpp +++ b/src/core/logger.cpp @@ -294,7 +294,7 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context, g_ImGuiLogger->debug(message); const string logStreamBuf = g_LogStream.str(); - g_Console.AddLog(ConLog_t(logStreamBuf, overlayColor)); + g_Console.AddLog(logStreamBuf.c_str(), ImGui::ColorConvertFloat4ToU32(overlayColor)); // We can only log to the in-game overlay console when the SDK has // been fully initialized, due to the use of ConVar's. diff --git a/src/gameui/IConsole.cpp b/src/gameui/IConsole.cpp index c0cc0e78..ff31ad0f 100644 --- a/src/gameui/IConsole.cpp +++ b/src/gameui/IConsole.cpp @@ -672,7 +672,9 @@ void CConsole::FindFromPartial(void) void CConsole::ProcessCommand(string svCommand) { StringRTrim(svCommand, " "); // Remove trailing white space characters to prevent history duplication. - AddLog(ImVec4(1.00f, 0.80f, 0.60f, 1.00f), "%s] %s\n", Plat_GetProcessUpTime(), svCommand.c_str()); + + const ImU32 commandColor = ImGui::ColorConvertFloat4ToU32(ImVec4(1.00f, 0.80f, 0.60f, 1.00f)); + AddLog(commandColor, "%s] %s\n", Plat_GetProcessUpTime(), svCommand.c_str()); Cbuf_AddText(Cbuf_GetCurrentPlayer(), svCommand.c_str(), cmd_source_t::kCommandSrcCode); m_nHistoryPos = PositionMode_t::kPark; @@ -1025,11 +1027,11 @@ int CConsole::TextEditCallbackStub(ImGuiInputTextCallbackData* iData) // the size of the vector here !!! // Input : &conLog - //----------------------------------------------------------------------------- -void CConsole::AddLog(const ConLog_t& conLog) +void CConsole::AddLog(const char* const text, const ImU32 color) { AUTO_LOCK(m_Mutex); - m_Logger.InsertText(conLog); + m_Logger.InsertText(text, color); ClampLogSize(); } @@ -1039,16 +1041,15 @@ void CConsole::AddLog(const ConLog_t& conLog) // *fmt - // ... - //----------------------------------------------------------------------------- -void CConsole::AddLog(const ImVec4& color, const char* fmt, ...) /*IM_FMTARGS(2)*/ +void CConsole::AddLog(const ImU32 color, const char* fmt, ...) /*IM_FMTARGS(2)*/ { - string result; va_list args; - va_start(args, fmt); - result = FormatV(fmt, args); + + string result = FormatV(fmt, args); va_end(args); - AddLog(ConLog_t(result, color)); + AddLog(result.c_str(), color); } //----------------------------------------------------------------------------- diff --git a/src/gameui/IConsole.h b/src/gameui/IConsole.h index 8ef2e09d..c52e1418 100644 --- a/src/gameui/IConsole.h +++ b/src/gameui/IConsole.h @@ -50,7 +50,7 @@ private: /////////////////////////////////////////////////////////////////////////// public: - void AddLog(const ConLog_t& conLog); + void AddLog(const char* const text, const ImU32 color); void RemoveLog(int nStart, int nEnd); void ClearLog(void); @@ -69,7 +69,7 @@ public: static void ClearHistory_f(); private: // Internals. - void AddLog(const ImVec4& color, const char* fmt, ...) /*IM_FMTARGS(2)*/; + void AddLog(const ImU32 color, const char* fmt, ...) /*IM_FMTARGS(2)*/; void ClampLogSize(void); void ClampHistorySize(void); diff --git a/src/thirdparty/imgui/misc/imgui_logger.cpp b/src/thirdparty/imgui/misc/imgui_logger.cpp index cac47b67..2ce6d746 100644 --- a/src/thirdparty/imgui/misc/imgui_logger.cpp +++ b/src/thirdparty/imgui/misc/imgui_logger.cpp @@ -9,7 +9,7 @@ #include "imgui_internal.h" template -bool equals(InputIt1 first1, InputIt1 last1, +static bool equals(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate p) { for (; first1 != last1 && first2 != last2; ++first1, ++first2) @@ -27,12 +27,10 @@ CTextLogger::CTextLogger() , m_bScrolledToBottom(false) , m_bHandleUserInputs(true) , m_bWithinLoggingRect(false) - , m_bShowWhiteSpaces(false) , m_bLinesOffsetForward(false) , m_nLinesOffsetAmount(0) , m_nTabSize(4) , m_nLeftMargin(0) - , m_flTextStart(0.0f) , m_flLineSpacing(1.0f) , m_SelectionMode(SelectionMode::Normal) , m_flLastClick(-1.0) @@ -45,7 +43,7 @@ CTextLogger::~CTextLogger() { } -std::string CTextLogger::GetText(const Coordinates & aStart, const Coordinates & aEnd) const +std::string CTextLogger::GetText(const Coordinates& aStart, const Coordinates& aEnd) const { std::string result; @@ -56,7 +54,7 @@ std::string CTextLogger::GetText(const Coordinates & aStart, const Coordinates & size_t s = 0; for (int i = lstart; i < lend; i++) - s += m_Lines[i].size(); + s += m_Lines[i].Length(); result.reserve(s + s / 8); @@ -66,9 +64,9 @@ std::string CTextLogger::GetText(const Coordinates & aStart, const Coordinates & break; const Line& line = m_Lines[lstart]; - if (istart < static_cast(line.size())) + if (istart < line.Length()) { - result += line[istart].m_Char; + result += line.buffer[istart]; istart++; } else @@ -111,7 +109,7 @@ CTextLogger::Coordinates CTextLogger::SanitizeCoordinates(const Coordinates & aV } else { - column = m_Lines.empty() ? 0 : std::min(column, GetLineMaxColumn(line)); + column = m_Lines.empty() ? 0 : ImMin(column, GetLineMaxColumn(line)); return Coordinates(line, column); } } @@ -160,17 +158,17 @@ bool UTF8StringValid(const char* pszString) return byteCount == 0; } -void CTextLogger::Advance(Coordinates & aCoordinates) const +void CTextLogger::Advance(Coordinates& aCoordinates) const { if (aCoordinates.m_nLine < static_cast(m_Lines.size())) { const Line& line = m_Lines[aCoordinates.m_nLine]; int cindex = GetCharacterIndex(aCoordinates); - if (cindex + 1 < static_cast(line.size())) + if (cindex + 1 < line.Length()) { - int delta = UTF8CharLength(line[cindex].m_Char); - cindex = std::min(cindex + delta, static_cast(line.size() - 1)); + int delta = UTF8CharLength(line.buffer[cindex]); + cindex = ImMin(cindex + delta, static_cast(line.Length() - 1)); } else { @@ -181,61 +179,61 @@ void CTextLogger::Advance(Coordinates & aCoordinates) const } } -void CTextLogger::DeleteRange(const Coordinates & aStart, const Coordinates & aEnd) -{ - assert(aEnd >= aStart); +//void CTextLogger::DeleteRange(const Coordinates & aStart, const Coordinates & aEnd) +//{ +// assert(aEnd >= aStart); +// +// //printf("D(%d.%d)-(%d.%d)\n", aStart.mLine, aStart.mColumn, aEnd.mLine, aEnd.mColumn); +// +// if (aEnd == aStart) +// return; +// +// int start = GetCharacterIndex(aStart); +// int end = GetCharacterIndex(aEnd); +// +// if (aStart.m_nLine == aEnd.m_nLine) +// { +// Line& line = m_Lines[aStart.m_nLine]; +// int n = GetLineMaxColumn(aStart.m_nLine); +// if (aEnd.m_nColumn >= n) +// line.erase(line.begin() + start, line.end()); +// else +// line.erase(line.begin() + start, line.begin() + end); +// } +// else +// { +// Line& firstLine = m_Lines[aStart.m_nLine]; +// Line& lastLine = m_Lines[aEnd.m_nLine]; +// +// firstLine.erase(firstLine.begin() + start, firstLine.end()); +// lastLine.erase(lastLine.begin(), lastLine.begin() + end); +// +// if (aStart.m_nLine < aEnd.m_nLine) +// firstLine.insert(firstLine.end(), lastLine.begin(), lastLine.end()); +// +// if (aStart.m_nLine < aEnd.m_nLine) +// RemoveLine(aStart.m_nLine + 1, aEnd.m_nLine + 1); +// } +//} - //printf("D(%d.%d)-(%d.%d)\n", aStart.mLine, aStart.mColumn, aEnd.mLine, aEnd.mColumn); - - if (aEnd == aStart) - return; - - int start = GetCharacterIndex(aStart); - int end = GetCharacterIndex(aEnd); - - if (aStart.m_nLine == aEnd.m_nLine) - { - Line& line = m_Lines[aStart.m_nLine]; - int n = GetLineMaxColumn(aStart.m_nLine); - if (aEnd.m_nColumn >= n) - line.erase(line.begin() + start, line.end()); - else - line.erase(line.begin() + start, line.begin() + end); - } - else - { - Line& firstLine = m_Lines[aStart.m_nLine]; - Line& lastLine = m_Lines[aEnd.m_nLine]; - - firstLine.erase(firstLine.begin() + start, firstLine.end()); - lastLine.erase(lastLine.begin(), lastLine.begin() + end); - - if (aStart.m_nLine < aEnd.m_nLine) - firstLine.insert(firstLine.end(), lastLine.begin(), lastLine.end()); - - if (aStart.m_nLine < aEnd.m_nLine) - RemoveLine(aStart.m_nLine + 1, aEnd.m_nLine + 1); - } -} - -void CTextLogger::MarkNewline(Coordinates& /* inout */ aWhere, const ImVec4& aColor, int aIndex) +void CTextLogger::MarkNewline(Coordinates& aWhere, int aIndex) { Line& newLine = InsertLine(aWhere.m_nLine + 1); Line& line = m_Lines[aWhere.m_nLine]; - if (aIndex < static_cast(m_Lines[aWhere.m_nLine].size())) + if (aIndex < static_cast(m_Lines[aWhere.m_nLine].buffer.size())) { - newLine.insert(newLine.begin(), line.begin() + aIndex, line.end()); - line.erase(line.begin() + aIndex, line.end()); + newLine.buffer.insert(newLine.buffer.begin(), line.buffer.begin() + aIndex, line.buffer.end()); + line.buffer.erase(line.buffer.begin() + aIndex, line.buffer.end()); } else - line.push_back(Glyph('\n', aColor)); + line.buffer.push_back('\n'); ++aWhere.m_nLine; aWhere.m_nColumn = 0; } -int CTextLogger::InsertTextAt(Coordinates& /* inout */ aWhere, const char* aValue, const ImVec4& aColor) +int CTextLogger::InsertTextAt(Coordinates& aWhere, const char* aValue, const ImU32 aColor) { int cindex = GetCharacterIndex(aWhere); int totalLines = 0; @@ -257,7 +255,7 @@ int CTextLogger::InsertTextAt(Coordinates& /* inout */ aWhere, const char* aValu } else if (*aValue == '\n') { - MarkNewline(aWhere, aColor, cindex); + MarkNewline(aWhere, cindex); cindex = 0; ++totalLines; ++aValue; @@ -265,9 +263,11 @@ int CTextLogger::InsertTextAt(Coordinates& /* inout */ aWhere, const char* aValu else { Line& line = m_Lines[aWhere.m_nLine]; - if (!line.empty() && ImGui::ColorConvertFloat4ToU32(aColor) != ImGui::ColorConvertFloat4ToU32(line[0].m_Color)) + + // if the buffer isn't empty, and the next log isn't from the same context, log it as a new line + if (!line.buffer.empty() && aColor != line.color) { - MarkNewline(aWhere, line[0].m_Color, cindex); + MarkNewline(aWhere, cindex); cindex = 0; ++totalLines; continue; @@ -276,19 +276,23 @@ int CTextLogger::InsertTextAt(Coordinates& /* inout */ aWhere, const char* aValu size_t d = UTF8CharLength(*aValue); while (d-- > 0 && *aValue != '\0') { - if (cindex >= 0 && cindex <= static_cast(line.size())) - line.insert(line.begin() + cindex++, Glyph(*aValue++, aColor)); + if (cindex >= 0 && cindex <= line.Length()) + line.buffer.insert(line.buffer.begin() + cindex++, *aValue++); else ++aValue; // Possibly an invalid character } + + line.color = aColor; ++aWhere.m_nColumn; } } + + // TODO[ AMOS ]: should we really pad it with a white space if buf empty? if (!*aValue) { Line& line = m_Lines[aWhere.m_nLine]; - if (!line.empty() && cindex >= 0 && cindex <= static_cast(line.size())) - line.insert(line.begin() + cindex, Glyph(' ', aColor)); + if (!line.buffer.empty() && cindex >= 0 && cindex <= line.Length()) + line.buffer.insert(line.buffer.begin() + cindex, ' '); } return totalLines; @@ -299,28 +303,30 @@ CTextLogger::Coordinates CTextLogger::ScreenPosToCoordinates(const ImVec2& aPosi ImVec2 origin = ImGui::GetCursorScreenPos(); ImVec2 local(aPosition.x - origin.x, aPosition.y - origin.y); - int lineNo = std::max(0, static_cast(floor(local.y / m_CharAdvance.y))); + int lineNo = ImMax(0, static_cast(ImFloor(local.y / m_CharAdvance.y))); int columnCoord = 0; if (lineNo >= 0 && lineNo < static_cast(m_Lines.size())) { - const Line& line = m_Lines.at(lineNo); + const Line& line = m_Lines[lineNo]; int columnIndex = 0; float columnX = 0.0f; - while (columnIndex < static_cast(line.size())) + while (columnIndex < line.Length()) { float columnWidth = 0.0f; - if (line[columnIndex].m_Char == '\t') + if (line.buffer[columnIndex] == '\t') { float spaceSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ").x; float oldX = columnX; - float newColumnX = (1.0f + std::floor((1.0f + columnX) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize); + float newColumnX = (1.0f + ImFloor((1.0f + columnX) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize); columnWidth = newColumnX - oldX; - if (m_flTextStart + columnX + columnWidth * 0.5f > local.x) + + if (columnX + columnWidth * 0.5f > local.x) break; + columnX = newColumnX; columnCoord = (columnCoord / m_nTabSize) * m_nTabSize + m_nTabSize; columnIndex++; @@ -328,14 +334,18 @@ CTextLogger::Coordinates CTextLogger::ScreenPosToCoordinates(const ImVec2& aPosi else { char buf[7]; - size_t d = UTF8CharLength(line[columnIndex].m_Char); + size_t d = UTF8CharLength(line.buffer[columnIndex]); size_t i = 0; - while (i < 6 && d-- > 0 && columnIndex < line.size()) - buf[i++] = line[columnIndex++].m_Char; + + while (i < 6 && d-- > 0 && columnIndex < line.Length()) + buf[i++] = line.buffer[columnIndex++]; + buf[i] = '\0'; columnWidth = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf).x; - if (m_flTextStart + columnX + columnWidth * 0.5f > local.x) + + if (columnX + columnWidth * 0.5f > local.x) break; + columnX += columnWidth; columnCoord++; } @@ -354,15 +364,15 @@ CTextLogger::Coordinates CTextLogger::FindWordStart(const Coordinates & aFrom) c const Line& line = m_Lines[at.m_nLine]; int cindex = GetCharacterIndex(at); - if (cindex >= static_cast(line.size())) + if (cindex >= line.Length()) return at; - while (cindex > 0 && isspace(line[cindex].m_Char)) + while (cindex > 0 && isspace(line.buffer[cindex])) --cindex; while (cindex > 0) { - Char c = line[cindex].m_Char; + Char c = line.buffer[cindex]; if ((c & 0xC0) != 0x80) // not UTF code sequence 10xxxxxx { if (c <= 32 && isspace(c)) @@ -386,19 +396,19 @@ CTextLogger::Coordinates CTextLogger::FindWordEnd(const Coordinates & aFrom) con const Line& line = m_Lines[at.m_nLine]; int cindex = GetCharacterIndex(at); - if (cindex >= static_cast(line.size())) + if (cindex >= line.Length()) return at; - bool prevspace = static_cast(isspace(line[cindex].m_Char)); - while (cindex < static_cast(line.size())) + bool prevspace = static_cast(isspace(line.buffer[cindex])); + while (cindex < line.Length()) { - Char c = line[cindex].m_Char; + Char c = line.buffer[cindex]; int d = UTF8CharLength(c); if (prevspace != !!isspace(c)) { if (isspace(c)) - while (cindex < static_cast(line.size()) && !isspace(line[cindex].m_Char)) + while (cindex < line.Length() && !isspace(line.buffer[cindex])) ++cindex; break; } @@ -418,10 +428,11 @@ CTextLogger::Coordinates CTextLogger::FindNextWord(const Coordinates & aFrom) co int cindex = GetCharacterIndex(aFrom); bool isword = false; bool skip = false; - if (cindex < static_cast(m_Lines[at.m_nLine].size())) + + if (cindex < static_cast(m_Lines[at.m_nLine].buffer.size())) { const Line& line = m_Lines[at.m_nLine]; - isword = isalnum(line[cindex].m_Char); + isword = isalnum(line.buffer[cindex]); skip = isword; } @@ -429,14 +440,14 @@ CTextLogger::Coordinates CTextLogger::FindNextWord(const Coordinates & aFrom) co { if (at.m_nLine >= static_cast(m_Lines.size())) { - int l = std::max(0, static_cast(m_Lines.size() - 1)); + int l = ImMax(0, static_cast(m_Lines.size() - 1)); return Coordinates(l, GetLineMaxColumn(l)); } const Line& line = m_Lines[at.m_nLine]; - if (cindex < static_cast(line.size())) + if (cindex < line.Length()) { - isword = isalnum(line[cindex].m_Char); + isword = isalnum(line.buffer[cindex]); if (isword && !skip) return Coordinates(at.m_nLine, GetCharacterColumn(at.m_nLine, cindex)); @@ -467,13 +478,13 @@ int CTextLogger::GetCharacterIndex(const Coordinates& aCoordinates) const int c = 0; int i = 0; - for (; i < static_cast(line.size()) && c < aCoordinates.m_nColumn;) + for (; i < line.Length() && c < aCoordinates.m_nColumn;) { - if (line[i].m_Char == '\t') + if (line.buffer[i] == '\t') c = (c / m_nTabSize) * m_nTabSize + m_nTabSize; else ++c; - i += UTF8CharLength(line[i].m_Char); + i += UTF8CharLength(line.buffer[i]); } return i; } @@ -487,9 +498,9 @@ int CTextLogger::GetCharacterColumn(int aLine, int aIndex) const int col = 0; int i = 0; - while (i < aIndex && i < static_cast(line.size())) + while (i < aIndex && i < line.Length()) { - Char c = line[i].m_Char; + Char c = line.buffer[i]; i += UTF8CharLength(c); if (c == '\t') col = (col / m_nTabSize) * m_nTabSize + m_nTabSize; @@ -507,8 +518,8 @@ int CTextLogger::GetLineCharacterCount(int aLine) const const Line& line = m_Lines[aLine]; int c = 0; - for (size_t i = 0; i < line.size(); c++) - i += static_cast(UTF8CharLength(m_Lines[aLine][i].m_Char)); + for (size_t i = 0; i < line.Length(); c++) + i += static_cast(UTF8CharLength(m_Lines[aLine].buffer[i])); return c; } @@ -520,9 +531,9 @@ int CTextLogger::GetLineMaxColumn(int aLine) const const Line& line = m_Lines[aLine]; int col = 0; - for (size_t i = 0; i < line.size(); ) + for (size_t i = 0; i < line.Length(); ) { - Char c = line[i].m_Char; + Char c = line.buffer[i]; if (c == '\t') col = (col / m_nTabSize) * m_nTabSize + m_nTabSize; else @@ -540,10 +551,10 @@ bool CTextLogger::IsOnWordBoundary(const Coordinates & aAt) const const Line& line = m_Lines[aAt.m_nLine]; size_t cindex = static_cast(GetCharacterIndex(aAt)); - if (cindex >= line.size()) + if (cindex >= line.Length()) return true; - return isspace(line[cindex].m_Char) != isspace(line[cindex - 1].m_Char); + return isspace(line.buffer[cindex]) != isspace(line.buffer[cindex - 1]); } void CTextLogger::RemoveLine(int aStart, int aEnd) @@ -563,6 +574,7 @@ void CTextLogger::RemoveLine(int aIndex) assert(!m_Lines.empty()); } +// TODO[ AMOS ]: rename to InsertBlankLine ? CTextLogger::Line& CTextLogger::InsertLine(int aIndex) { Line& result = *m_Lines.insert(m_Lines.begin() + aIndex, Line()); @@ -586,16 +598,16 @@ std::string CTextLogger::GetWordAt(const Coordinates & aCoords) const int iend = GetCharacterIndex(end); for (int it = istart; it < iend; ++it) - r.push_back(m_Lines[aCoords.m_nLine][it].m_Char); + r.push_back(m_Lines[aCoords.m_nLine].buffer[it]); return r; } -ImU32 CTextLogger::GetGlyphColor(const Glyph & aGlyph) const -{ - ImVec4 color = aGlyph.m_Color; - return ImGui::ColorConvertFloat4ToU32(color); -} +//ImU32 CTextLogger::GetGlyphColor(const Glyph & aGlyph) const +//{ +// ImVec4 color = aGlyph.m_Color; +// return ImGui::ColorConvertFloat4ToU32(color); +//} void CTextLogger::HandleKeyboardInputs(bool bHoveredScrollbar, bool bActiveScrollbar) { @@ -760,11 +772,13 @@ void CTextLogger::Render() { ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); - ImGuiWindow* pWindow = ImGui::GetCurrentWindow(); - ImGuiID activeID = ImGui::GetActiveID(); - ImGuiID hoveredID = ImGui::GetHoveredID(); - bool bHoveredScrollbar = hoveredID && (hoveredID == ImGui::GetWindowScrollbarID(pWindow, ImGuiAxis_X) || hoveredID == ImGui::GetWindowScrollbarID(pWindow, ImGuiAxis_Y)); - bool bActiveScrollbar = activeID && (activeID == ImGui::GetWindowScrollbarID(pWindow, ImGuiAxis_X) || activeID == ImGui::GetWindowScrollbarID(pWindow, ImGuiAxis_Y)); + ImGuiWindow* const pWindow = ImGui::GetCurrentWindow(); + + const ImGuiID activeID = ImGui::GetActiveID(); + const ImGuiID hoveredID = ImGui::GetHoveredID(); + + const bool bHoveredScrollbar = hoveredID && (hoveredID == ImGui::GetWindowScrollbarID(pWindow, ImGuiAxis_X) || hoveredID == ImGui::GetWindowScrollbarID(pWindow, ImGuiAxis_Y)); + const bool bActiveScrollbar = activeID && (activeID == ImGui::GetWindowScrollbarID(pWindow, ImGuiAxis_X) || activeID == ImGui::GetWindowScrollbarID(pWindow, ImGuiAxis_Y)); if (m_bHandleUserInputs) { @@ -778,33 +792,27 @@ void CTextLogger::Render() const float fontSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, "#", nullptr, nullptr).x; m_CharAdvance = ImVec2(fontSize, ImGui::GetTextLineHeightWithSpacing() * m_flLineSpacing); - assert(m_svLineBuffer.empty()); + const ImVec2 contentSize = ImGui::GetWindowContentRegionMax(); + ImDrawList* const drawList = ImGui::GetWindowDrawList(); - ImVec2 contentSize = ImGui::GetWindowContentRegionMax(); - ImDrawList* drawList = ImGui::GetWindowDrawList(); - float longest(m_flTextStart); + const ImVec2 cursorScreenPos = ImGui::GetCursorScreenPos(); - ImVec2 cursorScreenPos = ImGui::GetCursorScreenPos(); - float scrollX = ImGui::GetScrollX(); - float scrollY = ImGui::GetScrollY(); + float longest = 0.0f; + const float scrollY = ImGui::GetScrollY(); - int lineNo = static_cast(floor(scrollY / m_CharAdvance.y)); - int lineMax = std::max(0, std::min(static_cast(m_Lines.size()) - 1, lineNo + static_cast(floor((scrollY + contentSize.y) / m_CharAdvance.y)))); - - //m_flTextStart = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf, nullptr, nullptr).x + m_nLeftMargin; + int lineNo = static_cast(ImFloor(scrollY / m_CharAdvance.y)); + const int lineMax = ImMax(0, ImMin(static_cast(m_Lines.size()) - 1, lineNo + static_cast(ImFloor((scrollY + contentSize.y) / m_CharAdvance.y)))); if (!m_Lines.empty()) { - float spaceSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ", nullptr, nullptr).x; - while (lineNo <= lineMax) { - ImVec2 lineStartScreenPos = ImVec2(cursorScreenPos.x, cursorScreenPos.y + lineNo * m_CharAdvance.y); - ImVec2 textScreenPos = ImVec2(lineStartScreenPos.x + m_flTextStart, lineStartScreenPos.y); + const ImVec2 lineStartScreenPos = ImVec2(cursorScreenPos.x, cursorScreenPos.y + lineNo * m_CharAdvance.y); + const ImVec2 textScreenPos = ImVec2(lineStartScreenPos.x, lineStartScreenPos.y); const Line& line = m_Lines[lineNo]; - longest = std::max(m_flTextStart + TextDistanceToLineStart(Coordinates(lineNo, GetLineMaxColumn(lineNo))), longest); - int columnNo = 0; + longest = TextDistanceToLineStart(Coordinates(lineNo, GetLineMaxColumn(lineNo))); + Coordinates lineStartCoord(lineNo, 0); Coordinates lineEndCoord(lineNo, GetLineMaxColumn(lineNo)); @@ -823,120 +831,58 @@ void CTextLogger::Render() if (sstart != -1 && ssend != -1 && sstart < ssend) { - ImVec2 vstart(lineStartScreenPos.x + m_flTextStart + sstart, lineStartScreenPos.y); - ImVec2 vend(lineStartScreenPos.x + m_flTextStart + ssend, lineStartScreenPos.y + m_CharAdvance.y); + const ImVec2 vstart(lineStartScreenPos.x + sstart, lineStartScreenPos.y); + const ImVec2 vend(lineStartScreenPos.x + ssend, lineStartScreenPos.y + m_CharAdvance.y); + drawList->AddRectFilled(vstart, vend, ImGui::GetColorU32(ImGuiCol_TextSelectedBg)); } - if (m_State.m_CursorPosition.m_nLine == lineNo) + // Render the cursor + if (m_State.m_CursorPosition.m_nLine == lineNo && ImGui::IsWindowFocused()) { - bool focused = ImGui::IsWindowFocused(); - ImVec2 start = ImVec2(lineStartScreenPos.x + scrollX, lineStartScreenPos.y); + const ImS64 timeEnd = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + const ImU64 elapsed = timeEnd - m_nStartTime; - // Render the cursor - if (focused) + if (elapsed > 400) { - auto timeEnd = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - auto elapsed = timeEnd - m_nStartTime; - if (elapsed > 400) - { - float width = 1.0f; - float cx = TextDistanceToLineStart(m_State.m_CursorPosition); + const float width = 1.0f; + const float cx = TextDistanceToLineStart(m_State.m_CursorPosition); - const ImVec2 cstart(textScreenPos.x + cx, lineStartScreenPos.y); - const ImVec2 cend(textScreenPos.x + cx + width, lineStartScreenPos.y + m_CharAdvance.y); + const ImVec2 cstart(textScreenPos.x + cx, lineStartScreenPos.y); + const ImVec2 cend(textScreenPos.x + cx + width, lineStartScreenPos.y + m_CharAdvance.y); - drawList->AddRectFilled(cstart, cend, 0xffe0e0e0); - if (elapsed > 800) - m_nStartTime = timeEnd; - } + drawList->AddRectFilled(cstart, cend, 0xffe0e0e0); + + if (elapsed > 800) + m_nStartTime = timeEnd; } } - ImVec2 bufferOffset; - for (size_t i = 0; i < line.size();) + if (!line.buffer.empty()) { - const Glyph& glyph = line[i]; - ImU32 color = 0xff605040; + ImU32 color = line.color; if (m_itFilter.IsActive()) { - if (m_itFilter.PassFilter(GetTextFromLine(line).c_str())) - color = GetGlyphColor(glyph); - } - else - color = GetGlyphColor(glyph); - - if ((glyph.m_Char == '\t' || glyph.m_Char == '\n' || glyph.m_Char == ' ') && !m_svLineBuffer.empty()) - { - const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, textScreenPos.y + bufferOffset.y); - const ImVec2 textSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, m_svLineBuffer.c_str(), nullptr, nullptr); - - drawList->AddText(newOffset, color, m_svLineBuffer.c_str()); - bufferOffset.x += textSize.x; - m_svLineBuffer.clear(); + // Make line dark if it isn't found by the filter + if (!m_itFilter.PassFilter(line.buffer.c_str())) + color = 0xff605040; } - if (glyph.m_Char == '\t' || glyph.m_Char == '\n') - { - float oldX = bufferOffset.x; - bufferOffset.x = (1.0f + std::floor((1.0f + bufferOffset.x) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize); - ++i; - - if (m_bShowWhiteSpaces) - { - const float s = ImGui::GetFontSize(); - const float x1 = textScreenPos.x + oldX + 1.0f; - const float x2 = textScreenPos.x + bufferOffset.x - 1.0f; - const float y = textScreenPos.y + bufferOffset.y + s * 0.5f; - const ImVec2 p1(x1, y); - const ImVec2 p2(x2, y); - const ImVec2 p3(x2 - s * 0.2f, y - s * 0.2f); - const ImVec2 p4(x2 - s * 0.2f, y + s * 0.2f); - drawList->AddLine(p1, p2, 0x90909090); - drawList->AddLine(p2, p3, 0x90909090); - drawList->AddLine(p2, p4, 0x90909090); - } - } - else if (glyph.m_Char == ' ') - { - if (m_bShowWhiteSpaces) - { - const float s = ImGui::GetFontSize(); - const float x = textScreenPos.x + bufferOffset.x + spaceSize * 0.5f; - const float y = textScreenPos.y + bufferOffset.y + s * 0.5f; - drawList->AddCircleFilled(ImVec2(x, y), 1.5f, 0x80808080, 4); - } - bufferOffset.x += spaceSize; - i++; - } - else - { - size_t l = UTF8CharLength(glyph.m_Char); - while (l-- > 0 && i < line.size()) - m_svLineBuffer.push_back(line[i++].m_Char); - } - ++columnNo; - } - - if (!m_svLineBuffer.empty()) - { - const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, textScreenPos.y + bufferOffset.y); - drawList->AddText(newOffset, 0xffffffff, m_svLineBuffer.c_str()); // COLOR (obtain from glyph?) - m_svLineBuffer.clear(); + const ImVec2 newOffset(textScreenPos.x, textScreenPos.y); + drawList->AddText(newOffset, color, line.buffer.c_str()); } ++lineNo; } } - ImGui::Dummy(ImVec2((longest + 2), m_Lines.size() * m_CharAdvance.y)); m_bScrolledToBottom = ImGui::GetScrollY() >= ImGui::GetScrollMaxY(); if (m_bScrollToBottom || (m_bAutoScroll && m_bScrolledToBottom && !m_bScrollToCursor)) { - ImGui::SetScrollHereX(0.0f); + ImGui::SetScrollHereX(0.0f); // TODO[ AMOS ]: only scroll x if a command has been submitted ImGui::SetScrollHereY(1.0f); m_bScrollToBottom = false; @@ -960,12 +906,8 @@ void CTextLogger::Copy(bool aCopyAll) { if (!m_Lines.empty()) { - std::string str; const Line& line = m_Lines[GetActualCursorCoordinates().m_nLine]; - for (const Glyph& g : line) - str.push_back(g.m_Char); - - ImGui::SetClipboardText(str.c_str()); + ImGui::SetClipboardText(line.buffer.c_str()); } } else // Copy all lines to clipboard. @@ -973,52 +915,52 @@ void CTextLogger::Copy(bool aCopyAll) std::string str; for (const Line& line : m_Lines) { - for (const Glyph& g : line) - str.push_back(g.m_Char); + str.append(line.buffer); } + ImGui::SetClipboardText(str.c_str()); } } -void CTextLogger::SetText(const ConLog_t& aText) -{ - m_Lines.clear(); - m_Lines.emplace_back(Line()); - for (char chr : aText.m_svConLog) - { - if (chr == '\r') // ignore the carriage return character - continue; - else if (chr == '\n') - m_Lines.emplace_back(Line()); - else - m_Lines.back().emplace_back(Glyph(chr, aText.m_imColor)); - } -} +//void CTextLogger::SetText(const ConLog_t& aText) +//{ +// m_Lines.clear(); +// m_Lines.emplace_back(Line()); +// for (char chr : aText.m_svConLog) +// { +// if (chr == '\r') // ignore the carriage return character +// continue; +// else if (chr == '\n') +// m_Lines.emplace_back(Line()); +// else +// m_Lines.back().emplace_back(Glyph(chr, aText.m_imColor)); +// } +//} -void CTextLogger::SetTextLines(const std::vector& aLines) -{ - m_Lines.clear(); - - if (aLines.empty()) - { - m_Lines.emplace_back(Line()); - } - else - { - m_Lines.resize(aLines.size()); - - for (size_t i = 0; i < aLines.size(); ++i) - { - const std::string & aLine = aLines[i].m_svConLog; - - m_Lines[i].reserve(aLine.size()); - for (size_t j = 0; j < aLine.size(); ++j) - { - m_Lines[i].emplace_back(Glyph(aLine[j], aLines[i].m_imColor)); - } - } - } -} +//void CTextLogger::SetTextLines(const std::vector& aLines) +//{ +// m_Lines.clear(); +// +// if (aLines.empty()) +// { +// m_Lines.emplace_back(Line()); +// } +// else +// { +// m_Lines.resize(aLines.size()); +// +// for (size_t i = 0; i < aLines.size(); ++i) +// { +// const std::string & aLine = aLines[i].m_svConLog; +// +// m_Lines[i].reserve(aLine.size()); +// for (size_t j = 0; j < aLine.size(); ++j) +// { +// m_Lines[i].emplace_back(Glyph(aLine[j], aLines[i].m_imColor)); +// } +// } +// } +//} void CTextLogger::MoveCursor(int aLines, bool aForward) { @@ -1063,14 +1005,14 @@ void CTextLogger::SetSelectionStart(const Coordinates & aPosition) { m_State.m_SelectionStart = SanitizeCoordinates(aPosition); if (m_State.m_SelectionStart > m_State.m_SelectionEnd) - std::swap(m_State.m_SelectionStart, m_State.m_SelectionEnd); + ImSwap(m_State.m_SelectionStart, m_State.m_SelectionEnd); } void CTextLogger::SetSelectionEnd(const Coordinates & aPosition) { m_State.m_SelectionEnd = SanitizeCoordinates(aPosition); if (m_State.m_SelectionStart > m_State.m_SelectionEnd) - std::swap(m_State.m_SelectionStart, m_State.m_SelectionEnd); + ImSwap(m_State.m_SelectionStart, m_State.m_SelectionEnd); } void CTextLogger::SetSelection(const Coordinates & aStart, const Coordinates & aEnd, SelectionMode aMode) @@ -1080,8 +1022,9 @@ void CTextLogger::SetSelection(const Coordinates & aStart, const Coordinates & a m_State.m_SelectionStart = SanitizeCoordinates(aStart); m_State.m_SelectionEnd = SanitizeCoordinates(aEnd); + if (m_State.m_SelectionStart > m_State.m_SelectionEnd) - std::swap(m_State.m_SelectionStart, m_State.m_SelectionEnd); + ImSwap(m_State.m_SelectionStart, m_State.m_SelectionEnd); switch (aMode) { @@ -1109,26 +1052,28 @@ void CTextLogger::SetSelection(const Coordinates & aStart, const Coordinates & a void CTextLogger::SetTabSize(int aValue) { - m_nTabSize = std::max(0, std::min(32, aValue)); + m_nTabSize = ImMax(0, ImMin(32, aValue)); } -void CTextLogger::InsertText(const ConLog_t & aValue) +void CTextLogger::InsertText(const char* const text, const ImU32 color) { - if (!aValue.m_svConLog.empty()) - { - Coordinates pos = GetActualLastLineCoordinates(); + IM_ASSERT(text); - const Coordinates &start = std::min(pos, m_State.m_SelectionStart); - int totalLines = pos.m_nLine - start.m_nLine; + if (!*text) + return; - totalLines += InsertTextAt(pos, aValue.m_svConLog.c_str(), aValue.m_imColor); - } + Coordinates pos = GetActualLastLineCoordinates(); + + const Coordinates& start = ImMin(pos, m_State.m_SelectionStart); + int totalLines = pos.m_nLine - start.m_nLine; + + totalLines += InsertTextAt(pos, text, color); } void CTextLogger::MoveUp(int aAmount, bool aSelect) { const Coordinates oldPos = m_State.m_CursorPosition; - m_State.m_CursorPosition.m_nLine = std::max(0, m_State.m_CursorPosition.m_nLine - aAmount); + m_State.m_CursorPosition.m_nLine = ImMax(0, m_State.m_CursorPosition.m_nLine - aAmount); if (oldPos != m_State.m_CursorPosition) { if (aSelect) @@ -1156,7 +1101,7 @@ void CTextLogger::MoveDown(int aAmount, bool aSelect) assert(m_State.m_CursorPosition.m_nColumn >= 0); Coordinates oldPos = m_State.m_CursorPosition; - m_State.m_CursorPosition.m_nLine = std::max(0, std::min(static_cast(m_Lines.size() - 1), m_State.m_CursorPosition.m_nLine + aAmount)); + m_State.m_CursorPosition.m_nLine = ImMax(0, ImMin(static_cast(m_Lines.size() - 1), m_State.m_CursorPosition.m_nLine + aAmount)); if (m_State.m_CursorPosition != oldPos) { @@ -1204,7 +1149,7 @@ void CTextLogger::MoveLeft(int aAmount, bool aSelect, bool aWordMode) { --line; if (static_cast(m_Lines.size()) > line) - cindex = static_cast(m_Lines[line].size()); + cindex = static_cast(m_Lines[line].buffer.size()); else cindex = 0; } @@ -1218,11 +1163,11 @@ void CTextLogger::MoveLeft(int aAmount, bool aSelect, bool aWordMode) { const Line &lineData = m_Lines[line]; - while (cindex > 0 && IsUTFSequence(lineData[cindex].m_Char)) + while (cindex > 0 && IsUTFSequence(lineData.buffer[cindex])) --cindex; // Skip the newline character. - if (cindex > 0 && lineData[cindex].m_Char == '\n') + if (cindex > 0 && lineData.buffer[cindex] == '\n') --cindex; } } @@ -1272,18 +1217,18 @@ void CTextLogger::MoveRight(int aAmount, bool aSelect, bool aWordMode) const Line& line = m_Lines[lindex]; bool isNewLine = false; - const bool isLastChar = (cindex >= static_cast(line.size())-1); + const bool isLastChar = (cindex >= line.Length()-1); // If the cursor is at the last character before the newline character, // we want to skip the newline character and move to the next line. - if (isLastChar && !line.empty()) - isNewLine = line.back().m_Char == '\n'; + if (isLastChar && !line.buffer.empty()) + isNewLine = line.buffer.back() == '\n'; - if (cindex >= static_cast(line.size()) || isNewLine) + if (cindex >= line.Length() || isNewLine) { if (m_State.m_CursorPosition.m_nLine < static_cast(m_Lines.size()) - 1) { - m_State.m_CursorPosition.m_nLine = std::max(0, std::min(static_cast(m_Lines.size()) - 1, m_State.m_CursorPosition.m_nLine + 1)); + m_State.m_CursorPosition.m_nLine = ImMax(0, ImMin(static_cast(m_Lines.size()) - 1, m_State.m_CursorPosition.m_nLine + 1)); m_State.m_CursorPosition.m_nColumn = 0; } else @@ -1291,7 +1236,7 @@ void CTextLogger::MoveRight(int aAmount, bool aSelect, bool aWordMode) } else { - cindex += UTF8CharLength(line[cindex].m_Char); + cindex += UTF8CharLength(line.buffer[cindex]); m_State.m_CursorPosition = Coordinates(lindex, GetCharacterColumn(lindex, cindex)); if (aWordMode) m_State.m_CursorPosition = FindNextWord(m_State.m_CursorPosition); @@ -1485,13 +1430,7 @@ std::vector CTextLogger::GetTextLines() const for (const Line& line : m_Lines) { - std::string text; - text.resize(line.size()); - - for (size_t i = 0; i < line.size(); ++i) - text[i] = line[i].m_Char; - - result.emplace_back(std::move(text)); + result.emplace_back(line.buffer); } return result; @@ -1510,57 +1449,28 @@ std::string CTextLogger::GetCurrentLineText()const Coordinates(m_State.m_CursorPosition.m_nLine, lineLength)); } -std::string CTextLogger::GetTextFromLine(const Line& aLine) const -{ - std::string result; - for (const Glyph& glyph : aLine) - result.push_back(glyph.m_Char); - - return result; -} - -int CTextLogger::GetTotalFilterMatches() const -{ - if (!m_itFilter.IsActive()) - return static_cast(m_Lines.size()); - - int result = 0; - for (size_t i = 0; i < m_Lines.size(); i++) - { - std::string svLineBuffer; - for (size_t j = 0; j < m_Lines[i].size(); j++) - { - svLineBuffer += m_Lines[i][j].m_Char; - } - if (m_itFilter.PassFilter(svLineBuffer.c_str())) - { - result++; - } - } - return result; -} - float CTextLogger::TextDistanceToLineStart(const Coordinates& aFrom) const { const Line& line = m_Lines[aFrom.m_nLine]; float distance = 0.0f; float spaceSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ", nullptr, nullptr).x; int colIndex = GetCharacterIndex(aFrom); - for (size_t it = 0u; it < line.size() && it < colIndex; ) + + for (size_t it = 0u; it < line.Length() && it < colIndex; ) { - if (line[it].m_Char == '\t') + if (line.buffer[it] == '\t') { - distance = (1.0f + std::floor((1.0f + distance) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize); + distance = (1.0f + ImFloor((1.0f + distance) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize); ++it; } else { - size_t d = UTF8CharLength(line[it].m_Char); + size_t d = UTF8CharLength(line.buffer[it]); size_t i = 0; char tempCString[7]; - for (; i < 6 && d-- > 0 && it < line.size(); i++, it++) - tempCString[i] = line[it].m_Char; + for (; i < 6 && d-- > 0 && it < line.Length(); i++, it++) + tempCString[i] = line.buffer[it]; tempCString[i] = '\0'; distance += ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, tempCString, nullptr, nullptr).x; @@ -1581,24 +1491,24 @@ void CTextLogger::EnsureCursorVisible() float width = ImGui::GetWindowWidth(); float height = ImGui::GetWindowHeight(); - int top = 1 + static_cast(ceil(scrollY / m_CharAdvance.y)); - int bottom = static_cast(ceil((scrollY + height) / m_CharAdvance.y)); + int top = 1 + static_cast(ImCeil(scrollY / m_CharAdvance.y)); + int bottom = static_cast(ImCeil((scrollY + height) / m_CharAdvance.y)); - int left = static_cast(ceil(scrollX / m_CharAdvance.x)); - int right = static_cast(ceil((scrollX + width) / m_CharAdvance.x)); + int left = static_cast(ImCeil(scrollX / m_CharAdvance.x)); + int right = static_cast(ImCeil((scrollX + width) / m_CharAdvance.x)); if (pos.m_nColumn < left) - ImGui::SetScrollX(std::max(0.0f, (pos.m_nColumn) * m_CharAdvance.x)); + ImGui::SetScrollX(ImMax(0.0f, (pos.m_nColumn) * m_CharAdvance.x)); if (pos.m_nColumn > right - 3) - ImGui::SetScrollX(std::max(0.0f, (pos.m_nColumn + 3) * m_CharAdvance.x - width)); + ImGui::SetScrollX(ImMax(0.0f, (pos.m_nColumn + 3) * m_CharAdvance.x - width)); if (pos.m_nLine < top) - ImGui::SetScrollY(std::max(0.0f, (pos.m_nLine) * m_CharAdvance.y)); + ImGui::SetScrollY(ImMax(0.0f, (pos.m_nLine) * m_CharAdvance.y)); if (pos.m_nLine > bottom - 2) - ImGui::SetScrollY(std::max(0.0f, (pos.m_nLine + 2) * m_CharAdvance.y - height)); + ImGui::SetScrollY(ImMax(0.0f, (pos.m_nLine + 2) * m_CharAdvance.y - height)); } int CTextLogger::GetPageSize() const { float height = ImGui::GetWindowHeight() - 20.0f; - return static_cast(floor(height / m_CharAdvance.y)); + return static_cast(ImFloor(height / m_CharAdvance.y)); } diff --git a/src/thirdparty/imgui/misc/imgui_logger.h b/src/thirdparty/imgui/misc/imgui_logger.h index 1bf207fe..64e7caea 100644 --- a/src/thirdparty/imgui/misc/imgui_logger.h +++ b/src/thirdparty/imgui/misc/imgui_logger.h @@ -12,17 +12,6 @@ #include #include "imgui.h" -struct ConLog_t -{ - ConLog_t(const std::string& svConLog, const ImVec4& imColor) - { - m_svConLog = svConLog; - m_imColor = imColor; - } - std::string m_svConLog; - ImVec4 m_imColor; -}; - class CTextLogger { public: @@ -98,15 +87,34 @@ public: typedef std::string String; typedef uint8_t Char; - struct Glyph - { - Char m_Char; - ImVec4 m_Color = ImVec4(0.23f, 0.47f, 0.85f, 1.00f); + //struct Glyph + //{ + // Char m_Char; + // ImVec4 m_Color = ImVec4(0.23f, 0.47f, 0.85f, 1.00f); - Glyph(Char aChar, ImVec4 aColor = ImVec4(0.80f, 0.80f, 0.80f, 1.00f)) : m_Char(aChar), m_Color(aColor) {} + // Glyph(Char aChar, ImVec4 aColor = ImVec4(0.80f, 0.80f, 0.80f, 1.00f)) : m_Char(aChar), m_Color(aColor) {} + //}; + + //typedef std::vector Line; + + + + struct Line + { + std::string buffer; + ImU32 color; + + inline int Length() const + { + return static_cast(buffer.size()); + } + + Line(const char* const text = "", const ImU32 col = 0xFFFFFFFF) + : buffer(text) + , color(col) + {} }; - typedef std::vector Line; typedef std::vector Lines; CTextLogger(); @@ -115,20 +123,17 @@ public: void Render(); void Copy(bool aCopyAll = false); - void SetText(const ConLog_t& aText); + //void SetText(const ConLog_t& aText); std::string GetText() const; - void SetTextLines(const std::vector& aLines); + //void SetTextLines(const std::vector& aLines); std::vector GetTextLines() const; ImGuiTextFilter& GetFilter() { return m_itFilter; }; std::string GetSelectedText() const; std::string GetCurrentLineText() const; - std::string GetTextFromLine(const Line& aLine) const; - int GetTotalFilterMatches() const; int GetTotalLines() const { return (int)m_Lines.size(); } - Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); } void MoveCursor(int aLines, bool aForward = true); @@ -137,9 +142,6 @@ public: inline void SetHandleUserInputs (bool aValue){ m_bHandleUserInputs = aValue;} inline bool IsHandleUserInputs() const { return m_bHandleUserInputs; } - inline void SetShowWhitespaces(bool aValue) { m_bShowWhiteSpaces = aValue; } - inline bool IsShowingWhitespaces() const { return m_bShowWhiteSpaces; } - inline void ShouldScrollToBottom(bool aValue) { m_bScrollToBottom = aValue; } inline bool IsScrollingToBottom() const { return m_bScrollToBottom; } @@ -149,7 +151,7 @@ public: void SetTabSize(int aValue); inline int GetTabSize() const { return m_nTabSize; } - void InsertText(const ConLog_t& aValue); + void InsertText(const char* const text, const ImU32 color); void MoveUp(int aAmount = 1, bool aSelect = false); void MoveDown(int aAmount = 1, bool aSelect = false); @@ -188,8 +190,8 @@ private: Coordinates SanitizeCoordinates(const Coordinates& aValue) const; void Advance(Coordinates& aCoordinates) const; void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd); - int InsertTextAt(Coordinates& aWhere, const char* aValue, const ImVec4& aColor); - void MarkNewline(Coordinates& aWhere, const ImVec4& aColor, int aIndex); + int InsertTextAt(Coordinates& aWhere, const char* aValue, const ImU32 aColor); + void MarkNewline(Coordinates& aWhere, int aIndex); Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const; Coordinates FindWordStart(const Coordinates& aFrom) const; Coordinates FindWordEnd(const Coordinates& aFrom) const; @@ -202,7 +204,7 @@ private: Line& InsertLine(int aIndex); std::string GetWordUnderCursor() const; std::string GetWordAt(const Coordinates& aCoords) const; - ImU32 GetGlyphColor(const Glyph& aGlyph) const; + //ImU32 GetGlyphColor(const Glyph& aGlyph) const; void HandleKeyboardInputs(bool bHoveredScrollbar, bool bActiveScrollbar); void HandleMouseInputs(bool bHoveredScrollbar, bool bActiveScrollbar); @@ -216,12 +218,10 @@ private: bool m_bScrolledToBottom; bool m_bHandleUserInputs; bool m_bWithinLoggingRect; - bool m_bShowWhiteSpaces; bool m_bLinesOffsetForward; int m_nLinesOffsetAmount; int m_nTabSize; int m_nLeftMargin; - float m_flTextStart; // position (in pixels) where a code line starts relative to the left of the TextLogger. float m_flLineSpacing; SelectionMode m_SelectionMode; double m_flLastClick; @@ -233,7 +233,5 @@ private: ImVec2 m_CharAdvance; Lines m_Lines; - - std::string m_svLineBuffer; ImGuiTextFilter m_itFilter; };