// File: donfreiday[P]gb/./imgui/imgui.cpp
// Function: ImGui::ShowMetricsWindow(bool*)
void ImGui::ShowMetricsWindow(bool* opened)
{
    if (ImGui::Begin("ImGui Metrics", opened))
    {
        ImGui::Text("ImGui %s", ImGui::GetVersion());
        ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
        ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3);
        ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs);
        static bool show_clip_rects = true;
        ImGui::Checkbox("Show clipping rectangles when hovering a ImDrawCmd", &show_clip_rects);
        ImGui::Separator();

        struct Funcs
        {
            static void NodeDrawList(ImDrawList* draw_list, const char* label)
            {
                bool node_opened = 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())
                {
                    ImGui::SameLine();
                    ImGui::TextColored(ImColor(255,100,100), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered)
                }
                if (!node_opened)
                    return;

                int elem_offset = 0;
                for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++)
                {
                    if (pcmd->UserCallback)
                        ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
                    else
                    {
                        ImGui::BulletText("Draw %d indexed vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
                        if (show_clip_rects && ImGui::IsItemHovered())
                        {
                            ImRect clip_rect = pcmd->ClipRect;
                            ImRect vtxs_rect;
                            for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++)
                                vtxs_rect.Add(draw_list->VtxBuffer[draw_list->IdxBuffer[i]].pos);
                            GImGui->OverlayDrawList.PushClipRectFullScreen();
                            clip_rect.Round(); GImGui->OverlayDrawList.AddRect(clip_rect.Min, clip_rect.Max, ImColor(255,255,0));
                            vtxs_rect.Round(); GImGui->OverlayDrawList.AddRect(vtxs_rect.Min, vtxs_rect.Max, ImColor(255,0,255));
                            GImGui->OverlayDrawList.PopClipRect();
                        }
                    }
                }
                ImGui::TreePop();
            }

            static void NodeWindows(ImVector<ImGuiWindow*>& windows, const char* label)
            {
                if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size))
                    return;
                for (int i = 0; i < windows.Size; i++)
                    Funcs::NodeWindow(windows[i], "Window");
                ImGui::TreePop();
            }

            static void NodeWindow(ImGuiWindow* window, const char* label)
            {
                if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window))
                    return;
                NodeDrawList(window->DrawList, "DrawList");
                if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
                if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows");
                ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair));
                ImGui::TreePop();
            }
        };

        ImGuiState& g = *GImGui;                // Access private state
        g.DisableHideTextAfterDoubleHash++;     // Not exposed (yet). Disable processing that hides text after '##' markers.
        Funcs::NodeWindows(g.Windows, "Windows");
        if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.RenderDrawLists[0].Size))
        {
            for (int i = 0; i < g.RenderDrawLists[0].Size; i++)
                Funcs::NodeDrawList(g.RenderDrawLists[0][i], "DrawList");
            ImGui::TreePop();
        }
        if (ImGui::TreeNode("Popups", "Opened Popups Stack (%d)", g.OpenedPopupStack.Size))
        {
            for (int i = 0; i < g.OpenedPopupStack.Size; i++)
            {
                ImGuiWindow* window = g.OpenedPopupStack[i].Window;
                ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenedPopupStack[i].PopupID, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : "");
            }
            ImGui::TreePop();
        }
        if (ImGui::TreeNode("Basic state"))
        {
            ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL");
            ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
            ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
            ImGui::Text("HoveredID: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not
            ImGui::Text("ActiveID: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame);
            ImGui::TreePop();
        }
        g.DisableHideTextAfterDoubleHash--;
    }
    ImGui::End();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rsi
leaq 0x31e08(%rip), %rdi     # 0x5c502
xorl %edx, %edx
callq 0xe7e0
testb $0x1, %al
jne 0x2a70a
jmp 0x2aaf0
callq 0xca20
movq %rax, %rsi
leaq 0x31df7(%rip), %rdi     # 0x5c510
movb $0x0, %al
callq 0x1a220
callq 0xca90
movss 0x30a07(%rip), %xmm0    # 0x5b134
divss 0x328(%rax), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, -0x30(%rbp)
callq 0xca90
movsd -0x30(%rbp), %xmm0
movss 0x328(%rax), %xmm1
cvtss2sd %xmm1, %xmm1
leaq 0x31dbe(%rip), %rdi     # 0x5c519
movb $0x2, %al
callq 0x1a220
callq 0xca90
movl 0x330(%rax), %eax
movl %eax, -0x28(%rbp)
callq 0xca90
movl 0x334(%rax), %eax
movl %eax, -0x24(%rbp)
callq 0xca90
movl -0x28(%rbp), %esi
movl 0x334(%rax), %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl -0x24(%rbp), %edx
movl %eax, %ecx
leaq 0x31da6(%rip), %rdi     # 0x5c546
movb $0x0, %al
callq 0x1a220
callq 0xca90
movl 0x32c(%rax), %esi
leaq 0x31db4(%rip), %rdi     # 0x5c56d
movb $0x0, %al
callq 0x1a220
leaq 0x31db5(%rip), %rdi     # 0x5c57c
leaq 0x4ecfa(%rip), %rsi     # 0x794c8
callq 0x23a60
callq 0x29c00
movq 0x4ece1(%rip), %rax     # 0x794c0
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl 0x17c4(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x17c4(%rax)
movq -0x10(%rbp), %rdi
addq $0x1738, %rdi           # imm = 0x1738
leaq 0x324f1(%rip), %rsi     # 0x5ccf9
callq 0x2ab00
movq -0x10(%rbp), %rax
movl 0x1870(%rax), %edx
leaq 0x31d91(%rip), %rdi     # 0x5c5af
leaq 0x31d93(%rip), %rsi     # 0x5c5b8
movb $0x0, %al
callq 0x1c920
testb $0x1, %al
jne 0x2a832
jmp 0x2a87a
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x1870(%rcx), %eax
jge 0x2a875
movq -0x10(%rbp), %rdi
addq $0x1870, %rdi           # imm = 0x1870
movl -0x14(%rbp), %esi
callq 0x2e9c0
movq (%rax), %rdi
leaq 0x31d4a(%rip), %rsi     # 0x5c5af
callq 0x2ab80
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x2a839
callq 0x2a440
movq -0x10(%rbp), %rax
movl 0x17f8(%rax), %edx
leaq 0x31d43(%rip), %rdi     # 0x5c5ce
leaq 0x31d43(%rip), %rsi     # 0x5c5d5
movb $0x0, %al
callq 0x1c920
testb $0x1, %al
jne 0x2a8a2
jmp 0x2a9bc
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x17f8(%rcx), %eax
jge 0x2a9b7
movq -0x10(%rbp), %rdi
addq $0x17f8, %rdi           # imm = 0x17F8
movl -0x18(%rbp), %esi
callq 0x2eca0
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rdi
addq $0x17f8, %rdi           # imm = 0x17F8
movl -0x18(%rbp), %esi
callq 0x2eca0
movl (%rax), %eax
movl %eax, -0x34(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x2a903
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x40(%rbp)
jmp 0x2a910
leaq 0x31d04(%rip), %rax     # 0x5c60e
movq %rax, -0x40(%rbp)
jmp 0x2a910
movq -0x40(%rbp), %rax
movq %rax, -0x50(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x20(%rbp)
movb %al, -0x41(%rbp)
je 0x2a939
movq -0x20(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x100000, %eax         # imm = 0x100000
cmpl $0x0, %eax
setne %al
movb %al, -0x41(%rbp)
movb -0x41(%rbp), %dl
leaq 0x3490b(%rip), %rax     # 0x5f24e
leaq 0x31cc9(%rip), %rcx     # 0x5c613
testb $0x1, %dl
cmovneq %rcx, %rax
movq %rax, -0x60(%rbp)
xorl %eax, %eax
cmpq $0x0, -0x20(%rbp)
movb %al, -0x51(%rbp)
je 0x2a976
movq -0x20(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x8000000, %eax        # imm = 0x8000000
cmpl $0x0, %eax
setne %al
movb %al, -0x51(%rbp)
movq -0x60(%rbp), %rcx
movq -0x50(%rbp), %rdx
movl -0x34(%rbp), %esi
movb -0x51(%rbp), %dil
leaq 0x348c2(%rip), %r8      # 0x5f24e
leaq 0x31c8d(%rip), %rax     # 0x5c620
testb $0x1, %dil
cmovneq %rax, %r8
leaq 0x31c4c(%rip), %rdi     # 0x5c5ee
movb $0x0, %al
callq 0x1c760
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x2a8a9
callq 0x2a440
leaq 0x31c68(%rip), %rdi     # 0x5c62b
callq 0x1cba0
testb $0x1, %al
jne 0x2a9d1
jmp 0x2aadd
movq -0x10(%rbp), %rax
cmpq $0x0, 0x1770(%rax)
je 0x2a9f3
movq -0x10(%rbp), %rax
movq 0x1770(%rax), %rax
movq (%rax), %rax
movq %rax, -0x68(%rbp)
jmp 0x2aa00
leaq 0x31c14(%rip), %rax     # 0x5c60e
movq %rax, -0x68(%rbp)
jmp 0x2aa00
movq -0x68(%rbp), %rsi
leaq 0x31c2c(%rip), %rdi     # 0x5c637
movb $0x0, %al
callq 0x1a220
movq -0x10(%rbp), %rax
cmpq $0x0, 0x1778(%rax)
je 0x2aa34
movq -0x10(%rbp), %rax
movq 0x1778(%rax), %rax
movq (%rax), %rax
movq %rax, -0x70(%rbp)
jmp 0x2aa41
leaq 0x31bd3(%rip), %rax     # 0x5c60e
movq %rax, -0x70(%rbp)
jmp 0x2aa41
movq -0x70(%rbp), %rsi
leaq 0x31bff(%rip), %rdi     # 0x5c64b
movb $0x0, %al
callq 0x1a220
movq -0x10(%rbp), %rax
cmpq $0x0, 0x1780(%rax)
je 0x2aa75
movq -0x10(%rbp), %rax
movq 0x1780(%rax), %rax
movq (%rax), %rax
movq %rax, -0x78(%rbp)
jmp 0x2aa82
leaq 0x31b92(%rip), %rax     # 0x5c60e
movq %rax, -0x78(%rbp)
jmp 0x2aa82
movq -0x78(%rbp), %rsi
leaq 0x31bd2(%rip), %rdi     # 0x5c65f
movb $0x0, %al
callq 0x1a220
movq -0x10(%rbp), %rax
movl 0x1788(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x178c(%rax), %edx
leaq 0x31bc8(%rip), %rdi     # 0x5c677
movb $0x0, %al
callq 0x1a220
movq -0x10(%rbp), %rax
movl 0x1790(%rax), %esi
movq -0x10(%rbp), %rax
movl 0x1794(%rax), %edx
leaq 0x31bbf(%rip), %rdi     # 0x5c690
movb $0x0, %al
callq 0x1a220
callq 0x2a440
movq -0x10(%rbp), %rax
movl 0x17c4(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x17c4(%rax)
callq 0xee30
addq $0x80, %rsp
popq %rbp
retq
nop