├── ColorAimbot.cpp ├── Core ├── FastFind.cpp ├── FastFind.h ├── GUI.cpp ├── GUI.h ├── IOManagement.cpp └── IOManagement.h ├── ImGui ├── imconfig.h ├── imgui.cpp ├── imgui.h ├── imgui_demo.cpp ├── imgui_draw.cpp ├── imgui_impl_dx11.cpp ├── imgui_impl_dx11.h ├── imgui_impl_win32.cpp ├── imgui_impl_win32.h ├── imgui_internal.h ├── imgui_tables.cpp ├── imgui_widgets.cpp ├── imstb_rectpack.h ├── imstb_textedit.h └── imstb_truetype.h ├── Menu.png ├── README.md └── Utilities ├── Colors.h ├── SimpleIni.h ├── User.cpp ├── User.h ├── VKNames.h ├── interception.h └── skCrypter.h /ColorAimbot.cpp: -------------------------------------------------------------------------------- 1 | // ColorAimbot.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 | // 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Core/IOManagement.h" 8 | #include "Core/FastFind.h" 9 | #include "Core/GUI.h" 10 | #include "Utilities/User.h" 11 | 12 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) 13 | { 14 | User User; 15 | 16 | bool appRunning = true; 17 | Menu Menu(appRunning, User); 18 | Sleep(1000); 19 | User.Data.loadedApp = true; // For an animation and a little bit of time for the Menu thread 20 | 21 | FastFind FastFind(&User); 22 | Interception Mouse; 23 | 24 | const int MONITOR_CENTER_X = GetSystemMetrics(SM_CXSCREEN) / 2; 25 | const int MONITOR_CENTER_Y = GetSystemMetrics(SM_CYSCREEN) / 2; 26 | int x = MONITOR_CENTER_X - User.Aimbot.fov / 2 + User.SearchSettings.refX; 27 | int y = MONITOR_CENTER_Y - User.Aimbot.fov / 2 + User.SearchSettings.refY; 28 | 29 | while (appRunning) 30 | { 31 | Sleep(50); 32 | while (GetAsyncKeyState(User.Binds.aim) & 0x8000) 33 | { 34 | if (!FastFind.ScreenShoot()) { std::cerr << "\Screenshot failed"; continue; } 35 | if (!FastFind.ColorSearch(x, y)) { std::cerr << "\nPixelsearch failed"; continue; } 36 | 37 | // Convert to relative coordinates and apply the most basic smooth ever 38 | int relX = (x - MONITOR_CENTER_X + User.Aimbot.offsetX) * User.Aimbot.strength; 39 | int relY = (y - MONITOR_CENTER_Y + User.Aimbot.offsetY) * User.Aimbot.strength; 40 | Mouse.Aim(relX, relY); 41 | continue; 42 | } 43 | } 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /Core/FastFind.cpp: -------------------------------------------------------------------------------- 1 | #include "FastFind.h" 2 | #include "../Utilities/User.h" 3 | #include 4 | 5 | FastFind::FastFind(User* user) 6 | { 7 | std::cout << "[FastFind] Starting\n"; 8 | 9 | m_User = user; 10 | 11 | // Dinamically load FastFind functions 12 | HINSTANCE hGetProcIDDLL = LoadLibrary(L".\\FastFind64.dll"); 13 | 14 | if (!hGetProcIDDLL) { std::cout << "Could not load the dll" << std::endl; return; } 15 | 16 | m_SnapShot = (f_SnapShot)GetProcAddress(hGetProcIDDLL, "SnapShot"); 17 | m_GenericColorSearch = (f_GenericColorSearch)GetProcAddress(hGetProcIDDLL, "GenericColorSearch"); 18 | //m_SetHWnd = (f_SetHWnd)GetProcAddress(hGetProcIDDLL, "SetHWnd"); 19 | //m_AddColor = (f_AddColor)GetProcAddress(hGetProcIDDLL, "AddColor"); 20 | //m_GetPixel = (f_GetPixel)GetProcAddress(hGetProcIDDLL, "FFGetPixel"); 21 | //m_AddExcludedArea = (f_AddExcludedArea)GetProcAddress(hGetProcIDDLL, "AddExcludedArea"); 22 | 23 | if (!m_SnapShot) { std::cout << "Could not locate SnapShot" << std::endl; return; } 24 | if (!m_GenericColorSearch) { std::cout << "Could not locate GenericColorSearch" << std::endl; return; } 25 | //if (!m_SetHWnd) { std::cout << "Could not locate SetHWnd" << std::endl; return; } 26 | //if (!m_AddColor) { std::cout << "Could not locate AddColor" << std::endl; return; } 27 | //if (!m_GetPixel) { std::cout << "Could not locate GetPixel" << std::endl; return; } 28 | //if (!m_AddExcludedArea) { std::cout << "Could not locate AddExcludedArea" << std::endl; return; } 29 | 30 | std::cout << "[FastFind] Started\n"; 31 | 32 | } 33 | 34 | const int MONITOR_CENTER_X = GetSystemMetrics(SM_CXSCREEN) / 2; 35 | const int MONITOR_CENTER_Y = GetSystemMetrics(SM_CYSCREEN) / 2; 36 | 37 | const int FastFind::ScreenShoot() 38 | { 39 | // Only screenshot inside the FOV 40 | return m_SnapShot( 41 | MONITOR_CENTER_X - m_User->Aimbot.fov / 2, 42 | MONITOR_CENTER_Y - m_User->Aimbot.fov / 2, 43 | MONITOR_CENTER_X + m_User->Aimbot.fov / 2, 44 | MONITOR_CENTER_Y + m_User->Aimbot.fov / 2, 45 | 1); 46 | } 47 | 48 | const int FastFind::ColorSearch(int& x, int& y) 49 | { 50 | int minMatch = m_User->SearchSettings.minMatch; 51 | 52 | // Found 53 | if (m_GenericColorSearch(m_User->SearchSettings.sizeSearch, minMatch, x, y, m_User->SearchSettings.color, m_User->SearchSettings.colorVariation, 1)) 54 | return 1; 55 | 56 | // Not found, we reset start search position 57 | else 58 | { 59 | x = m_User->SearchSettings.prefX; 60 | y = m_User->SearchSettings.prefY; 61 | return 0; 62 | } 63 | } 64 | 65 | FastFind::~FastFind() 66 | { 67 | FreeLibrary(m_hGetProcIDDLL); 68 | } -------------------------------------------------------------------------------- /Core/FastFind.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | //https://github.com/FastFrench/FastFind 6 | 7 | typedef LPCTSTR(__stdcall* f_FFVersion)(void); 8 | typedef void(__stdcall* f_SetHWnd)(HWND NewWindowHandle, bool bClientArea); 9 | typedef int(__stdcall* f_SnapShot)(int aLeft, int aTop, int aRight, int aBottom, int NoSnapShot); 10 | typedef int(__stdcall* f_AddColor)(COLORREF NewColor); 11 | typedef int(__stdcall* f_GetPixel)(int X, int Y, int NoSnapShot); 12 | typedef void(__stdcall* f_AddExcludedArea)(int x1, int y1, int x2, int y2); 13 | /* Return value: 0 if error, 1 if found 14 | SizeSearch: size of the sub-search area 15 | NbMatchMin: minimum ammount of pixels found in the search area (replaced by ammount of matchs found) 16 | XYRef: search will return closest find to this position (replaced by position of the match) 17 | ColorToFind: color to find 0xAARRGGBB 18 | ShadeVariation: variation of the color to match from 0 to 255 19 | NoSnapShot: number of the snapshot where the search is going to take place 20 | */ 21 | typedef int(__stdcall* f_GenericColorSearch)(int SizeSearch, int& NbMatchMin, int& XRef, int& YRef, int ColorToFind, int ShadeVariation, int NoSnapShot); 22 | 23 | class User; 24 | 25 | class FastFind 26 | { 27 | public: 28 | FastFind(User* user); 29 | 30 | const int ScreenShoot(); 31 | 32 | const int ColorSearch(int& XRef, int& YRef); 33 | 34 | ~FastFind(); 35 | 36 | private: 37 | User* m_User; 38 | HINSTANCE m_hGetProcIDDLL; 39 | f_SnapShot m_SnapShot; 40 | f_GenericColorSearch m_GenericColorSearch; 41 | //f_SetHWnd m_SetHWnd; 42 | //f_AddColor m_AddColor; 43 | //f_GetPixel m_GetPixel; 44 | //f_AddExcludedArea m_AddExcludedArea; 45 | }; -------------------------------------------------------------------------------- /Core/GUI.cpp: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | #include "../Utilities/User.h" 3 | #include "../Utilities/skCrypter.h" 4 | #include "../Utilities/VKNames.h" 5 | #include "../Utilities/Colors.h" 6 | #include "../ImGui/imgui.h" 7 | #include "../ImGui/imgui_impl_win32.h" 8 | #include "../ImGui/imgui_impl_dx11.h" 9 | #include "../ImGui/imgui_internal.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 18 | LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 19 | void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr); 20 | 21 | static int ConvertToHex(float color[3]) 22 | { 23 | int A = 0xFF; 24 | int R = (int)(color[0] * 255.0f); 25 | int G = (int)(color[1] * 255.0f); 26 | int B = (int)(color[2] * 255.0f); 27 | 28 | // Move bytes to the left and merge them 29 | return (A << 24) | (R << 16) | (G << 8) | B; 30 | } 31 | 32 | static void ConvertToRGB(int hex, float color[3]) 33 | { 34 | // Move bytes to the right and extract them 35 | color[0] = ((hex >> (16)) & 0x000000ff) / 255.0f; 36 | color[1] = ((hex >> (8)) & 0x000000ff) / 255.0f; 37 | color[2] = ((hex >> (0)) & 0x000000ff) / 255.0f; 38 | }; 39 | 40 | Menu::Menu(bool& running, User& user) 41 | { 42 | m_Running = &running; 43 | m_User = &user; 44 | 45 | ConvertToRGB(m_User->SearchSettings.color, m_User->SearchSettings.colorRGB); 46 | 47 | std::thread ThreadMenu(&Menu::Start, this); 48 | ThreadMenu.detach(); 49 | } 50 | 51 | void Menu::Start() { 52 | // Create console if enabled in User.ini file 53 | if (m_User->Data.debug) 54 | { 55 | AllocConsole(); 56 | BindCrtHandlesToStdHandles(true, true, true); 57 | } 58 | 59 | // Create application window 60 | WNDCLASSEXW wc = { 61 | sizeof(wc), 62 | CS_CLASSDC, 63 | WndProc, 0L, 0L, 64 | GetModuleHandle(nullptr), 65 | nullptr, nullptr, 66 | nullptr, nullptr, 67 | L"Xbox", 68 | nullptr }; 69 | 70 | ::RegisterClassExW(&wc); 71 | int windowWidth = 320; 72 | int windowHeight = 480; 73 | 74 | HWND hwnd = ::CreateWindowW( 75 | wc.lpszClassName, 76 | _(L"Xbox"), 77 | WS_POPUP, 78 | 0, 79 | 0, 80 | windowWidth, windowHeight, 81 | nullptr, nullptr, 82 | wc.hInstance, nullptr); 83 | 84 | // Initialize Direct3D 85 | if (!CreateDeviceD3D(hwnd)) 86 | { 87 | CleanupDeviceD3D(); 88 | ::UnregisterClassW(wc.lpszClassName, wc.hInstance); 89 | std::cerr << '\n' << _("[ImGui] Could not initialize Direct3D"); 90 | return; 91 | } 92 | 93 | // Show the window 94 | bool hidden = false; 95 | ::ShowWindow(hwnd, SW_SHOWDEFAULT); 96 | ::UpdateWindow(hwnd); 97 | 98 | // Setup Dear ImGui context 99 | ImGui::CreateContext(); 100 | ImGuiIO& io = ImGui::GetIO(); (void)io; 101 | io.IniFilename = NULL; 102 | 103 | // Setup Dear ImGui style 104 | StyleMenu(); 105 | 106 | // Setup Platform/Renderer backends 107 | ImGui_ImplWin32_Init(hwnd); 108 | ImGui_ImplDX11_Init(m_pd3dDevice, m_pd3dDeviceContext); 109 | 110 | while (*m_Running) { 111 | // Poll and handle messages (inputs, window resize, etc.) 112 | // See the WndProc() function below for our to dispatch events to the Win32 backend. 113 | MSG msg; 114 | while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) 115 | { 116 | ::TranslateMessage(&msg); 117 | ::DispatchMessage(&msg); 118 | if (msg.message == WM_QUIT) 119 | *m_Running = false; 120 | } 121 | if (!*m_Running) 122 | break; 123 | 124 | if (GetAsyncKeyState(m_User->Binds.toggleMenu) & 0x01) hidden = !hidden; 125 | if (hidden) 126 | { 127 | ::ShowWindow(hwnd, SW_HIDE); 128 | Sleep(10); 129 | continue; 130 | } 131 | else ::ShowWindow(hwnd, SW_SHOWDEFAULT); 132 | 133 | // Start the Dear ImGui frame 134 | ImGui_ImplDX11_NewFrame(); 135 | ImGui_ImplWin32_NewFrame(); 136 | ImGui::NewFrame(); 137 | 138 | // Cover full viewport size 139 | ImGuiViewport* viewport = ImGui::GetMainViewport(); 140 | ImGui::SetNextWindowPos(viewport->Pos); 141 | ImGui::SetNextWindowSize(viewport->Size); 142 | 143 | // Render 144 | if(!m_User->Data.loadedApp) DrawLoading(); 145 | else DrawMenu(); 146 | 147 | // Rendering 148 | ImGui::Render(); 149 | m_pd3dDeviceContext->OMSetRenderTargets(1, &m_mainRenderTargetView, nullptr); 150 | ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); 151 | 152 | m_pSwapChain->Present(1, 0); // Present with vsync 153 | } 154 | 155 | // Cleanup 156 | ImGui_ImplDX11_Shutdown(); 157 | ImGui_ImplWin32_Shutdown(); 158 | ImGui::DestroyContext(); 159 | 160 | CleanupDeviceD3D(); 161 | ::DestroyWindow(hwnd); 162 | ::UnregisterClassW(wc.lpszClassName, wc.hInstance); 163 | } 164 | 165 | void Menu::DrawLoading() 166 | { 167 | ImGui::Begin(_(""), m_Running, 168 | ImGuiWindowFlags_NoTitleBar | 169 | ImGuiWindowFlags_NoCollapse | 170 | ImGuiWindowFlags_NoResize | 171 | ImGuiWindowFlags_NoMove); 172 | 173 | ImGui::Dummy(ImVec2(0.0f, 96.0f)); 174 | ImGui::Dummy(ImVec2(112.0f, 0.0f)); ImGui::SameLine(); 175 | ImU32 redSeny = ImGui::ColorConvertFloat4ToU32(Color::redSeny); 176 | Spinner("##LOADING", 32, 5, redSeny); 177 | 178 | ImGui::Dummy(ImVec2(0.0f, 20.0f)); 179 | ImGui::Dummy(ImVec2(112.0f, 0.0f)); ImGui::SameLine(); 180 | ImGui::Text(_("Loading")); 181 | 182 | ImGui::End(); 183 | } 184 | 185 | const int MONITOR_CENTER_X = GetSystemMetrics(SM_CXSCREEN) / 2; 186 | const int MONITOR_CENTER_Y = GetSystemMetrics(SM_CYSCREEN) / 2; 187 | 188 | //https://github.com/soufianekhiat/DearWidgets 189 | bool Slider2D(char const* pLabel, int pFov, int pSize, void* p_valueX, void* p_valueY, int p_minX, int p_maxX, int p_minY, int p_maxY) 190 | { 191 | ImGuiWindow* window = ImGui::GetCurrentWindow(); 192 | if (window->SkipItems) 193 | return false; 194 | 195 | ImGuiID const iID = ImGui::GetID(pLabel); 196 | ImGui::PushID(iID); 197 | 198 | // Render frame 199 | ImVec2 const size(pFov, pFov); 200 | ImVec2 vPos = ImGui::GetCursorScreenPos(); 201 | ImRect oRect(vPos, ImVec2(vPos.x + size.x, vPos.y + size.y)); 202 | ImU32 const uFrameCol = ImGui::GetColorU32(ImGuiCol_FrameBg); 203 | ImVec2 const vOriginPos = ImGui::GetCursorScreenPos(); 204 | ImGui::RenderFrame(oRect.Min, oRect.Max, uFrameCol, true, 0.0f); 205 | ImGui::Dummy(size); 206 | 207 | // Mouse state 208 | bool hovered, held; 209 | bool pressed = ImGui::ButtonBehavior(oRect, ImGui::GetID("##Zone"), &hovered, &held, ImGuiButtonFlags_AllowOverlap); 210 | 211 | // Update position 212 | ImU64 s_delta_x = static_cast(static_cast(p_maxX) - static_cast(p_minX)); 213 | ImU64 s_delta_y = static_cast(static_cast(p_maxY) - static_cast(p_minY)); 214 | bool bModified = false; 215 | 216 | if (hovered && held) 217 | { 218 | ImVec2 const vCursorPos = ImVec2(ImGui::GetMousePos().x - oRect.Min.x, ImGui::GetMousePos().y - oRect.Min.y); 219 | 220 | float fValueX = vCursorPos.x / (oRect.Max.x - oRect.Min.x) * static_cast(*reinterpret_cast(&s_delta_x)) + static_cast(static_cast((ImU64)p_minX)); 221 | float fValueY = vCursorPos.y / (oRect.Max.y - oRect.Min.y) * static_cast(*reinterpret_cast(&s_delta_y)) + static_cast(static_cast((ImU64)p_minY)); 222 | 223 | ImU64 s_value_x = static_cast(static_cast(fValueX)); 224 | ImU64 s_value_y = static_cast(static_cast(fValueY)); 225 | 226 | *reinterpret_cast((ImU64*)p_valueX) = *reinterpret_cast(&s_value_x); 227 | *reinterpret_cast((ImU64*)p_valueY) = *reinterpret_cast(&s_value_y); 228 | 229 | bModified = true; 230 | } 231 | 232 | // Update values 233 | ImU64 s_clamped_x = static_cast(ImClamp(*reinterpret_cast(p_valueX), static_cast(p_minX), static_cast(p_maxX))); 234 | ImU64 s_clamped_y = static_cast(ImClamp(*reinterpret_cast(p_valueY), static_cast(p_minY), static_cast(p_maxY))); 235 | *reinterpret_cast((ImU64*)p_valueX) = *reinterpret_cast(&s_clamped_x); 236 | *reinterpret_cast((ImU64*)p_valueY) = *reinterpret_cast(&s_clamped_y); 237 | 238 | float const fScaleX = (static_cast(*reinterpret_cast((ImU64*)p_valueX)) - static_cast(static_cast((ImU64)p_minX))) / static_cast(*reinterpret_cast(&s_delta_x)); 239 | float const fScaleY = (static_cast(*reinterpret_cast((ImU64*)p_valueY)) - static_cast(static_cast((ImU64)p_minY))) / static_cast(*reinterpret_cast(&s_delta_y)); 240 | 241 | ImVec2 const vCursorPos((oRect.Max.x - oRect.Min.x) * fScaleX + oRect.Min.x, (oRect.Max.y - oRect.Min.y) * fScaleY + oRect.Min.y); 242 | 243 | // Draw size search 244 | ImDrawList* pDrawList = ImGui::GetWindowDrawList(); 245 | 246 | pSize = pSize < 5 ? 5 : pSize; // Check for minimum size 247 | 248 | // Check for boundaries 249 | pDrawList->AddRectFilled( 250 | ImVec2((vCursorPos.x - pSize / 2) < oRect.Min.x ? oRect.Min.x : (vCursorPos.x - pSize / 2), // Top 251 | (vCursorPos.y - pSize / 2) < oRect.Min.y ? oRect.Min.y : (vCursorPos.y - pSize / 2)), // Left 252 | ImVec2((vCursorPos.x + pSize / 2) > oRect.Max.x ? oRect.Max.x : (vCursorPos.x + pSize / 2), // Bottom 253 | (vCursorPos.y + pSize / 2) > oRect.Max.y ? oRect.Max.y : (vCursorPos.y + pSize / 2)), // Right 254 | ImGui::ColorConvertFloat4ToU32(Color::redSeny)); 255 | 256 | ImGui::PopID(); 257 | 258 | return bModified; 259 | } 260 | 261 | void Menu::DrawMenu() { 262 | 263 | ImGui::Begin(_("Discord: tutryx"), m_Running, 264 | ImGuiWindowFlags_NoCollapse | 265 | ImGuiWindowFlags_NoResize | 266 | ImGuiWindowFlags_NoMove); 267 | 268 | ImGui::Text(_("Strength")); ImGui::SameLine(); Menu::HelpMark(_("Amount of movement produced.")); 269 | Menu::SliderPercentage(_("##STR"), &m_User->Aimbot.strength, 1.0f, 100.0f); 270 | 271 | ImGui::Text(_("FOV")); ImGui::SameLine(); Menu::HelpMark(_("Square of detection in pixels.")); 272 | if (Menu::SliderInteger(_("##FOV"), &m_User->Aimbot.fov, 1, 320)) 273 | { 274 | //PreferenceXY has to be inside FOV 275 | m_User->SearchSettings.refX = m_User->SearchSettings.refX > m_User->Aimbot.fov 276 | ? m_User->Aimbot.fov : m_User->SearchSettings.refX; 277 | m_User->SearchSettings.refY = m_User->SearchSettings.refY > m_User->Aimbot.fov 278 | ? m_User->Aimbot.fov : m_User->SearchSettings.refY; 279 | m_User->SearchSettings.prefX = MONITOR_CENTER_X - m_User->Aimbot.fov / 2 + m_User->SearchSettings.refX; 280 | m_User->SearchSettings.prefY = MONITOR_CENTER_Y - m_User->Aimbot.fov / 2 + m_User->SearchSettings.refY; 281 | 282 | // Size search can't be bigger than the FOV 283 | m_User->SearchSettings.sizeSearch = m_User->SearchSettings.sizeSearch > m_User->Aimbot.fov 284 | ? m_User->Aimbot.fov : m_User->SearchSettings.sizeSearch; 285 | } 286 | 287 | ImGui::Text(_("Offset X")); ImGui::SameLine(); Menu::HelpMark(_("Offset X from left to right.")); 288 | Menu::SliderInteger(_("##OFX"), &m_User->Aimbot.offsetX, 0, m_User->Aimbot.fov); 289 | 290 | ImGui::Text(_("Offset Y")); ImGui::SameLine(); Menu::HelpMark(_("Offset Y from top to bottom.")); 291 | Menu::SliderInteger(_("##OFY"), &m_User->Aimbot.offsetY, 0, m_User->Aimbot.fov); 292 | 293 | 294 | ImGui::Separator(); 295 | 296 | 297 | // This has been done in a hurry so the implementation can be better 298 | ImGui::Text(_("Start position of the search:")); 299 | if (Slider2D("##REF", m_User->Aimbot.fov, m_User->SearchSettings.sizeSearch, &m_User->SearchSettings.refX, &m_User->SearchSettings.refY, 0, m_User->Aimbot.fov, 0, m_User->Aimbot.fov)) 300 | { 301 | // Update PreferenceXY 302 | m_User->SearchSettings.prefX = MONITOR_CENTER_X - m_User->Aimbot.fov / 2 + m_User->SearchSettings.refX; 303 | m_User->SearchSettings.prefY = MONITOR_CENTER_Y - m_User->Aimbot.fov / 2 + m_User->SearchSettings.refY; 304 | } 305 | 306 | ImGui::Text(_("Size Search")); ImGui::SameLine(); Menu::HelpMark(_("Size of the sub-search square.")); 307 | if (Menu::SliderInteger(_("##SSN"), &m_User->SearchSettings.sizeSearch, 1, m_User->Aimbot.fov)) 308 | // Minimum Match can't be higher than the number of pixels in the sub-search square 309 | m_User->SearchSettings.minMatch = m_User->SearchSettings.minMatch > pow(m_User->SearchSettings.sizeSearch, 2) 310 | ? pow(m_User->SearchSettings.sizeSearch, 2) : m_User->SearchSettings.minMatch; 311 | 312 | ImGui::Text(_("Minimum Match")); ImGui::SameLine(); Menu::HelpMark(_("Minimum number of pixels to match.\n[CTRL + CLICK] for precise input")); 313 | Menu::SliderInteger(_("##MMN"), &m_User->SearchSettings.minMatch, 1, pow(m_User->SearchSettings.sizeSearch, 2)); 314 | 315 | ImGui::Text(_("Color variaton")); ImGui::SameLine(); Menu::HelpMark(_("Variation of the color, the more,\nthe less of a perfect match it needs\n(0 for perfect match)")); 316 | Menu::SliderInteger(_("##CVA"), &m_User->SearchSettings.colorVariation, 0, 64); 317 | 318 | if (ImGui::ColorPicker3(_("##COLOR"), m_User->SearchSettings.colorRGB, 319 | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_NoAlpha | 320 | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoOptions)) 321 | m_User->SearchSettings.color = ConvertToHex(m_User->SearchSettings.colorRGB); 322 | 323 | 324 | ImGui::Separator(); 325 | 326 | 327 | ImGui::Text(_("Aim:")); ImGui::SameLine(120.0f); 328 | Menu::HotKey(_("##HK1"), m_User->Binds.aim, ImVec2(150, 0)); 329 | 330 | ImGui::Text(_("Hide menu: ")); ImGui::SameLine(120.0f); 331 | Menu::HotKey(_("##HK2"), m_User->Binds.toggleMenu, ImVec2(150, 0)); 332 | 333 | ImGui::End(); 334 | } 335 | 336 | bool Menu::CreateDeviceD3D(HWND hWnd) { 337 | // Setup swap chain 338 | DXGI_SWAP_CHAIN_DESC sd; 339 | ZeroMemory(&sd, sizeof(sd)); 340 | sd.BufferCount = 2; 341 | sd.BufferDesc.Width = 0; 342 | sd.BufferDesc.Height = 0; 343 | sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 344 | sd.BufferDesc.RefreshRate.Numerator = 60; 345 | sd.BufferDesc.RefreshRate.Denominator = 1; 346 | sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; 347 | sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 348 | sd.OutputWindow = hWnd; 349 | sd.SampleDesc.Count = 1; 350 | sd.SampleDesc.Quality = 0; 351 | sd.Windowed = TRUE; 352 | sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 353 | 354 | UINT createDeviceFlags = 0; 355 | //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; 356 | D3D_FEATURE_LEVEL featureLevel; 357 | const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, }; 358 | HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &m_pSwapChain, &m_pd3dDevice, &featureLevel, &m_pd3dDeviceContext); 359 | if (res == DXGI_ERROR_UNSUPPORTED) // Try high-performance WARP software driver if hardware is not available. 360 | res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &m_pSwapChain, &m_pd3dDevice, &featureLevel, &m_pd3dDeviceContext); 361 | if (res != S_OK) 362 | return false; 363 | 364 | CreateRenderTarget(); 365 | return true; 366 | } 367 | 368 | void Menu::CleanupDeviceD3D() { 369 | CleanupRenderTarget(); 370 | if (m_pSwapChain) { m_pSwapChain->Release(); m_pSwapChain = nullptr; } 371 | if (m_pd3dDeviceContext) { m_pd3dDeviceContext->Release(); m_pd3dDeviceContext = nullptr; } 372 | if (m_pd3dDevice) { m_pd3dDevice->Release(); m_pd3dDevice = nullptr; } 373 | } 374 | 375 | void Menu::CreateRenderTarget() 376 | { 377 | ID3D11Texture2D* pBackBuffer; 378 | m_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); 379 | m_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &m_mainRenderTargetView); 380 | pBackBuffer->Release(); 381 | } 382 | 383 | void Menu::CleanupRenderTarget() 384 | { 385 | if (m_mainRenderTargetView) { m_mainRenderTargetView->Release(); m_mainRenderTargetView = nullptr; } 386 | } 387 | 388 | bool Menu::SliderPercentage(const char* label, float* v, float v_min, float v_max) 389 | { 390 | bool interacted = false; 391 | float f = *v * 100.0f; 392 | if (ImGui::SliderFloat(label, &f, v_min, v_max, "", ImGuiSliderFlags_AlwaysClamp)) 393 | { 394 | *v = f / 100.0f; 395 | interacted = true; 396 | } 397 | ImGui::SameLine(); ImGui::Text(_("%.0f%%"), f); 398 | return interacted; 399 | } 400 | 401 | bool Menu::SliderInteger(const char* label, int* v, int v_min, int v_max) 402 | { 403 | bool interacted = false; 404 | if(ImGui::SliderInt(label, v, v_min, v_max, "", ImGuiSliderFlags_AlwaysClamp)) interacted = true; 405 | ImGui::SameLine(); ImGui::Text(_("%d"), *v); 406 | return interacted; 407 | } 408 | 409 | // https://github.com/xvorost/ImGui-Custom-HotKeys 410 | void Menu::HotKey(const char* hkId, int& hotkey, const ImVec2& size) 411 | { 412 | const ImGuiID id = ImGui::GetID(hkId); 413 | ImGui::PushID(id); 414 | if (ImGui::GetActiveID() == id) { 415 | ImGui::SetActiveID(id, ImGui::GetCurrentWindow()); 416 | 417 | // Draw active button 418 | ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_ButtonActive)); 419 | ImGui::Button("...", size); 420 | ImGui::PopStyleColor(); 421 | 422 | // Get key 423 | for (int key = 0x01; key < 0xFF; key++) 424 | { 425 | if (!(GetAsyncKeyState(key) & 0x8000)) continue; 426 | if (key == VK_BACK) key = 0x00; // Unbind with Back space 427 | hotkey = key; 428 | ImGui::ClearActiveID(); 429 | return; 430 | } 431 | } 432 | // Draw and update button state 433 | else if (ImGui::Button(VKNames.at(hotkey), size)) { 434 | ImGui::SetActiveID(id, ImGui::GetCurrentWindow()); 435 | return; 436 | } 437 | 438 | ImGui::PopID(); 439 | return; 440 | } 441 | 442 | void Menu::HelpMark(const char* desc) { 443 | ImGui::TextDisabled("(?)"); 444 | if (ImGui::BeginItemTooltip()) 445 | { 446 | ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); 447 | ImGui::TextUnformatted(desc); 448 | ImGui::PopTextWrapPos(); 449 | ImGui::EndTooltip(); 450 | } 451 | } 452 | 453 | // https://github.com/ocornut/imgui/issues/1901#issue-335266223 454 | bool Menu::Spinner(const char* label, float radius, int thickness, const ImU32& color) { 455 | ImGuiWindow* window = ImGui::GetCurrentWindow(); 456 | if (window->SkipItems) 457 | return false; 458 | 459 | ImGuiContext& g = *GImGui; 460 | const ImGuiStyle& style = g.Style; 461 | const ImGuiID id = window->GetID(label); 462 | 463 | ImVec2 pos = window->DC.CursorPos; 464 | ImVec2 size((radius) * 2, (radius + style.FramePadding.y) * 2); 465 | 466 | const ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y)); 467 | ImGui::ItemSize(bb, style.FramePadding.y); 468 | if (!ImGui::ItemAdd(bb, id)) 469 | return false; 470 | 471 | // Render 472 | window->DrawList->PathClear(); 473 | 474 | int num_segments = 30; 475 | int start = abs(ImSin(g.Time * 1.8f) * (num_segments - 5)); 476 | 477 | const float a_min = IM_PI * 2.0f * ((float)start) / (float)num_segments; 478 | const float a_max = IM_PI * 2.0f * ((float)num_segments - 3) / (float)num_segments; 479 | 480 | const ImVec2 centre = ImVec2(pos.x + radius, pos.y + radius + style.FramePadding.y); 481 | 482 | for (int i = 0; i < num_segments; i++) 483 | { 484 | const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); 485 | window->DrawList->PathLineTo(ImVec2(centre.x + ImCos(a + g.Time * 8) * radius, 486 | centre.y + ImSin(a + g.Time * 8) * radius)); 487 | } 488 | 489 | window->DrawList->PathStroke(color, false, thickness); 490 | } 491 | 492 | void Menu::StyleMenu() 493 | { 494 | ImGuiStyle* style = &ImGui::GetStyle(); 495 | ImVec4* colors = style->Colors; 496 | 497 | colors[ImGuiCol_Text] = Color::gray200; 498 | colors[ImGuiCol_TextDisabled] = Color::gray300; 499 | colors[ImGuiCol_WindowBg] = Color::gray958; 500 | colors[ImGuiCol_ChildBg] = colors[ImGuiCol_WindowBg]; 501 | colors[ImGuiCol_PopupBg] = Color::gray900; 502 | colors[ImGuiCol_Border] = Color::gray846; 503 | colors[ImGuiCol_BorderShadow] = colors[ImGuiCol_WindowBg]; 504 | colors[ImGuiCol_FrameBg] = colors[ImGuiCol_Border]; 505 | colors[ImGuiCol_FrameBgHovered] = Color::gray700; 506 | colors[ImGuiCol_FrameBgActive] = colors[ImGuiCol_FrameBgHovered]; 507 | colors[ImGuiCol_TitleBg] = colors[ImGuiCol_PopupBg]; 508 | colors[ImGuiCol_TitleBgActive] = colors[ImGuiCol_TitleBg]; 509 | colors[ImGuiCol_TitleBgCollapsed] = colors[ImGuiCol_TitleBg]; 510 | colors[ImGuiCol_ScrollbarBg] = Color::traslucid; 511 | colors[ImGuiCol_ScrollbarGrab] = colors[ImGuiCol_FrameBg]; 512 | colors[ImGuiCol_ScrollbarGrabHovered] = colors[ImGuiCol_FrameBgHovered]; 513 | colors[ImGuiCol_ScrollbarGrabActive] = colors[ImGuiCol_FrameBgHovered]; 514 | colors[ImGuiCol_CheckMark] = Color::redSeny; 515 | colors[ImGuiCol_SliderGrab] = Color::gray600; 516 | colors[ImGuiCol_SliderGrabActive] = Color::redSeny; 517 | colors[ImGuiCol_Button] = colors[ImGuiCol_FrameBg]; 518 | colors[ImGuiCol_ButtonHovered] = colors[ImGuiCol_FrameBgHovered]; 519 | colors[ImGuiCol_ButtonActive] = colors[ImGuiCol_FrameBgHovered]; 520 | colors[ImGuiCol_Header] = colors[ImGuiCol_FrameBgHovered]; 521 | colors[ImGuiCol_HeaderHovered] = colors[ImGuiCol_FrameBgHovered]; 522 | colors[ImGuiCol_HeaderActive] = colors[ImGuiCol_FrameBgHovered]; 523 | 524 | style->WindowRounding = 0.0f; 525 | style->ScrollbarRounding = 2.0f; 526 | style->ScrollbarSize = 10.0f; 527 | } 528 | 529 | LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 530 | { 531 | if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) 532 | return true; 533 | 534 | switch (msg) 535 | { 536 | case WM_SYSCOMMAND: 537 | if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu 538 | return 0; 539 | break; 540 | case WM_DESTROY: 541 | ::PostQuitMessage(0); 542 | return 0; 543 | case WM_NCHITTEST: 544 | { // Handle WS_POPUP movement and resize 545 | constexpr int TITLEBAR = 20; 546 | constexpr int BUTTONS = 32; 547 | constexpr int BORDER = 4; 548 | 549 | RECT clientRect; 550 | GetClientRect(hWnd, &clientRect); 551 | POINT clientPoint{ LOWORD(lParam), HIWORD(lParam) }; 552 | ScreenToClient(hWnd, &clientPoint); 553 | 554 | // Handle resize by the borders 555 | /*if (clientPoint.y <= BORDER && clientPoint.x <= BORDER) return HTTOPLEFT; 556 | if (clientPoint.y <= BORDER && clientPoint.x >= (clientRect.right - BORDER)) return HTTOPRIGHT; 557 | if (clientPoint.y >= (clientRect.bottom - BORDER) && clientPoint.x <= BORDER) return HTBOTTOMLEFT; 558 | if (clientPoint.y >= (clientRect.bottom - BORDER) && clientPoint.x >= (clientRect.right - BORDER)) return HTBOTTOMRIGHT; 559 | if (clientPoint.y <= BORDER) return HTTOP; 560 | if (clientPoint.x <= BORDER) return HTLEFT; 561 | if (clientPoint.y >= (clientRect.bottom - BORDER)) return HTBOTTOM; 562 | if (clientPoint.x >= (clientRect.right - BORDER)) return HTRIGHT;*/ 563 | 564 | // Handle movement by titlebar 565 | if (clientPoint.y <= TITLEBAR && clientPoint.x < (clientRect.right - BUTTONS)) return HTCAPTION; 566 | return HTCLIENT; 567 | } 568 | case WM_GETMINMAXINFO: 569 | { 570 | MINMAXINFO* clientSize = (MINMAXINFO*)lParam; 571 | POINT minSize{ 300, 300 }; 572 | clientSize->ptMinTrackSize = minSize; 573 | break; 574 | } 575 | } 576 | return ::DefWindowProcW(hWnd, msg, wParam, lParam); 577 | } 578 | 579 | //https://stackoverflow.com/a/25927081 580 | void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) 581 | { 582 | // Re-initialize the C runtime "FILE" handles with clean handles bound to "nul". We do this because it has been 583 | // observed that the file number of our standard handle file objects can be assigned internally to a value of -2 584 | // when not bound to a valid target, which represents some kind of unknown internal invalid state. In this state our 585 | // call to "_dup2" fails, as it specifically tests to ensure that the target file number isn't equal to this value 586 | // before allowing the operation to continue. We can resolve this issue by first "re-opening" the target files to 587 | // use the "nul" device, which will place them into a valid state, after which we can redirect them to our target 588 | // using the "_dup2" function. 589 | if (bindStdIn) 590 | { 591 | FILE* dummyFile; 592 | freopen_s(&dummyFile, "nul", "r", stdin); 593 | } 594 | if (bindStdOut) 595 | { 596 | FILE* dummyFile; 597 | freopen_s(&dummyFile, "nul", "w", stdout); 598 | } 599 | if (bindStdErr) 600 | { 601 | FILE* dummyFile; 602 | freopen_s(&dummyFile, "nul", "w", stderr); 603 | } 604 | 605 | // Redirect unbuffered stdin from the current standard input handle 606 | if (bindStdIn) 607 | { 608 | HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); 609 | if (stdHandle != INVALID_HANDLE_VALUE) 610 | { 611 | int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); 612 | if (fileDescriptor != -1) 613 | { 614 | FILE* file = _fdopen(fileDescriptor, "r"); 615 | if (file != NULL) 616 | { 617 | int dup2Result = _dup2(_fileno(file), _fileno(stdin)); 618 | if (dup2Result == 0) 619 | { 620 | setvbuf(stdin, NULL, _IONBF, 0); 621 | } 622 | } 623 | } 624 | } 625 | } 626 | 627 | // Redirect unbuffered stdout to the current standard output handle 628 | if (bindStdOut) 629 | { 630 | HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); 631 | if (stdHandle != INVALID_HANDLE_VALUE) 632 | { 633 | int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); 634 | if (fileDescriptor != -1) 635 | { 636 | FILE* file = _fdopen(fileDescriptor, "w"); 637 | if (file != NULL) 638 | { 639 | int dup2Result = _dup2(_fileno(file), _fileno(stdout)); 640 | if (dup2Result == 0) 641 | { 642 | setvbuf(stdout, NULL, _IONBF, 0); 643 | } 644 | } 645 | } 646 | } 647 | } 648 | 649 | // Redirect unbuffered stderr to the current standard error handle 650 | if (bindStdErr) 651 | { 652 | HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); 653 | if (stdHandle != INVALID_HANDLE_VALUE) 654 | { 655 | int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT); 656 | if (fileDescriptor != -1) 657 | { 658 | FILE* file = _fdopen(fileDescriptor, "w"); 659 | if (file != NULL) 660 | { 661 | int dup2Result = _dup2(_fileno(file), _fileno(stderr)); 662 | if (dup2Result == 0) 663 | { 664 | setvbuf(stderr, NULL, _IONBF, 0); 665 | } 666 | } 667 | } 668 | } 669 | } 670 | 671 | // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the 672 | // standard streams before they refer to a valid target will cause the iostream objects to enter an error state. In 673 | // versions of Visual Studio after 2005, this seems to always occur during startup regardless of whether anything 674 | // has been read from or written to the targets or not. 675 | if (bindStdIn) 676 | { 677 | std::wcin.clear(); 678 | std::cin.clear(); 679 | } 680 | if (bindStdOut) 681 | { 682 | std::wcout.clear(); 683 | std::cout.clear(); 684 | } 685 | if (bindStdErr) 686 | { 687 | std::wcerr.clear(); 688 | std::cerr.clear(); 689 | } 690 | } -------------------------------------------------------------------------------- /Core/GUI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "../ImGui/imgui.h" 4 | 5 | class User; 6 | 7 | class Menu 8 | { 9 | public: 10 | Menu(bool& running, User& user); 11 | 12 | void Start(); 13 | 14 | private: 15 | bool* m_Running; 16 | User* m_User; 17 | 18 | void DrawLoading(); 19 | void DrawMenu(); 20 | 21 | ID3D11Device* m_pd3dDevice = nullptr; 22 | ID3D11DeviceContext* m_pd3dDeviceContext = nullptr; 23 | IDXGISwapChain* m_pSwapChain = nullptr; 24 | ID3D11RenderTargetView* m_mainRenderTargetView = nullptr; 25 | //UINT m_ResizeWidth, m_ResizeHeight = 0; 26 | 27 | bool CreateDeviceD3D(HWND hWnd); 28 | void CleanupDeviceD3D(); 29 | void CreateRenderTarget(); 30 | void CleanupRenderTarget(); 31 | void StyleMenu(); 32 | 33 | bool SliderPercentage(const char* label, float* v, float v_min, float v_max); 34 | bool SliderInteger(const char* label, int* v, int v_min, int v_max); 35 | void HotKey(const char* label, int& hotkey, const ImVec2& size = ImVec2(0, 0)); 36 | void HelpMark(const char* desc); 37 | bool Spinner(const char* label, float radius, int thickness, const ImU32& color); 38 | }; -------------------------------------------------------------------------------- /Core/IOManagement.cpp: -------------------------------------------------------------------------------- 1 | #include "IOManagement.h" 2 | #include "../Utilities/skCrypter.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma comment(lib, "interception.lib") 8 | 9 | Interception::Interception() { 10 | 11 | std::cerr << _("[Interception] Starting\n"); 12 | m_Context = interception_create_context(); 13 | interception_set_filter(m_Context, interception_is_mouse, INTERCEPTION_FILTER_MOUSE_MOVE); 14 | m_Device = interception_wait(m_Context); 15 | 16 | while (interception_receive(m_Context, m_Device = interception_wait(m_Context), &m_Stroke, 1) > 0) { 17 | if (interception_is_mouse(m_Device)) 18 | { 19 | InterceptionMouseStroke& mstroke = *(InterceptionMouseStroke*)&m_Stroke; 20 | interception_send(m_Context, m_Device, &m_Stroke, 1); 21 | break; 22 | } 23 | } 24 | 25 | std::thread normal(&Interception::NormalMouse, this); 26 | normal.detach(); 27 | 28 | std::cerr << _("[Interception] Started\n"); 29 | } 30 | 31 | void Interception::NormalMouse() { 32 | while (interception_receive(m_Context, m_Device = interception_wait(m_Context), &m_Stroke, 1) > 0) { 33 | if (interception_is_mouse(m_Device)) 34 | { 35 | InterceptionMouseStroke& mstroke = *(InterceptionMouseStroke*)&m_Stroke; 36 | interception_send(m_Context, m_Device, &m_Stroke, 1); 37 | } 38 | } 39 | } 40 | 41 | void Interception::Aim(int x, int y) { 42 | InterceptionMouseStroke& mstroke = *(InterceptionMouseStroke*)&m_Stroke; 43 | mstroke.flags = INTERCEPTION_MOUSE_MOVE_RELATIVE; 44 | mstroke.information = 0; 45 | mstroke.x = x; 46 | mstroke.y = y; 47 | interception_send(m_Context, m_Device, &m_Stroke, 1); 48 | } 49 | 50 | Interception::~Interception() { 51 | // Destructor 52 | } -------------------------------------------------------------------------------- /Core/IOManagement.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Utilities/interception.h" 3 | 4 | class Interception 5 | { 6 | public: 7 | Interception(); 8 | 9 | void Aim(int x, int y); 10 | 11 | ~Interception(); 12 | 13 | private: 14 | void NormalMouse(); 15 | 16 | InterceptionContext m_Context; 17 | InterceptionDevice m_Device; 18 | InterceptionStroke m_Stroke; 19 | }; -------------------------------------------------------------------------------- /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 will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions. 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 ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88). 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 | -------------------------------------------------------------------------------- /ImGui/imgui_impl_dx11.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // Learn about Dear ImGui: 11 | // - FAQ https://dearimgui.com/faq 12 | // - Getting Started https://dearimgui.com/getting-started 13 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 14 | // - Introduction, links and more at the top of imgui.cpp 15 | 16 | // CHANGELOG 17 | // (minor and older changes stripped away, please see git history for details) 18 | // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. 19 | // 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). 20 | // 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) 21 | // 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer. 22 | // 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). 23 | // 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. 24 | // 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 25 | // 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 26 | // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). 27 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 28 | // 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. 29 | // 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions. 30 | // 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example. 31 | // 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 32 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. 33 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 34 | // 2016-05-07: DirectX11: Disabling depth-write. 35 | 36 | #include "imgui.h" 37 | #ifndef IMGUI_DISABLE 38 | #include "imgui_impl_dx11.h" 39 | 40 | // DirectX 41 | #include 42 | #include 43 | #include 44 | #ifdef _MSC_VER 45 | #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. 46 | #endif 47 | 48 | // DirectX11 data 49 | struct ImGui_ImplDX11_Data 50 | { 51 | ID3D11Device* pd3dDevice; 52 | ID3D11DeviceContext* pd3dDeviceContext; 53 | IDXGIFactory* pFactory; 54 | ID3D11Buffer* pVB; 55 | ID3D11Buffer* pIB; 56 | ID3D11VertexShader* pVertexShader; 57 | ID3D11InputLayout* pInputLayout; 58 | ID3D11Buffer* pVertexConstantBuffer; 59 | ID3D11PixelShader* pPixelShader; 60 | ID3D11SamplerState* pFontSampler; 61 | ID3D11ShaderResourceView* pFontTextureView; 62 | ID3D11RasterizerState* pRasterizerState; 63 | ID3D11BlendState* pBlendState; 64 | ID3D11DepthStencilState* pDepthStencilState; 65 | int VertexBufferSize; 66 | int IndexBufferSize; 67 | 68 | ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } 69 | }; 70 | 71 | struct VERTEX_CONSTANT_BUFFER_DX11 72 | { 73 | float mvp[4][4]; 74 | }; 75 | 76 | // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts 77 | // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. 78 | static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData() 79 | { 80 | return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; 81 | } 82 | 83 | // Functions 84 | static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) 85 | { 86 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 87 | 88 | // Setup viewport 89 | D3D11_VIEWPORT vp; 90 | memset(&vp, 0, sizeof(D3D11_VIEWPORT)); 91 | vp.Width = draw_data->DisplaySize.x; 92 | vp.Height = draw_data->DisplaySize.y; 93 | vp.MinDepth = 0.0f; 94 | vp.MaxDepth = 1.0f; 95 | vp.TopLeftX = vp.TopLeftY = 0; 96 | ctx->RSSetViewports(1, &vp); 97 | 98 | // Setup shader and vertex buffers 99 | unsigned int stride = sizeof(ImDrawVert); 100 | unsigned int offset = 0; 101 | ctx->IASetInputLayout(bd->pInputLayout); 102 | ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset); 103 | ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); 104 | ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 105 | ctx->VSSetShader(bd->pVertexShader, nullptr, 0); 106 | ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer); 107 | ctx->PSSetShader(bd->pPixelShader, nullptr, 0); 108 | ctx->PSSetSamplers(0, 1, &bd->pFontSampler); 109 | ctx->GSSetShader(nullptr, nullptr, 0); 110 | ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 111 | ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 112 | ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 113 | 114 | // Setup blend state 115 | const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; 116 | ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff); 117 | ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0); 118 | ctx->RSSetState(bd->pRasterizerState); 119 | } 120 | 121 | // Render function 122 | void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) 123 | { 124 | // Avoid rendering when minimized 125 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) 126 | return; 127 | 128 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 129 | ID3D11DeviceContext* ctx = bd->pd3dDeviceContext; 130 | 131 | // Create and grow vertex/index buffers if needed 132 | if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount) 133 | { 134 | if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } 135 | bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; 136 | D3D11_BUFFER_DESC desc; 137 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 138 | desc.Usage = D3D11_USAGE_DYNAMIC; 139 | desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert); 140 | desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 141 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 142 | desc.MiscFlags = 0; 143 | if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVB) < 0) 144 | return; 145 | } 146 | if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount) 147 | { 148 | if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } 149 | bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; 150 | D3D11_BUFFER_DESC desc; 151 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 152 | desc.Usage = D3D11_USAGE_DYNAMIC; 153 | desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx); 154 | desc.BindFlags = D3D11_BIND_INDEX_BUFFER; 155 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 156 | if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0) 157 | return; 158 | } 159 | 160 | // Upload vertex/index data into a single contiguous GPU buffer 161 | D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; 162 | if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) 163 | return; 164 | if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) 165 | return; 166 | ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; 167 | ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; 168 | for (int n = 0; n < draw_data->CmdListsCount; n++) 169 | { 170 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 171 | memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); 172 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 173 | vtx_dst += cmd_list->VtxBuffer.Size; 174 | idx_dst += cmd_list->IdxBuffer.Size; 175 | } 176 | ctx->Unmap(bd->pVB, 0); 177 | ctx->Unmap(bd->pIB, 0); 178 | 179 | // Setup orthographic projection matrix into our constant buffer 180 | // 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. 181 | { 182 | D3D11_MAPPED_SUBRESOURCE mapped_resource; 183 | if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) 184 | return; 185 | VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData; 186 | float L = draw_data->DisplayPos.x; 187 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; 188 | float T = draw_data->DisplayPos.y; 189 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; 190 | float mvp[4][4] = 191 | { 192 | { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, 193 | { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, 194 | { 0.0f, 0.0f, 0.5f, 0.0f }, 195 | { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, 196 | }; 197 | memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); 198 | ctx->Unmap(bd->pVertexConstantBuffer, 0); 199 | } 200 | 201 | // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) 202 | struct BACKUP_DX11_STATE 203 | { 204 | UINT ScissorRectsCount, ViewportsCount; 205 | D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 206 | D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 207 | ID3D11RasterizerState* RS; 208 | ID3D11BlendState* BlendState; 209 | FLOAT BlendFactor[4]; 210 | UINT SampleMask; 211 | UINT StencilRef; 212 | ID3D11DepthStencilState* DepthStencilState; 213 | ID3D11ShaderResourceView* PSShaderResource; 214 | ID3D11SamplerState* PSSampler; 215 | ID3D11PixelShader* PS; 216 | ID3D11VertexShader* VS; 217 | ID3D11GeometryShader* GS; 218 | UINT PSInstancesCount, VSInstancesCount, GSInstancesCount; 219 | ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation 220 | D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; 221 | ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; 222 | UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; 223 | DXGI_FORMAT IndexBufferFormat; 224 | ID3D11InputLayout* InputLayout; 225 | }; 226 | BACKUP_DX11_STATE old = {}; 227 | old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; 228 | ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); 229 | ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); 230 | ctx->RSGetState(&old.RS); 231 | ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); 232 | ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); 233 | ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); 234 | ctx->PSGetSamplers(0, 1, &old.PSSampler); 235 | old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256; 236 | ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); 237 | ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); 238 | ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); 239 | ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount); 240 | 241 | ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); 242 | ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); 243 | ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); 244 | ctx->IAGetInputLayout(&old.InputLayout); 245 | 246 | // Setup desired DX state 247 | ImGui_ImplDX11_SetupRenderState(draw_data, ctx); 248 | 249 | // Render command lists 250 | // (Because we merged all buffers into a single one, we maintain our own offset into them) 251 | int global_idx_offset = 0; 252 | int global_vtx_offset = 0; 253 | ImVec2 clip_off = draw_data->DisplayPos; 254 | for (int n = 0; n < draw_data->CmdListsCount; n++) 255 | { 256 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 257 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 258 | { 259 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 260 | if (pcmd->UserCallback != nullptr) 261 | { 262 | // User callback, registered via ImDrawList::AddCallback() 263 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 264 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 265 | ImGui_ImplDX11_SetupRenderState(draw_data, ctx); 266 | else 267 | pcmd->UserCallback(cmd_list, pcmd); 268 | } 269 | else 270 | { 271 | // Project scissor/clipping rectangles into framebuffer space 272 | ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); 273 | ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); 274 | if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) 275 | continue; 276 | 277 | // Apply scissor/clipping rectangle 278 | const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; 279 | ctx->RSSetScissorRects(1, &r); 280 | 281 | // Bind texture, Draw 282 | ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID(); 283 | ctx->PSSetShaderResources(0, 1, &texture_srv); 284 | ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); 285 | } 286 | } 287 | global_idx_offset += cmd_list->IdxBuffer.Size; 288 | global_vtx_offset += cmd_list->VtxBuffer.Size; 289 | } 290 | 291 | // Restore modified DX state 292 | ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); 293 | ctx->RSSetViewports(old.ViewportsCount, old.Viewports); 294 | ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); 295 | ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); 296 | ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); 297 | ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); 298 | ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); 299 | ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); 300 | for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); 301 | ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); 302 | ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); 303 | ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release(); 304 | for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); 305 | ctx->IASetPrimitiveTopology(old.PrimitiveTopology); 306 | ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); 307 | ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); 308 | ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); 309 | } 310 | 311 | static void ImGui_ImplDX11_CreateFontsTexture() 312 | { 313 | // Build texture atlas 314 | ImGuiIO& io = ImGui::GetIO(); 315 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 316 | unsigned char* pixels; 317 | int width, height; 318 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 319 | 320 | // Upload texture to graphics system 321 | { 322 | D3D11_TEXTURE2D_DESC desc; 323 | ZeroMemory(&desc, sizeof(desc)); 324 | desc.Width = width; 325 | desc.Height = height; 326 | desc.MipLevels = 1; 327 | desc.ArraySize = 1; 328 | desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 329 | desc.SampleDesc.Count = 1; 330 | desc.Usage = D3D11_USAGE_DEFAULT; 331 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 332 | desc.CPUAccessFlags = 0; 333 | 334 | ID3D11Texture2D* pTexture = nullptr; 335 | D3D11_SUBRESOURCE_DATA subResource; 336 | subResource.pSysMem = pixels; 337 | subResource.SysMemPitch = desc.Width * 4; 338 | subResource.SysMemSlicePitch = 0; 339 | bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); 340 | IM_ASSERT(pTexture != nullptr); 341 | 342 | // Create texture view 343 | D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 344 | ZeroMemory(&srvDesc, sizeof(srvDesc)); 345 | srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 346 | srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 347 | srvDesc.Texture2D.MipLevels = desc.MipLevels; 348 | srvDesc.Texture2D.MostDetailedMip = 0; 349 | bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView); 350 | pTexture->Release(); 351 | } 352 | 353 | // Store our identifier 354 | io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView); 355 | 356 | // Create texture sampler 357 | // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) 358 | { 359 | D3D11_SAMPLER_DESC desc; 360 | ZeroMemory(&desc, sizeof(desc)); 361 | desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 362 | desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; 363 | desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; 364 | desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; 365 | desc.MipLODBias = 0.f; 366 | desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; 367 | desc.MinLOD = 0.f; 368 | desc.MaxLOD = 0.f; 369 | bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler); 370 | } 371 | } 372 | 373 | bool ImGui_ImplDX11_CreateDeviceObjects() 374 | { 375 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 376 | if (!bd->pd3dDevice) 377 | return false; 378 | if (bd->pFontSampler) 379 | ImGui_ImplDX11_InvalidateDeviceObjects(); 380 | 381 | // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) 382 | // If you would like to use this DX11 sample code but remove this dependency you can: 383 | // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] 384 | // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. 385 | // See https://github.com/ocornut/imgui/pull/638 for sources and details. 386 | 387 | // Create the vertex shader 388 | { 389 | static const char* vertexShader = 390 | "cbuffer vertexBuffer : register(b0) \ 391 | {\ 392 | float4x4 ProjectionMatrix; \ 393 | };\ 394 | struct VS_INPUT\ 395 | {\ 396 | float2 pos : POSITION;\ 397 | float4 col : COLOR0;\ 398 | float2 uv : TEXCOORD0;\ 399 | };\ 400 | \ 401 | struct PS_INPUT\ 402 | {\ 403 | float4 pos : SV_POSITION;\ 404 | float4 col : COLOR0;\ 405 | float2 uv : TEXCOORD0;\ 406 | };\ 407 | \ 408 | PS_INPUT main(VS_INPUT input)\ 409 | {\ 410 | PS_INPUT output;\ 411 | output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ 412 | output.col = input.col;\ 413 | output.uv = input.uv;\ 414 | return output;\ 415 | }"; 416 | 417 | ID3DBlob* vertexShaderBlob; 418 | if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr))) 419 | return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! 420 | if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &bd->pVertexShader) != S_OK) 421 | { 422 | vertexShaderBlob->Release(); 423 | return false; 424 | } 425 | 426 | // Create the input layout 427 | D3D11_INPUT_ELEMENT_DESC local_layout[] = 428 | { 429 | { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 430 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 431 | { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 432 | }; 433 | if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK) 434 | { 435 | vertexShaderBlob->Release(); 436 | return false; 437 | } 438 | vertexShaderBlob->Release(); 439 | 440 | // Create the constant buffer 441 | { 442 | D3D11_BUFFER_DESC desc; 443 | desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX11); 444 | desc.Usage = D3D11_USAGE_DYNAMIC; 445 | desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 446 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 447 | desc.MiscFlags = 0; 448 | bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer); 449 | } 450 | } 451 | 452 | // Create the pixel shader 453 | { 454 | static const char* pixelShader = 455 | "struct PS_INPUT\ 456 | {\ 457 | float4 pos : SV_POSITION;\ 458 | float4 col : COLOR0;\ 459 | float2 uv : TEXCOORD0;\ 460 | };\ 461 | sampler sampler0;\ 462 | Texture2D texture0;\ 463 | \ 464 | float4 main(PS_INPUT input) : SV_Target\ 465 | {\ 466 | float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ 467 | return out_col; \ 468 | }"; 469 | 470 | ID3DBlob* pixelShaderBlob; 471 | if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr))) 472 | return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! 473 | if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &bd->pPixelShader) != S_OK) 474 | { 475 | pixelShaderBlob->Release(); 476 | return false; 477 | } 478 | pixelShaderBlob->Release(); 479 | } 480 | 481 | // Create the blending setup 482 | { 483 | D3D11_BLEND_DESC desc; 484 | ZeroMemory(&desc, sizeof(desc)); 485 | desc.AlphaToCoverageEnable = false; 486 | desc.RenderTarget[0].BlendEnable = true; 487 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; 488 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 489 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; 490 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; 491 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; 492 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 493 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 494 | bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState); 495 | } 496 | 497 | // Create the rasterizer state 498 | { 499 | D3D11_RASTERIZER_DESC desc; 500 | ZeroMemory(&desc, sizeof(desc)); 501 | desc.FillMode = D3D11_FILL_SOLID; 502 | desc.CullMode = D3D11_CULL_NONE; 503 | desc.ScissorEnable = true; 504 | desc.DepthClipEnable = true; 505 | bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState); 506 | } 507 | 508 | // Create depth-stencil State 509 | { 510 | D3D11_DEPTH_STENCIL_DESC desc; 511 | ZeroMemory(&desc, sizeof(desc)); 512 | desc.DepthEnable = false; 513 | desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; 514 | desc.DepthFunc = D3D11_COMPARISON_ALWAYS; 515 | desc.StencilEnable = false; 516 | desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 517 | desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 518 | desc.BackFace = desc.FrontFace; 519 | bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState); 520 | } 521 | 522 | ImGui_ImplDX11_CreateFontsTexture(); 523 | 524 | return true; 525 | } 526 | 527 | void ImGui_ImplDX11_InvalidateDeviceObjects() 528 | { 529 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 530 | if (!bd->pd3dDevice) 531 | return; 532 | 533 | if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; } 534 | if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. 535 | if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } 536 | if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } 537 | if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; } 538 | if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; } 539 | if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; } 540 | if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; } 541 | if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; } 542 | if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; } 543 | if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; } 544 | } 545 | 546 | bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) 547 | { 548 | ImGuiIO& io = ImGui::GetIO(); 549 | IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); 550 | 551 | // Setup backend capabilities flags 552 | ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)(); 553 | io.BackendRendererUserData = (void*)bd; 554 | io.BackendRendererName = "imgui_impl_dx11"; 555 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 556 | 557 | // Get factory from device 558 | IDXGIDevice* pDXGIDevice = nullptr; 559 | IDXGIAdapter* pDXGIAdapter = nullptr; 560 | IDXGIFactory* pFactory = nullptr; 561 | 562 | if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) 563 | if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) 564 | if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) 565 | { 566 | bd->pd3dDevice = device; 567 | bd->pd3dDeviceContext = device_context; 568 | bd->pFactory = pFactory; 569 | } 570 | if (pDXGIDevice) pDXGIDevice->Release(); 571 | if (pDXGIAdapter) pDXGIAdapter->Release(); 572 | bd->pd3dDevice->AddRef(); 573 | bd->pd3dDeviceContext->AddRef(); 574 | 575 | return true; 576 | } 577 | 578 | void ImGui_ImplDX11_Shutdown() 579 | { 580 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 581 | IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); 582 | ImGuiIO& io = ImGui::GetIO(); 583 | 584 | ImGui_ImplDX11_InvalidateDeviceObjects(); 585 | if (bd->pFactory) { bd->pFactory->Release(); } 586 | if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } 587 | if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); } 588 | io.BackendRendererName = nullptr; 589 | io.BackendRendererUserData = nullptr; 590 | io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; 591 | IM_DELETE(bd); 592 | } 593 | 594 | void ImGui_ImplDX11_NewFrame() 595 | { 596 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 597 | IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX11_Init()?"); 598 | 599 | if (!bd->pFontSampler) 600 | ImGui_ImplDX11_CreateDeviceObjects(); 601 | } 602 | 603 | //----------------------------------------------------------------------------- 604 | 605 | #endif // #ifndef IMGUI_DISABLE 606 | -------------------------------------------------------------------------------- /ImGui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // Learn about Dear ImGui: 11 | // - FAQ https://dearimgui.com/faq 12 | // - Getting Started https://dearimgui.com/getting-started 13 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 14 | // - Introduction, links and more at the top of imgui.cpp 15 | 16 | #pragma once 17 | #include "imgui.h" // IMGUI_IMPL_API 18 | #ifndef IMGUI_DISABLE 19 | 20 | struct ID3D11Device; 21 | struct ID3D11DeviceContext; 22 | 23 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 24 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 25 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 26 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 27 | 28 | // Use if you want to reset your rendering device without losing Dear ImGui state. 29 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 30 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); 31 | 32 | #endif // #ifndef IMGUI_DISABLE 33 | -------------------------------------------------------------------------------- /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-09-07: Inputs: Added support for keyboard codepage conversion for when application is compiled in MBCS mode and using a non-Unicode window. 43 | // 2023-04-19: Added ImGui_ImplWin32_InitForOpenGL() to facilitate combining raw Win32/Winapi with OpenGL. (#3218) 44 | // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen. (#2702) 45 | // 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) 46 | // 2023-02-02: Inputs: Flipping WM_MOUSEHWHEEL (horizontal mouse-wheel) value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463) 47 | // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. 48 | // 2022-09-28: Inputs: Convert WM_CHAR values with MultiByteToWideChar() when window class was registered as MBCS (not Unicode). 49 | // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). 50 | // 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. 51 | // 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[]. 52 | // 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). 53 | // 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. 54 | // 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. 55 | // 2022-01-12: Inputs: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. 56 | // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. 57 | // 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness. 58 | // 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages. 59 | // 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus. 60 | // 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). 61 | // 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). 62 | // 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). 63 | // 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS). 64 | // 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). 65 | // 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. 66 | // 2021-01-25: Inputs: Dynamically loading XInput DLL. 67 | // 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed. 68 | // 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs) 69 | // 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions. 70 | // 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. 71 | // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. 72 | // 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). 73 | // 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent. 74 | // 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. 75 | // 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application). 76 | // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. 77 | // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. 78 | // 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads). 79 | // 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples. 80 | // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. 81 | // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). 82 | // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. 83 | // 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). 84 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 85 | // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. 86 | // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. 87 | // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. 88 | // 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read. 89 | // 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. 90 | // 2016-11-12: Inputs: Only call Win32 ::SetCursor(nullptr) when io.MouseDrawCursor is set. 91 | 92 | struct ImGui_ImplWin32_Data 93 | { 94 | HWND hWnd; 95 | HWND MouseHwnd; 96 | int MouseTrackedArea; // 0: not tracked, 1: client are, 2: non-client area 97 | int MouseButtonsDown; 98 | INT64 Time; 99 | INT64 TicksPerSecond; 100 | ImGuiMouseCursor LastMouseCursor; 101 | UINT32 KeyboardCodePage; 102 | 103 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 104 | bool HasGamepad; 105 | bool WantUpdateHasGamepad; 106 | HMODULE XInputDLL; 107 | PFN_XInputGetCapabilities XInputGetCapabilities; 108 | PFN_XInputGetState XInputGetState; 109 | #endif 110 | 111 | ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); } 112 | }; 113 | 114 | // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts 115 | // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. 116 | // FIXME: multi-context support is not well tested and probably dysfunctional in this backend. 117 | // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. 118 | static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData() 119 | { 120 | return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; 121 | } 122 | 123 | // Functions 124 | static void ImGui_ImplWin32_UpdateKeyboardCodePage() 125 | { 126 | // Retrieve keyboard code page, required for handling of non-Unicode Windows. 127 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 128 | HKL keyboard_layout = ::GetKeyboardLayout(0); 129 | LCID keyboard_lcid = MAKELCID(HIWORD(keyboard_layout), SORT_DEFAULT); 130 | if (::GetLocaleInfoA(keyboard_lcid, (LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE), (LPSTR)&bd->KeyboardCodePage, sizeof(bd->KeyboardCodePage)) == 0) 131 | bd->KeyboardCodePage = CP_ACP; // Fallback to default ANSI code page when fails. 132 | } 133 | 134 | static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc) 135 | { 136 | ImGuiIO& io = ImGui::GetIO(); 137 | IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); 138 | 139 | INT64 perf_frequency, perf_counter; 140 | if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency)) 141 | return false; 142 | if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter)) 143 | return false; 144 | 145 | // Setup backend capabilities flags 146 | ImGui_ImplWin32_Data* bd = IM_NEW(ImGui_ImplWin32_Data)(); 147 | io.BackendPlatformUserData = (void*)bd; 148 | io.BackendPlatformName = "imgui_impl_win32"; 149 | io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) 150 | io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) 151 | 152 | bd->hWnd = (HWND)hwnd; 153 | bd->TicksPerSecond = perf_frequency; 154 | bd->Time = perf_counter; 155 | bd->LastMouseCursor = ImGuiMouseCursor_COUNT; 156 | ImGui_ImplWin32_UpdateKeyboardCodePage(); 157 | 158 | // Set platform dependent data in viewport 159 | ImGui::GetMainViewport()->PlatformHandleRaw = (void*)hwnd; 160 | IM_UNUSED(platform_has_own_dc); // Used in 'docking' branch 161 | 162 | // Dynamically load XInput library 163 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 164 | bd->WantUpdateHasGamepad = true; 165 | const char* xinput_dll_names[] = 166 | { 167 | "xinput1_4.dll", // Windows 8+ 168 | "xinput1_3.dll", // DirectX SDK 169 | "xinput9_1_0.dll", // Windows Vista, Windows 7 170 | "xinput1_2.dll", // DirectX SDK 171 | "xinput1_1.dll" // DirectX SDK 172 | }; 173 | for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++) 174 | if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n])) 175 | { 176 | bd->XInputDLL = dll; 177 | bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities"); 178 | bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState"); 179 | break; 180 | } 181 | #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 182 | 183 | return true; 184 | } 185 | 186 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd) 187 | { 188 | return ImGui_ImplWin32_InitEx(hwnd, false); 189 | } 190 | 191 | IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd) 192 | { 193 | // OpenGL needs CS_OWNDC 194 | return ImGui_ImplWin32_InitEx(hwnd, true); 195 | } 196 | 197 | void ImGui_ImplWin32_Shutdown() 198 | { 199 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 200 | IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); 201 | ImGuiIO& io = ImGui::GetIO(); 202 | 203 | // Unload XInput library 204 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 205 | if (bd->XInputDLL) 206 | ::FreeLibrary(bd->XInputDLL); 207 | #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 208 | 209 | io.BackendPlatformName = nullptr; 210 | io.BackendPlatformUserData = nullptr; 211 | io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad); 212 | IM_DELETE(bd); 213 | } 214 | 215 | static bool ImGui_ImplWin32_UpdateMouseCursor() 216 | { 217 | ImGuiIO& io = ImGui::GetIO(); 218 | if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) 219 | return false; 220 | 221 | ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); 222 | if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) 223 | { 224 | // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor 225 | ::SetCursor(nullptr); 226 | } 227 | else 228 | { 229 | // Show OS mouse cursor 230 | LPTSTR win32_cursor = IDC_ARROW; 231 | switch (imgui_cursor) 232 | { 233 | case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; 234 | case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; 235 | case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; 236 | case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; 237 | case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; 238 | case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; 239 | case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; 240 | case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; 241 | case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; 242 | } 243 | ::SetCursor(::LoadCursor(nullptr, win32_cursor)); 244 | } 245 | return true; 246 | } 247 | 248 | static bool IsVkDown(int vk) 249 | { 250 | return (::GetKeyState(vk) & 0x8000) != 0; 251 | } 252 | 253 | static void ImGui_ImplWin32_AddKeyEvent(ImGuiKey key, bool down, int native_keycode, int native_scancode = -1) 254 | { 255 | ImGuiIO& io = ImGui::GetIO(); 256 | io.AddKeyEvent(key, down); 257 | io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To support legacy indexing (<1.87 user code) 258 | IM_UNUSED(native_scancode); 259 | } 260 | 261 | static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds() 262 | { 263 | // Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one. 264 | if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && !IsVkDown(VK_LSHIFT)) 265 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, false, VK_LSHIFT); 266 | if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT)) 267 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, false, VK_RSHIFT); 268 | 269 | // Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Win+V on some setups, according to GLFW). 270 | if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN)) 271 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftSuper, false, VK_LWIN); 272 | if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN)) 273 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightSuper, false, VK_RWIN); 274 | } 275 | 276 | static void ImGui_ImplWin32_UpdateKeyModifiers() 277 | { 278 | ImGuiIO& io = ImGui::GetIO(); 279 | io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL)); 280 | io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT)); 281 | io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU)); 282 | io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_APPS)); 283 | } 284 | 285 | static void ImGui_ImplWin32_UpdateMouseData() 286 | { 287 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 288 | ImGuiIO& io = ImGui::GetIO(); 289 | IM_ASSERT(bd->hWnd != 0); 290 | 291 | HWND focused_window = ::GetForegroundWindow(); 292 | const bool is_app_focused = (focused_window == bd->hWnd); 293 | if (is_app_focused) 294 | { 295 | // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) 296 | if (io.WantSetMousePos) 297 | { 298 | POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; 299 | if (::ClientToScreen(bd->hWnd, &pos)) 300 | ::SetCursorPos(pos.x, pos.y); 301 | } 302 | 303 | // (Optional) Fallback to provide mouse position when focused (WM_MOUSEMOVE already provides this when hovered or captured) 304 | // This also fills a short gap when clicking non-client area: WM_NCMOUSELEAVE -> modal OS move -> gap -> WM_NCMOUSEMOVE 305 | if (!io.WantSetMousePos && bd->MouseTrackedArea == 0) 306 | { 307 | POINT pos; 308 | if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos)) 309 | io.AddMousePosEvent((float)pos.x, (float)pos.y); 310 | } 311 | } 312 | } 313 | 314 | // Gamepad navigation mapping 315 | static void ImGui_ImplWin32_UpdateGamepads() 316 | { 317 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 318 | ImGuiIO& io = ImGui::GetIO(); 319 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 320 | //if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. 321 | // return; 322 | 323 | // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. 324 | // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. 325 | if (bd->WantUpdateHasGamepad) 326 | { 327 | XINPUT_CAPABILITIES caps = {}; 328 | bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; 329 | bd->WantUpdateHasGamepad = false; 330 | } 331 | 332 | io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; 333 | XINPUT_STATE xinput_state; 334 | XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; 335 | if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS) 336 | return; 337 | io.BackendFlags |= ImGuiBackendFlags_HasGamepad; 338 | 339 | #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) 340 | #define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); } 341 | #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)); } 342 | MAP_BUTTON(ImGuiKey_GamepadStart, XINPUT_GAMEPAD_START); 343 | MAP_BUTTON(ImGuiKey_GamepadBack, XINPUT_GAMEPAD_BACK); 344 | MAP_BUTTON(ImGuiKey_GamepadFaceLeft, XINPUT_GAMEPAD_X); 345 | MAP_BUTTON(ImGuiKey_GamepadFaceRight, XINPUT_GAMEPAD_B); 346 | MAP_BUTTON(ImGuiKey_GamepadFaceUp, XINPUT_GAMEPAD_Y); 347 | MAP_BUTTON(ImGuiKey_GamepadFaceDown, XINPUT_GAMEPAD_A); 348 | MAP_BUTTON(ImGuiKey_GamepadDpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); 349 | MAP_BUTTON(ImGuiKey_GamepadDpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); 350 | MAP_BUTTON(ImGuiKey_GamepadDpadUp, XINPUT_GAMEPAD_DPAD_UP); 351 | MAP_BUTTON(ImGuiKey_GamepadDpadDown, XINPUT_GAMEPAD_DPAD_DOWN); 352 | MAP_BUTTON(ImGuiKey_GamepadL1, XINPUT_GAMEPAD_LEFT_SHOULDER); 353 | MAP_BUTTON(ImGuiKey_GamepadR1, XINPUT_GAMEPAD_RIGHT_SHOULDER); 354 | MAP_ANALOG(ImGuiKey_GamepadL2, gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255); 355 | MAP_ANALOG(ImGuiKey_GamepadR2, gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255); 356 | MAP_BUTTON(ImGuiKey_GamepadL3, XINPUT_GAMEPAD_LEFT_THUMB); 357 | MAP_BUTTON(ImGuiKey_GamepadR3, XINPUT_GAMEPAD_RIGHT_THUMB); 358 | MAP_ANALOG(ImGuiKey_GamepadLStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 359 | MAP_ANALOG(ImGuiKey_GamepadLStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 360 | MAP_ANALOG(ImGuiKey_GamepadLStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 361 | MAP_ANALOG(ImGuiKey_GamepadLStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 362 | MAP_ANALOG(ImGuiKey_GamepadRStickLeft, gamepad.sThumbRX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 363 | MAP_ANALOG(ImGuiKey_GamepadRStickRight, gamepad.sThumbRX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 364 | MAP_ANALOG(ImGuiKey_GamepadRStickUp, gamepad.sThumbRY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 365 | MAP_ANALOG(ImGuiKey_GamepadRStickDown, gamepad.sThumbRY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 366 | #undef MAP_BUTTON 367 | #undef MAP_ANALOG 368 | #endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 369 | } 370 | 371 | void ImGui_ImplWin32_NewFrame() 372 | { 373 | ImGuiIO& io = ImGui::GetIO(); 374 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 375 | IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplWin32_Init()?"); 376 | 377 | // Setup display size (every frame to accommodate for window resizing) 378 | RECT rect = { 0, 0, 0, 0 }; 379 | ::GetClientRect(bd->hWnd, &rect); 380 | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); 381 | 382 | // Setup time step 383 | INT64 current_time = 0; 384 | ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); 385 | io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond; 386 | bd->Time = current_time; 387 | 388 | // Update OS mouse position 389 | ImGui_ImplWin32_UpdateMouseData(); 390 | 391 | // Process workarounds for known Windows key handling issues 392 | ImGui_ImplWin32_ProcessKeyEventsWorkarounds(); 393 | 394 | // Update OS mouse cursor with the cursor requested by imgui 395 | ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); 396 | if (bd->LastMouseCursor != mouse_cursor) 397 | { 398 | bd->LastMouseCursor = mouse_cursor; 399 | ImGui_ImplWin32_UpdateMouseCursor(); 400 | } 401 | 402 | // Update game controllers (if enabled and available) 403 | ImGui_ImplWin32_UpdateGamepads(); 404 | } 405 | 406 | // 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) 407 | #define IM_VK_KEYPAD_ENTER (VK_RETURN + 256) 408 | 409 | // Map VK_xxx to ImGuiKey_xxx. 410 | static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam) 411 | { 412 | switch (wParam) 413 | { 414 | case VK_TAB: return ImGuiKey_Tab; 415 | case VK_LEFT: return ImGuiKey_LeftArrow; 416 | case VK_RIGHT: return ImGuiKey_RightArrow; 417 | case VK_UP: return ImGuiKey_UpArrow; 418 | case VK_DOWN: return ImGuiKey_DownArrow; 419 | case VK_PRIOR: return ImGuiKey_PageUp; 420 | case VK_NEXT: return ImGuiKey_PageDown; 421 | case VK_HOME: return ImGuiKey_Home; 422 | case VK_END: return ImGuiKey_End; 423 | case VK_INSERT: return ImGuiKey_Insert; 424 | case VK_DELETE: return ImGuiKey_Delete; 425 | case VK_BACK: return ImGuiKey_Backspace; 426 | case VK_SPACE: return ImGuiKey_Space; 427 | case VK_RETURN: return ImGuiKey_Enter; 428 | case VK_ESCAPE: return ImGuiKey_Escape; 429 | case VK_OEM_7: return ImGuiKey_Apostrophe; 430 | case VK_OEM_COMMA: return ImGuiKey_Comma; 431 | case VK_OEM_MINUS: return ImGuiKey_Minus; 432 | case VK_OEM_PERIOD: return ImGuiKey_Period; 433 | case VK_OEM_2: return ImGuiKey_Slash; 434 | case VK_OEM_1: return ImGuiKey_Semicolon; 435 | case VK_OEM_PLUS: return ImGuiKey_Equal; 436 | case VK_OEM_4: return ImGuiKey_LeftBracket; 437 | case VK_OEM_5: return ImGuiKey_Backslash; 438 | case VK_OEM_6: return ImGuiKey_RightBracket; 439 | case VK_OEM_3: return ImGuiKey_GraveAccent; 440 | case VK_CAPITAL: return ImGuiKey_CapsLock; 441 | case VK_SCROLL: return ImGuiKey_ScrollLock; 442 | case VK_NUMLOCK: return ImGuiKey_NumLock; 443 | case VK_SNAPSHOT: return ImGuiKey_PrintScreen; 444 | case VK_PAUSE: return ImGuiKey_Pause; 445 | case VK_NUMPAD0: return ImGuiKey_Keypad0; 446 | case VK_NUMPAD1: return ImGuiKey_Keypad1; 447 | case VK_NUMPAD2: return ImGuiKey_Keypad2; 448 | case VK_NUMPAD3: return ImGuiKey_Keypad3; 449 | case VK_NUMPAD4: return ImGuiKey_Keypad4; 450 | case VK_NUMPAD5: return ImGuiKey_Keypad5; 451 | case VK_NUMPAD6: return ImGuiKey_Keypad6; 452 | case VK_NUMPAD7: return ImGuiKey_Keypad7; 453 | case VK_NUMPAD8: return ImGuiKey_Keypad8; 454 | case VK_NUMPAD9: return ImGuiKey_Keypad9; 455 | case VK_DECIMAL: return ImGuiKey_KeypadDecimal; 456 | case VK_DIVIDE: return ImGuiKey_KeypadDivide; 457 | case VK_MULTIPLY: return ImGuiKey_KeypadMultiply; 458 | case VK_SUBTRACT: return ImGuiKey_KeypadSubtract; 459 | case VK_ADD: return ImGuiKey_KeypadAdd; 460 | case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter; 461 | case VK_LSHIFT: return ImGuiKey_LeftShift; 462 | case VK_LCONTROL: return ImGuiKey_LeftCtrl; 463 | case VK_LMENU: return ImGuiKey_LeftAlt; 464 | case VK_LWIN: return ImGuiKey_LeftSuper; 465 | case VK_RSHIFT: return ImGuiKey_RightShift; 466 | case VK_RCONTROL: return ImGuiKey_RightCtrl; 467 | case VK_RMENU: return ImGuiKey_RightAlt; 468 | case VK_RWIN: return ImGuiKey_RightSuper; 469 | case VK_APPS: return ImGuiKey_Menu; 470 | case '0': return ImGuiKey_0; 471 | case '1': return ImGuiKey_1; 472 | case '2': return ImGuiKey_2; 473 | case '3': return ImGuiKey_3; 474 | case '4': return ImGuiKey_4; 475 | case '5': return ImGuiKey_5; 476 | case '6': return ImGuiKey_6; 477 | case '7': return ImGuiKey_7; 478 | case '8': return ImGuiKey_8; 479 | case '9': return ImGuiKey_9; 480 | case 'A': return ImGuiKey_A; 481 | case 'B': return ImGuiKey_B; 482 | case 'C': return ImGuiKey_C; 483 | case 'D': return ImGuiKey_D; 484 | case 'E': return ImGuiKey_E; 485 | case 'F': return ImGuiKey_F; 486 | case 'G': return ImGuiKey_G; 487 | case 'H': return ImGuiKey_H; 488 | case 'I': return ImGuiKey_I; 489 | case 'J': return ImGuiKey_J; 490 | case 'K': return ImGuiKey_K; 491 | case 'L': return ImGuiKey_L; 492 | case 'M': return ImGuiKey_M; 493 | case 'N': return ImGuiKey_N; 494 | case 'O': return ImGuiKey_O; 495 | case 'P': return ImGuiKey_P; 496 | case 'Q': return ImGuiKey_Q; 497 | case 'R': return ImGuiKey_R; 498 | case 'S': return ImGuiKey_S; 499 | case 'T': return ImGuiKey_T; 500 | case 'U': return ImGuiKey_U; 501 | case 'V': return ImGuiKey_V; 502 | case 'W': return ImGuiKey_W; 503 | case 'X': return ImGuiKey_X; 504 | case 'Y': return ImGuiKey_Y; 505 | case 'Z': return ImGuiKey_Z; 506 | case VK_F1: return ImGuiKey_F1; 507 | case VK_F2: return ImGuiKey_F2; 508 | case VK_F3: return ImGuiKey_F3; 509 | case VK_F4: return ImGuiKey_F4; 510 | case VK_F5: return ImGuiKey_F5; 511 | case VK_F6: return ImGuiKey_F6; 512 | case VK_F7: return ImGuiKey_F7; 513 | case VK_F8: return ImGuiKey_F8; 514 | case VK_F9: return ImGuiKey_F9; 515 | case VK_F10: return ImGuiKey_F10; 516 | case VK_F11: return ImGuiKey_F11; 517 | case VK_F12: return ImGuiKey_F12; 518 | default: return ImGuiKey_None; 519 | } 520 | } 521 | 522 | // Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. 523 | #ifndef WM_MOUSEHWHEEL 524 | #define WM_MOUSEHWHEEL 0x020E 525 | #endif 526 | #ifndef DBT_DEVNODES_CHANGED 527 | #define DBT_DEVNODES_CHANGED 0x0007 528 | #endif 529 | 530 | // Win32 message handler (process Win32 mouse/keyboard inputs, etc.) 531 | // Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. 532 | // When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs. 533 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. 534 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. 535 | // Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags. 536 | // 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. 537 | // 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. 538 | #if 0 539 | // Copy this line into your .cpp file to forward declare the function. 540 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 541 | #endif 542 | 543 | // See https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages 544 | // Prefer to call this at the top of the message handler to avoid the possibility of other Win32 calls interfering with this. 545 | static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo() 546 | { 547 | LPARAM extra_info = ::GetMessageExtraInfo(); 548 | if ((extra_info & 0xFFFFFF80) == 0xFF515700) 549 | return ImGuiMouseSource_Pen; 550 | if ((extra_info & 0xFFFFFF80) == 0xFF515780) 551 | return ImGuiMouseSource_TouchScreen; 552 | return ImGuiMouseSource_Mouse; 553 | } 554 | 555 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 556 | { 557 | if (ImGui::GetCurrentContext() == nullptr) 558 | return 0; 559 | 560 | ImGuiIO& io = ImGui::GetIO(); 561 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 562 | 563 | switch (msg) 564 | { 565 | case WM_MOUSEMOVE: 566 | case WM_NCMOUSEMOVE: 567 | { 568 | // We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events 569 | ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo(); 570 | const int area = (msg == WM_MOUSEMOVE) ? 1 : 2; 571 | bd->MouseHwnd = hwnd; 572 | if (bd->MouseTrackedArea != area) 573 | { 574 | TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 }; 575 | TRACKMOUSEEVENT tme_track = { sizeof(tme_track), (DWORD)((area == 2) ? (TME_LEAVE | TME_NONCLIENT) : TME_LEAVE), hwnd, 0 }; 576 | if (bd->MouseTrackedArea != 0) 577 | ::TrackMouseEvent(&tme_cancel); 578 | ::TrackMouseEvent(&tme_track); 579 | bd->MouseTrackedArea = area; 580 | } 581 | POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) }; 582 | if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates. 583 | break; 584 | io.AddMouseSourceEvent(mouse_source); 585 | io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y); 586 | break; 587 | } 588 | case WM_MOUSELEAVE: 589 | case WM_NCMOUSELEAVE: 590 | { 591 | const int area = (msg == WM_MOUSELEAVE) ? 1 : 2; 592 | if (bd->MouseTrackedArea == area) 593 | { 594 | if (bd->MouseHwnd == hwnd) 595 | bd->MouseHwnd = nullptr; 596 | bd->MouseTrackedArea = 0; 597 | io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); 598 | } 599 | break; 600 | } 601 | case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: 602 | case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: 603 | case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: 604 | case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: 605 | { 606 | ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo(); 607 | int button = 0; 608 | if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; } 609 | if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } 610 | if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } 611 | if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } 612 | if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr) 613 | ::SetCapture(hwnd); 614 | bd->MouseButtonsDown |= 1 << button; 615 | io.AddMouseSourceEvent(mouse_source); 616 | io.AddMouseButtonEvent(button, true); 617 | return 0; 618 | } 619 | case WM_LBUTTONUP: 620 | case WM_RBUTTONUP: 621 | case WM_MBUTTONUP: 622 | case WM_XBUTTONUP: 623 | { 624 | ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo(); 625 | int button = 0; 626 | if (msg == WM_LBUTTONUP) { button = 0; } 627 | if (msg == WM_RBUTTONUP) { button = 1; } 628 | if (msg == WM_MBUTTONUP) { button = 2; } 629 | if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } 630 | bd->MouseButtonsDown &= ~(1 << button); 631 | if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd) 632 | ::ReleaseCapture(); 633 | io.AddMouseSourceEvent(mouse_source); 634 | io.AddMouseButtonEvent(button, false); 635 | return 0; 636 | } 637 | case WM_MOUSEWHEEL: 638 | io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA); 639 | return 0; 640 | case WM_MOUSEHWHEEL: 641 | io.AddMouseWheelEvent(-(float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f); 642 | return 0; 643 | case WM_KEYDOWN: 644 | case WM_KEYUP: 645 | case WM_SYSKEYDOWN: 646 | case WM_SYSKEYUP: 647 | { 648 | const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN); 649 | if (wParam < 256) 650 | { 651 | // Submit modifiers 652 | ImGui_ImplWin32_UpdateKeyModifiers(); 653 | 654 | // Obtain virtual key code 655 | // (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.) 656 | int vk = (int)wParam; 657 | if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED)) 658 | vk = IM_VK_KEYPAD_ENTER; 659 | 660 | // Submit key event 661 | const ImGuiKey key = ImGui_ImplWin32_VirtualKeyToImGuiKey(vk); 662 | const int scancode = (int)LOBYTE(HIWORD(lParam)); 663 | if (key != ImGuiKey_None) 664 | ImGui_ImplWin32_AddKeyEvent(key, is_key_down, vk, scancode); 665 | 666 | // Submit individual left/right modifier events 667 | if (vk == VK_SHIFT) 668 | { 669 | // Important: Shift keys tend to get stuck when pressed together, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkarounds() 670 | if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); } 671 | if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); } 672 | } 673 | else if (vk == VK_CONTROL) 674 | { 675 | if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); } 676 | if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); } 677 | } 678 | else if (vk == VK_MENU) 679 | { 680 | if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); } 681 | if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); } 682 | } 683 | } 684 | return 0; 685 | } 686 | case WM_SETFOCUS: 687 | case WM_KILLFOCUS: 688 | io.AddFocusEvent(msg == WM_SETFOCUS); 689 | return 0; 690 | case WM_INPUTLANGCHANGE: 691 | ImGui_ImplWin32_UpdateKeyboardCodePage(); 692 | return 0; 693 | case WM_CHAR: 694 | if (::IsWindowUnicode(hwnd)) 695 | { 696 | // You can also use ToAscii()+GetKeyboardState() to retrieve characters. 697 | if (wParam > 0 && wParam < 0x10000) 698 | io.AddInputCharacterUTF16((unsigned short)wParam); 699 | } 700 | else 701 | { 702 | wchar_t wch = 0; 703 | ::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 1, &wch, 1); 704 | io.AddInputCharacter(wch); 705 | } 706 | return 0; 707 | case WM_SETCURSOR: 708 | // This is required to restore cursor when transitioning from e.g resize borders to client area. 709 | if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) 710 | return 1; 711 | return 0; 712 | case WM_DEVICECHANGE: 713 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 714 | if ((UINT)wParam == DBT_DEVNODES_CHANGED) 715 | bd->WantUpdateHasGamepad = true; 716 | #endif 717 | return 0; 718 | } 719 | return 0; 720 | } 721 | 722 | 723 | //-------------------------------------------------------------------------------------------------------- 724 | // DPI-related helpers (optional) 725 | //-------------------------------------------------------------------------------------------------------- 726 | // - Use to enable DPI awareness without having to create an application manifest. 727 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 728 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 729 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 730 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 731 | //--------------------------------------------------------------------------------------------------------- 732 | // This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable. 733 | // ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically. 734 | // If you are trying to implement your own backend for your own engine, you may ignore that noise. 735 | //--------------------------------------------------------------------------------------------------------- 736 | 737 | // Perform our own check with RtlVerifyVersionInfo() instead of using functions from as they 738 | // require a manifest to be functional for checks above 8.1. See https://github.com/ocornut/imgui/issues/4200 739 | static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD) 740 | { 741 | typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG); 742 | static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = nullptr; 743 | if (RtlVerifyVersionInfoFn == nullptr) 744 | if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll")) 745 | RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo"); 746 | if (RtlVerifyVersionInfoFn == nullptr) 747 | return FALSE; 748 | 749 | RTL_OSVERSIONINFOEXW versionInfo = { }; 750 | ULONGLONG conditionMask = 0; 751 | versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); 752 | versionInfo.dwMajorVersion = major; 753 | versionInfo.dwMinorVersion = minor; 754 | VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); 755 | VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); 756 | return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE; 757 | } 758 | 759 | #define _IsWindowsVistaOrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA 760 | #define _IsWindows8OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8 761 | #define _IsWindows8Point1OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE 762 | #define _IsWindows10OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0A00), LOBYTE(0x0A00), 0) // _WIN32_WINNT_WINTHRESHOLD / _WIN32_WINNT_WIN10 763 | 764 | #ifndef DPI_ENUMS_DECLARED 765 | typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS; 766 | typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE; 767 | #endif 768 | #ifndef _DPI_AWARENESS_CONTEXTS_ 769 | DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); 770 | #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3 771 | #endif 772 | #ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 773 | #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4 774 | #endif 775 | typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+ 776 | typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+ 777 | typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update) 778 | 779 | // Helper function to enable DPI awareness without setting up a manifest 780 | void ImGui_ImplWin32_EnableDpiAwareness() 781 | { 782 | if (_IsWindows10OrGreater()) 783 | { 784 | static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process 785 | if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext")) 786 | { 787 | SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); 788 | return; 789 | } 790 | } 791 | if (_IsWindows8Point1OrGreater()) 792 | { 793 | static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process 794 | if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness")) 795 | { 796 | SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE); 797 | return; 798 | } 799 | } 800 | #if _WIN32_WINNT >= 0x0600 801 | ::SetProcessDPIAware(); 802 | #endif 803 | } 804 | 805 | #if defined(_MSC_VER) && !defined(NOGDI) 806 | #pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32' 807 | #endif 808 | 809 | float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor) 810 | { 811 | UINT xdpi = 96, ydpi = 96; 812 | if (_IsWindows8Point1OrGreater()) 813 | { 814 | static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process 815 | static PFN_GetDpiForMonitor GetDpiForMonitorFn = nullptr; 816 | if (GetDpiForMonitorFn == nullptr && shcore_dll != nullptr) 817 | GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor"); 818 | if (GetDpiForMonitorFn != nullptr) 819 | { 820 | GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); 821 | IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! 822 | return xdpi / 96.0f; 823 | } 824 | } 825 | #ifndef NOGDI 826 | const HDC dc = ::GetDC(nullptr); 827 | xdpi = ::GetDeviceCaps(dc, LOGPIXELSX); 828 | ydpi = ::GetDeviceCaps(dc, LOGPIXELSY); 829 | IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! 830 | ::ReleaseDC(nullptr, dc); 831 | #endif 832 | return xdpi / 96.0f; 833 | } 834 | 835 | float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd) 836 | { 837 | HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST); 838 | return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor); 839 | } 840 | 841 | //--------------------------------------------------------------------------------------------------------- 842 | // Transparency related helpers (optional) 843 | //-------------------------------------------------------------------------------------------------------- 844 | 845 | #if defined(_MSC_VER) 846 | #pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi' 847 | #endif 848 | 849 | // [experimental] 850 | // Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c 851 | // (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW) 852 | void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd) 853 | { 854 | if (!_IsWindowsVistaOrGreater()) 855 | return; 856 | 857 | BOOL composition; 858 | if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition) 859 | return; 860 | 861 | BOOL opaque; 862 | DWORD color; 863 | if (_IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque)) 864 | { 865 | HRGN region = ::CreateRectRgn(0, 0, -1, -1); 866 | DWM_BLURBEHIND bb = {}; 867 | bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; 868 | bb.hRgnBlur = region; 869 | bb.fEnable = TRUE; 870 | ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); 871 | ::DeleteObject(region); 872 | } 873 | else 874 | { 875 | DWM_BLURBEHIND bb = {}; 876 | bb.dwFlags = DWM_BB_ENABLE; 877 | ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); 878 | } 879 | } 880 | 881 | //--------------------------------------------------------------------------------------------------------- 882 | 883 | #endif // #ifndef IMGUI_DISABLE 884 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tutryx/FastAim/0bddbc6e8da0de7cf76859a2c7671bff2b81ecc9/Menu.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FastAim 2 | This is a color aimbot a created in a couple hours by joining together some files from other projects I made. 3 | It uses [FastFind](https://github.com/FastFrench/FastFind/tree/master) a library which has helped me a lot before when I started to program this kind of things in Autohotkey and Autoit. 4 | 5 | It makes use of [Interception](https://github.com/oblitum/Interception) to emulate the mouse movement. 6 | Be aware that this method might be detected by some AntiCheats, I have only tested it in Fortnite, CsGo 2 Gamers Club and Paladins so far. 7 | 8 | Also the screenshot method of the FastFind library is quite old and there are some better alternatives, but implementing all the FastFind functions to other screenshot system would take a considerable ammount of time. 9 | 10 | There is still many ways to optimize this and add new features but I will leave it as it is for now because it was just a one day project to use with the fortnite Thermal Vision and share with some friends. 11 | 12 | ![alt text](https://github.com/tutryx/FastAim/blob/main/Menu.png?raw=true) 13 | 14 | ### Interception installation process 15 | Download [interception's latest release](https://github.com/oblitum/Interception/releases/download/v1.0.1/Interception.zip) and follow the steps: 16 | 1. Extract files 17 | 2. Copy the path of command line installer e.g: `C:\Users\tutryx\Downloads\Interception\command line installer` 18 | 3. Open CMD with administrator rights 19 | 4. Move to the command line installer directory `cd C:\Users\tutryx\Downloads\Interception\command line installer` 20 | 5. Press TAB to select the .exe or write its name and add "/install" `command line installer/install` 21 | 6. Reboot computer 22 | -------------------------------------------------------------------------------- /Utilities/Colors.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../ImGui/imgui.h" 3 | 4 | namespace Color 5 | { 6 | ImVec4 gray958(0.054f, 0.062f, 0.074f, 1.000f); //0E1013 7 | ImVec4 gray928(0.090f, 0.094f, 0.105f, 1.000f); //17181B 8 | ImVec4 gray900(0.125f, 0.129f, 0.141f, 1.000f); //202124 9 | ImVec4 gray868(0.156f, 0.164f, 0.176f, 1.000f); //282A2D 10 | ImVec4 gray846(0.180f, 0.192f, 0.203f, 1.000f); //2E3134 11 | ImVec4 gray800(0.235f, 0.250f, 0.262f, 1.000f); //3C4043 12 | ImVec4 gray700(0.372f, 0.388f, 0.407f, 1.000f); //5F6368 13 | ImVec4 gray600(0.501f, 0.525f, 0.545f, 1.000f); //80868B 14 | ImVec4 gray500(0.603f, 0.627f, 0.650f, 1.000f); //9AA0A6 15 | ImVec4 gray400(0.741f, 0.756f, 0.776f, 1.000f); //BDC1C6 16 | ImVec4 gray300(0.854f, 0.862f, 0.878f, 1.000f); //DADCE0 17 | ImVec4 gray200(0.909f, 0.917f, 0.929f, 1.000f); //E8EAED 18 | ImVec4 gray100(0.945f, 0.952f, 0.956f, 1.000f); //F1F3F4 19 | ImVec4 gray050(0.972f, 0.976f, 0.980f, 1.000f); //F8F9FA 20 | ImVec4 redSeny(1.000f, 0.000f, 0.000f, 1.000f); //FF0000 21 | ImVec4 traslucid(0.000f, 0.000f, 0.000f, 0.000f); 22 | } -------------------------------------------------------------------------------- /Utilities/User.cpp: -------------------------------------------------------------------------------- 1 | #include "User.h" 2 | #include "SimpleIni.h" 3 | #include "skCrypter.h" 4 | #include 5 | #include 6 | 7 | 8 | User::User() { 9 | CSimpleIniA ini; 10 | SI_Error rc = ini.LoadFile(_("User.ini")); 11 | if (rc < 0) 12 | { 13 | return; 14 | } 15 | 16 | this->Binds.aim = ini.GetDoubleValue(_("Key Binds"), _("Aim")); 17 | this->Binds.toggleMenu = ini.GetDoubleValue(_("Key Binds"), _("Hide Menu")); 18 | 19 | this->Aimbot.strength = ini.GetDoubleValue(_("Aimbot"), _("Strength")); 20 | this->Aimbot.fov = ini.GetDoubleValue(_("Aimbot"), _("FOV")); 21 | this->Aimbot.offsetX = ini.GetDoubleValue(_("Aimbot"), _("Offset X")); 22 | this->Aimbot.offsetY = ini.GetDoubleValue(_("Aimbot"), _("Offset Y")); 23 | 24 | this->SearchSettings.color = ini.GetDoubleValue(_("Search Settings"), _("Color")); 25 | this->SearchSettings.colorVariation = ini.GetDoubleValue(_("Search Settings"), _("Variation")); 26 | this->SearchSettings.sizeSearch = ini.GetDoubleValue(_("Search Settings"), _("Size Search")); 27 | this->SearchSettings.minMatch = ini.GetDoubleValue(_("Search Settings"), _("Minimum Match")); 28 | this->SearchSettings.refX = ini.GetDoubleValue(_("Search Settings"), _("Reference X")); 29 | this->SearchSettings.refY = ini.GetDoubleValue(_("Search Settings"), _("Reference Y")); 30 | 31 | this->Data.debug = ini.GetBoolValue(_("Data"), _("Debug")); 32 | 33 | // Update PreferenceXY 34 | const int MONITOR_CENTER_X = GetSystemMetrics(SM_CXSCREEN) / 2; 35 | const int MONITOR_CENTER_Y = GetSystemMetrics(SM_CYSCREEN) / 2; 36 | this->SearchSettings.prefX = MONITOR_CENTER_X - this->Aimbot.fov / 2 + this->SearchSettings.refX; 37 | this->SearchSettings.prefY = MONITOR_CENTER_Y - this->Aimbot.fov / 2 + this->SearchSettings.refY; 38 | 39 | } 40 | 41 | User::~User() { 42 | CSimpleIniA ini; 43 | ini.SetUnicode(); 44 | SI_Error rc = ini.LoadFile(_("User.ini")); 45 | if (rc < 0) 46 | { 47 | std::ofstream{ _("User.ini") }; 48 | ini.LoadFile(_("User.ini")); 49 | } 50 | 51 | ini.SetDoubleValue(_("Key Binds"), _("Aim"), this->Binds.aim); 52 | ini.SetDoubleValue(_("Key Binds"), _("Hide Menu"), this->Binds.toggleMenu); 53 | 54 | ini.SetDoubleValue(_("Aimbot"), _("Strength"), this->Aimbot.strength); 55 | ini.SetDoubleValue(_("Aimbot"), _("FOV"), this->Aimbot.fov); 56 | ini.SetDoubleValue(_("Aimbot"), _("Offset X"), this->Aimbot.offsetX); 57 | ini.SetDoubleValue(_("Aimbot"), _("Offset Y"), this->Aimbot.offsetY); 58 | 59 | ini.SetDoubleValue(_("Search Settings"), _("Color"), this->SearchSettings.color); 60 | ini.SetDoubleValue(_("Search Settings"), _("Variation"), this->SearchSettings.colorVariation); 61 | ini.SetDoubleValue(_("Search Settings"), _("Size Search"), this->SearchSettings.sizeSearch); 62 | ini.SetDoubleValue(_("Search Settings"), _("Minimum Match"), this->SearchSettings.minMatch); 63 | ini.SetDoubleValue(_("Search Settings"), _("Reference X"), this->SearchSettings.refX); 64 | ini.SetDoubleValue(_("Search Settings"), _("Reference Y"), this->SearchSettings.refY); 65 | 66 | ini.SetBoolValue(_("Data"), _("Debug"), false); 67 | 68 | ini.SaveFile(_("User.ini")); 69 | } -------------------------------------------------------------------------------- /Utilities/User.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class User { 5 | public: 6 | User(); 7 | 8 | ~User(); 9 | 10 | struct 11 | { 12 | int aim = 0x00; 13 | int toggleMenu = VK_F10; 14 | }Binds; 15 | 16 | struct 17 | { 18 | float strength = 1.0f; 19 | int fov = 320; 20 | int offsetX = 0; 21 | int offsetY = 0; 22 | }Aimbot; 23 | 24 | struct 25 | { 26 | int color = 0x000000; 27 | int colorVariation = 0; 28 | int prefX = GetSystemMetrics(SM_CXSCREEN) / 2; 29 | int prefY = GetSystemMetrics(SM_CYSCREEN) / 2; 30 | int sizeSearch = 1; 31 | int minMatch = 1; 32 | // For ImGui widget 33 | float colorRGB[3] = { 0 , 0, 0 }; 34 | int refX = 0; 35 | int refY = 0; 36 | }SearchSettings; 37 | 38 | struct 39 | { 40 | bool debug = false; 41 | bool loadedApp = false; 42 | }Data; 43 | }; -------------------------------------------------------------------------------- /Utilities/VKNames.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static std::unordered_map VKNames{ 5 | { 0x00, "" }, 6 | { VK_LBUTTON, "L BUTTON" }, 7 | { VK_RBUTTON, "R BUTTON" }, 8 | { VK_MBUTTON, "M BUTTON" }, 9 | { VK_XBUTTON1, "BUTTON 4" }, 10 | { VK_XBUTTON2, "BUTTON 5" }, 11 | { VK_BACK, "BACKSPACE" }, 12 | { VK_TAB, "TAB" }, 13 | { VK_CLEAR, "CLEAR" }, 14 | { VK_RETURN, "ENTER" }, 15 | { VK_SHIFT, "SHIFT" }, 16 | { VK_CONTROL, "CONTROL" }, 17 | { VK_MENU, "ALT" }, 18 | { VK_PAUSE, "PAUSE" }, 19 | { VK_CAPITAL, "CAPS LOCK" }, 20 | { VK_ESCAPE, "ESCAPE" }, 21 | { VK_SPACE, "SPACE" }, 22 | { VK_PRIOR, "PAGE UP" }, 23 | { VK_NEXT, "PAGE DOWN" }, 24 | { VK_END, "END" }, 25 | { VK_HOME, "HOME" }, 26 | { VK_LEFT, "LEFT ARROW" }, 27 | { VK_UP, "UP ARROW" }, 28 | { VK_RIGHT, "RIGHT ARROW" }, 29 | { VK_DOWN, "DOWN ARROW" }, 30 | { VK_SELECT, "SELECT" }, 31 | { VK_PRINT, "PRINT" }, 32 | { VK_EXECUTE, "EXECUTE" }, 33 | { VK_SNAPSHOT, "PRINT SCREEN" }, 34 | { VK_INSERT, "INSERT" }, 35 | { VK_DELETE, "DELETE" }, 36 | { VK_HELP, "HELP" }, 37 | { 0x30, "0" }, 38 | { 0x31, "1" }, 39 | { 0x32, "2" }, 40 | { 0x33, "3" }, 41 | { 0x34, "4" }, 42 | { 0x35, "5" }, 43 | { 0x36, "6" }, 44 | { 0x37, "7" }, 45 | { 0x38, "8" }, 46 | { 0x39, "9" }, 47 | { 0x41, "A" }, 48 | { 0x42, "B" }, 49 | { 0x43, "C" }, 50 | { 0x44, "D" }, 51 | { 0x45, "E" }, 52 | { 0x46, "F" }, 53 | { 0x47, "G" }, 54 | { 0x48, "H" }, 55 | { 0x49, "I" }, 56 | { 0x4A, "J" }, 57 | { 0x4B, "K" }, 58 | { 0x4C, "L" }, 59 | { 0x4D, "M" }, 60 | { 0x4E, "N" }, 61 | { 0x4F, "O" }, 62 | { 0x50, "P" }, 63 | { 0x51, "Q" }, 64 | { 0x52, "R" }, 65 | { 0x53, "S" }, 66 | { 0x54, "T" }, 67 | { 0x55, "U" }, 68 | { 0x56, "V" }, 69 | { 0x57, "W" }, 70 | { 0x58, "X" }, 71 | { 0x59, "Y" }, 72 | { 0x5A, "Z" }, 73 | { VK_LWIN, "L WIN" }, 74 | { VK_RWIN, "R WIN" }, 75 | { VK_APPS, "CONTEXT MENU" }, 76 | { VK_SLEEP, "SLEEP" }, 77 | { VK_NUMPAD0, "NUMPAD 0" }, 78 | { VK_NUMPAD1, "NUMPAD 1" }, 79 | { VK_NUMPAD2, "NUMPAD 2" }, 80 | { VK_NUMPAD3, "NUMPAD 3" }, 81 | { VK_NUMPAD4, "NUMPAD 4" }, 82 | { VK_NUMPAD5, "NUMPAD 5" }, 83 | { VK_NUMPAD6, "NUMPAD 6" }, 84 | { VK_NUMPAD7, "NUMPAD 7" }, 85 | { VK_NUMPAD8, "NUMPAD 8" }, 86 | { VK_NUMPAD9, "NUMPAD 9" }, 87 | { VK_MULTIPLY, "NUMPAD *" }, 88 | { VK_ADD, "NUMPAD +" }, 89 | { VK_SEPARATOR, "NUMPAD ," }, 90 | { VK_SUBTRACT, "NUMPAD -" }, 91 | { VK_DECIMAL, "NUMPAD ." }, 92 | { VK_DIVIDE, "NUMPAD /" }, 93 | { VK_F1, "F1" }, 94 | { VK_F2, "F2" }, 95 | { VK_F3, "F3" }, 96 | { VK_F4, "F4" }, 97 | { VK_F5, "F5" }, 98 | { VK_F6, "F6" }, 99 | { VK_F7, "F7" }, 100 | { VK_F8, "F8" }, 101 | { VK_F9, "F9" }, 102 | { VK_F10, "F10" }, 103 | { VK_F11, "F11" }, 104 | { VK_F12, "F12" }, 105 | { VK_NUMLOCK, "NUM LOCK" }, 106 | { VK_SCROLL, "SCROLL LOCK" }, 107 | { VK_LSHIFT, "L SHIFT" }, 108 | { VK_RSHIFT, "R SHIFT" }, 109 | { VK_LCONTROL, "L CONTROL" }, 110 | { VK_RCONTROL, "R CONTROL" }, 111 | { VK_LMENU, "L ALT" }, 112 | { VK_RMENU, "R ALT" }, 113 | { VK_OEM_1, ";:" }, 114 | { VK_OEM_PLUS, "+" }, 115 | { VK_OEM_COMMA, "," }, 116 | { VK_OEM_MINUS, "-" }, 117 | { VK_OEM_PERIOD, "." }, 118 | { VK_OEM_2, "/?" }, 119 | { VK_OEM_3, "`~" }, 120 | { VK_GAMEPAD_A, "GAMEPAD A" }, 121 | { VK_GAMEPAD_B, "GAMEPAD B" }, 122 | { VK_GAMEPAD_X, "GAMEPAD X" }, 123 | { VK_GAMEPAD_Y, "GAMEPAD Y" }, 124 | { VK_GAMEPAD_RIGHT_SHOULDER, "GAMEPAD R SHOULDER" }, 125 | { VK_GAMEPAD_LEFT_SHOULDER, "GAMEPAD L SHOULDER" }, 126 | { VK_GAMEPAD_LEFT_TRIGGER, "GAMEPAD L TRIGGER" }, 127 | { VK_GAMEPAD_RIGHT_TRIGGER, "GAMEPAD R TRIGGER" }, 128 | { VK_GAMEPAD_DPAD_UP, "GAMEPAD DPAD UP" }, 129 | { VK_GAMEPAD_DPAD_DOWN, "GAMEPAD DPAD DOWN" }, 130 | { VK_GAMEPAD_DPAD_LEFT, "GAMEPAD DPAD LEFT" }, 131 | { VK_GAMEPAD_DPAD_RIGHT, "GAMEPAD DPAD RIGHT" }, 132 | { VK_GAMEPAD_MENU, "GAMEPAD MENU" }, 133 | { VK_GAMEPAD_VIEW, "GAMEPAD VIEW" }, 134 | { VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON, "GAMEPAD L BUTTON" }, 135 | { VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON, "GAMEPAD R BUTTON" }, 136 | { VK_GAMEPAD_LEFT_THUMBSTICK_UP, "GAMEPAD L UP" }, 137 | { VK_GAMEPAD_LEFT_THUMBSTICK_DOWN, "GAMEPAD L DOWN" }, 138 | { VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT, "GAMEPAD L RIGHT" }, 139 | { VK_GAMEPAD_LEFT_THUMBSTICK_LEFT, "GAMEPAD L LEFT" }, 140 | { VK_GAMEPAD_RIGHT_THUMBSTICK_UP, "GAMEPAD R UP" }, 141 | { VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN, "GAMEPAD R DOWN" }, 142 | { VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT, "GAMEPAD R RIGHT" }, 143 | { VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT, "GAMEPAD R LEFT" }, 144 | { VK_OEM_4, "[{" }, 145 | { VK_OEM_5, "\\|" }, 146 | { VK_OEM_6, "]}" }, 147 | { VK_OEM_7, "'\"" }, 148 | { VK_OEM_102, "<>" }, 149 | }; -------------------------------------------------------------------------------- /Utilities/interception.h: -------------------------------------------------------------------------------- 1 | #ifndef _INTERCEPTION_H_ 2 | #define _INTERCEPTION_H_ 3 | 4 | #ifdef INTERCEPTION_STATIC 5 | #define INTERCEPTION_API 6 | #else 7 | #if defined _WIN32 || defined __CYGWIN__ 8 | #ifdef INTERCEPTION_EXPORT 9 | #ifdef __GNUC__ 10 | #define INTERCEPTION_API __attribute__((dllexport)) 11 | #else 12 | #define INTERCEPTION_API __declspec(dllexport) 13 | #endif 14 | #else 15 | #ifdef __GNUC__ 16 | #define INTERCEPTION_API __attribute__((dllimport)) 17 | #else 18 | #define INTERCEPTION_API __declspec(dllimport) 19 | #endif 20 | #endif 21 | #else 22 | #if __GNUC__ >= 4 23 | #define INTERCEPTION_API __attribute__ ((visibility("default"))) 24 | #else 25 | #define INTERCEPTION_API 26 | #endif 27 | #endif 28 | #endif 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | #define INTERCEPTION_MAX_KEYBOARD 10 35 | 36 | #define INTERCEPTION_MAX_MOUSE 10 37 | 38 | #define INTERCEPTION_MAX_DEVICE ((INTERCEPTION_MAX_KEYBOARD) + (INTERCEPTION_MAX_MOUSE)) 39 | 40 | #define INTERCEPTION_KEYBOARD(index) ((index) + 1) 41 | 42 | #define INTERCEPTION_MOUSE(index) ((INTERCEPTION_MAX_KEYBOARD) + (index) + 1) 43 | 44 | typedef void *InterceptionContext; 45 | 46 | typedef int InterceptionDevice; 47 | 48 | typedef int InterceptionPrecedence; 49 | 50 | typedef unsigned short InterceptionFilter; 51 | 52 | typedef int (*InterceptionPredicate)(InterceptionDevice device); 53 | 54 | enum InterceptionKeyState 55 | { 56 | INTERCEPTION_KEY_DOWN = 0x00, 57 | INTERCEPTION_KEY_UP = 0x01, 58 | INTERCEPTION_KEY_E0 = 0x02, 59 | INTERCEPTION_KEY_E1 = 0x04, 60 | INTERCEPTION_KEY_TERMSRV_SET_LED = 0x08, 61 | INTERCEPTION_KEY_TERMSRV_SHADOW = 0x10, 62 | INTERCEPTION_KEY_TERMSRV_VKPACKET = 0x20 63 | }; 64 | 65 | enum InterceptionFilterKeyState 66 | { 67 | INTERCEPTION_FILTER_KEY_NONE = 0x0000, 68 | INTERCEPTION_FILTER_KEY_ALL = 0xFFFF, 69 | INTERCEPTION_FILTER_KEY_DOWN = INTERCEPTION_KEY_UP, 70 | INTERCEPTION_FILTER_KEY_UP = INTERCEPTION_KEY_UP << 1, 71 | INTERCEPTION_FILTER_KEY_E0 = INTERCEPTION_KEY_E0 << 1, 72 | INTERCEPTION_FILTER_KEY_E1 = INTERCEPTION_KEY_E1 << 1, 73 | INTERCEPTION_FILTER_KEY_TERMSRV_SET_LED = INTERCEPTION_KEY_TERMSRV_SET_LED << 1, 74 | INTERCEPTION_FILTER_KEY_TERMSRV_SHADOW = INTERCEPTION_KEY_TERMSRV_SHADOW << 1, 75 | INTERCEPTION_FILTER_KEY_TERMSRV_VKPACKET = INTERCEPTION_KEY_TERMSRV_VKPACKET << 1 76 | }; 77 | 78 | enum InterceptionMouseState 79 | { 80 | INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN = 0x001, 81 | INTERCEPTION_MOUSE_LEFT_BUTTON_UP = 0x002, 82 | INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN = 0x004, 83 | INTERCEPTION_MOUSE_RIGHT_BUTTON_UP = 0x008, 84 | INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN = 0x010, 85 | INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP = 0x020, 86 | 87 | INTERCEPTION_MOUSE_BUTTON_1_DOWN = INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN, 88 | INTERCEPTION_MOUSE_BUTTON_1_UP = INTERCEPTION_MOUSE_LEFT_BUTTON_UP, 89 | INTERCEPTION_MOUSE_BUTTON_2_DOWN = INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN, 90 | INTERCEPTION_MOUSE_BUTTON_2_UP = INTERCEPTION_MOUSE_RIGHT_BUTTON_UP, 91 | INTERCEPTION_MOUSE_BUTTON_3_DOWN = INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN, 92 | INTERCEPTION_MOUSE_BUTTON_3_UP = INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP, 93 | 94 | INTERCEPTION_MOUSE_BUTTON_4_DOWN = 0x040, 95 | INTERCEPTION_MOUSE_BUTTON_4_UP = 0x080, 96 | INTERCEPTION_MOUSE_BUTTON_5_DOWN = 0x100, 97 | INTERCEPTION_MOUSE_BUTTON_5_UP = 0x200, 98 | 99 | INTERCEPTION_MOUSE_WHEEL = 0x400, 100 | INTERCEPTION_MOUSE_HWHEEL = 0x800 101 | }; 102 | 103 | enum InterceptionFilterMouseState 104 | { 105 | INTERCEPTION_FILTER_MOUSE_NONE = 0x0000, 106 | INTERCEPTION_FILTER_MOUSE_ALL = 0xFFFF, 107 | 108 | INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_DOWN = INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN, 109 | INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_UP = INTERCEPTION_MOUSE_LEFT_BUTTON_UP, 110 | INTERCEPTION_FILTER_MOUSE_RIGHT_BUTTON_DOWN = INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN, 111 | INTERCEPTION_FILTER_MOUSE_RIGHT_BUTTON_UP = INTERCEPTION_MOUSE_RIGHT_BUTTON_UP, 112 | INTERCEPTION_FILTER_MOUSE_MIDDLE_BUTTON_DOWN = INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN, 113 | INTERCEPTION_FILTER_MOUSE_MIDDLE_BUTTON_UP = INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP, 114 | 115 | INTERCEPTION_FILTER_MOUSE_BUTTON_1_DOWN = INTERCEPTION_MOUSE_BUTTON_1_DOWN, 116 | INTERCEPTION_FILTER_MOUSE_BUTTON_1_UP = INTERCEPTION_MOUSE_BUTTON_1_UP, 117 | INTERCEPTION_FILTER_MOUSE_BUTTON_2_DOWN = INTERCEPTION_MOUSE_BUTTON_2_DOWN, 118 | INTERCEPTION_FILTER_MOUSE_BUTTON_2_UP = INTERCEPTION_MOUSE_BUTTON_2_UP, 119 | INTERCEPTION_FILTER_MOUSE_BUTTON_3_DOWN = INTERCEPTION_MOUSE_BUTTON_3_DOWN, 120 | INTERCEPTION_FILTER_MOUSE_BUTTON_3_UP = INTERCEPTION_MOUSE_BUTTON_3_UP, 121 | 122 | INTERCEPTION_FILTER_MOUSE_BUTTON_4_DOWN = INTERCEPTION_MOUSE_BUTTON_4_DOWN, 123 | INTERCEPTION_FILTER_MOUSE_BUTTON_4_UP = INTERCEPTION_MOUSE_BUTTON_4_UP, 124 | INTERCEPTION_FILTER_MOUSE_BUTTON_5_DOWN = INTERCEPTION_MOUSE_BUTTON_5_DOWN, 125 | INTERCEPTION_FILTER_MOUSE_BUTTON_5_UP = INTERCEPTION_MOUSE_BUTTON_5_UP, 126 | 127 | INTERCEPTION_FILTER_MOUSE_WHEEL = INTERCEPTION_MOUSE_WHEEL, 128 | INTERCEPTION_FILTER_MOUSE_HWHEEL = INTERCEPTION_MOUSE_HWHEEL, 129 | 130 | INTERCEPTION_FILTER_MOUSE_MOVE = 0x1000 131 | }; 132 | 133 | enum InterceptionMouseFlag 134 | { 135 | INTERCEPTION_MOUSE_MOVE_RELATIVE = 0x000, 136 | INTERCEPTION_MOUSE_MOVE_ABSOLUTE = 0x001, 137 | INTERCEPTION_MOUSE_VIRTUAL_DESKTOP = 0x002, 138 | INTERCEPTION_MOUSE_ATTRIBUTES_CHANGED = 0x004, 139 | INTERCEPTION_MOUSE_MOVE_NOCOALESCE = 0x008, 140 | INTERCEPTION_MOUSE_TERMSRV_SRC_SHADOW = 0x100 141 | }; 142 | 143 | typedef struct 144 | { 145 | unsigned short state; 146 | unsigned short flags; 147 | short rolling; 148 | int x; 149 | int y; 150 | unsigned int information; 151 | } InterceptionMouseStroke; 152 | 153 | typedef struct 154 | { 155 | unsigned short code; 156 | unsigned short state; 157 | unsigned int information; 158 | } InterceptionKeyStroke; 159 | 160 | typedef char InterceptionStroke[sizeof(InterceptionMouseStroke)]; 161 | 162 | InterceptionContext INTERCEPTION_API interception_create_context(void); 163 | 164 | void INTERCEPTION_API interception_destroy_context(InterceptionContext context); 165 | 166 | InterceptionPrecedence INTERCEPTION_API interception_get_precedence(InterceptionContext context, InterceptionDevice device); 167 | 168 | void INTERCEPTION_API interception_set_precedence(InterceptionContext context, InterceptionDevice device, InterceptionPrecedence precedence); 169 | 170 | InterceptionFilter INTERCEPTION_API interception_get_filter(InterceptionContext context, InterceptionDevice device); 171 | 172 | void INTERCEPTION_API interception_set_filter(InterceptionContext context, InterceptionPredicate predicate, InterceptionFilter filter); 173 | 174 | InterceptionDevice INTERCEPTION_API interception_wait(InterceptionContext context); 175 | 176 | InterceptionDevice INTERCEPTION_API interception_wait_with_timeout(InterceptionContext context, unsigned long milliseconds); 177 | 178 | int INTERCEPTION_API interception_send(InterceptionContext context, InterceptionDevice device, const InterceptionStroke *stroke, unsigned int nstroke); 179 | 180 | int INTERCEPTION_API interception_receive(InterceptionContext context, InterceptionDevice device, InterceptionStroke *stroke, unsigned int nstroke); 181 | 182 | unsigned int INTERCEPTION_API interception_get_hardware_id(InterceptionContext context, InterceptionDevice device, void *hardware_id_buffer, unsigned int buffer_size); 183 | 184 | int INTERCEPTION_API interception_is_invalid(InterceptionDevice device); 185 | 186 | int INTERCEPTION_API interception_is_keyboard(InterceptionDevice device); 187 | 188 | int INTERCEPTION_API interception_is_mouse(InterceptionDevice device); 189 | 190 | #ifdef __cplusplus 191 | } 192 | #endif 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /Utilities/skCrypter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*____________________________________________________________________________________________________________ 4 | 5 | Original Author: skadro 6 | Github: https://github.com/skadro-official 7 | License: See end of file 8 | 9 | skCrypter 10 | Compile-time, Usermode + Kernelmode, safe and lightweight string crypter library for C++11+ 11 | 12 | *Not removing this part is appreciated* 13 | ____________________________________________________________________________________________________________*/ 14 | 15 | #ifdef _KERNEL_MODE 16 | namespace std 17 | { 18 | // STRUCT TEMPLATE remove_reference 19 | template 20 | struct remove_reference { 21 | using type = _Ty; 22 | }; 23 | 24 | template 25 | struct remove_reference<_Ty&> { 26 | using type = _Ty; 27 | }; 28 | 29 | template 30 | struct remove_reference<_Ty&&> { 31 | using type = _Ty; 32 | }; 33 | 34 | template 35 | using remove_reference_t = typename remove_reference<_Ty>::type; 36 | 37 | // STRUCT TEMPLATE remove_const 38 | template 39 | struct remove_const { // remove top-level const qualifier 40 | using type = _Ty; 41 | }; 42 | 43 | template 44 | struct remove_const { 45 | using type = _Ty; 46 | }; 47 | 48 | template 49 | using remove_const_t = typename remove_const<_Ty>::type; 50 | } 51 | #else 52 | #include 53 | #endif 54 | 55 | namespace skc 56 | { 57 | template 58 | using clean_type = typename std::remove_const_t>; 59 | 60 | template 61 | class skCrypter 62 | { 63 | public: 64 | __forceinline constexpr skCrypter(T* data) 65 | { 66 | crypt(data); 67 | } 68 | 69 | __forceinline T* get() 70 | { 71 | return _storage; 72 | } 73 | 74 | __forceinline int size() // (w)char count 75 | { 76 | return _size; 77 | } 78 | 79 | __forceinline char key() 80 | { 81 | return _key1; 82 | } 83 | 84 | __forceinline T* encrypt() 85 | { 86 | if (!isEncrypted()) 87 | crypt(_storage); 88 | 89 | return _storage; 90 | } 91 | 92 | __forceinline T* decrypt() 93 | { 94 | if (isEncrypted()) 95 | crypt(_storage); 96 | 97 | return _storage; 98 | } 99 | 100 | __forceinline bool isEncrypted() 101 | { 102 | return _storage[_size - 1] != 0; 103 | } 104 | 105 | __forceinline void clear() // set full storage to 0 106 | { 107 | for (int i = 0; i < _size; i++) 108 | { 109 | _storage[i] = 0; 110 | } 111 | } 112 | 113 | __forceinline operator T* () 114 | { 115 | decrypt(); 116 | 117 | return _storage; 118 | } 119 | 120 | private: 121 | __forceinline constexpr void crypt(T* data) 122 | { 123 | for (int i = 0; i < _size; i++) 124 | { 125 | _storage[i] = data[i] ^ (_key1 + i % (1 + _key2)); 126 | } 127 | } 128 | 129 | T _storage[_size]{}; 130 | }; 131 | } 132 | 133 | #define _(str) skCrypt_key(str, __TIME__[4], __TIME__[7]) 134 | #define skCrypt_key(str, key1, key2) []() { \ 135 | constexpr static auto crypted = skc::skCrypter \ 136 | >((skc::clean_type*)str); \ 137 | return crypted; }() 138 | 139 | /*________________________________________________________________________________ 140 | 141 | MIT License 142 | 143 | Copyright (c) 2020 skadro 144 | 145 | Permission is hereby granted, free of charge, to any person obtaining a copy 146 | of this software and associated documentation files (the "Software"), to deal 147 | in the Software without restriction, including without limitation the rights 148 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 149 | copies of the Software, and to permit persons to whom the Software is 150 | furnished to do so, subject to the following conditions: 151 | 152 | The above copyright notice and this permission notice shall be included in all 153 | copies or substantial portions of the Software. 154 | 155 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 156 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 157 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 158 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 159 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 160 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 161 | SOFTWARE. 162 | 163 | ________________________________________________________________________________*/ 164 | --------------------------------------------------------------------------------