├── Sea of Thieves External ├── imgui.ini ├── sdk.cpp ├── tab_item.h ├── colors.h ├── esp.h ├── cheat.cpp ├── tabs.h ├── main.cpp ├── tab.h ├── tab_item.cpp ├── cheat.h ├── menu.h ├── overlay.h ├── hacklib.h ├── imgui │ ├── imgui_impl_dx11.h │ ├── imgui_impl_win32.h │ ├── imconfig.h │ ├── imstb_rectpack.h │ ├── imgui_impl_dx11.cpp │ └── imgui_impl_win32.cpp ├── offsets.h ├── tab.cpp ├── hacklib.cpp ├── menu.cpp ├── sot.h ├── overlay.cpp ├── Sea of Thieves External.vcxproj.filters ├── sdk.h ├── Sea of Thieves External.vcxproj ├── sot.cpp └── esp.cpp ├── Sea of Thieves External.sln ├── README.md └── .gitignore /Sea of Thieves External/imgui.ini: -------------------------------------------------------------------------------- 1 | [Window][Debug##Default] 2 | Pos=60,9 3 | Size=400,400 4 | Collapsed=0 5 | 6 | [Window][Hello] 7 | Pos=60,60 8 | Size=32,35 9 | Collapsed=0 10 | 11 | [Window][HELLO!] 12 | Pos=60,60 13 | Size=32,35 14 | Collapsed=0 15 | 16 | -------------------------------------------------------------------------------- /Sea of Thieves External/sdk.cpp: -------------------------------------------------------------------------------- 1 | #include "sdk.h" 2 | 3 | namespace sdk 4 | { 5 | hacklib::Process *_process; 6 | 7 | bool init(hacklib::Process *process) 8 | { 9 | _process = process; 10 | return _process != nullptr; 11 | } 12 | 13 | hacklib::Process *process() 14 | { 15 | return _process; 16 | } 17 | } -------------------------------------------------------------------------------- /Sea of Thieves External/tab_item.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace gui 5 | { 6 | class TabItem 7 | { 8 | public: 9 | TabItem(const std::string &name, bool *state) 10 | : _name(name) 11 | , _state(state) 12 | { 13 | } 14 | 15 | void draw(float x, float y, bool selected) const; 16 | void toggle(); 17 | 18 | private: 19 | std::string _name; 20 | bool *_state; 21 | }; 22 | } -------------------------------------------------------------------------------- /Sea of Thieves External/colors.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "imgui/imgui.h" 3 | 4 | namespace gui 5 | { 6 | namespace colors 7 | { 8 | constexpr ImColor background_color{ 0.2f, 0.2f, 0.2f }; 9 | constexpr ImColor foreground_color{ 0.0f, 0.5f, 1.0f }; 10 | constexpr ImColor accent_color{ 0.0f, 0.5f, 1.0f }; 11 | constexpr ImColor control_color{ 0.5f, 0.5f, 0.5f }; 12 | constexpr ImColor enabled_color{ 0.0f, 0.78f, 0.42f }; 13 | } 14 | } -------------------------------------------------------------------------------- /Sea of Thieves External/esp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cheat.h" 3 | 4 | #include 5 | 6 | #include "imgui/imgui.h" 7 | 8 | #include "sdk.h" 9 | 10 | namespace cheat 11 | { 12 | class ESP : public Cheat 13 | { 14 | public: 15 | ESP(); 16 | 17 | void tick() override; 18 | 19 | private: 20 | std::string convert_wide_string(const wchar_t *wide_string) const; 21 | 22 | void draw_text(float x, float y, const char *text, ImColor color); 23 | 24 | float _t = 0.0f; 25 | ImFont *_esp_font = nullptr; 26 | }; 27 | } -------------------------------------------------------------------------------- /Sea of Thieves External/cheat.cpp: -------------------------------------------------------------------------------- 1 | #include "cheat.h" 2 | 3 | namespace cheat 4 | { 5 | Settings _settings{ }; 6 | 7 | Settings *settings() 8 | { 9 | return &_settings; 10 | } 11 | 12 | void CheatManager::add_cheat(std::shared_ptr cheat) 13 | { 14 | this->_cheats.push_back(cheat); 15 | } 16 | 17 | void CheatManager::tick() 18 | { 19 | for (std::shared_ptr &cheat : this->_cheats) 20 | { 21 | cheat->tick(); 22 | } 23 | } 24 | 25 | CheatManager _cheat_manager{ }; 26 | 27 | CheatManager *cheat_manager() 28 | { 29 | return &_cheat_manager; 30 | } 31 | } -------------------------------------------------------------------------------- /Sea of Thieves External/tabs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "tab.h" 3 | 4 | #include "cheat.h" 5 | 6 | namespace cheat 7 | { 8 | class ESPTab : public gui::Tab 9 | { 10 | public: 11 | ESPTab() 12 | : Tab("ESP") 13 | { 14 | this->add_item(gui::TabItem{ "Players", &settings()->player_esp }); 15 | this->add_item(gui::TabItem{ "Creatures", &settings()->creature_esp }); 16 | this->add_item(gui::TabItem{ "Ships", &settings()->ship_esp }); 17 | this->add_item(gui::TabItem{ "Treasure", &settings()->treasure_esp }); 18 | this->add_item(gui::TabItem{ "NPCs", &settings()->npc_esp }); 19 | this->add_item(gui::TabItem{ "Debug", &settings()->debug_esp }); 20 | } 21 | }; 22 | } -------------------------------------------------------------------------------- /Sea of Thieves External/main.cpp: -------------------------------------------------------------------------------- 1 | #include "overlay.h" 2 | #include "tabs.h" 3 | #include "sot.h" 4 | #include "esp.h" 5 | 6 | #include 7 | 8 | int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show) 9 | { 10 | if (!cheat::game()->init()) 11 | { 12 | MessageBoxA(nullptr, "Initialization failed.", "Error", MB_OK); 13 | return 0; 14 | } 15 | 16 | auto overlay = gui::Overlay{ instance, "Overlay", FindWindowA(nullptr, "Sea of Thieves"), cmd_show }; 17 | 18 | overlay.menu().add_tab(std::make_shared()); 19 | 20 | cheat::cheat_manager()->add_cheat(std::make_shared()); 21 | 22 | overlay.add_draw_callback([]() { cheat::cheat_manager()->tick(); }); 23 | overlay.window_loop(); 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Sea of Thieves External/tab.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include "tab_item.h" 8 | 9 | namespace gui 10 | { 11 | class Tab abstract 12 | { 13 | public: 14 | Tab(const std::string &name) 15 | : _name(name) 16 | { 17 | } 18 | 19 | void select(); 20 | void deselect(); 21 | void open(); 22 | void close(); 23 | void add_item(const TabItem &item); 24 | void draw(float x, float y, int index) const; 25 | void process_key_input(int key_code); 26 | 27 | protected: 28 | void draw_content(float x, float y) const; 29 | void next_item(); 30 | void previous_item(); 31 | 32 | std::string _name; 33 | bool _selected = false; 34 | bool _opened = false; 35 | std::vector _items{ }; 36 | int _selected_item = 0; 37 | }; 38 | } -------------------------------------------------------------------------------- /Sea of Thieves External/tab_item.cpp: -------------------------------------------------------------------------------- 1 | #include "tab_item.h" 2 | 3 | #include "imgui/imgui.h" 4 | #include 5 | 6 | #include "colors.h" 7 | 8 | namespace gui 9 | { 10 | void TabItem::draw(float x, float y, bool selected) const 11 | { 12 | bool state = this->_state ? *this->_state : false; 13 | auto highlight_color = state ? colors::enabled_color : colors::control_color; 14 | if (selected) highlight_color = colors::accent_color; 15 | auto draw_list = ImGui::GetForegroundDrawList(); 16 | draw_list->AddRectFilled({ x, y }, { x + 190, y + 30 }, highlight_color, 1.0f); 17 | draw_list->AddText({ x + 5, y + 3 }, IM_COL32_WHITE, this->_name.c_str()); 18 | if (state) draw_list->AddText({ x + 175, y + 3 }, IM_COL32_WHITE, "*"); 19 | } 20 | 21 | void TabItem::toggle() 22 | { 23 | if (!this->_state) return; 24 | *this->_state = !*this->_state; 25 | } 26 | } -------------------------------------------------------------------------------- /Sea of Thieves External/cheat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace cheat 6 | { 7 | struct Settings 8 | { 9 | bool player_esp = false; 10 | bool creature_esp = false; 11 | bool ship_esp = false; 12 | bool treasure_esp = false; 13 | bool npc_esp = false; 14 | bool debug_esp = false; 15 | }; 16 | 17 | Settings *settings(); 18 | 19 | class Cheat abstract 20 | { 21 | public: 22 | Cheat() 23 | { 24 | } 25 | 26 | virtual void tick() = 0; // Not synced with in-game ticks, just called every time the overlay is rendered 27 | }; 28 | 29 | class CheatManager 30 | { 31 | public: 32 | CheatManager() 33 | { 34 | } 35 | 36 | void add_cheat(std::shared_ptr cheat); 37 | void tick(); 38 | 39 | private: 40 | std::vector> _cheats{ }; 41 | }; 42 | 43 | CheatManager *cheat_manager(); 44 | } -------------------------------------------------------------------------------- /Sea of Thieves External/menu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "imgui/imgui.h" 9 | 10 | #include "tab.h" 11 | 12 | namespace gui 13 | { 14 | class Menu 15 | { 16 | public: 17 | Menu(const std::string &title, float x, float y); 18 | 19 | void setup_fonts(); 20 | void set_position(float x, float y); 21 | void draw() const; 22 | void process_key_input(int key_code); 23 | void add_tab(std::shared_ptr tab); 24 | 25 | private: 26 | std::shared_ptr get_selected_tab(); 27 | void select_next_tab(); 28 | void select_previous_tab(); 29 | 30 | std::string _title; 31 | float _x; 32 | float _y; 33 | float _width = 200.0f; 34 | float _height = 300.0f; 35 | std::vector> _tabs{ }; 36 | int _selected_tab = 0; 37 | bool _tab_opened = false; 38 | bool _visible = false; 39 | ImFont *_title_font = nullptr; 40 | ImFont *_tab_font = nullptr; 41 | }; 42 | } -------------------------------------------------------------------------------- /Sea of Thieves External/overlay.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "menu.h" 9 | 10 | namespace gui 11 | { 12 | class Overlay 13 | { 14 | public: 15 | Overlay(HINSTANCE instance, const std::string &title, HWND target_window, int cmd_show); 16 | void window_loop(); 17 | Menu &menu(); 18 | 19 | using DrawCallbackFn = void(*)(); 20 | void add_draw_callback(DrawCallbackFn callback_fn); 21 | 22 | private: 23 | static LRESULT window_procedure(HWND window, UINT msg, WPARAM param1, LPARAM param2); 24 | 25 | void setup_window(HINSTANCE instance); 26 | void setup_direct3D(); 27 | 28 | const float _clear_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 29 | 30 | std::string _title; 31 | HWND _target_window; 32 | WNDCLASSEXA _window_class; 33 | HWND _window; 34 | IDXGISwapChain *_swap_chain; 35 | ID3D11Device *_device; 36 | ID3D11DeviceContext *_context; 37 | ID3D11RenderTargetView *_rt_view; 38 | Menu _menu; 39 | std::vector _callbacks{ }; 40 | }; 41 | } -------------------------------------------------------------------------------- /Sea of Thieves External/hacklib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | namespace hacklib 8 | { 9 | class SmartHandle 10 | { 11 | public: 12 | SmartHandle(HANDLE handle); 13 | SmartHandle &operator=(SmartHandle &&other) noexcept; 14 | ~SmartHandle(); 15 | 16 | operator HANDLE(); 17 | 18 | bool is_valid() const; 19 | 20 | private: 21 | HANDLE _handle; 22 | }; 23 | 24 | struct Module 25 | { 26 | void *_base; 27 | DWORD _size; 28 | }; 29 | 30 | class Process 31 | { 32 | public: 33 | Process(const std::string &name) 34 | : _name(name) 35 | , _pid(0) 36 | , _handle(nullptr) 37 | { 38 | } 39 | 40 | bool attach(DWORD access_mask); 41 | Module get_module(const std::string &module_name); 42 | 43 | void read_memory(void *address, void *out, SIZE_T size) 44 | { 45 | ReadProcessMemory(this->_handle, address, out, size, nullptr); 46 | } 47 | 48 | template 49 | T read_memory(void *address) 50 | { 51 | T result{ }; 52 | ReadProcessMemory(this->_handle, address, &result, sizeof(result), nullptr); 53 | return result; 54 | } 55 | 56 | private: 57 | std::string _name; 58 | DWORD _pid; 59 | SmartHandle _handle; 60 | std::unordered_map _modules{ }; 61 | }; 62 | } -------------------------------------------------------------------------------- /Sea of Thieves External/imgui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 12 | 13 | #pragma once 14 | #include "imgui.h" // IMGUI_IMPL_API 15 | 16 | struct ID3D11Device; 17 | struct ID3D11DeviceContext; 18 | 19 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 20 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 21 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 22 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 23 | 24 | // Use if you want to reset your rendering device without losing Dear ImGui state. 25 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 26 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); 27 | -------------------------------------------------------------------------------- /Sea of Thieves External.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.33130.400 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sea of Thieves External", "Sea of Thieves External\Sea of Thieves External.vcxproj", "{F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}.Debug|x64.ActiveCfg = Debug|x64 17 | {F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}.Debug|x64.Build.0 = Debug|x64 18 | {F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}.Debug|x86.ActiveCfg = Debug|Win32 19 | {F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}.Debug|x86.Build.0 = Debug|Win32 20 | {F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}.Release|x64.ActiveCfg = Release|x64 21 | {F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}.Release|x64.Build.0 = Release|x64 22 | {F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}.Release|x86.ActiveCfg = Release|Win32 23 | {F1D01F09-0BAD-43C3-A8C8-2328E5C861F9}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {53179D80-DF06-482E-AA85-35CFC3C5D8A5} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Sea of Thieves External/offsets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define OFFSET(name, value) constexpr const uint32_t name = value 5 | 6 | namespace offsets 7 | { 8 | //Global 9 | OFFSET(GNames, 0x8100bf8); 10 | OFFSET(GObjects, 0x8105240); 11 | OFFSET(GWorld, 0x81c8690); //UWorld * 12 | 13 | //UWorld 14 | OFFSET(PersistentLevel, 0x30); //ULevel * 15 | OFFSET(OwningGameInstance, 0x1c0); //UGameInstance * 16 | 17 | //ULevel 18 | OFFSET(Actors, 0xa0); //TArray 19 | 20 | //AActor 21 | OFFSET(RootComponent, 0x168); //USceneComponent * 22 | OFFSET(Children, 0x158); //TArray 23 | 24 | //USceneComponent 25 | OFFSET(RelativeLocation, 0x12c); //FVector 26 | 27 | //UGameInstance 28 | OFFSET(LocalPlayers, 0x38); //TArray 29 | 30 | //UPlayer 31 | OFFSET(PlayerController, 0x30); //APlayerController * 32 | 33 | //APlayerController 34 | OFFSET(AcknowledgedPawn, 0x438); //APawn * 35 | OFFSET(PlayerCameraManager, 0x458); //APlayerCameraManager * 36 | 37 | //APawn 38 | OFFSET(PlayerState, 0x3e8); //APlayerState * 39 | 40 | //AAthenaCharacter 41 | OFFSET(HealthComponent, 0x898); //UHealthComponent * 42 | 43 | //UHealthComponent 44 | OFFSET(MaxHealth, 0xe0); // float 45 | OFFSET(CurrentHealthInfo, 0xe4); // FCurrentHealthInfo 46 | 47 | //FCurrentHealthInfo 48 | OFFSET(Health, 0x00); // float 49 | 50 | //APlayerState 51 | OFFSET(PlayerName, 0x3d0); //FString 52 | 53 | //APlayerCameraManager 54 | OFFSET(CameraCache, 0x440); //FCameraCacheEntry 55 | 56 | //FCameraCacheEntry 57 | OFFSET(POV, 0x10); //FMinimalViewInfo 58 | 59 | //FMinimalViewInfo 60 | OFFSET(Location, 0x0); //FVector 61 | OFFSET(Rotation, 0xC); //FRotator 62 | OFFSET(FOV, 0x28); //float 63 | } 64 | 65 | #undef OFFSET -------------------------------------------------------------------------------- /Sea of Thieves External/tab.cpp: -------------------------------------------------------------------------------- 1 | #include "tab.h" 2 | 3 | #include "colors.h" 4 | 5 | namespace gui 6 | { 7 | 8 | void Tab::select() 9 | { 10 | this->_selected = true; 11 | } 12 | 13 | void Tab::deselect() 14 | { 15 | this->_selected = false; 16 | } 17 | 18 | void Tab::open() 19 | { 20 | this->_opened = true; 21 | } 22 | 23 | void Tab::close() 24 | { 25 | this->_selected_item = 0; 26 | this->_opened = false; 27 | } 28 | 29 | void Tab::add_item(const TabItem &item) 30 | { 31 | this->_items.push_back(item); 32 | } 33 | 34 | void Tab::draw(float x, float y, int index) const 35 | { 36 | const auto &highlight_color = this->_selected ? colors::accent_color : colors::control_color; 37 | auto draw_list = ImGui::GetForegroundDrawList(); 38 | auto tab_x = x + 5; 39 | auto tab_y = y + 60 + index * 35; 40 | draw_list->AddRectFilled({ tab_x, tab_y }, { tab_x + 190, tab_y + 30 }, highlight_color, 1.0f); 41 | draw_list->AddText({ tab_x + 5, tab_y + 3 }, IM_COL32_WHITE, this->_name.c_str()); 42 | char indicator = this->_selected && this->_opened ? '<' : '>'; 43 | draw_list->AddText({ tab_x + 175, tab_y + 3 }, IM_COL32_WHITE, &indicator, &indicator + 1); 44 | if (this->_selected && this->_opened) this->draw_content(x + 210, y); 45 | } 46 | 47 | void Tab::draw_content(float x, float y) const 48 | { 49 | auto draw_list = ImGui::GetForegroundDrawList(); 50 | draw_list->AddRectFilled({ x, y }, { x + 200, y + 300 }, colors::background_color, 1.0f); 51 | draw_list->AddRect({ x, y }, { x + 200, y + 300 }, colors::foreground_color, 1.0f); 52 | for (int i = 0; i < this->_items.size(); ++i) 53 | { 54 | const auto &item = this->_items[i]; 55 | auto item_x = x + 5; 56 | auto item_y = y + 5 + i * 35; 57 | bool is_selected = i == this->_selected_item; 58 | item.draw(item_x, item_y, is_selected); 59 | } 60 | } 61 | 62 | void Tab::process_key_input(int key_code) 63 | { 64 | switch (key_code) 65 | { 66 | case VK_DOWN: 67 | this->next_item(); 68 | break; 69 | case VK_UP: 70 | this->previous_item(); 71 | break; 72 | case VK_RIGHT: 73 | this->_items[this->_selected_item].toggle(); 74 | } 75 | } 76 | 77 | void Tab::next_item() 78 | { 79 | ++this->_selected_item; 80 | if (this->_selected_item > this->_items.size() - 1) this->_selected_item = 0; 81 | } 82 | 83 | void Tab::previous_item() 84 | { 85 | --this->_selected_item; 86 | if (this->_selected_item < 0) this->_selected_item = this->_items.size() - 1; 87 | } 88 | } -------------------------------------------------------------------------------- /Sea of Thieves External/hacklib.cpp: -------------------------------------------------------------------------------- 1 | #include "hacklib.h" 2 | 3 | #undef UNICODE 4 | #include 5 | #define UNICODE 6 | 7 | namespace hacklib 8 | { 9 | SmartHandle::SmartHandle(HANDLE handle) 10 | { 11 | if (handle == INVALID_HANDLE_VALUE) handle = nullptr; 12 | this->_handle = nullptr; 13 | auto current_process = GetCurrentProcess(); 14 | DuplicateHandle(current_process, handle, current_process, &this->_handle, 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 15 | } 16 | 17 | SmartHandle &SmartHandle::operator=(SmartHandle &&other) noexcept 18 | { 19 | this->_handle = other._handle; 20 | other._handle = nullptr; 21 | return *this; 22 | } 23 | 24 | SmartHandle::~SmartHandle() 25 | { 26 | if (this->_handle) CloseHandle(this->_handle); 27 | } 28 | 29 | SmartHandle::operator HANDLE() 30 | { 31 | return this->_handle; 32 | } 33 | 34 | bool SmartHandle::is_valid() const 35 | { 36 | return this->_handle != nullptr; 37 | } 38 | 39 | DWORD find_process_pid(const std::string &process_name) 40 | { 41 | DWORD result = 0; 42 | SmartHandle snapshot{ CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) }; 43 | if (!snapshot.is_valid()) return result; 44 | PROCESSENTRY32 process_entry{ }; 45 | process_entry.dwSize = sizeof(process_entry); 46 | for (bool b = Process32First(snapshot, &process_entry); b; b = Process32Next(snapshot, &process_entry)) 47 | { 48 | if (process_name.compare(process_entry.szExeFile) == 0) 49 | { 50 | result = process_entry.th32ProcessID; 51 | break; 52 | } 53 | } 54 | return result; 55 | } 56 | 57 | bool Process::attach(DWORD access_mask) 58 | { 59 | this->_pid = find_process_pid(this->_name); 60 | if (!this->_pid) return false; 61 | this->_handle = SmartHandle{ OpenProcess(access_mask, FALSE, this->_pid) }; 62 | if (!this->_handle) return false; 63 | return true; 64 | } 65 | 66 | Module Process::get_module(const std::string &module_name) 67 | { 68 | if (this->_modules.count(module_name)) return this->_modules[module_name]; 69 | Module result{ nullptr, 0 }; 70 | SmartHandle snapshot{ CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, this->_pid) }; 71 | if (!snapshot.is_valid()) return result; 72 | MODULEENTRY32 module_entry{ }; 73 | module_entry.dwSize = sizeof(module_entry); 74 | for (bool b = Module32First(snapshot, &module_entry); b; b = Module32Next(snapshot, &module_entry)) 75 | { 76 | if (module_name.compare(module_entry.szModule) == 0) 77 | { 78 | result._base = module_entry.modBaseAddr; 79 | result._size = module_entry.dwSize; 80 | break; 81 | } 82 | } 83 | if (result._base) this->_modules[module_name] = result; 84 | return result; 85 | } 86 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sea of Thieves External 2 | ## ESP 3 | 4 |
5 | Players 6 | 7 | Draws player names colored according to their health. (Green = 100%, Red = 0%) 8 |
9 | 10 |
11 | Creatures 12 | 13 | * Chicken 14 | * Crab Ocean Crawler 15 | * Hermit Ocean Crawler 16 | * Megalodon 17 | * Mermaid 18 | * Phantom 19 | * Pig 20 | * Shark 21 | * Siren 22 | * Skeleton 23 | * Snake 24 |
25 | 26 |
27 | Ships 28 | 29 | Draws ship names. 30 |
31 | 32 |
33 | Treasure 34 | 35 | * Ammo Pouch 36 | * Ashen Castaway's Chest 37 | * Ashen Chest 38 | * Ashen Key 39 | * Ashes of the Damned 40 | * Bronze Secret-Keeper 41 | * Captain's Chest 42 | * Chest of Ancient Tributes 43 | * Chest of a Thousand Grogs 44 | * Chest of the Damned 45 | * Coral Message in a Bottle 46 | * Crate of Ancient Bone Dust 47 | * Crate of Exotic Silks 48 | * Crate of Exquisite Spices 49 | * Crate of Extraordinary Minerals 50 | * Crate of Fine Ore 51 | * Crate of Fine Sugar 52 | * Crate of Rare Tea 53 | * Disgraced Bounty Skull 54 | * Elaborate Flagon 55 | * Emerald Cursed Mermaid Statue 56 | * Emerald Mermaid Gem 57 | * Emerald Siren Gem 58 | * Foul Bounty Skull 59 | * Fruit Crate 60 | * Generous Gift 61 | * Gold Pouch 62 | * Golden Reliquary 63 | * Hateful Bounty Skull 64 | * Humble Gift 65 | * Marauder's Chest 66 | * Message in a Bottle 67 | * Mysterious Vessel 68 | * Ornate Carafe 69 | * Ritual Skull 70 | * Roaring Goblet 71 | * Ruby Cursed Mermaid Statue 72 | * Ruby Mermaid Gem 73 | * Ruby Siren Gem 74 | * Sapphire Cursed Mermaid Statue 75 | * Sapphire Mermaid Gem 76 | * Sapphire Siren Gem 77 | * Seafarer's Chest 78 | * Skeleton's Orders 79 | * Skull of the Damned 80 | * Stronghold Chest 81 | * Stronghold Gunpowder Barrel 82 | * Stronghold Key 83 | * Stronghold Skull 84 | * Tom of Curses 85 | * Tome of Fire 86 | * Tome of Resurrection 87 | * Treasure Chest 88 | * Trident of Dark Tides 89 | * Villainous Bounty Skull 90 |
91 | 92 |
93 | NPCs 94 | 95 | __Order of Souls__ 96 | * Oksana 97 | * Olga 98 | * Olive 99 | * Olivia 100 | * Olwen 101 | * Oprah 102 | * Oya 103 | 104 | __Gold Hoarder__ 105 | * Harry 106 | * Henry 107 | * Herbert 108 | * Horace 109 | * Hugh 110 | * Humphrey 111 | * Hyde 112 | 113 | __Merchant Alliance__ 114 | * Mandy 115 | * Matilda 116 | * Maureen 117 | * Mavis 118 | * Meg 119 | * Mildred 120 | * Mollie 121 | 122 | __Cargo Run__ 123 | * Charlotte 124 | 125 | __Sovereign__ 126 | * Cuthbert 127 | 128 | __Special__ 129 | * Ferryman 130 |
131 | 132 |
133 | Debug 134 | 135 | Displays the internal actor name of all actors inside of PersistentLevel->Actors. 136 |
137 | 138 | ## Known Bugs 139 | 140 | * ESP occasionally flickers 141 | 142 | 143 | ## Todo List 144 | 145 | * Switch from ImGui to DirectX (this project doesn't use any ImGui functionality except drawing shapes and text) 146 | * Complete NPC and treasure ESP -------------------------------------------------------------------------------- /Sea of Thieves External/menu.cpp: -------------------------------------------------------------------------------- 1 | #include "menu.h" 2 | 3 | #include "colors.h" 4 | 5 | namespace gui 6 | { 7 | Menu::Menu(const std::string &title, float x, float y) 8 | : _title(title) 9 | , _x(x) 10 | , _y(y) 11 | { 12 | } 13 | 14 | void Menu::setup_fonts() 15 | { 16 | this->_title_font = ImGui::GetIO().Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\verdana.ttf", 32.0f); 17 | this->_tab_font = ImGui::GetIO().Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\tahoma.ttf", 20.0f); 18 | } 19 | 20 | void Menu::set_position(float x, float y) 21 | { 22 | this->_x = x; 23 | this->_y = y; 24 | } 25 | 26 | void Menu::draw() const { 27 | if (!this->_visible) return; 28 | auto draw_list = ImGui::GetForegroundDrawList(); 29 | draw_list->AddRectFilled({ this->_x, this->_y }, { this->_x + this->_width, this->_y + this->_height }, colors::background_color, 1.0f); 30 | draw_list->AddRect({ this->_x, this->_y }, { this->_x + this->_width, this->_y + this->_height }, colors::foreground_color, 1.0f); 31 | ImGui::PushFont(this->_title_font); 32 | draw_list->AddText({ this->_x + 16, this->_y + 8}, IM_COL32_WHITE, "SoT External"); 33 | ImGui::PopFont(); 34 | draw_list->AddLine({ this->_x + 5, this->_y + 50 }, { this->_x + this->_width - 5, this->_y + 50 }, colors::foreground_color); 35 | ImGui::PushFont(this->_tab_font); 36 | for (auto i = 0; i < this->_tabs.size(); ++i) 37 | { 38 | const auto tab = this->_tabs[i]; 39 | tab->draw(this->_x, this->_y, i); 40 | } 41 | ImGui::PopFont(); 42 | } 43 | 44 | void Menu::process_key_input(int key_code) 45 | { 46 | if (key_code == VK_DELETE) 47 | { 48 | this->_visible = !this->_visible; 49 | return; 50 | } 51 | 52 | if (!this->_visible) return; 53 | 54 | if (key_code == VK_LEFT) 55 | { 56 | this->_tab_opened = false; 57 | this->get_selected_tab()->close(); 58 | return; 59 | } 60 | 61 | if (this->_tab_opened) 62 | { 63 | this->get_selected_tab()->process_key_input(key_code); 64 | return; 65 | } 66 | 67 | switch (key_code) 68 | { 69 | case VK_DOWN: 70 | this->select_next_tab(); 71 | break; 72 | case VK_UP: 73 | this->select_previous_tab(); 74 | break; 75 | case VK_RIGHT: 76 | this->_tab_opened = true; 77 | this->get_selected_tab()->open(); 78 | break; 79 | } 80 | } 81 | 82 | void Menu::add_tab(std::shared_ptr tab) 83 | { 84 | this->_tabs.push_back(tab); 85 | if (this->_tabs.size() == 1) this->get_selected_tab()->select(); 86 | } 87 | 88 | std::shared_ptr Menu::get_selected_tab() 89 | { 90 | return this->_tabs[this->_selected_tab]; 91 | } 92 | 93 | void Menu::select_next_tab() 94 | { 95 | this->get_selected_tab()->deselect(); 96 | ++this->_selected_tab; 97 | if (this->_selected_tab > this->_tabs.size() - 1) this->_selected_tab = 0; 98 | this->get_selected_tab()->select(); 99 | } 100 | 101 | void Menu::select_previous_tab() 102 | { 103 | this->get_selected_tab()->deselect(); 104 | --this->_selected_tab; 105 | if (this->_selected_tab < 0) this->_selected_tab = static_cast(this->_tabs.size()) - 1; 106 | this->get_selected_tab()->select(); 107 | } 108 | } -------------------------------------------------------------------------------- /Sea of Thieves External/imgui/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] 7 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 8 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 14 | 15 | #pragma once 16 | #include "imgui.h" // IMGUI_IMPL_API 17 | 18 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 19 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 20 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 21 | 22 | // Win32 message handler your application need to call. 23 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 24 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 25 | // - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. 26 | 27 | #if 0 28 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 29 | #endif 30 | 31 | // DPI-related helpers (optional) 32 | // - Use to enable DPI awareness without having to create an application manifest. 33 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 34 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 35 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 36 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 37 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 38 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 39 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 40 | 41 | // Transparency related helpers (optional) [experimental] 42 | // - Use to enable alpha compositing transparency with the desktop. 43 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 44 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 45 | -------------------------------------------------------------------------------- /Sea of Thieves External/sot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "hacklib.h" 8 | #include "offsets.h" 9 | #include "sdk.h" 10 | 11 | namespace cheat 12 | { 13 | class SOT 14 | { 15 | public: 16 | enum class ActorType 17 | { 18 | //Players 19 | PLAYER_PIRATE = 0, 20 | 21 | //NPCs 22 | OOS_OPRAH, OOS_OLIVE, OOS_MADAME_OLWEN, OOS_OLIVIA, OOS_OKSANA, OOS_OLGA, OOS_OYA, 23 | GHD_HORACE, GHD_HUMPHREY, GHD_HERBERT, GHD_HARRY, GHD_HENRY, GHD_HUGH, GHD_HYDE, 24 | MCH_MANDY, MCH_MOLLIE, MCH_MILDRED, MCH_MEG, MCH_MAVIS, MCH_MAUREEN, MCH_MATILDA, 25 | CGR_CHARLOTTE, 26 | SVN_1, 27 | GHOST_SHIP_CAPTAIN, 28 | 29 | //Ships 30 | S_SHIP_TEMPLATE, M_SHIP_TEMPLATE, L_SHIP_TEMPLATE, 31 | 32 | //Creatures 33 | MERMAID, PIG, CHICKEN, SNAKE, SHARK, SKELETON, PHANTOM, OCEAN_CRAWLER_HERMIT, 34 | OCEAN_CRAWLER_CRAB, OCEAN_CRAWLER_EELECTRIC, GIANT_SKELETON, TINY_SHARK, SIREN, 35 | 36 | //Treasure chests 37 | COLLECTORS_CHEST, LG_TREASURE_CHEST, MY_TREASURE_CHEST, RA_TREASURE_CHEST, TREASURE_CHEST_FORT, ANCIENT_COLLECTORS_CHEST, ASHEN_CHEST_COLLECTORS_CHEST, 38 | TREASURE_CHEST_CM_DVR, CURSED_VOYAGE_CHEST, GHOST_TREASURE_CHEST, DRUNKEN_TREASURE_CHEST, 39 | 40 | //Crates 41 | MCH_CRATE_COMMODITY_FORT, MCH_CRATE_COMMODITY_MINERALS, MCH_CRATE_COMMODITY_SILK_CRATE, MCH_CRATE_COMMODITY_SUGAR_CRATE, MCH_COMMODITY_SPICE_CRATE, MCH_COMMODITY_TEA_CRATE, 42 | MCH_CRATE_COMMODITY_GHOST_CRATE, MCH_CRATE_COMMODITY_ORE, 43 | 44 | //Skulls 45 | MY_BOUNTY_REWARD_SKULL, LG_BOUNTY_REWARD_SKULL, CM_BOUNTY_REWARD_SKULL, FORT_BOUNTY_REWARD_SKULL, 46 | RARE_DVR_BOUNTY_REWARD_SKULL, CM_GHOST_BOUNTY_REWARD_SKULL, 47 | 48 | //Treasure items 49 | SIREN_TRIDENT, B_GUNPOWDER_BARREL, LOW_VALUE_GIFT, HIGH_VALUE_GIFT, RITUAL_SKULL, SKELETON_ORDERS, 50 | GOLD_POUCH, ASHEN_KEY, STRONGHOLD_KEY, 51 | MERMAID_GEM_RUBY, MERMAID_GEM_EMERALD, MERMAID_GEM_SAPPHIRE, SUNKEN_CURSE_RUBY, SUNKEN_CURSE_EMERALD, SUNKEN_CURSE_SAPPHIRE, 52 | SIREN_GEM_RUBY, SIREN_GEM_EMERALD, SIREN_GEM_SAPPHIRE, 53 | AMMO_POUCH, RA_BOUNTY_REWARD_SKULL, MESSAGE_IN_A_BOTTLE, CORAL_MESSAGE_IN_A_BOTTLE, BANANA_CRATE, 54 | 55 | //Tomes 56 | ASHEN_TOME_VOL4_05, ASHEN_TOME_VOL4_04, ASHEN_TOME_VOL4_03, ASHEN_TOME_VOL4_02, ASHEN_TOME_VOL4_01, 57 | ASHEN_TOME_VOL3_05, ASHEN_TOME_VOL3_04, ASHEN_TOME_VOL3_03, ASHEN_TOME_VOL3_02, ASHEN_TOME_VOL3_01, 58 | ASHEN_TOME_VOL1_05, ASHEN_TOME_VOL1_04, ASHEN_TOME_VOL1_03, ASHEN_TOME_VOL1_02, ASHEN_TOME_VOL1_01, 59 | 60 | //Artifacts 61 | TREASURE_ARTIFACT_VASE_01, TREASURE_ARTIFACT_VASE_02, TREASURE_ARTIFACT_VASE_03, 62 | TREASURE_ARTIFACT_BOX_01, TREASURE_ARTIFACT_BOX_02, TREASURE_ARTIFACT_BOX_03, 63 | TREASURE_ARTIFACT_GOBLET_02, 64 | TREASURE_ARTIFACT_DVR_COMMON, TREASURE_ARTIFACT_DVR_RARE, 65 | 66 | UNKNOWN 67 | }; 68 | 69 | bool init(); 70 | hacklib::Process *process(); 71 | 72 | sdk::UWorld world(); 73 | void *names(); 74 | std::string get_actor_name(int id); 75 | ActorType get_actor_type(int id); 76 | 77 | //https://github.com/DougTheDruid/SoT-ESP-Framework/blob/main/helpers.py#L71-L161 78 | bool world_to_screen(const sdk::FMinimalViewInfo &camera_pov, sdk::Vector3 &position, sdk::Vector2 *out); 79 | 80 | private: 81 | hacklib::Process _process{ "SoTGame.exe" }; 82 | char *_process_base = nullptr; 83 | std::unordered_map _actor_id_map{ }; 84 | }; 85 | 86 | SOT *game(); 87 | } -------------------------------------------------------------------------------- /Sea of Thieves External/overlay.cpp: -------------------------------------------------------------------------------- 1 | #include "overlay.h" 2 | 3 | #include 4 | 5 | #include "imgui/imgui_impl_dx11.h" 6 | #include "imgui/imgui_impl_win32.h" 7 | 8 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 9 | 10 | namespace gui 11 | { 12 | constexpr int listen_keys[] = { VK_DELETE, VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_RETURN }; 13 | bool quit_requested = false; 14 | 15 | Overlay::Overlay(HINSTANCE instance, const std::string &title, HWND target_window, int cmd_show) 16 | : _title(title) 17 | , _target_window(target_window) 18 | , _menu(title, 30.0f, 30.0f) 19 | { 20 | this->setup_window(instance); 21 | this->setup_direct3D(); 22 | ShowWindow(this->_window, cmd_show); 23 | UpdateWindow(this->_window); 24 | ImGui::CreateContext(); 25 | this->_menu.setup_fonts(); 26 | ImGui_ImplWin32_Init(this->_window); 27 | ImGui_ImplDX11_Init(this->_device, this->_context); 28 | } 29 | 30 | Menu &Overlay::menu() 31 | { 32 | return this->_menu; 33 | } 34 | 35 | void Overlay::add_draw_callback(DrawCallbackFn callback_fn) 36 | { 37 | this->_callbacks.push_back(callback_fn); 38 | } 39 | 40 | void Overlay::window_loop() 41 | { 42 | while (!quit_requested) 43 | { 44 | MSG msg{ }; 45 | while (PeekMessageA(&msg, this->_window, 0, 0, PM_REMOVE)) 46 | { 47 | TranslateMessage(&msg); 48 | DispatchMessageA(&msg); 49 | } 50 | 51 | RECT target_rect{ }; 52 | GetWindowRect(this->_target_window, &target_rect); 53 | MoveWindow(this->_window, target_rect.left, target_rect.top, target_rect.right - target_rect.left, target_rect.bottom - target_rect.top, TRUE); 54 | ImGui_ImplWin32_NewFrame(); 55 | ImGui_ImplDX11_NewFrame(); 56 | ImGui::NewFrame(); 57 | if (GetForegroundWindow() == this->_target_window) 58 | { 59 | for (int key_code : listen_keys) 60 | { 61 | if (GetAsyncKeyState(key_code) & 1) this->_menu.process_key_input(key_code); 62 | } 63 | this->_menu.draw(); 64 | for (const DrawCallbackFn &callback_fn : this->_callbacks) 65 | { 66 | callback_fn(); 67 | } 68 | } 69 | ImGui::Render(); 70 | this->_context->OMSetRenderTargets(1, &this->_rt_view, nullptr); 71 | this->_context->ClearRenderTargetView(this->_rt_view, this->_clear_color); 72 | ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); 73 | this->_swap_chain->Present(1, 0); 74 | Sleep(1); 75 | } 76 | 77 | ImGui_ImplDX11_Shutdown(); 78 | ImGui_ImplWin32_Shutdown(); 79 | ImGui::DestroyContext(); 80 | if (this->_swap_chain) this->_swap_chain->Release(); 81 | if (this->_device) this->_device->Release(); 82 | if (this->_context) this->_context->Release(); 83 | if (this->_rt_view) this->_rt_view->Release(); 84 | DestroyWindow(this->_window); 85 | UnregisterClassA(this->_window_class.lpszClassName, this->_window_class.hInstance); 86 | exit(0); 87 | } 88 | 89 | LRESULT Overlay::window_procedure(HWND window, UINT msg, WPARAM param1, LPARAM param2) 90 | { 91 | LRESULT result = ImGui_ImplWin32_WndProcHandler(window, msg, param1, param2); 92 | if (result) return result; 93 | 94 | switch (msg) 95 | { 96 | case WM_DESTROY: 97 | quit_requested = true; 98 | PostQuitMessage(0); 99 | return 0; 100 | } 101 | 102 | return DefWindowProcA(window, msg, param1, param2); 103 | } 104 | 105 | void Overlay::setup_window(HINSTANCE instance) 106 | { 107 | auto size = sizeof(this->_window_class); 108 | memset(&this->_window_class, 0, size); 109 | this->_window_class.cbSize = static_cast(size); 110 | this->_window_class.style = CS_HREDRAW | CS_VREDRAW; 111 | this->_window_class.lpfnWndProc = Overlay::window_procedure; 112 | this->_window_class.hInstance = instance; 113 | this->_window_class.lpszClassName = "1337"; 114 | RegisterClassExA(&this->_window_class); 115 | this->_window = CreateWindowExA( 116 | WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED, this->_window_class.lpszClassName, 117 | this->_title.c_str(), 118 | WS_POPUP, 119 | 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 120 | nullptr, nullptr, instance, nullptr 121 | ); 122 | SetLayeredWindowAttributes(this->_window, RGB(0, 0, 0), 255, LWA_ALPHA); 123 | RECT window_rect{ }; 124 | GetWindowRect(this->_window, &window_rect); 125 | RECT client_rect{ }; 126 | GetClientRect(this->_window, &client_rect); 127 | POINT offset{ 0, 0 }; 128 | ClientToScreen(this->_window, &offset); 129 | MARGINS margins{ offset.x, offset.y, client_rect.top, client_rect.bottom }; 130 | DwmExtendFrameIntoClientArea(this->_window, &margins); 131 | } 132 | 133 | void Overlay::setup_direct3D() 134 | { 135 | DXGI_SWAP_CHAIN_DESC desc{ }; 136 | desc.BufferDesc.RefreshRate.Numerator = 60; 137 | desc.BufferDesc.RefreshRate.Denominator = 1; 138 | desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 139 | desc.SampleDesc.Count = 1; 140 | desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 141 | desc.BufferCount = 2; 142 | desc.OutputWindow = this->_window; 143 | desc.Windowed = true; 144 | desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 145 | desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; 146 | 147 | D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0 }; 148 | D3D_FEATURE_LEVEL level{ }; 149 | 150 | D3D11CreateDeviceAndSwapChain( 151 | nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, levels, 1, D3D11_SDK_VERSION, 152 | &desc, &this->_swap_chain, &this->_device, &level, &this->_context 153 | ); 154 | ID3D11Texture2D *back_buffer = nullptr; 155 | this->_swap_chain->GetBuffer(0, IID_PPV_ARGS(&back_buffer)); 156 | this->_device->CreateRenderTargetView(back_buffer, nullptr, &this->_rt_view); 157 | back_buffer->Release(); 158 | } 159 | } -------------------------------------------------------------------------------- /Sea of Thieves External/Sea of Thieves External.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {57507802-82c9-4009-ad22-03e1496290c7} 18 | 19 | 20 | {c96e4542-0f80-4642-b9f9-4434da993917} 21 | 22 | 23 | {8feaec85-747e-4ec2-af40-1d39899e130b} 24 | 25 | 26 | {439ffeb7-c394-44c5-ae1d-b5d5c13a7641} 27 | 28 | 29 | {a78445b3-ec92-4c62-9b31-4ad5c5fb0243} 30 | 31 | 32 | {fd71fd89-b00c-403d-a8ae-8bba77969873} 33 | 34 | 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files\imgui 41 | 42 | 43 | Header Files\imgui 44 | 45 | 46 | Header Files\imgui 47 | 48 | 49 | Header Files\imgui 50 | 51 | 52 | Header Files\imgui 53 | 54 | 55 | Header Files\imgui 56 | 57 | 58 | Header Files\imgui 59 | 60 | 61 | Header Files\imgui 62 | 63 | 64 | Header Files\gui 65 | 66 | 67 | Header Files\gui 68 | 69 | 70 | Header Files\gui 71 | 72 | 73 | Header Files\gui 74 | 75 | 76 | Header Files\gui 77 | 78 | 79 | Header Files 80 | 81 | 82 | Header Files 83 | 84 | 85 | Header Files\cheats 86 | 87 | 88 | Header Files 89 | 90 | 91 | Header Files 92 | 93 | 94 | Header Files 95 | 96 | 97 | 98 | 99 | Source Files 100 | 101 | 102 | Source Files 103 | 104 | 105 | Source Files\imgui 106 | 107 | 108 | Source Files\imgui 109 | 110 | 111 | Source Files\imgui 112 | 113 | 114 | Source Files\imgui 115 | 116 | 117 | Source Files\imgui 118 | 119 | 120 | Source Files\imgui 121 | 122 | 123 | Source Files\gui 124 | 125 | 126 | Source Files\gui 127 | 128 | 129 | Source Files\gui 130 | 131 | 132 | Source Files\gui 133 | 134 | 135 | Source Files 136 | 137 | 138 | Source Files\cheats 139 | 140 | 141 | Source Files 142 | 143 | 144 | Source Files 145 | 146 | 147 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /Sea of Thieves External/sdk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include "hacklib.h" 7 | #include "offsets.h" 8 | 9 | namespace sdk 10 | { 11 | bool init(hacklib::Process *process); 12 | hacklib::Process *process(); 13 | 14 | class Vector3 15 | { 16 | public: 17 | Vector3() 18 | { 19 | memset(this, 0, sizeof(this)); 20 | } 21 | 22 | Vector3(float x, float y, float z) 23 | : _x(x) 24 | , _y(y) 25 | , _z(z) 26 | { 27 | } 28 | 29 | float dot(const Vector3 &other) const 30 | { 31 | return this->_x * other._x + this->_y * other._y + this->_z * other._z; 32 | } 33 | 34 | Vector3 operator*(float scalar) const 35 | { 36 | return Vector3{ this->_x * scalar, this->_y * scalar, this->_z * scalar }; 37 | } 38 | 39 | Vector3 operator-(const Vector3 &other) 40 | { 41 | return Vector3{ this->_x - other._x, this->_y - other._y, this->_z - other._z }; 42 | } 43 | 44 | float _x; 45 | float _y; 46 | float _z; 47 | }; 48 | 49 | class Vector2 50 | { 51 | public: 52 | Vector2() 53 | { 54 | memset(this, 0, sizeof(this)); 55 | } 56 | 57 | Vector2(float x, float y) 58 | : _x(x) 59 | , _y(y) 60 | { 61 | } 62 | 63 | float _x; 64 | float _y; 65 | }; 66 | 67 | class Matrix3x3 68 | { 69 | public: 70 | Matrix3x3() 71 | { 72 | memset(this, 0, sizeof(this)); 73 | } 74 | 75 | float *operator[](int index) 76 | { 77 | return this->_values[index]; 78 | } 79 | private: 80 | float _values[3][3]; 81 | }; 82 | 83 | class ExternalObject abstract 84 | { 85 | public: 86 | ExternalObject(void *instance) 87 | : _instance(instance) 88 | { 89 | } 90 | 91 | ExternalObject() 92 | : _instance(nullptr) 93 | { 94 | } 95 | 96 | void *instance() const 97 | { 98 | return this->_instance; 99 | } 100 | 101 | template 102 | T read_member(uint32_t offset) const 103 | { 104 | return process()->read_memory(static_cast(this->_instance) + offset); 105 | } 106 | 107 | protected: 108 | void *_instance; 109 | }; 110 | 111 | #define EXTERN_OBJECT_CCTOR(class_name) class_name() : ExternalObject() {} class_name(void *instance) : ExternalObject(instance) {} 112 | 113 | template 114 | class TArray : public ExternalObject 115 | { 116 | public: 117 | EXTERN_OBJECT_CCTOR(TArray); 118 | 119 | std::vector get_data(int size) const 120 | { 121 | void *data = process()->read_memory(this->_instance); 122 | std::vector result{ }; 123 | result.resize(size); 124 | process()->read_memory(data, result.data(), size * sizeof(T)); 125 | return result; 126 | } 127 | 128 | int array_num() const 129 | { 130 | return this->read_member(0x8); 131 | } 132 | 133 | int array_max() const 134 | { 135 | return this->read_member(0xC); 136 | } 137 | }; 138 | /* 139 | * ================================================================ 140 | */ 141 | class FString : public ExternalObject 142 | { 143 | public: 144 | EXTERN_OBJECT_CCTOR(FString); 145 | 146 | TArray data() const 147 | { 148 | return TArray{ this->_instance }; 149 | } 150 | }; 151 | /* 152 | * ================================================================ 153 | */ 154 | class FMinimalViewInfo : public ExternalObject 155 | { 156 | public: 157 | EXTERN_OBJECT_CCTOR(FMinimalViewInfo); 158 | 159 | Vector3 location() const 160 | { 161 | return this->read_member(offsets::Location); 162 | } 163 | 164 | Vector3 rotation() const 165 | { 166 | return this->read_member(offsets::Rotation); 167 | } 168 | 169 | float fov() const 170 | { 171 | return this->read_member(offsets::FOV); 172 | } 173 | }; 174 | 175 | /* 176 | * ================================================================ 177 | */ 178 | class FCameraCacheEntry : public ExternalObject 179 | { 180 | public: 181 | EXTERN_OBJECT_CCTOR(FCameraCacheEntry); 182 | 183 | FMinimalViewInfo pov() const 184 | { 185 | return FMinimalViewInfo{ static_cast(this->_instance) + offsets::POV }; 186 | } 187 | }; 188 | 189 | /* 190 | * ================================================================ 191 | */ 192 | class APlayerCameraManager : public ExternalObject 193 | { 194 | public: 195 | EXTERN_OBJECT_CCTOR(APlayerCameraManager); 196 | 197 | FCameraCacheEntry camera_cache() const 198 | { 199 | return FCameraCacheEntry{ static_cast(this->_instance) + offsets::CameraCache }; 200 | } 201 | }; 202 | /* 203 | * ================================================================ 204 | */ 205 | class APlayerState : public ExternalObject 206 | { 207 | public: 208 | EXTERN_OBJECT_CCTOR(APlayerState); 209 | 210 | FString player_name() const 211 | { 212 | return FString{ static_cast(this->_instance) + offsets::PlayerName }; 213 | } 214 | }; 215 | /* 216 | * ================================================================ 217 | */ 218 | class APawn : public ExternalObject 219 | { 220 | public: 221 | EXTERN_OBJECT_CCTOR(APawn); 222 | 223 | APlayerState player_state() const 224 | { 225 | return this->read_member(offsets::PlayerState); 226 | } 227 | }; 228 | class USceneComponent : public ExternalObject 229 | { 230 | public: 231 | EXTERN_OBJECT_CCTOR(USceneComponent); 232 | 233 | Vector3 relative_location() const 234 | { 235 | return this->read_member(offsets::RelativeLocation); 236 | } 237 | }; 238 | /* 239 | * ================================================================ 240 | */ 241 | class AActor : public APawn 242 | { 243 | public: 244 | AActor(void *instance) 245 | : APawn(instance) 246 | { 247 | } 248 | 249 | AActor() 250 | : APawn(nullptr) 251 | { 252 | } 253 | 254 | int id() const 255 | { 256 | return this->read_member(0x18); 257 | } 258 | 259 | USceneComponent root_component() const 260 | { 261 | return this->read_member(offsets::RootComponent); 262 | } 263 | 264 | TArray children() 265 | { 266 | return TArray{ static_cast(this->_instance) + offsets::Children }; 267 | } 268 | }; 269 | /* 270 | * ================================================================ 271 | */ 272 | class UHealthComponent : public ExternalObject 273 | { 274 | public: 275 | EXTERN_OBJECT_CCTOR(UHealthComponent); 276 | 277 | float max_health() const 278 | { 279 | return this->read_member(offsets::MaxHealth); 280 | } 281 | 282 | float current_health() const 283 | { 284 | return this->read_member(offsets::CurrentHealthInfo + offsets::Health); 285 | } 286 | }; 287 | /* 288 | * ================================================================ 289 | */ 290 | class AAthenaCharacter : public AActor 291 | { 292 | public: 293 | AAthenaCharacter(void *instance) 294 | : AActor(instance) 295 | { 296 | } 297 | 298 | UHealthComponent health_component() const 299 | { 300 | return this->read_member(offsets::HealthComponent); 301 | } 302 | }; 303 | /* 304 | * ================================================================ 305 | */ 306 | class APlayerController : public ExternalObject 307 | { 308 | public: 309 | EXTERN_OBJECT_CCTOR(APlayerController); 310 | 311 | APlayerCameraManager player_camera_manager() const 312 | { 313 | return this->read_member(offsets::PlayerCameraManager); 314 | } 315 | 316 | APawn acknowledged_pawn() const 317 | { 318 | return this->read_member(offsets::AcknowledgedPawn); 319 | } 320 | }; 321 | /* 322 | * ================================================================ 323 | */ 324 | class UPlayer : public ExternalObject 325 | { 326 | public: 327 | EXTERN_OBJECT_CCTOR(UPlayer); 328 | 329 | APlayerController player_controller() const 330 | { 331 | return this->read_member(offsets::PlayerController); 332 | } 333 | }; 334 | /* 335 | * ================================================================ 336 | */ 337 | class UGameInstance : public ExternalObject 338 | { 339 | public: 340 | EXTERN_OBJECT_CCTOR(UGameInstance); 341 | 342 | UPlayer local_player() const 343 | { 344 | UPlayer *local_players = this->read_member(offsets::LocalPlayers); 345 | return process()->read_memory(local_players + 0); 346 | } 347 | }; 348 | /* 349 | * ================================================================ 350 | */ 351 | class ULevel : public ExternalObject 352 | { 353 | public: 354 | EXTERN_OBJECT_CCTOR(ULevel); 355 | 356 | TArray actors() const 357 | { 358 | return TArray{ static_cast(this->_instance) + offsets::Actors }; 359 | } 360 | }; 361 | /* 362 | * ================================================================ 363 | */ 364 | class UWorld : public ExternalObject 365 | { 366 | public: 367 | EXTERN_OBJECT_CCTOR(UWorld); 368 | 369 | UGameInstance owning_game_instance() const 370 | { 371 | return this->read_member(offsets::OwningGameInstance); 372 | }; 373 | 374 | ULevel persistent_level() const 375 | { 376 | return this->read_member(offsets::PersistentLevel); 377 | } 378 | }; 379 | 380 | #undef EXTERN_OBJECT_CCTOR 381 | } -------------------------------------------------------------------------------- /Sea of Thieves External/Sea of Thieves External.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {f1d01f09-0bad-43c3-a8c8-2328e5c861f9} 25 | SeaofThievesExternal 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Windows 122 | true 123 | d3d11.lib;%(AdditionalDependencies) 124 | 125 | 126 | 127 | 128 | Level3 129 | true 130 | true 131 | true 132 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 133 | true 134 | 135 | 136 | Windows 137 | true 138 | true 139 | true 140 | d3d11.lib;%(AdditionalDependencies) 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /Sea of Thieves External/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/rebased branch with your modifications to it) 7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. 8 | //----------------------------------------------------------------------------- 9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp 10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 12 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. 13 | //----------------------------------------------------------------------------- 14 | 15 | #pragma once 16 | 17 | //---- Define assertion handler. Defaults to calling assert(). 18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. 19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 21 | 22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 23 | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. 24 | // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() 25 | // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. 26 | //#define IMGUI_API __declspec( dllexport ) 27 | //#define IMGUI_API __declspec( dllimport ) 28 | 29 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. 30 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 31 | //#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions. 32 | 33 | //---- Disable all of Dear ImGui or don't implement standard windows/tools. 34 | // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp. 35 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. 36 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. 37 | //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88). 38 | 39 | //---- Don't implement some functions to reduce linkage requirements. 40 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) 41 | //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) 42 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) 43 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). 44 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). 45 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) 46 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. 47 | //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) 48 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. 49 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). 50 | //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available 51 | 52 | //---- Include imgui_user.h at the end of imgui.h as a convenience 53 | //#define IMGUI_INCLUDE_IMGUI_USER_H 54 | 55 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 56 | //#define IMGUI_USE_BGRA_PACKED_COLOR 57 | 58 | //---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) 59 | //#define IMGUI_USE_WCHAR32 60 | 61 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 62 | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. 63 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 64 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 65 | //#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled 66 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 67 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 68 | 69 | //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) 70 | // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h. 71 | //#define IMGUI_USE_STB_SPRINTF 72 | 73 | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) 74 | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). 75 | // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. 76 | //#define IMGUI_ENABLE_FREETYPE 77 | 78 | //---- Use stb_truetype to build and rasterize the font atlas (default) 79 | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. 80 | //#define IMGUI_ENABLE_STB_TRUETYPE 81 | 82 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 83 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 84 | /* 85 | #define IM_VEC2_CLASS_EXTRA \ 86 | constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \ 87 | operator MyVec2() const { return MyVec2(x,y); } 88 | 89 | #define IM_VEC4_CLASS_EXTRA \ 90 | constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \ 91 | operator MyVec4() const { return MyVec4(x,y,z,w); } 92 | */ 93 | //---- ...Or use Dear ImGui's own very basic math operators. 94 | //#define IMGUI_DEFINE_MATH_OPERATORS 95 | 96 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. 97 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). 98 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. 99 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 100 | //#define ImDrawIdx unsigned int 101 | 102 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) 103 | //struct ImDrawList; 104 | //struct ImDrawCmd; 105 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 106 | //#define ImDrawCallback MyImDrawCallback 107 | 108 | //---- Debug Tools: Macro to break in Debugger 109 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) 110 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 111 | //#define IM_DEBUG_BREAK __debugbreak() 112 | 113 | //---- Debug Tools: Enable slower asserts 114 | //#define IMGUI_DEBUG_PARANOID 115 | 116 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 117 | /* 118 | namespace ImGui 119 | { 120 | void MyFunction(const char* name, const MyMatrix44& v); 121 | } 122 | */ 123 | -------------------------------------------------------------------------------- /Sea of Thieves External/sot.cpp: -------------------------------------------------------------------------------- 1 | #include "sot.h" 2 | 3 | #include 4 | 5 | #include "sdk.h" 6 | 7 | namespace cheat 8 | { 9 | constexpr const DWORD access_mask = PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION; 10 | constexpr const float pi = 3.141592f; 11 | 12 | SOT _game{ }; 13 | 14 | const std::unordered_map _actor_name_map 15 | { 16 | { "BP_PlayerPirate_C", SOT::ActorType::PLAYER_PIRATE }, 17 | 18 | { "BP_OrderOfSouls_Oprah_C", SOT::ActorType::OOS_OPRAH }, 19 | { "BP_Orderofsouls_Olive_C", SOT::ActorType::OOS_OLIVE }, 20 | { "BP_Orderofsouls_MadameOlwen_C", SOT::ActorType::OOS_MADAME_OLWEN }, 21 | { "BP_Orderofsouls_Olivia_C", SOT::ActorType::OOS_OLIVIA }, 22 | { "BP_Orderofsouls_Oksana_C", SOT::ActorType::OOS_OKSANA }, 23 | { "BP_Orderofsouls_Olga_C", SOT::ActorType::OOS_OLGA }, 24 | { "BP_OrderOfSouls_Oya_C", SOT::ActorType::OOS_OYA }, 25 | 26 | { "BP_Goldhoarder_Horace_C", SOT::ActorType::GHD_HORACE }, 27 | { "BP_Goldhoarder_Humphrey_C", SOT::ActorType::GHD_HUMPHREY }, 28 | { "BP_Goldhoarder_Herbert_C", SOT::ActorType::GHD_HERBERT }, 29 | { "BP_Goldhoarder_Harry_C", SOT::ActorType::GHD_HARRY }, 30 | { "BP_Goldhoarder_Henry_C", SOT::ActorType::GHD_HENRY }, 31 | { "BP_Goldhoarder_Hugh_C", SOT::ActorType::GHD_HUGH }, 32 | { "BP_Goldhoarder_Hyde_C", SOT::ActorType::GHD_HYDE }, 33 | 34 | { "BP_Merchant_Mandy_C", SOT::ActorType::MCH_MANDY }, 35 | { "BP_Merchant_Mollie_C", SOT::ActorType::MCH_MOLLIE }, 36 | { "BP_Merchant_Mildred_C", SOT::ActorType::MCH_MILDRED }, 37 | { "BP_Merchant_Meg_C", SOT::ActorType::MCH_MEG }, 38 | { "BP_Merchant_Mavis_C", SOT::ActorType::MCH_MAVIS }, 39 | { "BP_Merchant_Maureen_C", SOT::ActorType::MCH_MAUREEN }, 40 | { "BP_Merchant_DVR_C", SOT::ActorType::MCH_MATILDA }, 41 | 42 | { "BP_Cargorun_Charlotte_C", SOT::ActorType::CGR_CHARLOTTE }, 43 | 44 | { "BP_Sovereign_bsp_1_C", SOT::ActorType::SVN_1 }, 45 | 46 | { "BP_GhostShipCaptain_C", SOT::ActorType::GHOST_SHIP_CAPTAIN }, 47 | 48 | { "BP_SmallShipTemplate_C", SOT::ActorType::S_SHIP_TEMPLATE }, 49 | { "BP_SmallShipNetProxy_C", SOT::ActorType::S_SHIP_TEMPLATE }, 50 | { "BP_MediumShipTemplate_C", SOT::ActorType::M_SHIP_TEMPLATE }, 51 | { "BP_MediumShipNetProxy_C", SOT::ActorType::M_SHIP_TEMPLATE }, 52 | { "BP_LargeShipTemplate_C", SOT::ActorType::L_SHIP_TEMPLATE }, 53 | { "BP_LargeShipNetProxy_C", SOT::ActorType::L_SHIP_TEMPLATE }, 54 | 55 | { "BP_Mermaid_C", SOT::ActorType::MERMAID }, 56 | 57 | { "BP_Pig_Common_C", SOT::ActorType::PIG }, 58 | { "BP_Pig_Rare_C", SOT::ActorType::PIG }, 59 | { "BP_Pig_Legendary_C", SOT::ActorType::PIG }, 60 | { "BP_Pig_Mythical_C", SOT::ActorType::PIG }, 61 | 62 | { "BP_Chicken_Common_C", SOT::ActorType::CHICKEN }, 63 | { "BP_Chicken_Rare_C", SOT::ActorType::CHICKEN }, 64 | { "BP_Chicken_Legendary_C", SOT::ActorType::CHICKEN }, 65 | { "BP_Chicken_Mythical_C", SOT::ActorType::CHICKEN }, 66 | 67 | { "BP_Snake_Common_C", SOT::ActorType::SNAKE }, 68 | { "BP_Snake_Rare_C", SOT::ActorType::SNAKE }, 69 | { "BP_Snake_Legendary_C", SOT::ActorType::SNAKE }, 70 | { "BP_Snake_Mythical_C", SOT::ActorType::SNAKE }, 71 | 72 | { "BP_Shark_C", SOT::ActorType::SHARK }, 73 | { "BP_TinyShark_C", SOT::ActorType::TINY_SHARK }, 74 | 75 | { "BP_SkeletonPawnBase_C", SOT::ActorType::SKELETON }, 76 | { "BP_PhantomPawnBase_C", SOT::ActorType::PHANTOM }, 77 | { "BP_SirenPawnBase_C", SOT::ActorType::SIREN }, 78 | 79 | { "BP_OceanCrawlerCharacter_Hermit_C", SOT::ActorType::OCEAN_CRAWLER_HERMIT }, 80 | { "BP_OceanCrawlerCharacter_Crab_C", SOT::ActorType::OCEAN_CRAWLER_CRAB }, 81 | { "BP_OceanCrawlerCharacter_Eelectric_C", SOT::ActorType::OCEAN_CRAWLER_EELECTRIC }, 82 | 83 | { "BP_SirenTrident_Proxy_C", SOT::ActorType::SIREN_TRIDENT }, 84 | { "BP_MerchantCrate_BigGunpowderBarrelProxy_C", SOT::ActorType::B_GUNPOWDER_BARREL }, 85 | { "BP_LowValueGift_Proxy_C", SOT::ActorType::LOW_VALUE_GIFT }, 86 | { "BP_HighValueGift_Proxy_C", SOT::ActorType::HIGH_VALUE_GIFT }, 87 | { "BP_Ritual_Skull_Proxy_C", SOT::ActorType::RITUAL_SKULL }, 88 | { "BP_BountyRewardSkull_Proxy_Mythical_C", SOT::ActorType::MY_BOUNTY_REWARD_SKULL }, 89 | { "BP_SkeletonOrders_Proxy_C", SOT::ActorType::SKELETON_ORDERS }, 90 | { "BP_EmergentGoldPouchProxy_C", SOT::ActorType::GOLD_POUCH }, 91 | { "BP_TreasureChest_Proxy_Mythical_C", SOT::ActorType::MY_TREASURE_CHEST }, 92 | { "BP_ShipwreckTreasureChest_Proxy_Mythical_C", SOT::ActorType::MY_TREASURE_CHEST }, 93 | { "BP_TreasureChest_Proxy_Rare_C", SOT::ActorType::RA_TREASURE_CHEST }, 94 | { "BP_ShipwreckTreasureChest_Proxy_Rare_C", SOT::ActorType::RA_TREASURE_CHEST }, 95 | { "BP_AncientCollectorsChest_Proxy_C", SOT::ActorType::ANCIENT_COLLECTORS_CHEST }, 96 | { "BP_AshenChestCollectorsChest_Proxy_C", SOT::ActorType::ASHEN_CHEST_COLLECTORS_CHEST }, 97 | { "BP_AshenKey_Proxy_C", SOT::ActorType::ASHEN_KEY }, 98 | { "BP_StrongholdKey_Proxy_C", SOT::ActorType::STRONGHOLD_KEY }, 99 | { "BP_CollectorsChest_Proxy_C", SOT::ActorType::COLLECTORS_CHEST }, 100 | { "BP_MermaidGem_Proxy_Ruby_C", SOT::ActorType::MERMAID_GEM_RUBY }, 101 | { "BP_MermaidGem_Proxy_Emerald_C", SOT::ActorType::MERMAID_GEM_EMERALD }, 102 | { "BP_MermaidGem_Proxy_Sapphire_C", SOT::ActorType::MERMAID_GEM_SAPPHIRE }, 103 | { "BP_SirenGem_Proxy_Ruby_C", SOT::ActorType::SIREN_GEM_RUBY }, 104 | { "BP_SirenGem_Proxy_Emerald_C", SOT::ActorType::SIREN_GEM_EMERALD }, 105 | { "BP_SirenGem_Proxy_Sapphire_C", SOT::ActorType::SIREN_GEM_SAPPHIRE }, 106 | { "BP_AmmoPouchProxy_C", SOT::ActorType::AMMO_POUCH }, 107 | { "BP_BountyRewardSkull_Proxy_Rare_C", SOT::ActorType::RA_BOUNTY_REWARD_SKULL }, 108 | { "BP_MessageInABottle_Coral_Proxy_C", SOT::ActorType::CORAL_MESSAGE_IN_A_BOTTLE }, 109 | { "BP_MessageInABottleProxy_C", SOT::ActorType::MESSAGE_IN_A_BOTTLE }, 110 | { "BP_SunkenCurseArtefact_Ruby_EasierBetterRewards_C", SOT::ActorType::SUNKEN_CURSE_RUBY }, 111 | { "BP_SunkenCurseArtefact_Emerald_EasierBetterRewards_C", SOT::ActorType::SUNKEN_CURSE_EMERALD }, 112 | { "BP_SunkenCurseArtefact_Sapphire_EasierBetterRewards_C", SOT::ActorType::SUNKEN_CURSE_SAPPHIRE }, 113 | { "BP_MerchantCrate_BananaCrateProxy_C", SOT::ActorType::BANANA_CRATE }, 114 | { "BP_Treasure_Artifact_Proxy_vase_01_a_C", SOT::ActorType::TREASURE_ARTIFACT_VASE_01 }, 115 | { "BP_Treasure_Artifact_Proxy_vase_02_a_C", SOT::ActorType::TREASURE_ARTIFACT_VASE_02 }, 116 | { "BP_Treasure_Artifact_Proxy_vase_03_a_C", SOT::ActorType::TREASURE_ARTIFACT_VASE_03 }, 117 | { "BP_Treasure_Artifact_Proxy_box_01_a_C", SOT::ActorType::TREASURE_ARTIFACT_BOX_01 }, 118 | { "BP_Treasure_Artifact_Proxy_box_02_a_C", SOT::ActorType::TREASURE_ARTIFACT_BOX_02 }, 119 | { "BP_Treasure_Artifact_Proxy_box_03_a_C", SOT::ActorType::TREASURE_ARTIFACT_BOX_03 }, 120 | { "BP_Treasure_Artifact_Proxy_DVR_Common_C", SOT::ActorType::TREASURE_ARTIFACT_DVR_COMMON }, 121 | { "BP_Treasure_Artifact_Proxy_DVR_Rare_C", SOT::ActorType::TREASURE_ARTIFACT_DVR_RARE }, 122 | { "BP_MerchantCrate_Commodity_Fort_Proxy_C", SOT::ActorType::MCH_CRATE_COMMODITY_FORT }, 123 | { "BP_MerchantCrate_Commodity_Minerals_Proxy_C", SOT::ActorType::MCH_CRATE_COMMODITY_MINERALS }, 124 | { "BP_MerchantCrate_Commodity_SilkCrate_Proxy_C", SOT::ActorType::MCH_CRATE_COMMODITY_SILK_CRATE }, 125 | { "BP_MerchantCrate_Commodity_SugarCrate_Proxy_C", SOT::ActorType::MCH_CRATE_COMMODITY_SUGAR_CRATE }, 126 | { "BP_MerchantCrate_Commodity_GhostCrate_Proxy_C", SOT::ActorType::MCH_CRATE_COMMODITY_GHOST_CRATE }, 127 | { "BP_MerchantCrate_Commodity_Ore_Proxy_C", SOT::ActorType::MCH_CRATE_COMMODITY_ORE }, 128 | { "BP_BountyRewardSkull_Proxy_Fort_C", SOT::ActorType::FORT_BOUNTY_REWARD_SKULL }, 129 | { "BP_BountyRewardSkull_Proxy_Ghost_Common_C", SOT::ActorType::CM_GHOST_BOUNTY_REWARD_SKULL }, 130 | { "BP_BountyRewardSkull_Proxy_Legendary_C", SOT::ActorType::LG_BOUNTY_REWARD_SKULL }, 131 | { "BP_BountyRewardSkull_Proxy_Common_C", SOT::ActorType::CM_BOUNTY_REWARD_SKULL }, 132 | { "BP_TreasureChest_Proxy_Common_DVR_C", SOT::ActorType::TREASURE_CHEST_CM_DVR }, 133 | { "BP_TreasureChest_Proxy_Fort_C", SOT::ActorType::TREASURE_CHEST_FORT }, 134 | { "BP_TreasureChest_Proxy_Legendary_C", SOT::ActorType::LG_TREASURE_CHEST }, 135 | { "BP_TreasureChest_Proxy_Ghost_C", SOT::ActorType::GHOST_TREASURE_CHEST }, 136 | { "BP_TreasureChest_Proxy_Drunken_C", SOT::ActorType::DRUNKEN_TREASURE_CHEST }, 137 | { "BP_MerchantCrate_Commodity_SpiceCrate_Proxy_C", SOT::ActorType::MCH_COMMODITY_SPICE_CRATE }, 138 | { "BP_MerchantCrate_Commodity_TeaCrate_Proxy_C", SOT::ActorType::MCH_COMMODITY_TEA_CRATE }, 139 | { "BP_SirenGem_Proxy_Ruby_C", SOT::ActorType::MCH_COMMODITY_TEA_CRATE }, 140 | { "BP_AshenTomeVol4_05_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL4_05 }, 141 | { "BP_AshenTomeVol4_04_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL4_04 }, 142 | { "BP_AshenTomeVol4_03_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL4_03 }, 143 | { "BP_AshenTomeVol4_02_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL4_02 }, 144 | { "BP_AshenTomeVol4_01_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL4_01 }, 145 | { "BP_AshenTomeVol3_05_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL3_05 }, 146 | { "BP_AshenTomeVol3_04_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL3_04 }, 147 | { "BP_AshenTomeVol3_03_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL3_03 }, 148 | { "BP_AshenTomeVol3_02_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL3_02 }, 149 | { "BP_AshenTomeVol3_01_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL3_01 }, 150 | { "BP_AshenTomeVol1_05_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL1_05 }, 151 | { "BP_AshenTomeVol1_04_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL1_04 }, 152 | { "BP_AshenTomeVol1_03_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL1_03 }, 153 | { "BP_AshenTomeVol1_02_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL1_02 }, 154 | { "BP_AshenTomeVol1_01_Proxy_C", SOT::ActorType::ASHEN_TOME_VOL1_01 }, 155 | }; 156 | 157 | SOT *game() 158 | { 159 | return &_game; 160 | } 161 | 162 | bool SOT::init() 163 | { 164 | if (!this->_process.attach(access_mask)) return false; 165 | this->_process_base = static_cast(this->_process.get_module("SoTGame.exe")._base); 166 | if (!this->_process_base) return false; 167 | if (!sdk::init(&this->_process)) return false; 168 | return true; 169 | } 170 | 171 | hacklib::Process *SOT::process() 172 | { 173 | return &this->_process; 174 | } 175 | 176 | sdk::UWorld SOT::world() 177 | { 178 | return this->_process.read_memory(_process_base + offsets::GWorld); 179 | } 180 | 181 | void *SOT::names() 182 | { 183 | return this->_process.read_memory(_process_base + offsets::GNames); 184 | } 185 | 186 | sdk::Matrix3x3 create_view_matrix(const sdk::Vector3 &rotation) 187 | { 188 | sdk::Vector3 rotation_rads = rotation * (pi / 180); 189 | float sp = std::sinf(rotation_rads._x); 190 | float cp = std::cosf(rotation_rads._x); 191 | float sy = std::sinf(rotation_rads._y); 192 | float cy = std::cosf(rotation_rads._y); 193 | float sr = std::sinf(rotation_rads._z); 194 | float cr = std::cosf(rotation_rads._z); 195 | 196 | sdk::Matrix3x3 result{ }; 197 | result[0][0] = cp * cy; 198 | result[0][1] = cp * sy; 199 | result[0][2] = sp; 200 | result[1][0] = sr * sp * cy - cr * sy; 201 | result[1][1] = sr * sp * sy + cr * cy; 202 | result[1][2] = -sr * cp; 203 | result[2][0] = -(cr * sp * cy + sr * sy); 204 | result[2][1] = cy * sr - cr * sp * sy; 205 | result[2][2] = cr * cp; 206 | return result; 207 | } 208 | 209 | //https://github.com/DougTheDruid/SoT-ESP-Framework/blob/main/helpers.py#L71-L161 210 | bool SOT::world_to_screen(const sdk::FMinimalViewInfo &camera_pov, sdk::Vector3 &position, sdk::Vector2 *out) 211 | { 212 | auto temp = create_view_matrix(camera_pov.rotation()); 213 | const auto axis_x = sdk::Vector3{ temp[0][0], temp[0][1], temp[0][2] }; 214 | const auto axis_y = sdk::Vector3{ temp[1][0], temp[1][1], temp[1][2] }; 215 | const auto axis_z = sdk::Vector3{ temp[2][0], temp[2][1], temp[2][2] }; 216 | const auto delta = position - camera_pov.location(); 217 | const auto dot_products = sdk::Vector3{ delta.dot(axis_y), delta.dot(axis_z), delta.dot(axis_x) }; 218 | if (dot_products._z < 0.1f) return false; 219 | const sdk::Vector2 screen_center{ 1920.0f / 2, 1080.0f / 2 }; 220 | const auto magic = screen_center._x / std::tanf(camera_pov.fov() * pi / 360.0f) / dot_products._z; 221 | out->_x = screen_center._x + dot_products._x * magic; 222 | out->_y = screen_center._y - dot_products._y * magic; 223 | return true; 224 | } 225 | 226 | std::string SOT::get_actor_name(int id) 227 | { 228 | const auto chunk_offset = (id / 0x4000) * 8; 229 | const auto chunk_index_offset = (id % 0x4000) * 8; 230 | const auto name_chunk = this->_process.read_memory(static_cast(this->names()) + chunk_offset); 231 | const auto name_ptr = this->_process.read_memory(static_cast(name_chunk) + chunk_index_offset); 232 | char name_text[68]; 233 | this->_process.read_memory(static_cast(name_ptr) + 0x10, name_text, sizeof(name_text)); 234 | name_text[67] = '\0'; 235 | return std::string{ name_text }; 236 | } 237 | 238 | SOT::ActorType SOT::get_actor_type(int id) 239 | { 240 | if (this->_actor_id_map.count(id)) return this->_actor_id_map[id]; 241 | const std::string name = this->get_actor_name(id); 242 | if (_actor_name_map.count(name)) this->_actor_id_map[id] = _actor_name_map.at(name); 243 | else this->_actor_id_map[id] = SOT::ActorType::UNKNOWN; 244 | return this->_actor_id_map[id]; 245 | } 246 | } -------------------------------------------------------------------------------- /Sea of Thieves External/esp.cpp: -------------------------------------------------------------------------------- 1 | #include "esp.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "sot.h" 7 | #include "cheat.h" 8 | 9 | namespace cheat 10 | { 11 | struct ActorESPInfo 12 | { 13 | std::string _text; 14 | ImColor _draw_color; 15 | }; 16 | 17 | constexpr const ImColor _player_color{ 1.0f, 0.1f, 0.1f }; 18 | 19 | constexpr const ImColor _creature_color{ 1.0f, 1.0f, 1.0f }; 20 | constexpr const ImColor _ship_color{ 0.3f, 1.0f, 0.3f }; 21 | constexpr const ImColor _treasure_color{ 1.0f, 1.0f, 0.3f }; 22 | 23 | constexpr const ImColor _oos_color{ 1.0f, 0.4f, 1.0f }; 24 | constexpr const ImColor _ghd_color{ 1.0f, 0.75f, 0.3f }; 25 | constexpr const ImColor _mch_color{ 0.0f, 0.6f, 1.0f }; 26 | constexpr const ImColor _cgr_color{ 1.0f, 0.3f, 0.3f }; 27 | constexpr const ImColor _svn_color{ 0.51f, 1.0f, 0.38f }; 28 | constexpr const ImColor _special_npc_color{ 0.1f, 1.0f, 0.6f }; 29 | 30 | const std::unordered_map _creature_esp_info 31 | { 32 | { SOT::ActorType::CHICKEN, ActorESPInfo{ "[Chicken]", _creature_color } }, 33 | { SOT::ActorType::OCEAN_CRAWLER_CRAB, ActorESPInfo{ "[Crab Ocean Crawler]", _creature_color } }, 34 | { SOT::ActorType::OCEAN_CRAWLER_HERMIT, ActorESPInfo{ "[Hermit Ocean Crawler]", _creature_color } }, 35 | { SOT::ActorType::TINY_SHARK, ActorESPInfo{ "[Megalodon]", _creature_color } }, 36 | { SOT::ActorType::MERMAID, ActorESPInfo{ "[Mermaid]", _creature_color } }, 37 | { SOT::ActorType::PHANTOM, ActorESPInfo{ "[Phantom]", _creature_color } }, 38 | { SOT::ActorType::PIG, ActorESPInfo{ "[Pig]", _creature_color } }, 39 | { SOT::ActorType::SHARK, ActorESPInfo{ "[Shark]", _creature_color } }, 40 | { SOT::ActorType::SIREN, ActorESPInfo{ "[Siren]", _creature_color } }, 41 | { SOT::ActorType::SKELETON, ActorESPInfo{ "[Skeleton]", _creature_color } }, 42 | { SOT::ActorType::SNAKE, ActorESPInfo{ "[Snake]", _creature_color } }, 43 | }; 44 | 45 | const std::unordered_map _ship_esp_info 46 | { 47 | { SOT::ActorType::S_SHIP_TEMPLATE, ActorESPInfo{ "[Sloop]", _ship_color } }, 48 | { SOT::ActorType::M_SHIP_TEMPLATE, ActorESPInfo{ "[Brigantine]", _ship_color } }, 49 | { SOT::ActorType::L_SHIP_TEMPLATE, ActorESPInfo{ "[Galleon]", _ship_color } }, 50 | }; 51 | 52 | const std::unordered_map _treasure_esp_info 53 | { 54 | { SOT::ActorType::MERMAID_GEM_RUBY, ActorESPInfo{ "[Ammo Pouch]", _treasure_color } }, 55 | { SOT::ActorType::TREASURE_CHEST_CM_DVR, ActorESPInfo{ "[Ashen Castaway's Chest]", _treasure_color } }, 56 | { SOT::ActorType::ASHEN_CHEST_COLLECTORS_CHEST, ActorESPInfo{ "[Ashen Chest]", _treasure_color } }, 57 | { SOT::ActorType::ASHEN_KEY, ActorESPInfo{ "[Ashen Key]", _treasure_color } }, 58 | { SOT::ActorType::MCH_CRATE_COMMODITY_GHOST_CRATE, ActorESPInfo{ "[Ashes of the Damned]", _treasure_color } }, 59 | { SOT::ActorType::TREASURE_ARTIFACT_BOX_01, ActorESPInfo{ "[Bronze Secret-Keeper]", _treasure_color } }, 60 | { SOT::ActorType::MY_TREASURE_CHEST, ActorESPInfo{ "[Captain's Chest]", _treasure_color } }, 61 | { SOT::ActorType::ANCIENT_COLLECTORS_CHEST, ActorESPInfo{ "[Chest of Ancient Tributes]", _treasure_color } }, 62 | { SOT::ActorType::DRUNKEN_TREASURE_CHEST, ActorESPInfo{ "[Chest of a Thousand Grogs]", _treasure_color } }, 63 | { SOT::ActorType::GHOST_TREASURE_CHEST, ActorESPInfo{ "[Chest of the Damned]", _treasure_color } }, 64 | { SOT::ActorType::CORAL_MESSAGE_IN_A_BOTTLE, ActorESPInfo{ "[Coral Message in a Bottle]", _treasure_color } }, 65 | { SOT::ActorType::MCH_CRATE_COMMODITY_FORT, ActorESPInfo{ "[Crate of Ancient Bone Dust]", _treasure_color } }, 66 | { SOT::ActorType::MCH_CRATE_COMMODITY_SILK_CRATE, ActorESPInfo{ "[Crate of Exotic Silks]", _treasure_color } }, 67 | { SOT::ActorType::MCH_COMMODITY_SPICE_CRATE, ActorESPInfo{ "[Crate of Exquisite Spices]", _treasure_color } }, 68 | { SOT::ActorType::MCH_CRATE_COMMODITY_MINERALS, ActorESPInfo{ "[Crate of Extraordinary Minerals]", _treasure_color } }, 69 | { SOT::ActorType::MCH_CRATE_COMMODITY_ORE, ActorESPInfo{ "[Crate of Fine Ore]", _treasure_color } }, 70 | { SOT::ActorType::MCH_CRATE_COMMODITY_SUGAR_CRATE, ActorESPInfo{ "[Crate of Fine Sugar]", _treasure_color } }, 71 | { SOT::ActorType::MCH_COMMODITY_TEA_CRATE, ActorESPInfo{ "[Crate of Rare Tea]", _treasure_color } }, 72 | { SOT::ActorType::RA_BOUNTY_REWARD_SKULL, ActorESPInfo{ "[Disgraced Bounty Skull]", _treasure_color } }, 73 | { SOT::ActorType::TREASURE_ARTIFACT_VASE_02, ActorESPInfo{ "[Elaborate Flagon]", _treasure_color } }, 74 | { SOT::ActorType::SUNKEN_CURSE_EMERALD, ActorESPInfo{ "[Emerald Cursed Mermaid Statue]", _treasure_color } }, 75 | { SOT::ActorType::MERMAID_GEM_EMERALD, ActorESPInfo{ "[Emerald Mermaid Gem]", _treasure_color } }, 76 | { SOT::ActorType::SIREN_GEM_EMERALD, ActorESPInfo{ "[Emerald Siren Gem]", _treasure_color } }, 77 | { SOT::ActorType::CM_BOUNTY_REWARD_SKULL, ActorESPInfo{ "[Foul Bounty Skull]", _treasure_color } }, 78 | { SOT::ActorType::BANANA_CRATE, ActorESPInfo{ "[Fruit Crate]", _treasure_color } }, 79 | { SOT::ActorType::HIGH_VALUE_GIFT, ActorESPInfo{ "[Generous Gift]", _treasure_color } }, 80 | { SOT::ActorType::GOLD_POUCH, ActorESPInfo{ "[Gold Pouch]", _treasure_color } }, 81 | { SOT::ActorType::TREASURE_ARTIFACT_BOX_03, ActorESPInfo{ "[Golden Reliquary]", _treasure_color } }, 82 | { SOT::ActorType::LG_BOUNTY_REWARD_SKULL, ActorESPInfo{ "[Hateful Bounty Skull]", _treasure_color } }, 83 | { SOT::ActorType::LOW_VALUE_GIFT, ActorESPInfo{ "[Humble Gift]", _treasure_color } }, 84 | { SOT::ActorType::LG_TREASURE_CHEST, ActorESPInfo{ "[Marauder's Chest]", _treasure_color } }, 85 | { SOT::ActorType::MESSAGE_IN_A_BOTTLE, ActorESPInfo{ "[Message in a Bottle]", _treasure_color } }, 86 | { SOT::ActorType::TREASURE_ARTIFACT_VASE_01, ActorESPInfo{ "[Mysterious Vessel]", _treasure_color } }, 87 | { SOT::ActorType::TREASURE_ARTIFACT_VASE_03, ActorESPInfo{ "[Ornate Carafe]", _treasure_color } }, 88 | { SOT::ActorType::RITUAL_SKULL, ActorESPInfo{ "[Ritual Skull]", _treasure_color } }, 89 | { SOT::ActorType::TREASURE_ARTIFACT_DVR_COMMON, ActorESPInfo{ "[Roaring Goblet]", _treasure_color } }, 90 | { SOT::ActorType::SUNKEN_CURSE_RUBY, ActorESPInfo{ "[Ruby Cursed Mermaid Statue]", _treasure_color } }, 91 | { SOT::ActorType::MERMAID_GEM_RUBY, ActorESPInfo{ "[Ruby Mermaid Gem]", _treasure_color } }, 92 | { SOT::ActorType::SIREN_GEM_RUBY, ActorESPInfo{ "[Ruby Siren Gem", _treasure_color } }, 93 | { SOT::ActorType::SUNKEN_CURSE_SAPPHIRE, ActorESPInfo{ "[Sapphire Cursed Mermaid Statue]", _treasure_color } }, 94 | { SOT::ActorType::MERMAID_GEM_SAPPHIRE, ActorESPInfo{ "[Sapphire Mermaid Gem]", _treasure_color } }, 95 | { SOT::ActorType::SIREN_GEM_SAPPHIRE, ActorESPInfo{ "[Sapphire Siren Gem]", _treasure_color } }, 96 | { SOT::ActorType::RA_TREASURE_CHEST, ActorESPInfo{ "[Seafarer's Chest]", _treasure_color } }, 97 | { SOT::ActorType::SKELETON_ORDERS, ActorESPInfo{ "[Skeleton's Orders]", _treasure_color } }, 98 | { SOT::ActorType::CM_GHOST_BOUNTY_REWARD_SKULL, ActorESPInfo{ "[Skull of the Damned]", _treasure_color } }, 99 | { SOT::ActorType::TREASURE_CHEST_FORT, ActorESPInfo{ "[Stronghold Chest]", _treasure_color } }, 100 | { SOT::ActorType::B_GUNPOWDER_BARREL, ActorESPInfo{ "[Stronghold Gunpowder Barrel]", _treasure_color } }, 101 | { SOT::ActorType::STRONGHOLD_KEY, ActorESPInfo{ "[Stronghold Key]", _treasure_color } }, 102 | { SOT::ActorType::FORT_BOUNTY_REWARD_SKULL, ActorESPInfo{ "[Stronghold Skull]", _treasure_color } }, 103 | { SOT::ActorType::ASHEN_TOME_VOL1_01, ActorESPInfo{ "[Tome of Curses I]", _treasure_color } }, 104 | { SOT::ActorType::ASHEN_TOME_VOL1_02, ActorESPInfo{ "[Tome of Curses II]", _treasure_color } }, 105 | { SOT::ActorType::ASHEN_TOME_VOL1_03, ActorESPInfo{ "[Tome of Curses III]", _treasure_color } }, 106 | { SOT::ActorType::ASHEN_TOME_VOL1_04, ActorESPInfo{ "[Tome of Curses IV]", _treasure_color } }, 107 | { SOT::ActorType::ASHEN_TOME_VOL1_05, ActorESPInfo{ "[Tome of Curses V]", _treasure_color } }, 108 | { SOT::ActorType::ASHEN_TOME_VOL3_01, ActorESPInfo{ "[Tome of Fire I]", _treasure_color } }, 109 | { SOT::ActorType::ASHEN_TOME_VOL3_02, ActorESPInfo{ "[Tome of Fire II]", _treasure_color } }, 110 | { SOT::ActorType::ASHEN_TOME_VOL3_03, ActorESPInfo{ "[Tome of Fire III]", _treasure_color } }, 111 | { SOT::ActorType::ASHEN_TOME_VOL3_04, ActorESPInfo{ "[Tome of Fire IV]", _treasure_color } }, 112 | { SOT::ActorType::ASHEN_TOME_VOL3_05, ActorESPInfo{ "[Tome of Fire V]", _treasure_color } }, 113 | { SOT::ActorType::ASHEN_TOME_VOL4_01, ActorESPInfo{ "[Tome of Resurrection I]", _treasure_color } }, 114 | { SOT::ActorType::ASHEN_TOME_VOL4_02, ActorESPInfo{ "[Tome of Resurrection II]", _treasure_color } }, 115 | { SOT::ActorType::ASHEN_TOME_VOL4_03, ActorESPInfo{ "[Tome of Resurrection III]", _treasure_color } }, 116 | { SOT::ActorType::ASHEN_TOME_VOL4_04, ActorESPInfo{ "[Tome of Resurrection IV]", _treasure_color } }, 117 | { SOT::ActorType::ASHEN_TOME_VOL4_05, ActorESPInfo{ "[Tome of Resurrection V]", _treasure_color } }, 118 | { SOT::ActorType::COLLECTORS_CHEST, ActorESPInfo{ "[Treasure Chest]", _treasure_color } }, 119 | { SOT::ActorType::SIREN_TRIDENT, ActorESPInfo{ "[Trident of Dark Tides]", _treasure_color } }, 120 | { SOT::ActorType::MY_BOUNTY_REWARD_SKULL, ActorESPInfo{ "[Villainous Bounty Skull]", _treasure_color } }, 121 | }; 122 | 123 | const std::unordered_map _npc_esp_info 124 | { 125 | { SOT::ActorType::OOS_OPRAH, ActorESPInfo{ "[Oprah]", _oos_color } }, 126 | { SOT::ActorType::OOS_OLIVE, ActorESPInfo{ "[Olive]", _oos_color } }, 127 | { SOT::ActorType::OOS_MADAME_OLWEN, ActorESPInfo{ "[Olwen]", _oos_color } }, 128 | { SOT::ActorType::OOS_OKSANA, ActorESPInfo{ "[Oksana]", _oos_color } }, 129 | { SOT::ActorType::OOS_OLGA, ActorESPInfo{ "[Olga]", _oos_color } }, 130 | { SOT::ActorType::OOS_OLIVIA, ActorESPInfo{ "[Olivia]", _oos_color } }, 131 | { SOT::ActorType::OOS_OYA, ActorESPInfo{ "[Oya]", _oos_color } }, 132 | 133 | { SOT::ActorType::GHD_HORACE, ActorESPInfo{ "[Horace]", _ghd_color } }, 134 | { SOT::ActorType::GHD_HUMPHREY, ActorESPInfo{ "[Humphrey]", _ghd_color } }, 135 | { SOT::ActorType::GHD_HERBERT, ActorESPInfo{ "[Herbert]", _ghd_color } }, 136 | { SOT::ActorType::GHD_HARRY, ActorESPInfo{ "[Harry]", _ghd_color } }, 137 | { SOT::ActorType::GHD_HENRY, ActorESPInfo{ "[Henry]", _ghd_color } }, 138 | { SOT::ActorType::GHD_HUGH, ActorESPInfo{ "[Hugh]", _ghd_color } }, 139 | { SOT::ActorType::GHD_HYDE, ActorESPInfo{ "[Hyde]", _ghd_color } }, 140 | 141 | { SOT::ActorType::MCH_MANDY, ActorESPInfo{ "[Mandy]", _mch_color } }, 142 | { SOT::ActorType::MCH_MATILDA, ActorESPInfo{ "[Matilda]", _mch_color } }, 143 | { SOT::ActorType::MCH_MAUREEN, ActorESPInfo{ "[Maureen]", _mch_color } }, 144 | { SOT::ActorType::MCH_MAVIS, ActorESPInfo{ "[Mavis]", _mch_color } }, 145 | { SOT::ActorType::MCH_MEG, ActorESPInfo{ "[Meg]", _mch_color } }, 146 | { SOT::ActorType::MCH_MILDRED, ActorESPInfo{ "[Mildred]", _mch_color } }, 147 | { SOT::ActorType::MCH_MOLLIE, ActorESPInfo{ "[Mollie]", _mch_color } }, 148 | 149 | { SOT::ActorType::CGR_CHARLOTTE, ActorESPInfo{ "[Charlotte]", _cgr_color } }, 150 | 151 | { SOT::ActorType::SVN_1, ActorESPInfo{ "[Cuthbert]", _svn_color } }, 152 | 153 | { SOT::ActorType::GHOST_SHIP_CAPTAIN, ActorESPInfo{ "[Ferryman]", _special_npc_color } }, 154 | }; 155 | 156 | ESP::ESP() 157 | { 158 | this->_esp_font = ImGui::GetIO().Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\Arial.ttf", 15.0f); 159 | } 160 | 161 | std::string ESP::convert_wide_string(const wchar_t *wide_string) const 162 | { 163 | if (!wide_string) return ""; 164 | std::stringstream result{ }; 165 | const auto size = wcslen(wide_string); 166 | for (auto i = 0; i < size; ++i) 167 | { 168 | result << static_cast(wide_string[i]); 169 | } 170 | return result.str(); 171 | } 172 | 173 | void ESP::draw_text(float x, float y, const char *text, ImColor color) 174 | { 175 | auto draw_list = ImGui::GetBackgroundDrawList(); 176 | draw_list->AddText(ImVec2{ x, y }, color, text); 177 | } 178 | 179 | void ESP::tick() 180 | { 181 | ImGui::PushFont(this->_esp_font); 182 | 183 | const auto camera_pov = game()->world().owning_game_instance().local_player().player_controller().player_camera_manager().camera_cache().pov(); 184 | const auto actors = game()->world().persistent_level().actors(); 185 | auto actor_list = actors.get_data(actors.array_num()); 186 | 187 | std::vector *> esp_info_list; 188 | if (settings()->ship_esp) esp_info_list.push_back(&_ship_esp_info); 189 | if (settings()->creature_esp) esp_info_list.push_back(&_creature_esp_info); 190 | if (settings()->treasure_esp) esp_info_list.push_back(&_treasure_esp_info); 191 | if (settings()->npc_esp) esp_info_list.push_back(&_npc_esp_info); 192 | 193 | for (sdk::AActor &actor : actor_list) 194 | { 195 | const auto actor_type = game()->get_actor_type(actor.id()); 196 | 197 | for (const auto esp_info : esp_info_list) 198 | { 199 | if (esp_info->count(actor_type)) 200 | { 201 | sdk::Vector3 pos = actor.root_component().relative_location(); 202 | sdk::Vector2 screen_coords{ }; 203 | if (game()->world_to_screen(camera_pov, pos, &screen_coords)) 204 | { 205 | const auto &draw_info = esp_info->at(actor_type); 206 | this->draw_text(screen_coords._x + 1.0f, screen_coords._y + 1.0f, draw_info._text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 207 | this->draw_text(screen_coords._x + 1.0f, screen_coords._y - 1.0f, draw_info._text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 208 | this->draw_text(screen_coords._x - 1.0f, screen_coords._y - 1.0f, draw_info._text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 209 | this->draw_text(screen_coords._x - 1.0f, screen_coords._y + 1.0f, draw_info._text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 210 | this->draw_text(screen_coords._x, screen_coords._y, draw_info._text.c_str(), draw_info._draw_color); 211 | } 212 | } 213 | } 214 | 215 | if (settings()->player_esp) 216 | { 217 | if (actor_type == SOT::ActorType::PLAYER_PIRATE) 218 | { 219 | sdk::Vector3 pos = actor.root_component().relative_location(); 220 | sdk::Vector2 screen_coords{ }; 221 | if (game()->world_to_screen(camera_pov, pos, &screen_coords)) 222 | { 223 | sdk::AAthenaCharacter character{ actor.instance() }; 224 | const sdk::FString name = character.player_state().player_name(); 225 | std::string name_text = this->convert_wide_string(name.data().get_data(name.data().array_num()).data()); 226 | if (name_text.empty()) name_text = "Player"; 227 | std::string name_draw_text = "[" + name_text + "]"; 228 | const float percentage = character.health_component().current_health() / character.health_component().max_health(); 229 | ImColor name_color{ 1.0f - percentage, percentage, 0.0f }; 230 | this->draw_text(screen_coords._x + 1.0f, screen_coords._y + 1.0f, name_draw_text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 231 | this->draw_text(screen_coords._x - 1.0f, screen_coords._y + 1.0f, name_draw_text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 232 | this->draw_text(screen_coords._x - 1.0f, screen_coords._y - 1.0f, name_draw_text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 233 | this->draw_text(screen_coords._x + 1.0f, screen_coords._y - 1.0f, name_draw_text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 234 | this->draw_text(screen_coords._x, screen_coords._y, name_draw_text.c_str(), name_color); 235 | } 236 | } 237 | } 238 | 239 | if (settings()->debug_esp) 240 | { 241 | sdk::Vector3 pos = actor.root_component().relative_location(); 242 | sdk::Vector2 screen_coords{ }; 243 | if (game()->world_to_screen(camera_pov, pos, &screen_coords)) 244 | { 245 | std::string draw_text = game()->get_actor_name(actor.id()); 246 | if (draw_text.find("ItemInfo") == std::string::npos) 247 | { 248 | this->draw_text(screen_coords._x + 1.0f, screen_coords._y + 1.0f, draw_text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 249 | this->draw_text(screen_coords._x - 1.0f, screen_coords._y + 1.0f, draw_text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 250 | this->draw_text(screen_coords._x - 1.0f, screen_coords._y - 1.0f, draw_text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 251 | this->draw_text(screen_coords._x + 1.0f, screen_coords._y - 1.0f, draw_text.c_str(), ImColor{ 0.0f, 0.0f, 0.0f }); 252 | this->draw_text(screen_coords._x, screen_coords._y, draw_text.c_str(), ImColor{ 0.0f, 1.0f, 0.75f }); 253 | } 254 | } 255 | } 256 | } 257 | 258 | ImGui::PopFont(); 259 | } 260 | } -------------------------------------------------------------------------------- /Sea of Thieves External/imgui/imstb_rectpack.h: -------------------------------------------------------------------------------- 1 | // [DEAR IMGUI] 2 | // This is a slightly modified version of stb_rect_pack.h 1.01. 3 | // Grep for [DEAR IMGUI] to find the changes. 4 | // 5 | // stb_rect_pack.h - v1.01 - public domain - rectangle packing 6 | // Sean Barrett 2014 7 | // 8 | // Useful for e.g. packing rectangular textures into an atlas. 9 | // Does not do rotation. 10 | // 11 | // Before #including, 12 | // 13 | // #define STB_RECT_PACK_IMPLEMENTATION 14 | // 15 | // in the file that you want to have the implementation. 16 | // 17 | // Not necessarily the awesomest packing method, but better than 18 | // the totally naive one in stb_truetype (which is primarily what 19 | // this is meant to replace). 20 | // 21 | // Has only had a few tests run, may have issues. 22 | // 23 | // More docs to come. 24 | // 25 | // No memory allocations; uses qsort() and assert() from stdlib. 26 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 27 | // 28 | // This library currently uses the Skyline Bottom-Left algorithm. 29 | // 30 | // Please note: better rectangle packers are welcome! Please 31 | // implement them to the same API, but with a different init 32 | // function. 33 | // 34 | // Credits 35 | // 36 | // Library 37 | // Sean Barrett 38 | // Minor features 39 | // Martins Mozeiko 40 | // github:IntellectualKitty 41 | // 42 | // Bugfixes / warning fixes 43 | // Jeremy Jaussaud 44 | // Fabian Giesen 45 | // 46 | // Version history: 47 | // 48 | // 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section 49 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles 50 | // 0.99 (2019-02-07) warning fixes 51 | // 0.11 (2017-03-03) return packing success/fail result 52 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 53 | // 0.09 (2016-08-27) fix compiler warnings 54 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 55 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 56 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 57 | // 0.05: added STBRP_ASSERT to allow replacing assert 58 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 59 | // 0.01: initial release 60 | // 61 | // LICENSE 62 | // 63 | // See end of file for license information. 64 | 65 | ////////////////////////////////////////////////////////////////////////////// 66 | // 67 | // INCLUDE SECTION 68 | // 69 | 70 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 71 | #define STB_INCLUDE_STB_RECT_PACK_H 72 | 73 | #define STB_RECT_PACK_VERSION 1 74 | 75 | #ifdef STBRP_STATIC 76 | #define STBRP_DEF static 77 | #else 78 | #define STBRP_DEF extern 79 | #endif 80 | 81 | #ifdef __cplusplus 82 | extern "C" { 83 | #endif 84 | 85 | typedef struct stbrp_context stbrp_context; 86 | typedef struct stbrp_node stbrp_node; 87 | typedef struct stbrp_rect stbrp_rect; 88 | 89 | typedef int stbrp_coord; 90 | 91 | #define STBRP__MAXVAL 0x7fffffff 92 | // Mostly for internal use, but this is the maximum supported coordinate value. 93 | 94 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 95 | // Assign packed locations to rectangles. The rectangles are of type 96 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 97 | // are 'num_rects' many of them. 98 | // 99 | // Rectangles which are successfully packed have the 'was_packed' flag 100 | // set to a non-zero value and 'x' and 'y' store the minimum location 101 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 102 | // if you imagine y increasing downwards). Rectangles which do not fit 103 | // have the 'was_packed' flag set to 0. 104 | // 105 | // You should not try to access the 'rects' array from another thread 106 | // while this function is running, as the function temporarily reorders 107 | // the array while it executes. 108 | // 109 | // To pack into another rectangle, you need to call stbrp_init_target 110 | // again. To continue packing into the same rectangle, you can call 111 | // this function again. Calling this multiple times with multiple rect 112 | // arrays will probably produce worse packing results than calling it 113 | // a single time with the full rectangle array, but the option is 114 | // available. 115 | // 116 | // The function returns 1 if all of the rectangles were successfully 117 | // packed and 0 otherwise. 118 | 119 | struct stbrp_rect 120 | { 121 | // reserved for your use: 122 | int id; 123 | 124 | // input: 125 | stbrp_coord w, h; 126 | 127 | // output: 128 | stbrp_coord x, y; 129 | int was_packed; // non-zero if valid packing 130 | 131 | }; // 16 bytes, nominally 132 | 133 | 134 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 135 | // Initialize a rectangle packer to: 136 | // pack a rectangle that is 'width' by 'height' in dimensions 137 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 138 | // 139 | // You must call this function every time you start packing into a new target. 140 | // 141 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 142 | // the following stbrp_pack_rects() call (or calls), but can be freed after 143 | // the call (or calls) finish. 144 | // 145 | // Note: to guarantee best results, either: 146 | // 1. make sure 'num_nodes' >= 'width' 147 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 148 | // 149 | // If you don't do either of the above things, widths will be quantized to multiples 150 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 151 | // 152 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 153 | // may run out of temporary storage and be unable to pack some rectangles. 154 | 155 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 156 | // Optionally call this function after init but before doing any packing to 157 | // change the handling of the out-of-temp-memory scenario, described above. 158 | // If you call init again, this will be reset to the default (false). 159 | 160 | 161 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 162 | // Optionally select which packing heuristic the library should use. Different 163 | // heuristics will produce better/worse results for different data sets. 164 | // If you call init again, this will be reset to the default. 165 | 166 | enum 167 | { 168 | STBRP_HEURISTIC_Skyline_default=0, 169 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 170 | STBRP_HEURISTIC_Skyline_BF_sortHeight 171 | }; 172 | 173 | 174 | ////////////////////////////////////////////////////////////////////////////// 175 | // 176 | // the details of the following structures don't matter to you, but they must 177 | // be visible so you can handle the memory allocations for them 178 | 179 | struct stbrp_node 180 | { 181 | stbrp_coord x,y; 182 | stbrp_node *next; 183 | }; 184 | 185 | struct stbrp_context 186 | { 187 | int width; 188 | int height; 189 | int align; 190 | int init_mode; 191 | int heuristic; 192 | int num_nodes; 193 | stbrp_node *active_head; 194 | stbrp_node *free_head; 195 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 196 | }; 197 | 198 | #ifdef __cplusplus 199 | } 200 | #endif 201 | 202 | #endif 203 | 204 | ////////////////////////////////////////////////////////////////////////////// 205 | // 206 | // IMPLEMENTATION SECTION 207 | // 208 | 209 | #ifdef STB_RECT_PACK_IMPLEMENTATION 210 | #ifndef STBRP_SORT 211 | #include 212 | #define STBRP_SORT qsort 213 | #endif 214 | 215 | #ifndef STBRP_ASSERT 216 | #include 217 | #define STBRP_ASSERT assert 218 | #endif 219 | 220 | #ifdef _MSC_VER 221 | #define STBRP__NOTUSED(v) (void)(v) 222 | #define STBRP__CDECL __cdecl 223 | #else 224 | #define STBRP__NOTUSED(v) (void)sizeof(v) 225 | #define STBRP__CDECL 226 | #endif 227 | 228 | enum 229 | { 230 | STBRP__INIT_skyline = 1 231 | }; 232 | 233 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 234 | { 235 | switch (context->init_mode) { 236 | case STBRP__INIT_skyline: 237 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 238 | context->heuristic = heuristic; 239 | break; 240 | default: 241 | STBRP_ASSERT(0); 242 | } 243 | } 244 | 245 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 246 | { 247 | if (allow_out_of_mem) 248 | // if it's ok to run out of memory, then don't bother aligning them; 249 | // this gives better packing, but may fail due to OOM (even though 250 | // the rectangles easily fit). @TODO a smarter approach would be to only 251 | // quantize once we've hit OOM, then we could get rid of this parameter. 252 | context->align = 1; 253 | else { 254 | // if it's not ok to run out of memory, then quantize the widths 255 | // so that num_nodes is always enough nodes. 256 | // 257 | // I.e. num_nodes * align >= width 258 | // align >= width / num_nodes 259 | // align = ceil(width/num_nodes) 260 | 261 | context->align = (context->width + context->num_nodes-1) / context->num_nodes; 262 | } 263 | } 264 | 265 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 266 | { 267 | int i; 268 | 269 | for (i=0; i < num_nodes-1; ++i) 270 | nodes[i].next = &nodes[i+1]; 271 | nodes[i].next = NULL; 272 | context->init_mode = STBRP__INIT_skyline; 273 | context->heuristic = STBRP_HEURISTIC_Skyline_default; 274 | context->free_head = &nodes[0]; 275 | context->active_head = &context->extra[0]; 276 | context->width = width; 277 | context->height = height; 278 | context->num_nodes = num_nodes; 279 | stbrp_setup_allow_out_of_mem(context, 0); 280 | 281 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) 282 | context->extra[0].x = 0; 283 | context->extra[0].y = 0; 284 | context->extra[0].next = &context->extra[1]; 285 | context->extra[1].x = (stbrp_coord) width; 286 | context->extra[1].y = (1<<30); 287 | context->extra[1].next = NULL; 288 | } 289 | 290 | // find minimum y position if it starts at x1 291 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 292 | { 293 | stbrp_node *node = first; 294 | int x1 = x0 + width; 295 | int min_y, visited_width, waste_area; 296 | 297 | STBRP__NOTUSED(c); 298 | 299 | STBRP_ASSERT(first->x <= x0); 300 | 301 | #if 0 302 | // skip in case we're past the node 303 | while (node->next->x <= x0) 304 | ++node; 305 | #else 306 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 307 | #endif 308 | 309 | STBRP_ASSERT(node->x <= x0); 310 | 311 | min_y = 0; 312 | waste_area = 0; 313 | visited_width = 0; 314 | while (node->x < x1) { 315 | if (node->y > min_y) { 316 | // raise min_y higher. 317 | // we've accounted for all waste up to min_y, 318 | // but we'll now add more waste for everything we've visted 319 | waste_area += visited_width * (node->y - min_y); 320 | min_y = node->y; 321 | // the first time through, visited_width might be reduced 322 | if (node->x < x0) 323 | visited_width += node->next->x - x0; 324 | else 325 | visited_width += node->next->x - node->x; 326 | } else { 327 | // add waste area 328 | int under_width = node->next->x - node->x; 329 | if (under_width + visited_width > width) 330 | under_width = width - visited_width; 331 | waste_area += under_width * (min_y - node->y); 332 | visited_width += under_width; 333 | } 334 | node = node->next; 335 | } 336 | 337 | *pwaste = waste_area; 338 | return min_y; 339 | } 340 | 341 | typedef struct 342 | { 343 | int x,y; 344 | stbrp_node **prev_link; 345 | } stbrp__findresult; 346 | 347 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 348 | { 349 | int best_waste = (1<<30), best_x, best_y = (1 << 30); 350 | stbrp__findresult fr; 351 | stbrp_node **prev, *node, *tail, **best = NULL; 352 | 353 | // align to multiple of c->align 354 | width = (width + c->align - 1); 355 | width -= width % c->align; 356 | STBRP_ASSERT(width % c->align == 0); 357 | 358 | // if it can't possibly fit, bail immediately 359 | if (width > c->width || height > c->height) { 360 | fr.prev_link = NULL; 361 | fr.x = fr.y = 0; 362 | return fr; 363 | } 364 | 365 | node = c->active_head; 366 | prev = &c->active_head; 367 | while (node->x + width <= c->width) { 368 | int y,waste; 369 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 370 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 371 | // bottom left 372 | if (y < best_y) { 373 | best_y = y; 374 | best = prev; 375 | } 376 | } else { 377 | // best-fit 378 | if (y + height <= c->height) { 379 | // can only use it if it first vertically 380 | if (y < best_y || (y == best_y && waste < best_waste)) { 381 | best_y = y; 382 | best_waste = waste; 383 | best = prev; 384 | } 385 | } 386 | } 387 | prev = &node->next; 388 | node = node->next; 389 | } 390 | 391 | best_x = (best == NULL) ? 0 : (*best)->x; 392 | 393 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 394 | // 395 | // e.g, if fitting 396 | // 397 | // ____________________ 398 | // |____________________| 399 | // 400 | // into 401 | // 402 | // | | 403 | // | ____________| 404 | // |____________| 405 | // 406 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 407 | // 408 | // This makes BF take about 2x the time 409 | 410 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 411 | tail = c->active_head; 412 | node = c->active_head; 413 | prev = &c->active_head; 414 | // find first node that's admissible 415 | while (tail->x < width) 416 | tail = tail->next; 417 | while (tail) { 418 | int xpos = tail->x - width; 419 | int y,waste; 420 | STBRP_ASSERT(xpos >= 0); 421 | // find the left position that matches this 422 | while (node->next->x <= xpos) { 423 | prev = &node->next; 424 | node = node->next; 425 | } 426 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 427 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 428 | if (y + height <= c->height) { 429 | if (y <= best_y) { 430 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 431 | best_x = xpos; 432 | //STBRP_ASSERT(y <= best_y); [DEAR IMGUI] 433 | best_y = y; 434 | best_waste = waste; 435 | best = prev; 436 | } 437 | } 438 | } 439 | tail = tail->next; 440 | } 441 | } 442 | 443 | fr.prev_link = best; 444 | fr.x = best_x; 445 | fr.y = best_y; 446 | return fr; 447 | } 448 | 449 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 450 | { 451 | // find best position according to heuristic 452 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 453 | stbrp_node *node, *cur; 454 | 455 | // bail if: 456 | // 1. it failed 457 | // 2. the best node doesn't fit (we don't always check this) 458 | // 3. we're out of memory 459 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 460 | res.prev_link = NULL; 461 | return res; 462 | } 463 | 464 | // on success, create new node 465 | node = context->free_head; 466 | node->x = (stbrp_coord) res.x; 467 | node->y = (stbrp_coord) (res.y + height); 468 | 469 | context->free_head = node->next; 470 | 471 | // insert the new node into the right starting point, and 472 | // let 'cur' point to the remaining nodes needing to be 473 | // stiched back in 474 | 475 | cur = *res.prev_link; 476 | if (cur->x < res.x) { 477 | // preserve the existing one, so start testing with the next one 478 | stbrp_node *next = cur->next; 479 | cur->next = node; 480 | cur = next; 481 | } else { 482 | *res.prev_link = node; 483 | } 484 | 485 | // from here, traverse cur and free the nodes, until we get to one 486 | // that shouldn't be freed 487 | while (cur->next && cur->next->x <= res.x + width) { 488 | stbrp_node *next = cur->next; 489 | // move the current node to the free list 490 | cur->next = context->free_head; 491 | context->free_head = cur; 492 | cur = next; 493 | } 494 | 495 | // stitch the list back in 496 | node->next = cur; 497 | 498 | if (cur->x < res.x + width) 499 | cur->x = (stbrp_coord) (res.x + width); 500 | 501 | #ifdef _DEBUG 502 | cur = context->active_head; 503 | while (cur->x < context->width) { 504 | STBRP_ASSERT(cur->x < cur->next->x); 505 | cur = cur->next; 506 | } 507 | STBRP_ASSERT(cur->next == NULL); 508 | 509 | { 510 | int count=0; 511 | cur = context->active_head; 512 | while (cur) { 513 | cur = cur->next; 514 | ++count; 515 | } 516 | cur = context->free_head; 517 | while (cur) { 518 | cur = cur->next; 519 | ++count; 520 | } 521 | STBRP_ASSERT(count == context->num_nodes+2); 522 | } 523 | #endif 524 | 525 | return res; 526 | } 527 | 528 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b) 529 | { 530 | const stbrp_rect *p = (const stbrp_rect *) a; 531 | const stbrp_rect *q = (const stbrp_rect *) b; 532 | if (p->h > q->h) 533 | return -1; 534 | if (p->h < q->h) 535 | return 1; 536 | return (p->w > q->w) ? -1 : (p->w < q->w); 537 | } 538 | 539 | static int STBRP__CDECL rect_original_order(const void *a, const void *b) 540 | { 541 | const stbrp_rect *p = (const stbrp_rect *) a; 542 | const stbrp_rect *q = (const stbrp_rect *) b; 543 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 544 | } 545 | 546 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 547 | { 548 | int i, all_rects_packed = 1; 549 | 550 | // we use the 'was_packed' field internally to allow sorting/unsorting 551 | for (i=0; i < num_rects; ++i) { 552 | rects[i].was_packed = i; 553 | } 554 | 555 | // sort according to heuristic 556 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 557 | 558 | for (i=0; i < num_rects; ++i) { 559 | if (rects[i].w == 0 || rects[i].h == 0) { 560 | rects[i].x = rects[i].y = 0; // empty rect needs no space 561 | } else { 562 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 563 | if (fr.prev_link) { 564 | rects[i].x = (stbrp_coord) fr.x; 565 | rects[i].y = (stbrp_coord) fr.y; 566 | } else { 567 | rects[i].x = rects[i].y = STBRP__MAXVAL; 568 | } 569 | } 570 | } 571 | 572 | // unsort 573 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 574 | 575 | // set was_packed flags and all_rects_packed status 576 | for (i=0; i < num_rects; ++i) { 577 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 578 | if (!rects[i].was_packed) 579 | all_rects_packed = 0; 580 | } 581 | 582 | // return the all_rects_packed status 583 | return all_rects_packed; 584 | } 585 | #endif 586 | 587 | /* 588 | ------------------------------------------------------------------------------ 589 | This software is available under 2 licenses -- choose whichever you prefer. 590 | ------------------------------------------------------------------------------ 591 | ALTERNATIVE A - MIT License 592 | Copyright (c) 2017 Sean Barrett 593 | Permission is hereby granted, free of charge, to any person obtaining a copy of 594 | this software and associated documentation files (the "Software"), to deal in 595 | the Software without restriction, including without limitation the rights to 596 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 597 | of the Software, and to permit persons to whom the Software is furnished to do 598 | so, subject to the following conditions: 599 | The above copyright notice and this permission notice shall be included in all 600 | copies or substantial portions of the Software. 601 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 602 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 603 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 604 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 605 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 606 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 607 | SOFTWARE. 608 | ------------------------------------------------------------------------------ 609 | ALTERNATIVE B - Public Domain (www.unlicense.org) 610 | This is free and unencumbered software released into the public domain. 611 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 612 | software, either in source code form or as a compiled binary, for any purpose, 613 | commercial or non-commercial, and by any means. 614 | In jurisdictions that recognize copyright laws, the author or authors of this 615 | software dedicate any and all copyright interest in the software to the public 616 | domain. We make this dedication for the benefit of the public at large and to 617 | the detriment of our heirs and successors. We intend this dedication to be an 618 | overt act of relinquishment in perpetuity of all present and future rights to 619 | this software under copyright law. 620 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 621 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 622 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 623 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 624 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 625 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 626 | ------------------------------------------------------------------------------ 627 | */ 628 | -------------------------------------------------------------------------------- /Sea of Thieves External/imgui/imgui_impl_dx11.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. 7 | 8 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 12 | 13 | // CHANGELOG 14 | // (minor and older changes stripped away, please see git history for details) 15 | // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. 16 | // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). 17 | // 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) 18 | // 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer. 19 | // 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). 20 | // 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. 21 | // 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 22 | // 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 23 | // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). 24 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 25 | // 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. 26 | // 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions. 27 | // 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example. 28 | // 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 29 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. 30 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 31 | // 2016-05-07: DirectX11: Disabling depth-write. 32 | 33 | #include "imgui.h" 34 | #include "imgui_impl_dx11.h" 35 | 36 | // DirectX 37 | #include 38 | #include 39 | #include 40 | #ifdef _MSC_VER 41 | #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. 42 | #endif 43 | 44 | // DirectX11 data 45 | struct ImGui_ImplDX11_Data 46 | { 47 | ID3D11Device* pd3dDevice; 48 | ID3D11DeviceContext* pd3dDeviceContext; 49 | IDXGIFactory* pFactory; 50 | ID3D11Buffer* pVB; 51 | ID3D11Buffer* pIB; 52 | ID3D11VertexShader* pVertexShader; 53 | ID3D11InputLayout* pInputLayout; 54 | ID3D11Buffer* pVertexConstantBuffer; 55 | ID3D11PixelShader* pPixelShader; 56 | ID3D11SamplerState* pFontSampler; 57 | ID3D11ShaderResourceView* pFontTextureView; 58 | ID3D11RasterizerState* pRasterizerState; 59 | ID3D11BlendState* pBlendState; 60 | ID3D11DepthStencilState* pDepthStencilState; 61 | int VertexBufferSize; 62 | int IndexBufferSize; 63 | 64 | ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } 65 | }; 66 | 67 | struct VERTEX_CONSTANT_BUFFER_DX11 68 | { 69 | float mvp[4][4]; 70 | }; 71 | 72 | // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts 73 | // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. 74 | static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData() 75 | { 76 | return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; 77 | } 78 | 79 | // Functions 80 | static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) 81 | { 82 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 83 | 84 | // Setup viewport 85 | D3D11_VIEWPORT vp; 86 | memset(&vp, 0, sizeof(D3D11_VIEWPORT)); 87 | vp.Width = draw_data->DisplaySize.x; 88 | vp.Height = draw_data->DisplaySize.y; 89 | vp.MinDepth = 0.0f; 90 | vp.MaxDepth = 1.0f; 91 | vp.TopLeftX = vp.TopLeftY = 0; 92 | ctx->RSSetViewports(1, &vp); 93 | 94 | // Setup shader and vertex buffers 95 | unsigned int stride = sizeof(ImDrawVert); 96 | unsigned int offset = 0; 97 | ctx->IASetInputLayout(bd->pInputLayout); 98 | ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset); 99 | ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); 100 | ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 101 | ctx->VSSetShader(bd->pVertexShader, nullptr, 0); 102 | ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer); 103 | ctx->PSSetShader(bd->pPixelShader, nullptr, 0); 104 | ctx->PSSetSamplers(0, 1, &bd->pFontSampler); 105 | ctx->GSSetShader(nullptr, nullptr, 0); 106 | ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 107 | ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 108 | ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 109 | 110 | // Setup blend state 111 | const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; 112 | ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff); 113 | ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0); 114 | ctx->RSSetState(bd->pRasterizerState); 115 | } 116 | 117 | // Render function 118 | void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) 119 | { 120 | // Avoid rendering when minimized 121 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) 122 | return; 123 | 124 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 125 | ID3D11DeviceContext* ctx = bd->pd3dDeviceContext; 126 | 127 | // Create and grow vertex/index buffers if needed 128 | if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount) 129 | { 130 | if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } 131 | bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; 132 | D3D11_BUFFER_DESC desc; 133 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 134 | desc.Usage = D3D11_USAGE_DYNAMIC; 135 | desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert); 136 | desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 137 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 138 | desc.MiscFlags = 0; 139 | if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVB) < 0) 140 | return; 141 | } 142 | if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount) 143 | { 144 | if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } 145 | bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; 146 | D3D11_BUFFER_DESC desc; 147 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 148 | desc.Usage = D3D11_USAGE_DYNAMIC; 149 | desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx); 150 | desc.BindFlags = D3D11_BIND_INDEX_BUFFER; 151 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 152 | if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0) 153 | return; 154 | } 155 | 156 | // Upload vertex/index data into a single contiguous GPU buffer 157 | D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; 158 | if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) 159 | return; 160 | if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) 161 | return; 162 | ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; 163 | ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; 164 | for (int n = 0; n < draw_data->CmdListsCount; n++) 165 | { 166 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 167 | memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); 168 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 169 | vtx_dst += cmd_list->VtxBuffer.Size; 170 | idx_dst += cmd_list->IdxBuffer.Size; 171 | } 172 | ctx->Unmap(bd->pVB, 0); 173 | ctx->Unmap(bd->pIB, 0); 174 | 175 | // Setup orthographic projection matrix into our constant buffer 176 | // 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. 177 | { 178 | D3D11_MAPPED_SUBRESOURCE mapped_resource; 179 | if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) 180 | return; 181 | VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData; 182 | float L = draw_data->DisplayPos.x; 183 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; 184 | float T = draw_data->DisplayPos.y; 185 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; 186 | float mvp[4][4] = 187 | { 188 | { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, 189 | { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, 190 | { 0.0f, 0.0f, 0.5f, 0.0f }, 191 | { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, 192 | }; 193 | memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); 194 | ctx->Unmap(bd->pVertexConstantBuffer, 0); 195 | } 196 | 197 | // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) 198 | struct BACKUP_DX11_STATE 199 | { 200 | UINT ScissorRectsCount, ViewportsCount; 201 | D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 202 | D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 203 | ID3D11RasterizerState* RS; 204 | ID3D11BlendState* BlendState; 205 | FLOAT BlendFactor[4]; 206 | UINT SampleMask; 207 | UINT StencilRef; 208 | ID3D11DepthStencilState* DepthStencilState; 209 | ID3D11ShaderResourceView* PSShaderResource; 210 | ID3D11SamplerState* PSSampler; 211 | ID3D11PixelShader* PS; 212 | ID3D11VertexShader* VS; 213 | ID3D11GeometryShader* GS; 214 | UINT PSInstancesCount, VSInstancesCount, GSInstancesCount; 215 | ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation 216 | D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; 217 | ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; 218 | UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; 219 | DXGI_FORMAT IndexBufferFormat; 220 | ID3D11InputLayout* InputLayout; 221 | }; 222 | BACKUP_DX11_STATE old = {}; 223 | old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; 224 | ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); 225 | ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); 226 | ctx->RSGetState(&old.RS); 227 | ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); 228 | ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); 229 | ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); 230 | ctx->PSGetSamplers(0, 1, &old.PSSampler); 231 | old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256; 232 | ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); 233 | ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); 234 | ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); 235 | ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount); 236 | 237 | ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); 238 | ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); 239 | ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); 240 | ctx->IAGetInputLayout(&old.InputLayout); 241 | 242 | // Setup desired DX state 243 | ImGui_ImplDX11_SetupRenderState(draw_data, ctx); 244 | 245 | // Render command lists 246 | // (Because we merged all buffers into a single one, we maintain our own offset into them) 247 | int global_idx_offset = 0; 248 | int global_vtx_offset = 0; 249 | ImVec2 clip_off = draw_data->DisplayPos; 250 | for (int n = 0; n < draw_data->CmdListsCount; n++) 251 | { 252 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 253 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 254 | { 255 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 256 | if (pcmd->UserCallback != nullptr) 257 | { 258 | // User callback, registered via ImDrawList::AddCallback() 259 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 260 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 261 | ImGui_ImplDX11_SetupRenderState(draw_data, ctx); 262 | else 263 | pcmd->UserCallback(cmd_list, pcmd); 264 | } 265 | else 266 | { 267 | // Project scissor/clipping rectangles into framebuffer space 268 | ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); 269 | ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); 270 | if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) 271 | continue; 272 | 273 | // Apply scissor/clipping rectangle 274 | const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; 275 | ctx->RSSetScissorRects(1, &r); 276 | 277 | // Bind texture, Draw 278 | ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID(); 279 | ctx->PSSetShaderResources(0, 1, &texture_srv); 280 | ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); 281 | } 282 | } 283 | global_idx_offset += cmd_list->IdxBuffer.Size; 284 | global_vtx_offset += cmd_list->VtxBuffer.Size; 285 | } 286 | 287 | // Restore modified DX state 288 | ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); 289 | ctx->RSSetViewports(old.ViewportsCount, old.Viewports); 290 | ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); 291 | ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); 292 | ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); 293 | ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); 294 | ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); 295 | ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); 296 | for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); 297 | ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); 298 | ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); 299 | ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release(); 300 | for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); 301 | ctx->IASetPrimitiveTopology(old.PrimitiveTopology); 302 | ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); 303 | ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); 304 | ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); 305 | } 306 | 307 | static void ImGui_ImplDX11_CreateFontsTexture() 308 | { 309 | // Build texture atlas 310 | ImGuiIO& io = ImGui::GetIO(); 311 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 312 | unsigned char* pixels; 313 | int width, height; 314 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 315 | 316 | // Upload texture to graphics system 317 | { 318 | D3D11_TEXTURE2D_DESC desc; 319 | ZeroMemory(&desc, sizeof(desc)); 320 | desc.Width = width; 321 | desc.Height = height; 322 | desc.MipLevels = 1; 323 | desc.ArraySize = 1; 324 | desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 325 | desc.SampleDesc.Count = 1; 326 | desc.Usage = D3D11_USAGE_DEFAULT; 327 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 328 | desc.CPUAccessFlags = 0; 329 | 330 | ID3D11Texture2D* pTexture = nullptr; 331 | D3D11_SUBRESOURCE_DATA subResource; 332 | subResource.pSysMem = pixels; 333 | subResource.SysMemPitch = desc.Width * 4; 334 | subResource.SysMemSlicePitch = 0; 335 | bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); 336 | IM_ASSERT(pTexture != nullptr); 337 | 338 | // Create texture view 339 | D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 340 | ZeroMemory(&srvDesc, sizeof(srvDesc)); 341 | srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 342 | srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 343 | srvDesc.Texture2D.MipLevels = desc.MipLevels; 344 | srvDesc.Texture2D.MostDetailedMip = 0; 345 | bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView); 346 | pTexture->Release(); 347 | } 348 | 349 | // Store our identifier 350 | io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView); 351 | 352 | // Create texture sampler 353 | // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) 354 | { 355 | D3D11_SAMPLER_DESC desc; 356 | ZeroMemory(&desc, sizeof(desc)); 357 | desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 358 | desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; 359 | desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; 360 | desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; 361 | desc.MipLODBias = 0.f; 362 | desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; 363 | desc.MinLOD = 0.f; 364 | desc.MaxLOD = 0.f; 365 | bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler); 366 | } 367 | } 368 | 369 | bool ImGui_ImplDX11_CreateDeviceObjects() 370 | { 371 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 372 | if (!bd->pd3dDevice) 373 | return false; 374 | if (bd->pFontSampler) 375 | ImGui_ImplDX11_InvalidateDeviceObjects(); 376 | 377 | // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) 378 | // If you would like to use this DX11 sample code but remove this dependency you can: 379 | // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] 380 | // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. 381 | // See https://github.com/ocornut/imgui/pull/638 for sources and details. 382 | 383 | // Create the vertex shader 384 | { 385 | static const char* vertexShader = 386 | "cbuffer vertexBuffer : register(b0) \ 387 | {\ 388 | float4x4 ProjectionMatrix; \ 389 | };\ 390 | struct VS_INPUT\ 391 | {\ 392 | float2 pos : POSITION;\ 393 | float4 col : COLOR0;\ 394 | float2 uv : TEXCOORD0;\ 395 | };\ 396 | \ 397 | struct PS_INPUT\ 398 | {\ 399 | float4 pos : SV_POSITION;\ 400 | float4 col : COLOR0;\ 401 | float2 uv : TEXCOORD0;\ 402 | };\ 403 | \ 404 | PS_INPUT main(VS_INPUT input)\ 405 | {\ 406 | PS_INPUT output;\ 407 | output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ 408 | output.col = input.col;\ 409 | output.uv = input.uv;\ 410 | return output;\ 411 | }"; 412 | 413 | ID3DBlob* vertexShaderBlob; 414 | if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr))) 415 | return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! 416 | if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &bd->pVertexShader) != S_OK) 417 | { 418 | vertexShaderBlob->Release(); 419 | return false; 420 | } 421 | 422 | // Create the input layout 423 | D3D11_INPUT_ELEMENT_DESC local_layout[] = 424 | { 425 | { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 426 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 427 | { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 428 | }; 429 | if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK) 430 | { 431 | vertexShaderBlob->Release(); 432 | return false; 433 | } 434 | vertexShaderBlob->Release(); 435 | 436 | // Create the constant buffer 437 | { 438 | D3D11_BUFFER_DESC desc; 439 | desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX11); 440 | desc.Usage = D3D11_USAGE_DYNAMIC; 441 | desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 442 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 443 | desc.MiscFlags = 0; 444 | bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer); 445 | } 446 | } 447 | 448 | // Create the pixel shader 449 | { 450 | static const char* pixelShader = 451 | "struct PS_INPUT\ 452 | {\ 453 | float4 pos : SV_POSITION;\ 454 | float4 col : COLOR0;\ 455 | float2 uv : TEXCOORD0;\ 456 | };\ 457 | sampler sampler0;\ 458 | Texture2D texture0;\ 459 | \ 460 | float4 main(PS_INPUT input) : SV_Target\ 461 | {\ 462 | float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ 463 | return out_col; \ 464 | }"; 465 | 466 | ID3DBlob* pixelShaderBlob; 467 | if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr))) 468 | return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! 469 | if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &bd->pPixelShader) != S_OK) 470 | { 471 | pixelShaderBlob->Release(); 472 | return false; 473 | } 474 | pixelShaderBlob->Release(); 475 | } 476 | 477 | // Create the blending setup 478 | { 479 | D3D11_BLEND_DESC desc; 480 | ZeroMemory(&desc, sizeof(desc)); 481 | desc.AlphaToCoverageEnable = false; 482 | desc.RenderTarget[0].BlendEnable = true; 483 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; 484 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 485 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; 486 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; 487 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; 488 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 489 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 490 | bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState); 491 | } 492 | 493 | // Create the rasterizer state 494 | { 495 | D3D11_RASTERIZER_DESC desc; 496 | ZeroMemory(&desc, sizeof(desc)); 497 | desc.FillMode = D3D11_FILL_SOLID; 498 | desc.CullMode = D3D11_CULL_NONE; 499 | desc.ScissorEnable = true; 500 | desc.DepthClipEnable = true; 501 | bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState); 502 | } 503 | 504 | // Create depth-stencil State 505 | { 506 | D3D11_DEPTH_STENCIL_DESC desc; 507 | ZeroMemory(&desc, sizeof(desc)); 508 | desc.DepthEnable = false; 509 | desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; 510 | desc.DepthFunc = D3D11_COMPARISON_ALWAYS; 511 | desc.StencilEnable = false; 512 | desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 513 | desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 514 | desc.BackFace = desc.FrontFace; 515 | bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState); 516 | } 517 | 518 | ImGui_ImplDX11_CreateFontsTexture(); 519 | 520 | return true; 521 | } 522 | 523 | void ImGui_ImplDX11_InvalidateDeviceObjects() 524 | { 525 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 526 | if (!bd->pd3dDevice) 527 | return; 528 | 529 | if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; } 530 | if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. 531 | if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } 532 | if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } 533 | if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; } 534 | if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; } 535 | if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; } 536 | if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; } 537 | if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; } 538 | if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; } 539 | if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; } 540 | } 541 | 542 | bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) 543 | { 544 | ImGuiIO& io = ImGui::GetIO(); 545 | IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); 546 | 547 | // Setup backend capabilities flags 548 | ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)(); 549 | io.BackendRendererUserData = (void*)bd; 550 | io.BackendRendererName = "imgui_impl_dx11"; 551 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 552 | 553 | // Get factory from device 554 | IDXGIDevice* pDXGIDevice = nullptr; 555 | IDXGIAdapter* pDXGIAdapter = nullptr; 556 | IDXGIFactory* pFactory = nullptr; 557 | 558 | if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) 559 | if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) 560 | if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) 561 | { 562 | bd->pd3dDevice = device; 563 | bd->pd3dDeviceContext = device_context; 564 | bd->pFactory = pFactory; 565 | } 566 | if (pDXGIDevice) pDXGIDevice->Release(); 567 | if (pDXGIAdapter) pDXGIAdapter->Release(); 568 | bd->pd3dDevice->AddRef(); 569 | bd->pd3dDeviceContext->AddRef(); 570 | 571 | return true; 572 | } 573 | 574 | void ImGui_ImplDX11_Shutdown() 575 | { 576 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 577 | IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); 578 | ImGuiIO& io = ImGui::GetIO(); 579 | 580 | ImGui_ImplDX11_InvalidateDeviceObjects(); 581 | if (bd->pFactory) { bd->pFactory->Release(); } 582 | if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } 583 | if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); } 584 | io.BackendRendererName = nullptr; 585 | io.BackendRendererUserData = nullptr; 586 | IM_DELETE(bd); 587 | } 588 | 589 | void ImGui_ImplDX11_NewFrame() 590 | { 591 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 592 | IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX11_Init()?"); 593 | 594 | if (!bd->pFontSampler) 595 | ImGui_ImplDX11_CreateDeviceObjects(); 596 | } 597 | -------------------------------------------------------------------------------- /Sea of Thieves External/imgui/imgui_impl_win32.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] 7 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 8 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 14 | 15 | #include "imgui.h" 16 | #include "imgui_impl_win32.h" 17 | #ifndef WIN32_LEAN_AND_MEAN 18 | #define WIN32_LEAN_AND_MEAN 19 | #endif 20 | #include 21 | #include // GET_X_LPARAM(), GET_Y_LPARAM() 22 | #include 23 | #include 24 | 25 | // Configuration flags to add in your imconfig.h file: 26 | //#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant. 27 | 28 | // Using XInput for gamepad (will load DLL dynamically) 29 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 30 | #include 31 | typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*); 32 | typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); 33 | #endif 34 | 35 | // CHANGELOG 36 | // (minor and older changes stripped away, please see git history for details) 37 | // 2023-02-15: Inputs: Use WM_NCMOUSEMOVE / WM_NCMOUSELEAVE to track mouse position over non-client area (e.g. OS decorations) when app is not focused. (#6045, #6162) 38 | // 2023-02-02: Inputs: Flipping WM_MOUSEHWHEEL (horizontal mouse-wheel) value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463) 39 | // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. 40 | // 2022-09-28: Inputs: Convert WM_CHAR values with MultiByteToWideChar() when window class was registered as MBCS (not Unicode). 41 | // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). 42 | // 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. 43 | // 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[]. 44 | // 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). 45 | // 2022-01-17: Inputs: always update key mods next and before a key event (not in NewFrame) to fix input queue with very low framerates. 46 | // 2022-01-12: Inputs: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API. 47 | // 2022-01-12: Inputs: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted. 48 | // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. 49 | // 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness. 50 | // 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages. 51 | // 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus. 52 | // 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events). 53 | // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). 54 | // 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1). 55 | // 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS). 56 | // 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi). 57 | // 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1. 58 | // 2021-01-25: Inputs: Dynamically loading XInput DLL. 59 | // 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed. 60 | // 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs) 61 | // 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions. 62 | // 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT. 63 | // 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor. 64 | // 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter(). 65 | // 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent. 66 | // 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. 67 | // 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application). 68 | // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. 69 | // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. 70 | // 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads). 71 | // 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples. 72 | // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. 73 | // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). 74 | // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. 75 | // 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). 76 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 77 | // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. 78 | // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. 79 | // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. 80 | // 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read. 81 | // 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. 82 | // 2016-11-12: Inputs: Only call Win32 ::SetCursor(nullptr) when io.MouseDrawCursor is set. 83 | 84 | struct ImGui_ImplWin32_Data 85 | { 86 | HWND hWnd; 87 | HWND MouseHwnd; 88 | int MouseTrackedArea; // 0: not tracked, 1: client are, 2: non-client area 89 | int MouseButtonsDown; 90 | INT64 Time; 91 | INT64 TicksPerSecond; 92 | ImGuiMouseCursor LastMouseCursor; 93 | 94 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 95 | bool HasGamepad; 96 | bool WantUpdateHasGamepad; 97 | HMODULE XInputDLL; 98 | PFN_XInputGetCapabilities XInputGetCapabilities; 99 | PFN_XInputGetState XInputGetState; 100 | #endif 101 | 102 | ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); } 103 | }; 104 | 105 | // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts 106 | // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. 107 | // FIXME: multi-context support is not well tested and probably dysfunctional in this backend. 108 | // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. 109 | static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData() 110 | { 111 | return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; 112 | } 113 | 114 | // Functions 115 | bool ImGui_ImplWin32_Init(void* hwnd) 116 | { 117 | ImGuiIO& io = ImGui::GetIO(); 118 | IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); 119 | 120 | INT64 perf_frequency, perf_counter; 121 | if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency)) 122 | return false; 123 | if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter)) 124 | return false; 125 | 126 | // Setup backend capabilities flags 127 | ImGui_ImplWin32_Data* bd = IM_NEW(ImGui_ImplWin32_Data)(); 128 | io.BackendPlatformUserData = (void*)bd; 129 | io.BackendPlatformName = "imgui_impl_win32"; 130 | io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) 131 | io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) 132 | 133 | bd->hWnd = (HWND)hwnd; 134 | bd->TicksPerSecond = perf_frequency; 135 | bd->Time = perf_counter; 136 | bd->LastMouseCursor = ImGuiMouseCursor_COUNT; 137 | 138 | // Set platform dependent data in viewport 139 | ImGui::GetMainViewport()->PlatformHandleRaw = (void*)hwnd; 140 | 141 | // Dynamically load XInput library 142 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 143 | bd->WantUpdateHasGamepad = true; 144 | const char* xinput_dll_names[] = 145 | { 146 | "xinput1_4.dll", // Windows 8+ 147 | "xinput1_3.dll", // DirectX SDK 148 | "xinput9_1_0.dll", // Windows Vista, Windows 7 149 | "xinput1_2.dll", // DirectX SDK 150 | "xinput1_1.dll" // DirectX SDK 151 | }; 152 | for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++) 153 | if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n])) 154 | { 155 | bd->XInputDLL = dll; 156 | bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities"); 157 | bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState"); 158 | break; 159 | } 160 | #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 161 | 162 | return true; 163 | } 164 | 165 | void ImGui_ImplWin32_Shutdown() 166 | { 167 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 168 | IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); 169 | ImGuiIO& io = ImGui::GetIO(); 170 | 171 | // Unload XInput library 172 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 173 | if (bd->XInputDLL) 174 | ::FreeLibrary(bd->XInputDLL); 175 | #endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 176 | 177 | io.BackendPlatformName = nullptr; 178 | io.BackendPlatformUserData = nullptr; 179 | IM_DELETE(bd); 180 | } 181 | 182 | static bool ImGui_ImplWin32_UpdateMouseCursor() 183 | { 184 | ImGuiIO& io = ImGui::GetIO(); 185 | if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) 186 | return false; 187 | 188 | ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); 189 | if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) 190 | { 191 | // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor 192 | ::SetCursor(nullptr); 193 | } 194 | else 195 | { 196 | // Show OS mouse cursor 197 | LPTSTR win32_cursor = IDC_ARROW; 198 | switch (imgui_cursor) 199 | { 200 | case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; 201 | case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; 202 | case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; 203 | case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; 204 | case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; 205 | case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; 206 | case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; 207 | case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; 208 | case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; 209 | } 210 | ::SetCursor(::LoadCursor(nullptr, win32_cursor)); 211 | } 212 | return true; 213 | } 214 | 215 | static bool IsVkDown(int vk) 216 | { 217 | return (::GetKeyState(vk) & 0x8000) != 0; 218 | } 219 | 220 | static void ImGui_ImplWin32_AddKeyEvent(ImGuiKey key, bool down, int native_keycode, int native_scancode = -1) 221 | { 222 | ImGuiIO& io = ImGui::GetIO(); 223 | io.AddKeyEvent(key, down); 224 | io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To support legacy indexing (<1.87 user code) 225 | IM_UNUSED(native_scancode); 226 | } 227 | 228 | static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds() 229 | { 230 | // Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one. 231 | if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && !IsVkDown(VK_LSHIFT)) 232 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, false, VK_LSHIFT); 233 | if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT)) 234 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, false, VK_RSHIFT); 235 | 236 | // Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Win+V on some setups, according to GLFW). 237 | if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN)) 238 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftSuper, false, VK_LWIN); 239 | if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN)) 240 | ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightSuper, false, VK_RWIN); 241 | } 242 | 243 | static void ImGui_ImplWin32_UpdateKeyModifiers() 244 | { 245 | ImGuiIO& io = ImGui::GetIO(); 246 | io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL)); 247 | io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT)); 248 | io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU)); 249 | io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_APPS)); 250 | } 251 | 252 | static void ImGui_ImplWin32_UpdateMouseData() 253 | { 254 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 255 | ImGuiIO& io = ImGui::GetIO(); 256 | IM_ASSERT(bd->hWnd != 0); 257 | 258 | HWND focused_window = ::GetForegroundWindow(); 259 | const bool is_app_focused = (focused_window == bd->hWnd); 260 | if (is_app_focused) 261 | { 262 | // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) 263 | if (io.WantSetMousePos) 264 | { 265 | POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; 266 | if (::ClientToScreen(bd->hWnd, &pos)) 267 | ::SetCursorPos(pos.x, pos.y); 268 | } 269 | 270 | // (Optional) Fallback to provide mouse position when focused (WM_MOUSEMOVE already provides this when hovered or captured) 271 | // This also fills a short gap when clicking non-client area: WM_NCMOUSELEAVE -> modal OS move -> gap -> WM_NCMOUSEMOVE 272 | if (!io.WantSetMousePos && bd->MouseTrackedArea == 0) 273 | { 274 | POINT pos; 275 | if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos)) 276 | io.AddMousePosEvent((float)pos.x, (float)pos.y); 277 | } 278 | } 279 | } 280 | 281 | // Gamepad navigation mapping 282 | static void ImGui_ImplWin32_UpdateGamepads() 283 | { 284 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 285 | ImGuiIO& io = ImGui::GetIO(); 286 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 287 | //if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. 288 | // return; 289 | 290 | // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow. 291 | // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE. 292 | if (bd->WantUpdateHasGamepad) 293 | { 294 | XINPUT_CAPABILITIES caps = {}; 295 | bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false; 296 | bd->WantUpdateHasGamepad = false; 297 | } 298 | 299 | io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; 300 | XINPUT_STATE xinput_state; 301 | XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad; 302 | if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS) 303 | return; 304 | io.BackendFlags |= ImGuiBackendFlags_HasGamepad; 305 | 306 | #define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V) 307 | #define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); } 308 | #define MAP_ANALOG(KEY_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); io.AddKeyAnalogEvent(KEY_NO, vn > 0.10f, IM_SATURATE(vn)); } 309 | MAP_BUTTON(ImGuiKey_GamepadStart, XINPUT_GAMEPAD_START); 310 | MAP_BUTTON(ImGuiKey_GamepadBack, XINPUT_GAMEPAD_BACK); 311 | MAP_BUTTON(ImGuiKey_GamepadFaceLeft, XINPUT_GAMEPAD_X); 312 | MAP_BUTTON(ImGuiKey_GamepadFaceRight, XINPUT_GAMEPAD_B); 313 | MAP_BUTTON(ImGuiKey_GamepadFaceUp, XINPUT_GAMEPAD_Y); 314 | MAP_BUTTON(ImGuiKey_GamepadFaceDown, XINPUT_GAMEPAD_A); 315 | MAP_BUTTON(ImGuiKey_GamepadDpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); 316 | MAP_BUTTON(ImGuiKey_GamepadDpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); 317 | MAP_BUTTON(ImGuiKey_GamepadDpadUp, XINPUT_GAMEPAD_DPAD_UP); 318 | MAP_BUTTON(ImGuiKey_GamepadDpadDown, XINPUT_GAMEPAD_DPAD_DOWN); 319 | MAP_BUTTON(ImGuiKey_GamepadL1, XINPUT_GAMEPAD_LEFT_SHOULDER); 320 | MAP_BUTTON(ImGuiKey_GamepadR1, XINPUT_GAMEPAD_RIGHT_SHOULDER); 321 | MAP_ANALOG(ImGuiKey_GamepadL2, gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255); 322 | MAP_ANALOG(ImGuiKey_GamepadR2, gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255); 323 | MAP_BUTTON(ImGuiKey_GamepadL3, XINPUT_GAMEPAD_LEFT_THUMB); 324 | MAP_BUTTON(ImGuiKey_GamepadR3, XINPUT_GAMEPAD_RIGHT_THUMB); 325 | MAP_ANALOG(ImGuiKey_GamepadLStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 326 | MAP_ANALOG(ImGuiKey_GamepadLStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 327 | MAP_ANALOG(ImGuiKey_GamepadLStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 328 | MAP_ANALOG(ImGuiKey_GamepadLStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 329 | MAP_ANALOG(ImGuiKey_GamepadRStickLeft, gamepad.sThumbRX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 330 | MAP_ANALOG(ImGuiKey_GamepadRStickRight, gamepad.sThumbRX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 331 | MAP_ANALOG(ImGuiKey_GamepadRStickUp, gamepad.sThumbRY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767); 332 | MAP_ANALOG(ImGuiKey_GamepadRStickDown, gamepad.sThumbRY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768); 333 | #undef MAP_BUTTON 334 | #undef MAP_ANALOG 335 | #endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 336 | } 337 | 338 | void ImGui_ImplWin32_NewFrame() 339 | { 340 | ImGuiIO& io = ImGui::GetIO(); 341 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 342 | IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplWin32_Init()?"); 343 | 344 | // Setup display size (every frame to accommodate for window resizing) 345 | RECT rect = { 0, 0, 0, 0 }; 346 | ::GetClientRect(bd->hWnd, &rect); 347 | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); 348 | 349 | // Setup time step 350 | INT64 current_time = 0; 351 | ::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time); 352 | io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond; 353 | bd->Time = current_time; 354 | 355 | // Update OS mouse position 356 | ImGui_ImplWin32_UpdateMouseData(); 357 | 358 | // Process workarounds for known Windows key handling issues 359 | ImGui_ImplWin32_ProcessKeyEventsWorkarounds(); 360 | 361 | // Update OS mouse cursor with the cursor requested by imgui 362 | ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); 363 | if (bd->LastMouseCursor != mouse_cursor) 364 | { 365 | bd->LastMouseCursor = mouse_cursor; 366 | ImGui_ImplWin32_UpdateMouseCursor(); 367 | } 368 | 369 | // Update game controllers (if enabled and available) 370 | ImGui_ImplWin32_UpdateGamepads(); 371 | } 372 | 373 | // There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED, we assign it an arbitrary value to make code more readable (VK_ codes go up to 255) 374 | #define IM_VK_KEYPAD_ENTER (VK_RETURN + 256) 375 | 376 | // Map VK_xxx to ImGuiKey_xxx. 377 | static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam) 378 | { 379 | switch (wParam) 380 | { 381 | case VK_TAB: return ImGuiKey_Tab; 382 | case VK_LEFT: return ImGuiKey_LeftArrow; 383 | case VK_RIGHT: return ImGuiKey_RightArrow; 384 | case VK_UP: return ImGuiKey_UpArrow; 385 | case VK_DOWN: return ImGuiKey_DownArrow; 386 | case VK_PRIOR: return ImGuiKey_PageUp; 387 | case VK_NEXT: return ImGuiKey_PageDown; 388 | case VK_HOME: return ImGuiKey_Home; 389 | case VK_END: return ImGuiKey_End; 390 | case VK_INSERT: return ImGuiKey_Insert; 391 | case VK_DELETE: return ImGuiKey_Delete; 392 | case VK_BACK: return ImGuiKey_Backspace; 393 | case VK_SPACE: return ImGuiKey_Space; 394 | case VK_RETURN: return ImGuiKey_Enter; 395 | case VK_ESCAPE: return ImGuiKey_Escape; 396 | case VK_OEM_7: return ImGuiKey_Apostrophe; 397 | case VK_OEM_COMMA: return ImGuiKey_Comma; 398 | case VK_OEM_MINUS: return ImGuiKey_Minus; 399 | case VK_OEM_PERIOD: return ImGuiKey_Period; 400 | case VK_OEM_2: return ImGuiKey_Slash; 401 | case VK_OEM_1: return ImGuiKey_Semicolon; 402 | case VK_OEM_PLUS: return ImGuiKey_Equal; 403 | case VK_OEM_4: return ImGuiKey_LeftBracket; 404 | case VK_OEM_5: return ImGuiKey_Backslash; 405 | case VK_OEM_6: return ImGuiKey_RightBracket; 406 | case VK_OEM_3: return ImGuiKey_GraveAccent; 407 | case VK_CAPITAL: return ImGuiKey_CapsLock; 408 | case VK_SCROLL: return ImGuiKey_ScrollLock; 409 | case VK_NUMLOCK: return ImGuiKey_NumLock; 410 | case VK_SNAPSHOT: return ImGuiKey_PrintScreen; 411 | case VK_PAUSE: return ImGuiKey_Pause; 412 | case VK_NUMPAD0: return ImGuiKey_Keypad0; 413 | case VK_NUMPAD1: return ImGuiKey_Keypad1; 414 | case VK_NUMPAD2: return ImGuiKey_Keypad2; 415 | case VK_NUMPAD3: return ImGuiKey_Keypad3; 416 | case VK_NUMPAD4: return ImGuiKey_Keypad4; 417 | case VK_NUMPAD5: return ImGuiKey_Keypad5; 418 | case VK_NUMPAD6: return ImGuiKey_Keypad6; 419 | case VK_NUMPAD7: return ImGuiKey_Keypad7; 420 | case VK_NUMPAD8: return ImGuiKey_Keypad8; 421 | case VK_NUMPAD9: return ImGuiKey_Keypad9; 422 | case VK_DECIMAL: return ImGuiKey_KeypadDecimal; 423 | case VK_DIVIDE: return ImGuiKey_KeypadDivide; 424 | case VK_MULTIPLY: return ImGuiKey_KeypadMultiply; 425 | case VK_SUBTRACT: return ImGuiKey_KeypadSubtract; 426 | case VK_ADD: return ImGuiKey_KeypadAdd; 427 | case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter; 428 | case VK_LSHIFT: return ImGuiKey_LeftShift; 429 | case VK_LCONTROL: return ImGuiKey_LeftCtrl; 430 | case VK_LMENU: return ImGuiKey_LeftAlt; 431 | case VK_LWIN: return ImGuiKey_LeftSuper; 432 | case VK_RSHIFT: return ImGuiKey_RightShift; 433 | case VK_RCONTROL: return ImGuiKey_RightCtrl; 434 | case VK_RMENU: return ImGuiKey_RightAlt; 435 | case VK_RWIN: return ImGuiKey_RightSuper; 436 | case VK_APPS: return ImGuiKey_Menu; 437 | case '0': return ImGuiKey_0; 438 | case '1': return ImGuiKey_1; 439 | case '2': return ImGuiKey_2; 440 | case '3': return ImGuiKey_3; 441 | case '4': return ImGuiKey_4; 442 | case '5': return ImGuiKey_5; 443 | case '6': return ImGuiKey_6; 444 | case '7': return ImGuiKey_7; 445 | case '8': return ImGuiKey_8; 446 | case '9': return ImGuiKey_9; 447 | case 'A': return ImGuiKey_A; 448 | case 'B': return ImGuiKey_B; 449 | case 'C': return ImGuiKey_C; 450 | case 'D': return ImGuiKey_D; 451 | case 'E': return ImGuiKey_E; 452 | case 'F': return ImGuiKey_F; 453 | case 'G': return ImGuiKey_G; 454 | case 'H': return ImGuiKey_H; 455 | case 'I': return ImGuiKey_I; 456 | case 'J': return ImGuiKey_J; 457 | case 'K': return ImGuiKey_K; 458 | case 'L': return ImGuiKey_L; 459 | case 'M': return ImGuiKey_M; 460 | case 'N': return ImGuiKey_N; 461 | case 'O': return ImGuiKey_O; 462 | case 'P': return ImGuiKey_P; 463 | case 'Q': return ImGuiKey_Q; 464 | case 'R': return ImGuiKey_R; 465 | case 'S': return ImGuiKey_S; 466 | case 'T': return ImGuiKey_T; 467 | case 'U': return ImGuiKey_U; 468 | case 'V': return ImGuiKey_V; 469 | case 'W': return ImGuiKey_W; 470 | case 'X': return ImGuiKey_X; 471 | case 'Y': return ImGuiKey_Y; 472 | case 'Z': return ImGuiKey_Z; 473 | case VK_F1: return ImGuiKey_F1; 474 | case VK_F2: return ImGuiKey_F2; 475 | case VK_F3: return ImGuiKey_F3; 476 | case VK_F4: return ImGuiKey_F4; 477 | case VK_F5: return ImGuiKey_F5; 478 | case VK_F6: return ImGuiKey_F6; 479 | case VK_F7: return ImGuiKey_F7; 480 | case VK_F8: return ImGuiKey_F8; 481 | case VK_F9: return ImGuiKey_F9; 482 | case VK_F10: return ImGuiKey_F10; 483 | case VK_F11: return ImGuiKey_F11; 484 | case VK_F12: return ImGuiKey_F12; 485 | default: return ImGuiKey_None; 486 | } 487 | } 488 | 489 | // Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. 490 | #ifndef WM_MOUSEHWHEEL 491 | #define WM_MOUSEHWHEEL 0x020E 492 | #endif 493 | #ifndef DBT_DEVNODES_CHANGED 494 | #define DBT_DEVNODES_CHANGED 0x0007 495 | #endif 496 | 497 | // Win32 message handler (process Win32 mouse/keyboard inputs, etc.) 498 | // Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. 499 | // When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs. 500 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. 501 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. 502 | // Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags. 503 | // 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. 504 | // 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. 505 | #if 0 506 | // Copy this line into your .cpp file to forward declare the function. 507 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 508 | #endif 509 | IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 510 | { 511 | if (ImGui::GetCurrentContext() == nullptr) 512 | return 0; 513 | 514 | ImGuiIO& io = ImGui::GetIO(); 515 | ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); 516 | 517 | switch (msg) 518 | { 519 | case WM_MOUSEMOVE: 520 | case WM_NCMOUSEMOVE: 521 | { 522 | // We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events 523 | const int area = (msg == WM_MOUSEMOVE) ? 1 : 2; 524 | bd->MouseHwnd = hwnd; 525 | if (bd->MouseTrackedArea != area) 526 | { 527 | TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 }; 528 | TRACKMOUSEEVENT tme_track = { sizeof(tme_track), (DWORD)((area == 2) ? (TME_LEAVE | TME_NONCLIENT) : TME_LEAVE), hwnd, 0 }; 529 | if (bd->MouseTrackedArea != 0) 530 | ::TrackMouseEvent(&tme_cancel); 531 | ::TrackMouseEvent(&tme_track); 532 | bd->MouseTrackedArea = area; 533 | } 534 | POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) }; 535 | if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates. 536 | break; 537 | io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y); 538 | break; 539 | } 540 | case WM_MOUSELEAVE: 541 | case WM_NCMOUSELEAVE: 542 | { 543 | const int area = (msg == WM_MOUSELEAVE) ? 1 : 2; 544 | if (bd->MouseTrackedArea == area) 545 | { 546 | if (bd->MouseHwnd == hwnd) 547 | bd->MouseHwnd = nullptr; 548 | bd->MouseTrackedArea = 0; 549 | io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); 550 | } 551 | break; 552 | } 553 | case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: 554 | case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: 555 | case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: 556 | case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: 557 | { 558 | int button = 0; 559 | if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; } 560 | if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; } 561 | if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; } 562 | if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } 563 | if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr) 564 | ::SetCapture(hwnd); 565 | bd->MouseButtonsDown |= 1 << button; 566 | io.AddMouseButtonEvent(button, true); 567 | return 0; 568 | } 569 | case WM_LBUTTONUP: 570 | case WM_RBUTTONUP: 571 | case WM_MBUTTONUP: 572 | case WM_XBUTTONUP: 573 | { 574 | int button = 0; 575 | if (msg == WM_LBUTTONUP) { button = 0; } 576 | if (msg == WM_RBUTTONUP) { button = 1; } 577 | if (msg == WM_MBUTTONUP) { button = 2; } 578 | if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; } 579 | bd->MouseButtonsDown &= ~(1 << button); 580 | if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd) 581 | ::ReleaseCapture(); 582 | io.AddMouseButtonEvent(button, false); 583 | return 0; 584 | } 585 | case WM_MOUSEWHEEL: 586 | io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA); 587 | return 0; 588 | case WM_MOUSEHWHEEL: 589 | io.AddMouseWheelEvent(-(float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f); 590 | return 0; 591 | case WM_KEYDOWN: 592 | case WM_KEYUP: 593 | case WM_SYSKEYDOWN: 594 | case WM_SYSKEYUP: 595 | { 596 | const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN); 597 | if (wParam < 256) 598 | { 599 | // Submit modifiers 600 | ImGui_ImplWin32_UpdateKeyModifiers(); 601 | 602 | // Obtain virtual key code 603 | // (keypad enter doesn't have its own... VK_RETURN with KF_EXTENDED flag means keypad enter, see IM_VK_KEYPAD_ENTER definition for details, it is mapped to ImGuiKey_KeyPadEnter.) 604 | int vk = (int)wParam; 605 | if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED)) 606 | vk = IM_VK_KEYPAD_ENTER; 607 | 608 | // Submit key event 609 | const ImGuiKey key = ImGui_ImplWin32_VirtualKeyToImGuiKey(vk); 610 | const int scancode = (int)LOBYTE(HIWORD(lParam)); 611 | if (key != ImGuiKey_None) 612 | ImGui_ImplWin32_AddKeyEvent(key, is_key_down, vk, scancode); 613 | 614 | // Submit individual left/right modifier events 615 | if (vk == VK_SHIFT) 616 | { 617 | // Important: Shift keys tend to get stuck when pressed together, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkarounds() 618 | if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); } 619 | if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); } 620 | } 621 | else if (vk == VK_CONTROL) 622 | { 623 | if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); } 624 | if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); } 625 | } 626 | else if (vk == VK_MENU) 627 | { 628 | if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); } 629 | if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); } 630 | } 631 | } 632 | return 0; 633 | } 634 | case WM_SETFOCUS: 635 | case WM_KILLFOCUS: 636 | io.AddFocusEvent(msg == WM_SETFOCUS); 637 | return 0; 638 | case WM_CHAR: 639 | if (::IsWindowUnicode(hwnd)) 640 | { 641 | // You can also use ToAscii()+GetKeyboardState() to retrieve characters. 642 | if (wParam > 0 && wParam < 0x10000) 643 | io.AddInputCharacterUTF16((unsigned short)wParam); 644 | } 645 | else 646 | { 647 | wchar_t wch = 0; 648 | ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char*)&wParam, 1, &wch, 1); 649 | io.AddInputCharacter(wch); 650 | } 651 | return 0; 652 | case WM_SETCURSOR: 653 | // This is required to restore cursor when transitioning from e.g resize borders to client area. 654 | if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) 655 | return 1; 656 | return 0; 657 | case WM_DEVICECHANGE: 658 | #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD 659 | if ((UINT)wParam == DBT_DEVNODES_CHANGED) 660 | bd->WantUpdateHasGamepad = true; 661 | #endif 662 | return 0; 663 | } 664 | return 0; 665 | } 666 | 667 | 668 | //-------------------------------------------------------------------------------------------------------- 669 | // DPI-related helpers (optional) 670 | //-------------------------------------------------------------------------------------------------------- 671 | // - Use to enable DPI awareness without having to create an application manifest. 672 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 673 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 674 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 675 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 676 | //--------------------------------------------------------------------------------------------------------- 677 | // This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable. 678 | // ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically. 679 | // If you are trying to implement your own backend for your own engine, you may ignore that noise. 680 | //--------------------------------------------------------------------------------------------------------- 681 | 682 | // Perform our own check with RtlVerifyVersionInfo() instead of using functions from as they 683 | // require a manifest to be functional for checks above 8.1. See https://github.com/ocornut/imgui/issues/4200 684 | static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD) 685 | { 686 | typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG); 687 | static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = nullptr; 688 | if (RtlVerifyVersionInfoFn == nullptr) 689 | if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll")) 690 | RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo"); 691 | if (RtlVerifyVersionInfoFn == nullptr) 692 | return FALSE; 693 | 694 | RTL_OSVERSIONINFOEXW versionInfo = { }; 695 | ULONGLONG conditionMask = 0; 696 | versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); 697 | versionInfo.dwMajorVersion = major; 698 | versionInfo.dwMinorVersion = minor; 699 | VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); 700 | VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); 701 | return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE; 702 | } 703 | 704 | #define _IsWindowsVistaOrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA 705 | #define _IsWindows8OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8 706 | #define _IsWindows8Point1OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE 707 | #define _IsWindows10OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0A00), LOBYTE(0x0A00), 0) // _WIN32_WINNT_WINTHRESHOLD / _WIN32_WINNT_WIN10 708 | 709 | #ifndef DPI_ENUMS_DECLARED 710 | typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS; 711 | typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE; 712 | #endif 713 | #ifndef _DPI_AWARENESS_CONTEXTS_ 714 | DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); 715 | #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3 716 | #endif 717 | #ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 718 | #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4 719 | #endif 720 | typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+ 721 | typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+ 722 | typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update) 723 | 724 | // Helper function to enable DPI awareness without setting up a manifest 725 | void ImGui_ImplWin32_EnableDpiAwareness() 726 | { 727 | if (_IsWindows10OrGreater()) 728 | { 729 | static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process 730 | if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext")) 731 | { 732 | SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); 733 | return; 734 | } 735 | } 736 | if (_IsWindows8Point1OrGreater()) 737 | { 738 | static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process 739 | if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness")) 740 | { 741 | SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE); 742 | return; 743 | } 744 | } 745 | #if _WIN32_WINNT >= 0x0600 746 | ::SetProcessDPIAware(); 747 | #endif 748 | } 749 | 750 | #if defined(_MSC_VER) && !defined(NOGDI) 751 | #pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32' 752 | #endif 753 | 754 | float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor) 755 | { 756 | UINT xdpi = 96, ydpi = 96; 757 | if (_IsWindows8Point1OrGreater()) 758 | { 759 | static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process 760 | static PFN_GetDpiForMonitor GetDpiForMonitorFn = nullptr; 761 | if (GetDpiForMonitorFn == nullptr && shcore_dll != nullptr) 762 | GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor"); 763 | if (GetDpiForMonitorFn != nullptr) 764 | { 765 | GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); 766 | IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! 767 | return xdpi / 96.0f; 768 | } 769 | } 770 | #ifndef NOGDI 771 | const HDC dc = ::GetDC(nullptr); 772 | xdpi = ::GetDeviceCaps(dc, LOGPIXELSX); 773 | ydpi = ::GetDeviceCaps(dc, LOGPIXELSY); 774 | IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! 775 | ::ReleaseDC(nullptr, dc); 776 | #endif 777 | return xdpi / 96.0f; 778 | } 779 | 780 | float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd) 781 | { 782 | HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST); 783 | return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor); 784 | } 785 | 786 | //--------------------------------------------------------------------------------------------------------- 787 | // Transparency related helpers (optional) 788 | //-------------------------------------------------------------------------------------------------------- 789 | 790 | #if defined(_MSC_VER) 791 | #pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi' 792 | #endif 793 | 794 | // [experimental] 795 | // Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c 796 | // (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW) 797 | void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd) 798 | { 799 | if (!_IsWindowsVistaOrGreater()) 800 | return; 801 | 802 | BOOL composition; 803 | if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition) 804 | return; 805 | 806 | BOOL opaque; 807 | DWORD color; 808 | if (_IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque)) 809 | { 810 | HRGN region = ::CreateRectRgn(0, 0, -1, -1); 811 | DWM_BLURBEHIND bb = {}; 812 | bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; 813 | bb.hRgnBlur = region; 814 | bb.fEnable = TRUE; 815 | ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); 816 | ::DeleteObject(region); 817 | } 818 | else 819 | { 820 | DWM_BLURBEHIND bb = {}; 821 | bb.dwFlags = DWM_BB_ENABLE; 822 | ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb); 823 | } 824 | } 825 | 826 | //--------------------------------------------------------------------------------------------------------- 827 | --------------------------------------------------------------------------------