diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5b7fa035..6bdb7512 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -75,6 +75,9 @@ Other Changes: tampered with between NewFrame() and EndFrame(). - Misc, Freetype: Fixed support for IMGUI_STB_RECT_PACK_FILENAME compile time directive in imgui_freetype.cpp (matching support in the regular code path). (#3062) [@DonKult] +- Metrics: Made Tools section more prominent. Showing wire-frame mesh directly hovering the ImDrawCmd + instead of requiring to open it. Added options to disable bounding box and mesh display. + Added notes on inactive/gc-ed windows. - Demo: Added black and white and color gradients to Demo>Examples>Custom Rendering. - CI: Added more tests on the continuous-integration server: extra warnings for Clang/GCC, building SDL+Metal example, building imgui_freetype.cpp, more compile-time imconfig.h settings: disabling diff --git a/imgui.cpp b/imgui.cpp index ad39fa14..9876cf92 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9990,7 +9990,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) static bool show_windows_begin_order = false; static bool show_tables_rects = false; static int show_tables_rect_type = TRT_WorkRect; - static bool show_drawcmd_details = true; + static bool show_drawcmd_mesh = true; + static bool show_drawcmd_aabb = true; // Basic info ImGuiContext& g = *GImGui; @@ -10024,6 +10025,38 @@ void ImGui::ShowMetricsWindow(bool* p_open) return ImRect(); } + static void NodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow* window, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, int elem_offset, bool show_mesh, bool show_aabb) + { + IM_ASSERT(show_mesh || show_aabb); + ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list + ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; + + // Draw wire-frame version of all triangles + ImRect clip_rect = draw_cmd->ClipRect; + ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); + ImDrawListFlags backup_flags = fg_draw_list->Flags; + fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. + for (unsigned int base_idx = elem_offset; base_idx < (elem_offset + draw_cmd->ElemCount); base_idx += 3) + { + ImVec2 triangle[3]; + for (int n = 0; n < 3; n++) + { + ImVec2 p = draw_list->VtxBuffer[idx_buffer ? idx_buffer[base_idx + n] : (base_idx + n)].pos; + triangle[n] = p; + vtxs_rect.Add(p); + } + if (show_mesh) + fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); // In yellow: mesh triangles + } + // Draw bounding boxes + if (show_aabb) + { + fg_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU + fg_draw_list->AddRect(ImFloor(vtxs_rect.Min), ImFloor(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles + } + fg_draw_list->Flags = backup_flags; + } + 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); @@ -10061,15 +10094,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) pcmd->ElemCount/3, (void*)(intptr_t)pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); - if (show_drawcmd_details && fg_draw_list && ImGui::IsItemHovered()) - { - ImRect clip_rect = pcmd->ClipRect; - ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); - for (unsigned int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++) - vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos); - fg_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255,0,255,255)); - fg_draw_list->AddRect(ImFloor(vtxs_rect.Min), ImFloor(vtxs_rect.Max), IM_COL32(255,255,0,255)); - } + if (ImGui::IsItemHovered() && (show_drawcmd_mesh || show_drawcmd_aabb) && fg_draw_list) + NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, elem_offset, show_drawcmd_mesh, show_drawcmd_aabb); if (!pcmd_node_open) continue; @@ -10087,22 +10113,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) // Display vertex information summary. Hover to get all triangles drawn in wire-frame ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area); ImGui::Selectable(buf); - if (fg_draw_list && ImGui::IsItemHovered() && show_drawcmd_details) - { - // Draw wire-frame version of everything - ImDrawListFlags backup_flags = fg_draw_list->Flags; - fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. - ImRect clip_rect = pcmd->ClipRect; - fg_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255, 0, 255, 255)); - for (unsigned int base_idx = elem_offset; base_idx < (elem_offset + pcmd->ElemCount); base_idx += 3) - { - ImVec2 triangle[3]; - for (int n = 0; n < 3; n++) - triangle[n] = draw_list->VtxBuffer[idx_buffer ? idx_buffer[base_idx + n] : (base_idx + n)].pos; - fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), true, 1.0f); - } - fg_draw_list->Flags = backup_flags; - } + if (ImGui::IsItemHovered() && fg_draw_list) + NodeDrawCmdShowMeshAndBoundingBox(window, draw_list, pcmd, elem_offset, true, false); // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. @@ -10168,6 +10180,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::GetForegroundDrawList()->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); if (!open) return; + + if (!window->WasActive) + ImGui::TextDisabled("Note: window is not currently visible."); + if (window->MemoryCompacted) + ImGui::TextDisabled("Note: some memory buffers have been compacted/freed."); + ImGuiWindowFlags flags = window->Flags; NodeDrawList(window, window->DrawList, "DrawList"); ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y); @@ -10232,6 +10250,38 @@ void ImGui::ShowMetricsWindow(bool* p_open) } }; + + // Tools + if (ImGui::TreeNode("Tools")) + { + // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. + if (ImGui::Button("Item Picker..")) + ImGui::DebugStartItemPicker(); + ImGui::SameLine(); + MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); + + ImGui::Checkbox("Show windows begin order", &show_windows_begin_order); + ImGui::Checkbox("Show windows rectangles", &show_windows_rects); + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12); + show_windows_rects |= ImGui::Combo("##show_windows_rect_type", &show_windows_rect_type, wrt_rects_names, WRT_Count, WRT_Count); + if (show_windows_rects && g.NavWindow) + { + ImGui::BulletText("'%s':", g.NavWindow->Name); + ImGui::Indent(); + for (int rect_n = 0; rect_n < WRT_Count; rect_n++) + { + ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n); + ImGui::Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]); + } + ImGui::Unindent(); + } + ImGui::Checkbox("Show mesh when hovering ImDrawCmd", &show_drawcmd_mesh); + ImGui::Checkbox("Show bounding boxes when hovering ImDrawCmd", &show_drawcmd_aabb); + ImGui::TreePop(); + } + + // Contents Funcs::NodeWindows(g.Windows, "Windows"); //Funcs::NodeWindows(g.WindowsFocusOrder, "WindowsFocusOrder"); if (ImGui::TreeNode("DrawLists", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) @@ -10302,35 +10352,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::TreePop(); } - // Tools - if (ImGui::TreeNode("Tools")) - { - // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. - if (ImGui::Button("Item Picker..")) - ImGui::DebugStartItemPicker(); - ImGui::SameLine(); - MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); - - ImGui::Checkbox("Show windows begin order", &show_windows_begin_order); - ImGui::Checkbox("Show windows rectangles", &show_windows_rects); - ImGui::SameLine(); - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12); - show_windows_rects |= ImGui::Combo("##show_windows_rect_type", &show_windows_rect_type, wrt_rects_names, WRT_Count, WRT_Count); - if (show_windows_rects && g.NavWindow) - { - ImGui::BulletText("'%s':", g.NavWindow->Name); - ImGui::Indent(); - for (int rect_n = 0; rect_n < WRT_Count; rect_n++) - { - ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n); - ImGui::Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]); - } - ImGui::Unindent(); - } - ImGui::Checkbox("Show details when hovering ImDrawCmd node", &show_drawcmd_details); - ImGui::TreePop(); - } - // Overlay: Display windows Rectangles and Begin Order if (show_windows_rects || show_windows_begin_order) {