From 1493de4f8173a54e2aa726a2b9a654aa43a735a3 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jan 2018 19:53:27 +0100 Subject: [PATCH 1/8] Internals: Merge of harmless stuff from Navigation stuff. Added GetHoveredID() internal helper. --- imgui.cpp | 11 +++++++++-- imgui_demo.cpp | 3 ++- imgui_internal.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1a1be7949..910101143 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1952,6 +1952,12 @@ void ImGui::SetHoveredID(ImGuiID id) g.HoveredIdTimer = (id != 0 && g.HoveredIdPreviousFrame == id) ? (g.HoveredIdTimer + g.IO.DeltaTime) : 0.0f; } +ImGuiID ImGui::GetHoveredID() +{ + ImGuiContext& g = *GImGui; + return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame; +} + void ImGui::KeepAliveID(ImGuiID id) { ImGuiContext& g = *GImGui; @@ -4773,6 +4779,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const float window_rounding = window->WindowRounding; const float window_border_size = window->WindowBorderSize; ImRect title_bar_rect = window->TitleBarRect(); + const bool window_is_focused = want_focus || (g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow); if (window->Collapsed) { // Title bar only @@ -4788,7 +4795,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); // Title bar - const bool window_is_focused = want_focus || (g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow); if (!(flags & ImGuiWindowFlags_NoTitleBar)) window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImDrawCornerFlags_Top); @@ -6358,7 +6364,8 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags if (!ItemAdd(bb, id)) return false; - if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; + if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) + flags |= ImGuiButtonFlags_Repeat; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9cebf88b3..87e4f57cf 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1552,7 +1552,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::OpenPopup("Stacked 2"); if (ImGui::BeginPopupModal("Stacked 2")) { - ImGui::Text("Hello from Stacked The Second"); + ImGui::Text("Hello from Stacked The Second!"); if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); @@ -1857,6 +1857,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf)); if (ImGui::IsItemActive()) has_focus = 3; ImGui::PopAllowKeyboardFocus(); + if (has_focus) ImGui::Text("Item with focus: %d", has_focus); else diff --git a/imgui_internal.h b/imgui_internal.h index 51702eab9..87a4a131a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -880,6 +880,7 @@ namespace ImGui IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); IMGUI_API void ClearActiveID(); IMGUI_API void SetHoveredID(ImGuiID id); + IMGUI_API ImGuiID GetHoveredID(); IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); From daa38f2ad0c8cbb7582a833051ab60055a54d0c6 Mon Sep 17 00:00:00 2001 From: Crunkle Date: Sun, 14 Jan 2018 03:31:22 +0000 Subject: [PATCH 2/8] Fix cross compilers --- imgui.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 910101143..ff6b871d4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11524,7 +11524,11 @@ void ImGui::EndDragDropTarget() #if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)) #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#ifndef __MINGW32__ #include +#else +#include +#endif #endif // Win32 API clipboard implementation From 514d30d8cdd659b6af3c93512583a00ee18ecbaf Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 14 Jan 2018 14:13:54 +0100 Subject: [PATCH 3/8] MovingWindow: Track click offset based on MovingWindow and not its RootWindow. Followup to 3849bb4470aebb4ff276113170f26cc82f990f49. Comments + adding a local to ease patch #1345. --- imgui.cpp | 15 +++++++++++---- imgui_internal.h | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ff6b871d4..fee26e2ff 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2392,10 +2392,17 @@ void ImGui::NewFrame() IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) { + // MovingWindow = window we clicked on, could be a child window. We track it to preserve Focus and so that ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. + // actually_moving_window = MovingWindow->RootWindow. + ImGuiWindow* actually_moving_window = g.MovingWindow->RootWindow; ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; - if (g.MovingWindow->RootWindow->PosFloat.x != pos.x || g.MovingWindow->RootWindow->PosFloat.y != pos.y) - MarkIniSettingsDirty(g.MovingWindow->RootWindow); - g.MovingWindow->RootWindow->PosFloat = pos; + if (actually_moving_window != g.MovingWindow) + pos += actually_moving_window->PosFloat - g.MovingWindow->PosFloat; + if (actually_moving_window->PosFloat.x != pos.x || actually_moving_window->PosFloat.y != pos.y) + { + MarkIniSettingsDirty(actually_moving_window); + actually_moving_window->PosFloat = pos; + } FocusWindow(g.MovingWindow); } else @@ -2950,7 +2957,7 @@ void ImGui::EndFrame() // Set ActiveId even if the _NoMove flag is set, without it dragging away from a window with _NoMove would activate hover on other windows. FocusWindow(g.HoveredWindow); SetActiveID(g.HoveredWindow->MoveId, g.HoveredWindow); - g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; + g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredWindow->Pos; if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovingWindow = g.HoveredWindow; diff --git a/imgui_internal.h b/imgui_internal.h index 87a4a131a..797f70758 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -534,7 +534,7 @@ struct ImGuiContext bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; - ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window. + ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow. ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() From 06eef2ce6fe3e41fec1a60eb37dbb8f97a0a89c9 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 17:25:11 +0100 Subject: [PATCH 4/8] Internals: DrawData: renamed fields only (committing separately so that next commit is less nosiy). --- imgui.cpp | 60 ++++++++++++++++++++++++------------------------ imgui_internal.h | 4 ++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fee26e2ff..4457ee5fd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2246,7 +2246,7 @@ ImGuiStyle& ImGui::GetStyle() // Same value as passed to your RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { - return GImGui->RenderDrawData.Valid ? &GImGui->RenderDrawData : NULL; + return GImGui->DrawData.Valid ? &GImGui->DrawData : NULL; } float ImGui::GetTime() @@ -2303,9 +2303,9 @@ void ImGui::NewFrame() g.OverlayDrawList.Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); // Mark rendering data as invalid to prevent user who may have a handle on it to use it - g.RenderDrawData.Valid = false; - g.RenderDrawData.CmdLists = NULL; - g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; + g.DrawData.Valid = false; + g.DrawData.CmdLists = NULL; + g.DrawData.CmdListsCount = g.DrawData.TotalVtxCount = g.DrawData.TotalIdxCount = 0; // Clear reference to active widget if the widget isn't alive anymore if (!g.HoveredIdPreviousFrame) @@ -2656,8 +2656,8 @@ void ImGui::Shutdown() g.FontStack.clear(); g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); - for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - g.RenderDrawLists[i].clear(); + for (int i = 0; i < IM_ARRAYSIZE(g.DrawDataLists); i++) + g.DrawDataLists[i].clear(); g.OverlayDrawList.ClearFreeMemory(); g.PrivateClipboard.clear(); g.InputTextState.Text.clear(); @@ -2902,11 +2902,11 @@ static void AddWindowToRenderListSelectLayer(ImGuiWindow* window) ImGuiContext& g = *GImGui; g.IO.MetricsActiveWindows++; if (window->Flags & ImGuiWindowFlags_Popup) - AddWindowToRenderList(g.RenderDrawLists[1], window); + AddWindowToRenderList(g.DrawDataLists[1], window); else if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(g.RenderDrawLists[2], window); + AddWindowToRenderList(g.DrawDataLists[2], window); else - AddWindowToRenderList(g.RenderDrawLists[0], window); + AddWindowToRenderList(g.DrawDataLists[0], window); } // When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. @@ -3031,8 +3031,8 @@ void ImGui::Render() { // Gather windows to render g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; - for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - g.RenderDrawLists[i].resize(0); + for (int i = 0; i < IM_ARRAYSIZE(g.DrawDataLists); i++) + g.DrawDataLists[i].resize(0); for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; @@ -3041,17 +3041,17 @@ void ImGui::Render() } // Flatten layers - int n = g.RenderDrawLists[0].Size; + int n = g.DrawDataLists[0].Size; int flattened_size = n; - for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - flattened_size += g.RenderDrawLists[i].Size; - g.RenderDrawLists[0].resize(flattened_size); - for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) + for (int i = 1; i < IM_ARRAYSIZE(g.DrawDataLists); i++) + flattened_size += g.DrawDataLists[i].Size; + g.DrawDataLists[0].resize(flattened_size); + for (int i = 1; i < IM_ARRAYSIZE(g.DrawDataLists); i++) { - ImVector& layer = g.RenderDrawLists[i]; + ImVector& layer = g.DrawDataLists[i]; if (layer.empty()) continue; - memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); + memcpy(&g.DrawDataLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); n += layer.Size; } @@ -3070,18 +3070,18 @@ void ImGui::Render() g.OverlayDrawList.PopTextureID(); } if (!g.OverlayDrawList.VtxBuffer.empty()) - AddDrawListToRenderList(g.RenderDrawLists[0], &g.OverlayDrawList); + AddDrawListToRenderList(g.DrawDataLists[0], &g.OverlayDrawList); // Setup draw data - g.RenderDrawData.Valid = true; - g.RenderDrawData.CmdLists = (g.RenderDrawLists[0].Size > 0) ? &g.RenderDrawLists[0][0] : NULL; - g.RenderDrawData.CmdListsCount = g.RenderDrawLists[0].Size; - g.RenderDrawData.TotalVtxCount = g.IO.MetricsRenderVertices; - g.RenderDrawData.TotalIdxCount = g.IO.MetricsRenderIndices; + g.DrawData.Valid = true; + g.DrawData.CmdLists = (g.DrawDataLists[0].Size > 0) ? &g.DrawDataLists[0][0] : NULL; + g.DrawData.CmdListsCount = g.DrawDataLists[0].Size; + g.DrawData.TotalVtxCount = g.IO.MetricsRenderVertices; + g.DrawData.TotalIdxCount = g.IO.MetricsRenderIndices; // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() - if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) - g.IO.RenderDrawListsFn(&g.RenderDrawData); + if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) + g.IO.RenderDrawListsFn(&g.DrawData); } } @@ -11749,11 +11749,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGuiContext& g = *GImGui; // Access private state Funcs::NodeWindows(g.Windows, "Windows"); - if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.RenderDrawLists[0].Size)) + if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataLists[0].Size)) { - for (int layer = 0; layer < IM_ARRAYSIZE(g.RenderDrawLists); layer++) - for (int i = 0; i < g.RenderDrawLists[layer].Size; i++) - Funcs::NodeDrawList(g.RenderDrawLists[0][i], "DrawList"); + for (int layer = 0; layer < IM_ARRAYSIZE(g.DrawDataLists); layer++) + for (int i = 0; i < g.DrawDataLists[layer].Size; i++) + Funcs::NodeDrawList(g.DrawDataLists[0][i], "DrawList"); ImGui::TreePop(); } if (ImGui::TreeNode("Popups", "Open Popups Stack (%d)", g.OpenPopupStack.Size)) diff --git a/imgui_internal.h b/imgui_internal.h index 797f70758..aba8c4192 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -546,8 +546,8 @@ struct ImGuiContext ImGuiCond NextTreeNodeOpenCond; // Render - ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user - ImVector RenderDrawLists[3]; + ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user + ImVector DrawDataLists[3]; float ModalWindowDarkeningRatio; ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays ImGuiMouseCursor MouseCursor; From 061d8df0336589ffee5061cec356496088f1fd8e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 17:29:18 +0100 Subject: [PATCH 5/8] MIssing IMGUI_API for a type with non-inline methods. --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index aba8c4192..a0909f888 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -448,7 +448,7 @@ struct ImGuiColumnsSet } }; -struct ImDrawListSharedData +struct IMGUI_API ImDrawListSharedData { ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas ImFont* Font; // Current/default font (optional, for simplified AddText overload) From 038453258e0dc03b159d9e8c16a98b092aedbc5f Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 17:48:07 +0100 Subject: [PATCH 6/8] Internals: DrawData: Refactored chunks into a ImDrawDataBuilder we can reuse. --- imgui.cpp | 115 +++++++++++++++++++++++++---------------------- imgui_internal.h | 12 ++++- 2 files changed, 72 insertions(+), 55 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4457ee5fd..89afeced7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -648,9 +648,9 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWind static void CheckStacksSize(ImGuiWindow* window, bool write); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); -static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list); -static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window); -static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, ImGuiWindow* window); +static void AddDrawListToRenderList(ImVector* out_render_list, ImDrawList* draw_list); +static void AddWindowToRenderList(ImVector* out_render_list, ImGuiWindow* window); +static void AddWindowToSortedBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); static ImGuiWindowSettings* AddWindowSettings(const char* name); @@ -2656,8 +2656,7 @@ void ImGui::Shutdown() g.FontStack.clear(); g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); - for (int i = 0; i < IM_ARRAYSIZE(g.DrawDataLists); i++) - g.DrawDataLists[i].clear(); + g.DrawDataBuilder.ClearFreeMemory(); g.OverlayDrawList.ClearFreeMemory(); g.PrivateClipboard.clear(); g.InputTextState.Text.clear(); @@ -2847,7 +2846,7 @@ static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, } } -static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list) +static void AddDrawListToRenderList(ImVector* out_render_list, ImDrawList* draw_list) { if (draw_list->CmdBuffer.empty()) return; @@ -2866,9 +2865,9 @@ static void AddDrawListToRenderList(ImVector& out_render_list, ImDr IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); - // Check that draw_list doesn't use more vertices than indexable in a single draw call (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) + // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) // If this assert triggers because you are drawing lots of stuff manually: - // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use thre Metrics window to inspect draw list contents. + // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use the Metrics window to inspect draw list contents. // B) If you need/want meshes with more than 64K vertices, uncomment the '#define ImDrawIdx unsigned int' line in imconfig.h to set the index size to 4 bytes. // You'll need to handle the 4-bytes indices to your renderer. For example, the OpenGL example code detect index size at compile-time by doing: // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); @@ -2877,36 +2876,61 @@ static void AddDrawListToRenderList(ImVector& out_render_list, ImDr if (sizeof(ImDrawIdx) == 2) IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); - out_render_list.push_back(draw_list); - GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; - GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; + out_render_list->push_back(draw_list); } -static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window) +static void AddWindowToRenderList(ImVector* out_render_list, ImGuiWindow* window) { AddDrawListToRenderList(out_render_list, window->DrawList); for (int i = 0; i < window->DC.ChildWindows.Size; i++) { ImGuiWindow* child = window->DC.ChildWindows[i]; - if (!child->Active) // clipped children may have been marked not active - continue; - if (child->HiddenFrames > 0) - continue; - AddWindowToRenderList(out_render_list, child); + if (child->Active && child->HiddenFrames <= 0) // clipped children may have been marked not active + AddWindowToRenderList(out_render_list, child); } } -static void AddWindowToRenderListSelectLayer(ImGuiWindow* window) +static void AddWindowToDrawDataSelectLayer(ImDrawDataBuilder* builder, ImGuiWindow* window) { - // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, .. ImGuiContext& g = *GImGui; g.IO.MetricsActiveWindows++; - if (window->Flags & ImGuiWindowFlags_Popup) - AddWindowToRenderList(g.DrawDataLists[1], window); - else if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(g.DrawDataLists[2], window); + if (window->Flags & ImGuiWindowFlags_Tooltip) + AddWindowToRenderList(&builder->Layers[2], window); + else if (window->Flags & ImGuiWindowFlags_Popup) + AddWindowToRenderList(&builder->Layers[1], window); else - AddWindowToRenderList(g.DrawDataLists[0], window); + AddWindowToRenderList(&builder->Layers[0], window); +} + +void ImDrawDataBuilder::FlattenIntoSingleLayer() +{ + int n = Layers[0].Size; + int size = n; + for (int i = 1; i < IM_ARRAYSIZE(Layers); i++) + size += Layers[i].Size; + Layers[0].resize(size); + for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++) + { + ImVector& layer = Layers[layer_n]; + if (layer.empty()) + continue; + memcpy(&Layers[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); + n += layer.Size; + layer.resize(0); + } +} + +void ImDrawDataBuilder::SetupDrawData(ImDrawData* out_draw_data) +{ + out_draw_data->Valid = true; + out_draw_data->CmdLists = (Layers[0].Size > 0) ? Layers[0].Data : NULL; + out_draw_data->CmdListsCount = Layers[0].Size; + out_draw_data->TotalVtxCount = out_draw_data->TotalIdxCount = 0; + for (int n = 0; n < Layers[0].Size; n++) + { + out_draw_data->TotalVtxCount += Layers[0][n]->VtxBuffer.Size; + out_draw_data->TotalIdxCount += Layers[0][n]->IdxBuffer.Size; + } } // When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. @@ -3031,29 +3055,14 @@ void ImGui::Render() { // Gather windows to render g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; - for (int i = 0; i < IM_ARRAYSIZE(g.DrawDataLists); i++) - g.DrawDataLists[i].resize(0); + g.DrawDataBuilder.Clear(); for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0) - AddWindowToRenderListSelectLayer(window); - } - - // Flatten layers - int n = g.DrawDataLists[0].Size; - int flattened_size = n; - for (int i = 1; i < IM_ARRAYSIZE(g.DrawDataLists); i++) - flattened_size += g.DrawDataLists[i].Size; - g.DrawDataLists[0].resize(flattened_size); - for (int i = 1; i < IM_ARRAYSIZE(g.DrawDataLists); i++) - { - ImVector& layer = g.DrawDataLists[i]; - if (layer.empty()) - continue; - memcpy(&g.DrawDataLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); - n += layer.Size; + AddWindowToDrawDataSelectLayer(&g.DrawDataBuilder, window); } + g.DrawDataBuilder.FlattenIntoSingleLayer(); // Draw software mouse cursor if requested if (g.IO.MouseDrawCursor) @@ -3070,14 +3079,12 @@ void ImGui::Render() g.OverlayDrawList.PopTextureID(); } if (!g.OverlayDrawList.VtxBuffer.empty()) - AddDrawListToRenderList(g.DrawDataLists[0], &g.OverlayDrawList); + AddDrawListToRenderList(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList); - // Setup draw data - g.DrawData.Valid = true; - g.DrawData.CmdLists = (g.DrawDataLists[0].Size > 0) ? &g.DrawDataLists[0][0] : NULL; - g.DrawData.CmdListsCount = g.DrawDataLists[0].Size; - g.DrawData.TotalVtxCount = g.IO.MetricsRenderVertices; - g.DrawData.TotalIdxCount = g.IO.MetricsRenderIndices; + // Setup ImDrawData structure for end-user + g.DrawDataBuilder.SetupDrawData(&g.DrawData); + g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount; + g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount; // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) @@ -11747,13 +11754,13 @@ void ImGui::ShowMetricsWindow(bool* p_open) } }; - ImGuiContext& g = *GImGui; // Access private state + // Access private state, we are going to display the draw lists from last frame + ImGuiContext& g = *GImGui; Funcs::NodeWindows(g.Windows, "Windows"); - if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataLists[0].Size)) + if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) { - for (int layer = 0; layer < IM_ARRAYSIZE(g.DrawDataLists); layer++) - for (int i = 0; i < g.DrawDataLists[layer].Size; i++) - Funcs::NodeDrawList(g.DrawDataLists[0][i], "DrawList"); + for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++) + Funcs::NodeDrawList(g.DrawDataBuilder.Layers[0][i], "DrawList"); ImGui::TreePop(); } if (ImGui::TreeNode("Popups", "Open Popups Stack (%d)", g.OpenPopupStack.Size)) diff --git a/imgui_internal.h b/imgui_internal.h index a0909f888..2c67cfcd3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -463,6 +463,16 @@ struct IMGUI_API ImDrawListSharedData ImDrawListSharedData(); }; +struct ImDrawDataBuilder +{ + ImVector Layers[3]; // Layered for: regular, popup, tooltip + + void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); } + void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); } + IMGUI_API void FlattenIntoSingleLayer(); + IMGUI_API void SetupDrawData(ImDrawData* out_draw_data); +}; + // Storage for SetNexWindow** functions struct ImGuiNextWindowData { @@ -547,7 +557,7 @@ struct ImGuiContext // Render ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user - ImVector DrawDataLists[3]; + ImDrawDataBuilder DrawDataBuilder; float ModalWindowDarkeningRatio; ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays ImGuiMouseCursor MouseCursor; From 0c06b43e6b5b0cb01a31c1985bd5009cf61ebc71 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 17:55:38 +0100 Subject: [PATCH 7/8] Metrics: Tweaks to hover-window-drawlist to see window bounding box. --- imgui.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 89afeced7..1937e96fb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11662,7 +11662,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) struct Funcs { - static void NodeDrawList(ImDrawList* draw_list, const char* label) + static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label) { bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); if (draw_list == ImGui::GetWindowDrawList()) @@ -11672,10 +11672,13 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (node_open) ImGui::TreePop(); return; } + + ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list + if (window && ImGui::IsItemHovered()) + overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); if (!node_open) return; - ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list int elem_offset = 0; for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++) { @@ -11741,10 +11744,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) { if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window)) return; - NodeDrawList(window->DrawList, "DrawList"); + NodeDrawList(window, window->DrawList, "DrawList"); ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); - if (ImGui::IsItemHovered()) - GImGui->OverlayDrawList.AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255,255,0,255)); ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); ImGui::BulletText("Active: %d, WriteAccessed: %d", window->Active, window->WriteAccessed); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); @@ -11760,7 +11761,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) { for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++) - Funcs::NodeDrawList(g.DrawDataBuilder.Layers[0][i], "DrawList"); + Funcs::NodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList"); ImGui::TreePop(); } if (ImGui::TreeNode("Popups", "Open Popups Stack (%d)", g.OpenPopupStack.Size)) From 1182174d818802e2c2692b515f0710224a53ffb6 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 18:00:13 +0100 Subject: [PATCH 8/8] Internals: DrawData: We don't need an intermediate layer for popups. --- imgui.cpp | 2 -- imgui_internal.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1937e96fb..f33ab67fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2895,8 +2895,6 @@ static void AddWindowToDrawDataSelectLayer(ImDrawDataBuilder* builder, ImGuiWind ImGuiContext& g = *GImGui; g.IO.MetricsActiveWindows++; if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(&builder->Layers[2], window); - else if (window->Flags & ImGuiWindowFlags_Popup) AddWindowToRenderList(&builder->Layers[1], window); else AddWindowToRenderList(&builder->Layers[0], window); diff --git a/imgui_internal.h b/imgui_internal.h index 2c67cfcd3..81230757f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -465,7 +465,7 @@ struct IMGUI_API ImDrawListSharedData struct ImDrawDataBuilder { - ImVector Layers[3]; // Layered for: regular, popup, tooltip + ImVector Layers[2]; // Global layers for: regular, tooltip void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); } void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); }