├── ladder.h ├── rand.h ├── unlock_all.h ├── imgui.ini ├── monkeware.vcxproj.user ├── knife_walls.h ├── encryption.h ├── flash.h ├── firemode.h ├── monkeware_keys.h ├── no_spread.h ├── spectate.h ├── fullbright.h ├── gun_fov.h ├── player_fov.h ├── long_knife.h ├── ads.h ├── offsets.h ├── glow.h ├── cav.h ├── noclip.h ├── speed.h ├── no_recoil.h ├── imgui_impl_dx9.h ├── imgui_impl_win32.h ├── requests.hpp ├── features.h ├── includes.h ├── main.cpp ├── run_and_shoot.h ├── rainbow_six.h ├── keybind.h ├── memory_class.h ├── vector.h ├── imconfig.h ├── interface.hpp ├── monkeware.vcxproj.filters ├── aimbot.h ├── xor.h ├── monkeware.vcxproj ├── menu.h ├── defs.h ├── imgui_impl_dx9.cpp ├── imgui_impl_win32.cpp ├── imstb_rectpack.h └── imstb_textedit.h /ladder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /rand.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsideExploit/monkeware-selfleak-v1/HEAD/rand.h -------------------------------------------------------------------------------- /unlock_all.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool unlocked = false; 4 | 5 | void unlock_all() 6 | { 7 | if (unlocked == false) 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /imgui.ini: -------------------------------------------------------------------------------- 1 | [Window][Debug##Default] 2 | Pos=60,60 3 | Size=400,400 4 | Collapsed=0 5 | 6 | [Window][ ] 7 | Pos=-1,0 8 | Size=400,390 9 | Collapsed=0 10 | 11 | -------------------------------------------------------------------------------- /monkeware.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /knife_walls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | uint64_t knife() 4 | { 5 | 6 | } 7 | 8 | void WriteKnifeStartPos(float pos) 9 | { 10 | 11 | } 12 | 13 | void WriteKnifeEndPos(float pos) 14 | { 15 | 16 | } -------------------------------------------------------------------------------- /encryption.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | uintptr_t decrypt(uintptr_t encrypted, uintptr_t key) 4 | { 5 | encrypted = __ROL8__(encrypted, -0x5FA); 6 | encrypted = encrypted - 0xC0FFEE; 7 | encrypted = encrypted / 3; 8 | encrypted = encrypted >> 2; 9 | 10 | return encrypted ^ key; 11 | } -------------------------------------------------------------------------------- /flash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void no_flash() 4 | { 5 | if (features::flash_enabled_state == true) 6 | { 7 | uintptr_t chain = event_manager(); 8 | 9 | chain = Interface->Read(chain + 0x30); 10 | chain = Interface->Read(chain + 0x28); 11 | 12 | Interface->Write(chain + 0xA0, 2); 13 | } 14 | } -------------------------------------------------------------------------------- /firemode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void fire_mode() 4 | { 5 | uintptr_t chain = NULL; 6 | 7 | chain = Interface->Read(get_localplayer() + 0x90); 8 | chain = Interface->Read(chain + 0x70) + 0x120; 9 | 10 | if (features::firemode_state_enable == true) 11 | { 12 | Interface->Write(chain, 0); 13 | } 14 | } -------------------------------------------------------------------------------- /monkeware_keys.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace custom_keys 4 | { 5 | constexpr std::uintptr_t game_manager_key = 0xF5ACE5A7; 6 | constexpr std::uintptr_t fov_manager_key = 0xFACEE5A67A; 7 | constexpr std::uintptr_t profile_manager_key = 0x4f4cbc593ded; 8 | constexpr std::uintptr_t network_manager_key = 0x30465e849e84e; 9 | constexpr std::uintptr_t round_manager_key = 0x4c6bf5e691; 10 | } -------------------------------------------------------------------------------- /no_spread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void no_spread() 4 | { 5 | if (features::ns_enabled_state == true) 6 | { 7 | Interface->Write(get_weapon_info() + 0x88, features::spread); 8 | features::ns_disabled_state = true; 9 | } 10 | else if (features::ns_disabled_state == true) 11 | { 12 | Interface->Write(get_weapon_info() + 0x88, 0.75); 13 | features::ns_disabled_state = false; 14 | } 15 | } -------------------------------------------------------------------------------- /spectate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void spoof_spectate() 4 | { 5 | if (features::spectate_enabled_state == true) 6 | { 7 | Interface->Write(spoof_spectate_manager() + offsets::spoof, 1); 8 | features::spectate_disabled_state = true; 9 | } 10 | else if (features::spectate_disabled_state == true) 11 | { 12 | Interface->Write(spoof_spectate_manager() + offsets::spoof, 0); 13 | features::spectate_disabled_state = false; 14 | } 15 | } -------------------------------------------------------------------------------- /fullbright.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool wrote_fullbright = false; 4 | 5 | void fullbright() 6 | { 7 | if (features::fullbright_enabled_state == true) 8 | { 9 | if (wrote_fullbright == false) 10 | { 11 | uintptr_t chain = enviroment_manager(); 12 | 13 | chain = Interface->Read(chain + 0xB8); 14 | Interface->Write(chain + decrypt(0x80000000031F3F1, 0xFA55A7), 0); // Dont share, its private 15 | wrote_fullbright = true; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /gun_fov.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void gun_fov() 4 | { 5 | uintptr_t chain = NULL; 6 | 7 | chain = Interface->Read(fov_manager() + 0x10); 8 | 9 | if (features::gfov_enabled_state == true) 10 | { 11 | Interface->Write(chain + 0xB3C, features::gun_fov); 12 | features::gfov_disabled_state = true; 13 | } 14 | else if (features::gfov_disabled_state == true) 15 | { 16 | Interface->Write(chain + 0xB3C, 0.8726646304f); 17 | features::gfov_disabled_state = false; 18 | } 19 | } -------------------------------------------------------------------------------- /player_fov.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void player_fov() 4 | { 5 | uintptr_t chain = NULL; 6 | 7 | chain = Interface->Read(fov_manager() + 0x10); 8 | 9 | 10 | if (features::pfov_enabled_state == true) 11 | { 12 | Interface->Write(chain + 0xB38, features::player_fov); 13 | features::pfov_disabled_state = true; 14 | } 15 | else if (features::pfov_disabled_state == true) 16 | { 17 | Interface->Write(chain + 0xB38, 1.506999969f); 18 | features::pfov_disabled_state = false; 19 | } 20 | } -------------------------------------------------------------------------------- /long_knife.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void long_knife() 4 | { 5 | uintptr_t chain = event_manager(); 6 | 7 | chain = Interface->Read(chain + 0x80); 8 | chain = Interface->Read(chain + 0x30); 9 | 10 | if (features::knife_enabled_state == true) 11 | { 12 | Interface->Write(chain + 0x60, { features::knife_distance, features::knife_distance }); 13 | features::knife_disabled_state = true; 14 | } 15 | else if (features::knife_disabled_state == true) 16 | { 17 | Interface->Write(chain + 0x60, { 1.3, 1.3 }); 18 | features::knife_disabled_state = false; 19 | } 20 | } -------------------------------------------------------------------------------- /ads.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void ads() 4 | { 5 | if (features::ads_enabled_state == true) 6 | { 7 | auto chain = Interface->Read(get_localplayer() + 0x90); 8 | chain = Interface->Read(chain + 0x70) + 0x384; 9 | Interface->Write(chain, 0); 10 | features::ads_disabled_state = true; 11 | } 12 | else if (features::ads_disabled_state == true) 13 | { 14 | auto chain = Interface->Read(get_localplayer() + 0x90); 15 | chain = Interface->Read(chain + 0x70) + 0x384; 16 | Interface->Write(chain, 1); 17 | features::ads_disabled_state = false; 18 | } 19 | } -------------------------------------------------------------------------------- /offsets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace offsets 4 | { 5 | constexpr std::uintptr_t game_manager = 0x880000002d186b0a; 6 | constexpr std::uintptr_t fov_manager = 0x1800002f05b4aa37; 7 | constexpr std::uintptr_t profile_manager = 0xa8000ede62d59dc2; 8 | constexpr std::uintptr_t network_manager = 0xa80090d31c27669e; 9 | constexpr std::uintptr_t round_manager = 0x6800000E547290EE; 10 | 11 | constexpr std::uintptr_t content_manager = 0x5E20A90; 12 | constexpr std::uintptr_t vt_marker = 0x52C71F0; 13 | constexpr std::uintptr_t noclip_manager = 0x5AFC450; 14 | constexpr std::uintptr_t enviroment_manager = 0x5DF1ED0; 15 | constexpr std::uintptr_t spoof_spectate_manager = 0x6CF7B38; 16 | 17 | constexpr std::uintptr_t cav = 0x220; 18 | constexpr std::uintptr_t rgb = 0xD0; 19 | constexpr std::uintptr_t spoof = 0x5D; 20 | } 21 | -------------------------------------------------------------------------------- /glow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void glow() 4 | { 5 | if (features::glow_enabled_state == true) 6 | { 7 | uintptr_t glow = Interface->Read(enviroment_manager() + 0xB8); 8 | 9 | Interface->Write(glow + 0xD0, { features::RGB[0], features::RGB[1], features::RGB[2] }); 10 | Interface->Write(glow + 0x110, { 255, 0.5, 999, 999 }); 11 | 12 | features::glow_disabled_state = true; 13 | } 14 | else if (features::glow_disabled_state == true) 15 | { 16 | uintptr_t glow = Interface->Read(enviroment_manager() + 0xB8); 17 | 18 | Interface->Write(glow + 0xD0, { 0.5372549295, 0.5372549295, 0.5372549295 }); 19 | Interface->Write(glow + 0x110, { 0, 0, 0, 0 }); 20 | 21 | features::glow_disabled_state = false; 22 | } 23 | } -------------------------------------------------------------------------------- /cav.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void cav_esp() 4 | { 5 | if (features::cav_enabled_state == true) 6 | { 7 | for (int i = 0; i < GetEntityCount(); i++) 8 | { 9 | auto entityObject = GetEntityByID(i); 10 | entityObject = DecryptEntityInfo(entityObject); 11 | 12 | auto entityInfo = Interface->Read(entityObject + 0x18); 13 | entityInfo = Interface->Read(entityInfo + 0xD8); 14 | 15 | for (uint32_t curCo = 0x80; curCo < 0xF0; curCo += 4) 16 | { 17 | auto marker = Interface->Read(entityInfo + curCo); 18 | if (marker == 0) continue; 19 | 20 | auto markerCheck = Interface->Read(marker); 21 | if (markerCheck != (MainModule + offsets::vt_marker)) continue; 22 | Interface->Write(marker + offsets::cav, 0x85); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /noclip.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void noclip() 4 | { 5 | if (features::noclip_state_enable == true) 6 | { 7 | uintptr_t chain = Interface->Read(noclip_manager() +0x128); 8 | chain = Interface->Read(chain + 0x10); 9 | 10 | set_noclip_bind(); 11 | if (noclip_key_state == true) 12 | { 13 | if (GetAsyncKeyState(noclip_key)) 14 | { 15 | Interface->Write(chain + 0x700, -1); 16 | } 17 | else 18 | { 19 | Interface->Write(chain + 0x700, 0.0003051850945f); 20 | } 21 | } 22 | else 23 | { 24 | Interface->Write(chain + 0x700, -1); 25 | } 26 | features::noclip_state_disable = true; 27 | } 28 | else if (features::noclip_state_disable == true) 29 | { 30 | uintptr_t chain = Interface->Read(noclip_manager() + 0x128); 31 | chain = Interface->Read(chain + 0x10); 32 | 33 | Interface->Write(chain + 0x700, 0.0003051850945f); 34 | features::noclip_state_disable = false; 35 | } 36 | } -------------------------------------------------------------------------------- /speed.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void speed() 4 | { 5 | if (features::speed_state_enable == true) 6 | { 7 | uintptr_t chain = event_manager(); 8 | 9 | chain = Interface->Read(chain + 0x30); 10 | chain = Interface->Read(chain + 0x38); 11 | 12 | set_speed_bind(); 13 | if (speed_key_state == true) 14 | { 15 | if (GetAsyncKeyState(speed_key)) 16 | { 17 | Interface->Write(chain + 0x58, features::player_speed); 18 | } 19 | else 20 | { 21 | Interface->Write(chain + 0x58, 110); 22 | } 23 | } 24 | else 25 | { 26 | Interface->Write(chain + 0x58, features::player_speed); 27 | } 28 | features::speed_state_disable = true; 29 | } 30 | else if (features::speed_state_disable == true) 31 | { 32 | uintptr_t chain = event_manager(); 33 | 34 | chain = Interface->Read(chain + 0x30); 35 | chain = Interface->Read(chain + 0x38); 36 | 37 | Interface->Write(chain + 0x58, 110); 38 | features::speed_state_disable = false; 39 | } 40 | } -------------------------------------------------------------------------------- /no_recoil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void recoil_multiplier() 4 | { 5 | uint64_t weapon = Interface->Read(get_localplayer() + 0x90); 6 | uint64_t curWeapon = Interface->Read(weapon + 0x70); 7 | uint64_t arrayToSingle = Interface->Read(curWeapon + 0x258); 8 | arrayToSingle = Interface->Read(arrayToSingle); 9 | uint64_t curWeaponPreset = Interface->Read(arrayToSingle + 0x140); 10 | curWeaponPreset = Interface->Read(curWeaponPreset); 11 | Interface->Write(curWeaponPreset + 0x70, 0.f); //Pull 12 | Interface->Write(curWeaponPreset + 0x74, 0.f); //Kick 13 | } 14 | 15 | void no_recoil() 16 | { 17 | if (features::nr_enabled_state == true) 18 | { 19 | Interface->Write(get_weapon_info() + 0x198, 0); 20 | Interface->Write(get_weapon_info() + 0x18C, { features::recoil, features::recoil }); 21 | recoil_multiplier(); 22 | features::nr_disabled_state = true; 23 | } 24 | else if (features::nr_disabled_state == true) 25 | { 26 | Interface->Write(get_weapon_info() + 0x198, 0); 27 | features::nr_disabled_state = false; 28 | } 29 | } -------------------------------------------------------------------------------- /imgui_impl_dx9.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer for DirectX9 2 | // This needs to be used along with a Platform Binding (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. 7 | 8 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 9 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. 10 | // https://github.com/ocornut/imgui 11 | 12 | #pragma once 13 | 14 | struct IDirect3DDevice9; 15 | 16 | IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device); 17 | IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown(); 18 | IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame(); 19 | IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data); 20 | 21 | // Use if you want to reset your rendering device without losing ImGui state. 22 | IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects(); 23 | IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects(); 24 | -------------------------------------------------------------------------------- /imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Binding for Windows (standard windows API for 32 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 imgui) 6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | 10 | #pragma once 11 | 12 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 13 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 14 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 15 | 16 | // Handler for Win32 messages, update mouse/keyboard data. 17 | // You may or not need this for your implementation, but it can serve as reference for handling inputs. 18 | // Intentionally commented out to avoid dragging dependencies on types. You can COPY this line into your .cpp code instead. 19 | /* 20 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 21 | */ 22 | -------------------------------------------------------------------------------- /requests.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum class RequestType : int 4 | { 5 | Unload, 6 | NewThread, 7 | MainModule, 8 | Module, 9 | ReadMemory, 10 | WriteMemory, 11 | WriteToReadOnly 12 | }; 13 | 14 | typedef struct _INIT_PACKET 15 | { 16 | PVOID RequestBuffer; 17 | HANDLE UserProcessId; 18 | WCHAR KernelEventName[0xFF]; 19 | WCHAR UserEventName[0xFF]; 20 | BOOLEAN IsInitialized; 21 | } INIT_PACKET, * PINIT_PACKET; 22 | 23 | typedef struct _REQUEST_PACKET 24 | { 25 | RequestType Type; 26 | PVOID Buffer; 27 | NTSTATUS Status; 28 | } REQUEST_PACKET, * PREQUEST_PACKET; 29 | 30 | typedef struct _MAIN_MODULE_PACKET 31 | { 32 | HANDLE ProcessId; 33 | PVOID Result; 34 | } MAIN_MODULE_PACKET, * PMAIN_MODULE_PACKET; 35 | 36 | typedef struct _MODULE_PACKET 37 | { 38 | HANDLE ProcessId; 39 | WCHAR ModuleName[128]; 40 | PVOID Result; 41 | } MODULE_PACKET, * PMODULE_PACKET; 42 | 43 | typedef struct _READ_PACKET 44 | { 45 | HANDLE ProcessId; 46 | PVOID SourceAddress; 47 | PVOID TargetAddress; 48 | SIZE_T Size; 49 | } READ_PACKET, * PREAD_PACKET; 50 | 51 | typedef struct _WRITE_PACKET 52 | { 53 | HANDLE ProcessId; 54 | PVOID SourceAddress; 55 | PVOID TargetAddress; 56 | SIZE_T Size; 57 | } WRITE_PACKET, * PWRITE_PACKET; 58 | 59 | typedef struct _FORCE_WRITE_PACKET 60 | { 61 | HANDLE ProcessId; 62 | PVOID SourceAddress; 63 | PVOID TargetAddress; 64 | SIZE_T Size; 65 | } FORCE_WRITE_PACKET, * PFORCE_WRITE_PACKET; 66 | -------------------------------------------------------------------------------- /features.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace features 4 | { 5 | bool aim_enabled_state = false; 6 | bool team_aim_enabled_state = false; 7 | float aim_fov = 0; 8 | 9 | bool cav_enabled_state = false; 10 | bool cav_disabled_state = false; 11 | 12 | bool nr_enabled_state = false; 13 | bool nr_disabled_state = false; 14 | float recoil = 0; 15 | 16 | bool ns_enabled_state = false; 17 | bool ns_disabled_state = false; 18 | float spread = 0; 19 | 20 | bool pfov_enabled_state = false; 21 | bool pfov_disabled_state = false; 22 | float player_fov = 0; 23 | 24 | bool gfov_enabled_state = false; 25 | bool gfov_disabled_state = false; 26 | float gun_fov = 0; 27 | 28 | bool ras_enabled_state = false; 29 | bool ras_disabled_state = false; 30 | 31 | bool ladder_enabled_state = false; 32 | bool ladder_disabled_state = false; 33 | 34 | bool ua_state_enable = false; 35 | bool ua_state_disable = false; 36 | 37 | bool noclip_state_enable = false; 38 | bool noclip_state_disable = false; 39 | 40 | bool speed_state_enable = false; 41 | bool speed_state_disable = false; 42 | int player_speed = 0; 43 | 44 | bool firemode_state_enable = false; 45 | 46 | bool spectate_enabled_state = false; 47 | bool spectate_disabled_state = false; 48 | 49 | bool flash_enabled_state = false; 50 | 51 | bool knife_enabled_state = false; 52 | bool knife_disabled_state = false; 53 | float knife_distance = 0; 54 | 55 | bool ads_enabled_state = false; 56 | bool ads_disabled_state = false; 57 | 58 | bool patched_silent = false; 59 | bool unpatched_silent = false; 60 | 61 | bool knife_wall_enbaled = false; 62 | bool knife_wall_disabled = false; 63 | 64 | bool outlines_enabled_state = false; 65 | bool outlines_disabled_state = false; 66 | float outline_thickness = 0; 67 | float RGB[3]; 68 | 69 | bool fullbright_enabled_state = false; 70 | 71 | bool glow_enabled_state = false; 72 | bool glow_disabled_state = false; 73 | float glow_RGB[3]; 74 | } -------------------------------------------------------------------------------- /includes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum entity_bones 4 | { 5 | head = 0x1070, 6 | spine = 0x1090, 7 | neck = 0x10F0 8 | }; 9 | 10 | 11 | bool noclip_key_state = false; 12 | bool speed_key_state = false; 13 | int sleep_aim = 1; 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "interface.hpp" 43 | 44 | const auto Interface = new KernelInterface; 45 | uintptr_t MainModule; 46 | 47 | #include "xor.h" 48 | #include "defs.h" 49 | #include "features.h" 50 | #include "keybind.h" 51 | #include "memory.h" 52 | #include "random.h" 53 | #include "rand.h" 54 | #include "encryption.h" 55 | #include "monkeware_keys.h" 56 | #include "offsets.h" 57 | #include "vector.h" 58 | #include "rainbow_six.h" // 59 | #include "no_recoil.h" // 60 | #include "no_spread.h" // 61 | #include "gun_fov.h" // 62 | #include "run_and_shoot.h" // 63 | #include "fullbright.h" // 64 | #include "player_fov.h" // 65 | #include "unlock_all.h" 66 | #include "glow.h" // 67 | #include "noclip.h" // 68 | #include "flash.h" // 69 | #include "firemode.h" // 70 | #include "long_knife.h" // 71 | #include "speed.h" // 72 | #include "spectate.h" // 73 | #include "ads.h" // 74 | #include "knife_walls.h" // 75 | #include "aimbot.h" // 76 | #include "cav.h"// 77 | 78 | #include "imgui.h" 79 | #include "imgui_impl_win32.h" 80 | #include "imgui_impl_dx9.h" 81 | 82 | #define DIRECTINPUT_VERSION 0x0800 83 | 84 | #pragma comment(lib, "d3d9.lib") -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "includes.h" 5 | #include "menu.h" 6 | 7 | void init() 8 | { 9 | printf("Setup : %lX\n", Interface->Setup()); 10 | Interface->SetTargetProcessId((HANDLE)14892); // Put r6 pid here 11 | 12 | MainModule = Interface->GetMainModule(); 13 | printf("MainModule : %llX\n", MainModule); 14 | } 15 | 16 | void feature_loop() 17 | { 18 | while (true) 19 | { 20 | std::this_thread::sleep_for(std::chrono::milliseconds(16));// 21 | if (game_state() == 2) 22 | { 23 | cav_esp(); 24 | player_fov(); 25 | gun_fov(); 26 | no_spread(); 27 | no_recoil(); 28 | fire_mode(); 29 | no_flash(); 30 | long_knife(); 31 | fullbright(); 32 | spoof_spectate(); 33 | //run_and_shoot(); 34 | speed(); 35 | glow(); 36 | ads(); 37 | } 38 | else if (game_state() == 3) 39 | { 40 | cav_esp(); 41 | player_fov(); 42 | gun_fov(); 43 | no_spread(); 44 | no_recoil(); 45 | fire_mode(); 46 | no_flash(); 47 | long_knife(); 48 | fullbright(); 49 | spoof_spectate(); 50 | //run_and_shoot(); 51 | noclip(); 52 | speed(); 53 | glow(); 54 | ads(); 55 | } 56 | unlock_all(); 57 | } 58 | } 59 | 60 | void aim_loop() 61 | { 62 | while (true) 63 | { 64 | std::this_thread::sleep_for(std::chrono::microseconds(sleep_aim)); 65 | if (features::aim_enabled_state == true) 66 | { 67 | set_key(); 68 | aimbot(); 69 | } 70 | } 71 | } 72 | 73 | int main(void) 74 | { 75 | init(); 76 | 77 | std::thread menu(draw_menu); 78 | std::thread features(feature_loop); 79 | std::thread aim(aim_loop); 80 | 81 | menu.detach(); 82 | features.detach(); 83 | aim.detach(); 84 | 85 | while (1) {Sleep(10000);} 86 | } -------------------------------------------------------------------------------- /run_and_shoot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void run_and_shoot() 4 | { 5 | static bool getOrigRCX = true; 6 | static uint64_t origRCX = 0x0; 7 | static bool getOrigRCX40 = true; 8 | static uint64_t origRCX40 = 0x0; 9 | 10 | if (features::ras_enabled_state == true) 11 | { 12 | uint64_t rcx = Interface->Read(MainModule + 0x68CEC90); 13 | rcx = Interface->Read(rcx + 0x18); 14 | rcx = Interface->Read(rcx); 15 | rcx = Interface->Read(rcx + 0x30); 16 | rcx = Interface->Read(rcx + 0x30); 17 | rcx = Interface->Read(rcx + 0x50); 18 | rcx = Interface->Read(rcx + 0x8); 19 | rcx = Interface->Read(rcx + 0x148); 20 | uint64_t rcxW = Interface->Read(rcx + 0x30); 21 | rcx = Interface->Read(rcxW + 0x178); 22 | if (getOrigRCX) 23 | { 24 | origRCX = rcx; 25 | getOrigRCX = false; 26 | } 27 | if (getOrigRCX40) 28 | { 29 | origRCX40 = Interface->Read(rcx + 0x40); 30 | getOrigRCX40 = false; 31 | } 32 | Interface->Write(rcx + 0x40, 0x0); 33 | Interface->Write(rcx + 0x80, 0x1); 34 | Interface->Write(rcxW + 0x178, 0x0); 35 | 36 | features::ras_disabled_state = true; 37 | } 38 | else if (features::ras_disabled_state == true) 39 | { 40 | uint64_t rcx = Interface->Read(MainModule + 0x68CEC90); 41 | rcx = Interface->Read(rcx + 0x18); 42 | rcx = Interface->Read(rcx); 43 | rcx = Interface->Read(rcx + 0x30); 44 | rcx = Interface->Read(rcx + 0x30); 45 | rcx = Interface->Read(rcx + 0x50); 46 | rcx = Interface->Read(rcx + 0x8); 47 | rcx = Interface->Read(rcx + 0x148); 48 | rcx = Interface->Read(rcx + 0x30); 49 | Interface->Write(rcx + 0x178, origRCX); 50 | getOrigRCX = true; 51 | rcx = Interface->Read(rcx + 0x178); 52 | Interface->Write(rcx + 0x40, origRCX40); 53 | getOrigRCX40 = true; 54 | features::ras_disabled_state = false; 55 | } 56 | } -------------------------------------------------------------------------------- /rainbow_six.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | uintptr_t game_manager() 5 | { 6 | return Interface->Read(MainModule + decrypt(offsets::game_manager, custom_keys::game_manager_key)); 7 | } 8 | 9 | uintptr_t profile_manager() 10 | { 11 | return Interface->Read(MainModule + decrypt(offsets::profile_manager, custom_keys::profile_manager_key)); 12 | } 13 | 14 | uintptr_t fov_manager() 15 | { 16 | return Interface->Read(MainModule + decrypt(offsets::fov_manager, custom_keys::fov_manager_key)); 17 | } 18 | 19 | uintptr_t network_manager() 20 | { 21 | return Interface->Read(MainModule + decrypt(offsets::network_manager, custom_keys::network_manager_key)); 22 | } 23 | 24 | uintptr_t enviroment_manager() 25 | { 26 | return Interface->Read(MainModule + offsets::enviroment_manager); 27 | } 28 | 29 | uintptr_t round_manager() 30 | { 31 | return Interface->Read(MainModule + ((decrypt(offsets::round_manager, custom_keys::round_manager_key) - 0xC4F) + 0x4DA8)); 32 | } 33 | 34 | uintptr_t spoof_spectate_manager() 35 | { 36 | return Interface->Read(MainModule + offsets::spoof_spectate_manager); 37 | } 38 | 39 | uintptr_t noclip_manager() 40 | { 41 | return Interface->Read(MainModule + offsets::noclip_manager); 42 | } 43 | 44 | int game_state() 45 | { 46 | return Interface->Read(round_manager() + 0x300); 47 | } 48 | 49 | uint64_t get_localplayer() 50 | { 51 | uint64_t local = Interface->Read(profile_manager() + 0x88); 52 | local = Interface->Read(local); 53 | local = Interface->Read(local + 0x28); 54 | local += 0xBADD3F9015EF5524; 55 | local ^= 0x23; 56 | local += 0xB0EB703322DA824D; 57 | 58 | return local; 59 | } 60 | 61 | uint64_t get_weapon_info() 62 | { 63 | uint64_t weaponInfo = Interface->Read(get_localplayer() + 0x90); 64 | weaponInfo = Interface->Read(weaponInfo + 0x70); 65 | weaponInfo = Interface->Read(weaponInfo + 0x288); 66 | weaponInfo = __ROL8__(weaponInfo, 0x1D); 67 | weaponInfo -= 0x49; 68 | weaponInfo ^= 0xC07C346E918191F1; 69 | 70 | return weaponInfo; 71 | } 72 | 73 | uintptr_t event_manager() 74 | { 75 | uintptr_t chain = NULL; 76 | 77 | chain = Interface->Read(get_localplayer() + 0x30); 78 | 79 | chain ^= 0x48; 80 | chain += 0x5364B35667A05F5B; 81 | 82 | return __ROL8__(chain, 0x2D); 83 | } 84 | 85 | uint64_t get_entity_list() 86 | { 87 | uint64_t entityList = Interface->Read(game_manager() + 0xE0); 88 | entityList ^= 0x53; 89 | entityList += 0xEEBD43B91E3D5D54; 90 | entityList ^= 0x1FEC13843E78A654; 91 | 92 | return entityList; 93 | } -------------------------------------------------------------------------------- /keybind.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | const char* firemode_options[] = { ("Full auto"), ("Burst 2"), ("Burst 3"), ("Single") }; 4 | static int firemode_setting = 0; 5 | 6 | const char* key_options[] = { ("LBUTTON"), ("RBUTTON"), ("M5"), ("M4") }; 7 | static int key_setting = 0; 8 | uintptr_t key = 0x0; 9 | 10 | void set_key() 11 | { 12 | if (key_setting == 0) 13 | { 14 | key = 0x01; 15 | } 16 | if (key_setting == 1) 17 | { 18 | key = 0x02; 19 | } 20 | if (key_setting == 2) 21 | { 22 | key = 0x05; 23 | } 24 | if (key_setting == 3) 25 | { 26 | key = 0x06; 27 | } 28 | } 29 | 30 | const char* speed_item[] = { ("None"), ("M4"),("M5"), ("V"), ("X"), ("J"), ("K"), ("Shift"), ("`") }; 31 | static int speed_bind = 0; 32 | uintptr_t speed_key = 0; 33 | 34 | void set_speed_bind() 35 | { 36 | if (speed_bind == 0) 37 | { 38 | speed_key_state = false; 39 | } 40 | if (speed_bind == 1) 41 | { 42 | speed_key_state = true; 43 | speed_key = 0x06; 44 | } 45 | if (speed_bind == 2) 46 | { 47 | speed_key_state = true; 48 | speed_key = 0x05; 49 | } 50 | if (speed_bind == 3) 51 | { 52 | speed_key_state = true; 53 | speed_key = 0x56; 54 | } 55 | if (speed_bind == 4) 56 | { 57 | speed_key_state = true; 58 | speed_key = 0x58; 59 | } 60 | if (speed_bind == 5) 61 | { 62 | speed_key_state = true; 63 | speed_key = 0x4A; 64 | } 65 | if (speed_bind == 6) 66 | { 67 | speed_key_state = true; 68 | speed_key = 0x4B; 69 | } 70 | if (speed_bind == 7) 71 | { 72 | speed_key_state = true; 73 | speed_key = 0x10; 74 | } 75 | if (speed_bind == 8) 76 | { 77 | speed_key_state = true; 78 | speed_key = 0xC0; 79 | } 80 | } 81 | 82 | const char* noclip_item[] = { ("None"), ("M4"),("M5"), ("V"), ("X"), ("J"), ("K"), ("Shift"), ("`") }; 83 | static int noclip_bind = 0; 84 | uintptr_t noclip_key = 0; 85 | 86 | void set_noclip_bind() 87 | { 88 | if (noclip_bind == 0) 89 | { 90 | noclip_key_state = false; 91 | } 92 | if (noclip_bind == 1) 93 | { 94 | noclip_key_state = true; 95 | noclip_key = 0x06; 96 | } 97 | if (noclip_bind == 2) 98 | { 99 | noclip_key_state = true; 100 | noclip_key = 0x05; 101 | } 102 | if (noclip_bind == 3) 103 | { 104 | noclip_key_state = true; 105 | noclip_key = 0x56; 106 | } 107 | if (noclip_bind == 4) 108 | { 109 | noclip_key_state = true; 110 | noclip_key = 0x58; 111 | } 112 | if (noclip_bind == 5) 113 | { 114 | noclip_key_state = true; 115 | noclip_key = 0x4A; 116 | } 117 | if (noclip_bind == 6) 118 | { 119 | noclip_key_state = true; 120 | noclip_key = 0x4B; 121 | } 122 | if (noclip_bind == 7) 123 | { 124 | noclip_key_state = true; 125 | noclip_key = 0x10; 126 | } 127 | if (noclip_bind == 8) 128 | { 129 | noclip_key_state = true; 130 | noclip_key = 0xC0; 131 | } 132 | } -------------------------------------------------------------------------------- /memory_class.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// Class containing memory functions 5 | /// 6 | class memory_class 7 | { 8 | public: 9 | /// 10 | /// Base address of the target program 11 | /// 12 | uint64_t target_base = 0x0; 13 | 14 | /// 15 | /// Initializes the memory class 16 | /// 17 | /// true = success false = fail 18 | inline bool init_mem() 19 | { 20 | //system("cls"); 21 | //printf("Init Memory... \n"); 22 | 23 | if (get_pid()) 24 | { 25 | //printf("PID: %d \n", target_pid); 26 | 27 | if (get_module()) 28 | { 29 | //printf("Module: %d \n", target_base); 30 | 31 | return true; 32 | } 33 | } 34 | 35 | return false; 36 | } 37 | 38 | /// 39 | /// Grabs the process identifier of the target program 40 | /// 41 | /// PID = success 0 = fail 42 | inline uint32_t get_pid() 43 | { 44 | PROCESSENTRY32 process_info; 45 | 46 | HANDLE process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 47 | if (process_snapshot == INVALID_HANDLE_VALUE) 48 | return 0; 49 | 50 | Process32First(process_snapshot, &process_info); 51 | if (!strcmp(process_info.szExeFile, target_name.c_str())) 52 | { 53 | CloseHandle(process_snapshot); 54 | } 55 | 56 | while (Process32Next(process_snapshot, &process_info)) 57 | { 58 | if (!strcmp(process_info.szExeFile, target_name.c_str())) 59 | { 60 | CloseHandle(process_snapshot); 61 | } 62 | } 63 | 64 | target_pid = (uint32_t)process_info.th32ProcessID; 65 | return target_pid; 66 | } 67 | 68 | /// 69 | /// Grabs target handle and base address 70 | /// 71 | /// BASE = success 0 = fail 72 | inline uint64_t get_module() 73 | { 74 | HMODULE h_modules[1024]; 75 | DWORD pcb_needed; 76 | 77 | target_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, target_pid); 78 | 79 | if (K32EnumProcessModules(target_handle, h_modules, sizeof(h_modules), &pcb_needed)) 80 | { 81 | for (unsigned int i = 0; i < (pcb_needed / sizeof(HMODULE)); i++) 82 | { 83 | TCHAR module_name[MAX_PATH]; 84 | if (GetModuleFileNameEx(target_handle, h_modules[i], module_name, sizeof(module_name) / sizeof(TCHAR))) 85 | { 86 | std::string str_module_name = module_name; 87 | if (str_module_name.find(target_name) != std::string::npos) 88 | { 89 | target_base = (uint64_t)h_modules[i]; 90 | return target_base; 91 | } 92 | } 93 | } 94 | } 95 | 96 | return 0; 97 | } 98 | 99 | /// 100 | /// Template for reading memory from the target process 101 | /// 102 | /// Type of memory to read 103 | /// Address to read inside of target 104 | /// Buffer returned from ReadProcessMemory 105 | template 106 | T read(uintptr_t address) 107 | { 108 | T buffer; 109 | ReadProcessMemory(target_handle, (LPCVOID)address, &buffer, sizeof(T), NULL); 110 | return buffer; 111 | } 112 | 113 | /// 114 | /// Template for writing memory into the target process 115 | /// 116 | /// Type of memory to write 117 | /// Address to write buffer into 118 | /// What to write into targeted address 119 | template 120 | void write(uintptr_t address, T buffer) 121 | { 122 | WriteProcessMemory(target_handle, (LPVOID)address, &buffer, sizeof(buffer), NULL); 123 | } 124 | 125 | private: 126 | uint32_t target_pid = 0x0; 127 | HANDLE target_handle = 0x0; 128 | 129 | std::string target_name = "RainbowSix.exe"; 130 | }; 131 | 132 | 133 | /// 134 | /// Handler of memory class 135 | /// 136 | memory_class memory; -------------------------------------------------------------------------------- /vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef VECTOR_H 4 | #define VECTOR_H 5 | 6 | #include 7 | 8 | #define M_PI 3.14159265358979323846264338327950288419716939937510 9 | 10 | class Vector2 11 | { 12 | public: 13 | Vector2() : x(0.f), y(0.f) 14 | { 15 | 16 | } 17 | 18 | Vector2(float _x, float _y) : x(_x), y(_y) 19 | { 20 | 21 | } 22 | ~Vector2() 23 | { 24 | 25 | } 26 | 27 | float x; 28 | float y; 29 | 30 | 31 | bool equals(Vector2 other) { 32 | return (x == other.x && y == other.y); 33 | } 34 | 35 | }; 36 | 37 | class Vector3 38 | { 39 | public: 40 | float x; 41 | float y; 42 | float z; 43 | 44 | Vector3(); 45 | Vector3(float x, float y, float z); 46 | 47 | Vector3 operator+(const Vector3& vector) const; 48 | Vector3 operator-(const Vector3& vector) const; 49 | Vector3 operator-() const; 50 | Vector3 operator*(float number) const; 51 | Vector3 operator/(float number) const; 52 | 53 | Vector3& operator+=(const Vector3& vector); 54 | Vector3& operator-=(const Vector3& vector); 55 | Vector3& operator*=(float number); 56 | Vector3& operator/=(float number); 57 | 58 | bool operator==(const Vector3& vector) const; 59 | bool operator!=(const Vector3& vector) const; 60 | 61 | inline float Dot(const Vector3& vector) 62 | { 63 | return x * vector.x + y * vector.y + z * vector.z; 64 | } 65 | 66 | inline float Distance(const Vector3& vector) 67 | { 68 | float xCoord = vector.x - x; 69 | float yCoord = vector.y - y; 70 | float zCoord = vector.z - z; 71 | return sqrtf((xCoord * xCoord) + (yCoord * yCoord) + (zCoord * zCoord)); 72 | } 73 | 74 | inline float Length() 75 | { 76 | return sqrt((x * x) + (y * y) + (z * z)); 77 | } 78 | 79 | inline void Rotate2D(float angle) 80 | { 81 | // use local variables to find transformed components 82 | float Vx1 = cosf(angle) * x - sinf(angle) * y; 83 | float Vy1 = sinf(angle) * x + cosf(angle) * y; 84 | // store results thru the pointer 85 | x = Vx1; 86 | y = Vy1; 87 | 88 | return; 89 | } 90 | 91 | inline void Clamp() 92 | { 93 | if (x > 75.f) x = 75.f; 94 | else if (x < -75.f) x = -75.f; 95 | if (z < -180) z += 360.0f; 96 | else if (z > 180) z -= 360.0f; 97 | 98 | y = 0.f; 99 | } 100 | }; 101 | 102 | inline bool Vector3::operator==(const Vector3& vector) const 103 | { 104 | return x == vector.x && y == vector.y && z == vector.z; 105 | } 106 | 107 | inline bool Vector3::operator!=(const Vector3& vector) const 108 | { 109 | return x != vector.x || y != vector.y || z != vector.z; 110 | } 111 | 112 | inline Vector3 Vector3::operator+(const Vector3& vector) const 113 | { 114 | return Vector3(x + vector.x, y + vector.y, z + vector.z); 115 | } 116 | 117 | inline Vector3 Vector3::operator-(const Vector3& vector) const 118 | { 119 | return Vector3(x - vector.x, y - vector.y, z - vector.z); 120 | } 121 | 122 | inline Vector3 Vector3::operator-() const 123 | { 124 | return Vector3(-x, -y, -z); 125 | } 126 | 127 | inline Vector3 Vector3::operator*(float number) const 128 | { 129 | return Vector3(x * number, y * number, z * number); 130 | } 131 | 132 | inline Vector3 Vector3::operator/(float number) const 133 | { 134 | return Vector3(x / number, y / number, z / number); 135 | } 136 | 137 | inline Vector3::Vector3() 138 | { 139 | } 140 | 141 | inline Vector3::Vector3(float x, float y, float z) 142 | : x(x), y(y), z(z) 143 | { 144 | } 145 | 146 | inline Vector3& Vector3::operator+=(const Vector3& vector) 147 | { 148 | x += vector.x; 149 | y += vector.y; 150 | z += vector.z; 151 | 152 | return *this; 153 | } 154 | 155 | inline Vector3& Vector3::operator-=(const Vector3& vector) 156 | { 157 | x -= vector.x; 158 | y -= vector.y; 159 | z -= vector.z; 160 | 161 | return *this; 162 | } 163 | 164 | inline Vector3& Vector3::operator*=(float number) 165 | { 166 | x *= number; 167 | y *= number; 168 | z *= number; 169 | 170 | return *this; 171 | } 172 | 173 | inline Vector3& Vector3::operator/=(float number) 174 | { 175 | x /= number; 176 | y /= number; 177 | z /= number; 178 | 179 | return *this; 180 | } 181 | 182 | //Quickly needed for distance calculations 183 | float DistanceVec2(Vector2 src, Vector2 dst) 184 | { 185 | float distance; 186 | distance = sqrtf(powf(src.x - dst.x, 2) + powf(src.y - dst.y, 2)); 187 | return distance; 188 | } 189 | 190 | float DistanceVec3(Vector3 src, Vector3 dst) 191 | { 192 | float distance; 193 | distance = sqrtf(powf(src.x - dst.x, 2) + powf(src.y - dst.y, 2) + powf(src.z - dst.z, 2)); 194 | return distance; 195 | } 196 | 197 | class Vector4 198 | { 199 | public: 200 | Vector4() : x(0.f), y(0.f), z(0.f), w(0.f) 201 | { 202 | 203 | } 204 | 205 | Vector4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) 206 | { 207 | 208 | } 209 | ~Vector4() 210 | { 211 | 212 | } 213 | 214 | float x; 215 | float y; 216 | float z; 217 | float w; 218 | }; 219 | 220 | #endif -------------------------------------------------------------------------------- /imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI 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/branch with your modifications to imconfig.h) 7 | // B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h" 8 | // If you do so you need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include 9 | // the imgui*.cpp files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 10 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 11 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. 12 | //----------------------------------------------------------------------------- 13 | 14 | #pragma once 15 | 16 | //---- Define assertion handler. Defaults to calling assert(). 17 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 18 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 19 | 20 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 21 | // 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. 22 | //#define IMGUI_API __declspec( dllexport ) 23 | //#define IMGUI_API __declspec( dllimport ) 24 | 25 | //---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. 26 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 27 | 28 | //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) 29 | // It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp. 30 | //#define IMGUI_DISABLE_DEMO_WINDOWS 31 | //#define IMGUI_DISABLE_METRICS_WINDOW 32 | 33 | //---- Don't implement some functions to reduce linkage requirements. 34 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. 35 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. 36 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). 37 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices'). 38 | //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf. 39 | //#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h. 40 | //#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(). 41 | 42 | //---- Include imgui_user.h at the end of imgui.h as a convenience 43 | //#define IMGUI_INCLUDE_IMGUI_USER_H 44 | 45 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 46 | //#define IMGUI_USE_BGRA_PACKED_COLOR 47 | 48 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 49 | // By default the embedded implementations are declared static and not available outside of imgui cpp files. 50 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 51 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 52 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 53 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 54 | 55 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 56 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 57 | /* 58 | #define IM_VEC2_CLASS_EXTRA \ 59 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 60 | operator MyVec2() const { return MyVec2(x,y); } 61 | 62 | #define IM_VEC4_CLASS_EXTRA \ 63 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 64 | operator MyVec4() const { return MyVec4(x,y,z,w); } 65 | */ 66 | 67 | //---- Using 32-bits vertex indices (default is 16-bits) is one way to allow large meshes with more than 64K vertices. 68 | // Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bits indices). 69 | // Another way to allow large meshes while keeping 16-bits indices is to handle ImDrawCmd::VtxOffset in your renderer. 70 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 71 | //#define ImDrawIdx unsigned int 72 | 73 | //---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly) 74 | //struct ImDrawList; 75 | //struct ImDrawCmd; 76 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 77 | //#define ImDrawCallback MyImDrawCallback 78 | 79 | //---- Debug Tools 80 | // Use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging. 81 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 82 | //#define IM_DEBUG_BREAK __debugbreak() 83 | // Have the Item Picker break in the ItemAdd() function instead of ItemHoverable() - which is earlier in the code, will catch a few extra items, allow picking items other than Hovered one. 84 | // This adds a small runtime cost which is why it is not enabled by default. 85 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX 86 | 87 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 88 | /* 89 | namespace ImGui 90 | { 91 | void MyFunction(const char* name, const MyMatrix44& v); 92 | } 93 | */ 94 | -------------------------------------------------------------------------------- /interface.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "Requests.hpp" 11 | 12 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) 13 | 14 | typedef struct _CALL_DATA 15 | { 16 | PVOID Function; 17 | ULONG_PTR Param; 18 | } CALL_DATA, * PCALL_DATA; 19 | 20 | void CallFunction(PCALL_DATA CallData) 21 | { 22 | using tFn = NTSTATUS(__stdcall*)(UINT_PTR Param1); 23 | const auto fn = static_cast(CallData->Function); 24 | 25 | fn(CallData->Param); 26 | } 27 | 28 | class KernelInterface 29 | { 30 | private: 31 | 32 | REQUEST_PACKET RequestPacket; 33 | HANDLE KernelEvent; 34 | HANDLE UserEvent; 35 | 36 | public: 37 | 38 | HANDLE TargetProcessId; 39 | 40 | NTSTATUS Setup() 41 | { 42 | auto User32Module = LoadLibraryA("user32.dll"); 43 | 44 | if (User32Module == NULL) 45 | { 46 | return STATUS_NOT_FOUND; 47 | } 48 | 49 | 50 | auto Win32uModule = LoadLibraryA("win32u.dll"); 51 | 52 | if (Win32uModule == NULL) 53 | { 54 | return STATUS_NOT_FOUND; 55 | } 56 | 57 | 58 | PVOID ExportedFunction = GetProcAddress(Win32uModule, "NtTokenManagerCreateFlipObjectReturnTokenHandle"); 59 | 60 | if (ExportedFunction == NULL) 61 | { 62 | return STATUS_NOT_FOUND; 63 | } 64 | 65 | 66 | WCHAR Characters[63] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 67 | 68 | WCHAR UserEventName[0xFF] = L"\\BaseNamedObjects\\Global\\"; 69 | WCHAR KernelEventName[0xFF] = L"\\BaseNamedObjects\\Global\\"; 70 | 71 | srand(time(NULL)); 72 | int NameLength = rand() % 8 + 10; 73 | 74 | 75 | for (SIZE_T I = 0; I <= NameLength; I++) 76 | { 77 | UserEventName[I + 25] = Characters[rand() % 62]; 78 | } 79 | 80 | for (SIZE_T I = 0; I <= NameLength; I++) 81 | { 82 | KernelEventName[I + 25] = Characters[rand() % 62]; 83 | } 84 | 85 | this->UserEvent = CreateEventW(NULL, FALSE, FALSE, &UserEventName[18]); 86 | this->KernelEvent = CreateEventW(NULL, FALSE, FALSE, &KernelEventName[18]); 87 | 88 | if (this->UserEvent == NULL || this->KernelEvent == NULL) 89 | { 90 | return STATUS_UNSUCCESSFUL; 91 | } 92 | 93 | INIT_PACKET InitPacket = { }; 94 | 95 | InitPacket.RequestBuffer = &this->RequestPacket; 96 | InitPacket.UserProcessId = (HANDLE)GetCurrentProcessId(); 97 | RtlCopyMemory(InitPacket.KernelEventName, KernelEventName, sizeof(KernelEventName)); 98 | RtlCopyMemory(InitPacket.UserEventName, UserEventName, sizeof(UserEventName)); 99 | 100 | 101 | printf("InitPacket->KernelEventName : %S\n", InitPacket.KernelEventName); 102 | printf("InitPacket->UserEventName : %S\n", InitPacket.UserEventName); 103 | 104 | CALL_DATA CallData = { }; 105 | 106 | CallData.Function = ExportedFunction; 107 | CallData.Param = (ULONG_PTR)&InitPacket; 108 | 109 | CreateThread(0, 0, (LPTHREAD_START_ROUTINE)CallFunction, &CallData, 0, 0); 110 | WaitForSingleObject(this->KernelEvent, 1000 * 60); // 3 minutes 111 | 112 | return InitPacket.IsInitialized ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 113 | } 114 | 115 | NTSTATUS Unload() 116 | { 117 | RtlZeroMemory(&this->RequestPacket, sizeof(this->RequestPacket)); 118 | 119 | this->RequestPacket.Type = RequestType::Unload; 120 | this->RequestPacket.Status = STATUS_PENDING; 121 | 122 | SetEvent(this->UserEvent); 123 | WaitForSingleObject(this->KernelEvent, 1000 * 60); // 3 minutes 124 | 125 | return this->RequestPacket.Status; 126 | } 127 | 128 | void SetTargetProcessId(HANDLE ProcessId) 129 | { 130 | this->TargetProcessId = ProcessId; 131 | } 132 | 133 | UINT_PTR GetMainModule() 134 | { 135 | RtlZeroMemory(&this->RequestPacket, sizeof(this->RequestPacket)); 136 | 137 | MAIN_MODULE_PACKET MainModulePacket = { }; 138 | 139 | MainModulePacket.ProcessId = this->TargetProcessId; 140 | 141 | this->RequestPacket.Type = RequestType::MainModule; 142 | this->RequestPacket.Buffer = &MainModulePacket; 143 | this->RequestPacket.Status = STATUS_PENDING; 144 | 145 | SetEvent(this->UserEvent); 146 | WaitForSingleObject(this->KernelEvent, 1000 * 60); // 3 minutes 147 | 148 | if (!NT_SUCCESS(this->RequestPacket.Status)) 149 | { 150 | return NULL; 151 | } 152 | 153 | return (UINT_PTR)MainModulePacket.Result; 154 | } 155 | 156 | NTSTATUS Read(PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size) 157 | { 158 | RtlZeroMemory(&this->RequestPacket, sizeof(this->RequestPacket)); 159 | 160 | READ_PACKET ReadPacket = { }; 161 | 162 | ReadPacket.ProcessId = this->TargetProcessId; 163 | ReadPacket.Size = Size; 164 | ReadPacket.SourceAddress = SourceAddress; 165 | ReadPacket.TargetAddress = TargetAddress; 166 | 167 | this->RequestPacket.Type = RequestType::ReadMemory; 168 | this->RequestPacket.Buffer = &ReadPacket; 169 | this->RequestPacket.Status = STATUS_PENDING; 170 | 171 | SetEvent(this->UserEvent); 172 | WaitForSingleObject(this->KernelEvent, 1000 * 60); // 3 minutes 173 | 174 | return this->RequestPacket.Status; 175 | } 176 | 177 | template 178 | T Read(UINT_PTR Address) 179 | { 180 | T Buffer = { }; 181 | 182 | if (!NT_SUCCESS(Read((PVOID)Address, &Buffer, sizeof(T)))) 183 | { 184 | RtlZeroMemory(&Buffer, sizeof(Buffer)); 185 | } 186 | 187 | return Buffer; 188 | } 189 | 190 | NTSTATUS Write(PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size) 191 | { 192 | RtlZeroMemory(&this->RequestPacket, sizeof(this->RequestPacket)); 193 | 194 | WRITE_PACKET WritePacket = { }; 195 | 196 | WritePacket.ProcessId = this->TargetProcessId; 197 | WritePacket.Size = Size; 198 | WritePacket.SourceAddress = SourceAddress; 199 | WritePacket.TargetAddress = TargetAddress; 200 | 201 | this->RequestPacket.Type = RequestType::WriteMemory; 202 | this->RequestPacket.Buffer = &WritePacket; 203 | this->RequestPacket.Status = STATUS_PENDING; 204 | 205 | SetEvent(this->UserEvent); 206 | WaitForSingleObject(this->KernelEvent, 1000 * 60); // 3 minutes 207 | 208 | return this->RequestPacket.Status; 209 | } 210 | 211 | template 212 | NTSTATUS Write(UINT_PTR Address, T Buffer) 213 | { 214 | return Write(&Buffer, (PVOID)Address, sizeof(T)); 215 | } 216 | 217 | NTSTATUS WriteToReadOnly(PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size) 218 | { 219 | RtlZeroMemory(&this->RequestPacket, sizeof(this->RequestPacket)); 220 | 221 | FORCE_WRITE_PACKET ForceWritePacket = { }; 222 | 223 | ForceWritePacket.ProcessId = this->TargetProcessId; 224 | ForceWritePacket.Size = Size; 225 | ForceWritePacket.SourceAddress = SourceAddress; 226 | ForceWritePacket.TargetAddress = TargetAddress; 227 | 228 | this->RequestPacket.Type = RequestType::WriteToReadOnly; 229 | this->RequestPacket.Buffer = &ForceWritePacket; 230 | this->RequestPacket.Status = STATUS_PENDING; 231 | 232 | SetEvent(this->UserEvent); 233 | WaitForSingleObject(this->KernelEvent, 1000 * 60); // 3 minutes 234 | 235 | return this->RequestPacket.Status; 236 | } 237 | 238 | template 239 | NTSTATUS WriteToReadOnly(UINT_PTR Address, T Buffer) 240 | { 241 | return WriteToReadOnly(&Buffer, (PVOID)Address, sizeof(T)); 242 | } 243 | 244 | }; -------------------------------------------------------------------------------- /monkeware.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8ad28735-0c4b-4317-b33c-9ee1929168eb} 18 | 19 | 20 | {bf450f78-4535-426e-90a7-01fb179be715} 21 | 22 | 23 | {1597f2ec-9683-4b34-8909-d2b1ded2d66d} 24 | 25 | 26 | {04b28d26-fb88-47d8-af06-9b4091a41e28} 27 | 28 | 29 | {d53235ea-9c4a-4ae1-8ef0-4228ca9d7f99} 30 | 31 | 32 | {9736d72a-5ea8-48b3-b979-58d3be6a75aa} 33 | 34 | 35 | {1a38dd24-89a9-4e14-b380-7a47e1af2053} 36 | 37 | 38 | 39 | 40 | Source Files 41 | 42 | 43 | Resource Files\imgui 44 | 45 | 46 | Resource Files\imgui 47 | 48 | 49 | Resource Files\imgui 50 | 51 | 52 | Resource Files\imgui 53 | 54 | 55 | Resource Files\imgui 56 | 57 | 58 | Resource Files\imgui 59 | 60 | 61 | 62 | 63 | Resource Files\Security 64 | 65 | 66 | Header Files 67 | 68 | 69 | Resource Files\math 70 | 71 | 72 | Header Files\R6 73 | 74 | 75 | Header Files\R6 76 | 77 | 78 | Header Files\R6 79 | 80 | 81 | Header Files\features 82 | 83 | 84 | Header Files\features 85 | 86 | 87 | Header Files\features 88 | 89 | 90 | Header Files\features 91 | 92 | 93 | Header Files\features 94 | 95 | 96 | Header Files\features 97 | 98 | 99 | Header Files\features 100 | 101 | 102 | Header Files\features 103 | 104 | 105 | Header Files\features 106 | 107 | 108 | Header Files\features 109 | 110 | 111 | Header Files\features 112 | 113 | 114 | Header Files\features 115 | 116 | 117 | Header Files\features 118 | 119 | 120 | Header Files\features 121 | 122 | 123 | Resource Files\math 124 | 125 | 126 | Resource Files\Security 127 | 128 | 129 | Resource Files 130 | 131 | 132 | Header Files\menu 133 | 134 | 135 | Resource Files 136 | 137 | 138 | Resource Files\imgui 139 | 140 | 141 | Resource Files\imgui 142 | 143 | 144 | Resource Files\imgui 145 | 146 | 147 | Resource Files\imgui 148 | 149 | 150 | Resource Files\imgui 151 | 152 | 153 | Resource Files\imgui 154 | 155 | 156 | Resource Files\imgui 157 | 158 | 159 | Resource Files\imgui 160 | 161 | 162 | Header Files\features 163 | 164 | 165 | Header Files\features 166 | 167 | 168 | Header Files\features 169 | 170 | 171 | Header Files\features 172 | 173 | 174 | Header Files\features 175 | 176 | 177 | Resource Files\driver 178 | 179 | 180 | Resource Files\driver 181 | 182 | 183 | -------------------------------------------------------------------------------- /aimbot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | std::vector entityList = {}; 4 | 5 | uint64_t GetEntityList() 6 | { 7 | uint64_t entityList = Interface->Read(game_manager() + 0xE0); 8 | entityList ^= 0x53; 9 | entityList += 0xEEBD43B91E3D5D54; 10 | entityList ^= 0x1FEC13843E78A654; 11 | 12 | return entityList; 13 | } 14 | 15 | int GetEntityCount() 16 | { 17 | uint64_t entityCount = Interface->Read(game_manager() +0xE8); 18 | entityCount ^= 0x53; 19 | entityCount += 0xEEBD43B91E3D5D54; 20 | entityCount ^= 0x1FEC13843E78A654; 21 | int count = (int)(entityCount ^ 0x18C0000000); 22 | 23 | return count; 24 | } 25 | 26 | uint64_t GetEntityByID(int id) 27 | { 28 | uint64_t entityList = GetEntityList(); 29 | if (!entityList) 30 | return NULL; 31 | 32 | uint64_t entity = Interface->Read(entityList + (sizeof(PVOID) * id)); 33 | if (!entity) 34 | return NULL; 35 | 36 | return entity; 37 | } 38 | 39 | uint64_t DecryptEntityInfo(uint64_t entity) 40 | { 41 | uint64_t info = Interface->Read(entity + 0x50); 42 | info = __ROL8__(info, 1); 43 | info -= 0x53; 44 | info = info ^ 0x84B4E3BD4F9014AF; 45 | 46 | return info; 47 | } 48 | 49 | inline BYTE entity_team(uint64_t entity) 50 | { 51 | uint64_t teamInfo = Interface->Read(entity + 0xD0); 52 | teamInfo = Interface->Read(teamInfo + 0x98); 53 | teamInfo = __ROL8__(teamInfo, 0x33); 54 | teamInfo += 0xDE627E1C01E6C58F; 55 | teamInfo = __ROL8__(teamInfo, 0x2B); 56 | BYTE team = Interface->Read(teamInfo + 0x30); 57 | 58 | return team; 59 | } 60 | 61 | inline void set_entity_team(uint64_t entity, BYTE team) 62 | { 63 | uint64_t teamInfo = Interface->Read(entity + 0xD0); 64 | teamInfo = Interface->Read(teamInfo + 0x98); 65 | teamInfo = __ROL8__(teamInfo, 0x33); 66 | teamInfo += 0xDE627E1C01E6C58F; 67 | teamInfo = __ROL8__(teamInfo, 0x2B); 68 | Interface->Write(teamInfo + 0x30, team); 69 | } 70 | 71 | inline int32_t entity_health(uint64_t entity) 72 | { 73 | uint64_t tmp = DecryptEntityInfo(entity); 74 | tmp = Interface->Read(tmp + 0x18); 75 | tmp = Interface->Read(tmp + 0xD8); 76 | tmp = Interface->Read(tmp + 0x8); 77 | 78 | return Interface->Read(tmp + 0x170); 79 | } 80 | 81 | inline Vector3 entity_bone(uint64_t entity, uint32_t bone) 82 | { 83 | uint64_t tmp = DecryptEntityInfo(entity); 84 | 85 | return Interface->Read(tmp + (uint64_t)bone); 86 | } 87 | 88 | bool PopulateEntityList(std::vector& players) 89 | { 90 | BYTE localTeam = entity_team(get_localplayer()); 91 | 92 | int size = GetEntityCount(); 93 | 94 | if (size > 255) 95 | return false; 96 | 97 | entityList.resize(size); 98 | 99 | for (int i = 0; i < size; i++) 100 | { 101 | uint64_t player = GetEntityByID(i); 102 | 103 | if (player == 0) 104 | continue; 105 | 106 | if (entity_health(player) <= 20) 107 | continue; 108 | 109 | if (player == get_localplayer()) 110 | continue; 111 | 112 | if (entity_team(player) == localTeam) 113 | continue; 114 | 115 | players.at(i) = player; 116 | } 117 | return true; 118 | } 119 | 120 | bool IsEnemy(uint64_t entity) 121 | { 122 | if (entity == 0) return false; 123 | 124 | if (get_localplayer() == entity) return false; 125 | 126 | if (features::team_aim_enabled_state == false) 127 | { 128 | if (entity_team(get_localplayer()) == entity_team(entity)) return false; //Comment out if you want this to work for teamates/NPC's 129 | } 130 | 131 | return true; 132 | } 133 | 134 | // --- Camera Functions 135 | 136 | Vector3 view_translation; 137 | 138 | inline uint64_t game_camera() 139 | { 140 | uint64_t tmp = Interface->Read(profile_manager() +0x88); 141 | tmp = Interface->Read(tmp + 0x0); 142 | tmp = Interface->Read(tmp + 0x218); 143 | tmp = Interface->Read(tmp + 0x410); 144 | 145 | return tmp; 146 | } 147 | 148 | inline Vector3 GetViewRight() 149 | { 150 | return Interface->Read(game_camera() + 0x7A0); 151 | } 152 | 153 | inline Vector3 GetViewUp() 154 | { 155 | return Interface->Read(game_camera() + 0x7B0); 156 | } 157 | 158 | inline Vector3 GetViewForward() 159 | { 160 | return Interface->Read(game_camera() + 0x7C0); 161 | } 162 | 163 | inline Vector3 GetViewTranslation() 164 | { 165 | return Interface->Read(game_camera() + 0x7D0); 166 | } 167 | 168 | float GetViewFovX() 169 | { 170 | return Interface->Read(game_camera() + 0x7E0); 171 | } 172 | 173 | float GetViewFovY() 174 | { 175 | return Interface->Read(game_camera() + 0x7F4); 176 | } 177 | 178 | bool WorldToScreen(Vector3 position, Vector2& Screen) 179 | { 180 | uint64_t cam = game_camera(); 181 | Vector3 temp = position - GetViewTranslation(); 182 | float x = temp.Dot(GetViewRight()); 183 | float y = temp.Dot(GetViewUp()); 184 | float z = temp.Dot(GetViewForward() * -1.f); 185 | 186 | int width = 1920; 187 | int height = 1080; 188 | 189 | Screen.x = (width / 2.f) * (1.f + x / GetViewFovX() / z); 190 | Screen.y = (height / 2.f) * (1.f - y / GetViewFovY() / z); 191 | 192 | return z >= 1.0f ? true : false; 193 | } 194 | 195 | Vector4 CalculateQuaternion(Vector3 euler) 196 | { 197 | Vector4 result{}; 198 | 199 | auto yaw = (euler.z * 0.01745329251f) * 0.5f; 200 | auto sy = std::sin(yaw); 201 | auto cy = std::cos(yaw); 202 | 203 | auto roll = (euler.x * 0.01745329251f) * 0.5f; 204 | auto sr = std::sin(roll); 205 | auto cr = std::cos(roll); 206 | 207 | constexpr auto sp = 0.f; 208 | constexpr auto cp = 1.f; 209 | 210 | result.x = cy * sr * cp - sy * cr * sp; 211 | result.y = cy * cr * sp + sy * sr * cp; 212 | result.z = sy * cr * cp - cy * sr * sp; 213 | result.w = cy * cr * cp + sy * sr * sp; 214 | 215 | return result; 216 | } 217 | 218 | void SetAngles(Vector3 angles) 219 | { 220 | Vector4 quat = CalculateQuaternion(angles); 221 | 222 | uint64_t holder = DecryptEntityInfo(get_localplayer()); 223 | uint64_t skeleton = Interface->Read(holder + 0x1270); 224 | 225 | Interface->Write(skeleton + 0xC0, quat); 226 | } 227 | 228 | void set_gun_angles(Vector3 angles) 229 | { 230 | Interface->Write(get_weapon_info() + 0x148, angles); 231 | } 232 | 233 | Vector3 CalcAngle(Vector3 enemyPos, Vector3 cameraPos) 234 | { 235 | Vector3 dir = enemyPos - cameraPos; 236 | float x = asinf(dir.z / dir.Length()) * 57.2957795131f; 237 | 238 | float z = atanf(dir.y / dir.x) * 57.2957795131f; 239 | 240 | if (dir.x >= 0.f) z += 180.f; 241 | if (x > 179.99f) x -= 360.f; 242 | else if (x < -179.99f) x += 360.f; 243 | 244 | return Vector3(x, 0.f, z + 90.f); 245 | } 246 | 247 | uint64_t GetClosestEntityToCrosshair() 248 | { 249 | float oDist = FLT_MAX; 250 | float nDist = 0; 251 | uint64_t cur = NULL; 252 | uint64_t target = NULL; 253 | Vector2 screenPos; 254 | Vector2 screenCenter = { (1920 / 2), (1080 / 2) }; 255 | float fov = features::aim_fov; 256 | 257 | for (int i = 0; i < GetEntityCount(); i++) 258 | { 259 | cur = GetEntityByID(i); 260 | if (cur == 0) continue; 261 | 262 | if (WorldToScreen(entity_bone(cur, entity_bones::head), screenPos)) 263 | { 264 | nDist = DistanceVec2(screenCenter, screenPos); 265 | 266 | if (nDist < fov && nDist < oDist) 267 | { 268 | oDist = nDist; 269 | target = cur; 270 | } 271 | } 272 | } 273 | return target; 274 | } 275 | 276 | uint64_t GetClosestEntityToHead() 277 | { 278 | float oDist = FLT_MAX; 279 | float nDist = 0; 280 | uint64_t cur = NULL; 281 | uint64_t target = NULL; 282 | Vector2 screenPos; 283 | 284 | for (int i = 0; i < GetEntityCount(); i++) 285 | { 286 | cur = GetEntityByID(i); 287 | 288 | if (!IsEnemy(cur)) 289 | continue; 290 | 291 | if (WorldToScreen(entity_bone(cur, entity_bones::head), screenPos)) 292 | { 293 | nDist = DistanceVec3(entity_bone(get_localplayer(), entity_bones::head), entity_bone(cur, entity_bones::head)); 294 | 295 | if (nDist < oDist) 296 | { 297 | oDist = nDist; 298 | target = cur; 299 | } 300 | } 301 | } 302 | 303 | return target; 304 | } 305 | 306 | inline void aimbot() 307 | { 308 | uint64_t target = GetClosestEntityToCrosshair(); if (!IsEnemy(target)) return; 309 | Vector3 angles = CalcAngle(entity_bone(target, entity_bones::head), GetViewTranslation()); angles.Clamp(); 310 | if (GetAsyncKeyState(key)) 311 | { 312 | SetAngles(angles); 313 | } 314 | } 315 | 316 | inline Vector3 clamp_angles(Vector3 angles) 317 | { 318 | Vector3 clamped = angles; 319 | 320 | if (clamped.y > 179.f) 321 | clamped.y -= 360.f; 322 | 323 | else if (clamped.y < -179.f) 324 | clamped.y += 360.f; 325 | 326 | if (clamped.z > 179.f) 327 | clamped.z -= 360.f; 328 | 329 | else if (clamped.z < -179.f) 330 | clamped.z += 360.f; 331 | 332 | if (clamped.y < -89.f) 333 | clamped.y = -89.f; 334 | 335 | if (clamped.y > 89.f) 336 | clamped.y = 89.f; 337 | 338 | while (clamped.z < -179.0f) 339 | clamped.z += 360.0f; 340 | 341 | while (clamped.z > 179.0f) 342 | clamped.z -= 360.0f; 343 | 344 | return clamped; 345 | } -------------------------------------------------------------------------------- /xor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2020 Justas Masiulis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef JM_XORSTR_HPP 18 | #define JM_XORSTR_HPP 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define xorstr(str) \ 26 | ::jm::make_xorstr( \ 27 | []() { return str; }, \ 28 | std::make_index_sequence{}, \ 29 | std::make_index_sequence<::jm::detail::_buffer_size()>{}) 30 | #define xorstr_(str) xorstr(str).crypt_get() 31 | 32 | #ifdef _MSC_VER 33 | #define XORSTR_FORCEINLINE __forceinline 34 | #else 35 | #define XORSTR_FORCEINLINE __attribute__((always_inline)) inline 36 | #endif 37 | 38 | namespace jm { 39 | 40 | namespace detail { 41 | 42 | template 43 | struct unsigned_; 44 | 45 | template<> 46 | struct unsigned_<1> { 47 | using type = std::uint8_t; 48 | }; 49 | template<> 50 | struct unsigned_<2> { 51 | using type = std::uint16_t; 52 | }; 53 | template<> 54 | struct unsigned_<4> { 55 | using type = std::uint32_t; 56 | }; 57 | 58 | template 59 | struct pack_value_type { 60 | using type = decltype(C); 61 | }; 62 | 63 | template 64 | XORSTR_FORCEINLINE constexpr std::size_t _buffer_size() 65 | { 66 | return ((Size / 16) + (Size % 16 != 0)) * 2; 67 | } 68 | 69 | template 70 | struct tstring_ { 71 | using value_type = typename pack_value_type::type; 72 | constexpr static std::size_t size = sizeof...(Cs); 73 | constexpr static value_type str[size] = { Cs... }; 74 | 75 | constexpr static std::size_t buffer_size = _buffer_size(); 76 | constexpr static std::size_t buffer_align = 77 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS 78 | ((sizeof(str) > 16) ? 32 : 16); 79 | #else 80 | 16; 81 | #endif 82 | }; 83 | 84 | template 85 | struct _ki { 86 | constexpr static std::size_t idx = I; 87 | constexpr static std::uint64_t key = K; 88 | }; 89 | 90 | template 91 | XORSTR_FORCEINLINE constexpr std::uint32_t key4() noexcept 92 | { 93 | std::uint32_t value = Seed; 94 | for (char c : __TIME__) 95 | value = static_cast((value ^ c) * 16777619ull); 96 | return value; 97 | } 98 | 99 | template 100 | XORSTR_FORCEINLINE constexpr std::uint64_t key8() 101 | { 102 | constexpr auto first_part = key4<2166136261 + S>(); 103 | constexpr auto second_part = key4(); 104 | return (static_cast(first_part) << 32) | second_part; 105 | } 106 | 107 | // loads up to 8 characters of string into uint64 and xors it with the key 108 | template 109 | XORSTR_FORCEINLINE constexpr std::uint64_t 110 | load_xored_str8(std::uint64_t key, std::size_t idx) noexcept 111 | { 112 | using cast_type = typename unsigned_::type; 113 | constexpr auto value_size = sizeof(typename T::value_type); 114 | constexpr auto idx_offset = 8 / value_size; 115 | 116 | std::uint64_t value = key; 117 | for (std::size_t i = 0; i < idx_offset && i + idx * idx_offset < T::size; ++i) 118 | value ^= 119 | (std::uint64_t{ static_cast(T::str[i + idx * idx_offset]) } 120 | << ((i % idx_offset) * 8 * value_size)); 121 | 122 | return value; 123 | } 124 | 125 | // forces compiler to use registers instead of stuffing constants in rdata 126 | XORSTR_FORCEINLINE std::uint64_t load_from_reg(std::uint64_t value) noexcept 127 | { 128 | #if defined(__clang__) || defined(__GNUC__) 129 | asm("" : "=r"(value) : "0"(value) : ); 130 | #endif 131 | return value; 132 | } 133 | 134 | XORSTR_FORCEINLINE void xor128(std::uint64_t* value, 135 | const std::uint64_t* key) noexcept 136 | { 137 | _mm_store_si128( 138 | reinterpret_cast<__m128i*>(value), 139 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(value)), 140 | _mm_load_si128(reinterpret_cast(key)))); 141 | } 142 | 143 | XORSTR_FORCEINLINE void xor256(std::uint64_t* value, 144 | const std::uint64_t* key) noexcept 145 | { 146 | _mm256_store_si256( 147 | reinterpret_cast<__m256i*>(value), 148 | _mm256_xor_si256( 149 | _mm256_load_si256(reinterpret_cast(value)), 150 | _mm256_load_si256(reinterpret_cast(key)))); 151 | } 152 | 153 | template 154 | struct uint64_v { 155 | constexpr static std::uint64_t value = V; 156 | }; 157 | 158 | } // namespace detail 159 | 160 | template 161 | class xor_string { 162 | alignas(T::buffer_align) std::uint64_t _storage[T::buffer_size]; 163 | 164 | template 165 | XORSTR_FORCEINLINE void _crypt_256(const std::uint64_t* keys, 166 | std::index_sequence) noexcept 167 | { 168 | (detail::xor256(_storage + Idxs * 4, keys + Idxs * 4), ...); 169 | } 170 | 171 | template 172 | XORSTR_FORCEINLINE void _crypt_128(const std::uint64_t* keys, 173 | std::index_sequence) noexcept 174 | { 175 | (detail::xor128(_storage + Idxs * 2, keys + Idxs * 2), ...); 176 | } 177 | 178 | public: 179 | using value_type = typename T::value_type; 180 | using size_type = std::size_t; 181 | using pointer = value_type*; 182 | using const_pointer = const value_type*; 183 | 184 | XORSTR_FORCEINLINE xor_string() noexcept 185 | : _storage{ detail::load_from_reg(detail::uint64_v( 186 | Keys::key, Keys::idx)>::value)... } 187 | {} 188 | 189 | XORSTR_FORCEINLINE constexpr size_type size() const noexcept 190 | { 191 | return T::size - 1; 192 | } 193 | 194 | XORSTR_FORCEINLINE void crypt() noexcept 195 | { 196 | #if defined(__clang__) 197 | alignas(T::buffer_align) 198 | std::uint64_t arr[sizeof...(Keys)]{ detail::load_from_reg(Keys::key)... }; 199 | std::uint64_t* keys = 200 | (std::uint64_t*)detail::load_from_reg((std::uint64_t)arr); 201 | #else 202 | alignas(T::buffer_align) std::uint64_t keys[sizeof...(Keys)]{ 203 | detail::load_from_reg(Keys::key)... 204 | }; 205 | #endif 206 | 207 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS 208 | _crypt_256(keys, std::make_index_sequence{}); 209 | if constexpr (T::buffer_size % 4 != 0) 210 | _crypt_128(keys, std::index_sequence{}); 211 | #else 212 | _crypt_128(keys, std::make_index_sequence{}); 213 | #endif 214 | } 215 | 216 | XORSTR_FORCEINLINE const_pointer get() const noexcept 217 | { 218 | return reinterpret_cast(_storage); 219 | } 220 | 221 | XORSTR_FORCEINLINE pointer get() noexcept 222 | { 223 | return reinterpret_cast(_storage); 224 | } 225 | 226 | XORSTR_FORCEINLINE pointer crypt_get() noexcept 227 | { 228 | crypt(); 229 | return (pointer)(_storage); 230 | } 231 | }; 232 | 233 | template 234 | XORSTR_FORCEINLINE constexpr auto 235 | make_xorstr(Tstr str_lambda, 236 | std::index_sequence, 237 | std::index_sequence) noexcept 238 | { 239 | return xor_string, 240 | detail::_ki()>...>{}; 241 | } 242 | 243 | } // namespace jm 244 | 245 | #endif // include guard -------------------------------------------------------------------------------- /monkeware.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {3b6b1b3c-104f-465b-8e1a-5eaa48660852} 25 | monkeware 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | stdcpp17 134 | 135 | 136 | Console 137 | true 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /menu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool show_aim_tab = true; 4 | bool show_weapon_tab = false; 5 | bool show_visual_tab = false; 6 | bool show_misc_tab = false; 7 | 8 | static LPDIRECT3D9 g_pD3D = NULL; 9 | static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; 10 | static D3DPRESENT_PARAMETERS g_d3dpp = {}; 11 | 12 | // Forward declarations of helper functions 13 | bool CreateDeviceD3D(HWND hWnd); 14 | void CleanupDeviceD3D(); 15 | void ResetDevice(); 16 | LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 17 | 18 | static int draw_menu() 19 | { 20 | WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, (_T("Monkehook")), NULL }; 21 | ::RegisterClassEx(&wc); 22 | HWND hwnd = ::CreateWindow(wc.lpszClassName, (_T("Monkehook")), WS_TILEDWINDOW, 100, 100, 415.5, 428.4, NULL, NULL, wc.hInstance, NULL); 23 | 24 | if (!CreateDeviceD3D(hwnd)) 25 | { 26 | CleanupDeviceD3D(); 27 | ::UnregisterClass(wc.lpszClassName, wc.hInstance); 28 | return 0; 29 | } 30 | 31 | ::ShowWindow(hwnd, SW_SHOWDEFAULT); 32 | ::UpdateWindow(hwnd); 33 | IMGUI_CHECKVERSION(); 34 | ImGui::CreateContext(); 35 | ImGuiIO& io = ImGui::GetIO(); (void)io; 36 | 37 | //ImGui style 38 | ImGui::CustomStyle(); 39 | 40 | ImGui_ImplWin32_Init(hwnd); 41 | ImGui_ImplDX9_Init(g_pd3dDevice); 42 | 43 | ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); 44 | 45 | MSG msg; 46 | ZeroMemory(&msg, sizeof(msg)); 47 | while (msg.message != WM_QUIT) 48 | { 49 | 50 | if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) 51 | { 52 | ::TranslateMessage(&msg); 53 | ::DispatchMessage(&msg); 54 | continue; 55 | } 56 | ImGui_ImplDX9_NewFrame(); 57 | ImGui_ImplWin32_NewFrame(); 58 | ImGui::NewFrame(); 59 | { 60 | //Draw here 61 | ImGui::SetNextWindowSize({ 400, 390 }, ImGuiCond_Always); 62 | ImGui::SetNextWindowPos(ImVec2(-1, 0)); 63 | ImGui::SetNextWindowCollapsed(false); 64 | ImGui::Begin(xorstr_(" "), reinterpret_cast(true), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); 65 | ImGui::Dummy({ 0, 1 }); 66 | ImGui::Text(" Monkehook | "); 67 | ImGui::SameLine(); 68 | if (ImGui::Button(xorstr_(" Aimbot "))) 69 | { 70 | show_aim_tab = true; 71 | show_weapon_tab = false; 72 | show_visual_tab = false; 73 | show_misc_tab = false; 74 | } 75 | ImGui::SameLine(); 76 | if (ImGui::Button(xorstr_(" Weapon "))) 77 | { 78 | show_aim_tab = false; 79 | show_weapon_tab = true; 80 | show_visual_tab = false; 81 | show_misc_tab = false; 82 | } 83 | ImGui::SameLine(); 84 | if (ImGui::Button(xorstr_(" Visual "))) 85 | { 86 | show_aim_tab = false; 87 | show_weapon_tab = false; 88 | show_visual_tab = true; 89 | show_misc_tab = false; 90 | } 91 | ImGui::SameLine(); 92 | if (ImGui::Button(xorstr_(" Misc "))) 93 | { 94 | show_aim_tab = false; 95 | show_weapon_tab = false; 96 | show_visual_tab = false; 97 | show_misc_tab = true; 98 | } 99 | ImGui::Dummy({ 0, 5 }); 100 | ImGui::Separator(); 101 | ImGui::NewLine(); 102 | if (show_aim_tab == true) 103 | { 104 | ImGui::Checkbox(xorstr_(" Aimbot"), &features::aim_enabled_state); 105 | ImGui::Dummy({ 0, 1 }); 106 | ImGui::Checkbox(xorstr_(" Team"), &features::team_aim_enabled_state); 107 | ImGui::Dummy({ 0, 1 }); 108 | ImGui::SliderFloat(xorstr_(" FOV"), &features::aim_fov, 0.f, 3600.f); 109 | ImGui::Dummy({ 0, 2 }); 110 | ImGui::Combo(" Key##", &key_setting, key_options, IM_ARRAYSIZE(key_options)); 111 | ImGui::Dummy({ 0, 2 }); 112 | } 113 | if (show_weapon_tab == true) 114 | { 115 | ImGui::Checkbox(xorstr_(" Recoil"), &features::nr_enabled_state); 116 | ImGui::Dummy({ 0, 1 }); 117 | ImGui::SliderFloat(xorstr_(" Recoil##"), &features::recoil, 0.f, 1.f); 118 | ImGui::Dummy({ 0, 2 }); 119 | ImGui::Checkbox(xorstr_(" Spread"), &features::ns_enabled_state); 120 | ImGui::Dummy({ 0, 1 }); 121 | ImGui::SliderFloat(xorstr_(" Spread##"), &features::spread, 0.f, 1.f); 122 | ImGui::Dummy({ 0, 2 }); 123 | ImGui::Checkbox(xorstr_(" Firemode"), &features::firemode_state_enable); 124 | ImGui::Dummy({ 0, 2 }); 125 | ImGui::Combo(" Key##", &firemode_setting, firemode_options, IM_ARRAYSIZE(firemode_options)); 126 | ImGui::Dummy({ 0, 2 }); 127 | } 128 | if (show_visual_tab == true) 129 | { 130 | ImGui::Checkbox(xorstr_(" Cav ESP"), &features::cav_enabled_state); 131 | ImGui::Dummy({ 0, 1 }); 132 | ImGui::Checkbox(xorstr_(" Instant ADS"), &features::ads_enabled_state); 133 | ImGui::Dummy({ 0, 1 }); 134 | ImGui::Checkbox(xorstr_(" Spoof spectate"), &features::spectate_enabled_state); 135 | ImGui::Dummy({ 0, 1 }); 136 | ImGui::Checkbox(xorstr_(" No flash"), &features::flash_enabled_state); 137 | ImGui::Dummy({ 0, 1 }); 138 | ImGui::Checkbox(xorstr_(" Fullbright"), &features::fullbright_enabled_state); 139 | ImGui::Dummy({ 0, 1 }); 140 | ImGui::Checkbox(xorstr_(" Gun FOV"), &features::gfov_enabled_state); 141 | ImGui::Dummy({ 0, 1 }); 142 | ImGui::SliderFloat(xorstr_(" FOV"), &features::gun_fov, 0.f, 5.f); 143 | ImGui::Dummy({ 0, 2 }); 144 | ImGui::Checkbox(xorstr_(" Player FOV"), &features::pfov_enabled_state); 145 | ImGui::Dummy({ 0, 1 }); 146 | ImGui::SliderFloat(xorstr_(" FOV##"), &features::player_fov, 0.f, 5.f); 147 | ImGui::Dummy({ 0, 2 }); 148 | ImGui::Checkbox(xorstr_(" Glow"), &features::glow_enabled_state); 149 | ImGui::Dummy({ 0, 2 }); 150 | ImGui::SliderFloat(xorstr_(" R"), &features::glow_RGB[0], -255.f, 255.f); 151 | ImGui::Dummy({ 0, 1 }); 152 | ImGui::SliderFloat(xorstr_(" G"), &features::glow_RGB[1], -255.f, 255.f); 153 | ImGui::Dummy({ 0, 1 }); 154 | ImGui::SliderFloat(xorstr_(" B"), &features::glow_RGB[2], -255.f, 255.f); 155 | ImGui::Dummy({ 0, 2 }); 156 | } 157 | if (show_misc_tab == true) 158 | { 159 | ImGui::Checkbox(xorstr_(" Run and shoot"), &features::ras_enabled_state); 160 | ImGui::Dummy({ 0, 1 }); 161 | ImGui::Checkbox(xorstr_(" Unlock all"), &features::ua_state_enable); 162 | ImGui::Dummy({ 0, 1 }); 163 | ImGui::Checkbox(xorstr_(" Ladder launch"), &features::ladder_enabled_state); 164 | ImGui::Dummy({ 0, 1 }); 165 | ImGui::Checkbox(xorstr_(" Knfe through walls"), &features::knife_wall_enbaled); 166 | ImGui::Dummy({ 0, 1 }); 167 | ImGui::Checkbox(xorstr_(" Long knife"), &features::knife_enabled_state); 168 | ImGui::Dummy({ 0, 1 }); 169 | ImGui::SliderFloat(xorstr_(" Reach"), &features::knife_distance, 0.f, 1000.f); 170 | ImGui::Dummy({ 0, 1 }); 171 | ImGui::Checkbox(xorstr_(" Noclip"), &features::noclip_state_enable); 172 | ImGui::Dummy({ 0, 1 }); 173 | ImGui::Combo(" Key ##", &noclip_bind, noclip_item, IM_ARRAYSIZE(noclip_item)); 174 | ImGui::Dummy({ 0, 2 }); 175 | ImGui::Checkbox(xorstr_(" Speed"), &features::speed_state_enable); 176 | ImGui::Dummy({ 0, 1 }); 177 | ImGui::SliderInt(xorstr_(" Speed##"), &features::player_speed, 0, 350); 178 | ImGui::Dummy({ 0, 2 }); 179 | ImGui::Combo(" Key##", &speed_bind, speed_item, IM_ARRAYSIZE(speed_item)); 180 | ImGui::Dummy({ 0, 2 }); 181 | ImGui::NewLine(); 182 | ImGui::Text("Preformance"); 183 | ImGui::Separator(); 184 | ImGui::NewLine(); 185 | ImGui::SliderInt(xorstr_(" Aim thread sleep"), &sleep_aim, 1, 1000); 186 | } 187 | ImGui::End(); 188 | //Draw here 189 | } 190 | ImGui::EndFrame(); 191 | g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE); 192 | g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 193 | g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); 194 | D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x * 255.0f), (int)(clear_color.y * 255.0f), (int)(clear_color.z * 255.0f), (int)(clear_color.w * 255.0f)); 195 | g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0); 196 | if (g_pd3dDevice->BeginScene() >= 0) 197 | { 198 | ImGui::Render(); 199 | ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); 200 | g_pd3dDevice->EndScene(); 201 | } 202 | HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL); 203 | if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) 204 | ResetDevice(); 205 | } 206 | 207 | ImGui_ImplDX9_Shutdown(); 208 | ImGui_ImplWin32_Shutdown(); 209 | ImGui::DestroyContext(); 210 | 211 | CleanupDeviceD3D(); 212 | ::DestroyWindow(hwnd); 213 | ::UnregisterClass(wc.lpszClassName, wc.hInstance); 214 | 215 | return 0; 216 | } 217 | 218 | bool CreateDeviceD3D(HWND hWnd) 219 | { 220 | if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) 221 | return false; 222 | ZeroMemory(&g_d3dpp, sizeof(g_d3dpp)); 223 | g_d3dpp.Windowed = TRUE; 224 | g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 225 | g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; 226 | g_d3dpp.EnableAutoDepthStencil = TRUE; 227 | g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; 228 | g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; 229 | if (g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0) 230 | return false; 231 | 232 | return true; 233 | } 234 | 235 | void CleanupDeviceD3D() 236 | { 237 | if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } 238 | if (g_pD3D) { g_pD3D->Release(); g_pD3D = NULL; } 239 | } 240 | 241 | void ResetDevice() 242 | { 243 | ImGui_ImplDX9_InvalidateDeviceObjects(); 244 | HRESULT hr = g_pd3dDevice->Reset(&g_d3dpp); 245 | if (hr == D3DERR_INVALIDCALL) 246 | IM_ASSERT(0); 247 | ImGui_ImplDX9_CreateDeviceObjects(); 248 | } 249 | 250 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 251 | 252 | LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 253 | { 254 | if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) 255 | return true; 256 | 257 | switch (msg) 258 | { 259 | case WM_SIZE: 260 | if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) 261 | { 262 | g_d3dpp.BackBufferWidth = LOWORD(lParam); 263 | g_d3dpp.BackBufferHeight = HIWORD(lParam); 264 | ResetDevice(); 265 | } 266 | return 0; 267 | case WM_SYSCOMMAND: 268 | if ((wParam & 0xfff0) == SC_KEYMENU) 269 | return 0; 270 | break; 271 | case WM_DESTROY: 272 | ::PostQuitMessage(0); 273 | return 0; 274 | } 275 | return ::DefWindowProc(hWnd, msg, wParam, lParam); 276 | } -------------------------------------------------------------------------------- /defs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | This file contains definitions used by the Hex-Rays decompiler output. 5 | It has type definitions and convenience macros to make the 6 | output more readable. 7 | Copyright (c) 2007-2015 Hex-Rays 8 | */ 9 | 10 | #ifndef HEXRAYS_DEFS_H 11 | #define HEXRAYS_DEFS_H 12 | 13 | #if defined(__GNUC__) 14 | typedef long long ll; 15 | typedef unsigned long long ull; 16 | #define __int64 long long 17 | #define __int32 int 18 | #define __int16 short 19 | #define __int8 char 20 | #define MAKELL(num) num ## LL 21 | #define FMT_64 "ll" 22 | #elif defined(_MSC_VER) 23 | typedef __int64 ll; 24 | typedef unsigned __int64 ull; 25 | #define MAKELL(num) num ## i64 26 | #define FMT_64 "I64" 27 | #elif defined (__BORLANDC__) 28 | typedef __int64 ll; 29 | typedef unsigned __int64 ull; 30 | #define MAKELL(num) num ## i64 31 | #define FMT_64 "L" 32 | #else 33 | #error "unknown compiler" 34 | #endif 35 | typedef unsigned int uint; 36 | typedef unsigned char uchar; 37 | typedef unsigned short ushort; 38 | typedef unsigned long ulong; 39 | 40 | typedef char int8; 41 | typedef signed char sint8; 42 | typedef unsigned char uint8; 43 | typedef short int16; 44 | typedef signed short sint16; 45 | typedef unsigned short uint16; 46 | typedef int int32; 47 | typedef signed int sint32; 48 | typedef unsigned int uint32; 49 | typedef ll int64; 50 | typedef ll sint64; 51 | typedef ull uint64; 52 | 53 | // Partially defined types. They are used when the decompiler does not know 54 | // anything about the type except its size. 55 | #define _BYTE uint8 56 | #define _WORD uint16 57 | #define _DWORD uint32 58 | #define _QWORD uint64 59 | #if !defined(_MSC_VER) 60 | #define _LONGLONG __int128 61 | #endif 62 | 63 | // Non-standard boolean types. They are used when the decompiler can not use 64 | // the standard "bool" type because of the size mistmatch but the possible 65 | // values are only 0 and 1. See also 'BOOL' type below. 66 | typedef int8 _BOOL1; 67 | typedef int16 _BOOL2; 68 | typedef int32 _BOOL4; 69 | 70 | #ifndef _WINDOWS_ 71 | typedef int8 BYTE; 72 | typedef int16 WORD; 73 | typedef int32 DWORD; 74 | typedef int32 LONG; 75 | typedef int BOOL; // uppercase BOOL is usually 4 bytes 76 | #endif 77 | typedef int64 QWORD; 78 | #ifndef __cplusplus 79 | typedef int bool; // we want to use bool in our C programs 80 | #endif 81 | 82 | #define __pure // pure function: always returns the same value, has no 83 | // side effects 84 | 85 | // Non-returning function 86 | #if defined(__GNUC__) 87 | #define __noreturn __attribute__((noreturn)) 88 | #else 89 | #define __noreturn __declspec(noreturn) 90 | #endif 91 | 92 | 93 | #ifndef NULL 94 | #define NULL 0 95 | #endif 96 | 97 | // Some convenience macros to make partial accesses nicer 98 | // first unsigned macros: 99 | #define LOBYTE(x) (*((_BYTE*)&(x))) // low byte 100 | #define LOWORD(x) (*((_WORD*)&(x))) // low word 101 | #define LODWORD(x) (*((_DWORD*)&(x))) // low dword 102 | #define HIBYTE(x) (*((_BYTE*)&(x)+1)) 103 | #define HIWORD(x) (*((_WORD*)&(x)+1)) 104 | #define HIDWORD(x) (*((_DWORD*)&(x)+1)) 105 | #define BYTEn(x, n) (*((_BYTE*)&(x)+n)) 106 | #define WORDn(x, n) (*((_WORD*)&(x)+n)) 107 | #define BYTE1(x) BYTEn(x, 1) // byte 1 (counting from 0) 108 | #define BYTE2(x) BYTEn(x, 2) 109 | #define BYTE3(x) BYTEn(x, 3) 110 | #define BYTE4(x) BYTEn(x, 4) 111 | #define BYTE5(x) BYTEn(x, 5) 112 | #define BYTE6(x) BYTEn(x, 6) 113 | #define BYTE7(x) BYTEn(x, 7) 114 | #define BYTE8(x) BYTEn(x, 8) 115 | #define BYTE9(x) BYTEn(x, 9) 116 | #define BYTE10(x) BYTEn(x, 10) 117 | #define BYTE11(x) BYTEn(x, 11) 118 | #define BYTE12(x) BYTEn(x, 12) 119 | #define BYTE13(x) BYTEn(x, 13) 120 | #define BYTE14(x) BYTEn(x, 14) 121 | #define BYTE15(x) BYTEn(x, 15) 122 | #define WORD1(x) WORDn(x, 1) 123 | #define WORD2(x) WORDn(x, 2) // third word of the object, unsigned 124 | #define WORD3(x) WORDn(x, 3) 125 | #define WORD4(x) WORDn(x, 4) 126 | #define WORD5(x) WORDn(x, 5) 127 | #define WORD6(x) WORDn(x, 6) 128 | #define WORD7(x) WORDn(x, 7) 129 | 130 | // now signed macros (the same but with sign extension) 131 | #define SLOBYTE(x) (*((int8*)&(x))) 132 | #define SLOWORD(x) (*((int16*)&(x))) 133 | #define SLODWORD(x) (*((int32*)&(x))) 134 | #define SHIBYTE(x) (*((int8*)&(x)+1)) 135 | #define SHIWORD(x) (*((int16*)&(x)+1)) 136 | #define SHIDWORD(x) (*((int32*)&(x)+1)) 137 | #define SBYTEn(x, n) (*((int8*)&(x)+n)) 138 | #define SWORDn(x, n) (*((int16*)&(x)+n)) 139 | #define SBYTE1(x) SBYTEn(x, 1) 140 | #define SBYTE2(x) SBYTEn(x, 2) 141 | #define SBYTE3(x) SBYTEn(x, 3) 142 | #define SBYTE4(x) SBYTEn(x, 4) 143 | #define SBYTE5(x) SBYTEn(x, 5) 144 | #define SBYTE6(x) SBYTEn(x, 6) 145 | #define SBYTE7(x) SBYTEn(x, 7) 146 | #define SBYTE8(x) SBYTEn(x, 8) 147 | #define SBYTE9(x) SBYTEn(x, 9) 148 | #define SBYTE10(x) SBYTEn(x, 10) 149 | #define SBYTE11(x) SBYTEn(x, 11) 150 | #define SBYTE12(x) SBYTEn(x, 12) 151 | #define SBYTE13(x) SBYTEn(x, 13) 152 | #define SBYTE14(x) SBYTEn(x, 14) 153 | #define SBYTE15(x) SBYTEn(x, 15) 154 | #define SWORD1(x) SWORDn(x, 1) 155 | #define SWORD2(x) SWORDn(x, 2) 156 | #define SWORD3(x) SWORDn(x, 3) 157 | #define SWORD4(x) SWORDn(x, 4) 158 | #define SWORD5(x) SWORDn(x, 5) 159 | #define SWORD6(x) SWORDn(x, 6) 160 | #define SWORD7(x) SWORDn(x, 7) 161 | 162 | 163 | // Helper functions to represent some assembly instructions. 164 | 165 | #ifdef __cplusplus 166 | 167 | // compile time assertion 168 | #define __CASSERT_N0__(l) COMPILE_TIME_ASSERT_ ## l 169 | #define __CASSERT_N1__(l) __CASSERT_N0__(l) 170 | #define CASSERT(cnd) typedef char __CASSERT_N1__(__LINE__) [(cnd) ? 1 : -1] 171 | 172 | // check that unsigned multiplication does not overflow 173 | template bool is_mul_ok(T count, T elsize) 174 | { 175 | CASSERT((T)(-1) > 0); // make sure T is unsigned 176 | if (elsize == 0 || count == 0) 177 | return true; 178 | return count <= ((T)(-1)) / elsize; 179 | } 180 | 181 | // multiplication that saturates (yields the biggest value) instead of overflowing 182 | // such a construct is useful in "operator new[]" 183 | template bool saturated_mul(T count, T elsize) 184 | { 185 | return is_mul_ok(count, elsize) ? count * elsize : T(-1); 186 | } 187 | 188 | #include // for size_t 189 | 190 | // memcpy() with determined behavoir: it always copies 191 | // from the start to the end of the buffer 192 | // note: it copies byte by byte, so it is not equivalent to, for example, rep movsd 193 | inline void* qmemcpy(void* dst, const void* src, size_t cnt) 194 | { 195 | char* out = (char*)dst; 196 | const char* in = (const char*)src; 197 | while (cnt > 0) 198 | { 199 | *out++ = *in++; 200 | --cnt; 201 | } 202 | return dst; 203 | } 204 | 205 | // Generate a reference to pair of operands 206 | template int16 __PAIR__(int8 high, T low) { return (((int16)high) << sizeof(high) * 8) | uint8(low); } 207 | template int32 __PAIR__(int16 high, T low) { return (((int32)high) << sizeof(high) * 8) | uint16(low); } 208 | template int64 __PAIR__(int32 high, T low) { return (((int64)high) << sizeof(high) * 8) | uint32(low); } 209 | template uint16 __PAIR__(uint8 high, T low) { return (((uint16)high) << sizeof(high) * 8) | uint8(low); } 210 | template uint32 __PAIR__(uint16 high, T low) { return (((uint32)high) << sizeof(high) * 8) | uint16(low); } 211 | template uint64 __PAIR__(uint32 high, T low) { return (((uint64)high) << sizeof(high) * 8) | uint32(low); } 212 | 213 | // rotate left 214 | template T __ROL__(T value, int count) 215 | { 216 | const uint nbits = sizeof(T) * 8; 217 | 218 | if (count > 0) 219 | { 220 | count %= nbits; 221 | T high = value >> (nbits - count); 222 | if (T(-1) < 0) // signed value 223 | high &= ~((T(-1) << count)); 224 | value <<= count; 225 | value |= high; 226 | } 227 | else 228 | { 229 | count = -count % nbits; 230 | T low = value << (nbits - count); 231 | value >>= count; 232 | value |= low; 233 | } 234 | return value; 235 | } 236 | 237 | inline uint8 __ROL1__(uint8 value, int count) { return __ROL__((uint8)value, count); } 238 | inline uint16 __ROL2__(uint16 value, int count) { return __ROL__((uint16)value, count); } 239 | inline uint32 __ROL4__(uint32 value, int count) { return __ROL__((uint32)value, count); } 240 | inline uint64 __ROL8__(uint64 value, int count) { return __ROL__((uint64)value, count); } 241 | inline uint8 __ROR1__(uint8 value, int count) { return __ROL__((uint8)value, -count); } 242 | inline uint16 __ROR2__(uint16 value, int count) { return __ROL__((uint16)value, -count); } 243 | inline uint32 __ROR4__(uint32 value, int count) { return __ROL__((uint32)value, -count); } 244 | inline uint64 __ROR8__(uint64 value, int count) { return __ROL__((uint64)value, -count); } 245 | inline uint64_t ROL8(uint64_t value, int count) { return __ROL__((uint64_t)value, count); } 246 | 247 | // carry flag of left shift 248 | template int8 __MKCSHL__(T value, uint count) 249 | { 250 | const uint nbits = sizeof(T) * 8; 251 | count %= nbits; 252 | 253 | return (value >> (nbits - count)) & 1; 254 | } 255 | 256 | // carry flag of right shift 257 | template int8 __MKCSHR__(T value, uint count) 258 | { 259 | return (value >> (count - 1)) & 1; 260 | } 261 | 262 | // sign flag 263 | template int8 __SETS__(T x) 264 | { 265 | if (sizeof(T) == 1) 266 | return int8(x) < 0; 267 | if (sizeof(T) == 2) 268 | return int16(x) < 0; 269 | if (sizeof(T) == 4) 270 | return int32(x) < 0; 271 | return int64(x) < 0; 272 | } 273 | 274 | // overflow flag of subtraction (x-y) 275 | template int8 __OFSUB__(T x, U y) 276 | { 277 | if (sizeof(T) < sizeof(U)) 278 | { 279 | U x2 = x; 280 | int8 sx = __SETS__(x2); 281 | return (sx ^ __SETS__(y)) & (sx ^ __SETS__(x2 - y)); 282 | } 283 | else 284 | { 285 | T y2 = y; 286 | int8 sx = __SETS__(x); 287 | return (sx ^ __SETS__(y2)) & (sx ^ __SETS__(x - y2)); 288 | } 289 | } 290 | 291 | // overflow flag of addition (x+y) 292 | template int8 __OFADD__(T x, U y) 293 | { 294 | if (sizeof(T) < sizeof(U)) 295 | { 296 | U x2 = x; 297 | int8 sx = __SETS__(x2); 298 | return ((1 ^ sx) ^ __SETS__(y)) & (sx ^ __SETS__(x2 + y)); 299 | } 300 | else 301 | { 302 | T y2 = y; 303 | int8 sx = __SETS__(x); 304 | return ((1 ^ sx) ^ __SETS__(y2)) & (sx ^ __SETS__(x + y2)); 305 | } 306 | } 307 | 308 | // carry flag of subtraction (x-y) 309 | template int8 __CFSUB__(T x, U y) 310 | { 311 | int size = sizeof(T) > sizeof(U) ? sizeof(T) : sizeof(U); 312 | if (size == 1) 313 | return uint8(x) < uint8(y); 314 | if (size == 2) 315 | return uint16(x) < uint16(y); 316 | if (size == 4) 317 | return uint32(x) < uint32(y); 318 | return uint64(x) < uint64(y); 319 | } 320 | 321 | // carry flag of addition (x+y) 322 | template int8 __CFADD__(T x, U y) 323 | { 324 | int size = sizeof(T) > sizeof(U) ? sizeof(T) : sizeof(U); 325 | if (size == 1) 326 | return uint8(x) > uint8(x + y); 327 | if (size == 2) 328 | return uint16(x) > uint16(x + y); 329 | if (size == 4) 330 | return uint32(x) > uint32(x + y); 331 | return uint64(x) > uint64(x + y); 332 | } 333 | 334 | #else 335 | // The following definition is not quite correct because it always returns 336 | // uint64. The above C++ functions are good, though. 337 | #define __PAIR__(high, low) (((uint64)(high)<>y) 343 | #define __CFADD__(x, y) invalid_operation // Generate carry flag for (x+y) 344 | #define __CFSUB__(x, y) invalid_operation // Generate carry flag for (x-y) 345 | #define __OFADD__(x, y) invalid_operation // Generate overflow flag for (x+y) 346 | #define __OFSUB__(x, y) invalid_operation // Generate overflow flag for (x-y) 347 | #endif 348 | 349 | // No definition for rcl/rcr because the carry flag is unknown 350 | #define __RCL__(x, y) invalid_operation // Rotate left thru carry 351 | #define __RCR__(x, y) invalid_operation // Rotate right thru carry 352 | #define __MKCRCL__(x, y) invalid_operation // Generate carry flag for a RCL 353 | #define __MKCRCR__(x, y) invalid_operation // Generate carry flag for a RCR 354 | #define __SETP__(x, y) invalid_operation // Generate parity flag for (x-y) 355 | 356 | // In the decompilation listing there are some objects declarared as _UNKNOWN 357 | // because we could not determine their types. Since the C compiler does not 358 | // accept void item declarations, we replace them by anything of our choice, 359 | // for example a char: 360 | 361 | #define _UNKNOWN char 362 | 363 | #ifdef _MSC_VER 364 | #define snprintf _snprintf 365 | #define vsnprintf _vsnprintf 366 | #endif 367 | 368 | #endif // HEXRAYS_DEFS_H -------------------------------------------------------------------------------- /imgui_impl_dx9.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer for DirectX9 2 | // This needs to be used along with a Platform Binding (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. 7 | 8 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 9 | // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. 10 | // https://github.com/ocornut/imgui 11 | 12 | // CHANGELOG 13 | // (minor and older changes stripped away, please see git history for details) 14 | // 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 15 | // 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 16 | // 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects(). 17 | // 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288. 18 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 19 | // 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example. 20 | // 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 21 | // 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud. 22 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. 23 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 24 | 25 | #include "imgui.h" 26 | #include "imgui_impl_dx9.h" 27 | 28 | // DirectX 29 | #include 30 | #define DIRECTINPUT_VERSION 0x0800 31 | #include 32 | 33 | // DirectX data 34 | static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; 35 | static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; 36 | static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; 37 | static LPDIRECT3DTEXTURE9 g_FontTexture = NULL; 38 | static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; 39 | 40 | struct CUSTOMVERTEX 41 | { 42 | float pos[3]; 43 | D3DCOLOR col; 44 | float uv[2]; 45 | }; 46 | #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) 47 | 48 | static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) 49 | { 50 | // Setup viewport 51 | D3DVIEWPORT9 vp; 52 | vp.X = vp.Y = 0; 53 | vp.Width = (DWORD)draw_data->DisplaySize.x; 54 | vp.Height = (DWORD)draw_data->DisplaySize.y; 55 | vp.MinZ = 0.0f; 56 | vp.MaxZ = 1.0f; 57 | g_pd3dDevice->SetViewport(&vp); 58 | 59 | // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient) 60 | g_pd3dDevice->SetPixelShader(NULL); 61 | g_pd3dDevice->SetVertexShader(NULL); 62 | g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 63 | g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false); 64 | g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false); 65 | g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); 66 | g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); 67 | g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); 68 | g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 69 | g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 70 | g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, true); 71 | g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); 72 | g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, false); 73 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); 74 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); 75 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); 76 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 77 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); 78 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); 79 | g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 80 | g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 81 | 82 | // Setup orthographic projection matrix 83 | // 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. 84 | // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH() 85 | { 86 | float L = draw_data->DisplayPos.x + 0.5f; 87 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f; 88 | float T = draw_data->DisplayPos.y + 0.5f; 89 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f; 90 | D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } }; 91 | D3DMATRIX mat_projection = 92 | { { { 93 | 2.0f/(R-L), 0.0f, 0.0f, 0.0f, 94 | 0.0f, 2.0f/(T-B), 0.0f, 0.0f, 95 | 0.0f, 0.0f, 0.5f, 0.0f, 96 | (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f 97 | } } }; 98 | g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); 99 | g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); 100 | g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); 101 | } 102 | } 103 | 104 | // Render function. 105 | // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) 106 | void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) 107 | { 108 | // Avoid rendering when minimized 109 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) 110 | return; 111 | 112 | // Create and grow buffers if needed 113 | if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) 114 | { 115 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } 116 | g_VertexBufferSize = draw_data->TotalVtxCount + 5000; 117 | if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) 118 | return; 119 | } 120 | if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) 121 | { 122 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } 123 | g_IndexBufferSize = draw_data->TotalIdxCount + 10000; 124 | if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0) 125 | return; 126 | } 127 | 128 | // Backup the DX9 state 129 | IDirect3DStateBlock9* d3d9_state_block = NULL; 130 | if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0) 131 | return; 132 | 133 | // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to) 134 | D3DMATRIX last_world, last_view, last_projection; 135 | g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world); 136 | g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view); 137 | g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection); 138 | 139 | // Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format. 140 | // FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and 141 | // 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR 142 | // 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; } 143 | CUSTOMVERTEX* vtx_dst; 144 | ImDrawIdx* idx_dst; 145 | if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) 146 | return; 147 | if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0) 148 | return; 149 | for (int n = 0; n < draw_data->CmdListsCount; n++) 150 | { 151 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 152 | const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data; 153 | for (int i = 0; i < cmd_list->VtxBuffer.Size; i++) 154 | { 155 | vtx_dst->pos[0] = vtx_src->pos.x; 156 | vtx_dst->pos[1] = vtx_src->pos.y; 157 | vtx_dst->pos[2] = 0.0f; 158 | vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000) >> 16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9 159 | vtx_dst->uv[0] = vtx_src->uv.x; 160 | vtx_dst->uv[1] = vtx_src->uv.y; 161 | vtx_dst++; 162 | vtx_src++; 163 | } 164 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 165 | idx_dst += cmd_list->IdxBuffer.Size; 166 | } 167 | g_pVB->Unlock(); 168 | g_pIB->Unlock(); 169 | g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX)); 170 | g_pd3dDevice->SetIndices(g_pIB); 171 | g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); 172 | 173 | // Setup desired DX state 174 | ImGui_ImplDX9_SetupRenderState(draw_data); 175 | 176 | // Render command lists 177 | // (Because we merged all buffers into a single one, we maintain our own offset into them) 178 | int global_vtx_offset = 0; 179 | int global_idx_offset = 0; 180 | ImVec2 clip_off = draw_data->DisplayPos; 181 | for (int n = 0; n < draw_data->CmdListsCount; n++) 182 | { 183 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 184 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 185 | { 186 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 187 | if (pcmd->UserCallback != NULL) 188 | { 189 | // User callback, registered via ImDrawList::AddCallback() 190 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 191 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 192 | ImGui_ImplDX9_SetupRenderState(draw_data); 193 | else 194 | pcmd->UserCallback(cmd_list, pcmd); 195 | } 196 | else 197 | { 198 | const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; 199 | const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->TextureId; 200 | g_pd3dDevice->SetTexture(0, texture); 201 | g_pd3dDevice->SetScissorRect(&r); 202 | g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount/3); 203 | } 204 | } 205 | global_idx_offset += cmd_list->IdxBuffer.Size; 206 | global_vtx_offset += cmd_list->VtxBuffer.Size; 207 | } 208 | 209 | // Restore the DX9 transform 210 | g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world); 211 | g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view); 212 | g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection); 213 | 214 | // Restore the DX9 state 215 | d3d9_state_block->Apply(); 216 | d3d9_state_block->Release(); 217 | } 218 | 219 | bool ImGui_ImplDX9_Init(IDirect3DDevice9* device) 220 | { 221 | // Setup back-end capabilities flags 222 | ImGuiIO& io = ImGui::GetIO(); 223 | io.BackendRendererName = "imgui_impl_dx9"; 224 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 225 | 226 | g_pd3dDevice = device; 227 | g_pd3dDevice->AddRef(); 228 | return true; 229 | } 230 | 231 | void ImGui_ImplDX9_Shutdown() 232 | { 233 | ImGui_ImplDX9_InvalidateDeviceObjects(); 234 | if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } 235 | } 236 | 237 | static bool ImGui_ImplDX9_CreateFontsTexture() 238 | { 239 | // Build texture atlas 240 | ImGuiIO& io = ImGui::GetIO(); 241 | unsigned char* pixels; 242 | int width, height, bytes_per_pixel; 243 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel); 244 | 245 | // Upload texture to graphics system 246 | g_FontTexture = NULL; 247 | if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0) 248 | return false; 249 | D3DLOCKED_RECT tex_locked_rect; 250 | if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) 251 | return false; 252 | for (int y = 0; y < height; y++) 253 | memcpy((unsigned char *)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel)); 254 | g_FontTexture->UnlockRect(0); 255 | 256 | // Store our identifier 257 | io.Fonts->TexID = (ImTextureID)g_FontTexture; 258 | 259 | return true; 260 | } 261 | 262 | bool ImGui_ImplDX9_CreateDeviceObjects() 263 | { 264 | if (!g_pd3dDevice) 265 | return false; 266 | if (!ImGui_ImplDX9_CreateFontsTexture()) 267 | return false; 268 | return true; 269 | } 270 | 271 | void ImGui_ImplDX9_InvalidateDeviceObjects() 272 | { 273 | if (!g_pd3dDevice) 274 | return; 275 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } 276 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } 277 | if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. 278 | } 279 | 280 | void ImGui_ImplDX9_NewFrame() 281 | { 282 | if (!g_FontTexture) 283 | ImGui_ImplDX9_CreateDeviceObjects(); 284 | } 285 | -------------------------------------------------------------------------------- /imgui_impl_win32.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Binding for Windows (standard windows API for 32 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 imgui) 6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | 10 | #include "imgui.h" 11 | #include "imgui_impl_win32.h" 12 | #ifndef WIN32_LEAN_AND_MEAN 13 | #define WIN32_LEAN_AND_MEAN 14 | #endif 15 | #include 16 | #include 17 | #include 18 | 19 | // CHANGELOG 20 | // (minor and older changes stripped away, please see git history for details) 21 | // 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). 22 | // 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent. 23 | // 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. 24 | // 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application). 25 | // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. 26 | // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. 27 | // 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads). 28 | // 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples. 29 | // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. 30 | // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). 31 | // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. 32 | // 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). 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 | // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. 35 | // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. 36 | // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. 37 | // 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read. 38 | // 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. 39 | // 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set. 40 | 41 | // Win32 Data 42 | static HWND g_hWnd = 0; 43 | static INT64 g_Time = 0; 44 | static INT64 g_TicksPerSecond = 0; 45 | static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; 46 | static bool g_HasGamepad = false; 47 | static bool g_WantUpdateHasGamepad = true; 48 | 49 | // Functions 50 | bool ImGui_ImplWin32_Init(void* hwnd) 51 | { 52 | if (!::QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) 53 | return false; 54 | if (!::QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) 55 | return false; 56 | 57 | // Setup back-end capabilities flags 58 | g_hWnd = (HWND)hwnd; 59 | ImGuiIO& io = ImGui::GetIO(); 60 | io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) 61 | io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) 62 | io.BackendPlatformName = "imgui_impl_win32"; 63 | io.ImeWindowHandle = hwnd; 64 | 65 | // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. 66 | io.KeyMap[ImGuiKey_Tab] = VK_TAB; 67 | io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; 68 | io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; 69 | io.KeyMap[ImGuiKey_UpArrow] = VK_UP; 70 | io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; 71 | io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; 72 | io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; 73 | io.KeyMap[ImGuiKey_Home] = VK_HOME; 74 | io.KeyMap[ImGuiKey_End] = VK_END; 75 | io.KeyMap[ImGuiKey_Insert] = VK_INSERT; 76 | io.KeyMap[ImGuiKey_Delete] = VK_DELETE; 77 | io.KeyMap[ImGuiKey_Backspace] = VK_BACK; 78 | io.KeyMap[ImGuiKey_Space] = VK_SPACE; 79 | io.KeyMap[ImGuiKey_Enter] = VK_RETURN; 80 | io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; 81 | io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN; 82 | io.KeyMap[ImGuiKey_A] = 'A'; 83 | io.KeyMap[ImGuiKey_C] = 'C'; 84 | io.KeyMap[ImGuiKey_V] = 'V'; 85 | io.KeyMap[ImGuiKey_X] = 'X'; 86 | io.KeyMap[ImGuiKey_Y] = 'Y'; 87 | io.KeyMap[ImGuiKey_Z] = 'Z'; 88 | 89 | return true; 90 | } 91 | 92 | void ImGui_ImplWin32_Shutdown() 93 | { 94 | g_hWnd = (HWND)0; 95 | } 96 | 97 | static bool ImGui_ImplWin32_UpdateMouseCursor() 98 | { 99 | ImGuiIO& io = ImGui::GetIO(); 100 | if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) 101 | return false; 102 | 103 | ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); 104 | if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) 105 | { 106 | // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor 107 | ::SetCursor(NULL); 108 | } 109 | else 110 | { 111 | // Show OS mouse cursor 112 | LPTSTR win32_cursor = IDC_ARROW; 113 | switch (imgui_cursor) 114 | { 115 | case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; 116 | case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; 117 | case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; 118 | case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; 119 | case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; 120 | case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; 121 | case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; 122 | case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; 123 | } 124 | ::SetCursor(::LoadCursor(NULL, win32_cursor)); 125 | } 126 | return true; 127 | } 128 | 129 | static void ImGui_ImplWin32_UpdateMousePos() 130 | { 131 | ImGuiIO& io = ImGui::GetIO(); 132 | 133 | // Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) 134 | if (io.WantSetMousePos) 135 | { 136 | POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; 137 | ::ClientToScreen(g_hWnd, &pos); 138 | ::SetCursorPos(pos.x, pos.y); 139 | } 140 | 141 | // Set mouse position 142 | io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); 143 | POINT pos; 144 | if (HWND active_window = ::GetForegroundWindow()) 145 | if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd)) 146 | if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos)) 147 | io.MousePos = ImVec2((float)pos.x, (float)pos.y); 148 | } 149 | 150 | #ifdef _MSC_VER 151 | #pragma comment(lib, "xinput") 152 | #endif 153 | 154 | // Gamepad navigation mapping 155 | static void ImGui_ImplWin32_UpdateGamepads() 156 | { 157 | ImGuiIO& io = ImGui::GetIO(); 158 | memset(io.NavInputs, 0, sizeof(io.NavInputs)); 159 | if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) 160 | return; 161 | 162 | // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. 163 | // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. 164 | if (g_WantUpdateHasGamepad) 165 | { 166 | XINPUT_CAPABILITIES caps; 167 | g_HasGamepad = (XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS); 168 | g_WantUpdateHasGamepad = false; 169 | } 170 | 171 | XINPUT_STATE xinput_state; 172 | io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; 173 | if (g_HasGamepad && XInputGetState(0, &xinput_state) == ERROR_SUCCESS) 174 | { 175 | const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; 176 | io.BackendFlags |= ImGuiBackendFlags_HasGamepad; 177 | 178 | #define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; } 179 | #define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; } 180 | MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); // Cross / A 181 | MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); // Circle / B 182 | MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); // Square / X 183 | MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); // Triangle / Y 184 | MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); // D-Pad Left 185 | MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); // D-Pad Right 186 | MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); // D-Pad Up 187 | MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); // D-Pad Down 188 | MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB 189 | MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB 190 | MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB 191 | MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB 192 | MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 193 | MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 194 | MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 195 | MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767); 196 | #undef MAP_BUTTON 197 | #undef MAP_ANALOG 198 | } 199 | } 200 | 201 | void ImGui_ImplWin32_NewFrame() 202 | { 203 | ImGuiIO& io = ImGui::GetIO(); 204 | IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame()."); 205 | 206 | // Setup display size (every frame to accommodate for window resizing) 207 | RECT rect; 208 | ::GetClientRect(g_hWnd, &rect); 209 | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); 210 | 211 | // Setup time step 212 | INT64 current_time; 213 | ::QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); 214 | io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; 215 | g_Time = current_time; 216 | 217 | // Read keyboard modifiers inputs 218 | io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; 219 | io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; 220 | io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0; 221 | io.KeySuper = false; 222 | // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. 223 | 224 | // Update OS mouse position 225 | ImGui_ImplWin32_UpdateMousePos(); 226 | 227 | // Update OS mouse cursor with the cursor requested by imgui 228 | ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); 229 | if (g_LastMouseCursor != mouse_cursor) 230 | { 231 | g_LastMouseCursor = mouse_cursor; 232 | ImGui_ImplWin32_UpdateMouseCursor(); 233 | } 234 | 235 | // Update game controllers (if enabled and available) 236 | ImGui_ImplWin32_UpdateGamepads(); 237 | } 238 | 239 | // Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. 240 | #ifndef WM_MOUSEHWHEEL 241 | #define WM_MOUSEHWHEEL 0x020E 242 | #endif 243 | #ifndef DBT_DEVNODES_CHANGED 244 | #define DBT_DEVNODES_CHANGED 0x0007 245 | #endif 246 | 247 | // Process Win32 mouse/keyboard inputs. 248 | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. 249 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. 250 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. 251 | // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. 252 | // 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. 253 | // 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. 254 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 255 | { 256 | if (ImGui::GetCurrentContext() == NULL) 257 | return 0; 258 | 259 | ImGuiIO& io = ImGui::GetIO(); 260 | switch (msg) 261 | { 262 | case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: 263 | case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: 264 | case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: 265 | case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: 266 | { 267 | int button = 0; 268 | if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; } 269 | if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } 270 | if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } 271 | if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } 272 | if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) 273 | ::SetCapture(hwnd); 274 | io.MouseDown[button] = true; 275 | return 0; 276 | } 277 | case WM_LBUTTONUP: 278 | case WM_RBUTTONUP: 279 | case WM_MBUTTONUP: 280 | case WM_XBUTTONUP: 281 | { 282 | int button = 0; 283 | if (msg == WM_LBUTTONUP) { button = 0; } 284 | if (msg == WM_RBUTTONUP) { button = 1; } 285 | if (msg == WM_MBUTTONUP) { button = 2; } 286 | if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } 287 | io.MouseDown[button] = false; 288 | if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) 289 | ::ReleaseCapture(); 290 | return 0; 291 | } 292 | case WM_MOUSEWHEEL: 293 | io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; 294 | return 0; 295 | case WM_MOUSEHWHEEL: 296 | io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA; 297 | return 0; 298 | case WM_KEYDOWN: 299 | case WM_SYSKEYDOWN: 300 | if (wParam < 256) 301 | io.KeysDown[wParam] = 1; 302 | return 0; 303 | case WM_KEYUP: 304 | case WM_SYSKEYUP: 305 | if (wParam < 256) 306 | io.KeysDown[wParam] = 0; 307 | return 0; 308 | case WM_CHAR: 309 | // You can also use ToAscii()+GetKeyboardState() to retrieve characters. 310 | io.AddInputCharacter((unsigned int)wParam); 311 | return 0; 312 | case WM_SETCURSOR: 313 | if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) 314 | return 1; 315 | return 0; 316 | case WM_DEVICECHANGE: 317 | if ((UINT)wParam == DBT_DEVNODES_CHANGED) 318 | g_WantUpdateHasGamepad = true; 319 | return 0; 320 | } 321 | return 0; 322 | } 323 | 324 | -------------------------------------------------------------------------------- /imstb_rectpack.h: -------------------------------------------------------------------------------- 1 | // [DEAR IMGUI] 2 | // This is a slightly modified version of stb_rect_pack.h 1.00. 3 | // Those changes would need to be pushed into nothings/stb: 4 | // - Added STBRP__CDECL 5 | // Grep for [DEAR IMGUI] to find the changes. 6 | 7 | // stb_rect_pack.h - v1.00 - public domain - rectangle packing 8 | // Sean Barrett 2014 9 | // 10 | // Useful for e.g. packing rectangular textures into an atlas. 11 | // Does not do rotation. 12 | // 13 | // Not necessarily the awesomest packing method, but better than 14 | // the totally naive one in stb_truetype (which is primarily what 15 | // this is meant to replace). 16 | // 17 | // Has only had a few tests run, may have issues. 18 | // 19 | // More docs to come. 20 | // 21 | // No memory allocations; uses qsort() and assert() from stdlib. 22 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 23 | // 24 | // This library currently uses the Skyline Bottom-Left algorithm. 25 | // 26 | // Please note: better rectangle packers are welcome! Please 27 | // implement them to the same API, but with a different init 28 | // function. 29 | // 30 | // Credits 31 | // 32 | // Library 33 | // Sean Barrett 34 | // Minor features 35 | // Martins Mozeiko 36 | // github:IntellectualKitty 37 | // 38 | // Bugfixes / warning fixes 39 | // Jeremy Jaussaud 40 | // Fabian Giesen 41 | // 42 | // Version history: 43 | // 44 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles 45 | // 0.99 (2019-02-07) warning fixes 46 | // 0.11 (2017-03-03) return packing success/fail result 47 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 48 | // 0.09 (2016-08-27) fix compiler warnings 49 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 50 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 51 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 52 | // 0.05: added STBRP_ASSERT to allow replacing assert 53 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 54 | // 0.01: initial release 55 | // 56 | // LICENSE 57 | // 58 | // See end of file for license information. 59 | 60 | ////////////////////////////////////////////////////////////////////////////// 61 | // 62 | // INCLUDE SECTION 63 | // 64 | 65 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 66 | #define STB_INCLUDE_STB_RECT_PACK_H 67 | 68 | #define STB_RECT_PACK_VERSION 1 69 | 70 | #ifdef STBRP_STATIC 71 | #define STBRP_DEF static 72 | #else 73 | #define STBRP_DEF extern 74 | #endif 75 | 76 | #ifdef __cplusplus 77 | extern "C" { 78 | #endif 79 | 80 | typedef struct stbrp_context stbrp_context; 81 | typedef struct stbrp_node stbrp_node; 82 | typedef struct stbrp_rect stbrp_rect; 83 | 84 | #ifdef STBRP_LARGE_RECTS 85 | typedef int stbrp_coord; 86 | #else 87 | typedef unsigned short stbrp_coord; 88 | #endif 89 | 90 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 91 | // Assign packed locations to rectangles. The rectangles are of type 92 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 93 | // are 'num_rects' many of them. 94 | // 95 | // Rectangles which are successfully packed have the 'was_packed' flag 96 | // set to a non-zero value and 'x' and 'y' store the minimum location 97 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 98 | // if you imagine y increasing downwards). Rectangles which do not fit 99 | // have the 'was_packed' flag set to 0. 100 | // 101 | // You should not try to access the 'rects' array from another thread 102 | // while this function is running, as the function temporarily reorders 103 | // the array while it executes. 104 | // 105 | // To pack into another rectangle, you need to call stbrp_init_target 106 | // again. To continue packing into the same rectangle, you can call 107 | // this function again. Calling this multiple times with multiple rect 108 | // arrays will probably produce worse packing results than calling it 109 | // a single time with the full rectangle array, but the option is 110 | // available. 111 | // 112 | // The function returns 1 if all of the rectangles were successfully 113 | // packed and 0 otherwise. 114 | 115 | struct stbrp_rect 116 | { 117 | // reserved for your use: 118 | int id; 119 | 120 | // input: 121 | stbrp_coord w, h; 122 | 123 | // output: 124 | stbrp_coord x, y; 125 | int was_packed; // non-zero if valid packing 126 | 127 | }; // 16 bytes, nominally 128 | 129 | 130 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 131 | // Initialize a rectangle packer to: 132 | // pack a rectangle that is 'width' by 'height' in dimensions 133 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 134 | // 135 | // You must call this function every time you start packing into a new target. 136 | // 137 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 138 | // the following stbrp_pack_rects() call (or calls), but can be freed after 139 | // the call (or calls) finish. 140 | // 141 | // Note: to guarantee best results, either: 142 | // 1. make sure 'num_nodes' >= 'width' 143 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 144 | // 145 | // If you don't do either of the above things, widths will be quantized to multiples 146 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 147 | // 148 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 149 | // may run out of temporary storage and be unable to pack some rectangles. 150 | 151 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 152 | // Optionally call this function after init but before doing any packing to 153 | // change the handling of the out-of-temp-memory scenario, described above. 154 | // If you call init again, this will be reset to the default (false). 155 | 156 | 157 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 158 | // Optionally select which packing heuristic the library should use. Different 159 | // heuristics will produce better/worse results for different data sets. 160 | // If you call init again, this will be reset to the default. 161 | 162 | enum 163 | { 164 | STBRP_HEURISTIC_Skyline_default=0, 165 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 166 | STBRP_HEURISTIC_Skyline_BF_sortHeight 167 | }; 168 | 169 | 170 | ////////////////////////////////////////////////////////////////////////////// 171 | // 172 | // the details of the following structures don't matter to you, but they must 173 | // be visible so you can handle the memory allocations for them 174 | 175 | struct stbrp_node 176 | { 177 | stbrp_coord x,y; 178 | stbrp_node *next; 179 | }; 180 | 181 | struct stbrp_context 182 | { 183 | int width; 184 | int height; 185 | int align; 186 | int init_mode; 187 | int heuristic; 188 | int num_nodes; 189 | stbrp_node *active_head; 190 | stbrp_node *free_head; 191 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 192 | }; 193 | 194 | #ifdef __cplusplus 195 | } 196 | #endif 197 | 198 | #endif 199 | 200 | ////////////////////////////////////////////////////////////////////////////// 201 | // 202 | // IMPLEMENTATION SECTION 203 | // 204 | 205 | #ifdef STB_RECT_PACK_IMPLEMENTATION 206 | #ifndef STBRP_SORT 207 | #include 208 | #define STBRP_SORT qsort 209 | #endif 210 | 211 | #ifndef STBRP_ASSERT 212 | #include 213 | #define STBRP_ASSERT assert 214 | #endif 215 | 216 | // [DEAR IMGUI] Added STBRP__CDECL 217 | #ifdef _MSC_VER 218 | #define STBRP__NOTUSED(v) (void)(v) 219 | #define STBRP__CDECL __cdecl 220 | #else 221 | #define STBRP__NOTUSED(v) (void)sizeof(v) 222 | #define STBRP__CDECL 223 | #endif 224 | 225 | enum 226 | { 227 | STBRP__INIT_skyline = 1 228 | }; 229 | 230 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 231 | { 232 | switch (context->init_mode) { 233 | case STBRP__INIT_skyline: 234 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 235 | context->heuristic = heuristic; 236 | break; 237 | default: 238 | STBRP_ASSERT(0); 239 | } 240 | } 241 | 242 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 243 | { 244 | if (allow_out_of_mem) 245 | // if it's ok to run out of memory, then don't bother aligning them; 246 | // this gives better packing, but may fail due to OOM (even though 247 | // the rectangles easily fit). @TODO a smarter approach would be to only 248 | // quantize once we've hit OOM, then we could get rid of this parameter. 249 | context->align = 1; 250 | else { 251 | // if it's not ok to run out of memory, then quantize the widths 252 | // so that num_nodes is always enough nodes. 253 | // 254 | // I.e. num_nodes * align >= width 255 | // align >= width / num_nodes 256 | // align = ceil(width/num_nodes) 257 | 258 | context->align = (context->width + context->num_nodes-1) / context->num_nodes; 259 | } 260 | } 261 | 262 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 263 | { 264 | int i; 265 | #ifndef STBRP_LARGE_RECTS 266 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff); 267 | #endif 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 | #ifdef STBRP_LARGE_RECTS 287 | context->extra[1].y = (1<<30); 288 | #else 289 | context->extra[1].y = 65535; 290 | #endif 291 | context->extra[1].next = NULL; 292 | } 293 | 294 | // find minimum y position if it starts at x1 295 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 296 | { 297 | stbrp_node *node = first; 298 | int x1 = x0 + width; 299 | int min_y, visited_width, waste_area; 300 | 301 | STBRP__NOTUSED(c); 302 | 303 | STBRP_ASSERT(first->x <= x0); 304 | 305 | #if 0 306 | // skip in case we're past the node 307 | while (node->next->x <= x0) 308 | ++node; 309 | #else 310 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 311 | #endif 312 | 313 | STBRP_ASSERT(node->x <= x0); 314 | 315 | min_y = 0; 316 | waste_area = 0; 317 | visited_width = 0; 318 | while (node->x < x1) { 319 | if (node->y > min_y) { 320 | // raise min_y higher. 321 | // we've accounted for all waste up to min_y, 322 | // but we'll now add more waste for everything we've visted 323 | waste_area += visited_width * (node->y - min_y); 324 | min_y = node->y; 325 | // the first time through, visited_width might be reduced 326 | if (node->x < x0) 327 | visited_width += node->next->x - x0; 328 | else 329 | visited_width += node->next->x - node->x; 330 | } else { 331 | // add waste area 332 | int under_width = node->next->x - node->x; 333 | if (under_width + visited_width > width) 334 | under_width = width - visited_width; 335 | waste_area += under_width * (min_y - node->y); 336 | visited_width += under_width; 337 | } 338 | node = node->next; 339 | } 340 | 341 | *pwaste = waste_area; 342 | return min_y; 343 | } 344 | 345 | typedef struct 346 | { 347 | int x,y; 348 | stbrp_node **prev_link; 349 | } stbrp__findresult; 350 | 351 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 352 | { 353 | int best_waste = (1<<30), best_x, best_y = (1 << 30); 354 | stbrp__findresult fr; 355 | stbrp_node **prev, *node, *tail, **best = NULL; 356 | 357 | // align to multiple of c->align 358 | width = (width + c->align - 1); 359 | width -= width % c->align; 360 | STBRP_ASSERT(width % c->align == 0); 361 | 362 | // if it can't possibly fit, bail immediately 363 | if (width > c->width || height > c->height) { 364 | fr.prev_link = NULL; 365 | fr.x = fr.y = 0; 366 | return fr; 367 | } 368 | 369 | node = c->active_head; 370 | prev = &c->active_head; 371 | while (node->x + width <= c->width) { 372 | int y,waste; 373 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 374 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 375 | // bottom left 376 | if (y < best_y) { 377 | best_y = y; 378 | best = prev; 379 | } 380 | } else { 381 | // best-fit 382 | if (y + height <= c->height) { 383 | // can only use it if it first vertically 384 | if (y < best_y || (y == best_y && waste < best_waste)) { 385 | best_y = y; 386 | best_waste = waste; 387 | best = prev; 388 | } 389 | } 390 | } 391 | prev = &node->next; 392 | node = node->next; 393 | } 394 | 395 | best_x = (best == NULL) ? 0 : (*best)->x; 396 | 397 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 398 | // 399 | // e.g, if fitting 400 | // 401 | // ____________________ 402 | // |____________________| 403 | // 404 | // into 405 | // 406 | // | | 407 | // | ____________| 408 | // |____________| 409 | // 410 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 411 | // 412 | // This makes BF take about 2x the time 413 | 414 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 415 | tail = c->active_head; 416 | node = c->active_head; 417 | prev = &c->active_head; 418 | // find first node that's admissible 419 | while (tail->x < width) 420 | tail = tail->next; 421 | while (tail) { 422 | int xpos = tail->x - width; 423 | int y,waste; 424 | STBRP_ASSERT(xpos >= 0); 425 | // find the left position that matches this 426 | while (node->next->x <= xpos) { 427 | prev = &node->next; 428 | node = node->next; 429 | } 430 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 431 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 432 | if (y + height <= c->height) { 433 | if (y <= best_y) { 434 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 435 | best_x = xpos; 436 | STBRP_ASSERT(y <= best_y); 437 | best_y = y; 438 | best_waste = waste; 439 | best = prev; 440 | } 441 | } 442 | } 443 | tail = tail->next; 444 | } 445 | } 446 | 447 | fr.prev_link = best; 448 | fr.x = best_x; 449 | fr.y = best_y; 450 | return fr; 451 | } 452 | 453 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 454 | { 455 | // find best position according to heuristic 456 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 457 | stbrp_node *node, *cur; 458 | 459 | // bail if: 460 | // 1. it failed 461 | // 2. the best node doesn't fit (we don't always check this) 462 | // 3. we're out of memory 463 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 464 | res.prev_link = NULL; 465 | return res; 466 | } 467 | 468 | // on success, create new node 469 | node = context->free_head; 470 | node->x = (stbrp_coord) res.x; 471 | node->y = (stbrp_coord) (res.y + height); 472 | 473 | context->free_head = node->next; 474 | 475 | // insert the new node into the right starting point, and 476 | // let 'cur' point to the remaining nodes needing to be 477 | // stiched back in 478 | 479 | cur = *res.prev_link; 480 | if (cur->x < res.x) { 481 | // preserve the existing one, so start testing with the next one 482 | stbrp_node *next = cur->next; 483 | cur->next = node; 484 | cur = next; 485 | } else { 486 | *res.prev_link = node; 487 | } 488 | 489 | // from here, traverse cur and free the nodes, until we get to one 490 | // that shouldn't be freed 491 | while (cur->next && cur->next->x <= res.x + width) { 492 | stbrp_node *next = cur->next; 493 | // move the current node to the free list 494 | cur->next = context->free_head; 495 | context->free_head = cur; 496 | cur = next; 497 | } 498 | 499 | // stitch the list back in 500 | node->next = cur; 501 | 502 | if (cur->x < res.x + width) 503 | cur->x = (stbrp_coord) (res.x + width); 504 | 505 | #ifdef _DEBUG 506 | cur = context->active_head; 507 | while (cur->x < context->width) { 508 | STBRP_ASSERT(cur->x < cur->next->x); 509 | cur = cur->next; 510 | } 511 | STBRP_ASSERT(cur->next == NULL); 512 | 513 | { 514 | int count=0; 515 | cur = context->active_head; 516 | while (cur) { 517 | cur = cur->next; 518 | ++count; 519 | } 520 | cur = context->free_head; 521 | while (cur) { 522 | cur = cur->next; 523 | ++count; 524 | } 525 | STBRP_ASSERT(count == context->num_nodes+2); 526 | } 527 | #endif 528 | 529 | return res; 530 | } 531 | 532 | // [DEAR IMGUI] Added STBRP__CDECL 533 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b) 534 | { 535 | const stbrp_rect *p = (const stbrp_rect *) a; 536 | const stbrp_rect *q = (const stbrp_rect *) b; 537 | if (p->h > q->h) 538 | return -1; 539 | if (p->h < q->h) 540 | return 1; 541 | return (p->w > q->w) ? -1 : (p->w < q->w); 542 | } 543 | 544 | // [DEAR IMGUI] Added STBRP__CDECL 545 | static int STBRP__CDECL rect_original_order(const void *a, const void *b) 546 | { 547 | const stbrp_rect *p = (const stbrp_rect *) a; 548 | const stbrp_rect *q = (const stbrp_rect *) b; 549 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 550 | } 551 | 552 | #ifdef STBRP_LARGE_RECTS 553 | #define STBRP__MAXVAL 0xffffffff 554 | #else 555 | #define STBRP__MAXVAL 0xffff 556 | #endif 557 | 558 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 559 | { 560 | int i, all_rects_packed = 1; 561 | 562 | // we use the 'was_packed' field internally to allow sorting/unsorting 563 | for (i=0; i < num_rects; ++i) { 564 | rects[i].was_packed = i; 565 | } 566 | 567 | // sort according to heuristic 568 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 569 | 570 | for (i=0; i < num_rects; ++i) { 571 | if (rects[i].w == 0 || rects[i].h == 0) { 572 | rects[i].x = rects[i].y = 0; // empty rect needs no space 573 | } else { 574 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 575 | if (fr.prev_link) { 576 | rects[i].x = (stbrp_coord) fr.x; 577 | rects[i].y = (stbrp_coord) fr.y; 578 | } else { 579 | rects[i].x = rects[i].y = STBRP__MAXVAL; 580 | } 581 | } 582 | } 583 | 584 | // unsort 585 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 586 | 587 | // set was_packed flags and all_rects_packed status 588 | for (i=0; i < num_rects; ++i) { 589 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 590 | if (!rects[i].was_packed) 591 | all_rects_packed = 0; 592 | } 593 | 594 | // return the all_rects_packed status 595 | return all_rects_packed; 596 | } 597 | #endif 598 | 599 | /* 600 | ------------------------------------------------------------------------------ 601 | This software is available under 2 licenses -- choose whichever you prefer. 602 | ------------------------------------------------------------------------------ 603 | ALTERNATIVE A - MIT License 604 | Copyright (c) 2017 Sean Barrett 605 | Permission is hereby granted, free of charge, to any person obtaining a copy of 606 | this software and associated documentation files (the "Software"), to deal in 607 | the Software without restriction, including without limitation the rights to 608 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 609 | of the Software, and to permit persons to whom the Software is furnished to do 610 | so, subject to the following conditions: 611 | The above copyright notice and this permission notice shall be included in all 612 | copies or substantial portions of the Software. 613 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 614 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 615 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 616 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 617 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 618 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 619 | SOFTWARE. 620 | ------------------------------------------------------------------------------ 621 | ALTERNATIVE B - Public Domain (www.unlicense.org) 622 | This is free and unencumbered software released into the public domain. 623 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 624 | software, either in source code form or as a compiled binary, for any purpose, 625 | commercial or non-commercial, and by any means. 626 | In jurisdictions that recognize copyright laws, the author or authors of this 627 | software dedicate any and all copyright interest in the software to the public 628 | domain. We make this dedication for the benefit of the public at large and to 629 | the detriment of our heirs and successors. We intend this dedication to be an 630 | overt act of relinquishment in perpetuity of all present and future rights to 631 | this software under copyright law. 632 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 633 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 634 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 635 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 636 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 637 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 638 | ------------------------------------------------------------------------------ 639 | */ 640 | -------------------------------------------------------------------------------- /imstb_textedit.h: -------------------------------------------------------------------------------- 1 | // [DEAR IMGUI] 2 | // This is a slightly modified version of stb_textedit.h 1.13. 3 | // Those changes would need to be pushed into nothings/stb: 4 | // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) 5 | // Grep for [DEAR IMGUI] to find the changes. 6 | 7 | // stb_textedit.h - v1.13 - public domain - Sean Barrett 8 | // Development of this library was sponsored by RAD Game Tools 9 | // 10 | // This C header file implements the guts of a multi-line text-editing 11 | // widget; you implement display, word-wrapping, and low-level string 12 | // insertion/deletion, and stb_textedit will map user inputs into 13 | // insertions & deletions, plus updates to the cursor position, 14 | // selection state, and undo state. 15 | // 16 | // It is intended for use in games and other systems that need to build 17 | // their own custom widgets and which do not have heavy text-editing 18 | // requirements (this library is not recommended for use for editing large 19 | // texts, as its performance does not scale and it has limited undo). 20 | // 21 | // Non-trivial behaviors are modelled after Windows text controls. 22 | // 23 | // 24 | // LICENSE 25 | // 26 | // See end of file for license information. 27 | // 28 | // 29 | // DEPENDENCIES 30 | // 31 | // Uses the C runtime function 'memmove', which you can override 32 | // by defining STB_TEXTEDIT_memmove before the implementation. 33 | // Uses no other functions. Performs no runtime allocations. 34 | // 35 | // 36 | // VERSION HISTORY 37 | // 38 | // 1.13 (2019-02-07) fix bug in undo size management 39 | // 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash 40 | // 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield 41 | // 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual 42 | // 1.9 (2016-08-27) customizable move-by-word 43 | // 1.8 (2016-04-02) better keyboard handling when mouse button is down 44 | // 1.7 (2015-09-13) change y range handling in case baseline is non-0 45 | // 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove 46 | // 1.5 (2014-09-10) add support for secondary keys for OS X 47 | // 1.4 (2014-08-17) fix signed/unsigned warnings 48 | // 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary 49 | // 1.2 (2014-05-27) fix some RAD types that had crept into the new code 50 | // 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE ) 51 | // 1.0 (2012-07-26) improve documentation, initial public release 52 | // 0.3 (2012-02-24) bugfixes, single-line mode; insert mode 53 | // 0.2 (2011-11-28) fixes to undo/redo 54 | // 0.1 (2010-07-08) initial version 55 | // 56 | // ADDITIONAL CONTRIBUTORS 57 | // 58 | // Ulf Winklemann: move-by-word in 1.1 59 | // Fabian Giesen: secondary key inputs in 1.5 60 | // Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 61 | // 62 | // Bugfixes: 63 | // Scott Graham 64 | // Daniel Keller 65 | // Omar Cornut 66 | // Dan Thompson 67 | // 68 | // USAGE 69 | // 70 | // This file behaves differently depending on what symbols you define 71 | // before including it. 72 | // 73 | // 74 | // Header-file mode: 75 | // 76 | // If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this, 77 | // it will operate in "header file" mode. In this mode, it declares a 78 | // single public symbol, STB_TexteditState, which encapsulates the current 79 | // state of a text widget (except for the string, which you will store 80 | // separately). 81 | // 82 | // To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a 83 | // primitive type that defines a single character (e.g. char, wchar_t, etc). 84 | // 85 | // To save space or increase undo-ability, you can optionally define the 86 | // following things that are used by the undo system: 87 | // 88 | // STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position 89 | // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow 90 | // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer 91 | // 92 | // If you don't define these, they are set to permissive types and 93 | // moderate sizes. The undo system does no memory allocations, so 94 | // it grows STB_TexteditState by the worst-case storage which is (in bytes): 95 | // 96 | // [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT 97 | // + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT 98 | // 99 | // 100 | // Implementation mode: 101 | // 102 | // If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it 103 | // will compile the implementation of the text edit widget, depending 104 | // on a large number of symbols which must be defined before the include. 105 | // 106 | // The implementation is defined only as static functions. You will then 107 | // need to provide your own APIs in the same file which will access the 108 | // static functions. 109 | // 110 | // The basic concept is that you provide a "string" object which 111 | // behaves like an array of characters. stb_textedit uses indices to 112 | // refer to positions in the string, implicitly representing positions 113 | // in the displayed textedit. This is true for both plain text and 114 | // rich text; even with rich text stb_truetype interacts with your 115 | // code as if there was an array of all the displayed characters. 116 | // 117 | // Symbols that must be the same in header-file and implementation mode: 118 | // 119 | // STB_TEXTEDIT_CHARTYPE the character type 120 | // STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position 121 | // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow 122 | // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer 123 | // 124 | // Symbols you must define for implementation mode: 125 | // 126 | // STB_TEXTEDIT_STRING the type of object representing a string being edited, 127 | // typically this is a wrapper object with other data you need 128 | // 129 | // STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1)) 130 | // STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters 131 | // starting from character #n (see discussion below) 132 | // STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character 133 | // to the xpos of the i+1'th char for a line of characters 134 | // starting at character #n (i.e. accounts for kerning 135 | // with previous char) 136 | // STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character 137 | // (return type is int, -1 means not valid to insert) 138 | // STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based 139 | // STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize 140 | // as manually wordwrapping for end-of-line positioning 141 | // 142 | // STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i 143 | // STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*) 144 | // 145 | // STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key 146 | // 147 | // STB_TEXTEDIT_K_LEFT keyboard input to move cursor left 148 | // STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right 149 | // STB_TEXTEDIT_K_UP keyboard input to move cursor up 150 | // STB_TEXTEDIT_K_DOWN keyboard input to move cursor down 151 | // STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME 152 | // STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END 153 | // STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME 154 | // STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END 155 | // STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor 156 | // STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor 157 | // STB_TEXTEDIT_K_UNDO keyboard input to perform undo 158 | // STB_TEXTEDIT_K_REDO keyboard input to perform redo 159 | // 160 | // Optional: 161 | // STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode 162 | // STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'), 163 | // required for default WORDLEFT/WORDRIGHT handlers 164 | // STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to 165 | // STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to 166 | // STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT 167 | // STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT 168 | // STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line 169 | // STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line 170 | // STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text 171 | // STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text 172 | // 173 | // Todo: 174 | // STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page 175 | // STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page 176 | // 177 | // Keyboard input must be encoded as a single integer value; e.g. a character code 178 | // and some bitflags that represent shift states. to simplify the interface, SHIFT must 179 | // be a bitflag, so we can test the shifted state of cursor movements to allow selection, 180 | // i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow. 181 | // 182 | // You can encode other things, such as CONTROL or ALT, in additional bits, and 183 | // then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example, 184 | // my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN 185 | // bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit, 186 | // and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the 187 | // API below. The control keys will only match WM_KEYDOWN events because of the 188 | // keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN 189 | // bit so it only decodes WM_CHAR events. 190 | // 191 | // STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed 192 | // row of characters assuming they start on the i'th character--the width and 193 | // the height and the number of characters consumed. This allows this library 194 | // to traverse the entire layout incrementally. You need to compute word-wrapping 195 | // here. 196 | // 197 | // Each textfield keeps its own insert mode state, which is not how normal 198 | // applications work. To keep an app-wide insert mode, update/copy the 199 | // "insert_mode" field of STB_TexteditState before/after calling API functions. 200 | // 201 | // API 202 | // 203 | // void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) 204 | // 205 | // void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) 206 | // void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) 207 | // int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 208 | // int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) 209 | // void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key) 210 | // 211 | // Each of these functions potentially updates the string and updates the 212 | // state. 213 | // 214 | // initialize_state: 215 | // set the textedit state to a known good default state when initially 216 | // constructing the textedit. 217 | // 218 | // click: 219 | // call this with the mouse x,y on a mouse down; it will update the cursor 220 | // and reset the selection start/end to the cursor point. the x,y must 221 | // be relative to the text widget, with (0,0) being the top left. 222 | // 223 | // drag: 224 | // call this with the mouse x,y on a mouse drag/up; it will update the 225 | // cursor and the selection end point 226 | // 227 | // cut: 228 | // call this to delete the current selection; returns true if there was 229 | // one. you should FIRST copy the current selection to the system paste buffer. 230 | // (To copy, just copy the current selection out of the string yourself.) 231 | // 232 | // paste: 233 | // call this to paste text at the current cursor point or over the current 234 | // selection if there is one. 235 | // 236 | // key: 237 | // call this for keyboard inputs sent to the textfield. you can use it 238 | // for "key down" events or for "translated" key events. if you need to 239 | // do both (as in Win32), or distinguish Unicode characters from control 240 | // inputs, set a high bit to distinguish the two; then you can define the 241 | // various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit 242 | // set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is 243 | // clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to 244 | // anything other type you wante before including. 245 | // 246 | // 247 | // When rendering, you can read the cursor position and selection state from 248 | // the STB_TexteditState. 249 | // 250 | // 251 | // Notes: 252 | // 253 | // This is designed to be usable in IMGUI, so it allows for the possibility of 254 | // running in an IMGUI that has NOT cached the multi-line layout. For this 255 | // reason, it provides an interface that is compatible with computing the 256 | // layout incrementally--we try to make sure we make as few passes through 257 | // as possible. (For example, to locate the mouse pointer in the text, we 258 | // could define functions that return the X and Y positions of characters 259 | // and binary search Y and then X, but if we're doing dynamic layout this 260 | // will run the layout algorithm many times, so instead we manually search 261 | // forward in one pass. Similar logic applies to e.g. up-arrow and 262 | // down-arrow movement.) 263 | // 264 | // If it's run in a widget that *has* cached the layout, then this is less 265 | // efficient, but it's not horrible on modern computers. But you wouldn't 266 | // want to edit million-line files with it. 267 | 268 | 269 | //////////////////////////////////////////////////////////////////////////// 270 | //////////////////////////////////////////////////////////////////////////// 271 | //// 272 | //// Header-file mode 273 | //// 274 | //// 275 | 276 | #ifndef INCLUDE_STB_TEXTEDIT_H 277 | #define INCLUDE_STB_TEXTEDIT_H 278 | 279 | //////////////////////////////////////////////////////////////////////// 280 | // 281 | // STB_TexteditState 282 | // 283 | // Definition of STB_TexteditState which you should store 284 | // per-textfield; it includes cursor position, selection state, 285 | // and undo state. 286 | // 287 | 288 | #ifndef STB_TEXTEDIT_UNDOSTATECOUNT 289 | #define STB_TEXTEDIT_UNDOSTATECOUNT 99 290 | #endif 291 | #ifndef STB_TEXTEDIT_UNDOCHARCOUNT 292 | #define STB_TEXTEDIT_UNDOCHARCOUNT 999 293 | #endif 294 | #ifndef STB_TEXTEDIT_CHARTYPE 295 | #define STB_TEXTEDIT_CHARTYPE int 296 | #endif 297 | #ifndef STB_TEXTEDIT_POSITIONTYPE 298 | #define STB_TEXTEDIT_POSITIONTYPE int 299 | #endif 300 | 301 | typedef struct 302 | { 303 | // private data 304 | STB_TEXTEDIT_POSITIONTYPE where; 305 | STB_TEXTEDIT_POSITIONTYPE insert_length; 306 | STB_TEXTEDIT_POSITIONTYPE delete_length; 307 | int char_storage; 308 | } StbUndoRecord; 309 | 310 | typedef struct 311 | { 312 | // private data 313 | StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT]; 314 | STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; 315 | short undo_point, redo_point; 316 | int undo_char_point, redo_char_point; 317 | } StbUndoState; 318 | 319 | typedef struct 320 | { 321 | ///////////////////// 322 | // 323 | // public data 324 | // 325 | 326 | int cursor; 327 | // position of the text cursor within the string 328 | 329 | int select_start; // selection start point 330 | int select_end; 331 | // selection start and end point in characters; if equal, no selection. 332 | // note that start may be less than or greater than end (e.g. when 333 | // dragging the mouse, start is where the initial click was, and you 334 | // can drag in either direction) 335 | 336 | unsigned char insert_mode; 337 | // each textfield keeps its own insert mode state. to keep an app-wide 338 | // insert mode, copy this value in/out of the app state 339 | 340 | ///////////////////// 341 | // 342 | // private data 343 | // 344 | unsigned char cursor_at_end_of_line; // not implemented yet 345 | unsigned char initialized; 346 | unsigned char has_preferred_x; 347 | unsigned char single_line; 348 | unsigned char padding1, padding2, padding3; 349 | float preferred_x; // this determines where the cursor up/down tries to seek to along x 350 | StbUndoState undostate; 351 | } STB_TexteditState; 352 | 353 | 354 | //////////////////////////////////////////////////////////////////////// 355 | // 356 | // StbTexteditRow 357 | // 358 | // Result of layout query, used by stb_textedit to determine where 359 | // the text in each row is. 360 | 361 | // result of layout query 362 | typedef struct 363 | { 364 | float x0,x1; // starting x location, end x location (allows for align=right, etc) 365 | float baseline_y_delta; // position of baseline relative to previous row's baseline 366 | float ymin,ymax; // height of row above and below baseline 367 | int num_chars; 368 | } StbTexteditRow; 369 | #endif //INCLUDE_STB_TEXTEDIT_H 370 | 371 | 372 | //////////////////////////////////////////////////////////////////////////// 373 | //////////////////////////////////////////////////////////////////////////// 374 | //// 375 | //// Implementation mode 376 | //// 377 | //// 378 | 379 | 380 | // implementation isn't include-guarded, since it might have indirectly 381 | // included just the "header" portion 382 | #ifdef STB_TEXTEDIT_IMPLEMENTATION 383 | 384 | #ifndef STB_TEXTEDIT_memmove 385 | #include 386 | #define STB_TEXTEDIT_memmove memmove 387 | #endif 388 | 389 | 390 | ///////////////////////////////////////////////////////////////////////////// 391 | // 392 | // Mouse input handling 393 | // 394 | 395 | // traverse the layout to locate the nearest character to a display position 396 | static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) 397 | { 398 | StbTexteditRow r; 399 | int n = STB_TEXTEDIT_STRINGLEN(str); 400 | float base_y = 0, prev_x; 401 | int i=0, k; 402 | 403 | r.x0 = r.x1 = 0; 404 | r.ymin = r.ymax = 0; 405 | r.num_chars = 0; 406 | 407 | // search rows to find one that straddles 'y' 408 | while (i < n) { 409 | STB_TEXTEDIT_LAYOUTROW(&r, str, i); 410 | if (r.num_chars <= 0) 411 | return n; 412 | 413 | if (i==0 && y < base_y + r.ymin) 414 | return 0; 415 | 416 | if (y < base_y + r.ymax) 417 | break; 418 | 419 | i += r.num_chars; 420 | base_y += r.baseline_y_delta; 421 | } 422 | 423 | // below all text, return 'after' last character 424 | if (i >= n) 425 | return n; 426 | 427 | // check if it's before the beginning of the line 428 | if (x < r.x0) 429 | return i; 430 | 431 | // check if it's before the end of the line 432 | if (x < r.x1) { 433 | // search characters in row for one that straddles 'x' 434 | prev_x = r.x0; 435 | for (k=0; k < r.num_chars; ++k) { 436 | float w = STB_TEXTEDIT_GETWIDTH(str, i, k); 437 | if (x < prev_x+w) { 438 | if (x < prev_x+w/2) 439 | return k+i; 440 | else 441 | return k+i+1; 442 | } 443 | prev_x += w; 444 | } 445 | // shouldn't happen, but if it does, fall through to end-of-line case 446 | } 447 | 448 | // if the last character is a newline, return that. otherwise return 'after' the last character 449 | if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE) 450 | return i+r.num_chars-1; 451 | else 452 | return i+r.num_chars; 453 | } 454 | 455 | // API click: on mouse down, move the cursor to the clicked location, and reset the selection 456 | static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) 457 | { 458 | // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse 459 | // goes off the top or bottom of the text 460 | if( state->single_line ) 461 | { 462 | StbTexteditRow r; 463 | STB_TEXTEDIT_LAYOUTROW(&r, str, 0); 464 | y = r.ymin; 465 | } 466 | 467 | state->cursor = stb_text_locate_coord(str, x, y); 468 | state->select_start = state->cursor; 469 | state->select_end = state->cursor; 470 | state->has_preferred_x = 0; 471 | } 472 | 473 | // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location 474 | static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) 475 | { 476 | int p = 0; 477 | 478 | // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse 479 | // goes off the top or bottom of the text 480 | if( state->single_line ) 481 | { 482 | StbTexteditRow r; 483 | STB_TEXTEDIT_LAYOUTROW(&r, str, 0); 484 | y = r.ymin; 485 | } 486 | 487 | if (state->select_start == state->select_end) 488 | state->select_start = state->cursor; 489 | 490 | p = stb_text_locate_coord(str, x, y); 491 | state->cursor = state->select_end = p; 492 | } 493 | 494 | ///////////////////////////////////////////////////////////////////////////// 495 | // 496 | // Keyboard input handling 497 | // 498 | 499 | // forward declarations 500 | static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); 501 | static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); 502 | static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); 503 | static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); 504 | static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); 505 | 506 | typedef struct 507 | { 508 | float x,y; // position of n'th character 509 | float height; // height of line 510 | int first_char, length; // first char of row, and length 511 | int prev_first; // first char of previous row 512 | } StbFindState; 513 | 514 | // find the x/y location of a character, and remember info about the previous row in 515 | // case we get a move-up event (for page up, we'll have to rescan) 516 | static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line) 517 | { 518 | StbTexteditRow r; 519 | int prev_start = 0; 520 | int z = STB_TEXTEDIT_STRINGLEN(str); 521 | int i=0, first; 522 | 523 | if (n == z) { 524 | // if it's at the end, then find the last line -- simpler than trying to 525 | // explicitly handle this case in the regular code 526 | if (single_line) { 527 | STB_TEXTEDIT_LAYOUTROW(&r, str, 0); 528 | find->y = 0; 529 | find->first_char = 0; 530 | find->length = z; 531 | find->height = r.ymax - r.ymin; 532 | find->x = r.x1; 533 | } else { 534 | find->y = 0; 535 | find->x = 0; 536 | find->height = 1; 537 | while (i < z) { 538 | STB_TEXTEDIT_LAYOUTROW(&r, str, i); 539 | prev_start = i; 540 | i += r.num_chars; 541 | } 542 | find->first_char = i; 543 | find->length = 0; 544 | find->prev_first = prev_start; 545 | } 546 | return; 547 | } 548 | 549 | // search rows to find the one that straddles character n 550 | find->y = 0; 551 | 552 | for(;;) { 553 | STB_TEXTEDIT_LAYOUTROW(&r, str, i); 554 | if (n < i + r.num_chars) 555 | break; 556 | prev_start = i; 557 | i += r.num_chars; 558 | find->y += r.baseline_y_delta; 559 | } 560 | 561 | find->first_char = first = i; 562 | find->length = r.num_chars; 563 | find->height = r.ymax - r.ymin; 564 | find->prev_first = prev_start; 565 | 566 | // now scan to find xpos 567 | find->x = r.x0; 568 | for (i=0; first+i < n; ++i) 569 | find->x += STB_TEXTEDIT_GETWIDTH(str, first, i); 570 | } 571 | 572 | #define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) 573 | 574 | // make the selection/cursor state valid if client altered the string 575 | static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 576 | { 577 | int n = STB_TEXTEDIT_STRINGLEN(str); 578 | if (STB_TEXT_HAS_SELECTION(state)) { 579 | if (state->select_start > n) state->select_start = n; 580 | if (state->select_end > n) state->select_end = n; 581 | // if clamping forced them to be equal, move the cursor to match 582 | if (state->select_start == state->select_end) 583 | state->cursor = state->select_start; 584 | } 585 | if (state->cursor > n) state->cursor = n; 586 | } 587 | 588 | // delete characters while updating undo 589 | static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) 590 | { 591 | stb_text_makeundo_delete(str, state, where, len); 592 | STB_TEXTEDIT_DELETECHARS(str, where, len); 593 | state->has_preferred_x = 0; 594 | } 595 | 596 | // delete the section 597 | static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 598 | { 599 | stb_textedit_clamp(str, state); 600 | if (STB_TEXT_HAS_SELECTION(state)) { 601 | if (state->select_start < state->select_end) { 602 | stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start); 603 | state->select_end = state->cursor = state->select_start; 604 | } else { 605 | stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end); 606 | state->select_start = state->cursor = state->select_end; 607 | } 608 | state->has_preferred_x = 0; 609 | } 610 | } 611 | 612 | // canoncialize the selection so start <= end 613 | static void stb_textedit_sortselection(STB_TexteditState *state) 614 | { 615 | if (state->select_end < state->select_start) { 616 | int temp = state->select_end; 617 | state->select_end = state->select_start; 618 | state->select_start = temp; 619 | } 620 | } 621 | 622 | // move cursor to first character of selection 623 | static void stb_textedit_move_to_first(STB_TexteditState *state) 624 | { 625 | if (STB_TEXT_HAS_SELECTION(state)) { 626 | stb_textedit_sortselection(state); 627 | state->cursor = state->select_start; 628 | state->select_end = state->select_start; 629 | state->has_preferred_x = 0; 630 | } 631 | } 632 | 633 | // move cursor to last character of selection 634 | static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 635 | { 636 | if (STB_TEXT_HAS_SELECTION(state)) { 637 | stb_textedit_sortselection(state); 638 | stb_textedit_clamp(str, state); 639 | state->cursor = state->select_end; 640 | state->select_start = state->select_end; 641 | state->has_preferred_x = 0; 642 | } 643 | } 644 | 645 | #ifdef STB_TEXTEDIT_IS_SPACE 646 | static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx ) 647 | { 648 | return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; 649 | } 650 | 651 | #ifndef STB_TEXTEDIT_MOVEWORDLEFT 652 | static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c ) 653 | { 654 | --c; // always move at least one character 655 | while( c >= 0 && !is_word_boundary( str, c ) ) 656 | --c; 657 | 658 | if( c < 0 ) 659 | c = 0; 660 | 661 | return c; 662 | } 663 | #define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous 664 | #endif 665 | 666 | #ifndef STB_TEXTEDIT_MOVEWORDRIGHT 667 | static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c ) 668 | { 669 | const int len = STB_TEXTEDIT_STRINGLEN(str); 670 | ++c; // always move at least one character 671 | while( c < len && !is_word_boundary( str, c ) ) 672 | ++c; 673 | 674 | if( c > len ) 675 | c = len; 676 | 677 | return c; 678 | } 679 | #define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next 680 | #endif 681 | 682 | #endif 683 | 684 | // update selection and cursor to match each other 685 | static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state) 686 | { 687 | if (!STB_TEXT_HAS_SELECTION(state)) 688 | state->select_start = state->select_end = state->cursor; 689 | else 690 | state->cursor = state->select_end; 691 | } 692 | 693 | // API cut: delete selection 694 | static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 695 | { 696 | if (STB_TEXT_HAS_SELECTION(state)) { 697 | stb_textedit_delete_selection(str,state); // implicitly clamps 698 | state->has_preferred_x = 0; 699 | return 1; 700 | } 701 | return 0; 702 | } 703 | 704 | // API paste: replace existing selection with passed-in text 705 | static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) 706 | { 707 | // if there's a selection, the paste should delete it 708 | stb_textedit_clamp(str, state); 709 | stb_textedit_delete_selection(str,state); 710 | // try to insert the characters 711 | if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) { 712 | stb_text_makeundo_insert(state, state->cursor, len); 713 | state->cursor += len; 714 | state->has_preferred_x = 0; 715 | return 1; 716 | } 717 | // remove the undo since we didn't actually insert the characters 718 | if (state->undostate.undo_point) 719 | --state->undostate.undo_point; 720 | return 0; 721 | } 722 | 723 | #ifndef STB_TEXTEDIT_KEYTYPE 724 | #define STB_TEXTEDIT_KEYTYPE int 725 | #endif 726 | 727 | // API key: process a keyboard input 728 | static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) 729 | { 730 | retry: 731 | switch (key) { 732 | default: { 733 | int c = STB_TEXTEDIT_KEYTOTEXT(key); 734 | if (c > 0) { 735 | STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c; 736 | 737 | // can't add newline in single-line mode 738 | if (c == '\n' && state->single_line) 739 | break; 740 | 741 | if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { 742 | stb_text_makeundo_replace(str, state, state->cursor, 1, 1); 743 | STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); 744 | if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { 745 | ++state->cursor; 746 | state->has_preferred_x = 0; 747 | } 748 | } else { 749 | stb_textedit_delete_selection(str,state); // implicitly clamps 750 | if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { 751 | stb_text_makeundo_insert(state, state->cursor, 1); 752 | ++state->cursor; 753 | state->has_preferred_x = 0; 754 | } 755 | } 756 | } 757 | break; 758 | } 759 | 760 | #ifdef STB_TEXTEDIT_K_INSERT 761 | case STB_TEXTEDIT_K_INSERT: 762 | state->insert_mode = !state->insert_mode; 763 | break; 764 | #endif 765 | 766 | case STB_TEXTEDIT_K_UNDO: 767 | stb_text_undo(str, state); 768 | state->has_preferred_x = 0; 769 | break; 770 | 771 | case STB_TEXTEDIT_K_REDO: 772 | stb_text_redo(str, state); 773 | state->has_preferred_x = 0; 774 | break; 775 | 776 | case STB_TEXTEDIT_K_LEFT: 777 | // if currently there's a selection, move cursor to start of selection 778 | if (STB_TEXT_HAS_SELECTION(state)) 779 | stb_textedit_move_to_first(state); 780 | else 781 | if (state->cursor > 0) 782 | --state->cursor; 783 | state->has_preferred_x = 0; 784 | break; 785 | 786 | case STB_TEXTEDIT_K_RIGHT: 787 | // if currently there's a selection, move cursor to end of selection 788 | if (STB_TEXT_HAS_SELECTION(state)) 789 | stb_textedit_move_to_last(str, state); 790 | else 791 | ++state->cursor; 792 | stb_textedit_clamp(str, state); 793 | state->has_preferred_x = 0; 794 | break; 795 | 796 | case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: 797 | stb_textedit_clamp(str, state); 798 | stb_textedit_prep_selection_at_cursor(state); 799 | // move selection left 800 | if (state->select_end > 0) 801 | --state->select_end; 802 | state->cursor = state->select_end; 803 | state->has_preferred_x = 0; 804 | break; 805 | 806 | #ifdef STB_TEXTEDIT_MOVEWORDLEFT 807 | case STB_TEXTEDIT_K_WORDLEFT: 808 | if (STB_TEXT_HAS_SELECTION(state)) 809 | stb_textedit_move_to_first(state); 810 | else { 811 | state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); 812 | stb_textedit_clamp( str, state ); 813 | } 814 | break; 815 | 816 | case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: 817 | if( !STB_TEXT_HAS_SELECTION( state ) ) 818 | stb_textedit_prep_selection_at_cursor(state); 819 | 820 | state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); 821 | state->select_end = state->cursor; 822 | 823 | stb_textedit_clamp( str, state ); 824 | break; 825 | #endif 826 | 827 | #ifdef STB_TEXTEDIT_MOVEWORDRIGHT 828 | case STB_TEXTEDIT_K_WORDRIGHT: 829 | if (STB_TEXT_HAS_SELECTION(state)) 830 | stb_textedit_move_to_last(str, state); 831 | else { 832 | state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); 833 | stb_textedit_clamp( str, state ); 834 | } 835 | break; 836 | 837 | case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: 838 | if( !STB_TEXT_HAS_SELECTION( state ) ) 839 | stb_textedit_prep_selection_at_cursor(state); 840 | 841 | state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); 842 | state->select_end = state->cursor; 843 | 844 | stb_textedit_clamp( str, state ); 845 | break; 846 | #endif 847 | 848 | case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: 849 | stb_textedit_prep_selection_at_cursor(state); 850 | // move selection right 851 | ++state->select_end; 852 | stb_textedit_clamp(str, state); 853 | state->cursor = state->select_end; 854 | state->has_preferred_x = 0; 855 | break; 856 | 857 | case STB_TEXTEDIT_K_DOWN: 858 | case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: { 859 | StbFindState find; 860 | StbTexteditRow row; 861 | int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; 862 | 863 | if (state->single_line) { 864 | // on windows, up&down in single-line behave like left&right 865 | key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); 866 | goto retry; 867 | } 868 | 869 | if (sel) 870 | stb_textedit_prep_selection_at_cursor(state); 871 | else if (STB_TEXT_HAS_SELECTION(state)) 872 | stb_textedit_move_to_last(str,state); 873 | 874 | // compute current position of cursor point 875 | stb_textedit_clamp(str, state); 876 | stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); 877 | 878 | // now find character position down a row 879 | if (find.length) { 880 | float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 881 | float x; 882 | int start = find.first_char + find.length; 883 | state->cursor = start; 884 | STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); 885 | x = row.x0; 886 | for (i=0; i < row.num_chars; ++i) { 887 | float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); 888 | #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE 889 | if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) 890 | break; 891 | #endif 892 | x += dx; 893 | if (x > goal_x) 894 | break; 895 | ++state->cursor; 896 | } 897 | stb_textedit_clamp(str, state); 898 | 899 | state->has_preferred_x = 1; 900 | state->preferred_x = goal_x; 901 | 902 | if (sel) 903 | state->select_end = state->cursor; 904 | } 905 | break; 906 | } 907 | 908 | case STB_TEXTEDIT_K_UP: 909 | case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: { 910 | StbFindState find; 911 | StbTexteditRow row; 912 | int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; 913 | 914 | if (state->single_line) { 915 | // on windows, up&down become left&right 916 | key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); 917 | goto retry; 918 | } 919 | 920 | if (sel) 921 | stb_textedit_prep_selection_at_cursor(state); 922 | else if (STB_TEXT_HAS_SELECTION(state)) 923 | stb_textedit_move_to_first(state); 924 | 925 | // compute current position of cursor point 926 | stb_textedit_clamp(str, state); 927 | stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); 928 | 929 | // can only go up if there's a previous row 930 | if (find.prev_first != find.first_char) { 931 | // now find character position up a row 932 | float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 933 | float x; 934 | state->cursor = find.prev_first; 935 | STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); 936 | x = row.x0; 937 | for (i=0; i < row.num_chars; ++i) { 938 | float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); 939 | #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE 940 | if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) 941 | break; 942 | #endif 943 | x += dx; 944 | if (x > goal_x) 945 | break; 946 | ++state->cursor; 947 | } 948 | stb_textedit_clamp(str, state); 949 | 950 | state->has_preferred_x = 1; 951 | state->preferred_x = goal_x; 952 | 953 | if (sel) 954 | state->select_end = state->cursor; 955 | } 956 | break; 957 | } 958 | 959 | case STB_TEXTEDIT_K_DELETE: 960 | case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: 961 | if (STB_TEXT_HAS_SELECTION(state)) 962 | stb_textedit_delete_selection(str, state); 963 | else { 964 | int n = STB_TEXTEDIT_STRINGLEN(str); 965 | if (state->cursor < n) 966 | stb_textedit_delete(str, state, state->cursor, 1); 967 | } 968 | state->has_preferred_x = 0; 969 | break; 970 | 971 | case STB_TEXTEDIT_K_BACKSPACE: 972 | case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: 973 | if (STB_TEXT_HAS_SELECTION(state)) 974 | stb_textedit_delete_selection(str, state); 975 | else { 976 | stb_textedit_clamp(str, state); 977 | if (state->cursor > 0) { 978 | stb_textedit_delete(str, state, state->cursor-1, 1); 979 | --state->cursor; 980 | } 981 | } 982 | state->has_preferred_x = 0; 983 | break; 984 | 985 | #ifdef STB_TEXTEDIT_K_TEXTSTART2 986 | case STB_TEXTEDIT_K_TEXTSTART2: 987 | #endif 988 | case STB_TEXTEDIT_K_TEXTSTART: 989 | state->cursor = state->select_start = state->select_end = 0; 990 | state->has_preferred_x = 0; 991 | break; 992 | 993 | #ifdef STB_TEXTEDIT_K_TEXTEND2 994 | case STB_TEXTEDIT_K_TEXTEND2: 995 | #endif 996 | case STB_TEXTEDIT_K_TEXTEND: 997 | state->cursor = STB_TEXTEDIT_STRINGLEN(str); 998 | state->select_start = state->select_end = 0; 999 | state->has_preferred_x = 0; 1000 | break; 1001 | 1002 | #ifdef STB_TEXTEDIT_K_TEXTSTART2 1003 | case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: 1004 | #endif 1005 | case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: 1006 | stb_textedit_prep_selection_at_cursor(state); 1007 | state->cursor = state->select_end = 0; 1008 | state->has_preferred_x = 0; 1009 | break; 1010 | 1011 | #ifdef STB_TEXTEDIT_K_TEXTEND2 1012 | case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: 1013 | #endif 1014 | case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: 1015 | stb_textedit_prep_selection_at_cursor(state); 1016 | state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); 1017 | state->has_preferred_x = 0; 1018 | break; 1019 | 1020 | 1021 | #ifdef STB_TEXTEDIT_K_LINESTART2 1022 | case STB_TEXTEDIT_K_LINESTART2: 1023 | #endif 1024 | case STB_TEXTEDIT_K_LINESTART: 1025 | stb_textedit_clamp(str, state); 1026 | stb_textedit_move_to_first(state); 1027 | if (state->single_line) 1028 | state->cursor = 0; 1029 | else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) 1030 | --state->cursor; 1031 | state->has_preferred_x = 0; 1032 | break; 1033 | 1034 | #ifdef STB_TEXTEDIT_K_LINEEND2 1035 | case STB_TEXTEDIT_K_LINEEND2: 1036 | #endif 1037 | case STB_TEXTEDIT_K_LINEEND: { 1038 | int n = STB_TEXTEDIT_STRINGLEN(str); 1039 | stb_textedit_clamp(str, state); 1040 | stb_textedit_move_to_first(state); 1041 | if (state->single_line) 1042 | state->cursor = n; 1043 | else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) 1044 | ++state->cursor; 1045 | state->has_preferred_x = 0; 1046 | break; 1047 | } 1048 | 1049 | #ifdef STB_TEXTEDIT_K_LINESTART2 1050 | case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: 1051 | #endif 1052 | case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: 1053 | stb_textedit_clamp(str, state); 1054 | stb_textedit_prep_selection_at_cursor(state); 1055 | if (state->single_line) 1056 | state->cursor = 0; 1057 | else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) 1058 | --state->cursor; 1059 | state->select_end = state->cursor; 1060 | state->has_preferred_x = 0; 1061 | break; 1062 | 1063 | #ifdef STB_TEXTEDIT_K_LINEEND2 1064 | case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: 1065 | #endif 1066 | case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: { 1067 | int n = STB_TEXTEDIT_STRINGLEN(str); 1068 | stb_textedit_clamp(str, state); 1069 | stb_textedit_prep_selection_at_cursor(state); 1070 | if (state->single_line) 1071 | state->cursor = n; 1072 | else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) 1073 | ++state->cursor; 1074 | state->select_end = state->cursor; 1075 | state->has_preferred_x = 0; 1076 | break; 1077 | } 1078 | 1079 | // @TODO: 1080 | // STB_TEXTEDIT_K_PGUP - move cursor up a page 1081 | // STB_TEXTEDIT_K_PGDOWN - move cursor down a page 1082 | } 1083 | } 1084 | 1085 | ///////////////////////////////////////////////////////////////////////////// 1086 | // 1087 | // Undo processing 1088 | // 1089 | // @OPTIMIZE: the undo/redo buffer should be circular 1090 | 1091 | static void stb_textedit_flush_redo(StbUndoState *state) 1092 | { 1093 | state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; 1094 | state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; 1095 | } 1096 | 1097 | // discard the oldest entry in the undo list 1098 | static void stb_textedit_discard_undo(StbUndoState *state) 1099 | { 1100 | if (state->undo_point > 0) { 1101 | // if the 0th undo state has characters, clean those up 1102 | if (state->undo_rec[0].char_storage >= 0) { 1103 | int n = state->undo_rec[0].insert_length, i; 1104 | // delete n characters from all other records 1105 | state->undo_char_point -= n; 1106 | STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE))); 1107 | for (i=0; i < state->undo_point; ++i) 1108 | if (state->undo_rec[i].char_storage >= 0) 1109 | state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it 1110 | } 1111 | --state->undo_point; 1112 | STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); 1113 | } 1114 | } 1115 | 1116 | // discard the oldest entry in the redo list--it's bad if this 1117 | // ever happens, but because undo & redo have to store the actual 1118 | // characters in different cases, the redo character buffer can 1119 | // fill up even though the undo buffer didn't 1120 | static void stb_textedit_discard_redo(StbUndoState *state) 1121 | { 1122 | int k = STB_TEXTEDIT_UNDOSTATECOUNT-1; 1123 | 1124 | if (state->redo_point <= k) { 1125 | // if the k'th undo state has characters, clean those up 1126 | if (state->undo_rec[k].char_storage >= 0) { 1127 | int n = state->undo_rec[k].insert_length, i; 1128 | // move the remaining redo character data to the end of the buffer 1129 | state->redo_char_point += n; 1130 | STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE))); 1131 | // adjust the position of all the other records to account for above memmove 1132 | for (i=state->redo_point; i < k; ++i) 1133 | if (state->undo_rec[i].char_storage >= 0) 1134 | state->undo_rec[i].char_storage += n; 1135 | } 1136 | // now move all the redo records towards the end of the buffer; the first one is at 'redo_point' 1137 | // {DEAR IMGUI] 1138 | size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0])); 1139 | const char* buf_begin = (char*)state->undo_rec; (void)buf_begin; 1140 | const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end; 1141 | IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin); 1142 | IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end); 1143 | STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size); 1144 | 1145 | // now move redo_point to point to the new one 1146 | ++state->redo_point; 1147 | } 1148 | } 1149 | 1150 | static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars) 1151 | { 1152 | // any time we create a new undo record, we discard redo 1153 | stb_textedit_flush_redo(state); 1154 | 1155 | // if we have no free records, we have to make room, by sliding the 1156 | // existing records down 1157 | if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1158 | stb_textedit_discard_undo(state); 1159 | 1160 | // if the characters to store won't possibly fit in the buffer, we can't undo 1161 | if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) { 1162 | state->undo_point = 0; 1163 | state->undo_char_point = 0; 1164 | return NULL; 1165 | } 1166 | 1167 | // if we don't have enough free characters in the buffer, we have to make room 1168 | while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT) 1169 | stb_textedit_discard_undo(state); 1170 | 1171 | return &state->undo_rec[state->undo_point++]; 1172 | } 1173 | 1174 | static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) 1175 | { 1176 | StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); 1177 | if (r == NULL) 1178 | return NULL; 1179 | 1180 | r->where = pos; 1181 | r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len; 1182 | r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len; 1183 | 1184 | if (insert_len == 0) { 1185 | r->char_storage = -1; 1186 | return NULL; 1187 | } else { 1188 | r->char_storage = state->undo_char_point; 1189 | state->undo_char_point += insert_len; 1190 | return &state->undo_char[r->char_storage]; 1191 | } 1192 | } 1193 | 1194 | static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 1195 | { 1196 | StbUndoState *s = &state->undostate; 1197 | StbUndoRecord u, *r; 1198 | if (s->undo_point == 0) 1199 | return; 1200 | 1201 | // we need to do two things: apply the undo record, and create a redo record 1202 | u = s->undo_rec[s->undo_point-1]; 1203 | r = &s->undo_rec[s->redo_point-1]; 1204 | r->char_storage = -1; 1205 | 1206 | r->insert_length = u.delete_length; 1207 | r->delete_length = u.insert_length; 1208 | r->where = u.where; 1209 | 1210 | if (u.delete_length) { 1211 | // if the undo record says to delete characters, then the redo record will 1212 | // need to re-insert the characters that get deleted, so we need to store 1213 | // them. 1214 | 1215 | // there are three cases: 1216 | // there's enough room to store the characters 1217 | // characters stored for *redoing* don't leave room for redo 1218 | // characters stored for *undoing* don't leave room for redo 1219 | // if the last is true, we have to bail 1220 | 1221 | if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) { 1222 | // the undo records take up too much character space; there's no space to store the redo characters 1223 | r->insert_length = 0; 1224 | } else { 1225 | int i; 1226 | 1227 | // there's definitely room to store the characters eventually 1228 | while (s->undo_char_point + u.delete_length > s->redo_char_point) { 1229 | // should never happen: 1230 | if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1231 | return; 1232 | // there's currently not enough room, so discard a redo record 1233 | stb_textedit_discard_redo(s); 1234 | } 1235 | r = &s->undo_rec[s->redo_point-1]; 1236 | 1237 | r->char_storage = s->redo_char_point - u.delete_length; 1238 | s->redo_char_point = s->redo_char_point - u.delete_length; 1239 | 1240 | // now save the characters 1241 | for (i=0; i < u.delete_length; ++i) 1242 | s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); 1243 | } 1244 | 1245 | // now we can carry out the deletion 1246 | STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); 1247 | } 1248 | 1249 | // check type of recorded action: 1250 | if (u.insert_length) { 1251 | // easy case: was a deletion, so we need to insert n characters 1252 | STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); 1253 | s->undo_char_point -= u.insert_length; 1254 | } 1255 | 1256 | state->cursor = u.where + u.insert_length; 1257 | 1258 | s->undo_point--; 1259 | s->redo_point--; 1260 | } 1261 | 1262 | static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 1263 | { 1264 | StbUndoState *s = &state->undostate; 1265 | StbUndoRecord *u, r; 1266 | if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1267 | return; 1268 | 1269 | // we need to do two things: apply the redo record, and create an undo record 1270 | u = &s->undo_rec[s->undo_point]; 1271 | r = s->undo_rec[s->redo_point]; 1272 | 1273 | // we KNOW there must be room for the undo record, because the redo record 1274 | // was derived from an undo record 1275 | 1276 | u->delete_length = r.insert_length; 1277 | u->insert_length = r.delete_length; 1278 | u->where = r.where; 1279 | u->char_storage = -1; 1280 | 1281 | if (r.delete_length) { 1282 | // the redo record requires us to delete characters, so the undo record 1283 | // needs to store the characters 1284 | 1285 | if (s->undo_char_point + u->insert_length > s->redo_char_point) { 1286 | u->insert_length = 0; 1287 | u->delete_length = 0; 1288 | } else { 1289 | int i; 1290 | u->char_storage = s->undo_char_point; 1291 | s->undo_char_point = s->undo_char_point + u->insert_length; 1292 | 1293 | // now save the characters 1294 | for (i=0; i < u->insert_length; ++i) 1295 | s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); 1296 | } 1297 | 1298 | STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); 1299 | } 1300 | 1301 | if (r.insert_length) { 1302 | // easy case: need to insert n characters 1303 | STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); 1304 | s->redo_char_point += r.insert_length; 1305 | } 1306 | 1307 | state->cursor = r.where + r.insert_length; 1308 | 1309 | s->undo_point++; 1310 | s->redo_point++; 1311 | } 1312 | 1313 | static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length) 1314 | { 1315 | stb_text_createundo(&state->undostate, where, 0, length); 1316 | } 1317 | 1318 | static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) 1319 | { 1320 | int i; 1321 | STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); 1322 | if (p) { 1323 | for (i=0; i < length; ++i) 1324 | p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); 1325 | } 1326 | } 1327 | 1328 | static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) 1329 | { 1330 | int i; 1331 | STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); 1332 | if (p) { 1333 | for (i=0; i < old_length; ++i) 1334 | p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); 1335 | } 1336 | } 1337 | 1338 | // reset the state to default 1339 | static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line) 1340 | { 1341 | state->undostate.undo_point = 0; 1342 | state->undostate.undo_char_point = 0; 1343 | state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; 1344 | state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; 1345 | state->select_end = state->select_start = 0; 1346 | state->cursor = 0; 1347 | state->has_preferred_x = 0; 1348 | state->preferred_x = 0; 1349 | state->cursor_at_end_of_line = 0; 1350 | state->initialized = 1; 1351 | state->single_line = (unsigned char) is_single_line; 1352 | state->insert_mode = 0; 1353 | } 1354 | 1355 | // API initialize 1356 | static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) 1357 | { 1358 | stb_textedit_clear_state(state, is_single_line); 1359 | } 1360 | 1361 | #if defined(__GNUC__) || defined(__clang__) 1362 | #pragma GCC diagnostic push 1363 | #pragma GCC diagnostic ignored "-Wcast-qual" 1364 | #endif 1365 | 1366 | static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) 1367 | { 1368 | return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len); 1369 | } 1370 | 1371 | #if defined(__GNUC__) || defined(__clang__) 1372 | #pragma GCC diagnostic pop 1373 | #endif 1374 | 1375 | #endif//STB_TEXTEDIT_IMPLEMENTATION 1376 | 1377 | /* 1378 | ------------------------------------------------------------------------------ 1379 | This software is available under 2 licenses -- choose whichever you prefer. 1380 | ------------------------------------------------------------------------------ 1381 | ALTERNATIVE A - MIT License 1382 | Copyright (c) 2017 Sean Barrett 1383 | Permission is hereby granted, free of charge, to any person obtaining a copy of 1384 | this software and associated documentation files (the "Software"), to deal in 1385 | the Software without restriction, including without limitation the rights to 1386 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 1387 | of the Software, and to permit persons to whom the Software is furnished to do 1388 | so, subject to the following conditions: 1389 | The above copyright notice and this permission notice shall be included in all 1390 | copies or substantial portions of the Software. 1391 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1392 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1393 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1394 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1395 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1396 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1397 | SOFTWARE. 1398 | ------------------------------------------------------------------------------ 1399 | ALTERNATIVE B - Public Domain (www.unlicense.org) 1400 | This is free and unencumbered software released into the public domain. 1401 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 1402 | software, either in source code form or as a compiled binary, for any purpose, 1403 | commercial or non-commercial, and by any means. 1404 | In jurisdictions that recognize copyright laws, the author or authors of this 1405 | software dedicate any and all copyright interest in the software to the public 1406 | domain. We make this dedication for the benefit of the public at large and to 1407 | the detriment of our heirs and successors. We intend this dedication to be an 1408 | overt act of relinquishment in perpetuity of all present and future rights to 1409 | this software under copyright law. 1410 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1411 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1412 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1413 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1414 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 1415 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1416 | ------------------------------------------------------------------------------ 1417 | */ 1418 | --------------------------------------------------------------------------------