#pragma once #include <GLFW/glfw3.h> #include <GL/gl.h> #include "imgui/imgui.h" #include "imgui/imgui_impl_glfw.h" #include "imgui/imgui_impl_opengl3.h" #include "Font.hpp" class Overlay { private: GLFWwindow* overlayWindow = nullptr; const GLFWvidmode* vidMode = nullptr; int screenPosX; int screenPosY; int screenWidth; int screenHeight; void GrabScreenSize() { GLFWmonitor* primaryMonitor = glfwGetPrimaryMonitor(); vidMode = glfwGetVideoMode(primaryMonitor); glfwGetMonitorPos(primaryMonitor, &screenPosX, &screenPosY); screenWidth = vidMode->width; screenHeight = vidMode->height; } static void glfwErrorCallback(int error, const char* description) { fprintf(stderr, "GLFW error %d: %s\n", error, description); } static ImWchar* GetFontGlyphRanges() noexcept { static ImVector<ImWchar> ranges; if (ranges.empty()) { ImFontGlyphRangesBuilder builder; constexpr ImWchar baseRanges[] = { 0x0100, 0x024F, // Latin Extended-A + Latin Extended-B 0x0300, 0x03FF, // Combining Diacritical Marks + Greek/Coptic 0x0600, 0x06FF, // Arabic 0x0E00, 0x0E7F, // Thai 0 }; builder.AddRanges(baseRanges); builder.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesCyrillic()); builder.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesDefault()); builder.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesJapanese()); builder.AddRanges(ImGui::GetIO().Fonts->GetGlyphRangesChineseSimplifiedCommon()); // ★龍王™ builder.AddChar(u'\u2605'); // ★ builder.AddChar(u'\u9F8D'); // 龍 builder.AddChar(u'\u738B'); // 王 builder.AddChar(u'\u2122'); // ™ builder.BuildRanges(&ranges); } return ranges.Data; } public: bool InitializeOverlay(const char* overlayTitle) { glfwSetErrorCallback(glfwErrorCallback); if (!glfwInit()) { return false; } GrabScreenSize(); glfwDefaultWindowHints(); glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); glfwWindowHint(GLFW_FLOATING, GLFW_TRUE); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE); glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE); glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE); glfwWindowHint(GLFW_REFRESH_RATE, GLFW_DONT_CARE); overlayWindow = glfwCreateWindow(screenWidth, screenHeight, overlayTitle, nullptr, nullptr); CaptureInput(true); glfwMakeContextCurrent(overlayWindow); glfwSetWindowPos(overlayWindow, screenPosX, screenPosY); InitializeUI(); glfwShowWindow(overlayWindow); glfwSwapInterval(0); return true; } ImFont* IconFont = nullptr; void InitializeUI() { IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImFontConfig cfg; cfg.OversampleH = cfg.OversampleV = 1; cfg.PixelSnapH = false; cfg.SizePixels = 19.0f; cfg.GlyphOffset = { 0.0f, 0.0f }; ImGuiIO& io = ImGui::GetIO(); (void)io; io.Fonts->AddFontFromMemoryCompressedTTF(_compressedFontData, _compressedFontSize, cfg.SizePixels, &cfg, GetFontGlyphRanges()); ImGui_ImplGlfw_InitForOpenGL(overlayWindow, true); ImGui_ImplOpenGL3_Init("#version 330 core"); } // ocornut/imgui/issues/707#issuecomment-917151020 const void SetStyle() { ImGuiStyle& style = ImGui::GetStyle(); style.WindowPadding = ImVec2(8.00f, 8.00f); style.FramePadding = ImVec2(5.00f, 2.00f); style.CellPadding = ImVec2(6.00f, 6.00f); style.ItemSpacing = ImVec2(6.00f, 6.00f); style.ItemInnerSpacing = ImVec2(6.00f, 6.00f); style.TouchExtraPadding = ImVec2(0.00f, 0.00f); style.IndentSpacing = 25; style.ScrollbarSize = 15; style.GrabMinSize = 10; style.WindowBorderSize = 1; style.ChildBorderSize = 1; style.PopupBorderSize = 1; style.FrameBorderSize = 1; style.TabBorderSize = 1; style.WindowRounding = 7; style.ChildRounding = 4; style.FrameRounding = 3; style.PopupRounding = 4; style.ScrollbarRounding = 9; style.GrabRounding = 3; style.LogSliderDeadzone = 4; style.TabRounding = 4; style.Colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); style.Colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.10f, 0.10f, 1.00f); style.Colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); style.Colors[ImGuiCol_PopupBg] = ImVec4(0.19f, 0.19f, 0.19f, 0.92f); style.Colors[ImGuiCol_Border] = ImVec4(0.19f, 0.19f, 0.19f, 0.29f); style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.24f); style.Colors[ImGuiCol_FrameBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f); style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 0.54f); style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); style.Colors[ImGuiCol_TitleBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f); style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f); style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f); style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.54f); style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f); style.Colors[ImGuiCol_CheckMark] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f); style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f); style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f); style.Colors[ImGuiCol_Button] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f); style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.19f, 0.19f, 0.19f, 0.54f); style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); style.Colors[ImGuiCol_Header] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.00f, 0.00f, 0.00f, 0.36f); style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.20f, 0.22f, 0.23f, 0.33f); style.Colors[ImGuiCol_Separator] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f); style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f); style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f); style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f); style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f); style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f); style.Colors[ImGuiCol_Tab] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); style.Colors[ImGuiCol_TabHovered] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); style.Colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.20f, 0.20f, 0.36f); style.Colors[ImGuiCol_TabUnfocused] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); style.Colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); //style.Colors[ImGuiCol_DockingPreview] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f); //style.Colors[ImGuiCol_DockingEmptyBg] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); style.Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); style.Colors[ImGuiCol_PlotHistogram] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); style.Colors[ImGuiCol_TableHeaderBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); style.Colors[ImGuiCol_TableBorderStrong] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); style.Colors[ImGuiCol_TableBorderLight] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f); style.Colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); style.Colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); style.Colors[ImGuiCol_DragDropTarget] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f); style.Colors[ImGuiCol_NavHighlight] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); style.Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 0.00f, 0.00f, 0.70f); style.Colors[ImGuiCol_NavWindowingDimBg] = ImVec4(1.00f, 0.00f, 0.00f, 0.20f); style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(1.00f, 0.00f, 0.00f, 0.35f); } void DestroyOverlay() { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); if (overlayWindow != nullptr) { glfwDestroyWindow(overlayWindow); } glfwTerminate(); } void CaptureInput(bool capture) { glfwSetWindowAttrib(overlayWindow, GLFW_MOUSE_PASSTHROUGH, capture ? GLFW_FALSE : GLFW_TRUE); } void FocusOverlay() { glfwFocusWindow(overlayWindow); } void Render(void (*RenderUI)()) { glfwPollEvents(); glViewport(0, 0, screenWidth, screenHeight); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, screenWidth, screenHeight, 0, -1, 1); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); if (RenderUI != nullptr) RenderUI(); // Render ImGui and swap buffers ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(overlayWindow); } void GetScreenResolution(int& width, int& height) const { width = screenWidth; height = screenHeight; } };