├── 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 |
--------------------------------------------------------------------------------