serialWatch/third/imgui/imgui_helper.cpp
2024-11-07 13:44:49 +08:00

290 lines
10 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:
if (pHdr->dbch_devicetype == DBT_DEVTYP_PORT) {
PDEV_BROADCAST_PORT pPort =
reinterpret_cast<PDEV_BROADCAST_PORT>(pHdr);
spdlog::log(spdlog::level::debug,
std::format("port: [{}] add", pPort->dbcp_name));
ComKit::FlushLog();
ComKit::GetAllComPortNames();
ComKit::Work();
} else {
spdlog::log(spdlog::level::debug,
std::format("port: other device [{}] add",
pHdr->dbch_devicetype));
}
break;
case DBT_DEVICEREMOVECOMPLETE:
if (pHdr->dbch_devicetype == DBT_DEVTYP_PORT) {
PDEV_BROADCAST_PORT pPort =
reinterpret_cast<PDEV_BROADCAST_PORT>(pHdr);
spdlog::log(
spdlog::level::debug,
std::format("port: [{}] removed", pPort->dbcp_name));
ComKit::FlushLog();
ComKit::GetAllComPortNames();
} else {
spdlog::log(spdlog::level::debug,
std::format("port: other device [{}] add",
pHdr->dbch_devicetype));
}
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