#include "imgui_helper.h" #include "ComKit.h" #include "imgui.h" #include "spdlog/spdlog.h" #include #include #ifdef _WIN32 bool ImGuiHelper::CreateDeviceD3d(HWND hWnd) { DXGI_SWAP_CHAIN_DESC sd = {0}; sd.BufferCount = 2; sd.BufferDesc.Width = 0; sd.BufferDesc.Height = 0; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = true; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; UINT createDeviceFlags = 0; D3D_FEATURE_LEVEL featureLevel; const D3D_FEATURE_LEVEL featureLevelArray[2] = {D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0}; HRESULT res = D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); if (res == DXGI_ERROR_UNSUPPORTED) { res = D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext); } if (res != S_OK) return false; CreateRenderTarget(); return true; } void ImGuiHelper::CleanupDeviceD3d() { CleanupRenderTarget(); if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; } if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pSwapChain = nullptr; } if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; } } void ImGuiHelper::CleanupRenderTarget() { if (g_pMainRenderTargetView) { g_pMainRenderTargetView->Release(); g_pMainRenderTargetView = nullptr; } } void ImGuiHelper::CreateRenderTarget() { ID3D11Texture2D *pBackBuffer; g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pMainRenderTargetView); pBackBuffer->Release(); } LRESULT ImGuiHelper::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) { return true; } switch (msg) { case WM_SYSCOMMAND: if ((wParam & 0xfff0) == SC_KEYMENU) { return 0; } break; case WM_DESTROY: ::PostQuitMessage(0); return 0; case WM_DEVICECHANGE: PDEV_BROADCAST_HDR pHdr = reinterpret_cast(lParam); switch (wParam) { case DBT_DEVICEARRIVAL: case DBT_DEVICEREMOVECOMPLETE: break; } } return ::DefWindowProc(hWnd, msg, wParam, lParam); } ImGuiHelper::ImGuiHelper(int width, int height, const char *windowTitle) { this->windowTitle = *windowTitle; wc = {sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, "Windows", nullptr}; ::RegisterClassEx(&wc); hWnd = ::CreateWindow(wc.lpszClassName, windowTitle, WS_OVERLAPPEDWINDOW, 100, 100, width, height, nullptr, nullptr, wc.hInstance, nullptr); if (!CreateDeviceD3d(hWnd)) { CleanupDeviceD3d(); ::UnregisterClass(wc.lpszClassName, wc.hInstance); return; } IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO &io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.ConfigViewportsNoAutoMerge = true; io.ConfigViewportsNoTaskBarIcon = false; ImGui::StyleColorsLight(); ImGui_ImplWin32_Init(hWnd); ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); } void ImGuiHelper::Render(const std::function &context, bool &isRunning) { ImGuiIO &io = ImGui::GetIO(); ::ShowWindow(hWnd, SW_HIDE); UpdateWindow(hWnd); MSG msg; while (isRunning) { while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_QUIT) { isRunning = false; } } ImGui_ImplDX11_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); context(); ImGui::Render(); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); } const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w}; g_pd3dDeviceContext->OMSetRenderTargets(1, &g_pMainRenderTargetView, nullptr); g_pd3dDeviceContext->ClearRenderTargetView(g_pMainRenderTargetView, clear_color_with_alpha); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); g_pSwapChain->Present(1, 0); } } ImGuiHelper::~ImGuiHelper() { ImGui_ImplDX11_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); ::DestroyWindow(hWnd); ::UnregisterClass(wc.lpszClassName, wc.hInstance); } #elif __linux__ #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include static void glfw_error_callback(int error, const char *description) { fprintf(stderr, "GLFW ERROR %d: %s\n", error, description); } const char *ImGuiHelper::glsl_version = "#version 150"; ImGuiHelper::ImGuiHelper(int width, int height, const std::string &windowTitle) : width(width), height(height), windowTitle(windowTitle) { glfwSetErrorCallback(glfw_error_callback); glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); window = glfwCreateWindow(width, height, windowTitle.c_str(), nullptr, nullptr); glfwMakeContextCurrent(window); glfwSwapInterval(1); IMGUI_CHECKVERSION(); ImGui::CreateContext(); io = &ImGui::GetIO(); (void)io; io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; io->ConfigViewportsNoAutoMerge = true; ImGuiStyle &style = ImGui::GetStyle(); if (io->ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { style.WindowRounding = .0f; style.Colors[ImGuiCol_WindowBg].w = 1.f; } ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init(ImGuiHelper::glsl_version); } void ImGuiHelper::Render(const std::function &context, bool &isRunning) { ImVec4 clear_color = ImVec4{.45f, .55f, .60f, 1.f}; while (isRunning) { glfwPollEvents(); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); context(); // Rending ImGui::Render(); int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); if (io->ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { GLFWwindow *backup_current_context = glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); glfwMakeContextCurrent(backup_current_context); } glfwSwapBuffers(window); } ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); } ImGuiHelper::~ImGuiHelper() { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(window); glfwTerminate(); } #endif