|
@@ -3819,7 +3819,7 @@ void ImGui::Shutdown(ImGuiContext* context)
|
|
fclose(g.LogFile);
|
|
fclose(g.LogFile);
|
|
g.LogFile = NULL;
|
|
g.LogFile = NULL;
|
|
}
|
|
}
|
|
- g.LogClipboard.clear();
|
|
|
|
|
|
+ g.LogBuffer.clear();
|
|
|
|
|
|
g.Initialized = false;
|
|
g.Initialized = false;
|
|
}
|
|
}
|
|
@@ -5800,7 +5800,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
|
|
window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
|
|
window->DC.NavLayerActiveMaskNext = 0x00;
|
|
window->DC.NavLayerActiveMaskNext = 0x00;
|
|
window->DC.MenuBarAppending = false;
|
|
window->DC.MenuBarAppending = false;
|
|
- window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;
|
|
|
|
window->DC.ChildWindows.resize(0);
|
|
window->DC.ChildWindows.resize(0);
|
|
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
|
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
|
window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
|
|
window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
|
|
@@ -7153,7 +7152,6 @@ void ImGui::BeginGroup()
|
|
group_data.BackupGroupOffset = window->DC.GroupOffset;
|
|
group_data.BackupGroupOffset = window->DC.GroupOffset;
|
|
group_data.BackupCurrentLineSize = window->DC.CurrentLineSize;
|
|
group_data.BackupCurrentLineSize = window->DC.CurrentLineSize;
|
|
group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
|
|
group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
|
|
- group_data.BackupLogLinePosY = window->DC.LogLinePosY;
|
|
|
|
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
|
|
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
|
|
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
|
|
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
|
|
group_data.AdvanceCursor = true;
|
|
group_data.AdvanceCursor = true;
|
|
@@ -7162,14 +7160,15 @@ void ImGui::BeginGroup()
|
|
window->DC.Indent = window->DC.GroupOffset;
|
|
window->DC.Indent = window->DC.GroupOffset;
|
|
window->DC.CursorMaxPos = window->DC.CursorPos;
|
|
window->DC.CursorMaxPos = window->DC.CursorPos;
|
|
window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
|
|
window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
|
|
- window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
|
|
|
|
|
|
+ if (g.LogEnabled)
|
|
|
|
+ g.LogLinePosY = -FLT_MAX; // To enforce Log carriage return
|
|
}
|
|
}
|
|
|
|
|
|
void ImGui::EndGroup()
|
|
void ImGui::EndGroup()
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
- IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
|
|
|
|
|
|
+ IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
|
|
|
|
|
|
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
|
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
|
|
|
|
|
@@ -7182,7 +7181,8 @@ void ImGui::EndGroup()
|
|
window->DC.GroupOffset = group_data.BackupGroupOffset;
|
|
window->DC.GroupOffset = group_data.BackupGroupOffset;
|
|
window->DC.CurrentLineSize = group_data.BackupCurrentLineSize;
|
|
window->DC.CurrentLineSize = group_data.BackupCurrentLineSize;
|
|
window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
|
|
window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
|
|
- window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
|
|
|
|
|
|
+ if (g.LogEnabled)
|
|
|
|
+ g.LogLinePosY = -FLT_MAX; // To enforce Log carriage return
|
|
|
|
|
|
if (group_data.AdvanceCursor)
|
|
if (group_data.AdvanceCursor)
|
|
{
|
|
{
|
|
@@ -8913,9 +8913,12 @@ static void ImGui::NavUpdate()
|
|
NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
|
|
NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
|
|
NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ );
|
|
NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ );
|
|
NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
|
|
NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
|
|
- if (g.IO.KeyCtrl) g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
|
|
|
|
- if (g.IO.KeyShift) g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
|
|
|
|
- if (g.IO.KeyAlt) g.IO.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f;
|
|
|
|
|
|
+ if (g.IO.KeyCtrl)
|
|
|
|
+ g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
|
|
|
|
+ if (g.IO.KeyShift)
|
|
|
|
+ g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
|
|
|
|
+ if (g.IO.KeyAlt && !g.IO.KeyCtrl) // AltGR is Alt+Ctrl, also even on keyboards without AltGR we don't want Alt+Ctrl to open menu.
|
|
|
|
+ g.IO.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f;
|
|
#undef NAV_MAP_KEY
|
|
#undef NAV_MAP_KEY
|
|
}
|
|
}
|
|
memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration));
|
|
memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration));
|
|
@@ -13210,7 +13213,7 @@ void ImGui::LogText(const char* fmt, ...)
|
|
if (g.LogFile)
|
|
if (g.LogFile)
|
|
vfprintf(g.LogFile, fmt, args);
|
|
vfprintf(g.LogFile, fmt, args);
|
|
else
|
|
else
|
|
- g.LogClipboard.appendfv(fmt, args);
|
|
|
|
|
|
+ g.LogBuffer.appendfv(fmt, args);
|
|
va_end(args);
|
|
va_end(args);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -13224,17 +13227,20 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
|
|
if (!text_end)
|
|
if (!text_end)
|
|
text_end = FindRenderedTextEnd(text, text_end);
|
|
text_end = FindRenderedTextEnd(text, text_end);
|
|
|
|
|
|
- const bool log_new_line = ref_pos && (ref_pos->y > window->DC.LogLinePosY + 1);
|
|
|
|
|
|
+ const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + 1);
|
|
if (ref_pos)
|
|
if (ref_pos)
|
|
- window->DC.LogLinePosY = ref_pos->y;
|
|
|
|
|
|
+ g.LogLinePosY = ref_pos->y;
|
|
|
|
+ if (log_new_line)
|
|
|
|
+ g.LogLineFirstItem = true;
|
|
|
|
|
|
const char* text_remaining = text;
|
|
const char* text_remaining = text;
|
|
- if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth
|
|
|
|
- g.LogStartDepth = window->DC.TreeDepth;
|
|
|
|
- const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth);
|
|
|
|
|
|
+ if (g.LogDepthRef > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth
|
|
|
|
+ g.LogDepthRef = window->DC.TreeDepth;
|
|
|
|
+ const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef);
|
|
for (;;)
|
|
for (;;)
|
|
{
|
|
{
|
|
// Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
|
|
// Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
|
|
|
|
+ // We don't add a trailing \n to allow a subsequent item on the same line to be captured.
|
|
const char* line_start = text_remaining;
|
|
const char* line_start = text_remaining;
|
|
const char* line_end = ImStreolRange(line_start, text_end);
|
|
const char* line_end = ImStreolRange(line_start, text_end);
|
|
const bool is_first_line = (line_start == text);
|
|
const bool is_first_line = (line_start == text);
|
|
@@ -13243,9 +13249,18 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
|
|
{
|
|
{
|
|
const int char_count = (int)(line_end - line_start);
|
|
const int char_count = (int)(line_end - line_start);
|
|
if (log_new_line || !is_first_line)
|
|
if (log_new_line || !is_first_line)
|
|
- LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, line_start);
|
|
|
|
- else
|
|
|
|
|
|
+ LogText(IM_NEWLINE "%*s%.*s", tree_depth * 4, "", char_count, line_start);
|
|
|
|
+ else if (g.LogLineFirstItem)
|
|
|
|
+ LogText("%*s%.*s", tree_depth * 4, "", char_count, line_start);
|
|
|
|
+ else
|
|
LogText(" %.*s", char_count, line_start);
|
|
LogText(" %.*s", char_count, line_start);
|
|
|
|
+ g.LogLineFirstItem = false;
|
|
|
|
+ }
|
|
|
|
+ else if (log_new_line)
|
|
|
|
+ {
|
|
|
|
+ // An empty "" string at a different Y position should output a carriage return.
|
|
|
|
+ LogText(IM_NEWLINE);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
if (is_last_line)
|
|
if (is_last_line)
|
|
@@ -13254,64 +13269,71 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-// Start logging ImGui output to TTY
|
|
|
|
-void ImGui::LogToTTY(int max_depth)
|
|
|
|
|
|
+// Start logging/capturing text output
|
|
|
|
+void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
- if (g.LogEnabled)
|
|
|
|
- return;
|
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
-
|
|
|
|
|
|
+ IM_ASSERT(g.LogEnabled == false);
|
|
IM_ASSERT(g.LogFile == NULL);
|
|
IM_ASSERT(g.LogFile == NULL);
|
|
- g.LogFile = stdout;
|
|
|
|
|
|
+ IM_ASSERT(g.LogBuffer.empty());
|
|
g.LogEnabled = true;
|
|
g.LogEnabled = true;
|
|
- g.LogStartDepth = window->DC.TreeDepth;
|
|
|
|
- if (max_depth >= 0)
|
|
|
|
- g.LogAutoExpandMaxDepth = max_depth;
|
|
|
|
|
|
+ g.LogType = type;
|
|
|
|
+ g.LogDepthRef = window->DC.TreeDepth;
|
|
|
|
+ g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault);
|
|
|
|
+ g.LogLinePosY = FLT_MAX;
|
|
|
|
+ g.LogLineFirstItem = true;
|
|
}
|
|
}
|
|
|
|
|
|
-// Start logging ImGui output to given file
|
|
|
|
-void ImGui::LogToFile(int max_depth, const char* filename)
|
|
|
|
|
|
+void ImGui::LogToTTY(int auto_open_depth)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ if (g.LogEnabled)
|
|
|
|
+ return;
|
|
|
|
+ LogBegin(ImGuiLogType_TTY, auto_open_depth);
|
|
|
|
+ g.LogFile = stdout;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Start logging/capturing text output to given file
|
|
|
|
+void ImGui::LogToFile(int auto_open_depth, const char* filename)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
if (g.LogEnabled)
|
|
if (g.LogEnabled)
|
|
return;
|
|
return;
|
|
- ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
|
|
|
|
|
|
+ // FIXME: We could probably open the file in text mode "at", however note that clipboard/buffer logging will still
|
|
|
|
+ // be subject to outputting OS-incompatible carriage return if within strings the user doesn't use IM_NEWLINE.
|
|
|
|
+ // By opening the file in binary mode "ab" we have consistent output everywhere.
|
|
if (!filename)
|
|
if (!filename)
|
|
- {
|
|
|
|
filename = g.IO.LogFilename;
|
|
filename = g.IO.LogFilename;
|
|
- if (!filename)
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- IM_ASSERT(g.LogFile == NULL);
|
|
|
|
- g.LogFile = ImFileOpen(filename, "ab");
|
|
|
|
- if (g.LogFile == NULL)
|
|
|
|
|
|
+ if (!filename || !filename[0])
|
|
|
|
+ return;
|
|
|
|
+ FILE* f = ImFileOpen(filename, "ab");
|
|
|
|
+ if (f == NULL)
|
|
{
|
|
{
|
|
IM_ASSERT(0);
|
|
IM_ASSERT(0);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- g.LogEnabled = true;
|
|
|
|
- g.LogStartDepth = window->DC.TreeDepth;
|
|
|
|
- if (max_depth >= 0)
|
|
|
|
- g.LogAutoExpandMaxDepth = max_depth;
|
|
|
|
|
|
+
|
|
|
|
+ LogBegin(ImGuiLogType_File, auto_open_depth);
|
|
|
|
+ g.LogFile = f;
|
|
}
|
|
}
|
|
|
|
|
|
-// Start logging ImGui output to clipboard
|
|
|
|
-void ImGui::LogToClipboard(int max_depth)
|
|
|
|
|
|
+// Start logging/capturing text output to clipboard
|
|
|
|
+void ImGui::LogToClipboard(int auto_open_depth)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
if (g.LogEnabled)
|
|
if (g.LogEnabled)
|
|
return;
|
|
return;
|
|
- ImGuiWindow* window = g.CurrentWindow;
|
|
|
|
|
|
+ LogBegin(ImGuiLogType_Clipboard, auto_open_depth);
|
|
|
|
+}
|
|
|
|
|
|
- IM_ASSERT(g.LogFile == NULL);
|
|
|
|
- g.LogFile = NULL;
|
|
|
|
- g.LogEnabled = true;
|
|
|
|
- g.LogStartDepth = window->DC.TreeDepth;
|
|
|
|
- if (max_depth >= 0)
|
|
|
|
- g.LogAutoExpandMaxDepth = max_depth;
|
|
|
|
|
|
+void ImGui::LogToBuffer(int auto_open_depth)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ if (g.LogEnabled)
|
|
|
|
+ return;
|
|
|
|
+ LogBegin(ImGuiLogType_Buffer, auto_open_depth);
|
|
}
|
|
}
|
|
|
|
|
|
void ImGui::LogFinish()
|
|
void ImGui::LogFinish()
|
|
@@ -13321,23 +13343,33 @@ void ImGui::LogFinish()
|
|
return;
|
|
return;
|
|
|
|
|
|
LogText(IM_NEWLINE);
|
|
LogText(IM_NEWLINE);
|
|
- if (g.LogFile != NULL)
|
|
|
|
- {
|
|
|
|
- if (g.LogFile == stdout)
|
|
|
|
- fflush(g.LogFile);
|
|
|
|
- else
|
|
|
|
- fclose(g.LogFile);
|
|
|
|
- g.LogFile = NULL;
|
|
|
|
- }
|
|
|
|
- if (g.LogClipboard.size() > 1)
|
|
|
|
|
|
+ switch (g.LogType)
|
|
{
|
|
{
|
|
- SetClipboardText(g.LogClipboard.begin());
|
|
|
|
- g.LogClipboard.clear();
|
|
|
|
|
|
+ case ImGuiLogType_TTY:
|
|
|
|
+ fflush(g.LogFile);
|
|
|
|
+ break;
|
|
|
|
+ case ImGuiLogType_File:
|
|
|
|
+ fclose(g.LogFile);
|
|
|
|
+ break;
|
|
|
|
+ case ImGuiLogType_Buffer:
|
|
|
|
+ break;
|
|
|
|
+ case ImGuiLogType_Clipboard:
|
|
|
|
+ if (!g.LogBuffer.empty())
|
|
|
|
+ SetClipboardText(g.LogBuffer.begin());
|
|
|
|
+ break;
|
|
|
|
+ case ImGuiLogType_None:
|
|
|
|
+ IM_ASSERT(0);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
+
|
|
g.LogEnabled = false;
|
|
g.LogEnabled = false;
|
|
|
|
+ g.LogType = ImGuiLogType_None;
|
|
|
|
+ g.LogFile = NULL;
|
|
|
|
+ g.LogBuffer.clear();
|
|
}
|
|
}
|
|
|
|
|
|
// Helper to display logging buttons
|
|
// Helper to display logging buttons
|
|
|
|
+// FIXME-OBSOLETE: We should probably obsolete this and let the user have their own helper (this is one of the oldest function alive!)
|
|
void ImGui::LogButtons()
|
|
void ImGui::LogButtons()
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -13348,18 +13380,18 @@ void ImGui::LogButtons()
|
|
const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
|
|
const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
|
|
PushItemWidth(80.0f);
|
|
PushItemWidth(80.0f);
|
|
PushAllowKeyboardFocus(false);
|
|
PushAllowKeyboardFocus(false);
|
|
- SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL);
|
|
|
|
|
|
+ SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL);
|
|
PopAllowKeyboardFocus();
|
|
PopAllowKeyboardFocus();
|
|
PopItemWidth();
|
|
PopItemWidth();
|
|
PopID();
|
|
PopID();
|
|
|
|
|
|
// Start logging at the end of the function so that the buttons don't appear in the log
|
|
// Start logging at the end of the function so that the buttons don't appear in the log
|
|
if (log_to_tty)
|
|
if (log_to_tty)
|
|
- LogToTTY(g.LogAutoExpandMaxDepth);
|
|
|
|
|
|
+ LogToTTY();
|
|
if (log_to_file)
|
|
if (log_to_file)
|
|
- LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename);
|
|
|
|
|
|
+ LogToFile();
|
|
if (log_to_clipboard)
|
|
if (log_to_clipboard)
|
|
- LogToClipboard(g.LogAutoExpandMaxDepth);
|
|
|
|
|
|
+ LogToClipboard();
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|