├── .gitignore ├── LICENSE ├── README.md ├── repo └── screenshot.png └── src ├── Dependencies ├── include │ ├── ImGui │ │ ├── imconfig.h │ │ ├── imgui.h │ │ ├── imgui_impl_opengl3.cpp │ │ ├── imgui_impl_opengl3.h │ │ ├── imgui_impl_opengl3_loader.h │ │ ├── imgui_impl_win32.cpp │ │ ├── imgui_impl_win32.h │ │ ├── imgui_internal.h │ │ ├── imgui_stdlib.h │ │ ├── imstb_rectpack.h │ │ ├── imstb_textedit.h │ │ └── imstb_truetype.h │ └── MinHook.h └── lib │ ├── imgui.lib │ └── libMinHook-x64.lib ├── GUI.cpp ├── GUI.h ├── Hook.cpp ├── Hook.h ├── OpenGL-Hk.sln ├── OpenGL-Hk.vcxproj ├── OpenGL-Hk.vcxproj.filters └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | x64/ 2 | build/ 3 | .vs/ 4 | 5 | OpenGL-Hk.vcxproj.user -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 aXXo-dev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenGL-Hk 2 | 3 | ## What is this? 4 | 5 | A proof of concept (POC) OpenGL hook I made because many people came to me for question regarding a video I had released 6 | on YouTube about it. 7 | 8 | ![Screenshot](/repo/screenshot.png "Screenshot") 9 | 10 | ## How does it work? 11 | 12 | It works by hooking the `wglSwapBuffers` function from OpenGL's library exports.
13 | 14 | DISCLAMER: Trying to compile this project for 32-bit using the included libraries will not work. Though the process of hooking OpenGL remains the same. 15 | -------------------------------------------------------------------------------- /repo/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axxo1337/OpenGL-Hk/59d2efbd57360023d58b9ce663d5cf64887c236f/repo/screenshot.png -------------------------------------------------------------------------------- /src/Dependencies/include/ImGui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // DEAR IMGUI COMPILE-TIME OPTIONS 3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. 4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. 5 | //----------------------------------------------------------------------------- 6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) 7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. 8 | //----------------------------------------------------------------------------- 9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp 10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 12 | // Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using. 13 | //----------------------------------------------------------------------------- 14 | 15 | #pragma once 16 | 17 | //---- Define assertion handler. Defaults to calling assert(). 18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. 19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 21 | 22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 23 | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. 24 | // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() 25 | // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. 26 | //#define IMGUI_API __declspec( dllexport ) 27 | //#define IMGUI_API __declspec( dllimport ) 28 | 29 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names. 30 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 31 | //#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS. 32 | 33 | //---- Disable all of Dear ImGui or don't implement standard windows/tools. 34 | // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp. 35 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. 36 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. 37 | //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty. 38 | 39 | //---- Don't implement some functions to reduce linkage requirements. 40 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) 41 | //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) 42 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) 43 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME). 44 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). 45 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) 46 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. 47 | //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) 48 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. 49 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). 50 | //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available 51 | 52 | //---- Include imgui_user.h at the end of imgui.h as a convenience 53 | //#define IMGUI_INCLUDE_IMGUI_USER_H 54 | 55 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 56 | //#define IMGUI_USE_BGRA_PACKED_COLOR 57 | 58 | //---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) 59 | //#define IMGUI_USE_WCHAR32 60 | 61 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 62 | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. 63 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 64 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 65 | //#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined. 66 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 67 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 68 | //#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined. 69 | 70 | //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) 71 | // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h. 72 | //#define IMGUI_USE_STB_SPRINTF 73 | 74 | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) 75 | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). 76 | // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. 77 | //#define IMGUI_ENABLE_FREETYPE 78 | 79 | //---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT) 80 | // Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided). 81 | // Only works in combination with IMGUI_ENABLE_FREETYPE. 82 | // (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement) 83 | //#define IMGUI_ENABLE_FREETYPE_LUNASVG 84 | 85 | //---- Use stb_truetype to build and rasterize the font atlas (default) 86 | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. 87 | //#define IMGUI_ENABLE_STB_TRUETYPE 88 | 89 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 90 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 91 | /* 92 | #define IM_VEC2_CLASS_EXTRA \ 93 | constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \ 94 | operator MyVec2() const { return MyVec2(x,y); } 95 | 96 | #define IM_VEC4_CLASS_EXTRA \ 97 | constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \ 98 | operator MyVec4() const { return MyVec4(x,y,z,w); } 99 | */ 100 | //---- ...Or use Dear ImGui's own very basic math operators. 101 | //#define IMGUI_DEFINE_MATH_OPERATORS 102 | 103 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. 104 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). 105 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. 106 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 107 | //#define ImDrawIdx unsigned int 108 | 109 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) 110 | //struct ImDrawList; 111 | //struct ImDrawCmd; 112 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 113 | //#define ImDrawCallback MyImDrawCallback 114 | 115 | //---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase) 116 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) 117 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 118 | //#define IM_DEBUG_BREAK __debugbreak() 119 | 120 | //---- Debug Tools: Enable slower asserts 121 | //#define IMGUI_DEBUG_PARANOID 122 | 123 | //---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files) 124 | /* 125 | namespace ImGui 126 | { 127 | void MyFunction(const char* name, MyMatrix44* mtx); 128 | } 129 | */ 130 | -------------------------------------------------------------------------------- /src/Dependencies/include/ImGui/imgui_impl_opengl3.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline 2 | // - Desktop GL: 2.x 3.x 4.x 3 | // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) 4 | // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) 5 | 6 | // Implemented features: 7 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! 8 | // [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). 9 | 10 | // About WebGL/ES: 11 | // - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES. 12 | // - This is done automatically on iOS, Android and Emscripten targets. 13 | // - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h. 14 | 15 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 16 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 17 | // Learn about Dear ImGui: 18 | // - FAQ https://dearimgui.com/faq 19 | // - Getting Started https://dearimgui.com/getting-started 20 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 21 | // - Introduction, links and more at the top of imgui.cpp 22 | 23 | // CHANGELOG 24 | // (minor and older changes stripped away, please see git history for details) 25 | // 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink. 26 | // 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accommodating for NetBSD systems having only "libGL.so.3" available. (#6983) 27 | // 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445) 28 | // 2023-06-20: OpenGL: Fixed erroneous use glGetIntegerv(GL_CONTEXT_PROFILE_MASK) on contexts lower than 3.2. (#6539, #6333) 29 | // 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375) 30 | // 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333) 31 | // 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224) 32 | // 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns NULL. (#6154, #4445, #3530) 33 | // 2023-03-06: OpenGL: Fixed restoration of a potentially deleted OpenGL program, by calling glIsProgram(). (#6220, #6224) 34 | // 2022-11-09: OpenGL: Reverted use of glBufferSubData(), too many corruptions issues + old issues seemingly can't be reproed with Intel drivers nowadays (revert 2021-12-15 and 2022-05-23 changes). 35 | // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. 36 | // 2022-09-27: OpenGL: Added ability to '#define IMGUI_IMPL_OPENGL_DEBUG'. 37 | // 2022-05-23: OpenGL: Reworking 2021-12-15 "Using buffer orphaning" so it only happens on Intel GPU, seems to cause problems otherwise. (#4468, #4825, #4832, #5127). 38 | // 2022-05-13: OpenGL: Fixed state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states. 39 | // 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers. 40 | // 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions. 41 | // 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader. 42 | // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). 43 | // 2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state. 44 | // 2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader. 45 | // 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version. 46 | // 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) 47 | // 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater. 48 | // 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer. 49 | // 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state. 50 | // 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state. 51 | // 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) 52 | // 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader. 53 | // 2020-07-10: OpenGL: Added support for glad2 OpenGL loader. 54 | // 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX. 55 | // 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix. 56 | // 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset. 57 | // 2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader. 58 | // 2020-01-07: OpenGL: Added support for glbinding 3.x OpenGL loader. 59 | // 2019-10-25: OpenGL: Using a combination of GL define and runtime GL version to decide whether to use glDrawElementsBaseVertex(). Fix building with pre-3.2 GL loaders. 60 | // 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility. 61 | // 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call. 62 | // 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 63 | // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 64 | // 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop. 65 | // 2019-03-15: OpenGL: Added a GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early. 66 | // 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0). 67 | // 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader. 68 | // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. 69 | // 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450). 70 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 71 | // 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN. 72 | // 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used. 73 | // 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES". 74 | // 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation. 75 | // 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link. 76 | // 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples. 77 | // 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 78 | // 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state. 79 | // 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a nullptr pointer. 80 | // 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150". 81 | // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. 82 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. 83 | // 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. 84 | // 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode. 85 | // 2017-05-01: OpenGL: Fixed save and restore of current blend func state. 86 | // 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE. 87 | // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. 88 | // 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) 89 | 90 | //---------------------------------------- 91 | // OpenGL GLSL GLSL 92 | // version version string 93 | //---------------------------------------- 94 | // 2.0 110 "#version 110" 95 | // 2.1 120 "#version 120" 96 | // 3.0 130 "#version 130" 97 | // 3.1 140 "#version 140" 98 | // 3.2 150 "#version 150" 99 | // 3.3 330 "#version 330 core" 100 | // 4.0 400 "#version 400 core" 101 | // 4.1 410 "#version 410 core" 102 | // 4.2 420 "#version 410 core" 103 | // 4.3 430 "#version 430 core" 104 | // ES 2.0 100 "#version 100" = WebGL 1.0 105 | // ES 3.0 300 "#version 300 es" = WebGL 2.0 106 | //---------------------------------------- 107 | 108 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) 109 | #define _CRT_SECURE_NO_WARNINGS 110 | #endif 111 | 112 | #include "imgui.h" 113 | #ifndef IMGUI_DISABLE 114 | #include "imgui_impl_opengl3.h" 115 | #include 116 | #include // intptr_t 117 | #if defined(__APPLE__) 118 | #include 119 | #endif 120 | 121 | // Clang/GCC warnings with -Weverything 122 | #if defined(__clang__) 123 | #pragma clang diagnostic push 124 | #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast 125 | #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness 126 | #pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used 127 | #pragma clang diagnostic ignored "-Wnonportable-system-include-path" 128 | #pragma clang diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader) 129 | #endif 130 | #if defined(__GNUC__) 131 | #pragma GCC diagnostic push 132 | #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind 133 | #pragma GCC diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' 134 | #pragma GCC diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader) 135 | #endif 136 | 137 | // GL includes 138 | #if defined(IMGUI_IMPL_OPENGL_ES2) 139 | #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) 140 | #include // Use GL ES 2 141 | #else 142 | #include // Use GL ES 2 143 | #endif 144 | #if defined(__EMSCRIPTEN__) 145 | #ifndef GL_GLEXT_PROTOTYPES 146 | #define GL_GLEXT_PROTOTYPES 147 | #endif 148 | #include 149 | #endif 150 | #elif defined(IMGUI_IMPL_OPENGL_ES3) 151 | #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) 152 | #include // Use GL ES 3 153 | #else 154 | #include // Use GL ES 3 155 | #endif 156 | #elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) 157 | // Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. 158 | // Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w. 159 | // In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.). 160 | // If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp): 161 | // - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped 162 | // - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases 163 | // Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version. 164 | #define IMGL3W_IMPL 165 | #include "imgui_impl_opengl3_loader.h" 166 | #endif 167 | 168 | // Vertex arrays are not supported on ES2/WebGL1 unless Emscripten which uses an extension 169 | #ifndef IMGUI_IMPL_OPENGL_ES2 170 | #define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 171 | #elif defined(__EMSCRIPTEN__) 172 | #define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 173 | #define glBindVertexArray glBindVertexArrayOES 174 | #define glGenVertexArrays glGenVertexArraysOES 175 | #define glDeleteVertexArrays glDeleteVertexArraysOES 176 | #define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES 177 | #endif 178 | 179 | // Desktop GL 2.0+ has extension and glPolygonMode() which GL ES and WebGL don't have.. 180 | #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) 181 | #define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS // has glGetIntegerv(GL_NUM_EXTENSIONS) 182 | #define IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE // has glPolygonMode() 183 | #endif 184 | 185 | // Desktop GL 2.1+ and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target. 186 | #if !defined(IMGUI_IMPL_OPENGL_ES2) 187 | #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK 188 | #endif 189 | 190 | // Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state 191 | #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1) 192 | #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART 193 | #endif 194 | 195 | // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. 196 | #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2) 197 | #define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 198 | #endif 199 | 200 | // Desktop GL 3.3+ and GL ES 3.0+ have glBindSampler() 201 | #if !defined(IMGUI_IMPL_OPENGL_ES2) && (defined(IMGUI_IMPL_OPENGL_ES3) || defined(GL_VERSION_3_3)) 202 | #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER 203 | #endif 204 | 205 | // [Debugging] 206 | //#define IMGUI_IMPL_OPENGL_DEBUG 207 | #ifdef IMGUI_IMPL_OPENGL_DEBUG 208 | #include 209 | #define GL_CALL(_CALL) do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0) // Call with error check 210 | #else 211 | #define GL_CALL(_CALL) _CALL // Call without error check 212 | #endif 213 | 214 | // OpenGL Data 215 | struct ImGui_ImplOpenGL3_Data 216 | { 217 | GLuint GlVersion; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2) 218 | char GlslVersionString[32]; // Specified by user or detected based on compile time GL settings. 219 | bool GlProfileIsES2; 220 | bool GlProfileIsES3; 221 | bool GlProfileIsCompat; 222 | GLint GlProfileMask; 223 | GLuint FontTexture; 224 | GLuint ShaderHandle; 225 | GLint AttribLocationTex; // Uniforms location 226 | GLint AttribLocationProjMtx; 227 | GLuint AttribLocationVtxPos; // Vertex attributes location 228 | GLuint AttribLocationVtxUV; 229 | GLuint AttribLocationVtxColor; 230 | unsigned int VboHandle, ElementsHandle; 231 | GLsizeiptr VertexBufferSize; 232 | GLsizeiptr IndexBufferSize; 233 | bool HasClipOrigin; 234 | bool UseBufferSubData; 235 | 236 | ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); } 237 | }; 238 | 239 | // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts 240 | // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. 241 | static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData() 242 | { 243 | return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; 244 | } 245 | 246 | // OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only) 247 | #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 248 | struct ImGui_ImplOpenGL3_VtxAttribState 249 | { 250 | GLint Enabled, Size, Type, Normalized, Stride; 251 | GLvoid* Ptr; 252 | 253 | void GetState(GLint index) 254 | { 255 | glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &Enabled); 256 | glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &Size); 257 | glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &Type); 258 | glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &Normalized); 259 | glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &Stride); 260 | glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &Ptr); 261 | } 262 | void SetState(GLint index) 263 | { 264 | glVertexAttribPointer(index, Size, Type, (GLboolean)Normalized, Stride, Ptr); 265 | if (Enabled) glEnableVertexAttribArray(index); else glDisableVertexAttribArray(index); 266 | } 267 | }; 268 | #endif 269 | 270 | // Functions 271 | bool ImGui_ImplOpenGL3_Init(const char* glsl_version) 272 | { 273 | ImGuiIO& io = ImGui::GetIO(); 274 | IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); 275 | 276 | // Initialize our loader 277 | #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) 278 | if (imgl3wInit() != 0) 279 | { 280 | fprintf(stderr, "Failed to initialize OpenGL loader!\n"); 281 | return false; 282 | } 283 | #endif 284 | 285 | // Setup backend capabilities flags 286 | ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)(); 287 | io.BackendRendererUserData = (void*)bd; 288 | io.BackendRendererName = "imgui_impl_opengl3"; 289 | 290 | // Query for GL version (e.g. 320 for GL 3.2) 291 | #if defined(IMGUI_IMPL_OPENGL_ES2) 292 | // GLES 2 293 | bd->GlVersion = 200; 294 | bd->GlProfileIsES2 = true; 295 | #else 296 | // Desktop or GLES 3 297 | GLint major = 0; 298 | GLint minor = 0; 299 | glGetIntegerv(GL_MAJOR_VERSION, &major); 300 | glGetIntegerv(GL_MINOR_VERSION, &minor); 301 | if (major == 0 && minor == 0) 302 | { 303 | // Query GL_VERSION in desktop GL 2.x, the string will start with "." 304 | const char* gl_version = (const char*)glGetString(GL_VERSION); 305 | sscanf(gl_version, "%d.%d", &major, &minor); 306 | } 307 | bd->GlVersion = (GLuint)(major * 100 + minor * 10); 308 | #if defined(GL_CONTEXT_PROFILE_MASK) 309 | if (bd->GlVersion >= 320) 310 | glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask); 311 | bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0; 312 | #endif 313 | 314 | #if defined(IMGUI_IMPL_OPENGL_ES3) 315 | bd->GlProfileIsES3 = true; 316 | #endif 317 | 318 | bd->UseBufferSubData = false; 319 | /* 320 | // Query vendor to enable glBufferSubData kludge 321 | #ifdef _WIN32 322 | if (const char* vendor = (const char*)glGetString(GL_VENDOR)) 323 | if (strncmp(vendor, "Intel", 5) == 0) 324 | bd->UseBufferSubData = true; 325 | #endif 326 | */ 327 | #endif 328 | 329 | #ifdef IMGUI_IMPL_OPENGL_DEBUG 330 | printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG] 331 | #endif 332 | 333 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 334 | if (bd->GlVersion >= 320) 335 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 336 | #endif 337 | 338 | // Store GLSL version string so we can refer to it later in case we recreate shaders. 339 | // Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure. 340 | if (glsl_version == nullptr) 341 | { 342 | #if defined(IMGUI_IMPL_OPENGL_ES2) 343 | glsl_version = "#version 100"; 344 | #elif defined(IMGUI_IMPL_OPENGL_ES3) 345 | glsl_version = "#version 300 es"; 346 | #elif defined(__APPLE__) 347 | glsl_version = "#version 150"; 348 | #else 349 | glsl_version = "#version 130"; 350 | #endif 351 | } 352 | IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString)); 353 | strcpy(bd->GlslVersionString, glsl_version); 354 | strcat(bd->GlslVersionString, "\n"); 355 | 356 | // Make an arbitrary GL call (we don't actually need the result) 357 | // IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know! 358 | GLint current_texture; 359 | glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); 360 | 361 | // Detect extensions we support 362 | bd->HasClipOrigin = (bd->GlVersion >= 450); 363 | #ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS 364 | GLint num_extensions = 0; 365 | glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); 366 | for (GLint i = 0; i < num_extensions; i++) 367 | { 368 | const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i); 369 | if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0) 370 | bd->HasClipOrigin = true; 371 | } 372 | #endif 373 | 374 | return true; 375 | } 376 | 377 | void ImGui_ImplOpenGL3_Shutdown() 378 | { 379 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 380 | IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); 381 | ImGuiIO& io = ImGui::GetIO(); 382 | 383 | ImGui_ImplOpenGL3_DestroyDeviceObjects(); 384 | io.BackendRendererName = nullptr; 385 | io.BackendRendererUserData = nullptr; 386 | io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; 387 | IM_DELETE(bd); 388 | } 389 | 390 | void ImGui_ImplOpenGL3_NewFrame() 391 | { 392 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 393 | IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL3_Init()?"); 394 | 395 | if (!bd->ShaderHandle) 396 | ImGui_ImplOpenGL3_CreateDeviceObjects(); 397 | } 398 | 399 | static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) 400 | { 401 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 402 | 403 | // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill 404 | glEnable(GL_BLEND); 405 | glBlendEquation(GL_FUNC_ADD); 406 | glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 407 | glDisable(GL_CULL_FACE); 408 | glDisable(GL_DEPTH_TEST); 409 | glDisable(GL_STENCIL_TEST); 410 | glEnable(GL_SCISSOR_TEST); 411 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART 412 | if (bd->GlVersion >= 310) 413 | glDisable(GL_PRIMITIVE_RESTART); 414 | #endif 415 | #ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE 416 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 417 | #endif 418 | 419 | // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) 420 | #if defined(GL_CLIP_ORIGIN) 421 | bool clip_origin_lower_left = true; 422 | if (bd->HasClipOrigin) 423 | { 424 | GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); 425 | if (current_clip_origin == GL_UPPER_LEFT) 426 | clip_origin_lower_left = false; 427 | } 428 | #endif 429 | 430 | // Setup viewport, orthographic projection matrix 431 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. 432 | GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height)); 433 | float L = draw_data->DisplayPos.x; 434 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; 435 | float T = draw_data->DisplayPos.y; 436 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; 437 | #if defined(GL_CLIP_ORIGIN) 438 | if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left 439 | #endif 440 | const float ortho_projection[4][4] = 441 | { 442 | { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, 443 | { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, 444 | { 0.0f, 0.0f, -1.0f, 0.0f }, 445 | { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, 446 | }; 447 | glUseProgram(bd->ShaderHandle); 448 | glUniform1i(bd->AttribLocationTex, 0); 449 | glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); 450 | 451 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER 452 | if (bd->GlVersion >= 330 || bd->GlProfileIsES3) 453 | glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise. 454 | #endif 455 | 456 | (void)vertex_array_object; 457 | #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 458 | glBindVertexArray(vertex_array_object); 459 | #endif 460 | 461 | // Bind vertex/index buffers and setup attributes for ImDrawVert 462 | GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle)); 463 | GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle)); 464 | GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxPos)); 465 | GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxUV)); 466 | GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxColor)); 467 | GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, pos))); 468 | GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, uv))); 469 | GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col))); 470 | } 471 | 472 | // OpenGL3 Render function. 473 | // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly. 474 | // This is in order to be able to run within an OpenGL engine that doesn't do so. 475 | void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) 476 | { 477 | // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) 478 | int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); 479 | int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); 480 | if (fb_width <= 0 || fb_height <= 0) 481 | return; 482 | 483 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 484 | 485 | // Backup GL state 486 | GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); 487 | glActiveTexture(GL_TEXTURE0); 488 | GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program); 489 | GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture); 490 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER 491 | GLuint last_sampler; if (bd->GlVersion >= 330 || bd->GlProfileIsES3) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } 492 | #endif 493 | GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer); 494 | #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 495 | // This is part of VAO on OpenGL 3.0+ and OpenGL ES 3.0+. 496 | GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); 497 | ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_pos; last_vtx_attrib_state_pos.GetState(bd->AttribLocationVtxPos); 498 | ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_uv; last_vtx_attrib_state_uv.GetState(bd->AttribLocationVtxUV); 499 | ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_color; last_vtx_attrib_state_color.GetState(bd->AttribLocationVtxColor); 500 | #endif 501 | #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 502 | GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); 503 | #endif 504 | #ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE 505 | GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); 506 | #endif 507 | GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); 508 | GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); 509 | GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); 510 | GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb); 511 | GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha); 512 | GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha); 513 | GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb); 514 | GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha); 515 | GLboolean last_enable_blend = glIsEnabled(GL_BLEND); 516 | GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); 517 | GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); 518 | GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST); 519 | GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); 520 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART 521 | GLboolean last_enable_primitive_restart = (bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; 522 | #endif 523 | 524 | // Setup desired GL state 525 | // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) 526 | // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. 527 | GLuint vertex_array_object = 0; 528 | #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 529 | GL_CALL(glGenVertexArrays(1, &vertex_array_object)); 530 | #endif 531 | ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); 532 | 533 | // Will project scissor/clipping rectangles into framebuffer space 534 | ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports 535 | ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) 536 | 537 | // Render command lists 538 | for (int n = 0; n < draw_data->CmdListsCount; n++) 539 | { 540 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 541 | 542 | // Upload vertex/index buffers 543 | // - OpenGL drivers are in a very sorry state nowadays.... 544 | // During 2021 we attempted to switch from glBufferData() to orphaning+glBufferSubData() following reports 545 | // of leaks on Intel GPU when using multi-viewports on Windows. 546 | // - After this we kept hearing of various display corruptions issues. We started disabling on non-Intel GPU, but issues still got reported on Intel. 547 | // - We are now back to using exclusively glBufferData(). So bd->UseBufferSubData IS ALWAYS FALSE in this code. 548 | // We are keeping the old code path for a while in case people finding new issues may want to test the bd->UseBufferSubData path. 549 | // - See https://github.com/ocornut/imgui/issues/4468 and please report any corruption issues. 550 | const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert); 551 | const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx); 552 | if (bd->UseBufferSubData) 553 | { 554 | if (bd->VertexBufferSize < vtx_buffer_size) 555 | { 556 | bd->VertexBufferSize = vtx_buffer_size; 557 | GL_CALL(glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, nullptr, GL_STREAM_DRAW)); 558 | } 559 | if (bd->IndexBufferSize < idx_buffer_size) 560 | { 561 | bd->IndexBufferSize = idx_buffer_size; 562 | GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, nullptr, GL_STREAM_DRAW)); 563 | } 564 | GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data)); 565 | GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data)); 566 | } 567 | else 568 | { 569 | GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW)); 570 | GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW)); 571 | } 572 | 573 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 574 | { 575 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 576 | if (pcmd->UserCallback != nullptr) 577 | { 578 | // User callback, registered via ImDrawList::AddCallback() 579 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 580 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 581 | ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); 582 | else 583 | pcmd->UserCallback(cmd_list, pcmd); 584 | } 585 | else 586 | { 587 | // Project scissor/clipping rectangles into framebuffer space 588 | ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); 589 | ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); 590 | if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) 591 | continue; 592 | 593 | // Apply scissor/clipping rectangle (Y is inverted in OpenGL) 594 | GL_CALL(glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y))); 595 | 596 | // Bind texture, Draw 597 | GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); 598 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET 599 | if (bd->GlVersion >= 320) 600 | GL_CALL(glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset)); 601 | else 602 | #endif 603 | GL_CALL(glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)))); 604 | } 605 | } 606 | } 607 | 608 | // Destroy the temporary VAO 609 | #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 610 | GL_CALL(glDeleteVertexArrays(1, &vertex_array_object)); 611 | #endif 612 | 613 | // Restore modified GL state 614 | // This "glIsProgram()" check is required because if the program is "pending deletion" at the time of binding backup, it will have been deleted by now and will cause an OpenGL error. See #6220. 615 | if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program); 616 | glBindTexture(GL_TEXTURE_2D, last_texture); 617 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER 618 | if (bd->GlVersion >= 330 || bd->GlProfileIsES3) 619 | glBindSampler(0, last_sampler); 620 | #endif 621 | glActiveTexture(last_active_texture); 622 | #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 623 | glBindVertexArray(last_vertex_array_object); 624 | #endif 625 | glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); 626 | #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 627 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); 628 | last_vtx_attrib_state_pos.SetState(bd->AttribLocationVtxPos); 629 | last_vtx_attrib_state_uv.SetState(bd->AttribLocationVtxUV); 630 | last_vtx_attrib_state_color.SetState(bd->AttribLocationVtxColor); 631 | #endif 632 | glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); 633 | glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); 634 | if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); 635 | if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); 636 | if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); 637 | if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); 638 | if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); 639 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART 640 | if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } 641 | #endif 642 | 643 | #ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE 644 | // Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons 645 | if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) 646 | { 647 | glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); 648 | glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); 649 | } 650 | else 651 | { 652 | glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); 653 | } 654 | #endif // IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE 655 | 656 | glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); 657 | glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); 658 | (void)bd; // Not all compilation paths use this 659 | } 660 | 661 | bool ImGui_ImplOpenGL3_CreateFontsTexture() 662 | { 663 | ImGuiIO& io = ImGui::GetIO(); 664 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 665 | 666 | // Build texture atlas 667 | unsigned char* pixels; 668 | int width, height; 669 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. 670 | 671 | // Upload texture to graphics system 672 | // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) 673 | GLint last_texture; 674 | GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture)); 675 | GL_CALL(glGenTextures(1, &bd->FontTexture)); 676 | GL_CALL(glBindTexture(GL_TEXTURE_2D, bd->FontTexture)); 677 | GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 678 | GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 679 | #ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES 680 | GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)); 681 | #endif 682 | GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); 683 | 684 | // Store our identifier 685 | io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); 686 | 687 | // Restore state 688 | GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture)); 689 | 690 | return true; 691 | } 692 | 693 | void ImGui_ImplOpenGL3_DestroyFontsTexture() 694 | { 695 | ImGuiIO& io = ImGui::GetIO(); 696 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 697 | if (bd->FontTexture) 698 | { 699 | glDeleteTextures(1, &bd->FontTexture); 700 | io.Fonts->SetTexID(0); 701 | bd->FontTexture = 0; 702 | } 703 | } 704 | 705 | // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. 706 | static bool CheckShader(GLuint handle, const char* desc) 707 | { 708 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 709 | GLint status = 0, log_length = 0; 710 | glGetShaderiv(handle, GL_COMPILE_STATUS, &status); 711 | glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); 712 | if ((GLboolean)status == GL_FALSE) 713 | fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString); 714 | if (log_length > 1) 715 | { 716 | ImVector buf; 717 | buf.resize((int)(log_length + 1)); 718 | glGetShaderInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin()); 719 | fprintf(stderr, "%s\n", buf.begin()); 720 | } 721 | return (GLboolean)status == GL_TRUE; 722 | } 723 | 724 | // If you get an error please report on GitHub. You may try different GL context version or GLSL version. 725 | static bool CheckProgram(GLuint handle, const char* desc) 726 | { 727 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 728 | GLint status = 0, log_length = 0; 729 | glGetProgramiv(handle, GL_LINK_STATUS, &status); 730 | glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); 731 | if ((GLboolean)status == GL_FALSE) 732 | fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString); 733 | if (log_length > 1) 734 | { 735 | ImVector buf; 736 | buf.resize((int)(log_length + 1)); 737 | glGetProgramInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin()); 738 | fprintf(stderr, "%s\n", buf.begin()); 739 | } 740 | return (GLboolean)status == GL_TRUE; 741 | } 742 | 743 | bool ImGui_ImplOpenGL3_CreateDeviceObjects() 744 | { 745 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 746 | 747 | // Backup GL state 748 | GLint last_texture, last_array_buffer; 749 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); 750 | glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); 751 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK 752 | GLint last_pixel_unpack_buffer; 753 | if (bd->GlVersion >= 210) { glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &last_pixel_unpack_buffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } 754 | #endif 755 | #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 756 | GLint last_vertex_array; 757 | glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); 758 | #endif 759 | 760 | // Parse GLSL version string 761 | int glsl_version = 130; 762 | sscanf(bd->GlslVersionString, "#version %d", &glsl_version); 763 | 764 | const GLchar* vertex_shader_glsl_120 = 765 | "uniform mat4 ProjMtx;\n" 766 | "attribute vec2 Position;\n" 767 | "attribute vec2 UV;\n" 768 | "attribute vec4 Color;\n" 769 | "varying vec2 Frag_UV;\n" 770 | "varying vec4 Frag_Color;\n" 771 | "void main()\n" 772 | "{\n" 773 | " Frag_UV = UV;\n" 774 | " Frag_Color = Color;\n" 775 | " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" 776 | "}\n"; 777 | 778 | const GLchar* vertex_shader_glsl_130 = 779 | "uniform mat4 ProjMtx;\n" 780 | "in vec2 Position;\n" 781 | "in vec2 UV;\n" 782 | "in vec4 Color;\n" 783 | "out vec2 Frag_UV;\n" 784 | "out vec4 Frag_Color;\n" 785 | "void main()\n" 786 | "{\n" 787 | " Frag_UV = UV;\n" 788 | " Frag_Color = Color;\n" 789 | " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" 790 | "}\n"; 791 | 792 | const GLchar* vertex_shader_glsl_300_es = 793 | "precision highp float;\n" 794 | "layout (location = 0) in vec2 Position;\n" 795 | "layout (location = 1) in vec2 UV;\n" 796 | "layout (location = 2) in vec4 Color;\n" 797 | "uniform mat4 ProjMtx;\n" 798 | "out vec2 Frag_UV;\n" 799 | "out vec4 Frag_Color;\n" 800 | "void main()\n" 801 | "{\n" 802 | " Frag_UV = UV;\n" 803 | " Frag_Color = Color;\n" 804 | " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" 805 | "}\n"; 806 | 807 | const GLchar* vertex_shader_glsl_410_core = 808 | "layout (location = 0) in vec2 Position;\n" 809 | "layout (location = 1) in vec2 UV;\n" 810 | "layout (location = 2) in vec4 Color;\n" 811 | "uniform mat4 ProjMtx;\n" 812 | "out vec2 Frag_UV;\n" 813 | "out vec4 Frag_Color;\n" 814 | "void main()\n" 815 | "{\n" 816 | " Frag_UV = UV;\n" 817 | " Frag_Color = Color;\n" 818 | " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" 819 | "}\n"; 820 | 821 | const GLchar* fragment_shader_glsl_120 = 822 | "#ifdef GL_ES\n" 823 | " precision mediump float;\n" 824 | "#endif\n" 825 | "uniform sampler2D Texture;\n" 826 | "varying vec2 Frag_UV;\n" 827 | "varying vec4 Frag_Color;\n" 828 | "void main()\n" 829 | "{\n" 830 | " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n" 831 | "}\n"; 832 | 833 | const GLchar* fragment_shader_glsl_130 = 834 | "uniform sampler2D Texture;\n" 835 | "in vec2 Frag_UV;\n" 836 | "in vec4 Frag_Color;\n" 837 | "out vec4 Out_Color;\n" 838 | "void main()\n" 839 | "{\n" 840 | " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" 841 | "}\n"; 842 | 843 | const GLchar* fragment_shader_glsl_300_es = 844 | "precision mediump float;\n" 845 | "uniform sampler2D Texture;\n" 846 | "in vec2 Frag_UV;\n" 847 | "in vec4 Frag_Color;\n" 848 | "layout (location = 0) out vec4 Out_Color;\n" 849 | "void main()\n" 850 | "{\n" 851 | " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" 852 | "}\n"; 853 | 854 | const GLchar* fragment_shader_glsl_410_core = 855 | "in vec2 Frag_UV;\n" 856 | "in vec4 Frag_Color;\n" 857 | "uniform sampler2D Texture;\n" 858 | "layout (location = 0) out vec4 Out_Color;\n" 859 | "void main()\n" 860 | "{\n" 861 | " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" 862 | "}\n"; 863 | 864 | // Select shaders matching our GLSL versions 865 | const GLchar* vertex_shader = nullptr; 866 | const GLchar* fragment_shader = nullptr; 867 | if (glsl_version < 130) 868 | { 869 | vertex_shader = vertex_shader_glsl_120; 870 | fragment_shader = fragment_shader_glsl_120; 871 | } 872 | else if (glsl_version >= 410) 873 | { 874 | vertex_shader = vertex_shader_glsl_410_core; 875 | fragment_shader = fragment_shader_glsl_410_core; 876 | } 877 | else if (glsl_version == 300) 878 | { 879 | vertex_shader = vertex_shader_glsl_300_es; 880 | fragment_shader = fragment_shader_glsl_300_es; 881 | } 882 | else 883 | { 884 | vertex_shader = vertex_shader_glsl_130; 885 | fragment_shader = fragment_shader_glsl_130; 886 | } 887 | 888 | // Create shaders 889 | const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader }; 890 | GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER); 891 | glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr); 892 | glCompileShader(vert_handle); 893 | CheckShader(vert_handle, "vertex shader"); 894 | 895 | const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader }; 896 | GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER); 897 | glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr); 898 | glCompileShader(frag_handle); 899 | CheckShader(frag_handle, "fragment shader"); 900 | 901 | // Link 902 | bd->ShaderHandle = glCreateProgram(); 903 | glAttachShader(bd->ShaderHandle, vert_handle); 904 | glAttachShader(bd->ShaderHandle, frag_handle); 905 | glLinkProgram(bd->ShaderHandle); 906 | CheckProgram(bd->ShaderHandle, "shader program"); 907 | 908 | glDetachShader(bd->ShaderHandle, vert_handle); 909 | glDetachShader(bd->ShaderHandle, frag_handle); 910 | glDeleteShader(vert_handle); 911 | glDeleteShader(frag_handle); 912 | 913 | bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture"); 914 | bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx"); 915 | bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position"); 916 | bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV"); 917 | bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color"); 918 | 919 | // Create buffers 920 | glGenBuffers(1, &bd->VboHandle); 921 | glGenBuffers(1, &bd->ElementsHandle); 922 | 923 | ImGui_ImplOpenGL3_CreateFontsTexture(); 924 | 925 | // Restore modified GL state 926 | glBindTexture(GL_TEXTURE_2D, last_texture); 927 | glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); 928 | #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK 929 | if (bd->GlVersion >= 210) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, last_pixel_unpack_buffer); } 930 | #endif 931 | #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY 932 | glBindVertexArray(last_vertex_array); 933 | #endif 934 | 935 | return true; 936 | } 937 | 938 | void ImGui_ImplOpenGL3_DestroyDeviceObjects() 939 | { 940 | ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); 941 | if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; } 942 | if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; } 943 | if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; } 944 | ImGui_ImplOpenGL3_DestroyFontsTexture(); 945 | } 946 | 947 | //----------------------------------------------------------------------------- 948 | 949 | #if defined(__GNUC__) 950 | #pragma GCC diagnostic pop 951 | #endif 952 | #if defined(__clang__) 953 | #pragma clang diagnostic pop 954 | #endif 955 | 956 | #endif // #ifndef IMGUI_DISABLE 957 | -------------------------------------------------------------------------------- /src/Dependencies/include/ImGui/imgui_impl_opengl3.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline 2 | // - Desktop GL: 2.x 3.x 4.x 3 | // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) 4 | // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) 5 | 6 | // Implemented features: 7 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! 8 | // [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). 9 | 10 | // About WebGL/ES: 11 | // - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES. 12 | // - This is done automatically on iOS, Android and Emscripten targets. 13 | // - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h. 14 | 15 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 16 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 17 | // Learn about Dear ImGui: 18 | // - FAQ https://dearimgui.com/faq 19 | // - Getting Started https://dearimgui.com/getting-started 20 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 21 | // - Introduction, links and more at the top of imgui.cpp 22 | 23 | // About GLSL version: 24 | // The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string. 25 | // On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" 26 | // Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. 27 | 28 | #pragma once 29 | #include "imgui.h" // IMGUI_IMPL_API 30 | #ifndef IMGUI_DISABLE 31 | 32 | // Backend API 33 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr); 34 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); 35 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); 36 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); 37 | 38 | // (Optional) Called by Init/NewFrame/Shutdown 39 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); 40 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); 41 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); 42 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); 43 | 44 | // Specific OpenGL ES versions 45 | //#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten 46 | //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android 47 | 48 | // You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. 49 | #if !defined(IMGUI_IMPL_OPENGL_ES2) \ 50 | && !defined(IMGUI_IMPL_OPENGL_ES3) 51 | 52 | // Try to detect GLES on matching platforms 53 | #if defined(__APPLE__) 54 | #include 55 | #endif 56 | #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) 57 | #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" 58 | #elif defined(__EMSCRIPTEN__) || defined(__amigaos4__) 59 | #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" 60 | #else 61 | // Otherwise imgui_impl_opengl3_loader.h will be used. 62 | #endif 63 | 64 | #endif 65 | 66 | #endif // #ifndef IMGUI_DISABLE 67 | -------------------------------------------------------------------------------- /src/Dependencies/include/ImGui/imgui_impl_opengl3_loader.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // About imgui_impl_opengl3_loader.h: 3 | // 4 | // We embed our own OpenGL loader to not require user to provide their own or to have to use ours, 5 | // which proved to be endless problems for users. 6 | // Our loader is custom-generated, based on gl3w but automatically filtered to only include 7 | // enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small. 8 | // 9 | // YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY. 10 | // THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE. 11 | // 12 | // IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions): 13 | // IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCUDING 'imgui_impl_opengl3_loader.h' 14 | // IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER. 15 | // (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS) 16 | // YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT. 17 | // BUT IF YOU REALLY WANT TO, you can '#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM' and imgui_impl_opengl3.cpp 18 | // WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT. 19 | // 20 | // Regenerate with: 21 | // python gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt 22 | // 23 | // More info: 24 | // https://github.com/dearimgui/gl3w_stripped 25 | // https://github.com/ocornut/imgui/issues/4445 26 | //----------------------------------------------------------------------------- 27 | 28 | /* 29 | * This file was generated with gl3w_gen.py, part of imgl3w 30 | * (hosted at https://github.com/dearimgui/gl3w_stripped) 31 | * 32 | * This is free and unencumbered software released into the public domain. 33 | * 34 | * Anyone is free to copy, modify, publish, use, compile, sell, or 35 | * distribute this software, either in source code form or as a compiled 36 | * binary, for any purpose, commercial or non-commercial, and by any 37 | * means. 38 | * 39 | * In jurisdictions that recognize copyright laws, the author or authors 40 | * of this software dedicate any and all copyright interest in the 41 | * software to the public domain. We make this dedication for the benefit 42 | * of the public at large and to the detriment of our heirs and 43 | * successors. We intend this dedication to be an overt act of 44 | * relinquishment in perpetuity of all present and future rights to this 45 | * software under copyright law. 46 | * 47 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 50 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 51 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 52 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 53 | * OTHER DEALINGS IN THE SOFTWARE. 54 | */ 55 | 56 | #ifndef __gl3w_h_ 57 | #define __gl3w_h_ 58 | 59 | // Adapted from KHR/khrplatform.h to avoid including entire file. 60 | #ifndef __khrplatform_h_ 61 | typedef float khronos_float_t; 62 | typedef signed char khronos_int8_t; 63 | typedef unsigned char khronos_uint8_t; 64 | typedef signed short int khronos_int16_t; 65 | typedef unsigned short int khronos_uint16_t; 66 | #ifdef _WIN64 67 | typedef signed long long int khronos_intptr_t; 68 | typedef signed long long int khronos_ssize_t; 69 | #else 70 | typedef signed long int khronos_intptr_t; 71 | typedef signed long int khronos_ssize_t; 72 | #endif 73 | 74 | #if defined(_MSC_VER) && !defined(__clang__) 75 | typedef signed __int64 khronos_int64_t; 76 | typedef unsigned __int64 khronos_uint64_t; 77 | #elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100) 78 | #include 79 | typedef int64_t khronos_int64_t; 80 | typedef uint64_t khronos_uint64_t; 81 | #else 82 | typedef signed long long khronos_int64_t; 83 | typedef unsigned long long khronos_uint64_t; 84 | #endif 85 | #endif // __khrplatform_h_ 86 | 87 | #ifndef __gl_glcorearb_h_ 88 | #define __gl_glcorearb_h_ 1 89 | #ifdef __cplusplus 90 | extern "C" { 91 | #endif 92 | /* 93 | ** Copyright 2013-2020 The Khronos Group Inc. 94 | ** SPDX-License-Identifier: MIT 95 | ** 96 | ** This header is generated from the Khronos OpenGL / OpenGL ES XML 97 | ** API Registry. The current version of the Registry, generator scripts 98 | ** used to make the header, and the header can be found at 99 | ** https://github.com/KhronosGroup/OpenGL-Registry 100 | */ 101 | #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) 102 | #ifndef WIN32_LEAN_AND_MEAN 103 | #define WIN32_LEAN_AND_MEAN 1 104 | #endif 105 | #include 106 | #endif 107 | #ifndef APIENTRY 108 | #define APIENTRY 109 | #endif 110 | #ifndef APIENTRYP 111 | #define APIENTRYP APIENTRY * 112 | #endif 113 | #ifndef GLAPI 114 | #define GLAPI extern 115 | #endif 116 | /* glcorearb.h is for use with OpenGL core profile implementations. 117 | ** It should should be placed in the same directory as gl.h and 118 | ** included as . 119 | ** 120 | ** glcorearb.h includes only APIs in the latest OpenGL core profile 121 | ** implementation together with APIs in newer ARB extensions which 122 | ** can be supported by the core profile. It does not, and never will 123 | ** include functionality removed from the core profile, such as 124 | ** fixed-function vertex and fragment processing. 125 | ** 126 | ** Do not #include both and either of or 127 | ** in the same source file. 128 | */ 129 | /* Generated C header for: 130 | * API: gl 131 | * Profile: core 132 | * Versions considered: .* 133 | * Versions emitted: .* 134 | * Default extensions included: glcore 135 | * Additional extensions included: _nomatch_^ 136 | * Extensions removed: _nomatch_^ 137 | */ 138 | #ifndef GL_VERSION_1_0 139 | typedef void GLvoid; 140 | typedef unsigned int GLenum; 141 | 142 | typedef khronos_float_t GLfloat; 143 | typedef int GLint; 144 | typedef int GLsizei; 145 | typedef unsigned int GLbitfield; 146 | typedef double GLdouble; 147 | typedef unsigned int GLuint; 148 | typedef unsigned char GLboolean; 149 | typedef khronos_uint8_t GLubyte; 150 | #define GL_COLOR_BUFFER_BIT 0x00004000 151 | #define GL_FALSE 0 152 | #define GL_TRUE 1 153 | #define GL_TRIANGLES 0x0004 154 | #define GL_ONE 1 155 | #define GL_SRC_ALPHA 0x0302 156 | #define GL_ONE_MINUS_SRC_ALPHA 0x0303 157 | #define GL_FRONT 0x0404 158 | #define GL_BACK 0x0405 159 | #define GL_FRONT_AND_BACK 0x0408 160 | #define GL_POLYGON_MODE 0x0B40 161 | #define GL_CULL_FACE 0x0B44 162 | #define GL_DEPTH_TEST 0x0B71 163 | #define GL_STENCIL_TEST 0x0B90 164 | #define GL_VIEWPORT 0x0BA2 165 | #define GL_BLEND 0x0BE2 166 | #define GL_SCISSOR_BOX 0x0C10 167 | #define GL_SCISSOR_TEST 0x0C11 168 | #define GL_UNPACK_ROW_LENGTH 0x0CF2 169 | #define GL_PACK_ALIGNMENT 0x0D05 170 | #define GL_TEXTURE_2D 0x0DE1 171 | #define GL_UNSIGNED_BYTE 0x1401 172 | #define GL_UNSIGNED_SHORT 0x1403 173 | #define GL_UNSIGNED_INT 0x1405 174 | #define GL_FLOAT 0x1406 175 | #define GL_RGBA 0x1908 176 | #define GL_FILL 0x1B02 177 | #define GL_VENDOR 0x1F00 178 | #define GL_RENDERER 0x1F01 179 | #define GL_VERSION 0x1F02 180 | #define GL_EXTENSIONS 0x1F03 181 | #define GL_LINEAR 0x2601 182 | #define GL_TEXTURE_MAG_FILTER 0x2800 183 | #define GL_TEXTURE_MIN_FILTER 0x2801 184 | typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode); 185 | typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); 186 | typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); 187 | typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); 188 | typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); 189 | typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); 190 | typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap); 191 | typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap); 192 | typedef void (APIENTRYP PFNGLFLUSHPROC) (void); 193 | typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); 194 | typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); 195 | typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); 196 | typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data); 197 | typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); 198 | typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap); 199 | typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); 200 | #ifdef GL_GLEXT_PROTOTYPES 201 | GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode); 202 | GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); 203 | GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); 204 | GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); 205 | GLAPI void APIENTRY glClear (GLbitfield mask); 206 | GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); 207 | GLAPI void APIENTRY glDisable (GLenum cap); 208 | GLAPI void APIENTRY glEnable (GLenum cap); 209 | GLAPI void APIENTRY glFlush (void); 210 | GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); 211 | GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); 212 | GLAPI GLenum APIENTRY glGetError (void); 213 | GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data); 214 | GLAPI const GLubyte *APIENTRY glGetString (GLenum name); 215 | GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap); 216 | GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); 217 | #endif 218 | #endif /* GL_VERSION_1_0 */ 219 | #ifndef GL_VERSION_1_1 220 | typedef khronos_float_t GLclampf; 221 | typedef double GLclampd; 222 | #define GL_TEXTURE_BINDING_2D 0x8069 223 | typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices); 224 | typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); 225 | typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); 226 | typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); 227 | #ifdef GL_GLEXT_PROTOTYPES 228 | GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); 229 | GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture); 230 | GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); 231 | GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures); 232 | #endif 233 | #endif /* GL_VERSION_1_1 */ 234 | #ifndef GL_VERSION_1_3 235 | #define GL_TEXTURE0 0x84C0 236 | #define GL_ACTIVE_TEXTURE 0x84E0 237 | typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); 238 | #ifdef GL_GLEXT_PROTOTYPES 239 | GLAPI void APIENTRY glActiveTexture (GLenum texture); 240 | #endif 241 | #endif /* GL_VERSION_1_3 */ 242 | #ifndef GL_VERSION_1_4 243 | #define GL_BLEND_DST_RGB 0x80C8 244 | #define GL_BLEND_SRC_RGB 0x80C9 245 | #define GL_BLEND_DST_ALPHA 0x80CA 246 | #define GL_BLEND_SRC_ALPHA 0x80CB 247 | #define GL_FUNC_ADD 0x8006 248 | typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); 249 | typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); 250 | #ifdef GL_GLEXT_PROTOTYPES 251 | GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); 252 | GLAPI void APIENTRY glBlendEquation (GLenum mode); 253 | #endif 254 | #endif /* GL_VERSION_1_4 */ 255 | #ifndef GL_VERSION_1_5 256 | typedef khronos_ssize_t GLsizeiptr; 257 | typedef khronos_intptr_t GLintptr; 258 | #define GL_ARRAY_BUFFER 0x8892 259 | #define GL_ELEMENT_ARRAY_BUFFER 0x8893 260 | #define GL_ARRAY_BUFFER_BINDING 0x8894 261 | #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 262 | #define GL_STREAM_DRAW 0x88E0 263 | #define GL_PIXEL_UNPACK_BUFFER 0x88EC 264 | #define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF 265 | typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); 266 | typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); 267 | typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); 268 | typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); 269 | typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); 270 | #ifdef GL_GLEXT_PROTOTYPES 271 | GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer); 272 | GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); 273 | GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); 274 | GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); 275 | GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); 276 | #endif 277 | #endif /* GL_VERSION_1_5 */ 278 | #ifndef GL_VERSION_2_0 279 | typedef char GLchar; 280 | typedef khronos_int16_t GLshort; 281 | typedef khronos_int8_t GLbyte; 282 | typedef khronos_uint16_t GLushort; 283 | #define GL_BLEND_EQUATION_RGB 0x8009 284 | #define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 285 | #define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 286 | #define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 287 | #define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 288 | #define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 289 | #define GL_BLEND_EQUATION_ALPHA 0x883D 290 | #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A 291 | #define GL_FRAGMENT_SHADER 0x8B30 292 | #define GL_VERTEX_SHADER 0x8B31 293 | #define GL_COMPILE_STATUS 0x8B81 294 | #define GL_LINK_STATUS 0x8B82 295 | #define GL_INFO_LOG_LENGTH 0x8B84 296 | #define GL_CURRENT_PROGRAM 0x8B8D 297 | #define GL_UPPER_LEFT 0x8CA2 298 | typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); 299 | typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); 300 | typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); 301 | typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void); 302 | typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); 303 | typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); 304 | typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); 305 | typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); 306 | typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); 307 | typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); 308 | typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); 309 | typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); 310 | typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); 311 | typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); 312 | typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); 313 | typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); 314 | typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); 315 | typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); 316 | typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); 317 | typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); 318 | typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); 319 | typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); 320 | typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); 321 | typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 322 | typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); 323 | #ifdef GL_GLEXT_PROTOTYPES 324 | GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); 325 | GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader); 326 | GLAPI void APIENTRY glCompileShader (GLuint shader); 327 | GLAPI GLuint APIENTRY glCreateProgram (void); 328 | GLAPI GLuint APIENTRY glCreateShader (GLenum type); 329 | GLAPI void APIENTRY glDeleteProgram (GLuint program); 330 | GLAPI void APIENTRY glDeleteShader (GLuint shader); 331 | GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader); 332 | GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index); 333 | GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index); 334 | GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); 335 | GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); 336 | GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); 337 | GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); 338 | GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); 339 | GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); 340 | GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); 341 | GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); 342 | GLAPI GLboolean APIENTRY glIsProgram (GLuint program); 343 | GLAPI void APIENTRY glLinkProgram (GLuint program); 344 | GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); 345 | GLAPI void APIENTRY glUseProgram (GLuint program); 346 | GLAPI void APIENTRY glUniform1i (GLint location, GLint v0); 347 | GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 348 | GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); 349 | #endif 350 | #endif /* GL_VERSION_2_0 */ 351 | #ifndef GL_VERSION_3_0 352 | typedef khronos_uint16_t GLhalf; 353 | #define GL_MAJOR_VERSION 0x821B 354 | #define GL_MINOR_VERSION 0x821C 355 | #define GL_NUM_EXTENSIONS 0x821D 356 | #define GL_FRAMEBUFFER_SRGB 0x8DB9 357 | #define GL_VERTEX_ARRAY_BINDING 0x85B5 358 | typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); 359 | typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); 360 | typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); 361 | typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); 362 | typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); 363 | typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); 364 | #ifdef GL_GLEXT_PROTOTYPES 365 | GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index); 366 | GLAPI void APIENTRY glBindVertexArray (GLuint array); 367 | GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); 368 | GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); 369 | #endif 370 | #endif /* GL_VERSION_3_0 */ 371 | #ifndef GL_VERSION_3_1 372 | #define GL_VERSION_3_1 1 373 | #define GL_PRIMITIVE_RESTART 0x8F9D 374 | #endif /* GL_VERSION_3_1 */ 375 | #ifndef GL_VERSION_3_2 376 | #define GL_VERSION_3_2 1 377 | typedef struct __GLsync *GLsync; 378 | typedef khronos_uint64_t GLuint64; 379 | typedef khronos_int64_t GLint64; 380 | #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 381 | #define GL_CONTEXT_PROFILE_MASK 0x9126 382 | typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); 383 | typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); 384 | #ifdef GL_GLEXT_PROTOTYPES 385 | GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); 386 | #endif 387 | #endif /* GL_VERSION_3_2 */ 388 | #ifndef GL_VERSION_3_3 389 | #define GL_VERSION_3_3 1 390 | #define GL_SAMPLER_BINDING 0x8919 391 | typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); 392 | #ifdef GL_GLEXT_PROTOTYPES 393 | GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler); 394 | #endif 395 | #endif /* GL_VERSION_3_3 */ 396 | #ifndef GL_VERSION_4_1 397 | typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data); 398 | typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data); 399 | #endif /* GL_VERSION_4_1 */ 400 | #ifndef GL_VERSION_4_3 401 | typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); 402 | #endif /* GL_VERSION_4_3 */ 403 | #ifndef GL_VERSION_4_5 404 | #define GL_CLIP_ORIGIN 0x935C 405 | typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param); 406 | typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param); 407 | #endif /* GL_VERSION_4_5 */ 408 | #ifndef GL_ARB_bindless_texture 409 | typedef khronos_uint64_t GLuint64EXT; 410 | #endif /* GL_ARB_bindless_texture */ 411 | #ifndef GL_ARB_cl_event 412 | struct _cl_context; 413 | struct _cl_event; 414 | #endif /* GL_ARB_cl_event */ 415 | #ifndef GL_ARB_clip_control 416 | #define GL_ARB_clip_control 1 417 | #endif /* GL_ARB_clip_control */ 418 | #ifndef GL_ARB_debug_output 419 | typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); 420 | #endif /* GL_ARB_debug_output */ 421 | #ifndef GL_EXT_EGL_image_storage 422 | typedef void *GLeglImageOES; 423 | #endif /* GL_EXT_EGL_image_storage */ 424 | #ifndef GL_EXT_direct_state_access 425 | typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params); 426 | typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params); 427 | typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params); 428 | typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param); 429 | typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param); 430 | #endif /* GL_EXT_direct_state_access */ 431 | #ifndef GL_NV_draw_vulkan_image 432 | typedef void (APIENTRY *GLVULKANPROCNV)(void); 433 | #endif /* GL_NV_draw_vulkan_image */ 434 | #ifndef GL_NV_gpu_shader5 435 | typedef khronos_int64_t GLint64EXT; 436 | #endif /* GL_NV_gpu_shader5 */ 437 | #ifndef GL_NV_vertex_buffer_unified_memory 438 | typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result); 439 | #endif /* GL_NV_vertex_buffer_unified_memory */ 440 | #ifdef __cplusplus 441 | } 442 | #endif 443 | #endif 444 | 445 | #ifndef GL3W_API 446 | #define GL3W_API 447 | #endif 448 | 449 | #ifndef __gl_h_ 450 | #define __gl_h_ 451 | #endif 452 | 453 | #ifdef __cplusplus 454 | extern "C" { 455 | #endif 456 | 457 | #define GL3W_OK 0 458 | #define GL3W_ERROR_INIT -1 459 | #define GL3W_ERROR_LIBRARY_OPEN -2 460 | #define GL3W_ERROR_OPENGL_VERSION -3 461 | 462 | typedef void (*GL3WglProc)(void); 463 | typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc); 464 | 465 | /* gl3w api */ 466 | GL3W_API int imgl3wInit(void); 467 | GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc); 468 | GL3W_API int imgl3wIsSupported(int major, int minor); 469 | GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc); 470 | 471 | /* gl3w internal state */ 472 | union ImGL3WProcs { 473 | GL3WglProc ptr[59]; 474 | struct { 475 | PFNGLACTIVETEXTUREPROC ActiveTexture; 476 | PFNGLATTACHSHADERPROC AttachShader; 477 | PFNGLBINDBUFFERPROC BindBuffer; 478 | PFNGLBINDSAMPLERPROC BindSampler; 479 | PFNGLBINDTEXTUREPROC BindTexture; 480 | PFNGLBINDVERTEXARRAYPROC BindVertexArray; 481 | PFNGLBLENDEQUATIONPROC BlendEquation; 482 | PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate; 483 | PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate; 484 | PFNGLBUFFERDATAPROC BufferData; 485 | PFNGLBUFFERSUBDATAPROC BufferSubData; 486 | PFNGLCLEARPROC Clear; 487 | PFNGLCLEARCOLORPROC ClearColor; 488 | PFNGLCOMPILESHADERPROC CompileShader; 489 | PFNGLCREATEPROGRAMPROC CreateProgram; 490 | PFNGLCREATESHADERPROC CreateShader; 491 | PFNGLDELETEBUFFERSPROC DeleteBuffers; 492 | PFNGLDELETEPROGRAMPROC DeleteProgram; 493 | PFNGLDELETESHADERPROC DeleteShader; 494 | PFNGLDELETETEXTURESPROC DeleteTextures; 495 | PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays; 496 | PFNGLDETACHSHADERPROC DetachShader; 497 | PFNGLDISABLEPROC Disable; 498 | PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray; 499 | PFNGLDRAWELEMENTSPROC DrawElements; 500 | PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex; 501 | PFNGLENABLEPROC Enable; 502 | PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray; 503 | PFNGLFLUSHPROC Flush; 504 | PFNGLGENBUFFERSPROC GenBuffers; 505 | PFNGLGENTEXTURESPROC GenTextures; 506 | PFNGLGENVERTEXARRAYSPROC GenVertexArrays; 507 | PFNGLGETATTRIBLOCATIONPROC GetAttribLocation; 508 | PFNGLGETERRORPROC GetError; 509 | PFNGLGETINTEGERVPROC GetIntegerv; 510 | PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog; 511 | PFNGLGETPROGRAMIVPROC GetProgramiv; 512 | PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog; 513 | PFNGLGETSHADERIVPROC GetShaderiv; 514 | PFNGLGETSTRINGPROC GetString; 515 | PFNGLGETSTRINGIPROC GetStringi; 516 | PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation; 517 | PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv; 518 | PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv; 519 | PFNGLISENABLEDPROC IsEnabled; 520 | PFNGLISPROGRAMPROC IsProgram; 521 | PFNGLLINKPROGRAMPROC LinkProgram; 522 | PFNGLPIXELSTOREIPROC PixelStorei; 523 | PFNGLPOLYGONMODEPROC PolygonMode; 524 | PFNGLREADPIXELSPROC ReadPixels; 525 | PFNGLSCISSORPROC Scissor; 526 | PFNGLSHADERSOURCEPROC ShaderSource; 527 | PFNGLTEXIMAGE2DPROC TexImage2D; 528 | PFNGLTEXPARAMETERIPROC TexParameteri; 529 | PFNGLUNIFORM1IPROC Uniform1i; 530 | PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv; 531 | PFNGLUSEPROGRAMPROC UseProgram; 532 | PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer; 533 | PFNGLVIEWPORTPROC Viewport; 534 | } gl; 535 | }; 536 | 537 | GL3W_API extern union ImGL3WProcs imgl3wProcs; 538 | 539 | /* OpenGL functions */ 540 | #define glActiveTexture imgl3wProcs.gl.ActiveTexture 541 | #define glAttachShader imgl3wProcs.gl.AttachShader 542 | #define glBindBuffer imgl3wProcs.gl.BindBuffer 543 | #define glBindSampler imgl3wProcs.gl.BindSampler 544 | #define glBindTexture imgl3wProcs.gl.BindTexture 545 | #define glBindVertexArray imgl3wProcs.gl.BindVertexArray 546 | #define glBlendEquation imgl3wProcs.gl.BlendEquation 547 | #define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate 548 | #define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate 549 | #define glBufferData imgl3wProcs.gl.BufferData 550 | #define glBufferSubData imgl3wProcs.gl.BufferSubData 551 | #define glClear imgl3wProcs.gl.Clear 552 | #define glClearColor imgl3wProcs.gl.ClearColor 553 | #define glCompileShader imgl3wProcs.gl.CompileShader 554 | #define glCreateProgram imgl3wProcs.gl.CreateProgram 555 | #define glCreateShader imgl3wProcs.gl.CreateShader 556 | #define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers 557 | #define glDeleteProgram imgl3wProcs.gl.DeleteProgram 558 | #define glDeleteShader imgl3wProcs.gl.DeleteShader 559 | #define glDeleteTextures imgl3wProcs.gl.DeleteTextures 560 | #define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays 561 | #define glDetachShader imgl3wProcs.gl.DetachShader 562 | #define glDisable imgl3wProcs.gl.Disable 563 | #define glDisableVertexAttribArray imgl3wProcs.gl.DisableVertexAttribArray 564 | #define glDrawElements imgl3wProcs.gl.DrawElements 565 | #define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex 566 | #define glEnable imgl3wProcs.gl.Enable 567 | #define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray 568 | #define glFlush imgl3wProcs.gl.Flush 569 | #define glGenBuffers imgl3wProcs.gl.GenBuffers 570 | #define glGenTextures imgl3wProcs.gl.GenTextures 571 | #define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays 572 | #define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation 573 | #define glGetError imgl3wProcs.gl.GetError 574 | #define glGetIntegerv imgl3wProcs.gl.GetIntegerv 575 | #define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog 576 | #define glGetProgramiv imgl3wProcs.gl.GetProgramiv 577 | #define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog 578 | #define glGetShaderiv imgl3wProcs.gl.GetShaderiv 579 | #define glGetString imgl3wProcs.gl.GetString 580 | #define glGetStringi imgl3wProcs.gl.GetStringi 581 | #define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation 582 | #define glGetVertexAttribPointerv imgl3wProcs.gl.GetVertexAttribPointerv 583 | #define glGetVertexAttribiv imgl3wProcs.gl.GetVertexAttribiv 584 | #define glIsEnabled imgl3wProcs.gl.IsEnabled 585 | #define glIsProgram imgl3wProcs.gl.IsProgram 586 | #define glLinkProgram imgl3wProcs.gl.LinkProgram 587 | #define glPixelStorei imgl3wProcs.gl.PixelStorei 588 | #define glPolygonMode imgl3wProcs.gl.PolygonMode 589 | #define glReadPixels imgl3wProcs.gl.ReadPixels 590 | #define glScissor imgl3wProcs.gl.Scissor 591 | #define glShaderSource imgl3wProcs.gl.ShaderSource 592 | #define glTexImage2D imgl3wProcs.gl.TexImage2D 593 | #define glTexParameteri imgl3wProcs.gl.TexParameteri 594 | #define glUniform1i imgl3wProcs.gl.Uniform1i 595 | #define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv 596 | #define glUseProgram imgl3wProcs.gl.UseProgram 597 | #define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer 598 | #define glViewport imgl3wProcs.gl.Viewport 599 | 600 | #ifdef __cplusplus 601 | } 602 | #endif 603 | 604 | #endif 605 | 606 | #ifdef IMGL3W_IMPL 607 | #ifdef __cplusplus 608 | extern "C" { 609 | #endif 610 | 611 | #include 612 | 613 | #define GL3W_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 614 | 615 | #if defined(_WIN32) 616 | #ifndef WIN32_LEAN_AND_MEAN 617 | #define WIN32_LEAN_AND_MEAN 1 618 | #endif 619 | #include 620 | 621 | static HMODULE libgl; 622 | typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR); 623 | static GL3WglGetProcAddr wgl_get_proc_address; 624 | 625 | static int open_libgl(void) 626 | { 627 | libgl = LoadLibraryA("opengl32.dll"); 628 | if (!libgl) 629 | return GL3W_ERROR_LIBRARY_OPEN; 630 | wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress"); 631 | return GL3W_OK; 632 | } 633 | 634 | static void close_libgl(void) { FreeLibrary(libgl); } 635 | static GL3WglProc get_proc(const char *proc) 636 | { 637 | GL3WglProc res; 638 | res = (GL3WglProc)wgl_get_proc_address(proc); 639 | if (!res) 640 | res = (GL3WglProc)GetProcAddress(libgl, proc); 641 | return res; 642 | } 643 | #elif defined(__APPLE__) 644 | #include 645 | 646 | static void *libgl; 647 | static int open_libgl(void) 648 | { 649 | libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL); 650 | if (!libgl) 651 | return GL3W_ERROR_LIBRARY_OPEN; 652 | return GL3W_OK; 653 | } 654 | 655 | static void close_libgl(void) { dlclose(libgl); } 656 | 657 | static GL3WglProc get_proc(const char *proc) 658 | { 659 | GL3WglProc res; 660 | *(void **)(&res) = dlsym(libgl, proc); 661 | return res; 662 | } 663 | #else 664 | #include 665 | 666 | static void *libgl; 667 | static GL3WglProc (*glx_get_proc_address)(const GLubyte *); 668 | 669 | static int open_libgl(void) 670 | { 671 | // While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983 672 | libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL); 673 | if (!libgl) 674 | libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); 675 | if (!libgl) 676 | libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL); 677 | if (!libgl) 678 | return GL3W_ERROR_LIBRARY_OPEN; 679 | *(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); 680 | return GL3W_OK; 681 | } 682 | 683 | static void close_libgl(void) { dlclose(libgl); } 684 | 685 | static GL3WglProc get_proc(const char *proc) 686 | { 687 | GL3WglProc res; 688 | res = glx_get_proc_address((const GLubyte *)proc); 689 | if (!res) 690 | *(void **)(&res) = dlsym(libgl, proc); 691 | return res; 692 | } 693 | #endif 694 | 695 | static struct { int major, minor; } version; 696 | 697 | static int parse_version(void) 698 | { 699 | if (!glGetIntegerv) 700 | return GL3W_ERROR_INIT; 701 | glGetIntegerv(GL_MAJOR_VERSION, &version.major); 702 | glGetIntegerv(GL_MINOR_VERSION, &version.minor); 703 | if (version.major == 0 && version.minor == 0) 704 | { 705 | // Query GL_VERSION in desktop GL 2.x, the string will start with "." 706 | if (const char* gl_version = (const char*)glGetString(GL_VERSION)) 707 | sscanf(gl_version, "%d.%d", &version.major, &version.minor); 708 | } 709 | if (version.major < 2) 710 | return GL3W_ERROR_OPENGL_VERSION; 711 | return GL3W_OK; 712 | } 713 | 714 | static void load_procs(GL3WGetProcAddressProc proc); 715 | 716 | int imgl3wInit(void) 717 | { 718 | int res = open_libgl(); 719 | if (res) 720 | return res; 721 | atexit(close_libgl); 722 | return imgl3wInit2(get_proc); 723 | } 724 | 725 | int imgl3wInit2(GL3WGetProcAddressProc proc) 726 | { 727 | load_procs(proc); 728 | return parse_version(); 729 | } 730 | 731 | int imgl3wIsSupported(int major, int minor) 732 | { 733 | if (major < 2) 734 | return 0; 735 | if (version.major == major) 736 | return version.minor >= minor; 737 | return version.major >= major; 738 | } 739 | 740 | GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); } 741 | 742 | static const char *proc_names[] = { 743 | "glActiveTexture", 744 | "glAttachShader", 745 | "glBindBuffer", 746 | "glBindSampler", 747 | "glBindTexture", 748 | "glBindVertexArray", 749 | "glBlendEquation", 750 | "glBlendEquationSeparate", 751 | "glBlendFuncSeparate", 752 | "glBufferData", 753 | "glBufferSubData", 754 | "glClear", 755 | "glClearColor", 756 | "glCompileShader", 757 | "glCreateProgram", 758 | "glCreateShader", 759 | "glDeleteBuffers", 760 | "glDeleteProgram", 761 | "glDeleteShader", 762 | "glDeleteTextures", 763 | "glDeleteVertexArrays", 764 | "glDetachShader", 765 | "glDisable", 766 | "glDisableVertexAttribArray", 767 | "glDrawElements", 768 | "glDrawElementsBaseVertex", 769 | "glEnable", 770 | "glEnableVertexAttribArray", 771 | "glFlush", 772 | "glGenBuffers", 773 | "glGenTextures", 774 | "glGenVertexArrays", 775 | "glGetAttribLocation", 776 | "glGetError", 777 | "glGetIntegerv", 778 | "glGetProgramInfoLog", 779 | "glGetProgramiv", 780 | "glGetShaderInfoLog", 781 | "glGetShaderiv", 782 | "glGetString", 783 | "glGetStringi", 784 | "glGetUniformLocation", 785 | "glGetVertexAttribPointerv", 786 | "glGetVertexAttribiv", 787 | "glIsEnabled", 788 | "glIsProgram", 789 | "glLinkProgram", 790 | "glPixelStorei", 791 | "glPolygonMode", 792 | "glReadPixels", 793 | "glScissor", 794 | "glShaderSource", 795 | "glTexImage2D", 796 | "glTexParameteri", 797 | "glUniform1i", 798 | "glUniformMatrix4fv", 799 | "glUseProgram", 800 | "glVertexAttribPointer", 801 | "glViewport", 802 | }; 803 | 804 | GL3W_API union ImGL3WProcs imgl3wProcs; 805 | 806 | static void load_procs(GL3WGetProcAddressProc proc) 807 | { 808 | size_t i; 809 | for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++) 810 | imgl3wProcs.ptr[i] = proc(proc_names[i]); 811 | } 812 | 813 | #ifdef __cplusplus 814 | } 815 | #endif 816 | #endif 817 | -------------------------------------------------------------------------------- /src/Dependencies/include/ImGui/imgui_impl_win32.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen. 7 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 10 | 11 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 12 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 13 | // Learn about Dear ImGui: 14 | // - FAQ https://dearimgui.com/faq 15 | // - Getting Started https://dearimgui.com/getting-started 16 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 17 | // - Introduction, links and more at the top of imgui.cpp 18 | 19 | #include "imgui.h" 20 | #ifndef IMGUI_DISABLE 21 | #include "imgui_impl_win32.h" 22 | #ifndef WIN32_LEAN_AND_MEAN 23 | #define WIN32_LEAN_AND_MEAN 24 | #endif 25 | #include 26 | #include // GET_X_LPARAM(), GET_Y_LPARAM() 27 | #include 28 | #include 29 | 30 | // Configuration flags to add in your imconfig.h file: 31 | //#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant. 32 | 33 | // Using XInput for gamepad (will load DLL dynamically) 34 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 35 | #include 36 | typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*); 37 | typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); 38 | #endif 39 | 40 | // CHANGELOG 41 | // (minor and older changes stripped away, please see git history for details) 42 | // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. 43 | // 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL). 44 | // 2023-09-07: Inputs: Added support for keyboard codepage conversion for when application is compiled in MBCS mode and using a non-Unicode window. 45 | // 2023-04-19: Added ImGui_ImplWin32_InitForOpenGL() to facilitate combining raw Win32/Winapi with OpenGL. (#3218) 46 | // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen. (#2702) 47 | // 2023-02-15: Inputs: Use WM_NCMOUSEMOVE / WM_NCMOUSELEAVE to track mouse position over non-client area (e.g. OS decorations) when app is not focused. (#6045, #6162) 48 | // 2023-02-02: Inputs: Flipping WM_MOUSEHWHEEL (horizontal mouse-wheel) value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463) 49 | // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. 50 | // 2022-09-28: Inputs: Convert WM_CHAR values with MultiByteToWideChar() when window class was registered as MBCS (not Unicode). 51 | // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). 52 | // 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. 53 | // 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[]. 54 | // 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). 55 | // 2022-01-17: Inputs: always update key mods next and before a key event (not in NewFrame) to fix input queue with very low framerates. 56 | // 2022-01-12: Inputs: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API. 57 | // 2022-01-12: Inputs: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. 58 | // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. 59 | // 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness. 60 | // 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages. 61 | // 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus. 62 | // 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events). 63 | // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). 64 | // 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1). 65 | // 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS). 66 | // 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). 67 | // 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1. 68 | // 2021-01-25: Inputs: Dynamically loading XInput DLL. 69 | // 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed. 70 | // 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs) 71 | // 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions. 72 | // 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. 73 | // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. 74 | // 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). 75 | // 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent. 76 | // 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. 77 | // 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application). 78 | // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. 79 | // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. 80 | // 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads). 81 | // 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples. 82 | // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. 83 | // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). 84 | // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. 85 | // 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). 86 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 87 | // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. 88 | // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. 89 | // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. 90 | // 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read. 91 | // 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. 92 | // 2016-11-12: Inputs: Only call Win32 ::SetCursor(nullptr) when io.MouseDrawCursor is set. 93 | 94 | struct ImGui_ImplWin32_Data 95 | { 96 | HWND hWnd; 97 | HWND MouseHwnd; 98 | int MouseTrackedArea; // 0: not tracked, 1: client are, 2: non-client area 99 | int MouseButtonsDown; 100 | INT64 Time; 101 | INT64 TicksPerSecond; 102 | ImGuiMouseCursor LastMouseCursor; 103 | UINT32 KeyboardCodePage; 104 | 105 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 106 | bool HasGamepad; 107 | bool WantUpdateHasGamepad; 108 | HMODULE XInputDLL; 109 | PFN_XInputGetCapabilities XInputGetCapabilities; 110 | PFN_XInputGetState XInputGetState; 111 | #endif 112 | 113 | ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); } 114 | }; 115 | 116 | // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts 117 | // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. 118 | // FIXME: multi-context support is not well tested and probably dysfunctional in this backend. 119 | // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. 120 | static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData() 121 | { 122 | return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; 123 | } 124 | 125 | // Functions 126 | static void ImGui_ImplWin32_UpdateKeyboardCodePage() 127 | { 128 | // Retrieve keyboard code page, required for handling of non-Unicode Windows. 129 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 130 | HKL keyboard_layout = ::GetKeyboardLayout(0); 131 | LCID keyboard_lcid = MAKELCID(HIWORD(keyboard_layout), SORT_DEFAULT); 132 | if (::GetLocaleInfoA(keyboard_lcid, (LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE), (LPSTR)&bd->KeyboardCodePage, sizeof(bd->KeyboardCodePage)) == 0) 133 | bd->KeyboardCodePage = CP_ACP; // Fallback to default ANSI code page when fails. 134 | } 135 | 136 | static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc) 137 | { 138 | ImGuiIO& io = ImGui::GetIO(); 139 | IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); 140 | 141 | INT64 perf_frequency, perf_counter; 142 | if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency)) 143 | return false; 144 | if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter)) 145 | return false; 146 | 147 | // Setup backend capabilities flags 148 | ImGui_ImplWin32_Data* bd = IM_NEW(ImGui_ImplWin32_Data)(); 149 | io.BackendPlatformUserData = (void*)bd; 150 | io.BackendPlatformName = "imgui_impl_win32"; 151 | io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) 152 | io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) 153 | 154 | bd->hWnd = (HWND)hwnd; 155 | bd->TicksPerSecond = perf_frequency; 156 | bd->Time = perf_counter; 157 | bd->LastMouseCursor = ImGuiMouseCursor_COUNT; 158 | ImGui_ImplWin32_UpdateKeyboardCodePage(); 159 | 160 | // Set platform dependent data in viewport 161 | ImGui::GetMainViewport()->PlatformHandleRaw = (void*)hwnd; 162 | IM_UNUSED(platform_has_own_dc); // Used in 'docking' branch 163 | 164 | // Dynamically load XInput library 165 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 166 | bd->WantUpdateHasGamepad = true; 167 | const char* xinput_dll_names[] = 168 | { 169 | "xinput1_4.dll", // Windows 8+ 170 | "xinput1_3.dll", // DirectX SDK 171 | "xinput9_1_0.dll", // Windows Vista, Windows 7 172 | "xinput1_2.dll", // DirectX SDK 173 | "xinput1_1.dll" // DirectX SDK 174 | }; 175 | for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++) 176 | if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n])) 177 | { 178 | bd->XInputDLL = dll; 179 | bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities"); 180 | bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState"); 181 | break; 182 | } 183 | #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 184 | 185 | return true; 186 | } 187 | 188 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd) 189 | { 190 | return ImGui_ImplWin32_InitEx(hwnd, false); 191 | } 192 | 193 | IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd) 194 | { 195 | // OpenGL needs CS_OWNDC 196 | return ImGui_ImplWin32_InitEx(hwnd, true); 197 | } 198 | 199 | void ImGui_ImplWin32_Shutdown() 200 | { 201 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 202 | IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); 203 | ImGuiIO& io = ImGui::GetIO(); 204 | 205 | // Unload XInput library 206 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 207 | if (bd->XInputDLL) 208 | ::FreeLibrary(bd->XInputDLL); 209 | #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 210 | 211 | io.BackendPlatformName = nullptr; 212 | io.BackendPlatformUserData = nullptr; 213 | io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad); 214 | IM_DELETE(bd); 215 | } 216 | 217 | static bool ImGui_ImplWin32_UpdateMouseCursor() 218 | { 219 | ImGuiIO& io = ImGui::GetIO(); 220 | if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) 221 | return false; 222 | 223 | ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); 224 | if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) 225 | { 226 | // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor 227 | ::SetCursor(nullptr); 228 | } 229 | else 230 | { 231 | // Show OS mouse cursor 232 | LPTSTR win32_cursor = IDC_ARROW; 233 | switch (imgui_cursor) 234 | { 235 | case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; 236 | case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; 237 | case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; 238 | case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; 239 | case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; 240 | case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; 241 | case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; 242 | case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; 243 | case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; 244 | } 245 | ::SetCursor(::LoadCursor(nullptr, win32_cursor)); 246 | } 247 | return true; 248 | } 249 | 250 | static bool IsVkDown(int vk) 251 | { 252 | return (::GetKeyState(vk) & 0x8000) != 0; 253 | } 254 | 255 | static void ImGui_ImplWin32_AddKeyEvent(ImGuiKey key, bool down, int native_keycode, int native_scancode = -1) 256 | { 257 | ImGuiIO& io = ImGui::GetIO(); 258 | io.AddKeyEvent(key, down); 259 | io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To support legacy indexing (<1.87 user code) 260 | IM_UNUSED(native_scancode); 261 | } 262 | 263 | static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds() 264 | { 265 | // Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one. 266 | if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && !IsVkDown(VK_LSHIFT)) 267 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, false, VK_LSHIFT); 268 | if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT)) 269 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, false, VK_RSHIFT); 270 | 271 | // Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Win+V on some setups, according to GLFW). 272 | if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN)) 273 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftSuper, false, VK_LWIN); 274 | if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN)) 275 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightSuper, false, VK_RWIN); 276 | } 277 | 278 | static void ImGui_ImplWin32_UpdateKeyModifiers() 279 | { 280 | ImGuiIO& io = ImGui::GetIO(); 281 | io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL)); 282 | io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT)); 283 | io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU)); 284 | io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_APPS)); 285 | } 286 | 287 | static void ImGui_ImplWin32_UpdateMouseData() 288 | { 289 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 290 | ImGuiIO& io = ImGui::GetIO(); 291 | IM_ASSERT(bd->hWnd != 0); 292 | 293 | HWND focused_window = ::GetForegroundWindow(); 294 | const bool is_app_focused = (focused_window == bd->hWnd); 295 | if (is_app_focused) 296 | { 297 | // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) 298 | if (io.WantSetMousePos) 299 | { 300 | POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; 301 | if (::ClientToScreen(bd->hWnd, &pos)) 302 | ::SetCursorPos(pos.x, pos.y); 303 | } 304 | 305 | // (Optional) Fallback to provide mouse position when focused (WM_MOUSEMOVE already provides this when hovered or captured) 306 | // This also fills a short gap when clicking non-client area: WM_NCMOUSELEAVE -> modal OS move -> gap -> WM_NCMOUSEMOVE 307 | if (!io.WantSetMousePos && bd->MouseTrackedArea == 0) 308 | { 309 | POINT pos; 310 | if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos)) 311 | io.AddMousePosEvent((float)pos.x, (float)pos.y); 312 | } 313 | } 314 | } 315 | 316 | // Gamepad navigation mapping 317 | static void ImGui_ImplWin32_UpdateGamepads() 318 | { 319 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 320 | ImGuiIO& io = ImGui::GetIO(); 321 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 322 | //if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. 323 | // return; 324 | 325 | // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. 326 | // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. 327 | if (bd->WantUpdateHasGamepad) 328 | { 329 | XINPUT_CAPABILITIES caps = {}; 330 | bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; 331 | bd->WantUpdateHasGamepad = false; 332 | } 333 | 334 | io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; 335 | XINPUT_STATE xinput_state; 336 | XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; 337 | if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS) 338 | return; 339 | io.BackendFlags |= ImGuiBackendFlags_HasGamepad; 340 | 341 | #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) 342 | #define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); } 343 | #define MAP_ANALOG(KEY_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); io.AddKeyAnalogEvent(KEY_NO, vn > 0.10f, IM_SATURATE(vn)); } 344 | MAP_BUTTON(ImGuiKey_GamepadStart, XINPUT_GAMEPAD_START); 345 | MAP_BUTTON(ImGuiKey_GamepadBack, XINPUT_GAMEPAD_BACK); 346 | MAP_BUTTON(ImGuiKey_GamepadFaceLeft, XINPUT_GAMEPAD_X); 347 | MAP_BUTTON(ImGuiKey_GamepadFaceRight, XINPUT_GAMEPAD_B); 348 | MAP_BUTTON(ImGuiKey_GamepadFaceUp, XINPUT_GAMEPAD_Y); 349 | MAP_BUTTON(ImGuiKey_GamepadFaceDown, XINPUT_GAMEPAD_A); 350 | MAP_BUTTON(ImGuiKey_GamepadDpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); 351 | MAP_BUTTON(ImGuiKey_GamepadDpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); 352 | MAP_BUTTON(ImGuiKey_GamepadDpadUp, XINPUT_GAMEPAD_DPAD_UP); 353 | MAP_BUTTON(ImGuiKey_GamepadDpadDown, XINPUT_GAMEPAD_DPAD_DOWN); 354 | MAP_BUTTON(ImGuiKey_GamepadL1, XINPUT_GAMEPAD_LEFT_SHOULDER); 355 | MAP_BUTTON(ImGuiKey_GamepadR1, XINPUT_GAMEPAD_RIGHT_SHOULDER); 356 | MAP_ANALOG(ImGuiKey_GamepadL2, gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255); 357 | MAP_ANALOG(ImGuiKey_GamepadR2, gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255); 358 | MAP_BUTTON(ImGuiKey_GamepadL3, XINPUT_GAMEPAD_LEFT_THUMB); 359 | MAP_BUTTON(ImGuiKey_GamepadR3, XINPUT_GAMEPAD_RIGHT_THUMB); 360 | MAP_ANALOG(ImGuiKey_GamepadLStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 361 | MAP_ANALOG(ImGuiKey_GamepadLStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 362 | MAP_ANALOG(ImGuiKey_GamepadLStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 363 | MAP_ANALOG(ImGuiKey_GamepadLStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 364 | MAP_ANALOG(ImGuiKey_GamepadRStickLeft, gamepad.sThumbRX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 365 | MAP_ANALOG(ImGuiKey_GamepadRStickRight, gamepad.sThumbRX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 366 | MAP_ANALOG(ImGuiKey_GamepadRStickUp, gamepad.sThumbRY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 367 | MAP_ANALOG(ImGuiKey_GamepadRStickDown, gamepad.sThumbRY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 368 | #undef MAP_BUTTON 369 | #undef MAP_ANALOG 370 | #endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 371 | } 372 | 373 | void ImGui_ImplWin32_NewFrame() 374 | { 375 | ImGuiIO& io = ImGui::GetIO(); 376 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 377 | IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplWin32_Init()?"); 378 | 379 | // Setup display size (every frame to accommodate for window resizing) 380 | RECT rect = { 0, 0, 0, 0 }; 381 | ::GetClientRect(bd->hWnd, &rect); 382 | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); 383 | 384 | // Setup time step 385 | INT64 current_time = 0; 386 | ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); 387 | io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond; 388 | bd->Time = current_time; 389 | 390 | // Update OS mouse position 391 | ImGui_ImplWin32_UpdateMouseData(); 392 | 393 | // Process workarounds for known Windows key handling issues 394 | ImGui_ImplWin32_ProcessKeyEventsWorkarounds(); 395 | 396 | // Update OS mouse cursor with the cursor requested by imgui 397 | ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); 398 | if (bd->LastMouseCursor != mouse_cursor) 399 | { 400 | bd->LastMouseCursor = mouse_cursor; 401 | ImGui_ImplWin32_UpdateMouseCursor(); 402 | } 403 | 404 | // Update game controllers (if enabled and available) 405 | ImGui_ImplWin32_UpdateGamepads(); 406 | } 407 | 408 | // There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED, we assign it an arbitrary value to make code more readable (VK_ codes go up to 255) 409 | #define IM_VK_KEYPAD_ENTER (VK_RETURN + 256) 410 | 411 | // Map VK_xxx to ImGuiKey_xxx. 412 | static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam) 413 | { 414 | switch (wParam) 415 | { 416 | case VK_TAB: return ImGuiKey_Tab; 417 | case VK_LEFT: return ImGuiKey_LeftArrow; 418 | case VK_RIGHT: return ImGuiKey_RightArrow; 419 | case VK_UP: return ImGuiKey_UpArrow; 420 | case VK_DOWN: return ImGuiKey_DownArrow; 421 | case VK_PRIOR: return ImGuiKey_PageUp; 422 | case VK_NEXT: return ImGuiKey_PageDown; 423 | case VK_HOME: return ImGuiKey_Home; 424 | case VK_END: return ImGuiKey_End; 425 | case VK_INSERT: return ImGuiKey_Insert; 426 | case VK_DELETE: return ImGuiKey_Delete; 427 | case VK_BACK: return ImGuiKey_Backspace; 428 | case VK_SPACE: return ImGuiKey_Space; 429 | case VK_RETURN: return ImGuiKey_Enter; 430 | case VK_ESCAPE: return ImGuiKey_Escape; 431 | case VK_OEM_7: return ImGuiKey_Apostrophe; 432 | case VK_OEM_COMMA: return ImGuiKey_Comma; 433 | case VK_OEM_MINUS: return ImGuiKey_Minus; 434 | case VK_OEM_PERIOD: return ImGuiKey_Period; 435 | case VK_OEM_2: return ImGuiKey_Slash; 436 | case VK_OEM_1: return ImGuiKey_Semicolon; 437 | case VK_OEM_PLUS: return ImGuiKey_Equal; 438 | case VK_OEM_4: return ImGuiKey_LeftBracket; 439 | case VK_OEM_5: return ImGuiKey_Backslash; 440 | case VK_OEM_6: return ImGuiKey_RightBracket; 441 | case VK_OEM_3: return ImGuiKey_GraveAccent; 442 | case VK_CAPITAL: return ImGuiKey_CapsLock; 443 | case VK_SCROLL: return ImGuiKey_ScrollLock; 444 | case VK_NUMLOCK: return ImGuiKey_NumLock; 445 | case VK_SNAPSHOT: return ImGuiKey_PrintScreen; 446 | case VK_PAUSE: return ImGuiKey_Pause; 447 | case VK_NUMPAD0: return ImGuiKey_Keypad0; 448 | case VK_NUMPAD1: return ImGuiKey_Keypad1; 449 | case VK_NUMPAD2: return ImGuiKey_Keypad2; 450 | case VK_NUMPAD3: return ImGuiKey_Keypad3; 451 | case VK_NUMPAD4: return ImGuiKey_Keypad4; 452 | case VK_NUMPAD5: return ImGuiKey_Keypad5; 453 | case VK_NUMPAD6: return ImGuiKey_Keypad6; 454 | case VK_NUMPAD7: return ImGuiKey_Keypad7; 455 | case VK_NUMPAD8: return ImGuiKey_Keypad8; 456 | case VK_NUMPAD9: return ImGuiKey_Keypad9; 457 | case VK_DECIMAL: return ImGuiKey_KeypadDecimal; 458 | case VK_DIVIDE: return ImGuiKey_KeypadDivide; 459 | case VK_MULTIPLY: return ImGuiKey_KeypadMultiply; 460 | case VK_SUBTRACT: return ImGuiKey_KeypadSubtract; 461 | case VK_ADD: return ImGuiKey_KeypadAdd; 462 | case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter; 463 | case VK_LSHIFT: return ImGuiKey_LeftShift; 464 | case VK_LCONTROL: return ImGuiKey_LeftCtrl; 465 | case VK_LMENU: return ImGuiKey_LeftAlt; 466 | case VK_LWIN: return ImGuiKey_LeftSuper; 467 | case VK_RSHIFT: return ImGuiKey_RightShift; 468 | case VK_RCONTROL: return ImGuiKey_RightCtrl; 469 | case VK_RMENU: return ImGuiKey_RightAlt; 470 | case VK_RWIN: return ImGuiKey_RightSuper; 471 | case VK_APPS: return ImGuiKey_Menu; 472 | case '0': return ImGuiKey_0; 473 | case '1': return ImGuiKey_1; 474 | case '2': return ImGuiKey_2; 475 | case '3': return ImGuiKey_3; 476 | case '4': return ImGuiKey_4; 477 | case '5': return ImGuiKey_5; 478 | case '6': return ImGuiKey_6; 479 | case '7': return ImGuiKey_7; 480 | case '8': return ImGuiKey_8; 481 | case '9': return ImGuiKey_9; 482 | case 'A': return ImGuiKey_A; 483 | case 'B': return ImGuiKey_B; 484 | case 'C': return ImGuiKey_C; 485 | case 'D': return ImGuiKey_D; 486 | case 'E': return ImGuiKey_E; 487 | case 'F': return ImGuiKey_F; 488 | case 'G': return ImGuiKey_G; 489 | case 'H': return ImGuiKey_H; 490 | case 'I': return ImGuiKey_I; 491 | case 'J': return ImGuiKey_J; 492 | case 'K': return ImGuiKey_K; 493 | case 'L': return ImGuiKey_L; 494 | case 'M': return ImGuiKey_M; 495 | case 'N': return ImGuiKey_N; 496 | case 'O': return ImGuiKey_O; 497 | case 'P': return ImGuiKey_P; 498 | case 'Q': return ImGuiKey_Q; 499 | case 'R': return ImGuiKey_R; 500 | case 'S': return ImGuiKey_S; 501 | case 'T': return ImGuiKey_T; 502 | case 'U': return ImGuiKey_U; 503 | case 'V': return ImGuiKey_V; 504 | case 'W': return ImGuiKey_W; 505 | case 'X': return ImGuiKey_X; 506 | case 'Y': return ImGuiKey_Y; 507 | case 'Z': return ImGuiKey_Z; 508 | case VK_F1: return ImGuiKey_F1; 509 | case VK_F2: return ImGuiKey_F2; 510 | case VK_F3: return ImGuiKey_F3; 511 | case VK_F4: return ImGuiKey_F4; 512 | case VK_F5: return ImGuiKey_F5; 513 | case VK_F6: return ImGuiKey_F6; 514 | case VK_F7: return ImGuiKey_F7; 515 | case VK_F8: return ImGuiKey_F8; 516 | case VK_F9: return ImGuiKey_F9; 517 | case VK_F10: return ImGuiKey_F10; 518 | case VK_F11: return ImGuiKey_F11; 519 | case VK_F12: return ImGuiKey_F12; 520 | case VK_F13: return ImGuiKey_F13; 521 | case VK_F14: return ImGuiKey_F14; 522 | case VK_F15: return ImGuiKey_F15; 523 | case VK_F16: return ImGuiKey_F16; 524 | case VK_F17: return ImGuiKey_F17; 525 | case VK_F18: return ImGuiKey_F18; 526 | case VK_F19: return ImGuiKey_F19; 527 | case VK_F20: return ImGuiKey_F20; 528 | case VK_F21: return ImGuiKey_F21; 529 | case VK_F22: return ImGuiKey_F22; 530 | case VK_F23: return ImGuiKey_F23; 531 | case VK_F24: return ImGuiKey_F24; 532 | case VK_BROWSER_BACK: return ImGuiKey_AppBack; 533 | case VK_BROWSER_FORWARD: return ImGuiKey_AppForward; 534 | default: return ImGuiKey_None; 535 | } 536 | } 537 | 538 | // Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. 539 | #ifndef WM_MOUSEHWHEEL 540 | #define WM_MOUSEHWHEEL 0x020E 541 | #endif 542 | #ifndef DBT_DEVNODES_CHANGED 543 | #define DBT_DEVNODES_CHANGED 0x0007 544 | #endif 545 | 546 | // Win32 message handler (process Win32 mouse/keyboard inputs, etc.) 547 | // Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. 548 | // When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs. 549 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. 550 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. 551 | // Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags. 552 | // PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds. 553 | // PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. 554 | #if 0 555 | // Copy this line into your .cpp file to forward declare the function. 556 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 557 | #endif 558 | 559 | // See https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages 560 | // Prefer to call this at the top of the message handler to avoid the possibility of other Win32 calls interfering with this. 561 | static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo() 562 | { 563 | LPARAM extra_info = ::GetMessageExtraInfo(); 564 | if ((extra_info & 0xFFFFFF80) == 0xFF515700) 565 | return ImGuiMouseSource_Pen; 566 | if ((extra_info & 0xFFFFFF80) == 0xFF515780) 567 | return ImGuiMouseSource_TouchScreen; 568 | return ImGuiMouseSource_Mouse; 569 | } 570 | 571 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 572 | { 573 | if (ImGui::GetCurrentContext() == nullptr) 574 | return 0; 575 | 576 | ImGuiIO& io = ImGui::GetIO(); 577 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 578 | 579 | switch (msg) 580 | { 581 | case WM_MOUSEMOVE: 582 | case WM_NCMOUSEMOVE: 583 | { 584 | // We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events 585 | ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo(); 586 | const int area = (msg == WM_MOUSEMOVE) ? 1 : 2; 587 | bd->MouseHwnd = hwnd; 588 | if (bd->MouseTrackedArea != area) 589 | { 590 | TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 }; 591 | TRACKMOUSEEVENT tme_track = { sizeof(tme_track), (DWORD)((area == 2) ? (TME_LEAVE | TME_NONCLIENT) : TME_LEAVE), hwnd, 0 }; 592 | if (bd->MouseTrackedArea != 0) 593 | ::TrackMouseEvent(&tme_cancel); 594 | ::TrackMouseEvent(&tme_track); 595 | bd->MouseTrackedArea = area; 596 | } 597 | POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) }; 598 | if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates. 599 | break; 600 | io.AddMouseSourceEvent(mouse_source); 601 | io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y); 602 | break; 603 | } 604 | case WM_MOUSELEAVE: 605 | case WM_NCMOUSELEAVE: 606 | { 607 | const int area = (msg == WM_MOUSELEAVE) ? 1 : 2; 608 | if (bd->MouseTrackedArea == area) 609 | { 610 | if (bd->MouseHwnd == hwnd) 611 | bd->MouseHwnd = nullptr; 612 | bd->MouseTrackedArea = 0; 613 | io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); 614 | } 615 | break; 616 | } 617 | case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: 618 | case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: 619 | case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: 620 | case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: 621 | { 622 | ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo(); 623 | int button = 0; 624 | if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; } 625 | if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } 626 | if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } 627 | if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } 628 | if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr) 629 | ::SetCapture(hwnd); 630 | bd->MouseButtonsDown |= 1 << button; 631 | io.AddMouseSourceEvent(mouse_source); 632 | io.AddMouseButtonEvent(button, true); 633 | return 0; 634 | } 635 | case WM_LBUTTONUP: 636 | case WM_RBUTTONUP: 637 | case WM_MBUTTONUP: 638 | case WM_XBUTTONUP: 639 | { 640 | ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo(); 641 | int button = 0; 642 | if (msg == WM_LBUTTONUP) { button = 0; } 643 | if (msg == WM_RBUTTONUP) { button = 1; } 644 | if (msg == WM_MBUTTONUP) { button = 2; } 645 | if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } 646 | bd->MouseButtonsDown &= ~(1 << button); 647 | if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd) 648 | ::ReleaseCapture(); 649 | io.AddMouseSourceEvent(mouse_source); 650 | io.AddMouseButtonEvent(button, false); 651 | return 0; 652 | } 653 | case WM_MOUSEWHEEL: 654 | io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA); 655 | return 0; 656 | case WM_MOUSEHWHEEL: 657 | io.AddMouseWheelEvent(-(float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f); 658 | return 0; 659 | case WM_KEYDOWN: 660 | case WM_KEYUP: 661 | case WM_SYSKEYDOWN: 662 | case WM_SYSKEYUP: 663 | { 664 | const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN); 665 | if (wParam < 256) 666 | { 667 | // Submit modifiers 668 | ImGui_ImplWin32_UpdateKeyModifiers(); 669 | 670 | // Obtain virtual key code 671 | // (keypad enter doesn't have its own... VK_RETURN with KF_EXTENDED flag means keypad enter, see IM_VK_KEYPAD_ENTER definition for details, it is mapped to ImGuiKey_KeyPadEnter.) 672 | int vk = (int)wParam; 673 | if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED)) 674 | vk = IM_VK_KEYPAD_ENTER; 675 | const ImGuiKey key = ImGui_ImplWin32_VirtualKeyToImGuiKey(vk); 676 | const int scancode = (int)LOBYTE(HIWORD(lParam)); 677 | 678 | // Special behavior for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit the key down event. 679 | if (key == ImGuiKey_PrintScreen && !is_key_down) 680 | ImGui_ImplWin32_AddKeyEvent(key, true, vk, scancode); 681 | 682 | // Submit key event 683 | if (key != ImGuiKey_None) 684 | ImGui_ImplWin32_AddKeyEvent(key, is_key_down, vk, scancode); 685 | 686 | // Submit individual left/right modifier events 687 | if (vk == VK_SHIFT) 688 | { 689 | // Important: Shift keys tend to get stuck when pressed together, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkarounds() 690 | if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); } 691 | if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); } 692 | } 693 | else if (vk == VK_CONTROL) 694 | { 695 | if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); } 696 | if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); } 697 | } 698 | else if (vk == VK_MENU) 699 | { 700 | if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); } 701 | if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); } 702 | } 703 | } 704 | return 0; 705 | } 706 | case WM_SETFOCUS: 707 | case WM_KILLFOCUS: 708 | io.AddFocusEvent(msg == WM_SETFOCUS); 709 | return 0; 710 | case WM_INPUTLANGCHANGE: 711 | ImGui_ImplWin32_UpdateKeyboardCodePage(); 712 | return 0; 713 | case WM_CHAR: 714 | if (::IsWindowUnicode(hwnd)) 715 | { 716 | // You can also use ToAscii()+GetKeyboardState() to retrieve characters. 717 | if (wParam > 0 && wParam < 0x10000) 718 | io.AddInputCharacterUTF16((unsigned short)wParam); 719 | } 720 | else 721 | { 722 | wchar_t wch = 0; 723 | ::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 1, &wch, 1); 724 | io.AddInputCharacter(wch); 725 | } 726 | return 0; 727 | case WM_SETCURSOR: 728 | // This is required to restore cursor when transitioning from e.g resize borders to client area. 729 | if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) 730 | return 1; 731 | return 0; 732 | case WM_DEVICECHANGE: 733 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 734 | if ((UINT)wParam == DBT_DEVNODES_CHANGED) 735 | bd->WantUpdateHasGamepad = true; 736 | #endif 737 | return 0; 738 | } 739 | return 0; 740 | } 741 | 742 | 743 | //-------------------------------------------------------------------------------------------------------- 744 | // DPI-related helpers (optional) 745 | //-------------------------------------------------------------------------------------------------------- 746 | // - Use to enable DPI awareness without having to create an application manifest. 747 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 748 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 749 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 750 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 751 | //--------------------------------------------------------------------------------------------------------- 752 | // This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable. 753 | // ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically. 754 | // If you are trying to implement your own backend for your own engine, you may ignore that noise. 755 | //--------------------------------------------------------------------------------------------------------- 756 | 757 | // Perform our own check with RtlVerifyVersionInfo() instead of using functions from as they 758 | // require a manifest to be functional for checks above 8.1. See https://github.com/ocornut/imgui/issues/4200 759 | static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD) 760 | { 761 | typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG); 762 | static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = nullptr; 763 | if (RtlVerifyVersionInfoFn == nullptr) 764 | if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll")) 765 | RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo"); 766 | if (RtlVerifyVersionInfoFn == nullptr) 767 | return FALSE; 768 | 769 | RTL_OSVERSIONINFOEXW versionInfo = { }; 770 | ULONGLONG conditionMask = 0; 771 | versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); 772 | versionInfo.dwMajorVersion = major; 773 | versionInfo.dwMinorVersion = minor; 774 | VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); 775 | VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); 776 | return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE; 777 | } 778 | 779 | #define _IsWindowsVistaOrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA 780 | #define _IsWindows8OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8 781 | #define _IsWindows8Point1OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE 782 | #define _IsWindows10OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0A00), LOBYTE(0x0A00), 0) // _WIN32_WINNT_WINTHRESHOLD / _WIN32_WINNT_WIN10 783 | 784 | #ifndef DPI_ENUMS_DECLARED 785 | typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS; 786 | typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE; 787 | #endif 788 | #ifndef _DPI_AWARENESS_CONTEXTS_ 789 | DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); 790 | #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3 791 | #endif 792 | #ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 793 | #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4 794 | #endif 795 | typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+ 796 | typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+ 797 | typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update) 798 | 799 | // Helper function to enable DPI awareness without setting up a manifest 800 | void ImGui_ImplWin32_EnableDpiAwareness() 801 | { 802 | if (_IsWindows10OrGreater()) 803 | { 804 | static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process 805 | if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext")) 806 | { 807 | SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); 808 | return; 809 | } 810 | } 811 | if (_IsWindows8Point1OrGreater()) 812 | { 813 | static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process 814 | if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness")) 815 | { 816 | SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE); 817 | return; 818 | } 819 | } 820 | #if _WIN32_WINNT >= 0x0600 821 | ::SetProcessDPIAware(); 822 | #endif 823 | } 824 | 825 | #if defined(_MSC_VER) && !defined(NOGDI) 826 | #pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32' 827 | #endif 828 | 829 | float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor) 830 | { 831 | UINT xdpi = 96, ydpi = 96; 832 | if (_IsWindows8Point1OrGreater()) 833 | { 834 | static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process 835 | static PFN_GetDpiForMonitor GetDpiForMonitorFn = nullptr; 836 | if (GetDpiForMonitorFn == nullptr && shcore_dll != nullptr) 837 | GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor"); 838 | if (GetDpiForMonitorFn != nullptr) 839 | { 840 | GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); 841 | IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! 842 | return xdpi / 96.0f; 843 | } 844 | } 845 | #ifndef NOGDI 846 | const HDC dc = ::GetDC(nullptr); 847 | xdpi = ::GetDeviceCaps(dc, LOGPIXELSX); 848 | ydpi = ::GetDeviceCaps(dc, LOGPIXELSY); 849 | IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! 850 | ::ReleaseDC(nullptr, dc); 851 | #endif 852 | return xdpi / 96.0f; 853 | } 854 | 855 | float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd) 856 | { 857 | HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST); 858 | return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor); 859 | } 860 | 861 | //--------------------------------------------------------------------------------------------------------- 862 | // Transparency related helpers (optional) 863 | //-------------------------------------------------------------------------------------------------------- 864 | 865 | #if defined(_MSC_VER) 866 | #pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi' 867 | #endif 868 | 869 | // [experimental] 870 | // Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c 871 | // (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW) 872 | void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd) 873 | { 874 | if (!_IsWindowsVistaOrGreater()) 875 | return; 876 | 877 | BOOL composition; 878 | if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition) 879 | return; 880 | 881 | BOOL opaque; 882 | DWORD color; 883 | if (_IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque)) 884 | { 885 | HRGN region = ::CreateRectRgn(0, 0, -1, -1); 886 | DWM_BLURBEHIND bb = {}; 887 | bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; 888 | bb.hRgnBlur = region; 889 | bb.fEnable = TRUE; 890 | ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); 891 | ::DeleteObject(region); 892 | } 893 | else 894 | { 895 | DWM_BLURBEHIND bb = {}; 896 | bb.dwFlags = DWM_BB_ENABLE; 897 | ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); 898 | } 899 | } 900 | 901 | //--------------------------------------------------------------------------------------------------------- 902 | 903 | #endif // #ifndef IMGUI_DISABLE 904 | -------------------------------------------------------------------------------- /src/Dependencies/include/ImGui/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen. 7 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 10 | 11 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 12 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 13 | // Learn about Dear ImGui: 14 | // - FAQ https://dearimgui.com/faq 15 | // - Getting Started https://dearimgui.com/getting-started 16 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 17 | // - Introduction, links and more at the top of imgui.cpp 18 | 19 | #pragma once 20 | #include "imgui.h" // IMGUI_IMPL_API 21 | #ifndef IMGUI_DISABLE 22 | 23 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 24 | IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd); 25 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 26 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 27 | 28 | // Win32 message handler your application need to call. 29 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 30 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 31 | // - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. 32 | 33 | #if 0 34 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 35 | #endif 36 | 37 | // DPI-related helpers (optional) 38 | // - Use to enable DPI awareness without having to create an application manifest. 39 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 40 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 41 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 42 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 43 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 44 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 45 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 46 | 47 | // Transparency related helpers (optional) [experimental] 48 | // - Use to enable alpha compositing transparency with the desktop. 49 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 50 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 51 | 52 | #endif // #ifndef IMGUI_DISABLE 53 | -------------------------------------------------------------------------------- /src/Dependencies/include/ImGui/imgui_stdlib.h: -------------------------------------------------------------------------------- 1 | // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) 2 | // This is also an example of how you may wrap your own similar types. 3 | 4 | // Changelog: 5 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string 6 | 7 | // See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki: 8 | // https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness 9 | 10 | #pragma once 11 | 12 | #include 13 | 14 | namespace ImGui 15 | { 16 | // ImGui::InputText() with std::string 17 | // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity 18 | IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); 19 | IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); 20 | IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); 21 | } 22 | -------------------------------------------------------------------------------- /src/Dependencies/include/ImGui/imstb_rectpack.h: -------------------------------------------------------------------------------- 1 | // [DEAR IMGUI] 2 | // This is a slightly modified version of stb_rect_pack.h 1.01. 3 | // Grep for [DEAR IMGUI] to find the changes. 4 | // 5 | // stb_rect_pack.h - v1.01 - public domain - rectangle packing 6 | // Sean Barrett 2014 7 | // 8 | // Useful for e.g. packing rectangular textures into an atlas. 9 | // Does not do rotation. 10 | // 11 | // Before #including, 12 | // 13 | // #define STB_RECT_PACK_IMPLEMENTATION 14 | // 15 | // in the file that you want to have the implementation. 16 | // 17 | // Not necessarily the awesomest packing method, but better than 18 | // the totally naive one in stb_truetype (which is primarily what 19 | // this is meant to replace). 20 | // 21 | // Has only had a few tests run, may have issues. 22 | // 23 | // More docs to come. 24 | // 25 | // No memory allocations; uses qsort() and assert() from stdlib. 26 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 27 | // 28 | // This library currently uses the Skyline Bottom-Left algorithm. 29 | // 30 | // Please note: better rectangle packers are welcome! Please 31 | // implement them to the same API, but with a different init 32 | // function. 33 | // 34 | // Credits 35 | // 36 | // Library 37 | // Sean Barrett 38 | // Minor features 39 | // Martins Mozeiko 40 | // github:IntellectualKitty 41 | // 42 | // Bugfixes / warning fixes 43 | // Jeremy Jaussaud 44 | // Fabian Giesen 45 | // 46 | // Version history: 47 | // 48 | // 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section 49 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles 50 | // 0.99 (2019-02-07) warning fixes 51 | // 0.11 (2017-03-03) return packing success/fail result 52 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 53 | // 0.09 (2016-08-27) fix compiler warnings 54 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 55 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 56 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 57 | // 0.05: added STBRP_ASSERT to allow replacing assert 58 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 59 | // 0.01: initial release 60 | // 61 | // LICENSE 62 | // 63 | // See end of file for license information. 64 | 65 | ////////////////////////////////////////////////////////////////////////////// 66 | // 67 | // INCLUDE SECTION 68 | // 69 | 70 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 71 | #define STB_INCLUDE_STB_RECT_PACK_H 72 | 73 | #define STB_RECT_PACK_VERSION 1 74 | 75 | #ifdef STBRP_STATIC 76 | #define STBRP_DEF static 77 | #else 78 | #define STBRP_DEF extern 79 | #endif 80 | 81 | #ifdef __cplusplus 82 | extern "C" { 83 | #endif 84 | 85 | typedef struct stbrp_context stbrp_context; 86 | typedef struct stbrp_node stbrp_node; 87 | typedef struct stbrp_rect stbrp_rect; 88 | 89 | typedef int stbrp_coord; 90 | 91 | #define STBRP__MAXVAL 0x7fffffff 92 | // Mostly for internal use, but this is the maximum supported coordinate value. 93 | 94 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 95 | // Assign packed locations to rectangles. The rectangles are of type 96 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 97 | // are 'num_rects' many of them. 98 | // 99 | // Rectangles which are successfully packed have the 'was_packed' flag 100 | // set to a non-zero value and 'x' and 'y' store the minimum location 101 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 102 | // if you imagine y increasing downwards). Rectangles which do not fit 103 | // have the 'was_packed' flag set to 0. 104 | // 105 | // You should not try to access the 'rects' array from another thread 106 | // while this function is running, as the function temporarily reorders 107 | // the array while it executes. 108 | // 109 | // To pack into another rectangle, you need to call stbrp_init_target 110 | // again. To continue packing into the same rectangle, you can call 111 | // this function again. Calling this multiple times with multiple rect 112 | // arrays will probably produce worse packing results than calling it 113 | // a single time with the full rectangle array, but the option is 114 | // available. 115 | // 116 | // The function returns 1 if all of the rectangles were successfully 117 | // packed and 0 otherwise. 118 | 119 | struct stbrp_rect 120 | { 121 | // reserved for your use: 122 | int id; 123 | 124 | // input: 125 | stbrp_coord w, h; 126 | 127 | // output: 128 | stbrp_coord x, y; 129 | int was_packed; // non-zero if valid packing 130 | 131 | }; // 16 bytes, nominally 132 | 133 | 134 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 135 | // Initialize a rectangle packer to: 136 | // pack a rectangle that is 'width' by 'height' in dimensions 137 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 138 | // 139 | // You must call this function every time you start packing into a new target. 140 | // 141 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 142 | // the following stbrp_pack_rects() call (or calls), but can be freed after 143 | // the call (or calls) finish. 144 | // 145 | // Note: to guarantee best results, either: 146 | // 1. make sure 'num_nodes' >= 'width' 147 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 148 | // 149 | // If you don't do either of the above things, widths will be quantized to multiples 150 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 151 | // 152 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 153 | // may run out of temporary storage and be unable to pack some rectangles. 154 | 155 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 156 | // Optionally call this function after init but before doing any packing to 157 | // change the handling of the out-of-temp-memory scenario, described above. 158 | // If you call init again, this will be reset to the default (false). 159 | 160 | 161 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 162 | // Optionally select which packing heuristic the library should use. Different 163 | // heuristics will produce better/worse results for different data sets. 164 | // If you call init again, this will be reset to the default. 165 | 166 | enum 167 | { 168 | STBRP_HEURISTIC_Skyline_default=0, 169 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 170 | STBRP_HEURISTIC_Skyline_BF_sortHeight 171 | }; 172 | 173 | 174 | ////////////////////////////////////////////////////////////////////////////// 175 | // 176 | // the details of the following structures don't matter to you, but they must 177 | // be visible so you can handle the memory allocations for them 178 | 179 | struct stbrp_node 180 | { 181 | stbrp_coord x,y; 182 | stbrp_node *next; 183 | }; 184 | 185 | struct stbrp_context 186 | { 187 | int width; 188 | int height; 189 | int align; 190 | int init_mode; 191 | int heuristic; 192 | int num_nodes; 193 | stbrp_node *active_head; 194 | stbrp_node *free_head; 195 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 196 | }; 197 | 198 | #ifdef __cplusplus 199 | } 200 | #endif 201 | 202 | #endif 203 | 204 | ////////////////////////////////////////////////////////////////////////////// 205 | // 206 | // IMPLEMENTATION SECTION 207 | // 208 | 209 | #ifdef STB_RECT_PACK_IMPLEMENTATION 210 | #ifndef STBRP_SORT 211 | #include 212 | #define STBRP_SORT qsort 213 | #endif 214 | 215 | #ifndef STBRP_ASSERT 216 | #include 217 | #define STBRP_ASSERT assert 218 | #endif 219 | 220 | #ifdef _MSC_VER 221 | #define STBRP__NOTUSED(v) (void)(v) 222 | #define STBRP__CDECL __cdecl 223 | #else 224 | #define STBRP__NOTUSED(v) (void)sizeof(v) 225 | #define STBRP__CDECL 226 | #endif 227 | 228 | enum 229 | { 230 | STBRP__INIT_skyline = 1 231 | }; 232 | 233 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 234 | { 235 | switch (context->init_mode) { 236 | case STBRP__INIT_skyline: 237 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 238 | context->heuristic = heuristic; 239 | break; 240 | default: 241 | STBRP_ASSERT(0); 242 | } 243 | } 244 | 245 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 246 | { 247 | if (allow_out_of_mem) 248 | // if it's ok to run out of memory, then don't bother aligning them; 249 | // this gives better packing, but may fail due to OOM (even though 250 | // the rectangles easily fit). @TODO a smarter approach would be to only 251 | // quantize once we've hit OOM, then we could get rid of this parameter. 252 | context->align = 1; 253 | else { 254 | // if it's not ok to run out of memory, then quantize the widths 255 | // so that num_nodes is always enough nodes. 256 | // 257 | // I.e. num_nodes * align >= width 258 | // align >= width / num_nodes 259 | // align = ceil(width/num_nodes) 260 | 261 | context->align = (context->width + context->num_nodes-1) / context->num_nodes; 262 | } 263 | } 264 | 265 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 266 | { 267 | int i; 268 | 269 | for (i=0; i < num_nodes-1; ++i) 270 | nodes[i].next = &nodes[i+1]; 271 | nodes[i].next = NULL; 272 | context->init_mode = STBRP__INIT_skyline; 273 | context->heuristic = STBRP_HEURISTIC_Skyline_default; 274 | context->free_head = &nodes[0]; 275 | context->active_head = &context->extra[0]; 276 | context->width = width; 277 | context->height = height; 278 | context->num_nodes = num_nodes; 279 | stbrp_setup_allow_out_of_mem(context, 0); 280 | 281 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) 282 | context->extra[0].x = 0; 283 | context->extra[0].y = 0; 284 | context->extra[0].next = &context->extra[1]; 285 | context->extra[1].x = (stbrp_coord) width; 286 | context->extra[1].y = (1<<30); 287 | context->extra[1].next = NULL; 288 | } 289 | 290 | // find minimum y position if it starts at x1 291 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 292 | { 293 | stbrp_node *node = first; 294 | int x1 = x0 + width; 295 | int min_y, visited_width, waste_area; 296 | 297 | STBRP__NOTUSED(c); 298 | 299 | STBRP_ASSERT(first->x <= x0); 300 | 301 | #if 0 302 | // skip in case we're past the node 303 | while (node->next->x <= x0) 304 | ++node; 305 | #else 306 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 307 | #endif 308 | 309 | STBRP_ASSERT(node->x <= x0); 310 | 311 | min_y = 0; 312 | waste_area = 0; 313 | visited_width = 0; 314 | while (node->x < x1) { 315 | if (node->y > min_y) { 316 | // raise min_y higher. 317 | // we've accounted for all waste up to min_y, 318 | // but we'll now add more waste for everything we've visted 319 | waste_area += visited_width * (node->y - min_y); 320 | min_y = node->y; 321 | // the first time through, visited_width might be reduced 322 | if (node->x < x0) 323 | visited_width += node->next->x - x0; 324 | else 325 | visited_width += node->next->x - node->x; 326 | } else { 327 | // add waste area 328 | int under_width = node->next->x - node->x; 329 | if (under_width + visited_width > width) 330 | under_width = width - visited_width; 331 | waste_area += under_width * (min_y - node->y); 332 | visited_width += under_width; 333 | } 334 | node = node->next; 335 | } 336 | 337 | *pwaste = waste_area; 338 | return min_y; 339 | } 340 | 341 | typedef struct 342 | { 343 | int x,y; 344 | stbrp_node **prev_link; 345 | } stbrp__findresult; 346 | 347 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 348 | { 349 | int best_waste = (1<<30), best_x, best_y = (1 << 30); 350 | stbrp__findresult fr; 351 | stbrp_node **prev, *node, *tail, **best = NULL; 352 | 353 | // align to multiple of c->align 354 | width = (width + c->align - 1); 355 | width -= width % c->align; 356 | STBRP_ASSERT(width % c->align == 0); 357 | 358 | // if it can't possibly fit, bail immediately 359 | if (width > c->width || height > c->height) { 360 | fr.prev_link = NULL; 361 | fr.x = fr.y = 0; 362 | return fr; 363 | } 364 | 365 | node = c->active_head; 366 | prev = &c->active_head; 367 | while (node->x + width <= c->width) { 368 | int y,waste; 369 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 370 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 371 | // bottom left 372 | if (y < best_y) { 373 | best_y = y; 374 | best = prev; 375 | } 376 | } else { 377 | // best-fit 378 | if (y + height <= c->height) { 379 | // can only use it if it first vertically 380 | if (y < best_y || (y == best_y && waste < best_waste)) { 381 | best_y = y; 382 | best_waste = waste; 383 | best = prev; 384 | } 385 | } 386 | } 387 | prev = &node->next; 388 | node = node->next; 389 | } 390 | 391 | best_x = (best == NULL) ? 0 : (*best)->x; 392 | 393 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 394 | // 395 | // e.g, if fitting 396 | // 397 | // ____________________ 398 | // |____________________| 399 | // 400 | // into 401 | // 402 | // | | 403 | // | ____________| 404 | // |____________| 405 | // 406 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 407 | // 408 | // This makes BF take about 2x the time 409 | 410 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 411 | tail = c->active_head; 412 | node = c->active_head; 413 | prev = &c->active_head; 414 | // find first node that's admissible 415 | while (tail->x < width) 416 | tail = tail->next; 417 | while (tail) { 418 | int xpos = tail->x - width; 419 | int y,waste; 420 | STBRP_ASSERT(xpos >= 0); 421 | // find the left position that matches this 422 | while (node->next->x <= xpos) { 423 | prev = &node->next; 424 | node = node->next; 425 | } 426 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 427 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 428 | if (y + height <= c->height) { 429 | if (y <= best_y) { 430 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 431 | best_x = xpos; 432 | //STBRP_ASSERT(y <= best_y); [DEAR IMGUI] 433 | best_y = y; 434 | best_waste = waste; 435 | best = prev; 436 | } 437 | } 438 | } 439 | tail = tail->next; 440 | } 441 | } 442 | 443 | fr.prev_link = best; 444 | fr.x = best_x; 445 | fr.y = best_y; 446 | return fr; 447 | } 448 | 449 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 450 | { 451 | // find best position according to heuristic 452 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 453 | stbrp_node *node, *cur; 454 | 455 | // bail if: 456 | // 1. it failed 457 | // 2. the best node doesn't fit (we don't always check this) 458 | // 3. we're out of memory 459 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 460 | res.prev_link = NULL; 461 | return res; 462 | } 463 | 464 | // on success, create new node 465 | node = context->free_head; 466 | node->x = (stbrp_coord) res.x; 467 | node->y = (stbrp_coord) (res.y + height); 468 | 469 | context->free_head = node->next; 470 | 471 | // insert the new node into the right starting point, and 472 | // let 'cur' point to the remaining nodes needing to be 473 | // stiched back in 474 | 475 | cur = *res.prev_link; 476 | if (cur->x < res.x) { 477 | // preserve the existing one, so start testing with the next one 478 | stbrp_node *next = cur->next; 479 | cur->next = node; 480 | cur = next; 481 | } else { 482 | *res.prev_link = node; 483 | } 484 | 485 | // from here, traverse cur and free the nodes, until we get to one 486 | // that shouldn't be freed 487 | while (cur->next && cur->next->x <= res.x + width) { 488 | stbrp_node *next = cur->next; 489 | // move the current node to the free list 490 | cur->next = context->free_head; 491 | context->free_head = cur; 492 | cur = next; 493 | } 494 | 495 | // stitch the list back in 496 | node->next = cur; 497 | 498 | if (cur->x < res.x + width) 499 | cur->x = (stbrp_coord) (res.x + width); 500 | 501 | #ifdef _DEBUG 502 | cur = context->active_head; 503 | while (cur->x < context->width) { 504 | STBRP_ASSERT(cur->x < cur->next->x); 505 | cur = cur->next; 506 | } 507 | STBRP_ASSERT(cur->next == NULL); 508 | 509 | { 510 | int count=0; 511 | cur = context->active_head; 512 | while (cur) { 513 | cur = cur->next; 514 | ++count; 515 | } 516 | cur = context->free_head; 517 | while (cur) { 518 | cur = cur->next; 519 | ++count; 520 | } 521 | STBRP_ASSERT(count == context->num_nodes+2); 522 | } 523 | #endif 524 | 525 | return res; 526 | } 527 | 528 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b) 529 | { 530 | const stbrp_rect *p = (const stbrp_rect *) a; 531 | const stbrp_rect *q = (const stbrp_rect *) b; 532 | if (p->h > q->h) 533 | return -1; 534 | if (p->h < q->h) 535 | return 1; 536 | return (p->w > q->w) ? -1 : (p->w < q->w); 537 | } 538 | 539 | static int STBRP__CDECL rect_original_order(const void *a, const void *b) 540 | { 541 | const stbrp_rect *p = (const stbrp_rect *) a; 542 | const stbrp_rect *q = (const stbrp_rect *) b; 543 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 544 | } 545 | 546 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 547 | { 548 | int i, all_rects_packed = 1; 549 | 550 | // we use the 'was_packed' field internally to allow sorting/unsorting 551 | for (i=0; i < num_rects; ++i) { 552 | rects[i].was_packed = i; 553 | } 554 | 555 | // sort according to heuristic 556 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 557 | 558 | for (i=0; i < num_rects; ++i) { 559 | if (rects[i].w == 0 || rects[i].h == 0) { 560 | rects[i].x = rects[i].y = 0; // empty rect needs no space 561 | } else { 562 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 563 | if (fr.prev_link) { 564 | rects[i].x = (stbrp_coord) fr.x; 565 | rects[i].y = (stbrp_coord) fr.y; 566 | } else { 567 | rects[i].x = rects[i].y = STBRP__MAXVAL; 568 | } 569 | } 570 | } 571 | 572 | // unsort 573 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 574 | 575 | // set was_packed flags and all_rects_packed status 576 | for (i=0; i < num_rects; ++i) { 577 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 578 | if (!rects[i].was_packed) 579 | all_rects_packed = 0; 580 | } 581 | 582 | // return the all_rects_packed status 583 | return all_rects_packed; 584 | } 585 | #endif 586 | 587 | /* 588 | ------------------------------------------------------------------------------ 589 | This software is available under 2 licenses -- choose whichever you prefer. 590 | ------------------------------------------------------------------------------ 591 | ALTERNATIVE A - MIT License 592 | Copyright (c) 2017 Sean Barrett 593 | Permission is hereby granted, free of charge, to any person obtaining a copy of 594 | this software and associated documentation files (the "Software"), to deal in 595 | the Software without restriction, including without limitation the rights to 596 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 597 | of the Software, and to permit persons to whom the Software is furnished to do 598 | so, subject to the following conditions: 599 | The above copyright notice and this permission notice shall be included in all 600 | copies or substantial portions of the Software. 601 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 602 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 603 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 604 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 605 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 606 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 607 | SOFTWARE. 608 | ------------------------------------------------------------------------------ 609 | ALTERNATIVE B - Public Domain (www.unlicense.org) 610 | This is free and unencumbered software released into the public domain. 611 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 612 | software, either in source code form or as a compiled binary, for any purpose, 613 | commercial or non-commercial, and by any means. 614 | In jurisdictions that recognize copyright laws, the author or authors of this 615 | software dedicate any and all copyright interest in the software to the public 616 | domain. We make this dedication for the benefit of the public at large and to 617 | the detriment of our heirs and successors. We intend this dedication to be an 618 | overt act of relinquishment in perpetuity of all present and future rights to 619 | this software under copyright law. 620 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 621 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 622 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 623 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 624 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 625 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 626 | ------------------------------------------------------------------------------ 627 | */ 628 | -------------------------------------------------------------------------------- /src/Dependencies/include/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /src/Dependencies/lib/imgui.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axxo1337/OpenGL-Hk/59d2efbd57360023d58b9ce663d5cf64887c236f/src/Dependencies/lib/imgui.lib -------------------------------------------------------------------------------- /src/Dependencies/lib/libMinHook-x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/axxo1337/OpenGL-Hk/59d2efbd57360023d58b9ce663d5cf64887c236f/src/Dependencies/lib/libMinHook-x64.lib -------------------------------------------------------------------------------- /src/GUI.cpp: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | 3 | static bool is_init{}; 4 | static bool do_draw{true}; 5 | 6 | // 7 | // Management functions 8 | // 9 | 10 | bool GUI::init(HWND wnd_handle) 11 | { 12 | if (is_init) 13 | return false; 14 | 15 | ImGui::CreateContext(); 16 | ImGuiIO& io = ImGui::GetIO(); (void)io; 17 | ImGui::StyleColorsDark(); 18 | ImGui_ImplWin32_Init(wnd_handle); 19 | ImGui_ImplOpenGL3_Init(); 20 | 21 | is_init = true; 22 | 23 | return false; 24 | } 25 | 26 | void GUI::shutdown() 27 | { 28 | if (!is_init) 29 | return; 30 | 31 | ImGui_ImplOpenGL3_Shutdown(); 32 | ImGui_ImplWin32_Shutdown(); 33 | ImGui::DestroyContext(); 34 | 35 | is_init = false; 36 | } 37 | 38 | // 39 | // Global functions 40 | // 41 | 42 | void GUI::draw() 43 | { 44 | if (!do_draw) 45 | return; 46 | 47 | printf("TEST\n"); 48 | 49 | ImGui_ImplOpenGL3_NewFrame(); 50 | ImGui_ImplWin32_NewFrame(); 51 | ImGui::NewFrame(); 52 | ImGui::Begin("OpenGL-Hk"); 53 | { 54 | ImGui::Text("Hello, World!"); 55 | } 56 | ImGui::End(); 57 | ImGui::EndFrame(); 58 | ImGui::Render(); 59 | ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); 60 | } 61 | 62 | // 63 | // Get & Set functions 64 | // 65 | 66 | bool GUI::getIsInit() 67 | { 68 | return is_init; 69 | } 70 | 71 | bool GUI::getDoDraw() 72 | { 73 | return do_draw; 74 | } 75 | 76 | void GUI::setDoDraw(bool new_value) 77 | { 78 | do_draw = new_value; 79 | } 80 | -------------------------------------------------------------------------------- /src/GUI.h: -------------------------------------------------------------------------------- 1 | #ifndef GUI_H_ 2 | #define GUI_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace GUI 12 | { 13 | // 14 | // Management functions 15 | // 16 | 17 | bool init(HWND wnd_handle); 18 | void shutdown(); 19 | 20 | // 21 | // Global functions 22 | // 23 | 24 | void draw(); 25 | 26 | // 27 | // Get & Set functions 28 | // 29 | 30 | bool getIsInit(); 31 | bool getDoDraw(); 32 | 33 | void setDoDraw(bool new_value); 34 | } 35 | 36 | #endif -------------------------------------------------------------------------------- /src/Hook.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Hook.h" 5 | #include "GUI.h" 6 | 7 | typedef BOOL(__stdcall* TWglSwapBuffers) (HDC hDc); 8 | 9 | static bool is_init{}; 10 | static HWND wnd_handle{}; 11 | static WNDPROC origin_wndproc{}; 12 | void* p_swap_buffers{}; 13 | TWglSwapBuffers origin_wglSwapBuffers{}; 14 | 15 | static LRESULT __stdcall WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 16 | static bool __stdcall wglSwapBuffers(HDC hDc); 17 | 18 | // 19 | // Management functions 20 | // 21 | 22 | bool Hook::init() 23 | { 24 | if (is_init) 25 | return false; 26 | 27 | /* WndProc */ 28 | { 29 | // Older versions of mincraft 30 | wnd_handle = FindWindowA("LWJGL", nullptr); 31 | 32 | /* If failed to get window handle, attempt using window class used by more recent versions of minecraft */ 33 | if (!wnd_handle) 34 | { 35 | wnd_handle = FindWindowA("GLFW30", nullptr); 36 | 37 | /* At this point cannot find minecraft window */ 38 | if (!wnd_handle) 39 | { 40 | printf("[-] Failed to get window handle\n"); 41 | return true; 42 | } 43 | } 44 | 45 | origin_wndproc = (WNDPROC)SetWindowLongPtrW(wnd_handle, GWLP_WNDPROC, (LONG_PTR)WndProc); 46 | } 47 | 48 | MH_Initialize(); 49 | 50 | /* wglSwapBuffers */ 51 | { 52 | p_swap_buffers = (void*)GetProcAddress(GetModuleHandleA("opengl32.dll"), "wglSwapBuffers"); 53 | 54 | if (p_swap_buffers == nullptr) 55 | { 56 | printf("[-] Failed to get wglSwapBuffers' address\n"); 57 | return true; 58 | } 59 | 60 | MH_CreateHook(p_swap_buffers, &wglSwapBuffers, (LPVOID*)&origin_wglSwapBuffers); 61 | } 62 | 63 | MH_EnableHook(MH_ALL_HOOKS); 64 | 65 | is_init = true; 66 | 67 | return false; 68 | } 69 | 70 | void Hook::shutdown() 71 | { 72 | if (!is_init) 73 | return; 74 | 75 | SetWindowLongPtrW(wnd_handle, GWLP_WNDPROC, (LONG_PTR)origin_wndproc); 76 | MH_DisableHook(MH_ALL_HOOKS); 77 | MH_RemoveHook(MH_ALL_HOOKS); 78 | 79 | is_init = false; 80 | } 81 | 82 | // 83 | // Get functions 84 | // 85 | 86 | bool Hook::getIsInit() 87 | { 88 | return is_init; 89 | } 90 | 91 | // 92 | // Hooks 93 | // 94 | 95 | extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 96 | LRESULT __stdcall WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 97 | { 98 | if (GUI::getIsInit()) 99 | { 100 | /* If VK_INSERT, change menu draw state */ 101 | if (msg == WM_KEYDOWN && wParam == VK_INSERT) 102 | GUI::setDoDraw(!GUI::getDoDraw()); 103 | 104 | if (GUI::getDoDraw() && ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) 105 | return true; 106 | } 107 | 108 | return CallWindowProcA(origin_wndproc, hWnd, msg, wParam, lParam); 109 | } 110 | 111 | bool __stdcall wglSwapBuffers(HDC hDc) 112 | { 113 | HGLRC origin_context{ wglGetCurrentContext() }; 114 | static HGLRC new_context{}; 115 | 116 | if (static bool was_init{}; was_init == false) 117 | { 118 | new_context = wglCreateContext(hDc); 119 | wglMakeCurrent(hDc, new_context); 120 | 121 | GLint viewport[4]; 122 | glGetIntegerv(GL_VIEWPORT, viewport); 123 | glViewport(0, 0, viewport[2], viewport[3]); 124 | glMatrixMode(GL_PROJECTION); 125 | glLoadIdentity(); 126 | glOrtho(0, viewport[2], viewport[3], 0, -1, 1); 127 | glMatrixMode(GL_MODELVIEW); 128 | glLoadIdentity(); 129 | glDisable(GL_DEPTH_TEST); 130 | 131 | GUI::init(wnd_handle); 132 | 133 | was_init = true; 134 | } 135 | else 136 | { 137 | wglMakeCurrent(hDc, new_context); 138 | GUI::draw(); 139 | } 140 | 141 | wglMakeCurrent(hDc, origin_context); 142 | 143 | return origin_wglSwapBuffers(hDc); 144 | } 145 | -------------------------------------------------------------------------------- /src/Hook.h: -------------------------------------------------------------------------------- 1 | #ifndef HOOK_H_ 2 | #define HOOK_H_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | namespace Hook 9 | { 10 | // 11 | // Management functions 12 | // 13 | 14 | bool init(); 15 | void shutdown(); 16 | 17 | // 18 | // Get functions 19 | // 20 | 21 | bool getIsInit(); 22 | } 23 | 24 | #endif -------------------------------------------------------------------------------- /src/OpenGL-Hk.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.32112.339 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenGL-Hk", "OpenGL-Hk.vcxproj", "{F79D457C-9DD1-429F-A949-BBB72B02F574}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F79D457C-9DD1-429F-A949-BBB72B02F574}.Debug|x64.ActiveCfg = Debug|x64 17 | {F79D457C-9DD1-429F-A949-BBB72B02F574}.Debug|x64.Build.0 = Debug|x64 18 | {F79D457C-9DD1-429F-A949-BBB72B02F574}.Debug|x86.ActiveCfg = Debug|Win32 19 | {F79D457C-9DD1-429F-A949-BBB72B02F574}.Debug|x86.Build.0 = Debug|Win32 20 | {F79D457C-9DD1-429F-A949-BBB72B02F574}.Release|x64.ActiveCfg = Release|x64 21 | {F79D457C-9DD1-429F-A949-BBB72B02F574}.Release|x64.Build.0 = Release|x64 22 | {F79D457C-9DD1-429F-A949-BBB72B02F574}.Release|x86.ActiveCfg = Release|Win32 23 | {F79D457C-9DD1-429F-A949-BBB72B02F574}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {7EF777DD-4C3D-4BDE-96A4-A98B7FE44874} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /src/OpenGL-Hk.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {f79d457c-9dd1-429f-a949-bbb72b02f574} 25 | OpenGLHk 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | stdcpp17 120 | true 121 | $(SolutionDir)Dependencies\include 122 | 123 | 124 | Windows 125 | true 126 | $(SolutionDir)Dependencies\lib 127 | $(CoreLibraryDependencies);%(AdditionalDependencies);opengl32.lib;imgui.lib;libMinHook-x64.lib 128 | 129 | 130 | 131 | 132 | Level3 133 | true 134 | true 135 | true 136 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 137 | true 138 | stdcpp17 139 | true 140 | $(SolutionDir)Dependencies\include 141 | 142 | 143 | Windows 144 | true 145 | true 146 | true 147 | $(SolutionDir)Dependencies\lib 148 | $(CoreLibraryDependencies);%(AdditionalDependencies);opengl32.lib;imgui.lib;libMinHook-x64.lib 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /src/OpenGL-Hk.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Dependencies\ImGui 7 | 8 | 9 | Dependencies\ImGui 10 | 11 | 12 | Hook 13 | 14 | 15 | GUI 16 | 17 | 18 | 19 | 20 | {d5c61b2e-fc4a-4f14-9689-1376e19ca7a7} 21 | 22 | 23 | {4a96feb9-c21a-48c4-abe6-93c8405d4ed5} 24 | 25 | 26 | {db35df7d-97f2-45a5-ad23-88cb3816d874} 27 | 28 | 29 | {1a2b9cf3-1b07-4ef6-abad-9589822a24e9} 30 | 31 | 32 | 33 | 34 | Dependencies\ImGui 35 | 36 | 37 | Dependencies\ImGui 38 | 39 | 40 | Dependencies\ImGui 41 | 42 | 43 | Dependencies\ImGui 44 | 45 | 46 | Dependencies\ImGui 47 | 48 | 49 | Dependencies\ImGui 50 | 51 | 52 | Dependencies\ImGui 53 | 54 | 55 | Dependencies\ImGui 56 | 57 | 58 | Dependencies\ImGui 59 | 60 | 61 | Dependencies\ImGui 62 | 63 | 64 | Hook 65 | 66 | 67 | GUI 68 | 69 | 70 | Dependencies 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "Hook.h" 7 | 8 | void __stdcall MainThread(HINSTANCE instance) 9 | { 10 | if (Hook::init()) 11 | goto _shutdown; 12 | 13 | while (!GetAsyncKeyState(VK_END)) 14 | { 15 | std::this_thread::sleep_for(std::chrono::milliseconds(25)); 16 | } 17 | 18 | _shutdown: 19 | Hook::shutdown(); 20 | FreeLibrary(instance); 21 | } 22 | 23 | bool __stdcall DllMain(HINSTANCE instance, DWORD reason, LPVOID p_reserved) 24 | { 25 | if (reason == DLL_PROCESS_ATTACH) 26 | { 27 | DisableThreadLibraryCalls(instance); 28 | 29 | AllocConsole(); 30 | freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); 31 | 32 | /* Create, join and detach thread */ 33 | if (static std::thread main_thread([instance] { MainThread(instance); }); main_thread.joinable()) 34 | main_thread.detach(); 35 | } 36 | else if (reason == DLL_PROCESS_DETACH) 37 | { 38 | FreeConsole(); 39 | fclose(stdout); 40 | } 41 | 42 | return true; 43 | } 44 | --------------------------------------------------------------------------------