├── .gitignore ├── readme.md ├── hunt_internal ├── menu │ ├── menu.h │ ├── d3d11 │ │ ├── d3d11.h │ │ └── d3d11.cpp │ ├── variables.h │ └── menu.cpp ├── hunt │ └── bones │ │ ├── bones.h │ │ └── bones.cpp ├── hunt_internal.vcxproj.user ├── utils │ ├── utils.h │ ├── libraries │ │ ├── imgui │ │ │ ├── imgui_impl_dx11.h │ │ │ ├── imgui_impl_win32.h │ │ │ ├── imconfig.h │ │ │ ├── shaders.h │ │ │ ├── imgui_impl_win32.cpp │ │ │ ├── imstb_rectpack.h │ │ │ ├── imgui_impl_dx11.cpp │ │ │ └── imstb_textedit.h │ │ └── xor.h │ └── utils.cpp ├── features │ ├── features.h │ ├── features.cpp │ └── esp │ │ └── esp.cpp ├── cry_engine │ ├── sdk.h │ ├── cry_game │ │ └── game_framwork.h │ ├── cry_renderer │ │ ├── renderer.cpp │ │ └── renderer.h │ ├── cry_entity_system │ │ ├── entity_system.h │ │ ├── entity.h │ │ └── entity.cpp │ ├── math │ │ ├── quat.h │ │ ├── vector_2d.h │ │ ├── vector.h │ │ └── matrix.h │ ├── cry_animation │ │ └── cry_animation.h │ └── sdk.cpp ├── hooks │ ├── wndproc │ │ └── wndproc.cpp │ ├── hooks.h │ ├── hooks.cpp │ └── present │ │ └── present.cpp ├── hunt.cpp ├── includes.h ├── hunt_internal.vcxproj.filters └── hunt_internal.vcxproj ├── .gitmodules └── hunt_internal.sln /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs 2 | /bin -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # hunt_internal 2 | internal cheat for hunt showdown 3 | -------------------------------------------------------------------------------- /hunt_internal/menu/menu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "variables.h" 3 | 4 | namespace menu { 5 | bool initialize(); 6 | void render(); 7 | } -------------------------------------------------------------------------------- /hunt_internal/hunt/bones/bones.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace hunt::bones { 4 | std::vector> get_array(cry_engine::cry_entity_system::i_entity* entity); 5 | } -------------------------------------------------------------------------------- /hunt_internal/hunt_internal.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /hunt_internal/utils/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace utils { 4 | std::uintptr_t pattern_scan(std::uintptr_t address, const char* signature, bool relative = false); 5 | } 6 | 7 | namespace utils::console { 8 | bool initialize(const std::string& title); 9 | void release(); 10 | } -------------------------------------------------------------------------------- /hunt_internal/features/features.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace features { 4 | void run(); 5 | } 6 | 7 | namespace features::esp { 8 | void draw(cry_engine::cry_entity_system::i_entity* local_entity, cry_engine::cry_entity_system::i_entity* entity, cry_engine::cry_entity_system::i_entity_class* entity_class); 9 | } -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "hunt_internal/utils/libraries/minhook"] 2 | path = hunt_internal/utils/libraries/minhook 3 | url = https://github.com/TsudaKageyu/minhook.git 4 | [submodule "hunt_internal/utils/libraries/lazy_importer"] 5 | path = hunt_internal/utils/libraries/lazy_importer 6 | url = https://github.com/JustasMasiulis/lazy_importer.git 7 | -------------------------------------------------------------------------------- /hunt_internal/menu/d3d11/d3d11.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace d3d11 { 4 | inline ID3D11Device* device = nullptr; 5 | inline ID3D11DeviceContext* context = nullptr; 6 | inline ID3D11RenderTargetView* render_target_view; 7 | static std::uint64_t* methods_table; 8 | 9 | bool initialize(); 10 | unsigned long long get_present(); 11 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/sdk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::sdk { 4 | bool initialize(); 5 | 6 | template 7 | __forceinline return_type call(void* instance, args... _args) { 8 | using fn = return_type(__thiscall*)(void*, args...); 9 | 10 | auto function = (*reinterpret_cast(instance))[index]; 11 | return function(instance, _args...); 12 | } 13 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/cry_game/game_framwork.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::cry_entity_system { 4 | class i_entity; 5 | } 6 | 7 | namespace cry_engine::cry_game { 8 | class i_game_framework { 9 | public: 10 | cry_engine::cry_entity_system::i_entity* get_client_entity() { 11 | return cry_engine::sdk::call<71, cry_engine::cry_entity_system::i_entity*>(this); 12 | } 13 | }; 14 | 15 | inline cry_engine::cry_game::i_game_framework* game_framework; 16 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/cry_renderer/renderer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool cry_engine::cry_renderer::world_to_screen(const cry_engine::math::vector& origin, cry_engine::math::vector& screen) { 4 | float x, y, z; 5 | 6 | cry_engine::cry_renderer::renderer->project_to_screen(origin.x, origin.y, origin.z, &x, &y, &z); 7 | 8 | screen.x = x * cry_engine::cry_renderer::screen.x * 0.01f; 9 | screen.y = y * cry_engine::cry_renderer::screen.y * 0.01f; 10 | screen.z = z * 1.0f; 11 | 12 | return (screen.z < 1.0f); 13 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/cry_renderer/renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::cry_renderer { 4 | class i_renderer { 5 | public: 6 | bool project_to_screen(float ptx, float pty, float ptz, float* sx, float* sy, float* sz) { 7 | return cry_engine::sdk::call<65, bool>(this, ptx, pty, ptz, sx, sy, sz); 8 | } 9 | }; 10 | 11 | inline cry_engine::math::vector_2d screen{ 0.f, 0.f }; 12 | bool world_to_screen(const cry_engine::math::vector& origin, cry_engine::math::vector& screen); 13 | 14 | inline cry_engine::cry_renderer::i_renderer* renderer; 15 | } -------------------------------------------------------------------------------- /hunt_internal/hooks/wndproc/wndproc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../hooks.h" 3 | 4 | std::int64_t __stdcall hooks::wndproc::hook(const HWND hwnd, const unsigned int message, const WPARAM wparam, const LPARAM lparam) { 5 | if (message == WM_KEYDOWN && wparam == VK_INSERT) { 6 | variables::menu::opened = !variables::menu::opened; 7 | } 8 | 9 | inline std::int64_t ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 10 | ImGui_ImplWin32_WndProcHandler(window, message, wparam, lparam); 11 | 12 | return CallWindowProcA(wndproc::original, hwnd, message, wparam, lparam); 13 | } -------------------------------------------------------------------------------- /hunt_internal/hooks/hooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace hooks { 4 | inline HWND window; 5 | inline float delta_time; 6 | 7 | bool initialize(); 8 | bool release(); 9 | } 10 | 11 | namespace hooks::present { 12 | inline std::once_flag flag; 13 | using fn = long(__stdcall*)(IDXGISwapChain*, unsigned int, unsigned int); 14 | inline fn original; 15 | long __stdcall hook(IDXGISwapChain* swap_chain, unsigned int sync_interval, unsigned int flags); 16 | } 17 | 18 | namespace hooks::wndproc { 19 | using fn = std::int64_t(__stdcall*)(HWND, UINT, WPARAM, LPARAM); 20 | inline fn original; 21 | std::int64_t __stdcall hook(HWND hwnd, unsigned int message, WPARAM wparam, LPARAM lparam); 22 | } -------------------------------------------------------------------------------- /hunt_internal/menu/variables.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace variables::menu { 4 | inline bool opened{ true }; 5 | } 6 | 7 | namespace variables::entities { 8 | inline bool hunter{ false }; 9 | inline float hunter_color[4]{ 1.f, 0.f, 0.f, 1.f }; 10 | 11 | inline bool zombie{ false }; 12 | inline float zombie_color[4]{ 0.2f, 0.5f, 0.9f, 1.f }; 13 | 14 | inline bool boss_zombie{ false }; 15 | inline float boss_zombie_color[4]{ 0.2f, 0.5f, 0.9f, 1.f }; 16 | 17 | inline bool clue{ false }; 18 | inline float clue_color[4]{ 0.2f, 0.5f, 0.9f, 1.f }; 19 | 20 | inline bool extraction{ false }; 21 | inline float extraction_color[4]{ 0.2f, 0.5f, 0.9f, 1.f }; 22 | 23 | inline float max_distance{ 100.f }; 24 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/cry_entity_system/entity_system.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::cry_entity_system { 4 | class i_entity_it { 5 | public: 6 | bool is_end() { 7 | return cry_engine::sdk::call<3, bool>(this); 8 | } 9 | 10 | cry_engine::cry_entity_system::i_entity* next() { 11 | return cry_engine::sdk::call<4, cry_engine::cry_entity_system::i_entity*>(this); 12 | } 13 | 14 | void move_first() { 15 | return cry_engine::sdk::call<6, void>(this); 16 | } 17 | }; 18 | 19 | class i_entity_system { 20 | public: 21 | void get_entity_iterator(cry_engine::cry_entity_system::i_entity_it** it) { 22 | return cry_engine::sdk::call<19, void>(this, it); 23 | } 24 | }; 25 | 26 | inline cry_engine::cry_entity_system::i_entity_system* entity_system; 27 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/math/quat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::math { 4 | class quat { 5 | public: 6 | cry_engine::math::vector v; 7 | float w; 8 | 9 | friend float operator|(const cry_engine::math::quat& q, const cry_engine::math::quat& p) { 10 | return (q.v.x * p.v.x + q.v.y * p.v.y + q.v.z * p.v.z + q.w * p.w); 11 | } 12 | 13 | friend cry_engine::math::quat operator-(const cry_engine::math::quat& q, const cry_engine::math::quat& p) { 14 | cry_engine::math::quat ret{}; 15 | ret.w = q.w - p.w; 16 | 17 | ret.v.x = q.v.x - p.v.x; 18 | ret.v.y = q.v.y - p.v.y; 19 | ret.v.z = q.v.z - p.v.z; 20 | 21 | return ret; 22 | } 23 | }; 24 | 25 | class quat_t { 26 | public: 27 | cry_engine::math::quat q; 28 | cry_engine::math::vector t; 29 | }; 30 | } -------------------------------------------------------------------------------- /hunt_internal/hooks/hooks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hooks.h" 3 | 4 | bool hooks::initialize() { 5 | if (MH_Initialize() != MH_OK) throw std::runtime_error(_("failed to initialize min_hook")); 6 | 7 | if (d3d11::initialize()) { 8 | if (MH_CreateHook(reinterpret_cast(d3d11::get_present()), &hooks::present::hook, reinterpret_cast(&hooks::present::original)) != MH_OK) { 9 | throw std::runtime_error(_("failed to hook present")); 10 | } 11 | } 12 | 13 | if (MH_EnableHook(nullptr) != MH_OK) throw std::runtime_error(_("failed to initialize hooks")); 14 | 15 | return true; 16 | } 17 | 18 | bool hooks::release() { 19 | MH_Uninitialize(); 20 | 21 | MH_DisableHook(nullptr); 22 | MH_RemoveHook(nullptr); 23 | 24 | utils::console::release(); 25 | 26 | return true; 27 | } -------------------------------------------------------------------------------- /hunt_internal.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.32126.317 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hunt_internal", "hunt_internal\hunt_internal.vcxproj", "{B479C0F2-2A5A-400A-90BE-D2A1F8E9341B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {B479C0F2-2A5A-400A-90BE-D2A1F8E9341B}.Release|x64.ActiveCfg = Release|x64 14 | {B479C0F2-2A5A-400A-90BE-D2A1F8E9341B}.Release|x64.Build.0 = Release|x64 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | GlobalSection(ExtensibilityGlobals) = postSolution 20 | SolutionGuid = {99FA59A6-F0D3-43D7-9635-A8FBEA07178A} 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /hunt_internal/features/features.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void features::run() { 4 | const auto game_framework = cry_engine::cry_game::game_framework; 5 | if (!game_framework) return; 6 | 7 | const auto local_entity = game_framework->get_client_entity(); 8 | if (!local_entity) return; 9 | 10 | const auto entity_system = cry_engine::cry_entity_system::entity_system; 11 | if (!entity_system) return; 12 | 13 | cry_engine::cry_entity_system::i_entity_it* entity_iterator{}; 14 | entity_system->get_entity_iterator(&entity_iterator); 15 | if (!entity_iterator) return; 16 | 17 | entity_iterator->move_first(); 18 | 19 | cry_engine::cry_entity_system::i_entity* entity = nullptr; 20 | while (!entity_iterator->is_end()) { 21 | entity = entity_iterator->next(); 22 | if (entity == local_entity) continue; 23 | 24 | auto entity_class = entity->get_class(); 25 | if (!entity_class) continue; 26 | 27 | const auto entity_class_name = entity_class->get_name(); 28 | if (!entity_class_name) continue; 29 | 30 | features::esp::draw(local_entity, entity, entity_class); 31 | } 32 | } -------------------------------------------------------------------------------- /hunt_internal/hunt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hooks/hooks.h" 3 | 4 | void initialize(const HMODULE module) { 5 | try { 6 | utils::console::initialize(_("hunt_internal")); 7 | cry_engine::sdk::initialize(); 8 | hooks::initialize(); 9 | } 10 | 11 | catch (const std::runtime_error& error) { 12 | LI_FN(MessageBoxA)(nullptr, error.what(), _("hunt_internal"), MB_OK | MB_ICONERROR); 13 | LI_FN(FreeLibraryAndExitThread)(module, 0); 14 | } 15 | 16 | while (!LI_FN(GetAsyncKeyState)(VK_END)) { 17 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 18 | } 19 | 20 | LI_FN(FreeLibraryAndExitThread)(module, 0); 21 | } 22 | 23 | bool DllMain(const HMODULE module, const std::uint32_t call_reason, void* reserved [[maybe_unused]] ) { 24 | LI_FN(DisableThreadLibraryCalls)(module); 25 | 26 | switch (call_reason) { 27 | case DLL_PROCESS_ATTACH: 28 | if (const auto handle = LI_FN(CreateThread)(nullptr, NULL, reinterpret_cast(initialize), module, NULL, nullptr)) { 29 | LI_FN(CloseHandle)(handle); 30 | } 31 | break; 32 | case DLL_PROCESS_DETACH: 33 | hooks::release(); 34 | break; 35 | default: 36 | break; 37 | } 38 | 39 | return true; 40 | } -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/imgui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer for DirectX11 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 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit 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 ID3D11Device; 15 | struct ID3D11DeviceContext; 16 | 17 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 18 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 19 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 20 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 21 | 22 | // Use if you want to reset your rendering device without losing ImGui state. 23 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 24 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/imgui/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 | */ -------------------------------------------------------------------------------- /hunt_internal/cry_engine/cry_animation/cry_animation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::cry_animation { 4 | class i_skeleton_pose { 5 | public: 6 | cry_engine::math::quat_t& get_abs_joint_by_id(std::uint32_t joint_id) { 7 | return cry_engine::sdk::call<24, cry_engine::math::quat_t&>(this, joint_id); 8 | } 9 | 10 | cry_engine::math::quat_t& get_rel_joint_by_id(std::uint32_t joint_id) { 11 | return cry_engine::sdk::call<25, cry_engine::math::quat_t&>(this, joint_id); 12 | } 13 | }; 14 | 15 | class i_default_skeleton { 16 | public: 17 | std::uint32_t get_joint_count() { 18 | return cry_engine::sdk::call<1, std::uint32_t>(this); 19 | } 20 | 21 | const char* get_joint_name_by_id(std::int32_t id) { 22 | return cry_engine::sdk::call<8, const char*>(this, id); 23 | } 24 | 25 | std::int32_t get_joint_id_by_name(const char* name) { 26 | return cry_engine::sdk::call<9, std::int32_t>(this, name); 27 | } 28 | }; 29 | 30 | class i_character_instance { 31 | public: 32 | cry_engine::cry_animation::i_skeleton_pose* get_skeleton_pose() { 33 | return cry_engine::sdk::call<16, cry_engine::cry_animation::i_skeleton_pose*>(this); 34 | } 35 | 36 | cry_engine::cry_animation::i_default_skeleton& get_default_skeleton() { 37 | return cry_engine::sdk::call<20, cry_engine::cry_animation::i_default_skeleton&>(this); 38 | } 39 | }; 40 | } -------------------------------------------------------------------------------- /hunt_internal/includes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "utils/utils.h" 19 | #include "utils/libraries/minhook/include/MinHook.h" 20 | #include "utils/libraries/lazy_importer/include/lazy_importer.hpp" 21 | #include "utils/libraries/xor.h" 22 | 23 | #include "utils/libraries/imgui/imgui.h" 24 | #include "utils/libraries/imgui/imgui_impl_dx11.h" 25 | #include "utils/libraries/imgui/imgui_impl_win32.h" 26 | #include "utils/libraries/imgui/imgui_internal.h" 27 | 28 | #include "cry_engine/sdk.h" 29 | 30 | #include "cry_engine/math/vector.h" 31 | #include "cry_engine/math/vector_2d.h" 32 | #include "cry_engine/math/quat.h" 33 | #include "cry_engine/math/matrix.h" 34 | 35 | #include "cry_engine/cry_game/game_framwork.h" 36 | #include "cry_engine/cry_animation/cry_animation.h" 37 | #include "cry_engine/cry_entity_system/entity_system.h" 38 | #include "cry_engine/cry_entity_system/entity.h" 39 | #include "cry_engine/cry_renderer/renderer.h" 40 | 41 | #include "features/features.h" 42 | #include "menu/d3d11/d3d11.h" 43 | #include "menu/menu.h" 44 | 45 | #include "hunt/bones/bones.h" -------------------------------------------------------------------------------- /hunt_internal/cry_engine/sdk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../hooks/hooks.h" 3 | 4 | bool cry_engine::sdk::initialize() { 5 | const auto main = reinterpret_cast(LI_FN(GetModuleHandleA)(nullptr)); 6 | if (!main) throw std::runtime_error(_("failed to get main handle")); 7 | 8 | cry_engine::cry_game::game_framework = *reinterpret_cast(utils::pattern_scan(main, _("48 8B 0D ? ? ? ? 48 8B 01 FF 90 ? ? ? ? 48 8B 54 24 38 4C 8D 4C 24 20 4C 8D 05 ? ? ? ? 48 8B C8 4C 8B 10 41 FF 52 ? 48 8D 4C 24 20"), true)); 9 | if (!cry_engine::cry_game::game_framework) throw std::runtime_error(_("failed to get cry_engine::cry_game::game_framework")); 10 | 11 | cry_engine::cry_entity_system::entity_system = *reinterpret_cast(utils::pattern_scan(main, _("48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 50 ? 48 8B D8 48 85 C0 0F 84 90"), true)); 12 | if (!cry_engine::cry_entity_system::entity_system) throw std::runtime_error(_("failed to get cry_engine::cry_entity_system::entity_system")); 13 | 14 | cry_engine::cry_renderer::renderer = *reinterpret_cast(utils::pattern_scan(main, _("48 8B 0D ? ? ? ? 48 89 BC 24 90 ? ? ? 0F 29 B4 24"), true)); 15 | if (!cry_engine::cry_renderer::renderer) throw std::runtime_error(_("failed to get cry_engine::cry_renderer::renderer")); 16 | 17 | return true; 18 | } 19 | -------------------------------------------------------------------------------- /hunt_internal/cry_engine/cry_entity_system/entity.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::cry_entity_system { 4 | class i_entity_class { 5 | public: 6 | const char* get_name() { 7 | return cry_engine::sdk::call<2, const char*>(this); 8 | } 9 | 10 | std::tuple get_entity_name(std::string distance); 11 | }; 12 | 13 | class i_entity { 14 | public: 15 | cry_engine::cry_entity_system::i_entity_class* get_class() { 16 | return cry_engine::sdk::call<3, cry_engine::cry_entity_system::i_entity_class*>(this); 17 | } 18 | 19 | const char* get_name() { 20 | return cry_engine::sdk::call<16, const char*>(this); 21 | } 22 | 23 | cry_engine::math::matrix& get_world_tm() { 24 | return cry_engine::sdk::call<31, cry_engine::math::matrix&>(this); 25 | } 26 | 27 | cry_engine::math::vector& get_position() { 28 | return cry_engine::sdk::call<38, cry_engine::math::vector&>(this); 29 | } 30 | 31 | cry_engine::cry_animation::i_character_instance* get_character(int slot = 0) { 32 | return cry_engine::sdk::call<122, cry_engine::cry_animation::i_character_instance*>(this, slot); 33 | } 34 | 35 | float get_distance_to(cry_engine::cry_entity_system::i_entity* entity); 36 | std::string get_distance_to_string(cry_engine::cry_entity_system::i_entity* entity); 37 | cry_engine::math::vector get_bone_position(std::int64_t bone_id); 38 | cry_engine::math::vector get_bone_position(const char* bone_name); 39 | void dump_bones(); 40 | }; 41 | } -------------------------------------------------------------------------------- /hunt_internal/features/esp/esp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void features::esp::draw(cry_engine::cry_entity_system::i_entity* local_entity, cry_engine::cry_entity_system::i_entity* entity, cry_engine::cry_entity_system::i_entity_class* entity_class) { 4 | const auto distance = local_entity->get_distance_to(entity); 5 | const auto distance_string = local_entity->get_distance_to_string(entity); 6 | 7 | const auto entity_name = entity_class->get_entity_name(distance_string); 8 | const auto& entity_position = entity->get_position(); 9 | 10 | // draw name 11 | { 12 | if (distance > std::get<2>(entity_name)) return; 13 | 14 | cry_engine::math::vector screen{}; 15 | if (cry_engine::cry_renderer::world_to_screen(entity_position, screen)) { 16 | const auto text_size = ImGui::CalcTextSize(std::get<0>(entity_name).c_str()); 17 | ImGui::GetOverlayDrawList()->AddText(ImVec2(screen.x - (text_size.x / 2.f), screen.y), std::get<1>(entity_name), std::get<0>(entity_name).c_str()); 18 | } 19 | } 20 | 21 | // draw skeleton 22 | { 23 | for (const auto& bone : hunt::bones::get_array(entity)) { 24 | cry_engine::math::vector first_bone{}, second_bone{}; 25 | 26 | if (cry_engine::cry_renderer::world_to_screen(bone.first, first_bone) && cry_engine::cry_renderer::world_to_screen(bone.second, second_bone)) { 27 | ImGui::GetOverlayDrawList()->AddLine({ first_bone.x, first_bone.y }, { second_bone.x, second_bone.y }, ImGui::ColorConvertFloat4ToU32(ImVec4(1.f, 1.f, 1.f, 1.f))); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /hunt_internal/hooks/present/present.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../hooks.h" 3 | 4 | long __stdcall hooks::present::hook(IDXGISwapChain* swap_chain, const unsigned int sync_interval, const unsigned int flags) { 5 | std::call_once(flag, [&]() { 6 | if (SUCCEEDED(swap_chain->GetDevice(__uuidof(ID3D11Device), reinterpret_cast(&d3d11::device)))) { 7 | d3d11::device->GetImmediateContext(&d3d11::context); 8 | 9 | DXGI_SWAP_CHAIN_DESC swap_chain_desc; 10 | swap_chain->GetDesc(&swap_chain_desc); 11 | hooks::window = swap_chain_desc.OutputWindow; 12 | 13 | ID3D11Texture2D* back_buffer{}; 14 | swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(&back_buffer)); 15 | 16 | if (back_buffer != nullptr) { 17 | d3d11::device->CreateRenderTargetView(back_buffer, nullptr, &d3d11::render_target_view); 18 | } 19 | 20 | back_buffer->Release(); 21 | 22 | wndproc::original = reinterpret_cast(SetWindowLongPtrA(hooks::window, GWLP_WNDPROC, reinterpret_cast(wndproc::hook))); 23 | 24 | menu::initialize(); 25 | } 26 | }); 27 | 28 | ImGui_ImplDX11_NewFrame(); 29 | ImGui_ImplWin32_NewFrame(); 30 | ImGui::NewFrame(); 31 | 32 | menu::render(); 33 | features::run(); 34 | 35 | ImGui::EndFrame(); 36 | ImGui::Render(); 37 | 38 | const auto& io = ImGui::GetIO(); 39 | cry_engine::cry_renderer::screen = { io.DisplaySize.x, io.DisplaySize.y }; 40 | 41 | d3d11::context->OMSetRenderTargets(1, &d3d11::render_target_view, nullptr); 42 | ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); 43 | 44 | return present::original(swap_chain, sync_interval, flags); 45 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/math/vector_2d.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::math { 4 | class vector_2d { 5 | public: 6 | float x, y; 7 | 8 | inline cry_engine::math::vector_2d operator+(const cry_engine::math::vector_2d& a) const { 9 | return { x + a.x, y + a.y }; 10 | } 11 | 12 | inline void operator+=(const cry_engine::math::vector_2d& a) { 13 | x += a.x, y += a.y; 14 | } 15 | 16 | inline cry_engine::math::vector_2d operator-(const cry_engine::math::vector_2d& a) const { 17 | return { x - a.x, y - a.y }; 18 | } 19 | 20 | inline void operator-=(const cry_engine::math::vector_2d& a) { 21 | x -= a.x, y -= a.y; 22 | } 23 | 24 | inline cry_engine::math::vector_2d operator*(const cry_engine::math::vector_2d& a) const { 25 | return { x * a.x, y * a.y }; 26 | } 27 | 28 | inline void operator*=(const cry_engine::math::vector_2d& a) { 29 | x *= a.x, y *= a.y; 30 | } 31 | 32 | inline cry_engine::math::vector_2d operator/(const cry_engine::math::vector_2d& a) const { 33 | return { x / a.x, y / a.y }; 34 | } 35 | 36 | inline void operator/=(const cry_engine::math::vector_2d& a) { 37 | x /= a.x, y /= a.y; 38 | } 39 | 40 | inline cry_engine::math::vector_2d operator+(const float a) const { 41 | return { x + a, y + a }; 42 | } 43 | 44 | inline void operator+=(const float a) { 45 | x += a, y += a; 46 | } 47 | 48 | inline cry_engine::math::vector_2d operator-(const float a) const { 49 | return { x - a, y - a }; 50 | } 51 | 52 | inline void operator-=(const float a) { 53 | x -= a, y -= a; 54 | } 55 | 56 | inline cry_engine::math::vector_2d operator*(const float a) const { 57 | return { x * a, y * a }; 58 | } 59 | 60 | inline void operator*=(const float a) { 61 | x *= a, y *= a; 62 | } 63 | 64 | inline cry_engine::math::vector_2d operator/(const float a) const { 65 | return { x / a, y / a }; 66 | } 67 | 68 | inline void operator/=(const float a) { 69 | x /= a, y /= a; 70 | } 71 | 72 | bool is_zero() const { 73 | if (x == 0.f && y == 0.f) return true; 74 | 75 | return false; 76 | } 77 | }; 78 | } -------------------------------------------------------------------------------- /hunt_internal/utils/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utils.h" 3 | 4 | std::uintptr_t utils::pattern_scan(const std::uintptr_t address, const char* signature, const bool relative) { 5 | static auto pattern_to_byte = [](const char* pattern) { 6 | auto bytes = std::vector{}; 7 | const auto start = const_cast(pattern); 8 | const auto end = const_cast(pattern) + LI_FN(strlen)(pattern); 9 | 10 | for (auto current = start; current < end; ++current) { 11 | if (*current == '?') { 12 | ++current; 13 | bytes.push_back(-1); 14 | } else { 15 | bytes.push_back(LI_FN(strtoul)(current, ¤t, 16)); 16 | } 17 | } 18 | return bytes; 19 | }; 20 | 21 | const auto dos_header = reinterpret_cast(address); 22 | const auto nt_headers = reinterpret_cast(reinterpret_cast(address) + dos_header->e_lfanew); 23 | 24 | const auto size_of_image = nt_headers->OptionalHeader.SizeOfImage; 25 | const auto pattern_bytes = pattern_to_byte(signature); 26 | const auto scan_bytes = reinterpret_cast(address); 27 | 28 | const auto s = pattern_bytes.size(); 29 | const auto d = pattern_bytes.data(); 30 | 31 | for (auto i = 0ul; i < size_of_image - s; ++i) { 32 | bool found = true; 33 | for (auto j = 0ul; j < s; ++j) { 34 | if (scan_bytes[i + j] != d[j] && d[j] != -1) { 35 | found = false; 36 | break; 37 | } 38 | } 39 | 40 | if (found) { 41 | const auto offset = *reinterpret_cast(&scan_bytes[i] + 3); 42 | return relative ? reinterpret_cast(&scan_bytes[i]) + offset + 7 : reinterpret_cast(&scan_bytes[i]); 43 | } 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | bool utils::console::initialize(const std::string& title) { 50 | AllocConsole(); 51 | 52 | freopen_s(reinterpret_cast<_iobuf**>(__acrt_iob_func(0)), _("conin$"), _("r"), __acrt_iob_func(0)); 53 | freopen_s(reinterpret_cast<_iobuf**>(__acrt_iob_func(1)), _("conout$"), _("w"), __acrt_iob_func(1)); 54 | freopen_s(reinterpret_cast<_iobuf**>(__acrt_iob_func(2)), _("conout$"), _("w"), __acrt_iob_func(2)); 55 | 56 | 57 | SetConsoleTitleA(title.c_str()); 58 | 59 | return true; 60 | } 61 | 62 | void utils::console::release() { 63 | fclose(__acrt_iob_func(0)); 64 | fclose(__acrt_iob_func(1)); 65 | fclose(__acrt_iob_func(2)); 66 | 67 | FreeConsole(); 68 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/math/vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::math { 4 | class vector { 5 | public: 6 | float x, y, z; 7 | 8 | inline cry_engine::math::vector operator+(const cry_engine::math::vector& a) const { 9 | return { x + a.x, y + a.y, z + a.z }; 10 | } 11 | 12 | inline void operator+=(const cry_engine::math::vector& a) { 13 | x += a.x, y += a.y, z += a.z; 14 | } 15 | 16 | inline cry_engine::math::vector operator-(const cry_engine::math::vector& a) const { 17 | return { x - a.x, y - a.y, z - a.z }; 18 | } 19 | 20 | inline void operator-=(const cry_engine::math::vector& a) { 21 | x -= a.x, y -= a.y, z -= a.z; 22 | } 23 | 24 | inline cry_engine::math::vector operator*(const cry_engine::math::vector& a) const { 25 | return { x * a.x, y * a.y, z * a.z }; 26 | } 27 | 28 | inline void operator*=(const cry_engine::math::vector& a) { 29 | x *= a.x, y *= a.y, z *= a.z; 30 | } 31 | 32 | inline cry_engine::math::vector operator/(const cry_engine::math::vector& a) const { 33 | return { x / a.x, y / a.y, z / a.z }; 34 | } 35 | 36 | inline void operator/=(const cry_engine::math::vector& a) { 37 | x /= a.x, y /= a.y, z /= a.z; 38 | } 39 | 40 | inline cry_engine::math::vector operator+(const float a) const { 41 | return { x + a, y + a, z + a }; 42 | } 43 | 44 | inline void operator+=(const float a) { 45 | x += a, y += a, z += a; 46 | } 47 | 48 | inline cry_engine::math::vector operator-(const float a) const { 49 | return { x - a, y - a, z - a }; 50 | } 51 | 52 | inline void operator-=(const float a) { 53 | x -= a, y -= a, z -= a; 54 | } 55 | 56 | inline cry_engine::math::vector operator*(const float a) const { 57 | return { x * a, y * a, z * a }; 58 | } 59 | 60 | inline void operator*=(const float a) { 61 | x *= a, y *= a, z *= a; 62 | } 63 | 64 | inline cry_engine::math::vector operator/(const float a) const { 65 | return { x / a, y / a, z / a }; 66 | } 67 | 68 | inline void operator/=(const float a) { 69 | x /= a, y /= a, z /= a; 70 | } 71 | 72 | inline float distance_to(cry_engine::math::vector entity) { 73 | cry_engine::math::vector delta{}; 74 | 75 | delta.x = this->x - entity.x; 76 | delta.y = this->y - entity.y; 77 | delta.z = this->z - entity.z; 78 | 79 | return std::sqrt(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z); 80 | } 81 | }; 82 | } -------------------------------------------------------------------------------- /hunt_internal/cry_engine/math/matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace cry_engine::math { 4 | struct matrix { 5 | float m00, m01, m02, m03; 6 | float m10, m11, m12, m13; 7 | float m20, m21, m22, m23; 8 | 9 | matrix() { 10 | m00 = 1; 11 | m01 = 0; 12 | m02 = 0; 13 | m03 = 0; 14 | m10 = 0; 15 | m11 = 1; 16 | m12 = 0; 17 | m13 = 0; 18 | m20 = 0; 19 | m21 = 0; 20 | m22 = 1; 21 | m23 = 0; 22 | } 23 | 24 | matrix(const cry_engine::math::quat_t& q) { 25 | cry_engine::math::vector v2{}; 26 | v2.x = (q.q.v.x) + (q.q.v.x); 27 | 28 | float xx = 1 - v2.x * q.q.v.x; 29 | float yy = v2.y * q.q.v.y; 30 | float xw = v2.x * q.q.w; 31 | float xy = v2.y * q.q.v.x; 32 | float yz = v2.z * q.q.v.y; 33 | float yw = v2.y * q.q.w; 34 | float xz = v2.z * q.q.v.x; 35 | float zz = v2.z * q.q.v.z; 36 | float zw = v2.z * q.q.w; 37 | 38 | m00 = float(1 - yy - zz); 39 | m01 = float(xy - zw); 40 | m02 = float(xz + yw); 41 | m03 = float(q.t.x); 42 | m10 = float(xy + zw); 43 | m11 = float(xx - zz); 44 | m12 = float(yz - xw); 45 | m13 = float(q.t.y); 46 | m20 = float(xz - yw); 47 | m21 = float(yz + xw); 48 | m22 = float(xx - yy); 49 | m23 = float(q.t.z); 50 | } 51 | 52 | cry_engine::math::vector get_translation() { 53 | cry_engine::math::vector mf{}; 54 | 55 | mf.x = m03; 56 | mf.y = m13; 57 | mf.z = m23; 58 | 59 | return mf; 60 | } 61 | }; 62 | 63 | inline cry_engine::math::matrix operator*(const cry_engine::math::matrix& l, const cry_engine::math::matrix& r) { 64 | cry_engine::math::matrix m; 65 | 66 | m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20; 67 | m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20; 68 | m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20; 69 | m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21; 70 | m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21; 71 | m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21; 72 | m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22; 73 | m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22; 74 | m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22; 75 | m.m03 = l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23 + l.m03; 76 | m.m13 = l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23 + l.m13; 77 | m.m23 = l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23 + l.m23; 78 | 79 | return m; 80 | } 81 | } -------------------------------------------------------------------------------- /hunt_internal/hunt/bones/bones.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | std::vector> hunt::bones::get_array(cry_engine::cry_entity_system::i_entity* entity) { 4 | const auto character = entity->get_character(); 5 | if (!character) return {}; 6 | 7 | std::vector> bone; 8 | 9 | const auto head = entity->get_bone_position(_("head")); 10 | const auto neck = entity->get_bone_position(_("neck")); 11 | const auto pelvis = entity->get_bone_position(_("pelvis")); 12 | 13 | bone.emplace_back(std::make_pair(head, neck)); 14 | bone.emplace_back(std::make_pair(neck, pelvis)); 15 | 16 | // right upper body 17 | { 18 | const auto r_upperarm = entity->get_bone_position(_("r_upperarm")); 19 | const auto r_forearm = entity->get_bone_position(_("r_forearm")); 20 | const auto r_hand = entity->get_bone_position(_("r_hand")); 21 | 22 | bone.emplace_back(std::make_pair(neck, r_upperarm)); 23 | bone.emplace_back(std::make_pair(r_upperarm, r_forearm)); 24 | bone.emplace_back(std::make_pair(r_forearm, r_hand)); 25 | } 26 | 27 | // right lower body 28 | { 29 | const auto r_thigh = entity->get_bone_position(_("r_thigh")); 30 | const auto r_calf = entity->get_bone_position(_("r_calf")); 31 | const auto r_foot = entity->get_bone_position(_("r_foot")); 32 | 33 | bone.emplace_back(std::make_pair(pelvis, r_thigh)); 34 | bone.emplace_back(std::make_pair(r_thigh, r_calf)); 35 | bone.emplace_back(std::make_pair(r_calf, r_foot)); 36 | } 37 | 38 | // left upper body 39 | { 40 | const auto l_upperarm = entity->get_bone_position(_("l_upperarm")); 41 | const auto l_forearm = entity->get_bone_position(_("l_forearm")); 42 | const auto l_hand = entity->get_bone_position(_("l_hand")); 43 | 44 | bone.emplace_back(std::make_pair(neck, l_upperarm)); 45 | bone.emplace_back(std::make_pair(l_upperarm, l_forearm)); 46 | bone.emplace_back(std::make_pair(l_forearm, l_hand)); 47 | } 48 | 49 | // left lower body 50 | { 51 | const auto l_thigh = entity->get_bone_position(_("l_thigh")); 52 | const auto l_calf = entity->get_bone_position(_("l_calf")); 53 | const auto l_foot = entity->get_bone_position(_("l_foot")); 54 | 55 | bone.emplace_back(std::make_pair(pelvis, l_thigh)); 56 | bone.emplace_back(std::make_pair(l_thigh, l_calf)); 57 | bone.emplace_back(std::make_pair(l_calf, l_foot)); 58 | } 59 | 60 | return bone; 61 | } -------------------------------------------------------------------------------- /hunt_internal/menu/menu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hooks/hooks.h" 3 | 4 | bool menu::initialize() { 5 | ImGui::CreateContext(); 6 | ImGui_ImplWin32_Init(hooks::window); 7 | ImGui_ImplDX11_Init(d3d11::device, d3d11::context); 8 | 9 | auto& io = ImGui::GetIO(); 10 | io.IniFilename = nullptr; 11 | io.LogFilename = nullptr; 12 | io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange; 13 | 14 | ImGui::StyleColorsDark(); 15 | 16 | auto& style = ImGui::GetStyle(); 17 | style.ScrollbarSize = 13.0f; 18 | style.WindowTitleAlign = ImVec2{ 0.5f, 0.5f }; 19 | style.WindowRounding = 6.f; 20 | 21 | return true; 22 | } 23 | 24 | void menu::render() { 25 | auto& style = ImGui::GetStyle(); 26 | auto& io = ImGui::GetIO(); 27 | io.MouseDrawCursor = variables::menu::opened; 28 | 29 | static float alpha = 0.f; 30 | 31 | const auto& draw_list = ImGui::GetBackgroundDrawList(); 32 | draw_list->AddRectFilled(ImVec2{ 0.f, 0.f }, io.DisplaySize, ImColor{ 0.f, 0.f, 0.f, alpha }); 33 | 34 | if (!variables::menu::opened) { 35 | alpha = std::fmax(alpha - io.DeltaTime * 3.0f, 0.f); 36 | style.Alpha = std::fmax(style.Alpha - io.DeltaTime * 6.0f, 0.f); 37 | return; 38 | } 39 | 40 | alpha = std::fmin(alpha + io.DeltaTime * 3.0f, 0.5f); 41 | style.Alpha = std::fmin(style.Alpha + io.DeltaTime * 6.0f, 1.f); 42 | 43 | ImGui::SetNextWindowSize(ImVec2{ 500.f, 412.f }, ImGuiCond_Once); 44 | ImGui::Begin(_("papusa barbie"), nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); 45 | 46 | ImVec2 p0 = ImGui::GetCursorScreenPos(); 47 | ImGui::SetCursorScreenPos({ p0.x + 80.f, p0.y }); 48 | 49 | ImGui::BeginGroup(); 50 | { 51 | ImGui::Checkbox(_("hunter"), &variables::entities::hunter); 52 | ImGui::SameLine(); 53 | ImGui::ColorEdit4((_("##hunter_color")), variables::entities::hunter_color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_AlphaBar); 54 | 55 | ImGui::Checkbox(_("zombie"), &variables::entities::zombie); 56 | ImGui::SameLine(); 57 | ImGui::ColorEdit4((_("##zombie_color")), variables::entities::zombie_color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_AlphaBar); 58 | 59 | ImGui::Checkbox(_("boss zombie"), &variables::entities::boss_zombie); 60 | ImGui::SameLine(); 61 | ImGui::ColorEdit4((_("##boss_zombie_color")), variables::entities::boss_zombie_color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_AlphaBar); 62 | 63 | ImGui::Checkbox(_("clue"), &variables::entities::clue); 64 | ImGui::SameLine(); 65 | ImGui::ColorEdit4((_("##clue_color")), variables::entities::clue_color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_AlphaBar); 66 | 67 | ImGui::Checkbox(_("extraction"), &variables::entities::extraction); 68 | ImGui::SameLine(); 69 | ImGui::ColorEdit4((_("##extraction_color")), variables::entities::extraction_color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_AlphaBar); 70 | 71 | ImGui::Spacing(); 72 | ImGui::Spacing(); 73 | 74 | ImGui::Text(_("max distance")); 75 | ImGui::SliderFloat(_("##max_distance"), &variables::entities::max_distance, 0.f, 500.f, _("%.3gm"), 1.f); 76 | } 77 | ImGui::EndGroup(); 78 | 79 | ImGui::End(); 80 | } -------------------------------------------------------------------------------- /hunt_internal/menu/d3d11/d3d11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool d3d11::initialize() { 4 | WNDCLASSEX window_class{}; 5 | window_class.cbSize = sizeof(WNDCLASSEX); 6 | window_class.style = CS_HREDRAW | CS_VREDRAW; 7 | window_class.lpfnWndProc = DefWindowProcA; 8 | window_class.cbClsExtra = 0; 9 | window_class.cbWndExtra = 0; 10 | window_class.hInstance = GetModuleHandleA(nullptr); 11 | window_class.hIcon = nullptr; 12 | window_class.hCursor = nullptr; 13 | window_class.hbrBackground = nullptr; 14 | window_class.lpszMenuName = nullptr; 15 | window_class.lpszClassName = "d3d11"; 16 | window_class.hIconSm = nullptr; 17 | 18 | LI_FN(RegisterClassExA)(&window_class); 19 | 20 | const auto window = LI_FN(CreateWindowExA)(0l, window_class.lpszClassName, "dx11_window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, nullptr, nullptr, window_class.hInstance, nullptr); 21 | 22 | const auto d3d11_lib = LI_FN(GetModuleHandleA)("d3d11.dll"); 23 | if (d3d11_lib == nullptr) { 24 | LI_FN(DestroyWindow)(window); 25 | LI_FN(UnregisterClassA)(window_class.lpszClassName, window_class.hInstance); 26 | 27 | return false; 28 | } 29 | 30 | void* create_device_and_swap_chain = LI_FN(GetProcAddress)(d3d11_lib, "D3D11CreateDeviceAndSwapChain"); 31 | if (create_device_and_swap_chain == nullptr) { 32 | LI_FN(DestroyWindow)(window); 33 | LI_FN(UnregisterClassA)(window_class.lpszClassName, window_class.hInstance); 34 | 35 | return false; 36 | } 37 | 38 | D3D_FEATURE_LEVEL feature_level; 39 | constexpr D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0 }; 40 | 41 | DXGI_RATIONAL refresh_rate{}; 42 | refresh_rate.Numerator = 60; 43 | refresh_rate.Denominator = 1; 44 | 45 | DXGI_MODE_DESC buffer_desc{}; 46 | buffer_desc.Width = 100; 47 | buffer_desc.Height = 100; 48 | buffer_desc.RefreshRate = refresh_rate; 49 | buffer_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 50 | buffer_desc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 51 | buffer_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 52 | 53 | DXGI_SAMPLE_DESC sample_desc{}; 54 | sample_desc.Count = 1; 55 | sample_desc.Quality = 0; 56 | 57 | DXGI_SWAP_CHAIN_DESC swap_chain_desc{}; 58 | swap_chain_desc.BufferDesc = buffer_desc; 59 | swap_chain_desc.SampleDesc = sample_desc; 60 | swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 61 | swap_chain_desc.BufferCount = 1; 62 | swap_chain_desc.OutputWindow = window; 63 | swap_chain_desc.Windowed = 1; 64 | swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 65 | swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; 66 | 67 | IDXGISwapChain* swap_chain; 68 | ID3D11Device* device; 69 | ID3D11DeviceContext* context; 70 | 71 | if (LI_FN(D3D11CreateDeviceAndSwapChain).get()(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, feature_levels, 2, D3D11_SDK_VERSION, &swap_chain_desc, &swap_chain, &device, &feature_level, &context) < 0) { 72 | LI_FN(DestroyWindow)(window); 73 | LI_FN(UnregisterClassA)(window_class.lpszClassName, window_class.hInstance); 74 | return false; 75 | } 76 | 77 | methods_table = static_cast(calloc(205, sizeof(std::uint64_t))); 78 | if (methods_table != nullptr) { 79 | memcpy(methods_table, *reinterpret_cast(swap_chain), 18 * sizeof(std::uint64_t)); 80 | memcpy(methods_table + 18, *reinterpret_cast(device), 43 * sizeof(std::uint64_t)); 81 | memcpy(methods_table + 18 + 43, *reinterpret_cast(context), 144 * sizeof(std::uint64_t)); 82 | } 83 | 84 | swap_chain->Release(); 85 | swap_chain = nullptr; 86 | 87 | device->Release(); 88 | device = nullptr; 89 | 90 | context->Release(); 91 | context = nullptr; 92 | 93 | LI_FN(DestroyWindow)(window); 94 | LI_FN(UnregisterClassA)(window_class.lpszClassName, window_class.hInstance); 95 | 96 | return true; 97 | } 98 | 99 | unsigned long long d3d11::get_present() { 100 | return methods_table[8]; 101 | } -------------------------------------------------------------------------------- /hunt_internal/hunt_internal.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /hunt_internal/cry_engine/cry_entity_system/entity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float cry_engine::cry_entity_system::i_entity::get_distance_to(cry_engine::cry_entity_system::i_entity* entity) { 4 | auto local_position = this->get_position(); 5 | const auto& entity_position = entity->get_position(); 6 | 7 | return local_position.distance_to(entity_position); 8 | } 9 | 10 | std::string cry_engine::cry_entity_system::i_entity::get_distance_to_string(cry_engine::cry_entity_system::i_entity* entity) { 11 | const auto distance = this->get_distance_to(entity); 12 | 13 | std::stringstream ss; 14 | if (distance < 1000.f) { 15 | ss << std::fixed << std::setprecision(0) << distance << _("m"); 16 | 17 | } else { 18 | ss.precision(3); 19 | ss << std::fixed << std::setprecision(0) << (distance / 1000.f) << _("km"); 20 | } 21 | 22 | return ss.str(); 23 | } 24 | 25 | std::tuple cry_engine::cry_entity_system::i_entity_class::get_entity_name(std::string distance) { 26 | const auto get_name = this->get_name(); 27 | std::string name(get_name); 28 | 29 | if (name.contains(_("HunterBasic")) && variables::entities::hunter) { 30 | auto color = ImColor( 31 | variables::entities::hunter_color[0], 32 | variables::entities::hunter_color[1], 33 | variables::entities::hunter_color[2], 34 | variables::entities::hunter_color[3] 35 | ); 36 | 37 | std::string text; 38 | text.append(_("hunter [")).append(distance).append(_("]")); 39 | 40 | return { text, color, variables::entities::max_distance }; 41 | } 42 | 43 | if (name.contains(_("grunt_base")) && variables::entities::zombie) { 44 | auto color = ImColor( 45 | variables::entities::zombie_color[0], 46 | variables::entities::zombie_color[1], 47 | variables::entities::zombie_color[2], 48 | variables::entities::zombie_color[3] 49 | ); 50 | 51 | std::string text; 52 | text.append(_("zombie [")).append(distance).append(_("]")); 53 | 54 | return { text, color, variables::entities::max_distance }; 55 | } 56 | 57 | if (name.contains(_("target_butcher")) && variables::entities::boss_zombie) { 58 | auto color = ImColor( 59 | variables::entities::boss_zombie_color[0], 60 | variables::entities::boss_zombie_color[1], 61 | variables::entities::boss_zombie_color[2], 62 | variables::entities::boss_zombie_color[3] 63 | ); 64 | 65 | std::string text; 66 | text.append(_("butcher [")).append(distance).append(_("]")); 67 | 68 | return { text, color, variables::entities::max_distance }; 69 | } 70 | 71 | 72 | if (name.contains(_("Clue_Base")) && variables::entities::clue) { 73 | auto color = ImColor( 74 | variables::entities::clue_color[0], 75 | variables::entities::clue_color[1], 76 | variables::entities::clue_color[2], 77 | variables::entities::clue_color[3] 78 | ); 79 | 80 | std::string text; 81 | text.append(_("clue [")).append(distance).append(_("]")); 82 | 83 | return { text, color, variables::entities::max_distance }; 84 | } 85 | 86 | if (name.contains(_("ExtractionPoint")) && variables::entities::extraction) { 87 | auto color = ImColor( 88 | variables::entities::extraction_color[0], 89 | variables::entities::extraction_color[1], 90 | variables::entities::extraction_color[2], 91 | variables::entities::extraction_color[3] 92 | ); 93 | 94 | std::string text; 95 | text.append(_("extraction [")).append(distance).append(_("]")); 96 | 97 | return { text, color, variables::entities::max_distance }; 98 | } 99 | 100 | return { "", { 0.f, 0.f, 0.f, 0.f}, 0.f }; 101 | } 102 | 103 | cry_engine::math::vector cry_engine::cry_entity_system::i_entity::get_bone_position(std::int64_t bone_id) { 104 | const auto character = this->get_character(); 105 | if (!character) return { 0.f, 0.f, 0.f }; 106 | 107 | const auto skeleton_pose = character->get_skeleton_pose(); 108 | if (!skeleton_pose) return { 0.f, 0.f, 0.f }; 109 | 110 | return (this->get_world_tm() * skeleton_pose->get_abs_joint_by_id(bone_id)).get_translation(); 111 | } 112 | 113 | cry_engine::math::vector cry_engine::cry_entity_system::i_entity::get_bone_position(const char* bone_name) { 114 | std::int64_t bone = this->get_character()->get_default_skeleton().get_joint_id_by_name(bone_name); 115 | return get_bone_position(bone); 116 | } 117 | 118 | void cry_engine::cry_entity_system::i_entity::dump_bones() { 119 | const auto character = this->get_character(0); 120 | if (!character) return; 121 | 122 | const auto skeleton_pose = character->get_skeleton_pose(); 123 | if (!skeleton_pose) return; 124 | 125 | auto& skeleton = character->get_default_skeleton(); 126 | 127 | for (auto i = 0; i < skeleton.get_joint_count(); i++) { 128 | std::string bone_name = skeleton.get_joint_name_by_id(i); 129 | std::ranges::transform(bone_name.begin(), bone_name.end(), bone_name.begin(), ::tolower); 130 | 131 | std::cout << bone_name << " = " << i << "," << std::endl; 132 | } 133 | } -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/imgui/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/behaviors. 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', this is why this is not the default). 38 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) 39 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. 40 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. 41 | //#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(). 42 | 43 | //---- Include imgui_user.h at the end of imgui.h as a convenience 44 | //#define IMGUI_INCLUDE_IMGUI_USER_H 45 | 46 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 47 | //#define IMGUI_USE_BGRA_PACKED_COLOR 48 | 49 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 50 | // By default the embedded implementations are declared static and not available outside of imgui cpp files. 51 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 52 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 53 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 54 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 55 | 56 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 57 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 58 | /* 59 | #define IM_VEC2_CLASS_EXTRA \ 60 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 61 | operator MyVec2() const { return MyVec2(x,y); } 62 | 63 | #define IM_VEC4_CLASS_EXTRA \ 64 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 65 | operator MyVec4() const { return MyVec4(x,y,z,w); } 66 | */ 67 | 68 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. 69 | // Your renderer back-end will need to support it (most example renderer back-ends support both 16/32-bit indices). 70 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. 71 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 72 | //#define ImDrawIdx unsigned int 73 | 74 | //---- Override ImDrawCallback signature (will need to modify renderer back-ends accordingly) 75 | //struct ImDrawList; 76 | //struct ImDrawCmd; 77 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 78 | //#define ImDrawCallback MyImDrawCallback 79 | 80 | //---- Debug Tools: Macro to break in Debugger 81 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) 82 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 83 | //#define IM_DEBUG_BREAK __debugbreak() 84 | 85 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(), 86 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.) 87 | // This adds a small runtime cost which is why it is not enabled by default. 88 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX 89 | 90 | //---- Debug Tools: Enable slower asserts 91 | //#define IMGUI_DEBUG_PARANOID 92 | 93 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 94 | /* 95 | namespace ImGui 96 | { 97 | void MyFunction(const char* name, const MyMatrix44& v); 98 | } 99 | */ -------------------------------------------------------------------------------- /hunt_internal/hunt_internal.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Release 6 | x64 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | NotUsing 20 | 21 | 22 | 23 | 24 | 25 | NotUsing 26 | 27 | 28 | NotUsing 29 | 30 | 31 | NotUsing 32 | 33 | 34 | NotUsing 35 | 36 | 37 | NotUsing 38 | 39 | 40 | NotUsing 41 | 42 | 43 | NotUsing 44 | 45 | 46 | NotUsing 47 | 48 | 49 | NotUsing 50 | 51 | 52 | NotUsing 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 16.0 103 | Win32Proj 104 | {b479c0f2-2a5a-400a-90be-d2a1f8e9341b} 105 | ue4_base 106 | 10.0 107 | hunt_internal 108 | 109 | 110 | 111 | DynamicLibrary 112 | false 113 | v143 114 | true 115 | MultiByte 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | false 128 | $(SolutionDir)bin\ 129 | $(SolutionDir)bin\intermediates\ 130 | $(SolutionDir)$(ProjectName)\;$(IncludePath) 131 | 132 | 133 | 134 | TurnOffAllWarnings 135 | true 136 | true 137 | false 138 | NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 139 | true 140 | stdcpplatest 141 | true 142 | MinSpace 143 | OnlyExplicitInline 144 | Size 145 | true 146 | true 147 | MultiThreaded 148 | false 149 | false 150 | Create 151 | includes.h 152 | 153 | 154 | NoIPO 155 | false 156 | 157 | 158 | Console 159 | true 160 | true 161 | true 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/imgui/shaders.h: -------------------------------------------------------------------------------- 1 | static unsigned char pixel_shader[660] = { 2 | 0x44, 0x58, 0x42, 0x43, 0x9E, 0xCE, 0x85, 0x72, 0xA7, 0x97, 0x52, 0xB4, 3 | 0x6D, 0xC4, 0x28, 0xFA, 0x10, 0xC0, 0xD2, 0xC1, 0x01, 0x00, 0x00, 0x00, 4 | 0x94, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 5 | 0xD4, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x7C, 0x01, 0x00, 0x00, 6 | 0x18, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x98, 0x00, 0x00, 0x00, 7 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 8 | 0x1C, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0x00, 9 | 0x6E, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 10 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 11 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 12 | 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 13 | 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 14 | 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x73, 0x61, 0x6D, 0x70, 15 | 0x6C, 0x65, 0x72, 0x30, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 16 | 0x30, 0x00, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 17 | 0x28, 0x52, 0x29, 0x20, 0x48, 0x4C, 0x53, 0x4C, 0x20, 0x53, 0x68, 0x61, 18 | 0x64, 0x65, 0x72, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x69, 0x6C, 0x65, 0x72, 19 | 0x20, 0x31, 0x30, 0x2E, 0x31, 0x00, 0xAB, 0xAB, 0x49, 0x53, 0x47, 0x4E, 20 | 0x6C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 21 | 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 22 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 23 | 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 | 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 25 | 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 26 | 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 27 | 0x53, 0x56, 0x5F, 0x50, 0x4F, 0x53, 0x49, 0x54, 0x49, 0x4F, 0x4E, 0x00, 28 | 0x43, 0x4F, 0x4C, 0x4F, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4F, 0x4F, 29 | 0x52, 0x44, 0x00, 0xAB, 0x4F, 0x53, 0x47, 0x4E, 0x2C, 0x00, 0x00, 0x00, 30 | 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 31 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 32 | 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5F, 0x54, 33 | 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0xAB, 0xAB, 0x53, 0x48, 0x44, 0x52, 34 | 0x94, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 35 | 0x5A, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 36 | 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 37 | 0x55, 0x55, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0xF2, 0x10, 0x10, 0x00, 38 | 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 39 | 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xF2, 0x20, 0x10, 0x00, 40 | 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 41 | 0x45, 0x00, 0x00, 0x09, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 42 | 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x7E, 0x10, 0x00, 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 44 | 0x38, 0x00, 0x00, 0x07, 0xF2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1E, 0x10, 0x00, 46 | 0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 47 | 0x74, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 48 | 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 57 | }; 58 | 59 | static unsigned char vertex_shader[876] = { 60 | 0x44, 0x58, 0x42, 0x43, 0x7A, 0x54, 0x84, 0x96, 0xDF, 0xD1, 0x9E, 0x21, 61 | 0xFD, 0x85, 0x86, 0x3D, 0x28, 0xD1, 0x03, 0xAE, 0x01, 0x00, 0x00, 0x00, 62 | 0x6C, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 63 | 0x04, 0x01, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0xE8, 0x01, 0x00, 0x00, 64 | 0xF0, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xC8, 0x00, 0x00, 0x00, 65 | 0x01, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 66 | 0x1C, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFE, 0xFF, 0x00, 0x01, 0x00, 0x00, 67 | 0xA0, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 70 | 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 71 | 0x00, 0xAB, 0xAB, 0xAB, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 72 | 0x64, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 | 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 | 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 75 | 0x00, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x69, 76 | 0x6F, 0x6E, 0x4D, 0x61, 0x74, 0x72, 0x69, 0x78, 0x00, 0xAB, 0xAB, 0xAB, 77 | 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 78 | 0x00, 0x00, 0x00, 0x00, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 79 | 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4C, 0x53, 0x4C, 0x20, 0x53, 80 | 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x69, 0x6C, 81 | 0x65, 0x72, 0x20, 0x31, 0x30, 0x2E, 0x31, 0x00, 0x49, 0x53, 0x47, 0x4E, 82 | 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 83 | 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 84 | 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 85 | 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 | 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 87 | 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 88 | 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 89 | 0x50, 0x4F, 0x53, 0x49, 0x54, 0x49, 0x4F, 0x4E, 0x00, 0x43, 0x4F, 0x4C, 90 | 0x4F, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4F, 0x4F, 0x52, 0x44, 0x00, 91 | 0x4F, 0x53, 0x47, 0x4E, 0x6C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 92 | 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 93 | 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 | 0x0F, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 95 | 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 96 | 0x0F, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 97 | 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 98 | 0x03, 0x0C, 0x00, 0x00, 0x53, 0x56, 0x5F, 0x50, 0x4F, 0x53, 0x49, 0x54, 99 | 0x49, 0x4F, 0x4E, 0x00, 0x43, 0x4F, 0x4C, 0x4F, 0x52, 0x00, 0x54, 0x45, 100 | 0x58, 0x43, 0x4F, 0x4F, 0x52, 0x44, 0x00, 0xAB, 0x53, 0x48, 0x44, 0x52, 101 | 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 102 | 0x59, 0x00, 0x00, 0x04, 0x46, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 103 | 0x04, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 104 | 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x03, 0xF2, 0x10, 0x10, 0x00, 105 | 0x01, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 106 | 0x02, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, 0xF2, 0x20, 0x10, 0x00, 107 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 108 | 0xF2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 109 | 0x32, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 110 | 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00, 111 | 0x00, 0x00, 0x00, 0x00, 0x56, 0x15, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 112 | 0x46, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 113 | 0x32, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 114 | 0x46, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 115 | 0x06, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 116 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xF2, 0x20, 0x10, 0x00, 117 | 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 118 | 0x46, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 119 | 0x36, 0x00, 0x00, 0x05, 0xF2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 120 | 0x46, 0x1E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 121 | 0x32, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 122 | 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 123 | 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 124 | 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 125 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 126 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 128 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 129 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 130 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 131 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 132 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 133 | }; 134 | -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/xor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2021 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 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__) 21 | #include 22 | #elif defined(_M_X64) || defined(__amd64__) || defined(_M_IX86) || defined(__i386__) 23 | #include 24 | #else 25 | #error Unsupported platform 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define xorstr(str) ::jm::xor_string([]() { return str; }, std::integral_constant{}, std::make_index_sequence<::jm::detail::_buffer_size()>{}) 34 | #define _(str) xorstr(str).crypt_get() 35 | 36 | #ifdef _MSC_VER 37 | #define XORSTR_FORCEINLINE __forceinline 38 | #else 39 | #define XORSTR_FORCEINLINE __attribute__((always_inline)) inline 40 | #endif 41 | 42 | namespace jm { 43 | 44 | namespace detail { 45 | 46 | template 47 | XORSTR_FORCEINLINE constexpr std::size_t _buffer_size() 48 | { 49 | return ((Size / 16) + (Size % 16 != 0)) * 2; 50 | } 51 | 52 | template 53 | XORSTR_FORCEINLINE constexpr std::uint32_t key4() noexcept 54 | { 55 | std::uint32_t value = Seed; 56 | for (char c : __TIME__) 57 | value = static_cast((value ^ c) * 16777619ull); 58 | return value; 59 | } 60 | 61 | template 62 | XORSTR_FORCEINLINE constexpr std::uint64_t key8() 63 | { 64 | constexpr auto first_part = key4<2166136261 + S>(); 65 | constexpr auto second_part = key4(); 66 | return (static_cast(first_part) << 32) | second_part; 67 | } 68 | 69 | // loads up to 8 characters of string into uint64 and xors it with the key 70 | template 71 | XORSTR_FORCEINLINE constexpr std::uint64_t 72 | load_xored_str8(std::uint64_t key, std::size_t idx, const CharT* str) noexcept 73 | { 74 | using cast_type = typename std::make_unsigned::type; 75 | constexpr auto value_size = sizeof(CharT); 76 | constexpr auto idx_offset = 8 / value_size; 77 | 78 | std::uint64_t value = key; 79 | for (std::size_t i = 0; i < idx_offset && i + idx * idx_offset < N; ++i) 80 | value ^= 81 | (std::uint64_t{ static_cast(str[i + idx * idx_offset]) } 82 | << ((i % idx_offset) * 8 * value_size)); 83 | 84 | return value; 85 | } 86 | 87 | // forces compiler to use registers instead of stuffing constants in rdata 88 | XORSTR_FORCEINLINE std::uint64_t load_from_reg(std::uint64_t value) noexcept 89 | { 90 | #if defined(__clang__) || defined(__GNUC__) 91 | asm("" : "=r"(value) : "0"(value) : ); 92 | return value; 93 | #else 94 | volatile std::uint64_t reg = value; 95 | return reg; 96 | #endif 97 | } 98 | 99 | } // namespace detail 100 | 101 | template 102 | class xor_string; 103 | 104 | template 105 | class xor_string, std::index_sequence> { 106 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS 107 | constexpr static inline std::uint64_t alignment = ((Size > 16) ? 32 : 16); 108 | #else 109 | constexpr static inline std::uint64_t alignment = 16; 110 | #endif 111 | 112 | alignas(alignment) std::uint64_t _storage[sizeof...(Keys)]; 113 | 114 | public: 115 | using value_type = CharT; 116 | using size_type = std::size_t; 117 | using pointer = CharT*; 118 | using const_pointer = const CharT*; 119 | 120 | template 121 | XORSTR_FORCEINLINE xor_string(L l, std::integral_constant, std::index_sequence) noexcept 122 | : _storage{ ::jm::detail::load_from_reg((std::integral_constant(Keys, Indices, l())>::value))... } 123 | {} 124 | 125 | XORSTR_FORCEINLINE constexpr size_type size() const noexcept 126 | { 127 | return Size - 1; 128 | } 129 | 130 | XORSTR_FORCEINLINE void crypt() noexcept 131 | { 132 | // everything is inlined by hand because a certain compiler with a certain linker is _very_ slow 133 | #if defined(__clang__) 134 | alignas(alignment) 135 | std::uint64_t arr[]{ ::jm::detail::load_from_reg(Keys)... }; 136 | std::uint64_t* keys = 137 | (std::uint64_t*)::jm::detail::load_from_reg((std::uint64_t)arr); 138 | #else 139 | alignas(alignment) std::uint64_t keys[]{ ::jm::detail::load_from_reg(Keys)... }; 140 | #endif 141 | 142 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__) 143 | #if defined(__clang__) 144 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : __builtin_neon_vst1q_v( 145 | reinterpret_cast(_storage) + Indices * 2, 146 | veorq_u64(__builtin_neon_vld1q_v(reinterpret_cast(_storage) + Indices * 2, 51), 147 | __builtin_neon_vld1q_v(reinterpret_cast(keys) + Indices * 2, 51)), 148 | 51)), ...); 149 | #else // GCC, MSVC 150 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : vst1q_u64( 151 | reinterpret_cast(_storage) + Indices * 2, 152 | veorq_u64(vld1q_u64(reinterpret_cast(_storage) + Indices * 2), 153 | vld1q_u64(reinterpret_cast(keys) + Indices * 2)))), ...); 154 | #endif 155 | #elif !defined(JM_XORSTR_DISABLE_AVX_INTRINSICS) 156 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256( 157 | reinterpret_cast<__m256i*>(_storage) + Indices, 158 | _mm256_xor_si256( 159 | _mm256_load_si256(reinterpret_cast(_storage) + Indices), 160 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...); 161 | 162 | if constexpr (sizeof(_storage) % 32 != 0) 163 | _mm_store_si128( 164 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2), 165 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)), 166 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2)))); 167 | #else 168 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128( 169 | reinterpret_cast<__m128i*>(_storage) + Indices, 170 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices), 171 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...); 172 | #endif 173 | } 174 | 175 | XORSTR_FORCEINLINE const_pointer get() const noexcept 176 | { 177 | return reinterpret_cast(_storage); 178 | } 179 | 180 | XORSTR_FORCEINLINE pointer get() noexcept 181 | { 182 | return reinterpret_cast(_storage); 183 | } 184 | 185 | XORSTR_FORCEINLINE pointer crypt_get() noexcept 186 | { 187 | // crypt() is inlined by hand because a certain compiler with a certain linker is _very_ slow 188 | #if defined(__clang__) 189 | alignas(alignment) 190 | std::uint64_t arr[]{ ::jm::detail::load_from_reg(Keys)... }; 191 | std::uint64_t* keys = 192 | (std::uint64_t*)::jm::detail::load_from_reg((std::uint64_t)arr); 193 | #else 194 | alignas(alignment) std::uint64_t keys[]{ ::jm::detail::load_from_reg(Keys)... }; 195 | #endif 196 | 197 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__) 198 | #if defined(__clang__) 199 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : __builtin_neon_vst1q_v( 200 | reinterpret_cast(_storage) + Indices * 2, 201 | veorq_u64(__builtin_neon_vld1q_v(reinterpret_cast(_storage) + Indices * 2, 51), 202 | __builtin_neon_vld1q_v(reinterpret_cast(keys) + Indices * 2, 51)), 203 | 51)), ...); 204 | #else // GCC, MSVC 205 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : vst1q_u64( 206 | reinterpret_cast(_storage) + Indices * 2, 207 | veorq_u64(vld1q_u64(reinterpret_cast(_storage) + Indices * 2), 208 | vld1q_u64(reinterpret_cast(keys) + Indices * 2)))), ...); 209 | #endif 210 | #elif !defined(JM_XORSTR_DISABLE_AVX_INTRINSICS) 211 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256( 212 | reinterpret_cast<__m256i*>(_storage) + Indices, 213 | _mm256_xor_si256( 214 | _mm256_load_si256(reinterpret_cast(_storage) + Indices), 215 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...); 216 | 217 | if constexpr (sizeof(_storage) % 32 != 0) 218 | _mm_store_si128( 219 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2), 220 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)), 221 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2)))); 222 | #else 223 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128( 224 | reinterpret_cast<__m128i*>(_storage) + Indices, 225 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices), 226 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...); 227 | #endif 228 | 229 | return (pointer)(_storage); 230 | } 231 | }; 232 | 233 | template 234 | xor_string(L l, std::integral_constant, std::index_sequence)->xor_string< 235 | std::remove_const_t>, 236 | Size, 237 | std::integer_sequence()...>, 238 | std::index_sequence>; 239 | 240 | } // namespace jm 241 | 242 | #endif // include guard 243 | -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/imgui/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 | 18 | // CHANGELOG 19 | // (minor and older changes stripped away, please see git history for details) 20 | // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. 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 | } else 109 | { 110 | // Show OS mouse cursor 111 | LPTSTR win32_cursor = IDC_ARROW; 112 | switch (imgui_cursor) 113 | { 114 | case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; 115 | case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; 116 | case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; 117 | case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; 118 | case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; 119 | case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; 120 | case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; 121 | case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; 122 | case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; 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 | void ImGui_ImplWin32_NewFrame() 151 | { 152 | ImGuiIO& io = ImGui::GetIO(); 153 | 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()."); 154 | 155 | // Setup display size (every frame to accommodate for window resizing) 156 | RECT rect; 157 | ::GetClientRect(g_hWnd, &rect); 158 | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); 159 | 160 | // Setup time step 161 | INT64 current_time; 162 | ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); 163 | io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; 164 | g_Time = current_time; 165 | 166 | // Read keyboard modifiers inputs 167 | io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0; 168 | io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0; 169 | io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0; 170 | io.KeySuper = false; 171 | // io.KeysDown[], io.MousePos, io.MouseDown[], io.MouseWheel: filled by the WndProc handler below. 172 | 173 | // Update OS mouse position 174 | ImGui_ImplWin32_UpdateMousePos(); 175 | 176 | // Update OS mouse cursor with the cursor requested by imgui 177 | ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); 178 | if (g_LastMouseCursor != mouse_cursor) 179 | { 180 | g_LastMouseCursor = mouse_cursor; 181 | ImGui_ImplWin32_UpdateMouseCursor(); 182 | } 183 | } 184 | 185 | // Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. 186 | #ifndef WM_MOUSEHWHEEL 187 | #define WM_MOUSEHWHEEL 0x020E 188 | #endif 189 | #ifndef DBT_DEVNODES_CHANGED 190 | #define DBT_DEVNODES_CHANGED 0x0007 191 | #endif 192 | 193 | // Process Win32 mouse/keyboard inputs. 194 | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. 195 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. 196 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. 197 | // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. 198 | // 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. 199 | // 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. 200 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 201 | { 202 | if (ImGui::GetCurrentContext() == NULL) 203 | return 0; 204 | 205 | ImGuiIO& io = ImGui::GetIO(); 206 | switch (msg) 207 | { 208 | case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: 209 | case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: 210 | case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: 211 | { 212 | int button = 0; 213 | if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; 214 | if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; 215 | if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; 216 | if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) 217 | ::SetCapture(hwnd); 218 | io.MouseDown[button] = true; 219 | return 1; 220 | } 221 | case WM_LBUTTONUP: 222 | case WM_RBUTTONUP: 223 | case WM_MBUTTONUP: 224 | { 225 | int button = 0; 226 | if (msg == WM_LBUTTONUP) button = 0; 227 | if (msg == WM_RBUTTONUP) button = 1; 228 | if (msg == WM_MBUTTONUP) button = 2; 229 | io.MouseDown[button] = false; 230 | if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) 231 | ::ReleaseCapture(); 232 | return 1; 233 | } 234 | case WM_MOUSEWHEEL: 235 | io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; 236 | return 1; 237 | case WM_MOUSEHWHEEL: 238 | io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; 239 | return 1; 240 | case WM_MOUSEMOVE: 241 | io.MousePos.x = (signed short)(lParam); 242 | io.MousePos.y = (signed short)(lParam >> 16); 243 | return 1; 244 | case WM_KEYDOWN: 245 | case WM_SYSKEYDOWN: 246 | if (wParam < 256) 247 | io.KeysDown[wParam] = 1; 248 | return 1; 249 | case WM_KEYUP: 250 | case WM_SYSKEYUP: 251 | if (wParam < 256) 252 | io.KeysDown[wParam] = 0; 253 | return 1; 254 | case WM_CHAR: 255 | if (wParam > 0 && wParam < 0x10000) 256 | io.AddInputCharacter((unsigned short)wParam); 257 | return 1; 258 | case WM_SETCURSOR: 259 | if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) 260 | return 1; 261 | return 1; 262 | case WM_DEVICECHANGE: 263 | if ((UINT)wParam == DBT_DEVNODES_CHANGED) 264 | g_WantUpdateHasGamepad = true; 265 | return 1; 266 | } 267 | return 0; 268 | } -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/imgui/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 | */ -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/imgui/imgui_impl_dx11.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer for DirectX11 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 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit 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-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). 15 | // 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. 16 | // 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 17 | // 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 18 | // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). 19 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 20 | // 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. 21 | // 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions. 22 | // 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example. 23 | // 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 24 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. 25 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 26 | // 2016-05-07: DirectX11: Disabling depth-write. 27 | 28 | #include "imgui.h" 29 | #include "imgui_impl_dx11.h" 30 | 31 | // DirectX 32 | #include 33 | #include 34 | 35 | #include "shaders.h" 36 | 37 | // DirectX data 38 | static ID3D11Device* g_pd3dDevice = NULL; 39 | static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; 40 | static IDXGIFactory* g_pFactory = NULL; 41 | static ID3D11Buffer* g_pVB = NULL; 42 | static ID3D11Buffer* g_pIB = NULL; 43 | static ID3D10Blob* g_pVertexShaderBlob = NULL; 44 | static ID3D11VertexShader* g_pVertexShader = NULL; 45 | static ID3D11InputLayout* g_pInputLayout = NULL; 46 | static ID3D11Buffer* g_pVertexConstantBuffer = NULL; 47 | static ID3D10Blob* g_pPixelShaderBlob = NULL; 48 | static ID3D11PixelShader* g_pPixelShader = NULL; 49 | static ID3D11SamplerState* g_pFontSampler = NULL; 50 | static ID3D11ShaderResourceView* g_pFontTextureView = NULL; 51 | static ID3D11RasterizerState* g_pRasterizerState = NULL; 52 | static ID3D11BlendState* g_pBlendState = NULL; 53 | static ID3D11DepthStencilState* g_pDepthStencilState = NULL; 54 | static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; 55 | 56 | struct VERTEX_CONSTANT_BUFFER 57 | { 58 | float mvp[4][4]; 59 | }; 60 | 61 | static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) 62 | { 63 | // Setup viewport 64 | D3D11_VIEWPORT vp; 65 | memset(&vp, 0, sizeof(D3D11_VIEWPORT)); 66 | vp.Width = draw_data->DisplaySize.x; 67 | vp.Height = draw_data->DisplaySize.y; 68 | vp.MinDepth = 0.0f; 69 | vp.MaxDepth = 1.0f; 70 | vp.TopLeftX = vp.TopLeftY = 0; 71 | ctx->RSSetViewports(1, &vp); 72 | 73 | // Setup shader and vertex buffers 74 | unsigned int stride = sizeof(ImDrawVert); 75 | unsigned int offset = 0; 76 | ctx->IASetInputLayout(g_pInputLayout); 77 | ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); 78 | ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); 79 | ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 80 | ctx->VSSetShader(g_pVertexShader, NULL, 0); 81 | ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); 82 | ctx->PSSetShader(g_pPixelShader, NULL, 0); 83 | ctx->PSSetSamplers(0, 1, &g_pFontSampler); 84 | ctx->GSSetShader(NULL, NULL, 0); 85 | ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. 86 | ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. 87 | ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. 88 | 89 | // Setup blend state 90 | const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; 91 | ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); 92 | ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); 93 | ctx->RSSetState(g_pRasterizerState); 94 | } 95 | 96 | // Render function 97 | // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) 98 | void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) 99 | { 100 | // Avoid rendering when minimized 101 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) 102 | return; 103 | 104 | ID3D11DeviceContext* ctx = g_pd3dDeviceContext; 105 | 106 | // Create and grow vertex/index buffers if needed 107 | if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) 108 | { 109 | if (g_pVB) { 110 | g_pVB->Release(); g_pVB = NULL; 111 | } 112 | g_VertexBufferSize = draw_data->TotalVtxCount + 5000; 113 | D3D11_BUFFER_DESC desc; 114 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 115 | desc.Usage = D3D11_USAGE_DYNAMIC; 116 | desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); 117 | desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 118 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 119 | desc.MiscFlags = 0; 120 | if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) 121 | return; 122 | } 123 | if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) 124 | { 125 | if (g_pIB) { 126 | g_pIB->Release(); g_pIB = NULL; 127 | } 128 | g_IndexBufferSize = draw_data->TotalIdxCount + 10000; 129 | D3D11_BUFFER_DESC desc; 130 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 131 | desc.Usage = D3D11_USAGE_DYNAMIC; 132 | desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); 133 | desc.BindFlags = D3D11_BIND_INDEX_BUFFER; 134 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 135 | if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) 136 | return; 137 | } 138 | 139 | // Upload vertex/index data into a single contiguous GPU buffer 140 | D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; 141 | if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) 142 | return; 143 | if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) 144 | return; 145 | ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; 146 | ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; 147 | for (int n = 0; n < draw_data->CmdListsCount; n++) 148 | { 149 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 150 | memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); 151 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 152 | vtx_dst += cmd_list->VtxBuffer.Size; 153 | idx_dst += cmd_list->IdxBuffer.Size; 154 | } 155 | ctx->Unmap(g_pVB, 0); 156 | ctx->Unmap(g_pIB, 0); 157 | 158 | // Setup orthographic projection matrix into our constant buffer 159 | // 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. 160 | { 161 | D3D11_MAPPED_SUBRESOURCE mapped_resource; 162 | if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) 163 | return; 164 | VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; 165 | float L = draw_data->DisplayPos.x; 166 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; 167 | float T = draw_data->DisplayPos.y; 168 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; 169 | float mvp[4][4] = 170 | { 171 | { 2.0f / (R - L), 0.0f, 0.0f, 0.0f }, 172 | { 0.0f, 2.0f / (T - B), 0.0f, 0.0f }, 173 | { 0.0f, 0.0f, 0.5f, 0.0f }, 174 | { (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f }, 175 | }; 176 | memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); 177 | ctx->Unmap(g_pVertexConstantBuffer, 0); 178 | } 179 | 180 | // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) 181 | struct BACKUP_DX11_STATE 182 | { 183 | UINT ScissorRectsCount, ViewportsCount; 184 | D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 185 | D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 186 | ID3D11RasterizerState* RS; 187 | ID3D11BlendState* BlendState; 188 | FLOAT BlendFactor[4]; 189 | UINT SampleMask; 190 | UINT StencilRef; 191 | ID3D11DepthStencilState* DepthStencilState; 192 | ID3D11ShaderResourceView* PSShaderResource; 193 | ID3D11SamplerState* PSSampler; 194 | ID3D11PixelShader* PS; 195 | ID3D11VertexShader* VS; 196 | ID3D11GeometryShader* GS; 197 | UINT PSInstancesCount, VSInstancesCount, GSInstancesCount; 198 | ID3D11ClassInstance* PSInstances[256], * VSInstances[256], * GSInstances[256]; // 256 is max according to PSSetShader documentation 199 | D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; 200 | ID3D11Buffer* IndexBuffer, * VertexBuffer, * VSConstantBuffer; 201 | UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; 202 | DXGI_FORMAT IndexBufferFormat; 203 | ID3D11InputLayout* InputLayout; 204 | }; 205 | BACKUP_DX11_STATE old; 206 | old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; 207 | ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); 208 | ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); 209 | ctx->RSGetState(&old.RS); 210 | ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); 211 | ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); 212 | ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); 213 | ctx->PSGetSamplers(0, 1, &old.PSSampler); 214 | old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256; 215 | ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); 216 | ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); 217 | ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); 218 | ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount); 219 | 220 | ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); 221 | ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); 222 | ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); 223 | ctx->IAGetInputLayout(&old.InputLayout); 224 | 225 | // Setup desired DX state 226 | ImGui_ImplDX11_SetupRenderState(draw_data, ctx); 227 | 228 | // Render command lists 229 | // (Because we merged all buffers into a single one, we maintain our own offset into them) 230 | int global_idx_offset = 0; 231 | int global_vtx_offset = 0; 232 | ImVec2 clip_off = draw_data->DisplayPos; 233 | for (int n = 0; n < draw_data->CmdListsCount; n++) 234 | { 235 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 236 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 237 | { 238 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 239 | if (pcmd->UserCallback != NULL) 240 | { 241 | // User callback, registered via ImDrawList::AddCallback() 242 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 243 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 244 | ImGui_ImplDX11_SetupRenderState(draw_data, ctx); 245 | else 246 | pcmd->UserCallback(cmd_list, pcmd); 247 | } else 248 | { 249 | // Apply scissor/clipping rectangle 250 | const D3D11_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) }; 251 | ctx->RSSetScissorRects(1, &r); 252 | 253 | // Bind texture, Draw 254 | ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId; 255 | ctx->PSSetShaderResources(0, 1, &texture_srv); 256 | ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); 257 | } 258 | } 259 | global_idx_offset += cmd_list->IdxBuffer.Size; 260 | global_vtx_offset += cmd_list->VtxBuffer.Size; 261 | } 262 | 263 | // Restore modified DX state 264 | ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); 265 | ctx->RSSetViewports(old.ViewportsCount, old.Viewports); 266 | ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); 267 | ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); 268 | ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); 269 | ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); 270 | ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); 271 | ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); 272 | for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); 273 | ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); 274 | ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); 275 | ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release(); 276 | for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); 277 | ctx->IASetPrimitiveTopology(old.PrimitiveTopology); 278 | ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); 279 | ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); 280 | ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); 281 | } 282 | 283 | static void ImGui_ImplDX11_CreateFontsTexture() 284 | { 285 | // Build texture atlas 286 | ImGuiIO& io = ImGui::GetIO(); 287 | unsigned char* pixels; 288 | int width, height; 289 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 290 | 291 | // Upload texture to graphics system 292 | { 293 | D3D11_TEXTURE2D_DESC desc; 294 | ZeroMemory(&desc, sizeof(desc)); 295 | desc.Width = width; 296 | desc.Height = height; 297 | desc.MipLevels = 1; 298 | desc.ArraySize = 1; 299 | desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 300 | desc.SampleDesc.Count = 1; 301 | desc.Usage = D3D11_USAGE_DEFAULT; 302 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 303 | desc.CPUAccessFlags = 0; 304 | 305 | ID3D11Texture2D* pTexture = NULL; 306 | D3D11_SUBRESOURCE_DATA subResource; 307 | subResource.pSysMem = pixels; 308 | subResource.SysMemPitch = desc.Width * 4; 309 | subResource.SysMemSlicePitch = 0; 310 | g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); 311 | 312 | // Create texture view 313 | D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 314 | ZeroMemory(&srvDesc, sizeof(srvDesc)); 315 | srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 316 | srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 317 | srvDesc.Texture2D.MipLevels = desc.MipLevels; 318 | srvDesc.Texture2D.MostDetailedMip = 0; 319 | g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); 320 | pTexture->Release(); 321 | } 322 | 323 | // Store our identifier 324 | io.Fonts->TexID = (ImTextureID)g_pFontTextureView; 325 | 326 | // Create texture sampler 327 | { 328 | D3D11_SAMPLER_DESC desc; 329 | ZeroMemory(&desc, sizeof(desc)); 330 | desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 331 | desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; 332 | desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; 333 | desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; 334 | desc.MipLODBias = 0.f; 335 | desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; 336 | desc.MinLOD = 0.f; 337 | desc.MaxLOD = 0.f; 338 | g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); 339 | } 340 | } 341 | 342 | bool ImGui_ImplDX11_CreateDeviceObjects() 343 | { 344 | if (!g_pd3dDevice) 345 | return false; 346 | if (g_pFontSampler) 347 | ImGui_ImplDX11_InvalidateDeviceObjects(); 348 | 349 | // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) 350 | // If you would like to use this DX11 sample code but remove this dependency you can: 351 | // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] 352 | // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. 353 | // See https://github.com/ocornut/imgui/pull/638 for sources and details. 354 | 355 | // Create the vertex shader 356 | { 357 | if (g_pd3dDevice->CreateVertexShader(vertex_shader, sizeof(vertex_shader), NULL, &g_pVertexShader) != S_OK) 358 | return false; 359 | 360 | // Create the input layout 361 | D3D11_INPUT_ELEMENT_DESC local_layout[] = 362 | { 363 | { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 364 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 365 | { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 366 | }; 367 | if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertex_shader, sizeof(vertex_shader), &g_pInputLayout) != S_OK) 368 | return false; 369 | 370 | // Create the constant buffer 371 | { 372 | D3D11_BUFFER_DESC desc; 373 | desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); 374 | desc.Usage = D3D11_USAGE_DYNAMIC; 375 | desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 376 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 377 | desc.MiscFlags = 0; 378 | g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); 379 | } 380 | } 381 | 382 | // Create the pixel shader 383 | { 384 | if (g_pd3dDevice->CreatePixelShader(pixel_shader, sizeof(pixel_shader), NULL, &g_pPixelShader) != S_OK) 385 | return false; 386 | } 387 | 388 | // Create the blending setup 389 | { 390 | D3D11_BLEND_DESC desc; 391 | ZeroMemory(&desc, sizeof(desc)); 392 | desc.AlphaToCoverageEnable = false; 393 | desc.RenderTarget[0].BlendEnable = true; 394 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; 395 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 396 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; 397 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; 398 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; 399 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 400 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 401 | g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); 402 | } 403 | 404 | // Create the rasterizer state 405 | { 406 | D3D11_RASTERIZER_DESC desc; 407 | ZeroMemory(&desc, sizeof(desc)); 408 | desc.FillMode = D3D11_FILL_SOLID; 409 | desc.CullMode = D3D11_CULL_NONE; 410 | desc.ScissorEnable = true; 411 | desc.DepthClipEnable = true; 412 | g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); 413 | } 414 | 415 | // Create depth-stencil State 416 | { 417 | D3D11_DEPTH_STENCIL_DESC desc; 418 | ZeroMemory(&desc, sizeof(desc)); 419 | desc.DepthEnable = false; 420 | desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; 421 | desc.DepthFunc = D3D11_COMPARISON_ALWAYS; 422 | desc.StencilEnable = false; 423 | desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 424 | desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 425 | desc.BackFace = desc.FrontFace; 426 | g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); 427 | } 428 | 429 | ImGui_ImplDX11_CreateFontsTexture(); 430 | 431 | return true; 432 | } 433 | 434 | void ImGui_ImplDX11_InvalidateDeviceObjects() 435 | { 436 | if (!g_pd3dDevice) 437 | return; 438 | 439 | if (g_pFontSampler) { 440 | g_pFontSampler->Release(); g_pFontSampler = NULL; 441 | } 442 | if (g_pFontTextureView) { 443 | g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; 444 | } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. 445 | if (g_pIB) { 446 | g_pIB->Release(); g_pIB = NULL; 447 | } 448 | if (g_pVB) { 449 | g_pVB->Release(); g_pVB = NULL; 450 | } 451 | 452 | if (g_pBlendState) { 453 | g_pBlendState->Release(); g_pBlendState = NULL; 454 | } 455 | if (g_pDepthStencilState) { 456 | g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; 457 | } 458 | if (g_pRasterizerState) { 459 | g_pRasterizerState->Release(); g_pRasterizerState = NULL; 460 | } 461 | if (g_pPixelShader) { 462 | g_pPixelShader->Release(); g_pPixelShader = NULL; 463 | } 464 | if (g_pPixelShaderBlob) { 465 | g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; 466 | } 467 | if (g_pVertexConstantBuffer) { 468 | g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; 469 | } 470 | if (g_pInputLayout) { 471 | g_pInputLayout->Release(); g_pInputLayout = NULL; 472 | } 473 | if (g_pVertexShader) { 474 | g_pVertexShader->Release(); g_pVertexShader = NULL; 475 | } 476 | if (g_pVertexShaderBlob) { 477 | g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; 478 | } 479 | } 480 | 481 | bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) 482 | { 483 | // Setup back-end capabilities flags 484 | ImGuiIO& io = ImGui::GetIO(); 485 | io.BackendRendererName = "imgui_impl_dx11"; 486 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 487 | 488 | // Get factory from device 489 | IDXGIDevice* pDXGIDevice = NULL; 490 | IDXGIAdapter* pDXGIAdapter = NULL; 491 | IDXGIFactory* pFactory = NULL; 492 | 493 | if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) 494 | if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) 495 | if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) 496 | { 497 | g_pd3dDevice = device; 498 | g_pd3dDeviceContext = device_context; 499 | g_pFactory = pFactory; 500 | } 501 | if (pDXGIDevice) pDXGIDevice->Release(); 502 | if (pDXGIAdapter) pDXGIAdapter->Release(); 503 | g_pd3dDevice->AddRef(); 504 | g_pd3dDeviceContext->AddRef(); 505 | 506 | return true; 507 | } 508 | 509 | void ImGui_ImplDX11_Shutdown() 510 | { 511 | ImGui_ImplDX11_InvalidateDeviceObjects(); 512 | if (g_pFactory) { 513 | g_pFactory->Release(); g_pFactory = NULL; 514 | } 515 | if (g_pd3dDevice) { 516 | g_pd3dDevice->Release(); g_pd3dDevice = NULL; 517 | } 518 | if (g_pd3dDeviceContext) { 519 | g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; 520 | } 521 | } 522 | 523 | void ImGui_ImplDX11_NewFrame() 524 | { 525 | if (!g_pFontSampler) 526 | ImGui_ImplDX11_CreateDeviceObjects(); 527 | } -------------------------------------------------------------------------------- /hunt_internal/utils/libraries/imgui/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 | { 734 | int c = STB_TEXTEDIT_KEYTOTEXT(key); 735 | if (c > 0) { 736 | STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE)c; 737 | 738 | // can't add newline in single-line mode 739 | if (c == '\n' && state->single_line) 740 | break; 741 | 742 | if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { 743 | stb_text_makeundo_replace(str, state, state->cursor, 1, 1); 744 | STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); 745 | if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { 746 | ++state->cursor; 747 | state->has_preferred_x = 0; 748 | } 749 | } else { 750 | stb_textedit_delete_selection(str, state); // implicitly clamps 751 | if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { 752 | stb_text_makeundo_insert(state, state->cursor, 1); 753 | ++state->cursor; 754 | state->has_preferred_x = 0; 755 | } 756 | } 757 | } 758 | break; 759 | } 760 | 761 | #ifdef STB_TEXTEDIT_K_INSERT 762 | case STB_TEXTEDIT_K_INSERT: 763 | state->insert_mode = !state->insert_mode; 764 | break; 765 | #endif 766 | 767 | case STB_TEXTEDIT_K_UNDO: 768 | stb_text_undo(str, state); 769 | state->has_preferred_x = 0; 770 | break; 771 | 772 | case STB_TEXTEDIT_K_REDO: 773 | stb_text_redo(str, state); 774 | state->has_preferred_x = 0; 775 | break; 776 | 777 | case STB_TEXTEDIT_K_LEFT: 778 | // if currently there's a selection, move cursor to start of selection 779 | if (STB_TEXT_HAS_SELECTION(state)) 780 | stb_textedit_move_to_first(state); 781 | else 782 | if (state->cursor > 0) 783 | --state->cursor; 784 | state->has_preferred_x = 0; 785 | break; 786 | 787 | case STB_TEXTEDIT_K_RIGHT: 788 | // if currently there's a selection, move cursor to end of selection 789 | if (STB_TEXT_HAS_SELECTION(state)) 790 | stb_textedit_move_to_last(str, state); 791 | else 792 | ++state->cursor; 793 | stb_textedit_clamp(str, state); 794 | state->has_preferred_x = 0; 795 | break; 796 | 797 | case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: 798 | stb_textedit_clamp(str, state); 799 | stb_textedit_prep_selection_at_cursor(state); 800 | // move selection left 801 | if (state->select_end > 0) 802 | --state->select_end; 803 | state->cursor = state->select_end; 804 | state->has_preferred_x = 0; 805 | break; 806 | 807 | #ifdef STB_TEXTEDIT_MOVEWORDLEFT 808 | case STB_TEXTEDIT_K_WORDLEFT: 809 | if (STB_TEXT_HAS_SELECTION(state)) 810 | stb_textedit_move_to_first(state); 811 | else { 812 | state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); 813 | stb_textedit_clamp(str, state); 814 | } 815 | break; 816 | 817 | case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: 818 | if (!STB_TEXT_HAS_SELECTION(state)) 819 | stb_textedit_prep_selection_at_cursor(state); 820 | 821 | state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); 822 | state->select_end = state->cursor; 823 | 824 | stb_textedit_clamp(str, state); 825 | break; 826 | #endif 827 | 828 | #ifdef STB_TEXTEDIT_MOVEWORDRIGHT 829 | case STB_TEXTEDIT_K_WORDRIGHT: 830 | if (STB_TEXT_HAS_SELECTION(state)) 831 | stb_textedit_move_to_last(str, state); 832 | else { 833 | state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); 834 | stb_textedit_clamp(str, state); 835 | } 836 | break; 837 | 838 | case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: 839 | if (!STB_TEXT_HAS_SELECTION(state)) 840 | stb_textedit_prep_selection_at_cursor(state); 841 | 842 | state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); 843 | state->select_end = state->cursor; 844 | 845 | stb_textedit_clamp(str, state); 846 | break; 847 | #endif 848 | 849 | case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: 850 | stb_textedit_prep_selection_at_cursor(state); 851 | // move selection right 852 | ++state->select_end; 853 | stb_textedit_clamp(str, state); 854 | state->cursor = state->select_end; 855 | state->has_preferred_x = 0; 856 | break; 857 | 858 | case STB_TEXTEDIT_K_DOWN: 859 | case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: 860 | { 861 | StbFindState find; 862 | StbTexteditRow row; 863 | int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; 864 | 865 | if (state->single_line) { 866 | // on windows, up&down in single-line behave like left&right 867 | key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); 868 | goto retry; 869 | } 870 | 871 | if (sel) 872 | stb_textedit_prep_selection_at_cursor(state); 873 | else if (STB_TEXT_HAS_SELECTION(state)) 874 | stb_textedit_move_to_last(str, state); 875 | 876 | // compute current position of cursor point 877 | stb_textedit_clamp(str, state); 878 | stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); 879 | 880 | // now find character position down a row 881 | if (find.length) { 882 | float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 883 | float x; 884 | int start = find.first_char + find.length; 885 | state->cursor = start; 886 | STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); 887 | x = row.x0; 888 | for (i = 0; i < row.num_chars; ++i) { 889 | float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); 890 | #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE 891 | if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) 892 | break; 893 | #endif 894 | x += dx; 895 | if (x > goal_x) 896 | break; 897 | ++state->cursor; 898 | } 899 | stb_textedit_clamp(str, state); 900 | 901 | state->has_preferred_x = 1; 902 | state->preferred_x = goal_x; 903 | 904 | if (sel) 905 | state->select_end = state->cursor; 906 | } 907 | break; 908 | } 909 | 910 | case STB_TEXTEDIT_K_UP: 911 | case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: 912 | { 913 | StbFindState find; 914 | StbTexteditRow row; 915 | int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; 916 | 917 | if (state->single_line) { 918 | // on windows, up&down become left&right 919 | key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); 920 | goto retry; 921 | } 922 | 923 | if (sel) 924 | stb_textedit_prep_selection_at_cursor(state); 925 | else if (STB_TEXT_HAS_SELECTION(state)) 926 | stb_textedit_move_to_first(state); 927 | 928 | // compute current position of cursor point 929 | stb_textedit_clamp(str, state); 930 | stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); 931 | 932 | // can only go up if there's a previous row 933 | if (find.prev_first != find.first_char) { 934 | // now find character position up a row 935 | float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 936 | float x; 937 | state->cursor = find.prev_first; 938 | STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); 939 | x = row.x0; 940 | for (i = 0; i < row.num_chars; ++i) { 941 | float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); 942 | #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE 943 | if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) 944 | break; 945 | #endif 946 | x += dx; 947 | if (x > goal_x) 948 | break; 949 | ++state->cursor; 950 | } 951 | stb_textedit_clamp(str, state); 952 | 953 | state->has_preferred_x = 1; 954 | state->preferred_x = goal_x; 955 | 956 | if (sel) 957 | state->select_end = state->cursor; 958 | } 959 | break; 960 | } 961 | 962 | case STB_TEXTEDIT_K_DELETE: 963 | case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: 964 | if (STB_TEXT_HAS_SELECTION(state)) 965 | stb_textedit_delete_selection(str, state); 966 | else { 967 | int n = STB_TEXTEDIT_STRINGLEN(str); 968 | if (state->cursor < n) 969 | stb_textedit_delete(str, state, state->cursor, 1); 970 | } 971 | state->has_preferred_x = 0; 972 | break; 973 | 974 | case STB_TEXTEDIT_K_BACKSPACE: 975 | case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: 976 | if (STB_TEXT_HAS_SELECTION(state)) 977 | stb_textedit_delete_selection(str, state); 978 | else { 979 | stb_textedit_clamp(str, state); 980 | if (state->cursor > 0) { 981 | stb_textedit_delete(str, state, state->cursor - 1, 1); 982 | --state->cursor; 983 | } 984 | } 985 | state->has_preferred_x = 0; 986 | break; 987 | 988 | #ifdef STB_TEXTEDIT_K_TEXTSTART2 989 | case STB_TEXTEDIT_K_TEXTSTART2: 990 | #endif 991 | case STB_TEXTEDIT_K_TEXTSTART: 992 | state->cursor = state->select_start = state->select_end = 0; 993 | state->has_preferred_x = 0; 994 | break; 995 | 996 | #ifdef STB_TEXTEDIT_K_TEXTEND2 997 | case STB_TEXTEDIT_K_TEXTEND2: 998 | #endif 999 | case STB_TEXTEDIT_K_TEXTEND: 1000 | state->cursor = STB_TEXTEDIT_STRINGLEN(str); 1001 | state->select_start = state->select_end = 0; 1002 | state->has_preferred_x = 0; 1003 | break; 1004 | 1005 | #ifdef STB_TEXTEDIT_K_TEXTSTART2 1006 | case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: 1007 | #endif 1008 | case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: 1009 | stb_textedit_prep_selection_at_cursor(state); 1010 | state->cursor = state->select_end = 0; 1011 | state->has_preferred_x = 0; 1012 | break; 1013 | 1014 | #ifdef STB_TEXTEDIT_K_TEXTEND2 1015 | case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: 1016 | #endif 1017 | case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: 1018 | stb_textedit_prep_selection_at_cursor(state); 1019 | state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); 1020 | state->has_preferred_x = 0; 1021 | break; 1022 | 1023 | 1024 | #ifdef STB_TEXTEDIT_K_LINESTART2 1025 | case STB_TEXTEDIT_K_LINESTART2: 1026 | #endif 1027 | case STB_TEXTEDIT_K_LINESTART: 1028 | stb_textedit_clamp(str, state); 1029 | stb_textedit_move_to_first(state); 1030 | if (state->single_line) 1031 | state->cursor = 0; 1032 | else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor - 1) != STB_TEXTEDIT_NEWLINE) 1033 | --state->cursor; 1034 | state->has_preferred_x = 0; 1035 | break; 1036 | 1037 | #ifdef STB_TEXTEDIT_K_LINEEND2 1038 | case STB_TEXTEDIT_K_LINEEND2: 1039 | #endif 1040 | case STB_TEXTEDIT_K_LINEEND: 1041 | { 1042 | int n = STB_TEXTEDIT_STRINGLEN(str); 1043 | stb_textedit_clamp(str, state); 1044 | stb_textedit_move_to_first(state); 1045 | if (state->single_line) 1046 | state->cursor = n; 1047 | else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) 1048 | ++state->cursor; 1049 | state->has_preferred_x = 0; 1050 | break; 1051 | } 1052 | 1053 | #ifdef STB_TEXTEDIT_K_LINESTART2 1054 | case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: 1055 | #endif 1056 | case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: 1057 | stb_textedit_clamp(str, state); 1058 | stb_textedit_prep_selection_at_cursor(state); 1059 | if (state->single_line) 1060 | state->cursor = 0; 1061 | else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor - 1) != STB_TEXTEDIT_NEWLINE) 1062 | --state->cursor; 1063 | state->select_end = state->cursor; 1064 | state->has_preferred_x = 0; 1065 | break; 1066 | 1067 | #ifdef STB_TEXTEDIT_K_LINEEND2 1068 | case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: 1069 | #endif 1070 | case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: 1071 | { 1072 | int n = STB_TEXTEDIT_STRINGLEN(str); 1073 | stb_textedit_clamp(str, state); 1074 | stb_textedit_prep_selection_at_cursor(state); 1075 | if (state->single_line) 1076 | state->cursor = n; 1077 | else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) 1078 | ++state->cursor; 1079 | state->select_end = state->cursor; 1080 | state->has_preferred_x = 0; 1081 | break; 1082 | } 1083 | 1084 | // @TODO: 1085 | // STB_TEXTEDIT_K_PGUP - move cursor up a page 1086 | // STB_TEXTEDIT_K_PGDOWN - move cursor down a page 1087 | } 1088 | } 1089 | 1090 | ///////////////////////////////////////////////////////////////////////////// 1091 | // 1092 | // Undo processing 1093 | // 1094 | // @OPTIMIZE: the undo/redo buffer should be circular 1095 | 1096 | static void stb_textedit_flush_redo(StbUndoState* state) 1097 | { 1098 | state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; 1099 | state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; 1100 | } 1101 | 1102 | // discard the oldest entry in the undo list 1103 | static void stb_textedit_discard_undo(StbUndoState* state) 1104 | { 1105 | if (state->undo_point > 0) { 1106 | // if the 0th undo state has characters, clean those up 1107 | if (state->undo_rec[0].char_storage >= 0) { 1108 | int n = state->undo_rec[0].insert_length, i; 1109 | // delete n characters from all other records 1110 | state->undo_char_point -= n; 1111 | STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t)(state->undo_char_point * sizeof(STB_TEXTEDIT_CHARTYPE))); 1112 | for (i = 0; i < state->undo_point; ++i) 1113 | if (state->undo_rec[i].char_storage >= 0) 1114 | state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it 1115 | } 1116 | --state->undo_point; 1117 | STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec + 1, (size_t)(state->undo_point * sizeof(state->undo_rec[0]))); 1118 | } 1119 | } 1120 | 1121 | // discard the oldest entry in the redo list--it's bad if this 1122 | // ever happens, but because undo & redo have to store the actual 1123 | // characters in different cases, the redo character buffer can 1124 | // fill up even though the undo buffer didn't 1125 | static void stb_textedit_discard_redo(StbUndoState* state) 1126 | { 1127 | int k = STB_TEXTEDIT_UNDOSTATECOUNT - 1; 1128 | 1129 | if (state->redo_point <= k) { 1130 | // if the k'th undo state has characters, clean those up 1131 | if (state->undo_rec[k].char_storage >= 0) { 1132 | int n = state->undo_rec[k].insert_length, i; 1133 | // move the remaining redo character data to the end of the buffer 1134 | state->redo_char_point += n; 1135 | 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))); 1136 | // adjust the position of all the other records to account for above memmove 1137 | for (i = state->redo_point; i < k; ++i) 1138 | if (state->undo_rec[i].char_storage >= 0) 1139 | state->undo_rec[i].char_storage += n; 1140 | } 1141 | // now move all the redo records towards the end of the buffer; the first one is at 'redo_point' 1142 | // {DEAR IMGUI] 1143 | size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0])); 1144 | const char* buf_begin = (char*)state->undo_rec; (void)buf_begin; 1145 | const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end; 1146 | IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin); 1147 | IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end); 1148 | STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point + 1, state->undo_rec + state->redo_point, move_size); 1149 | 1150 | // now move redo_point to point to the new one 1151 | ++state->redo_point; 1152 | } 1153 | } 1154 | 1155 | static StbUndoRecord* stb_text_create_undo_record(StbUndoState* state, int numchars) 1156 | { 1157 | // any time we create a new undo record, we discard redo 1158 | stb_textedit_flush_redo(state); 1159 | 1160 | // if we have no free records, we have to make room, by sliding the 1161 | // existing records down 1162 | if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1163 | stb_textedit_discard_undo(state); 1164 | 1165 | // if the characters to store won't possibly fit in the buffer, we can't undo 1166 | if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) { 1167 | state->undo_point = 0; 1168 | state->undo_char_point = 0; 1169 | return NULL; 1170 | } 1171 | 1172 | // if we don't have enough free characters in the buffer, we have to make room 1173 | while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT) 1174 | stb_textedit_discard_undo(state); 1175 | 1176 | return &state->undo_rec[state->undo_point++]; 1177 | } 1178 | 1179 | static STB_TEXTEDIT_CHARTYPE* stb_text_createundo(StbUndoState* state, int pos, int insert_len, int delete_len) 1180 | { 1181 | StbUndoRecord* r = stb_text_create_undo_record(state, insert_len); 1182 | if (r == NULL) 1183 | return NULL; 1184 | 1185 | r->where = pos; 1186 | r->insert_length = (STB_TEXTEDIT_POSITIONTYPE)insert_len; 1187 | r->delete_length = (STB_TEXTEDIT_POSITIONTYPE)delete_len; 1188 | 1189 | if (insert_len == 0) { 1190 | r->char_storage = -1; 1191 | return NULL; 1192 | } else { 1193 | r->char_storage = state->undo_char_point; 1194 | state->undo_char_point += insert_len; 1195 | return &state->undo_char[r->char_storage]; 1196 | } 1197 | } 1198 | 1199 | static void stb_text_undo(STB_TEXTEDIT_STRING* str, STB_TexteditState* state) 1200 | { 1201 | StbUndoState* s = &state->undostate; 1202 | StbUndoRecord u, * r; 1203 | if (s->undo_point == 0) 1204 | return; 1205 | 1206 | // we need to do two things: apply the undo record, and create a redo record 1207 | u = s->undo_rec[s->undo_point - 1]; 1208 | r = &s->undo_rec[s->redo_point - 1]; 1209 | r->char_storage = -1; 1210 | 1211 | r->insert_length = u.delete_length; 1212 | r->delete_length = u.insert_length; 1213 | r->where = u.where; 1214 | 1215 | if (u.delete_length) { 1216 | // if the undo record says to delete characters, then the redo record will 1217 | // need to re-insert the characters that get deleted, so we need to store 1218 | // them. 1219 | 1220 | // there are three cases: 1221 | // there's enough room to store the characters 1222 | // characters stored for *redoing* don't leave room for redo 1223 | // characters stored for *undoing* don't leave room for redo 1224 | // if the last is true, we have to bail 1225 | 1226 | if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) { 1227 | // the undo records take up too much character space; there's no space to store the redo characters 1228 | r->insert_length = 0; 1229 | } else { 1230 | int i; 1231 | 1232 | // there's definitely room to store the characters eventually 1233 | while (s->undo_char_point + u.delete_length > s->redo_char_point) { 1234 | // should never happen: 1235 | if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1236 | return; 1237 | // there's currently not enough room, so discard a redo record 1238 | stb_textedit_discard_redo(s); 1239 | } 1240 | r = &s->undo_rec[s->redo_point - 1]; 1241 | 1242 | r->char_storage = s->redo_char_point - u.delete_length; 1243 | s->redo_char_point = s->redo_char_point - u.delete_length; 1244 | 1245 | // now save the characters 1246 | for (i = 0; i < u.delete_length; ++i) 1247 | s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); 1248 | } 1249 | 1250 | // now we can carry out the deletion 1251 | STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); 1252 | } 1253 | 1254 | // check type of recorded action: 1255 | if (u.insert_length) { 1256 | // easy case: was a deletion, so we need to insert n characters 1257 | STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); 1258 | s->undo_char_point -= u.insert_length; 1259 | } 1260 | 1261 | state->cursor = u.where + u.insert_length; 1262 | 1263 | s->undo_point--; 1264 | s->redo_point--; 1265 | } 1266 | 1267 | static void stb_text_redo(STB_TEXTEDIT_STRING* str, STB_TexteditState* state) 1268 | { 1269 | StbUndoState* s = &state->undostate; 1270 | StbUndoRecord* u, r; 1271 | if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1272 | return; 1273 | 1274 | // we need to do two things: apply the redo record, and create an undo record 1275 | u = &s->undo_rec[s->undo_point]; 1276 | r = s->undo_rec[s->redo_point]; 1277 | 1278 | // we KNOW there must be room for the undo record, because the redo record 1279 | // was derived from an undo record 1280 | 1281 | u->delete_length = r.insert_length; 1282 | u->insert_length = r.delete_length; 1283 | u->where = r.where; 1284 | u->char_storage = -1; 1285 | 1286 | if (r.delete_length) { 1287 | // the redo record requires us to delete characters, so the undo record 1288 | // needs to store the characters 1289 | 1290 | if (s->undo_char_point + u->insert_length > s->redo_char_point) { 1291 | u->insert_length = 0; 1292 | u->delete_length = 0; 1293 | } else { 1294 | int i; 1295 | u->char_storage = s->undo_char_point; 1296 | s->undo_char_point = s->undo_char_point + u->insert_length; 1297 | 1298 | // now save the characters 1299 | for (i = 0; i < u->insert_length; ++i) 1300 | s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); 1301 | } 1302 | 1303 | STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); 1304 | } 1305 | 1306 | if (r.insert_length) { 1307 | // easy case: need to insert n characters 1308 | STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); 1309 | s->redo_char_point += r.insert_length; 1310 | } 1311 | 1312 | state->cursor = r.where + r.insert_length; 1313 | 1314 | s->undo_point++; 1315 | s->redo_point++; 1316 | } 1317 | 1318 | static void stb_text_makeundo_insert(STB_TexteditState* state, int where, int length) 1319 | { 1320 | stb_text_createundo(&state->undostate, where, 0, length); 1321 | } 1322 | 1323 | static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING* str, STB_TexteditState* state, int where, int length) 1324 | { 1325 | int i; 1326 | STB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->undostate, where, length, 0); 1327 | if (p) { 1328 | for (i = 0; i < length; ++i) 1329 | p[i] = STB_TEXTEDIT_GETCHAR(str, where + i); 1330 | } 1331 | } 1332 | 1333 | static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING* str, STB_TexteditState* state, int where, int old_length, int new_length) 1334 | { 1335 | int i; 1336 | STB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->undostate, where, old_length, new_length); 1337 | if (p) { 1338 | for (i = 0; i < old_length; ++i) 1339 | p[i] = STB_TEXTEDIT_GETCHAR(str, where + i); 1340 | } 1341 | } 1342 | 1343 | // reset the state to default 1344 | static void stb_textedit_clear_state(STB_TexteditState* state, int is_single_line) 1345 | { 1346 | state->undostate.undo_point = 0; 1347 | state->undostate.undo_char_point = 0; 1348 | state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; 1349 | state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; 1350 | state->select_end = state->select_start = 0; 1351 | state->cursor = 0; 1352 | state->has_preferred_x = 0; 1353 | state->preferred_x = 0; 1354 | state->cursor_at_end_of_line = 0; 1355 | state->initialized = 1; 1356 | state->single_line = (unsigned char)is_single_line; 1357 | state->insert_mode = 0; 1358 | } 1359 | 1360 | // API initialize 1361 | static void stb_textedit_initialize_state(STB_TexteditState* state, int is_single_line) 1362 | { 1363 | stb_textedit_clear_state(state, is_single_line); 1364 | } 1365 | 1366 | #if defined(__GNUC__) || defined(__clang__) 1367 | #pragma GCC diagnostic push 1368 | #pragma GCC diagnostic ignored "-Wcast-qual" 1369 | #endif 1370 | 1371 | static int stb_textedit_paste(STB_TEXTEDIT_STRING* str, STB_TexteditState* state, STB_TEXTEDIT_CHARTYPE const* ctext, int len) 1372 | { 1373 | return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE*)ctext, len); 1374 | } 1375 | 1376 | #if defined(__GNUC__) || defined(__clang__) 1377 | #pragma GCC diagnostic pop 1378 | #endif 1379 | 1380 | #endif//STB_TEXTEDIT_IMPLEMENTATION 1381 | 1382 | /* 1383 | ------------------------------------------------------------------------------ 1384 | This software is available under 2 licenses -- choose whichever you prefer. 1385 | ------------------------------------------------------------------------------ 1386 | ALTERNATIVE A - MIT License 1387 | Copyright (c) 2017 Sean Barrett 1388 | Permission is hereby granted, free of charge, to any person obtaining a copy of 1389 | this software and associated documentation files (the "Software"), to deal in 1390 | the Software without restriction, including without limitation the rights to 1391 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 1392 | of the Software, and to permit persons to whom the Software is furnished to do 1393 | so, subject to the following conditions: 1394 | The above copyright notice and this permission notice shall be included in all 1395 | copies or substantial portions of the Software. 1396 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1397 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1398 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1399 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1400 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 1401 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 1402 | SOFTWARE. 1403 | ------------------------------------------------------------------------------ 1404 | ALTERNATIVE B - Public Domain (www.unlicense.org) 1405 | This is free and unencumbered software released into the public domain. 1406 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 1407 | software, either in source code form or as a compiled binary, for any purpose, 1408 | commercial or non-commercial, and by any means. 1409 | In jurisdictions that recognize copyright laws, the author or authors of this 1410 | software dedicate any and all copyright interest in the software to the public 1411 | domain. We make this dedication for the benefit of the public at large and to 1412 | the detriment of our heirs and successors. We intend this dedication to be an 1413 | overt act of relinquishment in perpetuity of all present and future rights to 1414 | this software under copyright law. 1415 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1416 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1417 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1418 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 1419 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 1420 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1421 | ------------------------------------------------------------------------------ 1422 | */ --------------------------------------------------------------------------------