263 lines
8.7 KiB
C++
263 lines
8.7 KiB
C++
#include "imgui_helper.h"
|
|
#include "ComKit.h"
|
|
#include "imgui.h"
|
|
#include "spdlog/spdlog.h"
|
|
#include <dbt.h>
|
|
#include <format>
|
|
#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<PDEV_BROADCAST_HDR>(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<void()> &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 <GLFW/glfw3.h>
|
|
|
|
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<void()> &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
|