├── meni.h ├── minhook ├── minhook.lib ├── LICENSE.txt └── MinHook.h ├── l0st.dev FN.user ├── l0st.dev FN.vcxproj.user ├── core.h ├── spoofinternal.asm ├── dllmain.cpp ├── settings.h ├── imgui ├── LICENSE.txt ├── imgui_impl_dx11.h ├── imconfig.h ├── stb_rect_pack.h ├── imgui_impl_dx11.cpp └── stb_textedit.h ├── MavenUpdated.sln ├── l0st.dev FN.sln ├── settings.cpp ├── offsets.h ├── Structs.h ├── util.h ├── l0st.dev FN.vcxproj.filters ├── stdafx.h ├── offsets.cpp ├── xor.hpp ├── core.cpp ├── l0st.dev FN.vcxproj ├── Util.cpp └── menu.cpp /meni.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Render { 4 | bool Initialize(); 5 | } -------------------------------------------------------------------------------- /minhook/minhook.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImperiousDev/MavenSourceUpdated/HEAD/minhook/minhook.lib -------------------------------------------------------------------------------- /l0st.dev FN.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /l0st.dev FN.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /core.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | #define BONE_HEAD_ID (66) 4 | 5 | namespace Core { 6 | extern bool NoSpread; 7 | extern PVOID LocalPlayerPawn; 8 | extern PVOID LocalPlayerController; 9 | extern PVOID TargetPawn; 10 | extern PVOID(*ProcessEvent)(PVOID, PVOID, PVOID, PVOID); 11 | 12 | BOOLEAN Initialize(); 13 | } -------------------------------------------------------------------------------- /spoofinternal.asm: -------------------------------------------------------------------------------- 1 | PUBLIC RetSpoofStub 2 | 3 | .code 4 | 5 | RetSpoofStub PROC 6 | pop r11 7 | add rsp, 8 8 | mov rax, [rsp + 24] 9 | 10 | mov r10, [rax] 11 | mov [rsp], r10 12 | 13 | mov r10, [rax + 8] 14 | mov [rax + 8], r11 15 | 16 | mov [rax + 16], rdi 17 | lea rdi, fixup 18 | mov [rax], rdi 19 | mov rdi, rax 20 | 21 | jmp r10 22 | 23 | fixup: 24 | sub rsp, 16 25 | mov rcx, rdi 26 | mov rdi, [rcx + 16] 27 | jmp QWORD PTR [rcx + 8] 28 | RetSpoofStub ENDP 29 | 30 | END -------------------------------------------------------------------------------- /dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | 4 | VOID Main() { 5 | Util::CreateConsole(); 6 | MH_Initialize(); 7 | SettingsHelper::Initialize(); 8 | 9 | if (!Util::Initialize()) { 10 | return; 11 | } 12 | 13 | if (!Offsets::Initialize()) { 14 | return; 15 | } 16 | 17 | if (!Core::Initialize()) { 18 | return; 19 | } 20 | 21 | if (!Render::Initialize()) { 22 | return; 23 | } 24 | } 25 | 26 | BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { 27 | if (reason == DLL_PROCESS_ATTACH) { 28 | Main(); 29 | } 30 | 31 | return TRUE; 32 | } -------------------------------------------------------------------------------- /settings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct { 4 | bool Aimbot; 5 | bool AutoAimbot; 6 | bool SilentAimbot; 7 | bool NoSpreadAimbot; 8 | float AimbotFOV; 9 | float AimbotSlow; 10 | bool InstantReload; 11 | float FOV; 12 | 13 | struct { 14 | bool AimbotFOV; 15 | bool Players; 16 | bool PlayerLines; 17 | bool PlayerNames; 18 | float PlayerVisibleColor[3]; 19 | float PlayerNotVisibleColor[3]; 20 | bool Ammo; 21 | bool Containers; 22 | bool Weapons; 23 | INT MinWeaponTier; 24 | } ESP; 25 | } SETTINGS; 26 | 27 | extern SETTINGS Settings; 28 | 29 | namespace SettingsHelper { 30 | VOID Initialize(); 31 | VOID SaveSettings(); 32 | } -------------------------------------------------------------------------------- /imgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2019 Omar Cornut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /imgui/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // ImGui Win32 + DirectX11 binding 2 | // In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. 3 | 4 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 5 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 6 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 7 | // https://github.com/ocornut/imgui 8 | 9 | struct ID3D11Device; 10 | struct ID3D11DeviceContext; 11 | 12 | IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context); 13 | IMGUI_API void ImGui_ImplDX11_Shutdown(); 14 | IMGUI_API void ImGui_ImplDX11_NewFrame(); 15 | 16 | // Use if you want to reset your rendering device without losing ImGui state. 17 | IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 18 | IMGUI_API bool ImGui_ImplDX11_CreateDeviceObjects(); 19 | 20 | // Handler for Win32 messages, update mouse/keyboard data. 21 | // You may or not need this for your implementation, but it can serve as reference for handling inputs. 22 | // Commented out to avoid dragging dependencies on types. You can copy the extern declaration in your code. 23 | /* 24 | IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 25 | */ 26 | -------------------------------------------------------------------------------- /MavenUpdated.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29806.167 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "l0st.dev FN", "l0st.dev FN\l0st.dev FN.vcxproj", "{432CD352-DFE6-4AC6-B858-3F74D5CB161F}" 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 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Debug|x64.ActiveCfg = Debug|x64 17 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Debug|x64.Build.0 = Debug|x64 18 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Debug|x86.ActiveCfg = Debug|Win32 19 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Debug|x86.Build.0 = Debug|Win32 20 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Release|x64.ActiveCfg = Release|x64 21 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Release|x64.Build.0 = Release|x64 22 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Release|x86.ActiveCfg = Release|Win32 23 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {DAD1E343-CD6C-422B-8676-0933ABCD6799} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /l0st.dev FN.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29806.167 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "l0st.dev FN", "l0st.dev FN\l0st.dev FN.vcxproj", "{432CD352-DFE6-4AC6-B858-3F74D5CB161F}" 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 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Debug|x64.ActiveCfg = Debug|x64 17 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Debug|x64.Build.0 = Debug|x64 18 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Debug|x86.ActiveCfg = Debug|Win32 19 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Debug|x86.Build.0 = Debug|Win32 20 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Release|x64.ActiveCfg = Release|x64 21 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Release|x64.Build.0 = Release|x64 22 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Release|x86.ActiveCfg = Release|Win32 23 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {DAD1E343-CD6C-422B-8676-0933ABCD6799} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /settings.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | SETTINGS Settings = { 0 }; 4 | 5 | namespace SettingsHelper { 6 | VOID SaveSettings() { 7 | CHAR path[0xFF]; 8 | GetTempPathA(sizeof(path) / sizeof(path[0]), path); 9 | strcat(path, ("fnambt.settings")); 10 | 11 | auto file = fopen(path, ("wb")); 12 | if (file) { 13 | fwrite(&Settings, sizeof(Settings), 1, file); 14 | fclose(file); 15 | } 16 | } 17 | 18 | VOID ResetSettings() { 19 | Settings = { 0 }; 20 | Settings.Aimbot = true; 21 | Settings.AutoAimbot = false; 22 | Settings.NoSpreadAimbot = true; 23 | Settings.AimbotFOV = 100.0f; 24 | Settings.AimbotSlow = 0.0f; 25 | Settings.InstantReload = true; 26 | Settings.FOV = 120.0f; 27 | Settings.ESP.AimbotFOV = true; 28 | Settings.ESP.Players = true; 29 | Settings.ESP.PlayerNames = true; 30 | Settings.ESP.PlayerVisibleColor[0] = 1.0f; 31 | Settings.ESP.PlayerVisibleColor[1] = 0.0f; 32 | Settings.ESP.PlayerVisibleColor[2] = 0.0f; 33 | Settings.ESP.PlayerNotVisibleColor[0] = 1.0f; 34 | Settings.ESP.PlayerNotVisibleColor[1] = 0.08f; 35 | Settings.ESP.PlayerNotVisibleColor[2] = 0.6f; 36 | Settings.ESP.Containers = true; 37 | Settings.ESP.Weapons = true; 38 | Settings.ESP.MinWeaponTier = 4; 39 | 40 | SaveSettings(); 41 | } 42 | 43 | VOID Initialize() { 44 | CHAR path[0xFF] = { 0 }; 45 | GetTempPathA(sizeof(path) / sizeof(path[0]), path); 46 | strcat(path, ("fnambt.settings")); 47 | 48 | auto file = fopen(path, ("rb")); 49 | if (file) { 50 | fseek(file, 0, SEEK_END); 51 | auto size = ftell(file); 52 | 53 | if (size == sizeof(Settings)) { 54 | fseek(file, 0, SEEK_SET); 55 | fread(&Settings, sizeof(Settings), 1, file); 56 | fclose(file); 57 | } 58 | else { 59 | fclose(file); 60 | ResetSettings(); 61 | } 62 | } 63 | else { 64 | ResetSettings(); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /offsets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | namespace Offsets { 4 | typedef struct { 5 | LPCWSTR Name; 6 | DWORD& Offset; 7 | } OFFSET; 8 | 9 | extern PVOID* uWorld; 10 | 11 | namespace Engine { 12 | namespace World { 13 | extern DWORD OwningGameInstance; 14 | extern DWORD Levels; 15 | } 16 | 17 | namespace Level { 18 | extern DWORD AActors; 19 | } 20 | 21 | namespace GameInstance { 22 | extern DWORD LocalPlayers; 23 | } 24 | 25 | namespace Player { 26 | extern DWORD PlayerController; 27 | } 28 | 29 | namespace Controller { 30 | extern DWORD ControlRotation; 31 | extern PVOID SetControlRotation; 32 | } 33 | 34 | namespace PlayerController { 35 | extern DWORD AcknowledgedPawn; 36 | } 37 | 38 | namespace Pawn { 39 | extern DWORD PlayerState; 40 | } 41 | 42 | namespace PlayerState { 43 | extern PVOID GetPlayerName; 44 | } 45 | 46 | namespace Actor { 47 | extern DWORD RootComponent; 48 | } 49 | 50 | namespace Character { 51 | extern DWORD Mesh; 52 | } 53 | 54 | namespace SceneComponent { 55 | extern DWORD RelativeLocation; 56 | extern DWORD ComponentVelocity; 57 | } 58 | 59 | namespace StaticMeshComponent { 60 | extern DWORD ComponentToWorld; 61 | extern DWORD StaticMesh; 62 | } 63 | 64 | namespace SkinnedMeshComponent { 65 | extern DWORD CachedWorldSpaceBounds; 66 | } 67 | } 68 | 69 | namespace FortniteGame { 70 | namespace FortPawn { 71 | extern DWORD bIsDBNO; 72 | extern DWORD bIsDying; 73 | extern DWORD CurrentWeapon; 74 | } 75 | 76 | namespace FortPickup { 77 | extern DWORD PrimaryPickupItemEntry; 78 | } 79 | 80 | namespace FortItemEntry { 81 | extern DWORD ItemDefinition; 82 | } 83 | 84 | namespace FortItemDefinition { 85 | extern DWORD DisplayName; 86 | extern DWORD Tier; 87 | } 88 | 89 | namespace FortPlayerStateAthena { 90 | extern DWORD TeamIndex; 91 | } 92 | 93 | namespace FortWeapon { 94 | extern DWORD WeaponData; 95 | } 96 | 97 | namespace FortWeaponItemDefinition { 98 | extern DWORD WeaponStatHandle; 99 | } 100 | 101 | namespace FortProjectileAthena { 102 | extern DWORD FireStartLoc; 103 | } 104 | 105 | namespace FortBaseWeaponStats { 106 | extern DWORD ReloadTime; 107 | } 108 | 109 | namespace BuildingContainer { 110 | extern DWORD bAlreadySearched; 111 | } 112 | } 113 | 114 | BOOLEAN Initialize(); 115 | } -------------------------------------------------------------------------------- /imgui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // USER IMPLEMENTATION 3 | // This file contains compile-time options for ImGui. 4 | // Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). 5 | //----------------------------------------------------------------------------- 6 | 7 | #pragma once 8 | 9 | //---- Define assertion handler. Defaults to calling assert(). 10 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 11 | 12 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows. 13 | //#define IMGUI_API __declspec( dllexport ) 14 | //#define IMGUI_API __declspec( dllimport ) 15 | 16 | //---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names 17 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 18 | 19 | //---- Include imgui_user.h at the end of imgui.h 20 | //#define IMGUI_INCLUDE_IMGUI_USER_H 21 | 22 | //---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) 23 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS 24 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS 25 | 26 | //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) 27 | //---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp to learn why. 28 | //#define IMGUI_DISABLE_DEMO_WINDOWS 29 | 30 | //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. 31 | //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS 32 | 33 | //---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends) 34 | //#define IMGUI_USE_BGRA_PACKED_COLOR 35 | 36 | //---- Implement STB libraries in a namespace to avoid linkage conflicts 37 | //#define IMGUI_STB_NAMESPACE ImGuiStb 38 | 39 | //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. 40 | /* 41 | #define IM_VEC2_CLASS_EXTRA \ 42 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 43 | operator MyVec2() const { return MyVec2(x,y); } 44 | 45 | #define IM_VEC4_CLASS_EXTRA \ 46 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 47 | operator MyVec4() const { return MyVec4(x,y,z,w); } 48 | */ 49 | 50 | //---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices 51 | //#define ImDrawIdx unsigned int 52 | 53 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 54 | //---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers. 55 | /* 56 | namespace ImGui 57 | { 58 | void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL); 59 | } 60 | */ 61 | 62 | -------------------------------------------------------------------------------- /Structs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | 4 | class UClass { 5 | public: 6 | BYTE _padding_0[0x40]; 7 | UClass* SuperClass; 8 | }; 9 | 10 | class UObject { 11 | public: 12 | PVOID VTableObject; 13 | DWORD ObjectFlags; 14 | DWORD InternalIndex; 15 | UClass* Class; 16 | BYTE _padding_0[0x8]; 17 | UObject* Outer; 18 | 19 | inline BOOLEAN IsA(PVOID parentClass) { 20 | for (auto super = this->Class; super; super = super->SuperClass) { 21 | if (super == parentClass) { 22 | return TRUE; 23 | } 24 | } 25 | 26 | return FALSE; 27 | } 28 | }; 29 | 30 | class FUObjectItem { 31 | public: 32 | UObject* Object; 33 | DWORD Flags; 34 | DWORD ClusterIndex; 35 | DWORD SerialNumber; 36 | DWORD SerialNumber2; 37 | }; 38 | 39 | class TUObjectArray { 40 | public: 41 | FUObjectItem* Objects[9]; 42 | }; 43 | 44 | class GObjects { 45 | public: 46 | TUObjectArray* ObjectArray; 47 | BYTE _padding_0[0xC]; 48 | DWORD ObjectCount; 49 | }; 50 | 51 | template 52 | struct TArray { 53 | friend struct FString; 54 | 55 | public: 56 | inline TArray() { 57 | Data = nullptr; 58 | Count = Max = 0; 59 | }; 60 | 61 | inline INT Num() const { 62 | return Count; 63 | }; 64 | 65 | inline T& operator[](INT i) { 66 | return Data[i]; 67 | }; 68 | 69 | inline BOOLEAN IsValidIndex(INT i) { 70 | return i < Num(); 71 | } 72 | 73 | private: 74 | T* Data; 75 | INT Count; 76 | INT Max; 77 | }; 78 | 79 | struct FString : private TArray { 80 | FString() { 81 | Data = nullptr; 82 | Max = Count = 0; 83 | } 84 | 85 | FString(LPCWSTR other) { 86 | Max = Count = static_cast(wcslen(other)); 87 | 88 | if (Count) { 89 | Data = const_cast(other); 90 | } 91 | }; 92 | 93 | inline BOOLEAN IsValid() { 94 | return Data != nullptr; 95 | } 96 | 97 | inline PWCHAR c_str() { 98 | return Data; 99 | } 100 | }; 101 | 102 | class FText { 103 | private: 104 | char _padding_[0x28]; 105 | PWCHAR Name; 106 | DWORD Length; 107 | 108 | public: 109 | inline PWCHAR c_str() { 110 | return Name; 111 | } 112 | }; 113 | 114 | typedef struct { 115 | float X, Y, Z; 116 | } FVector; 117 | 118 | typedef struct { 119 | float X, Y; 120 | } FVector2D; 121 | 122 | typedef struct { 123 | float Pitch; 124 | float Yaw; 125 | float Roll; 126 | } FRotator; 127 | 128 | typedef struct { 129 | FVector Location; 130 | FRotator Rotation; 131 | float FOV; 132 | float OrthoWidth; 133 | float OrthoNearClipPlane; 134 | float OrthoFarClipPlane; 135 | float AspectRatio; 136 | } FMinimalViewInfo; 137 | 138 | typedef struct { 139 | float M[4][4]; 140 | } FMatrix; 141 | 142 | typedef struct { 143 | FVector ViewOrigin; 144 | char _padding_0[4]; 145 | FMatrix ViewRotationMatrix; 146 | FMatrix ProjectionMatrix; 147 | } FSceneViewProjectionData; 148 | 149 | typedef struct { 150 | FVector Origin; 151 | FVector BoxExtent; 152 | float SphereRadius; 153 | } FBoxSphereBounds; -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | #define PI (3.141592653589793f) 4 | #define RELATIVE_ADDR(addr, size) ((PBYTE)((UINT_PTR)(addr) + *(PINT)((UINT_PTR)(addr) + ((size) - sizeof(INT))) + (size))) 5 | 6 | #define ReadPointer(base, offset) (*(PVOID *)(((PBYTE)base + offset))) 7 | #define ReadDWORD(base, offset) (*(PDWORD)(((PBYTE)base + offset))) 8 | #define ReadBYTE(base, offset) (*(((PBYTE)base + offset))) 9 | 10 | namespace Util { 11 | BOOLEAN Initialize(); 12 | VOID CreateConsole(); 13 | PBYTE FindPattern(LPCSTR pattern, LPCSTR mask); 14 | std::wstring GetObjectFirstName(UObject* object); 15 | std::wstring GetObjectName(UObject* object); 16 | PVOID FindObject(LPCWSTR name); 17 | BOOLEAN WorldToScreen(float width, float height, float inOutPosition[3]); 18 | VOID ToMatrixWithScale(float* in, float out[4][4]); 19 | VOID GetBoneLocation(float compMatrix[4][4], PVOID bones, DWORD index, float out[3]); 20 | BOOLEAN LineOfSightTo(PVOID PlayerController, PVOID Actor, FVector* ViewPoint); 21 | FMinimalViewInfo& GetViewInfo(); 22 | FVector* GetPawnRootLocation(PVOID pawn); 23 | VOID CalcAngle(float* src, float* dst, float* angles); 24 | 25 | extern VOID(*FreeInternal)(PVOID); 26 | 27 | namespace _SpoofCallInternal { 28 | extern "C" PVOID RetSpoofStub(); 29 | 30 | template 31 | inline Ret Wrapper(PVOID shell, Args... args) { 32 | auto fn = (Ret(*)(Args...))(shell); 33 | return fn(args...); 34 | } 35 | 36 | template 37 | struct Remapper { 38 | template 39 | static Ret Call(PVOID shell, PVOID shell_param, First first, Second second, Third third, Fourth fourth, Pack... pack) { 40 | return Wrapper(shell, first, second, third, fourth, shell_param, nullptr, pack...); 41 | } 42 | }; 43 | 44 | template 45 | struct Remapper> { 46 | template 47 | static Ret Call(PVOID shell, PVOID shell_param, First first = First{}, Second second = Second{}, Third third = Third{}, Fourth fourth = Fourth{}) { 48 | return Wrapper(shell, first, second, third, fourth, shell_param, nullptr); 49 | } 50 | }; 51 | } 52 | 53 | template 54 | Ret SpoofCall(Ret(*fn)(Args...), Args... args) { 55 | static PVOID trampoline = nullptr; 56 | if (!trampoline) { 57 | trampoline = Util::FindPattern("\xFF\x27", "xx"); 58 | if (!trampoline) { 59 | MessageBox(0, L"Failed to find valid trampoline", L"Failure", 0); 60 | ExitProcess(0); 61 | } 62 | } 63 | 64 | struct { 65 | PVOID Trampoline; 66 | PVOID Function; 67 | PVOID Reg; 68 | } params = { 69 | trampoline, 70 | reinterpret_cast(fn), 71 | }; 72 | 73 | return _SpoofCallInternal::Remapper::template Call(&_SpoofCallInternal::RetSpoofStub, ¶ms, args...); 74 | } 75 | } -------------------------------------------------------------------------------- /l0st.dev FN.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;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 | {8416771d-7784-41b1-bf2d-a01f84bbe794} 18 | 19 | 20 | {9bd2e87f-de85-49d3-ba86-5b6e9c0ad62b} 21 | 22 | 23 | {6ec731d4-4d85-41ae-ae50-fae180c0d113} 24 | 25 | 26 | {a1eeff16-103e-4ca4-9616-aea15be5a45e} 27 | 28 | 29 | {7889e946-8e7b-406b-8a86-308d22ca4c60} 30 | 31 | 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files\offsets 47 | 48 | 49 | Source Files\utils 50 | 51 | 52 | Source Files\menu 53 | 54 | 55 | Source Files\core 56 | 57 | 58 | Source Files\setting 59 | 60 | 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Source Files\offsets 88 | 89 | 90 | Source Files\utils 91 | 92 | 93 | Header Files 94 | 95 | 96 | Source Files\menu 97 | 98 | 99 | Source Files\core 100 | 101 | 102 | Source Files\setting 103 | 104 | 105 | 106 | 107 | Source Files 108 | 109 | 110 | -------------------------------------------------------------------------------- /stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _CRT_SECURE_NO_WARNINGS 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #pragma comment(lib, "minhook.lib") 19 | 20 | #include 21 | #pragma comment(lib, "d3d11.lib") 22 | 23 | #include "xor.hpp" 24 | #include "Structs.h" 25 | #include "util.h" 26 | #include "offsets.h" 27 | #include "meni.h" 28 | #include "core.h" 29 | #include "settings.h" 30 | 31 | 32 | ImGuiWindow &BeginScene(); 33 | VOID EndScene(ImGuiWindow &window); 34 | 35 | template 36 | T ReadMemory(DWORD_PTR address, const T& def = T()) 37 | { 38 | return *(T*)address; 39 | } 40 | 41 | typedef struct 42 | { 43 | DWORD R; 44 | DWORD G; 45 | DWORD B; 46 | DWORD A; 47 | }RGBA; 48 | 49 | class Color 50 | { 51 | public: 52 | 53 | RGBA NiggaGreen = { 128, 224, 0, 200 }; 54 | RGBA red = { 255,0,0,255 }; 55 | RGBA Magenta = { 255,0,255,255 }; 56 | RGBA yellow = { 255,255,0,255 }; 57 | RGBA grayblue = { 128,128,255,255 }; 58 | RGBA green = { 128,224,0,255 }; 59 | RGBA darkgreen = { 0,224,128,255 }; 60 | RGBA brown = { 192,96,0,255 }; 61 | RGBA pink = { 255,168,255,255 }; 62 | RGBA DarkYellow = { 216,216,0,255 }; 63 | RGBA SilverWhite = { 236,236,236,255 }; 64 | RGBA purple = { 144,0,255,255 }; 65 | RGBA Navy = { 88,48,224,255 }; 66 | RGBA skyblue = { 0,136,255,255 }; 67 | RGBA graygreen = { 128,160,128,255 }; 68 | RGBA blue = { 0,96,192,255 }; 69 | RGBA orange = { 255,128,0,255 }; 70 | RGBA peachred = { 255,80,128,255 }; 71 | RGBA reds = { 255,128,192,255 }; 72 | RGBA darkgray = { 96,96,96,255 }; 73 | RGBA Navys = { 0,0,128,255 }; 74 | RGBA darkgreens = { 0,128,0,255 }; 75 | RGBA darkblue = { 0,128,128,255 }; 76 | RGBA redbrown = { 128,0,0,255 }; 77 | RGBA purplered = { 128,0,128,255 }; 78 | RGBA greens = { 0,255,0,255 }; 79 | RGBA envy = { 0,255,255,255 }; 80 | RGBA black = { 0,0,0,255 }; 81 | RGBA gray = { 128,128,128,255 }; 82 | RGBA white = { 255,255,255,255 }; 83 | RGBA blues = { 30,144,255,255 }; 84 | RGBA lightblue = { 135,206,250,160 }; 85 | RGBA Scarlet = { 220, 20, 60, 160 }; 86 | RGBA white_ = { 255,255,255,200 }; 87 | RGBA gray_ = { 128,128,128,200 }; 88 | RGBA black_ = { 0,0,0,200 }; 89 | RGBA red_ = { 255,0,0,200 }; 90 | RGBA Magenta_ = { 255,0,255,200 }; 91 | RGBA yellow_ = { 255,255,0,200 }; 92 | RGBA grayblue_ = { 128,128,255,200 }; 93 | RGBA green_ = { 128,224,0,200 }; 94 | RGBA darkgreen_ = { 0,224,128,200 }; 95 | RGBA brown_ = { 192,96,0,200 }; 96 | RGBA pink_ = { 255,168,255,200 }; 97 | RGBA darkyellow_ = { 216,216,0,200 }; 98 | RGBA silverwhite_ = { 236,236,236,200 }; 99 | RGBA purple_ = { 144,0,255,200 }; 100 | RGBA Blue_ = { 88,48,224,200 }; 101 | RGBA skyblue_ = { 0,136,255,200 }; 102 | RGBA graygreen_ = { 128,160,128,200 }; 103 | RGBA blue_ = { 0,96,192,200 }; 104 | RGBA orange_ = { 255,128,0,200 }; 105 | RGBA pinks_ = { 255,80,128,200 }; 106 | RGBA Fuhong_ = { 255,128,192,200 }; 107 | RGBA darkgray_ = { 96,96,96,200 }; 108 | RGBA Navy_ = { 0,0,128,200 }; 109 | RGBA darkgreens_ = { 0,128,0,200 }; 110 | RGBA darkblue_ = { 0,128,128,200 }; 111 | RGBA redbrown_ = { 128,0,0,200 }; 112 | RGBA purplered_ = { 128,0,128,200 }; 113 | RGBA greens_ = { 0,255,0,200 }; 114 | RGBA envy_ = { 0,255,255,200 }; 115 | RGBA glassblack = { 0, 0, 0, 160 }; 116 | RGBA GlassBlue = { 65,105,225,80 }; 117 | RGBA glassyellow = { 255,255,0,160 }; 118 | RGBA glass = { 200,200,200,60 }; 119 | RGBA Plum = { 221,160,221,160 }; 120 | 121 | }; 122 | 123 | class Vector3 124 | { 125 | public: 126 | Vector3() : x(0.f), y(0.f), z(0.f) 127 | { 128 | 129 | } 130 | 131 | Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) 132 | { 133 | 134 | } 135 | ~Vector3() 136 | { 137 | 138 | } 139 | 140 | float x; 141 | float y; 142 | float z; 143 | 144 | inline float Dot(Vector3 v) 145 | { 146 | return x * v.x + y * v.y + z * v.z; 147 | } 148 | 149 | inline float Distance(Vector3 v) 150 | { 151 | return float(sqrtf(powf(v.x - x, 2.0) + powf(v.y - y, 2.0) + powf(v.z - z, 2.0))); 152 | } 153 | 154 | Vector3 operator+(Vector3 v) 155 | { 156 | return Vector3(x + v.x, y + v.y, z + v.z); 157 | } 158 | 159 | Vector3 operator-(Vector3 v) 160 | { 161 | return Vector3(x - v.x, y - v.y, z - v.z); 162 | } 163 | 164 | Vector3 operator*(float number) const { 165 | return Vector3(x * number, y * number, z * number); 166 | } 167 | }; -------------------------------------------------------------------------------- /minhook/LICENSE.txt: -------------------------------------------------------------------------------- 1 | MinHook - The Minimalistic API Hooking Library for x64/x86 2 | Copyright (C) 2009-2017 Tsuda Kageyu. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 18 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 19 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | ================================================================================ 28 | Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov. 29 | ================================================================================ 30 | Hacker Disassembler Engine 32 C 31 | Copyright (c) 2008-2009, Vyacheslav Patkov. 32 | All rights reserved. 33 | 34 | Redistribution and use in source and binary forms, with or without 35 | modification, are permitted provided that the following conditions 36 | are met: 37 | 38 | 1. Redistributions of source code must retain the above copyright 39 | notice, this list of conditions and the following disclaimer. 40 | 2. Redistributions in binary form must reproduce the above copyright 41 | notice, this list of conditions and the following disclaimer in the 42 | documentation and/or other materials provided with the distribution. 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 45 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 46 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 48 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 49 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 50 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 51 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 52 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 53 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 54 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 | 56 | ------------------------------------------------------------------------------- 57 | Hacker Disassembler Engine 64 C 58 | Copyright (c) 2008-2009, Vyacheslav Patkov. 59 | All rights reserved. 60 | 61 | Redistribution and use in source and binary forms, with or without 62 | modification, are permitted provided that the following conditions 63 | are met: 64 | 65 | 1. Redistributions of source code must retain the above copyright 66 | notice, this list of conditions and the following disclaimer. 67 | 2. Redistributions in binary form must reproduce the above copyright 68 | notice, this list of conditions and the following disclaimer in the 69 | documentation and/or other materials provided with the distribution. 70 | 71 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 72 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 73 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 74 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 75 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 76 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 77 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 78 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 79 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 80 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 81 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /offsets.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | namespace Offsets { 4 | PVOID* uWorld = 0; 5 | 6 | namespace Engine { 7 | namespace World { 8 | DWORD OwningGameInstance = 0; 9 | DWORD Levels = 0; 10 | } 11 | 12 | namespace Level { 13 | DWORD AActors = 0x98; 14 | } 15 | 16 | namespace GameInstance { 17 | DWORD LocalPlayers = 0; 18 | } 19 | 20 | namespace Player { 21 | DWORD PlayerController = 0x30; 22 | } 23 | 24 | namespace Controller { 25 | DWORD ControlRotation = 0; 26 | PVOID SetControlRotation = 0; 27 | } 28 | 29 | namespace PlayerController { 30 | DWORD AcknowledgedPawn = 0; 31 | DWORD PlayerCameraManager = 0; 32 | } 33 | 34 | namespace Pawn { 35 | DWORD PlayerState = 0x238; 36 | } 37 | 38 | namespace PlayerState { 39 | PVOID GetPlayerName = 0; 40 | } 41 | 42 | namespace Actor { 43 | DWORD RootComponent = 0; 44 | } 45 | 46 | namespace Character { 47 | DWORD Mesh = 0x278; 48 | } 49 | 50 | namespace SceneComponent { 51 | DWORD RelativeLocation = 0; 52 | DWORD ComponentVelocity = 0; 53 | } 54 | 55 | namespace StaticMeshComponent { 56 | DWORD ComponentToWorld = 0x14C; 57 | DWORD StaticMesh = 0x420; 58 | } 59 | 60 | namespace SkinnedMeshComponent { 61 | DWORD CachedWorldSpaceBounds = 0; 62 | } 63 | } 64 | 65 | namespace FortniteGame { 66 | namespace FortPawn { 67 | DWORD bIsDBNO = 0; 68 | DWORD bIsDying = 0; 69 | DWORD CurrentWeapon = 0; 70 | } 71 | 72 | namespace FortPickup { 73 | DWORD PrimaryPickupItemEntry = 0x280; 74 | } 75 | 76 | namespace FortItemEntry { 77 | DWORD ItemDefinition = 0x18; 78 | } 79 | 80 | namespace FortItemDefinition { 81 | DWORD DisplayName = 0x70; 82 | DWORD Tier = 0x54; 83 | } 84 | 85 | namespace FortPlayerStateAthena { 86 | DWORD TeamIndex = 0; 87 | } 88 | 89 | namespace FortWeapon { 90 | DWORD WeaponData = 0; 91 | } 92 | 93 | namespace FortWeaponItemDefinition { 94 | DWORD WeaponStatHandle = 0; 95 | } 96 | 97 | namespace FortProjectileAthena { 98 | DWORD FireStartLoc = 0x850; 99 | } 100 | 101 | namespace FortBaseWeaponStats { 102 | DWORD ReloadTime = 0; 103 | } 104 | 105 | namespace BuildingContainer { 106 | DWORD bAlreadySearched = 0; 107 | } 108 | } 109 | 110 | namespace UI { 111 | namespace ItemCount { 112 | DWORD ItemDefinition = 0; 113 | } 114 | } 115 | 116 | BOOLEAN Initialize() { 117 | auto addr = Util::FindPattern("\x48\x8B\x1D\x00\x00\x00\x00\x48\x85\xDB\x74\x3B\x41", "xxx????xxxxxx"); 118 | if (!addr) { 119 | MessageBox(0, L"Failed to find uWorld", L"Failure", 0); 120 | return FALSE; 121 | } 122 | 123 | uWorld = reinterpret_cast(RELATIVE_ADDR(addr, 7)); 124 | 125 | Engine::Controller::SetControlRotation = Util::FindObject(L"/Script/Engine.Controller.SetControlRotation"); 126 | if (!Engine::Controller::SetControlRotation) { 127 | MessageBox(0, L"Failed to find SetControlRotation", L"Failure", 0); 128 | return FALSE; 129 | } 130 | 131 | Engine::PlayerState::GetPlayerName = Util::FindObject(L"/Script/Engine.PlayerState.GetPlayerName"); 132 | if (!Engine::PlayerState::GetPlayerName) { 133 | MessageBox(0, L"Failed to find GetPlayerName", L"Failure", 0); 134 | return FALSE; 135 | } 136 | 137 | 138 | Engine::World::OwningGameInstance = 0x180; 139 | Engine::World::Levels = 0x138; 140 | Engine::GameInstance::LocalPlayers = 0x38; 141 | Engine::Player::PlayerController = 0x30; 142 | Engine::PlayerController::AcknowledgedPawn = 0x298; 143 | Engine::Controller::ControlRotation = 0x2A0; 144 | Engine::Pawn::PlayerState = 0x240; 145 | Engine::Actor::RootComponent = 0x130; 146 | Engine::Character::Mesh = 0x280; 147 | Engine::SceneComponent::RelativeLocation = 0x11C; 148 | Engine::SceneComponent::ComponentVelocity = 0x140; 149 | Engine::StaticMeshComponent::StaticMesh = 0x478; 150 | Engine::SkinnedMeshComponent::CachedWorldSpaceBounds = 0x5F8; 151 | FortniteGame::FortPawn::bIsDBNO = 0x552; 152 | FortniteGame::FortPawn::bIsDying = 0x538; 153 | FortniteGame::FortPlayerStateAthena::TeamIndex = 0xE88; 154 | FortniteGame::FortPickup::PrimaryPickupItemEntry = 0x2A8; 155 | FortniteGame::FortItemDefinition::DisplayName = 0x70; 156 | FortniteGame::FortItemDefinition::Tier = 0x54; 157 | FortniteGame::FortItemEntry::ItemDefinition = 0x18; 158 | FortniteGame::FortPawn::CurrentWeapon = 0x5C0; 159 | FortniteGame::FortWeapon::WeaponData = 0x378; 160 | FortniteGame::FortWeaponItemDefinition::WeaponStatHandle = 0x7B8; 161 | FortniteGame::FortProjectileAthena::FireStartLoc = 0x878; 162 | FortniteGame::FortBaseWeaponStats::ReloadTime = 0xFC; 163 | FortniteGame::BuildingContainer::bAlreadySearched = 0xC71; 164 | 165 | 166 | return TRUE; 167 | 168 | 169 | 170 | } 171 | } -------------------------------------------------------------------------------- /xor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace 7 | { 8 | constexpr int const_atoi(char c) 9 | { 10 | return c - '0'; 11 | } 12 | } 13 | 14 | #ifdef _MSC_VER 15 | #define ALWAYS_INLINE __forceinline 16 | #else 17 | #define ALWAYS_INLINE __attribute__((always_inline)) 18 | #endif 19 | 20 | template 21 | class _Basic_XorStr 22 | { 23 | using value_type = typename _string_type::value_type; 24 | static constexpr auto _length_minus_one = _length - 1; 25 | 26 | public: 27 | constexpr ALWAYS_INLINE _Basic_XorStr(value_type const (&str)[_length]) 28 | : _Basic_XorStr(str, std::make_index_sequence<_length_minus_one>()) 29 | { 30 | 31 | } 32 | 33 | inline auto c_str() const 34 | { 35 | decrypt(); 36 | 37 | return data; 38 | } 39 | 40 | inline auto str() const 41 | { 42 | decrypt(); 43 | 44 | return _string_type(data, data + _length_minus_one); 45 | } 46 | 47 | inline operator _string_type() const 48 | { 49 | return str(); 50 | } 51 | 52 | private: 53 | template 54 | constexpr ALWAYS_INLINE _Basic_XorStr(value_type const (&str)[_length], std::index_sequence) 55 | : data{ crypt(str[indices], indices)..., '\0' }, 56 | encrypted(true) 57 | { 58 | 59 | } 60 | 61 | static constexpr auto XOR_KEY = static_cast( 62 | const_atoi(__TIME__[7]) + 63 | const_atoi(__TIME__[6]) * 10 + 64 | const_atoi(__TIME__[4]) * 60 + 65 | const_atoi(__TIME__[3]) * 600 + 66 | const_atoi(__TIME__[1]) * 3600 + 67 | const_atoi(__TIME__[0]) * 36000 68 | ); 69 | 70 | static ALWAYS_INLINE constexpr auto crypt(value_type c, size_t i) 71 | { 72 | return static_cast(c ^ (XOR_KEY + i)); 73 | } 74 | 75 | inline void decrypt() const 76 | { 77 | if (encrypted) 78 | { 79 | for (size_t t = 0; t < _length_minus_one; t++) 80 | { 81 | data[t] = crypt(data[t], t); 82 | } 83 | encrypted = false; 84 | } 85 | } 86 | 87 | mutable value_type data[_length]; 88 | mutable bool encrypted; 89 | }; 90 | //--------------------------------------------------------------------------- 91 | template 92 | using XorStrA = _Basic_XorStr; 93 | template 94 | using XorStrW = _Basic_XorStr; 95 | template 96 | using XorStrU16 = _Basic_XorStr; 97 | template 98 | using XorStrU32 = _Basic_XorStr; 99 | //--------------------------------------------------------------------------- 100 | template 101 | inline auto operator==(const _Basic_XorStr<_string_type, _length>& lhs, const _Basic_XorStr<_string_type, _length2>& rhs) 102 | { 103 | static_assert(_length == _length2, "XorStr== different length"); 104 | 105 | return _length == _length2 && lhs.str() == rhs.str(); 106 | } 107 | //--------------------------------------------------------------------------- 108 | template 109 | inline auto operator==(const _string_type& lhs, const _Basic_XorStr<_string_type, _length>& rhs) 110 | { 111 | return lhs.size() == _length && lhs == rhs.str(); 112 | } 113 | //--------------------------------------------------------------------------- 114 | template 115 | inline auto& operator<<(_stream_type& lhs, const _Basic_XorStr<_string_type, _length>& rhs) 116 | { 117 | lhs << rhs.c_str(); 118 | 119 | return lhs; 120 | } 121 | //--------------------------------------------------------------------------- 122 | template 123 | inline auto operator+(const _Basic_XorStr<_string_type, _length>& lhs, const _Basic_XorStr<_string_type, _length2>& rhs) 124 | { 125 | return lhs.str() + rhs.str(); 126 | } 127 | //--------------------------------------------------------------------------- 128 | template 129 | inline auto operator+(const _string_type& lhs, const _Basic_XorStr<_string_type, _length>& rhs) 130 | { 131 | return lhs + rhs.str(); 132 | } 133 | //--------------------------------------------------------------------------- 134 | template 135 | constexpr ALWAYS_INLINE auto _xor_(char const (&str)[_length]) 136 | { 137 | return XorStrA<_length>(str); 138 | } 139 | //--------------------------------------------------------------------------- 140 | template 141 | constexpr ALWAYS_INLINE auto _xor_(wchar_t const (&str)[_length]) 142 | { 143 | return XorStrW<_length>(str); 144 | } 145 | //--------------------------------------------------------------------------- 146 | template 147 | constexpr ALWAYS_INLINE auto _xor_(char16_t const (&str)[_length]) 148 | { 149 | return XorStrU16<_length>(str); 150 | } 151 | //--------------------------------------------------------------------------- 152 | template 153 | constexpr ALWAYS_INLINE auto _xor_(char32_t const (&str)[_length]) 154 | { 155 | return XorStrU32<_length>(str); 156 | } 157 | //--------------------------------------------------------------------------- -------------------------------------------------------------------------------- /minhook/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /core.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | 4 | namespace Core { 5 | bool NoSpread = true; 6 | PVOID LocalPlayerPawn = nullptr; 7 | PVOID LocalPlayerController = nullptr; 8 | PVOID TargetPawn = nullptr; 9 | 10 | PVOID(*ProcessEvent)(PVOID, PVOID, PVOID, PVOID) = nullptr; 11 | PVOID(*CalculateSpread)(PVOID, float*, float*) = nullptr; 12 | float* (*CalculateShot)(PVOID, PVOID, PVOID) = nullptr; 13 | VOID(*ReloadOriginal)(PVOID, PVOID) = nullptr; 14 | PVOID(*GetWeaponStats)(PVOID) = nullptr; 15 | INT(*GetViewPoint)(PVOID, FMinimalViewInfo*, BYTE) = nullptr; 16 | 17 | PVOID calculateSpreadCaller = nullptr; 18 | float originalReloadTime = 0.0f; 19 | 20 | BOOLEAN GetTargetHead(FVector& out) { 21 | if (!Core::TargetPawn) { 22 | return FALSE; 23 | } 24 | 25 | auto mesh = ReadPointer(Core::TargetPawn, 0x280);//We need to find the names for this 26 | if (!mesh) { 27 | return FALSE; 28 | } 29 | 30 | auto bones = ReadPointer(mesh, 0x478); 31 | if (!bones) bones = ReadPointer(mesh, 0x478 + 0x10);//We need to find the names for this 32 | if (!bones) { 33 | return FALSE; 34 | } 35 | 36 | float compMatrix[4][4] = { 0 }; 37 | Util::ToMatrixWithScale(reinterpret_cast(reinterpret_cast(mesh) + 0x1C0), compMatrix); 38 | 39 | Util::GetBoneLocation(compMatrix, bones, 66, &out.X); 40 | return TRUE; 41 | } 42 | 43 | PVOID ProcessEventHook(UObject* object, UObject* func, PVOID params, PVOID result) { 44 | if (object && func) { 45 | auto objectName = Util::GetObjectFirstName(object); 46 | auto funcName = Util::GetObjectFirstName(func); 47 | 48 | 49 | if (wcsstr(objectName.c_str(), L"PlayerController") && wcsstr(funcName.c_str(), L"Kick")) { 50 | return 0; 51 | } 52 | 53 | do { 54 | if (Core::TargetPawn && Core::LocalPlayerController) { 55 | if (wcsstr(objectName.c_str(), L"B_Prj_Bullet_Sniper") && funcName == L"OnRep_FireStart") { 56 | //FVector head = { 0 }; 57 | FVector head{ 0 }; 58 | if (!GetTargetHead(head)) { 59 | break; 60 | } 61 | *reinterpret_cast(reinterpret_cast(object) + Offsets::FortniteGame::FortProjectileAthena::FireStartLoc) = head; 62 | auto root = reinterpret_cast(ReadPointer(object, Offsets::Engine::Actor::RootComponent)); 63 | *reinterpret_cast(root + Offsets::Engine::SceneComponent::RelativeLocation) = head; 64 | memset(root + Offsets::Engine::SceneComponent::ComponentVelocity, 0, sizeof(FVector)); 65 | } 66 | else if (!Settings.SilentAimbot && wcsstr(funcName.c_str(), L"Tick")) { 67 | FVector head; 68 | if (!GetTargetHead(head)) { 69 | break; 70 | } 71 | 72 | 73 | float angles[2] = { 0 }; 74 | Util::CalcAngle(&Util::GetViewInfo().Location.X, &head.X, angles); 75 | 76 | if (Settings.AimbotSlow <= 0.0f) { 77 | FRotator args = { 0 }; 78 | args.Pitch = angles[0]; 79 | args.Yaw = angles[1]; 80 | ProcessEvent(Core::LocalPlayerController, Offsets::Engine::Controller::SetControlRotation, &args, 0); 81 | } 82 | else { 83 | auto scale = Settings.AimbotSlow + 1.0f; 84 | auto currentRotation = Util::GetViewInfo().Rotation; 85 | 86 | FRotator args = { 0 }; 87 | args.Pitch = (angles[0] - currentRotation.Pitch) / scale + currentRotation.Pitch; 88 | args.Yaw = (angles[1] - currentRotation.Yaw) / scale + currentRotation.Yaw; 89 | ProcessEvent(Core::LocalPlayerController, Offsets::Engine::Controller::SetControlRotation, &args, 0); 90 | } 91 | } 92 | } 93 | } while (FALSE); 94 | } 95 | 96 | return ProcessEvent(object, func, params, result); 97 | } 98 | 99 | 100 | PVOID CalculateSpreadHook(PVOID arg0, float* arg1, float* arg2) { 101 | if (originalReloadTime != 0.0f) { 102 | auto localPlayerWeapon = ReadPointer(Core::LocalPlayerPawn, Offsets::FortniteGame::FortPawn::CurrentWeapon); 103 | if (localPlayerWeapon) { 104 | auto stats = GetWeaponStats(localPlayerWeapon); 105 | if (stats) { 106 | *reinterpret_cast(reinterpret_cast(stats) + Offsets::FortniteGame::FortBaseWeaponStats::ReloadTime) = originalReloadTime; 107 | originalReloadTime = 0.0f; 108 | } 109 | } 110 | } 111 | 112 | if (Settings.NoSpreadAimbot && Core::NoSpread && _ReturnAddress() == calculateSpreadCaller) { 113 | return 0; 114 | } 115 | 116 | return CalculateSpread(arg0, arg1, arg2); 117 | } 118 | 119 | 120 | float* CalculateShotHook(PVOID arg0, PVOID arg1, PVOID arg2) { 121 | auto ret = CalculateShot(arg0, arg1, arg2); 122 | if (ret && Settings.SilentAimbot && Core::TargetPawn && Core::LocalPlayerPawn) { 123 | auto mesh = ReadPointer(Core::TargetPawn, Offsets::Engine::Character::Mesh); 124 | if (!mesh) return ret; 125 | 126 | auto bones = ReadPointer(mesh, Offsets::Engine::StaticMeshComponent::StaticMesh); 127 | if (!bones) bones = ReadPointer(mesh, Offsets::Engine::StaticMeshComponent::StaticMesh + 0x10); 128 | if (!bones) return ret; 129 | 130 | float compMatrix[4][4] = { 0 }; 131 | Util::ToMatrixWithScale(reinterpret_cast(reinterpret_cast(mesh) + Offsets::Engine::StaticMeshComponent::ComponentToWorld), compMatrix); 132 | 133 | FVector head = { 0 }; 134 | Util::GetBoneLocation(compMatrix, bones, BONE_HEAD_ID, &head.X); 135 | 136 | auto rootPtr = Util::GetPawnRootLocation(Core::LocalPlayerPawn); 137 | if (!rootPtr) return ret; 138 | auto root = *rootPtr; 139 | 140 | auto dx = head.X - root.X; 141 | auto dy = head.Y - root.Y; 142 | auto dz = head.Z - root.Z; 143 | if (dx * dx + dy * dy + dz * dz < 125000.0f) { 144 | ret[4] = head.X; 145 | ret[5] = head.Y; 146 | ret[6] = head.Z; 147 | } 148 | else { 149 | head.Z -= 16.0f; 150 | root.Z += 45.0f; 151 | 152 | auto y = atan2f(head.Y - root.Y, head.X - root.X); 153 | 154 | root.X += cosf(y + 1.5708f) * 32.0f; 155 | root.Y += sinf(y + 1.5708f) * 32.0f; 156 | 157 | auto length = Util::SpoofCall(sqrtf, powf(head.X - root.X, 2) + powf(head.Y - root.Y, 2)); 158 | auto x = -atan2f(head.Z - root.Z, length); 159 | y = atan2f(head.Y - root.Y, head.X - root.X); 160 | 161 | x /= 2.0f; 162 | y /= 2.0f; 163 | 164 | ret[0] = -(sinf(x) * sinf(y)); 165 | ret[1] = sinf(x) * cosf(y); 166 | ret[2] = cosf(x) * sinf(y); 167 | ret[3] = cosf(x) * cosf(y); 168 | } 169 | } 170 | 171 | return ret; 172 | } 173 | 174 | INT GetViewPointHook(PVOID player, FMinimalViewInfo* viewInfo, BYTE stereoPass) { 175 | const float upperFOV = 50.534008f; 176 | const float lowerFOV = 40.0f; 177 | 178 | auto ret = GetViewPoint(player, viewInfo, stereoPass); 179 | 180 | auto fov = viewInfo->FOV; 181 | auto desired = (((180.0f - upperFOV) / (180.0f - 80.0f)) * (Settings.FOV - 80.0f)) + upperFOV; 182 | 183 | if (fov > upperFOV) { 184 | fov = desired; 185 | } 186 | else if (fov > lowerFOV) { 187 | fov = (((fov - lowerFOV) / (upperFOV - lowerFOV)) * (desired - lowerFOV)) + lowerFOV; 188 | } 189 | 190 | // Do whatever you want with viewInfo to change the camera location 191 | viewInfo->FOV = fov; 192 | 193 | return ret; 194 | } 195 | 196 | VOID ReloadHook(PVOID arg0, PVOID arg1) { 197 | if (Settings.InstantReload && Core::LocalPlayerPawn) { 198 | auto localPlayerWeapon = ReadPointer(Core::LocalPlayerPawn, Offsets::FortniteGame::FortPawn::CurrentWeapon); 199 | if (localPlayerWeapon) { 200 | auto stats = GetWeaponStats(localPlayerWeapon); 201 | if (stats) { 202 | auto& reloadTime = *reinterpret_cast(reinterpret_cast(stats) + Offsets::FortniteGame::FortBaseWeaponStats::ReloadTime); 203 | if (reloadTime != 0.01f) { 204 | originalReloadTime = reloadTime; 205 | reloadTime = 0.01f; 206 | } 207 | } 208 | } 209 | } 210 | 211 | ReloadOriginal(arg0, arg1); 212 | } 213 | 214 | PVOID* Proccess = 0; 215 | 216 | BOOLEAN Initialize() { 217 | 218 | // GetWeaponStats 219 | auto addr = Util::FindPattern("\x48\x83\xEC\x58\x48\x8B\x91\x00\x00\x00\x00\x48\x85\xD2\x0F\x84\x00\x00\x00\x00\xF6\x81\x00\x00\x00\x00\x00\x74\x10\x48\x8B\x81\x00\x00\x00\x00\x48\x85\xC0\x0F\x85\x00\x00\x00\x00\x48\x8B\x8A\x00\x00\x00\x00\x48\x89\x5C\x24\x00\x48\x8D\x9A\x00\x00\x00\x00\x48\x85\xC9", "xxxxxxx????xxxxx????xx?????xxxxx????xxxxx????xxx????xxxx?xxx????xxx"); 220 | if (!addr) { 221 | MessageBox(0, L"Failed to find GetWeaponStats", L"Failure", 0); 222 | return FALSE; 223 | } 224 | 225 | GetWeaponStats = reinterpret_cast(addr); 226 | 227 | //// ProcessEvent 228 | //addr = Util::FindPattern("\x40\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x81\xEC\x00\x00\x00\x00\x48\x8D\x6C\x24\x00\x48\x89\x9D\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\x48\x33\xC5\x48\x89\x85\x00\x00\x00\x00\x8B\x41\x0C\x45\x33\xF6\x3B\x05\x00\x00\x00\x00\x4D\x8B\xF8\x48\x8B\xF2\x4C\x8B\xE1\x41\xB8\x00\x00\x00\x00\x7D\x2A", "xxxxxxxxxxxxxxx????xxxx?xxx????xxx????xxxxxx????xxxxxxxx????xxxxxxxxxxx????xx"); 229 | //if (!addr) { 230 | // MessageBox(0, L"Failed to find ProcessEvent", L"Failure", 0); 231 | // return FALSE; 232 | //} 233 | 234 | MH_CreateHook(addr, ProcessEventHook, (PVOID*)&ProcessEvent); 235 | MH_EnableHook(addr); 236 | 237 | //CalculateShot 238 | addr = Util::FindPattern("\x48\x89\x5c\x24\x10\x4c\x89\x4c\x24\x20\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8d\x6c\x24\xd0\x48\x81\xec\x30", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 239 | if (!addr) { 240 | MessageBox(0, L"Failed to find CalculateShot", L"Failure", 0); 241 | return FALSE; 242 | } 243 | 244 | MH_CreateHook(addr, CalculateShotHook, (PVOID*)&CalculateShot); 245 | MH_EnableHook(addr); 246 | 247 | // GetViewPoint 248 | addr = Util::FindPattern("\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x20\x48\x8B\xD9\x41\x8B\xF0\x48\x8B\x49\x30\x48\x8B\xFA\xE8\x00\x00\x00\x00\xBA\x00\x00\x00\x00\x48\x8B\xC8", "xxxx?xxxx?xxxxxxxxxxxxxxxxxxx????x????xxx"); 249 | if (!addr) { 250 | MessageBox(0, L"Failed to find GetViewPoint", L"Failure", 0); 251 | return FALSE; 252 | } 253 | 254 | MH_CreateHook(addr, GetViewPointHook, (PVOID*)&GetViewPoint); 255 | MH_EnableHook(addr); 256 | 257 | 258 | return TRUE; 259 | } 260 | } -------------------------------------------------------------------------------- /l0st.dev FN.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 | {432CD352-DFE6-4AC6-B858-3F74D5CB161F} 24 | Win32Proj 25 | example 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | false 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | true 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | $(VC_IncludePath);$(WindowsSDK_IncludePath);C:\Users\Ticx\source\repos\l0st.dev FN\l0st.dev FN\imgui;C:\Users\Ticx\source\repos\l0st.dev FN\l0st.dev FN\minhook 85 | $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\Ticx\source\repos\l0st.dev FN\l0st.dev FN\minhook 86 | fn 87 | ..\x64\Release 88 | 89 | 90 | false 91 | .\imgui;.\minhook;$(VC_IncludePath);$(WindowsSDK_IncludePath); 92 | .\minhook;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 93 | Fortnite 94 | 95 | 96 | 97 | Use 98 | Level3 99 | true 100 | WIN32;_DEBUG;EXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 101 | true 102 | pch.h 103 | 104 | 105 | Windows 106 | true 107 | false 108 | 109 | 110 | 111 | 112 | Use 113 | Level3 114 | true 115 | _DEBUG;EXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 116 | true 117 | pch.h 118 | 119 | 120 | Windows 121 | true 122 | false 123 | 124 | 125 | 126 | 127 | Use 128 | Level3 129 | true 130 | true 131 | true 132 | WIN32;NDEBUG;EXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 133 | true 134 | pch.h 135 | 136 | 137 | Windows 138 | true 139 | true 140 | true 141 | false 142 | 143 | 144 | 145 | 146 | NotUsing 147 | Level3 148 | true 149 | true 150 | true 151 | NDEBUG;EXAMPLE_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 152 | true 153 | 154 | 155 | MultiThreaded 156 | Default 157 | 158 | 159 | Windows 160 | true 161 | true 162 | true 163 | false 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | Document 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /Util.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | namespace Util { 4 | GObjects* objects = nullptr; 5 | FString(*GetObjectNameInternal)(PVOID) = nullptr; 6 | VOID(*FreeInternal)(PVOID) = nullptr; 7 | BOOL(*LineOfSightToInternal)(PVOID PlayerController, PVOID Actor, FVector* ViewPoint) = nullptr; 8 | VOID(*CalculateProjectionMatrixGivenView)(FMinimalViewInfo* viewInfo, BYTE aspectRatioAxisConstraint, PBYTE viewport, FSceneViewProjectionData* inOutProjectionData) = nullptr; 9 | 10 | struct { 11 | FMinimalViewInfo Info; 12 | float ProjectionMatrix[4][4]; 13 | } view = { 0 }; 14 | 15 | VOID CreateConsole() { 16 | AllocConsole(); 17 | static_cast(freopen("CONIN$", "r", stdin)); 18 | static_cast(freopen("CONOUT$", "w", stdout)); 19 | static_cast(freopen("CONOUT$", "w", stderr)); 20 | } 21 | 22 | BOOLEAN MaskCompare(PVOID buffer, LPCSTR pattern, LPCSTR mask) { 23 | for (auto b = reinterpret_cast(buffer); *mask; ++pattern, ++mask, ++b) { 24 | if (*mask == 'x' && *reinterpret_cast(pattern) != *b) { 25 | return FALSE; 26 | } 27 | } 28 | 29 | return TRUE; 30 | } 31 | 32 | PBYTE FindPattern(PVOID base, DWORD size, LPCSTR pattern, LPCSTR mask) { 33 | size -= static_cast(strlen(mask)); 34 | 35 | for (auto i = 0UL; i < size; ++i) { 36 | auto addr = reinterpret_cast(base) + i; 37 | if (MaskCompare(addr, pattern, mask)) { 38 | return addr; 39 | } 40 | } 41 | 42 | return NULL; 43 | } 44 | 45 | PBYTE FindPattern(LPCSTR pattern, LPCSTR mask) { 46 | MODULEINFO info = { 0 }; 47 | GetModuleInformation(GetCurrentProcess(), GetModuleHandle(0), &info, sizeof(info)); 48 | 49 | return FindPattern(info.lpBaseOfDll, info.SizeOfImage, pattern, mask); 50 | } 51 | 52 | VOID Free(PVOID buffer) { 53 | FreeInternal(buffer); 54 | } 55 | 56 | std::wstring GetObjectFirstName(UObject* object) { 57 | auto internalName = GetObjectNameInternal(object); 58 | if (!internalName.c_str()) { 59 | return L""; 60 | } 61 | 62 | std::wstring name(internalName.c_str()); 63 | Free(internalName.c_str()); 64 | 65 | return name; 66 | } 67 | 68 | std::wstring GetObjectName(UObject* object) { 69 | std::wstring name(L""); 70 | for (auto i = 0; object; object = object->Outer, ++i) { 71 | auto internalName = GetObjectNameInternal(object); 72 | if (!internalName.c_str()) { 73 | break; 74 | } 75 | 76 | name = internalName.c_str() + std::wstring(i > 0 ? L"." : L"") + name; 77 | Free(internalName.c_str()); 78 | } 79 | 80 | return name; 81 | } 82 | 83 | BOOLEAN GetOffsets(std::vector& offsets) { 84 | auto current = 0ULL; 85 | auto size = offsets.size(); 86 | 87 | for (auto array : objects->ObjectArray->Objects) { 88 | auto fuObject = array; 89 | for (auto i = 0; i < 0x10000 && fuObject->Object; ++i, ++fuObject) { 90 | auto object = fuObject->Object; 91 | if (object->ObjectFlags != 0x41) { 92 | continue; 93 | } 94 | 95 | auto name = GetObjectName(object); 96 | for (auto& o : offsets) { 97 | if (!o.Offset && name == o.Name) { 98 | o.Offset = *reinterpret_cast(reinterpret_cast(object) + 0x44); 99 | 100 | if (++current == size) { 101 | return TRUE; 102 | } 103 | 104 | break; 105 | } 106 | } 107 | } 108 | } 109 | 110 | for (auto& o : offsets) { 111 | if (!o.Offset) { 112 | WCHAR buffer[0xFF] = { 0 }; 113 | wsprintf(buffer, L"Offset %ws not found", o.Name); 114 | MessageBox(0, buffer, L"Failure", 0); 115 | } 116 | } 117 | 118 | return FALSE; 119 | } 120 | 121 | PVOID FindObject(LPCWSTR name) { 122 | for (auto array : objects->ObjectArray->Objects) { 123 | auto fuObject = array; 124 | for (auto i = 0; i < 0x10000 && fuObject->Object; ++i, ++fuObject) { 125 | auto object = fuObject->Object; 126 | if (object->ObjectFlags != 0x41) { 127 | continue; 128 | } 129 | 130 | if (GetObjectName(object) == name) { 131 | return object; 132 | } 133 | } 134 | } 135 | 136 | return 0; 137 | } 138 | 139 | VOID ToMatrixWithScale(float* in, float out[4][4]) 140 | { 141 | auto* rotation = &in[0]; 142 | auto* translation = &in[4]; 143 | auto* scale = &in[8]; 144 | 145 | out[3][0] = translation[0]; 146 | out[3][1] = translation[1]; 147 | out[3][2] = translation[2]; 148 | 149 | auto x2 = rotation[0] + rotation[0]; 150 | auto y2 = rotation[1] + rotation[1]; 151 | auto z2 = rotation[2] + rotation[2]; 152 | 153 | auto xx2 = rotation[0] * x2; 154 | auto yy2 = rotation[1] * y2; 155 | auto zz2 = rotation[2] * z2; 156 | out[0][0] = (1.0f - (yy2 + zz2)) * scale[0]; 157 | out[1][1] = (1.0f - (xx2 + zz2)) * scale[1]; 158 | out[2][2] = (1.0f - (xx2 + yy2)) * scale[2]; 159 | 160 | auto yz2 = rotation[1] * z2; 161 | auto wx2 = rotation[3] * x2; 162 | out[2][1] = (yz2 - wx2) * scale[2]; 163 | out[1][2] = (yz2 + wx2) * scale[1]; 164 | 165 | auto xy2 = rotation[0] * y2; 166 | auto wz2 = rotation[3] * z2; 167 | out[1][0] = (xy2 - wz2) * scale[1]; 168 | out[0][1] = (xy2 + wz2) * scale[0]; 169 | 170 | auto xz2 = rotation[0] * z2; 171 | auto wy2 = rotation[3] * y2; 172 | out[2][0] = (xz2 + wy2) * scale[2]; 173 | out[0][2] = (xz2 - wy2) * scale[0]; 174 | 175 | out[0][3] = 0.0f; 176 | out[1][3] = 0.0f; 177 | out[2][3] = 0.0f; 178 | out[3][3] = 1.0f; 179 | } 180 | 181 | VOID MultiplyMatrices(float a[4][4], float b[4][4], float out[4][4]) { 182 | for (auto r = 0; r < 4; ++r) { 183 | for (auto c = 0; c < 4; ++c) { 184 | auto sum = 0.0f; 185 | 186 | for (auto i = 0; i < 4; ++i) { 187 | sum += a[r][i] * b[i][c]; 188 | } 189 | 190 | out[r][c] = sum; 191 | } 192 | } 193 | } 194 | 195 | VOID GetBoneLocation(float compMatrix[4][4], PVOID bones, DWORD index, float out[3]) { 196 | float boneMatrix[4][4]; 197 | ToMatrixWithScale((float*)((PBYTE)bones + (index * 0x30)), boneMatrix); 198 | 199 | float result[4][4]; 200 | MultiplyMatrices(boneMatrix, compMatrix, result); 201 | 202 | out[0] = result[3][0]; 203 | out[1] = result[3][1]; 204 | out[2] = result[3][2]; 205 | } 206 | 207 | VOID GetViewProjectionMatrix(FSceneViewProjectionData* projectionData, float out[4][4]) { 208 | auto loc = &projectionData->ViewOrigin; 209 | 210 | float translation[4][4] = { 211 | { 1.0f, 0.0f, 0.0f, 0.0f, }, 212 | { 0.0f, 1.0f, 0.0f, 0.0f, }, 213 | { 0.0f, 0.0f, 1.0f, 0.0f, }, 214 | { -loc->X, -loc->Y, -loc->Z, 0.0f, }, 215 | }; 216 | 217 | float temp[4][4]; 218 | MultiplyMatrices(translation, projectionData->ViewRotationMatrix.M, temp); 219 | MultiplyMatrices(temp, projectionData->ProjectionMatrix.M, out); 220 | } 221 | 222 | BOOLEAN ProjectWorldToScreen(float viewProjection[4][4], float width, float height, float inOutPosition[3]) { 223 | float res[4] = { 224 | viewProjection[0][0] * inOutPosition[0] + viewProjection[1][0] * inOutPosition[1] + viewProjection[2][0] * inOutPosition[2] + viewProjection[3][0], 225 | viewProjection[0][1] * inOutPosition[0] + viewProjection[1][1] * inOutPosition[1] + viewProjection[2][1] * inOutPosition[2] + viewProjection[3][1], 226 | viewProjection[0][2] * inOutPosition[0] + viewProjection[1][2] * inOutPosition[1] + viewProjection[2][2] * inOutPosition[2] + viewProjection[3][2], 227 | viewProjection[0][3] * inOutPosition[0] + viewProjection[1][3] * inOutPosition[1] + viewProjection[2][3] * inOutPosition[2] + viewProjection[3][3], 228 | }; 229 | 230 | auto r = res[3]; 231 | if (r > 0) { 232 | auto rhw = 1.0f / r; 233 | 234 | inOutPosition[0] = (((res[0] * rhw) / 2.0f) + 0.5f) * width; 235 | inOutPosition[1] = (0.5f - ((res[1] * rhw) / 2.0f)) * height; 236 | inOutPosition[2] = r; 237 | 238 | return TRUE; 239 | } 240 | 241 | return FALSE; 242 | } 243 | 244 | VOID CalculateProjectionMatrixGivenViewHook(FMinimalViewInfo* viewInfo, BYTE aspectRatioAxisConstraint, PBYTE viewport, FSceneViewProjectionData* inOutProjectionData) { 245 | CalculateProjectionMatrixGivenView(viewInfo, aspectRatioAxisConstraint, viewport, inOutProjectionData); 246 | 247 | view.Info = *viewInfo; 248 | GetViewProjectionMatrix(inOutProjectionData, view.ProjectionMatrix); 249 | } 250 | 251 | BOOLEAN WorldToScreen(float width, float height, float inOutPosition[3]) { 252 | return ProjectWorldToScreen(view.ProjectionMatrix, width, height, inOutPosition); 253 | } 254 | 255 | BOOLEAN LineOfSightTo(PVOID PlayerController, PVOID Actor, FVector* ViewPoint) { 256 | return SpoofCall(LineOfSightToInternal, PlayerController, Actor, ViewPoint); 257 | } 258 | 259 | FMinimalViewInfo& GetViewInfo() { 260 | return view.Info; 261 | } 262 | 263 | FVector* GetPawnRootLocation(PVOID pawn) { 264 | auto root = ReadPointer(pawn, Offsets::Engine::Actor::RootComponent); 265 | if (!root) { 266 | return nullptr; 267 | } 268 | 269 | return reinterpret_cast(reinterpret_cast(root) + Offsets::Engine::SceneComponent::RelativeLocation); 270 | } 271 | 272 | float Normalize(float angle) { 273 | float a = (float)fmod(fmod(angle, 360.0) + 360.0, 360.0); 274 | if (a > 180.0f) { 275 | a -= 360.0f; 276 | } 277 | return a; 278 | } 279 | 280 | VOID CalcAngle(float* src, float* dst, float* angles) { 281 | float rel[3] = { 282 | dst[0] - src[0], 283 | dst[1] - src[1], 284 | dst[2] - src[2], 285 | }; 286 | 287 | auto dist = sqrtf(rel[0] * rel[0] + rel[1] * rel[1] + rel[2] * rel[2]); 288 | auto yaw = atan2f(rel[1], rel[0]) * (180.0f / PI); 289 | auto pitch = (-((acosf((rel[2] / dist)) * 180.0f / PI) - 90.0f)); 290 | 291 | angles[0] = Normalize(pitch); 292 | angles[1] = Normalize(yaw); 293 | } 294 | 295 | BOOLEAN Initialize() { 296 | // GObjects 297 | auto addr = FindPattern("\x48\x8B\x05\x7E\x38\x79\x05\x4C\x8D\x34\xCD", "xxx????xxxx"); 298 | if (!addr) { 299 | MessageBox(0, L"Failed to find GObjects", L"Failure", 0); 300 | return FALSE; 301 | } 302 | 303 | objects = reinterpret_cast(RELATIVE_ADDR(addr, 7)); 304 | 305 | // GetObjectName 306 | addr = FindPattern("\x40\x53\x48\x83\xEC\x20\x48\x8B\xD9\x48\x85\xD2\x75\x45\x33\xC0\x48\x89\x01\x48\x89\x41\x08\x8D\x50\x05\xE8\x00\x00\x00\x00\x8B\x53\x08\x8D\x42\x05\x89\x43\x08\x3B\x43\x0C\x7E\x08\x48\x8B\xCB\xE8\x00\x00\x00\x00\x48\x8B\x0B\x48\x8D\x15\x00\x00\x00\x00\x41\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x8B\xC3\x48\x83\xC4\x20\x5B\xC3\x48\x8B\x42\x18", "xxxxxxxxxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxxxx????xxxxxx????xx????x????xxxxxxxxxxxxx"); 307 | if (!addr) { 308 | MessageBox(0, L"Failed to find GetObjectNameInternal", L"Failure", 0); 309 | return FALSE; 310 | } 311 | 312 | GetObjectNameInternal = reinterpret_cast(addr); 313 | 314 | // Free 315 | addr = FindPattern("\x48\x85\xC9\x74\x2E\x53\x48\x83\xEC\x20\x48\x8B\xD9\x48\x8B\x0D\x00\x00\x00\x00\x48\x85\xC9\x75\x0C", "xxxxxxxxxxxxxxxx????xxxxx"); 316 | if (!addr) { 317 | MessageBox(0, L"Failed to find FreeInternal", L"Failure", 0); 318 | return FALSE; 319 | } 320 | 321 | FreeInternal = reinterpret_cast(addr); 322 | 323 | // CalculateProjectionMatrixGivenView 324 | addr = FindPattern("\x45\x0F\x57\xC0\x45\x8B\x81\x00\x00\x00\x00", "xxxxxxx????"); 325 | if (!addr) { 326 | MessageBox(0, L"Failed to find CalculateProjectionMatrixGivenView", L"Failure", 0); 327 | return FALSE; 328 | } 329 | 330 | addr -= 0x280; 331 | MH_CreateHook(addr, CalculateProjectionMatrixGivenViewHook, (PVOID*)&CalculateProjectionMatrixGivenView); 332 | MH_EnableHook(addr); 333 | 334 | // LineOfSightTo 335 | addr = FindPattern("\x40\x55\x53\x56\x57\x48\x8D\x6C\x24\x00\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\x48\x33\xC4\x48\x89\x45\xE0\x49", "xxxxxxxxx?xxx????xxx????xxxxxxxx"); 336 | if (!addr) { 337 | MessageBox(0, L"Failed to find LineOfSightTo", L"Failure", 0); 338 | return FALSE; 339 | } 340 | 341 | LineOfSightToInternal = reinterpret_cast(addr); 342 | 343 | return TRUE; 344 | } 345 | } -------------------------------------------------------------------------------- /imgui/stb_rect_pack.h: -------------------------------------------------------------------------------- 1 | // stb_rect_pack.h - v0.10 - public domain - rectangle packing 2 | // Sean Barrett 2014 3 | // 4 | // Useful for e.g. packing rectangular textures into an atlas. 5 | // Does not do rotation. 6 | // 7 | // Not necessarily the awesomest packing method, but better than 8 | // the totally naive one in stb_truetype (which is primarily what 9 | // this is meant to replace). 10 | // 11 | // Has only had a few tests run, may have issues. 12 | // 13 | // More docs to come. 14 | // 15 | // No memory allocations; uses qsort() and assert() from stdlib. 16 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 17 | // 18 | // This library currently uses the Skyline Bottom-Left algorithm. 19 | // 20 | // Please note: better rectangle packers are welcome! Please 21 | // implement them to the same API, but with a different init 22 | // function. 23 | // 24 | // Credits 25 | // 26 | // Library 27 | // Sean Barrett 28 | // Minor features 29 | // Martins Mozeiko 30 | // Bugfixes / warning fixes 31 | // Jeremy Jaussaud 32 | // 33 | // Version history: 34 | // 35 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 36 | // 0.09 (2016-08-27) fix compiler warnings 37 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 38 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 39 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 40 | // 0.05: added STBRP_ASSERT to allow replacing assert 41 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 42 | // 0.01: initial release 43 | // 44 | // LICENSE 45 | // 46 | // This software is dual-licensed to the public domain and under the following 47 | // license: you are granted a perpetual, irrevocable license to copy, modify, 48 | // publish, and distribute this file as you see fit. 49 | 50 | ////////////////////////////////////////////////////////////////////////////// 51 | // 52 | // INCLUDE SECTION 53 | // 54 | 55 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 56 | #define STB_INCLUDE_STB_RECT_PACK_H 57 | 58 | #define STB_RECT_PACK_VERSION 1 59 | 60 | #ifdef STBRP_STATIC 61 | #define STBRP_DEF static 62 | #else 63 | #define STBRP_DEF extern 64 | #endif 65 | 66 | #ifdef __cplusplus 67 | extern "C" { 68 | #endif 69 | 70 | typedef struct stbrp_context stbrp_context; 71 | typedef struct stbrp_node stbrp_node; 72 | typedef struct stbrp_rect stbrp_rect; 73 | 74 | #ifdef STBRP_LARGE_RECTS 75 | typedef int stbrp_coord; 76 | #else 77 | typedef unsigned short stbrp_coord; 78 | #endif 79 | 80 | STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects); 81 | // Assign packed locations to rectangles. The rectangles are of type 82 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 83 | // are 'num_rects' many of them. 84 | // 85 | // Rectangles which are successfully packed have the 'was_packed' flag 86 | // set to a non-zero value and 'x' and 'y' store the minimum location 87 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 88 | // if you imagine y increasing downwards). Rectangles which do not fit 89 | // have the 'was_packed' flag set to 0. 90 | // 91 | // You should not try to access the 'rects' array from another thread 92 | // while this function is running, as the function temporarily reorders 93 | // the array while it executes. 94 | // 95 | // To pack into another rectangle, you need to call stbrp_init_target 96 | // again. To continue packing into the same rectangle, you can call 97 | // this function again. Calling this multiple times with multiple rect 98 | // arrays will probably produce worse packing results than calling it 99 | // a single time with the full rectangle array, but the option is 100 | // available. 101 | 102 | struct stbrp_rect 103 | { 104 | // reserved for your use: 105 | int id; 106 | 107 | // input: 108 | stbrp_coord w, h; 109 | 110 | // output: 111 | stbrp_coord x, y; 112 | int was_packed; // non-zero if valid packing 113 | 114 | }; // 16 bytes, nominally 115 | 116 | 117 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 118 | // Initialize a rectangle packer to: 119 | // pack a rectangle that is 'width' by 'height' in dimensions 120 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 121 | // 122 | // You must call this function every time you start packing into a new target. 123 | // 124 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 125 | // the following stbrp_pack_rects() call (or calls), but can be freed after 126 | // the call (or calls) finish. 127 | // 128 | // Note: to guarantee best results, either: 129 | // 1. make sure 'num_nodes' >= 'width' 130 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 131 | // 132 | // If you don't do either of the above things, widths will be quantized to multiples 133 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 134 | // 135 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 136 | // may run out of temporary storage and be unable to pack some rectangles. 137 | 138 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem); 139 | // Optionally call this function after init but before doing any packing to 140 | // change the handling of the out-of-temp-memory scenario, described above. 141 | // If you call init again, this will be reset to the default (false). 142 | 143 | 144 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic); 145 | // Optionally select which packing heuristic the library should use. Different 146 | // heuristics will produce better/worse results for different data sets. 147 | // If you call init again, this will be reset to the default. 148 | 149 | enum 150 | { 151 | STBRP_HEURISTIC_Skyline_default = 0, 152 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 153 | STBRP_HEURISTIC_Skyline_BF_sortHeight 154 | }; 155 | 156 | 157 | ////////////////////////////////////////////////////////////////////////////// 158 | // 159 | // the details of the following structures don't matter to you, but they must 160 | // be visible so you can handle the memory allocations for them 161 | 162 | struct stbrp_node 163 | { 164 | stbrp_coord x, y; 165 | stbrp_node *next; 166 | }; 167 | 168 | struct stbrp_context 169 | { 170 | int width; 171 | int height; 172 | int align; 173 | int init_mode; 174 | int heuristic; 175 | int num_nodes; 176 | stbrp_node *active_head; 177 | stbrp_node *free_head; 178 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 179 | }; 180 | 181 | #ifdef __cplusplus 182 | } 183 | #endif 184 | 185 | #endif 186 | 187 | ////////////////////////////////////////////////////////////////////////////// 188 | // 189 | // IMPLEMENTATION SECTION 190 | // 191 | 192 | #ifdef STB_RECT_PACK_IMPLEMENTATION 193 | #ifndef STBRP_SORT 194 | #include 195 | #define STBRP_SORT qsort 196 | #endif 197 | 198 | #ifndef STBRP_ASSERT 199 | #include 200 | #define STBRP_ASSERT assert 201 | #endif 202 | 203 | #ifdef _MSC_VER 204 | #define STBRP__NOTUSED(v) (void)(v) 205 | #else 206 | #define STBRP__NOTUSED(v) (void)sizeof(v) 207 | #endif 208 | 209 | enum 210 | { 211 | STBRP__INIT_skyline = 1 212 | }; 213 | 214 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 215 | { 216 | switch (context->init_mode) { 217 | case STBRP__INIT_skyline: 218 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 219 | context->heuristic = heuristic; 220 | break; 221 | default: 222 | STBRP_ASSERT(0); 223 | } 224 | } 225 | 226 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 227 | { 228 | if (allow_out_of_mem) 229 | // if it's ok to run out of memory, then don't bother aligning them; 230 | // this gives better packing, but may fail due to OOM (even though 231 | // the rectangles easily fit). @TODO a smarter approach would be to only 232 | // quantize once we've hit OOM, then we could get rid of this parameter. 233 | context->align = 1; 234 | else { 235 | // if it's not ok to run out of memory, then quantize the widths 236 | // so that num_nodes is always enough nodes. 237 | // 238 | // I.e. num_nodes * align >= width 239 | // align >= width / num_nodes 240 | // align = ceil(width/num_nodes) 241 | 242 | context->align = (context->width + context->num_nodes - 1) / context->num_nodes; 243 | } 244 | } 245 | 246 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 247 | { 248 | int i; 249 | #ifndef STBRP_LARGE_RECTS 250 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff); 251 | #endif 252 | 253 | for (i = 0; i < num_nodes - 1; ++i) 254 | nodes[i].next = &nodes[i + 1]; 255 | nodes[i].next = NULL; 256 | context->init_mode = STBRP__INIT_skyline; 257 | context->heuristic = STBRP_HEURISTIC_Skyline_default; 258 | context->free_head = &nodes[0]; 259 | context->active_head = &context->extra[0]; 260 | context->width = width; 261 | context->height = height; 262 | context->num_nodes = num_nodes; 263 | stbrp_setup_allow_out_of_mem(context, 0); 264 | 265 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) 266 | context->extra[0].x = 0; 267 | context->extra[0].y = 0; 268 | context->extra[0].next = &context->extra[1]; 269 | context->extra[1].x = (stbrp_coord)width; 270 | #ifdef STBRP_LARGE_RECTS 271 | context->extra[1].y = (1 << 30); 272 | #else 273 | context->extra[1].y = 65535; 274 | #endif 275 | context->extra[1].next = NULL; 276 | } 277 | 278 | // find minimum y position if it starts at x1 279 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 280 | { 281 | stbrp_node *node = first; 282 | int x1 = x0 + width; 283 | int min_y, visited_width, waste_area; 284 | 285 | STBRP__NOTUSED(c); 286 | 287 | STBRP_ASSERT(first->x <= x0); 288 | 289 | #if 0 290 | // skip in case we're past the node 291 | while (node->next->x <= x0) 292 | ++node; 293 | #else 294 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 295 | #endif 296 | 297 | STBRP_ASSERT(node->x <= x0); 298 | 299 | min_y = 0; 300 | waste_area = 0; 301 | visited_width = 0; 302 | while (node->x < x1) { 303 | if (node->y > min_y) { 304 | // raise min_y higher. 305 | // we've accounted for all waste up to min_y, 306 | // but we'll now add more waste for everything we've visted 307 | waste_area += visited_width * (node->y - min_y); 308 | min_y = node->y; 309 | // the first time through, visited_width might be reduced 310 | if (node->x < x0) 311 | visited_width += node->next->x - x0; 312 | else 313 | visited_width += node->next->x - node->x; 314 | } 315 | else { 316 | // add waste area 317 | int under_width = node->next->x - node->x; 318 | if (under_width + visited_width > width) 319 | under_width = width - visited_width; 320 | waste_area += under_width * (min_y - node->y); 321 | visited_width += under_width; 322 | } 323 | node = node->next; 324 | } 325 | 326 | *pwaste = waste_area; 327 | return min_y; 328 | } 329 | 330 | typedef struct 331 | { 332 | int x, y; 333 | stbrp_node **prev_link; 334 | } stbrp__findresult; 335 | 336 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 337 | { 338 | int best_waste = (1 << 30), best_x, best_y = (1 << 30); 339 | stbrp__findresult fr; 340 | stbrp_node **prev, *node, *tail, **best = NULL; 341 | 342 | // align to multiple of c->align 343 | width = (width + c->align - 1); 344 | width -= width % c->align; 345 | STBRP_ASSERT(width % c->align == 0); 346 | 347 | node = c->active_head; 348 | prev = &c->active_head; 349 | while (node->x + width <= c->width) { 350 | int y, waste; 351 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 352 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 353 | // bottom left 354 | if (y < best_y) { 355 | best_y = y; 356 | best = prev; 357 | } 358 | } 359 | else { 360 | // best-fit 361 | if (y + height <= c->height) { 362 | // can only use it if it first vertically 363 | if (y < best_y || (y == best_y && waste < best_waste)) { 364 | best_y = y; 365 | best_waste = waste; 366 | best = prev; 367 | } 368 | } 369 | } 370 | prev = &node->next; 371 | node = node->next; 372 | } 373 | 374 | best_x = (best == NULL) ? 0 : (*best)->x; 375 | 376 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 377 | // 378 | // e.g, if fitting 379 | // 380 | // ____________________ 381 | // |____________________| 382 | // 383 | // into 384 | // 385 | // | | 386 | // | ____________| 387 | // |____________| 388 | // 389 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 390 | // 391 | // This makes BF take about 2x the time 392 | 393 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 394 | tail = c->active_head; 395 | node = c->active_head; 396 | prev = &c->active_head; 397 | // find first node that's admissible 398 | while (tail->x < width) 399 | tail = tail->next; 400 | while (tail) { 401 | int xpos = tail->x - width; 402 | int y, waste; 403 | STBRP_ASSERT(xpos >= 0); 404 | // find the left position that matches this 405 | while (node->next->x <= xpos) { 406 | prev = &node->next; 407 | node = node->next; 408 | } 409 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 410 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 411 | if (y + height < c->height) { 412 | if (y <= best_y) { 413 | if (y < best_y || waste < best_waste || (waste == best_waste && xpos < best_x)) { 414 | best_x = xpos; 415 | STBRP_ASSERT(y <= best_y); 416 | best_y = y; 417 | best_waste = waste; 418 | best = prev; 419 | } 420 | } 421 | } 422 | tail = tail->next; 423 | } 424 | } 425 | 426 | fr.prev_link = best; 427 | fr.x = best_x; 428 | fr.y = best_y; 429 | return fr; 430 | } 431 | 432 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 433 | { 434 | // find best position according to heuristic 435 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 436 | stbrp_node *node, *cur; 437 | 438 | // bail if: 439 | // 1. it failed 440 | // 2. the best node doesn't fit (we don't always check this) 441 | // 3. we're out of memory 442 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 443 | res.prev_link = NULL; 444 | return res; 445 | } 446 | 447 | // on success, create new node 448 | node = context->free_head; 449 | node->x = (stbrp_coord)res.x; 450 | node->y = (stbrp_coord)(res.y + height); 451 | 452 | context->free_head = node->next; 453 | 454 | // insert the new node into the right starting point, and 455 | // let 'cur' point to the remaining nodes needing to be 456 | // stiched back in 457 | 458 | cur = *res.prev_link; 459 | if (cur->x < res.x) { 460 | // preserve the existing one, so start testing with the next one 461 | stbrp_node *next = cur->next; 462 | cur->next = node; 463 | cur = next; 464 | } 465 | else { 466 | *res.prev_link = node; 467 | } 468 | 469 | // from here, traverse cur and free the nodes, until we get to one 470 | // that shouldn't be freed 471 | while (cur->next && cur->next->x <= res.x + width) { 472 | stbrp_node *next = cur->next; 473 | // move the current node to the free list 474 | cur->next = context->free_head; 475 | context->free_head = cur; 476 | cur = next; 477 | } 478 | 479 | // stitch the list back in 480 | node->next = cur; 481 | 482 | if (cur->x < res.x + width) 483 | cur->x = (stbrp_coord)(res.x + width); 484 | 485 | #ifdef _DEBUG 486 | cur = context->active_head; 487 | while (cur->x < context->width) { 488 | STBRP_ASSERT(cur->x < cur->next->x); 489 | cur = cur->next; 490 | } 491 | STBRP_ASSERT(cur->next == NULL); 492 | 493 | { 494 | stbrp_node *L1 = NULL, *L2 = NULL; 495 | int count = 0; 496 | cur = context->active_head; 497 | while (cur) { 498 | L1 = cur; 499 | cur = cur->next; 500 | ++count; 501 | } 502 | cur = context->free_head; 503 | while (cur) { 504 | L2 = cur; 505 | cur = cur->next; 506 | ++count; 507 | } 508 | STBRP_ASSERT(count == context->num_nodes + 2); 509 | } 510 | #endif 511 | 512 | return res; 513 | } 514 | 515 | static int rect_height_compare(const void *a, const void *b) 516 | { 517 | const stbrp_rect *p = (const stbrp_rect *)a; 518 | const stbrp_rect *q = (const stbrp_rect *)b; 519 | if (p->h > q->h) 520 | return -1; 521 | if (p->h < q->h) 522 | return 1; 523 | return (p->w > q->w) ? -1 : (p->w < q->w); 524 | } 525 | 526 | static int rect_width_compare(const void *a, const void *b) 527 | { 528 | const stbrp_rect *p = (const stbrp_rect *)a; 529 | const stbrp_rect *q = (const stbrp_rect *)b; 530 | if (p->w > q->w) 531 | return -1; 532 | if (p->w < q->w) 533 | return 1; 534 | return (p->h > q->h) ? -1 : (p->h < q->h); 535 | } 536 | 537 | static int rect_original_order(const void *a, const void *b) 538 | { 539 | const stbrp_rect *p = (const stbrp_rect *)a; 540 | const stbrp_rect *q = (const stbrp_rect *)b; 541 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 542 | } 543 | 544 | #ifdef STBRP_LARGE_RECTS 545 | #define STBRP__MAXVAL 0xffffffff 546 | #else 547 | #define STBRP__MAXVAL 0xffff 548 | #endif 549 | 550 | STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 551 | { 552 | int i; 553 | 554 | // we use the 'was_packed' field internally to allow sorting/unsorting 555 | for (i = 0; i < num_rects; ++i) { 556 | rects[i].was_packed = i; 557 | #ifndef STBRP_LARGE_RECTS 558 | STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff); 559 | #endif 560 | } 561 | 562 | // sort according to heuristic 563 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 564 | 565 | for (i = 0; i < num_rects; ++i) { 566 | if (rects[i].w == 0 || rects[i].h == 0) { 567 | rects[i].x = rects[i].y = 0; // empty rect needs no space 568 | } 569 | else { 570 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 571 | if (fr.prev_link) { 572 | rects[i].x = (stbrp_coord)fr.x; 573 | rects[i].y = (stbrp_coord)fr.y; 574 | } 575 | else { 576 | rects[i].x = rects[i].y = STBRP__MAXVAL; 577 | } 578 | } 579 | } 580 | 581 | // unsort 582 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 583 | 584 | // set was_packed flags 585 | for (i = 0; i < num_rects; ++i) 586 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 587 | } 588 | #endif 589 | -------------------------------------------------------------------------------- /menu.cpp: -------------------------------------------------------------------------------- 1 | #include "meni.h" 2 | #include "stdafx.h" 3 | 4 | ID3D11Device* device = nullptr; 5 | ID3D11DeviceContext* immediateContext = nullptr; 6 | ID3D11RenderTargetView* renderTargetView = nullptr; 7 | 8 | HRESULT(*PresentOriginal)(IDXGISwapChain* swapChain, UINT syncInterval, UINT flags) = nullptr; 9 | HRESULT(*ResizeOriginal)(IDXGISwapChain* swapChain, UINT bufferCount, UINT width, UINT height, DXGI_FORMAT newFormat, UINT swapChainFlags) = nullptr; 10 | WNDPROC oWndProc; 11 | 12 | extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 13 | 14 | static bool ShowMenu = true; 15 | 16 | VOID AddMarker(ImGuiWindow& window, float width, float height, float* start, PVOID pawn, LPCSTR text, ImU32 color) { 17 | float minX = FLT_MAX; 18 | float maxX = -FLT_MAX; 19 | float minY = FLT_MAX; 20 | float maxY = -FLT_MAX; 21 | if (minX < width && maxX > 0 && minY < height && maxY > 0) { 22 | auto topLeft = ImVec2(minX - 3.0f, minY - 3.0f); 23 | auto bottomRight = ImVec2(maxX + 3.0f, maxY + 3.0f); 24 | auto centerTop = ImVec2((topLeft.x + bottomRight.x) / 2.0f, topLeft.y); 25 | auto root = Util::GetPawnRootLocation(pawn); 26 | if (root) { 27 | auto pos = *root; 28 | float dx = start[0] - pos.X; 29 | float dy = start[1] - pos.Y; 30 | float dz = start[2] - pos.Z; 31 | 32 | if (Util::WorldToScreen(width, height, &pos.X)) { 33 | float dist = Util::SpoofCall(sqrtf, dx * dx + dy * dy + dz * dz) / 1000.0f; 34 | 35 | CHAR modified[0xFF] = { 0 }; 36 | snprintf(modified, sizeof(modified), ("%s\n %dm"), text, static_cast(dist)); 37 | 38 | auto size = ImGui::GetFont()->CalcTextSizeA(window.DrawList->_Data->FontSize, FLT_MAX, 0, modified); 39 | window.DrawList->AddRectFilled(ImVec2(centerTop.x - size.x / 2.0f, centerTop.y - size.y + 3.0f), ImVec2(centerTop.x + size.x / 2.0f, centerTop.y), ImGui::GetColorU32({ 0.0f, 0.0f, 0.0f, 0.4f })); 40 | window.DrawList->AddText(ImVec2(pos.X - size.x / 2.0f, pos.Y - size.y / 2.0f), color, modified); 41 | } 42 | } 43 | } 44 | } 45 | __declspec(dllexport) LRESULT CALLBACK WndProcHook(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { 46 | if (msg == WM_KEYUP && (wParam == VK_INSERT || (ShowMenu && wParam == VK_ESCAPE))) { 47 | ShowMenu = !ShowMenu; 48 | ImGui::GetIO().MouseDrawCursor = ShowMenu; 49 | 50 | } 51 | else if (msg == WM_QUIT && ShowMenu) { 52 | ExitProcess(0); 53 | } 54 | 55 | if (ShowMenu) { 56 | ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam); 57 | return TRUE; 58 | } 59 | 60 | return CallWindowProc(oWndProc, hWnd, msg, wParam, lParam); 61 | } 62 | 63 | extern uint64_t base_address = 0; 64 | DWORD processID; 65 | const ImVec4 color = { 255.0,255.0,255.0,1 }; 66 | const ImVec4 red = { 0.65,0,0,1 }; 67 | const ImVec4 white = { 255.0,255.0,255.0,1 }; 68 | const ImVec4 green = { 0.03,0.81,0.14,1 }; 69 | const ImVec4 blue = { 0.21960784313,0.56470588235,0.90980392156,1.0 }; 70 | 71 | ImGuiWindow& BeginScene() { 72 | ImGui_ImplDX11_NewFrame(); 73 | ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0); 74 | ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); 75 | ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); 76 | ImGui::Begin(("##scene"), nullptr, ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar); 77 | 78 | auto& io = ImGui::GetIO(); 79 | ImGui::SetWindowPos(ImVec2(0, 0), ImGuiCond_Always); 80 | ImGui::SetWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y), ImGuiCond_Always); 81 | 82 | return *ImGui::GetCurrentWindow(); 83 | } 84 | 85 | VOID EndScene(ImGuiWindow& window) { 86 | window.DrawList->PushClipRectFullScreen(); 87 | //ImGui::End(); 88 | ImGui::PopStyleColor(); 89 | ImGui::PopStyleVar(2); 90 | ImGui::Render(); 91 | } 92 | VOID AddLine(ImGuiWindow& window, float width, float height, float a[3], float b[3], ImU32 color, float& minX, float& maxX, float& minY, float& maxY) { 93 | float ac[3] = { a[0], a[1], a[2] }; 94 | float bc[3] = { b[0], b[1], b[2] }; 95 | if (Util::WorldToScreen(width, height, ac) && Util::WorldToScreen(width, height, bc)) { 96 | window.DrawList->AddLine(ImVec2(ac[0], ac[1]), ImVec2(bc[0], bc[1]), color, 2.0f); 97 | 98 | minX = min(ac[0], minX); 99 | minX = min(bc[0], minX); 100 | 101 | maxX = max(ac[0], maxX); 102 | maxX = max(bc[0], maxX); 103 | 104 | minY = min(ac[1], minY); 105 | minY = min(bc[1], minY); 106 | 107 | maxY = max(ac[1], maxY); 108 | maxY = max(bc[1], maxY); 109 | } 110 | } 111 | __declspec(dllexport) HRESULT PresentHook(IDXGISwapChain* swapChain, UINT syncInterval, UINT flags) { 112 | static float width = 0; 113 | static float height = 0; 114 | static HWND hWnd = 0; 115 | if (!device) { 116 | swapChain->GetDevice(__uuidof(device), reinterpret_cast(&device)); 117 | device->GetImmediateContext(&immediateContext); 118 | 119 | ID3D11Texture2D* renderTarget = nullptr; 120 | swapChain->GetBuffer(0, __uuidof(renderTarget), reinterpret_cast(&renderTarget)); 121 | device->CreateRenderTargetView(renderTarget, nullptr, &renderTargetView); 122 | renderTarget->Release(); 123 | 124 | ID3D11Texture2D* backBuffer = 0; 125 | swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (PVOID*)&backBuffer); 126 | D3D11_TEXTURE2D_DESC backBufferDesc = { 0 }; 127 | backBuffer->GetDesc(&backBufferDesc); 128 | 129 | hWnd = FindWindow((L"UnrealWindow"), (L"Fortnite ")); 130 | if (!width) { 131 | oWndProc = reinterpret_cast(SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(WndProcHook))); 132 | } 133 | 134 | width = (float)backBufferDesc.Width; 135 | height = (float)backBufferDesc.Height; 136 | backBuffer->Release(); 137 | 138 | ImGui::GetIO().Fonts->AddFontFromFileTTF(("C:\\Windows\\Fonts\\arialbd.ttf"), 12.0f); 139 | 140 | ImGui_ImplDX11_Init(hWnd, device, immediateContext); 141 | ImGui_ImplDX11_CreateDeviceObjects(); 142 | } 143 | immediateContext->OMSetRenderTargets(1, &renderTargetView, nullptr); 144 | ////// reading 145 | auto& window = BeginScene(); 146 | ////// reading 147 | if (ShowMenu) 148 | { 149 | ImGuiStyle& style = ImGui::GetStyle(); 150 | ImVec4* colors = style.Colors; 151 | 152 | /// 0 = FLAT APPEARENCE 153 | /// 1 = MORE "3D" LOOK 154 | int is3D = 0; 155 | 156 | colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); 157 | colors[ImGuiCol_TextDisabled] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); 158 | colors[ImGuiCol_ChildBg] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 159 | colors[ImGuiCol_WindowBg] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 160 | colors[ImGuiCol_PopupBg] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 161 | colors[ImGuiCol_Border] = ImVec4(0.12f, 0.12f, 0.12f, 0.71f); 162 | colors[ImGuiCol_BorderShadow] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); 163 | colors[ImGuiCol_FrameBg] = ImVec4(0.42f, 0.42f, 0.42f, 0.54f); 164 | colors[ImGuiCol_FrameBgHovered] = ImVec4(0.42f, 0.42f, 0.42f, 0.40f); 165 | colors[ImGuiCol_FrameBgActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.67f); 166 | colors[ImGuiCol_TitleBg] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f); 167 | colors[ImGuiCol_TitleBgActive] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f); 168 | colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.17f, 0.17f, 0.17f, 0.90f); 169 | colors[ImGuiCol_MenuBarBg] = ImVec4(0.335f, 0.335f, 0.335f, 1.000f); 170 | colors[ImGuiCol_ScrollbarBg] = ImVec4(0.24f, 0.24f, 0.24f, 0.53f); 171 | colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); 172 | colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f); 173 | colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f); 174 | colors[ImGuiCol_CheckMark] = ImVec4(0.65f, 0.65f, 0.65f, 1.00f); 175 | colors[ImGuiCol_SliderGrab] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f); 176 | colors[ImGuiCol_SliderGrabActive] = ImVec4(0.64f, 0.64f, 0.64f, 1.00f); 177 | colors[ImGuiCol_Button] = ImVec4(0.54f, 0.54f, 0.54f, 0.35f); 178 | colors[ImGuiCol_ButtonHovered] = ImVec4(0.52f, 0.52f, 0.52f, 0.59f); 179 | colors[ImGuiCol_ButtonActive] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f); 180 | colors[ImGuiCol_Header] = ImVec4(0.38f, 0.38f, 0.38f, 1.00f); 181 | colors[ImGuiCol_HeaderHovered] = ImVec4(0.47f, 0.47f, 0.47f, 1.00f); 182 | colors[ImGuiCol_HeaderActive] = ImVec4(0.76f, 0.76f, 0.76f, 0.77f); 183 | colors[ImGuiCol_Separator] = ImVec4(0.000f, 0.000f, 0.000f, 0.137f); 184 | colors[ImGuiCol_SeparatorHovered] = ImVec4(0.700f, 0.671f, 0.600f, 0.290f); 185 | colors[ImGuiCol_SeparatorActive] = ImVec4(0.702f, 0.671f, 0.600f, 0.674f); 186 | colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); 187 | colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); 188 | colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); 189 | colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); 190 | colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); 191 | colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); 192 | colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); 193 | colors[ImGuiCol_TextSelectedBg] = ImVec4(0.73f, 0.73f, 0.73f, 0.35f); 194 | colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); 195 | 196 | style.PopupRounding = 3; 197 | 198 | style.WindowPadding = ImVec2(4, 4); 199 | style.FramePadding = ImVec2(6, 4); 200 | style.ItemSpacing = ImVec2(6, 2); 201 | 202 | style.ScrollbarSize = 18; 203 | 204 | style.WindowBorderSize = 1; 205 | style.ChildBorderSize = 1; 206 | style.PopupBorderSize = 1; 207 | style.FrameBorderSize = is3D; 208 | 209 | style.WindowRounding = 3; 210 | style.ChildRounding = 3; 211 | style.FrameRounding = 3; 212 | style.ScrollbarRounding = 2; 213 | style.GrabRounding = 3; 214 | 215 | #ifdef IMGUI_HAS_DOCK 216 | style.TabBorderSize = is3D; 217 | style.TabRounding = 3; 218 | 219 | colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.38f, 0.38f, 0.38f, 1.00f); 220 | colors[ImGuiCol_Tab] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 221 | colors[ImGuiCol_TabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); 222 | colors[ImGuiCol_TabActive] = ImVec4(0.33f, 0.33f, 0.33f, 1.00f); 223 | colors[ImGuiCol_TabUnfocused] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 224 | colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.33f, 0.33f, 0.33f, 1.00f); 225 | colors[ImGuiCol_DockingPreview] = ImVec4(0.85f, 0.85f, 0.85f, 0.28f); 226 | 227 | if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) 228 | { 229 | style.WindowRounding = 0.0f; 230 | style.Colors[ImGuiCol_WindowBg].w = 1.0f; 231 | } 232 | #endif 233 | 234 | 235 | ImGui::SetNextWindowSize({ 500, 400 }, ImGuiCond_Always); 236 | ImGui::SetNextWindowCollapsed(false, ImGuiCond_Always); 237 | static int tabb = 0; 238 | ImGui::Begin((" MavenFN - By Imperious "), reinterpret_cast(true)); // start open 239 | ImGui::SetWindowPos(ImVec2(0, 25), ImGuiCond_FirstUseEver); 240 | 241 | ImGui::Checkbox(("Aimbot"), &Settings.Aimbot); 242 | ImGui::Checkbox(("SilentAimbot"), &Settings.SilentAimbot); 243 | if (!Settings.AutoAimbot) { 244 | ImGui::Checkbox(("AimbotFOV##checkbox"), &Settings.ESP.AimbotFOV); 245 | } 246 | if (!Settings.AutoAimbot) { 247 | ImGui::SliderFloat(("AimbotFOV##slider"), &Settings.AimbotFOV, 0.0f, 1000.0f, ("%.2f")); 248 | ImGui::SliderFloat(("AimbotSlow"), &Settings.AimbotSlow, 0.0f, 25.0f, ("%.2f")); 249 | } 250 | ImGui::Text("Ban Rsik"); 251 | if (Settings.Aimbot) { 252 | ImGui::Checkbox(("Rage"), &Settings.AutoAimbot); 253 | ImGui::Checkbox(("NoSpreadAimbot"), &Settings.NoSpreadAimbot); 254 | ImGui::Checkbox(("InstantReload"), &Settings.InstantReload); 255 | } 256 | ImGui::Text(("ESP:")); 257 | ImGui::Checkbox(("bone/box"), &Settings.ESP.Players); 258 | 259 | if (Settings.ESP.Players) { 260 | ImGui::Checkbox(("PlayerLines"), &Settings.ESP.PlayerLines); 261 | ImGui::Checkbox(("PlayerNames"), &Settings.ESP.PlayerNames); 262 | 263 | ImGui::PushItemWidth(150.0f); 264 | ImGui::ColorPicker3(("PlayerVisibleColor"), Settings.ESP.PlayerVisibleColor); 265 | ImGui::ColorPicker3(("PlayerNotVisibleColor"), Settings.ESP.PlayerNotVisibleColor); 266 | ImGui::PopItemWidth(); 267 | } 268 | ImGui::SliderFloat(("FOV"), &Settings.FOV, 60.0f, 160.0f, ("%.2f")); 269 | ImGui::Text("Loot ESP:"); 270 | ImGui::Checkbox(("Ammo"), &Settings.ESP.Ammo); 271 | ImGui::Checkbox(("Containers"), &Settings.ESP.Containers); 272 | ImGui::Checkbox(("Weapons"), &Settings.ESP.Weapons); 273 | if (Settings.ESP.Weapons) { 274 | ImGui::SliderInt(("MinWeaponTier Rariety"), &Settings.ESP.MinWeaponTier, 0, 8); 275 | } 276 | ImGui::End(); 277 | } 278 | 279 | auto success = FALSE; 280 | do { 281 | float closestDistance = FLT_MAX; 282 | PVOID closestPawn = NULL; 283 | 284 | auto world = *Offsets::uWorld; 285 | if (!world) break; 286 | 287 | auto gameInstance = ReadPointer(world, Offsets::Engine::World::OwningGameInstance); 288 | if (!gameInstance) break; 289 | 290 | auto localPlayers = ReadPointer(gameInstance, Offsets::Engine::GameInstance::LocalPlayers); 291 | if (!localPlayers) break; 292 | 293 | auto localPlayer = ReadPointer(localPlayers, 0); 294 | if (!localPlayer) break; 295 | 296 | auto localPlayerController = ReadPointer(localPlayer, Offsets::Engine::Player::PlayerController); 297 | if (!localPlayerController) break; 298 | 299 | auto localPlayerPawn = reinterpret_cast(ReadPointer(localPlayerController, Offsets::Engine::PlayerController::AcknowledgedPawn)); 300 | if (!localPlayerPawn) break; 301 | 302 | auto localPlayerWeapon = ReadPointer(localPlayerPawn, Offsets::FortniteGame::FortPawn::CurrentWeapon); 303 | if (!localPlayerWeapon) break; 304 | 305 | auto localPlayerRoot = ReadPointer(localPlayerPawn, Offsets::Engine::Actor::RootComponent); 306 | if (!localPlayerRoot) break; 307 | 308 | auto localPlayerState = ReadPointer(localPlayerPawn, Offsets::Engine::Pawn::PlayerState); 309 | if (!localPlayerState) break; 310 | 311 | auto localPlayerLocation = reinterpret_cast(reinterpret_cast(localPlayerRoot) + Offsets::Engine::SceneComponent::RelativeLocation); 312 | auto localPlayerTeamIndex = ReadDWORD(localPlayerState, Offsets::FortniteGame::FortPlayerStateAthena::TeamIndex); 313 | 314 | auto weaponName = Util::GetObjectFirstName((UObject*)localPlayerWeapon); 315 | auto isProjectileWeapon = wcsstr(weaponName.c_str(), L"Rifle_Sniper"); 316 | 317 | Core::LocalPlayerPawn = localPlayerPawn; 318 | Core::LocalPlayerController = localPlayerController; 319 | 320 | 321 | std::vector playerPawns; 322 | for (auto li = 0UL; li < ReadDWORD(world, Offsets::Engine::World::Levels + sizeof(PVOID)); ++li) { 323 | auto levels = ReadPointer(world, 0x138);//Levels 324 | if (!levels) break; 325 | 326 | auto level = ReadPointer(levels, li * sizeof(PVOID)); 327 | if (!level) continue; 328 | 329 | for (auto ai = 0UL; ai < ReadDWORD(level, Offsets::Engine::Level::AActors + sizeof(PVOID)); ++ai) { 330 | auto actors = ReadPointer(level, Offsets::Engine::Level::AActors); 331 | if (!actors) break; 332 | 333 | auto pawn = reinterpret_cast(ReadPointer(actors, ai * sizeof(PVOID))); 334 | if (!pawn || pawn == localPlayerPawn) continue; 335 | 336 | auto name = Util::GetObjectFirstName(pawn); 337 | if (wcsstr(name.c_str(), L"PlayerPawn_Athena_C") || wcsstr(name.c_str(), L"PlayerPawn_Athena_Phoebe_C")) { 338 | playerPawns.push_back(pawn); 339 | } 340 | else if (wcsstr(name.c_str(), L"FortPickupAthena")) { 341 | auto item = ReadPointer(pawn, Offsets::FortniteGame::FortPickup::PrimaryPickupItemEntry + Offsets::FortniteGame::FortItemEntry::ItemDefinition); 342 | if (!item) continue; 343 | 344 | auto itemName = reinterpret_cast(ReadPointer(item, Offsets::FortniteGame::FortItemDefinition::DisplayName)); 345 | if (!itemName || !itemName->c_str()) continue; 346 | 347 | auto isAmmo = wcsstr(itemName->c_str(), L"Ammo: "); 348 | if ((!Settings.ESP.Ammo && isAmmo) || ((!Settings.ESP.Weapons || ReadBYTE(item, Offsets::FortniteGame::FortItemDefinition::Tier) < Settings.ESP.MinWeaponTier) && !isAmmo)) continue; 349 | 350 | CHAR text[0xFF] = { 0 }; 351 | wcstombs(text, itemName->c_str() + (isAmmo ? 6 : 0), sizeof(text)); 352 | 353 | AddMarker(window, width, height, localPlayerLocation, pawn, text, isAmmo ? ImGui::GetColorU32({ 0.75f, 0.75f, 0.75f, 1.0f }) : ImGui::GetColorU32({ 1.0f, 1.0f, 1.0f, 1.0f })); 354 | } 355 | else if (Settings.ESP.Containers && wcsstr(name.c_str(), L"Tiered_Chest") && !((ReadBYTE(pawn, Offsets::FortniteGame::BuildingContainer::bAlreadySearched) >> 7) & 1)) { 356 | AddMarker(window, width, height, localPlayerLocation, pawn, "Chest", ImGui::GetColorU32({ 1.0f, 0.84f, 0.0f, 1.0f })); 357 | } 358 | else if (Settings.ESP.Containers && wcsstr(name.c_str(), L"AthenaSupplyDrop_Llama")) { 359 | AddMarker(window, width, height, localPlayerLocation, pawn, "Llama", ImGui::GetColorU32({ 1.0f, 0.0f, 0.0f, 1.0f })); 360 | } 361 | else if (Settings.ESP.Ammo && wcsstr(name.c_str(), L"Tiered_Ammo") && !((ReadBYTE(pawn, Offsets::FortniteGame::BuildingContainer::bAlreadySearched) >> 7) & 1)) { 362 | AddMarker(window, width, height, localPlayerLocation, pawn, "Ammo Box", ImGui::GetColorU32({ 0.75f, 0.75f, 0.75f, 1.0f })); 363 | } 364 | } 365 | } 366 | printf("\nplayer pawns : %p.", playerPawns); 367 | 368 | for (auto pawn : playerPawns) 369 | { 370 | auto state = ReadPointer(pawn, Offsets::Engine::Pawn::PlayerState); 371 | if (!state) continue; 372 | 373 | auto mesh = ReadPointer(pawn, Offsets::Engine::Character::Mesh); 374 | if (!mesh) continue; 375 | 376 | auto bones = ReadPointer(mesh, Offsets::Engine::StaticMeshComponent::StaticMesh); 377 | if (!bones) bones = ReadPointer(mesh, Offsets::Engine::StaticMeshComponent::StaticMesh + 0x10); 378 | if (!bones) continue; 379 | 380 | float compMatrix[4][4] = { 0 }; 381 | Util::ToMatrixWithScale(reinterpret_cast(reinterpret_cast(mesh) + 0x1C0), compMatrix); 382 | 383 | // Top 384 | float head[3] = { 0 }; 385 | Util::GetBoneLocation(compMatrix, bones, 66, head); 386 | 387 | float neck[3] = { 0 }; 388 | Util::GetBoneLocation(compMatrix, bones, 65, neck); 389 | 390 | float chest[3] = { 0 }; 391 | Util::GetBoneLocation(compMatrix, bones, 36, chest); 392 | 393 | float pelvis[3] = { 0 }; 394 | Util::GetBoneLocation(compMatrix, bones, 2, pelvis); 395 | 396 | // Arms 397 | float leftShoulder[3] = { 0 }; 398 | Util::GetBoneLocation(compMatrix, bones, 9, leftShoulder); 399 | 400 | float rightShoulder[3] = { 0 }; 401 | Util::GetBoneLocation(compMatrix, bones, 62, rightShoulder); 402 | 403 | float leftElbow[3] = { 0 }; 404 | Util::GetBoneLocation(compMatrix, bones, 10, leftElbow); 405 | 406 | float rightElbow[3] = { 0 }; 407 | Util::GetBoneLocation(compMatrix, bones, 38, rightElbow); 408 | 409 | float leftHand[3] = { 0 }; 410 | Util::GetBoneLocation(compMatrix, bones, 11, leftHand); 411 | 412 | float rightHand[3] = { 0 }; 413 | Util::GetBoneLocation(compMatrix, bones, 39, rightHand); 414 | 415 | // Legs 416 | float leftLeg[3] = { 0 }; 417 | Util::GetBoneLocation(compMatrix, bones, 67, leftLeg); 418 | 419 | float rightLeg[3] = { 0 }; 420 | Util::GetBoneLocation(compMatrix, bones, 74, rightLeg); 421 | 422 | float leftThigh[3] = { 0 }; 423 | Util::GetBoneLocation(compMatrix, bones, 73, leftThigh); 424 | 425 | float rightThigh[3] = { 0 }; 426 | Util::GetBoneLocation(compMatrix, bones, 80, rightThigh); 427 | 428 | float leftFoot[3] = { 0 }; 429 | Util::GetBoneLocation(compMatrix, bones, 68, leftFoot); 430 | 431 | float rightFoot[3] = { 0 }; 432 | Util::GetBoneLocation(compMatrix, bones, 75, rightFoot); 433 | 434 | float leftFeet[3] = { 0 }; 435 | Util::GetBoneLocation(compMatrix, bones, 71, leftFeet); 436 | 437 | float rightFeet[3] = { 0 }; 438 | Util::GetBoneLocation(compMatrix, bones, 78, rightFeet); 439 | 440 | float leftFeetFinger[3] = { 0 }; 441 | Util::GetBoneLocation(compMatrix, bones, 72, leftFeetFinger); 442 | 443 | float rightFeetFinger[3] = { 0 }; 444 | Util::GetBoneLocation(compMatrix, bones, 79, rightFeetFinger); 445 | 446 | auto color = ImGui::GetColorU32({ Settings.ESP.PlayerNotVisibleColor[0], Settings.ESP.PlayerNotVisibleColor[1], Settings.ESP.PlayerNotVisibleColor[2], 1.0f }); 447 | FVector viewPoint = { 0 }; 448 | 449 | if (ReadDWORD(state, 0xE60) == localPlayerTeamIndex) { 450 | color = ImGui::GetColorU32({ 0.0f, 1.0f, 0.0f, 1.0f }); 451 | } 452 | else if ((ReadBYTE(pawn, Offsets::FortniteGame::FortPawn::bIsDBNO) & 1) && (isProjectileWeapon || Util::LineOfSightTo(localPlayerController, pawn, &viewPoint))) { 453 | color = ImGui::GetColorU32({ Settings.ESP.PlayerVisibleColor[0], Settings.ESP.PlayerVisibleColor[1], Settings.ESP.PlayerVisibleColor[2], 1.0f }); 454 | if (Settings.AutoAimbot) { 455 | auto dx = head[0] - localPlayerLocation[0]; 456 | auto dy = head[1] - localPlayerLocation[1]; 457 | auto dz = head[2] - localPlayerLocation[2]; 458 | auto dist = dx * dx + dy * dy + dz * dz; 459 | if (dist < closestDistance) { 460 | closestDistance = dist; 461 | closestPawn = pawn; 462 | 463 | 464 | } 465 | } 466 | else 467 | { 468 | auto w2s = *reinterpret_cast(head); 469 | if (Util::WorldToScreen(width, height, &w2s.X)) { 470 | auto dx = w2s.X - (width / 2); 471 | auto dy = w2s.Y - (height / 2); 472 | auto dist = Util::SpoofCall(sqrtf, dx * dx + dy * dy); 473 | if (dist < Settings.AimbotFOV && dist < closestDistance) { 474 | closestDistance = dist; 475 | closestPawn = pawn; 476 | 477 | 478 | } 479 | } 480 | } 481 | } 482 | 483 | 484 | 485 | if (!Settings.ESP.Players) continue; 486 | 487 | if (Settings.ESP.PlayerLines) { 488 | auto end = *reinterpret_cast(head); 489 | if (Util::WorldToScreen(width, height, &end.X)) { 490 | window.DrawList->AddLine(ImVec2(width / 2, height), ImVec2(end.X, end.Y), color); 491 | } 492 | } 493 | 494 | float minX = FLT_MAX; 495 | float maxX = -FLT_MAX; 496 | float minY = FLT_MAX; 497 | float maxY = -FLT_MAX; 498 | 499 | AddLine(window, width, height, head, neck, color, minX, maxX, minY, maxY); 500 | AddLine(window, width, height, neck, pelvis, color, minX, maxX, minY, maxY); 501 | AddLine(window, width, height, chest, leftShoulder, color, minX, maxX, minY, maxY); 502 | AddLine(window, width, height, chest, rightShoulder, color, minX, maxX, minY, maxY); 503 | AddLine(window, width, height, leftShoulder, leftElbow, color, minX, maxX, minY, maxY); 504 | AddLine(window, width, height, rightShoulder, rightElbow, color, minX, maxX, minY, maxY); 505 | AddLine(window, width, height, leftElbow, leftHand, color, minX, maxX, minY, maxY); 506 | AddLine(window, width, height, rightElbow, rightHand, color, minX, maxX, minY, maxY); 507 | AddLine(window, width, height, pelvis, leftLeg, color, minX, maxX, minY, maxY); 508 | AddLine(window, width, height, pelvis, rightLeg, color, minX, maxX, minY, maxY); 509 | AddLine(window, width, height, leftLeg, leftThigh, color, minX, maxX, minY, maxY); 510 | AddLine(window, width, height, rightLeg, rightThigh, color, minX, maxX, minY, maxY); 511 | AddLine(window, width, height, leftThigh, leftFoot, color, minX, maxX, minY, maxY); 512 | AddLine(window, width, height, rightThigh, rightFoot, color, minX, maxX, minY, maxY); 513 | AddLine(window, width, height, leftFoot, leftFeet, color, minX, maxX, minY, maxY); 514 | AddLine(window, width, height, rightFoot, rightFeet, color, minX, maxX, minY, maxY); 515 | AddLine(window, width, height, leftFeet, leftFeetFinger, color, minX, maxX, minY, maxY); 516 | AddLine(window, width, height, rightFeet, rightFeetFinger, color, minX, maxX, minY, maxY); 517 | 518 | if (minX < width && maxX > 0 && minY < height && maxY > 0) { 519 | auto topLeft = ImVec2(minX - 3.0f, minY - 3.0f); 520 | auto bottomRight = ImVec2(maxX + 3.0f, maxY + 3.0f); 521 | 522 | window.DrawList->AddRectFilled(topLeft, bottomRight, ImGui::GetColorU32({ 0.0f, 0.0f, 0.0f, 0.20f })); 523 | window.DrawList->AddRect(topLeft, bottomRight, ImGui::GetColorU32({ 0.0f, 0.50f, 0.90f, 1.0f }), 0.5, 15, 1.5f); 524 | 525 | if (Settings.ESP.PlayerNames) { 526 | FString playerName; 527 | Core::ProcessEvent(state, Offsets::Engine::PlayerState::GetPlayerName, &playerName, 0); 528 | if (playerName.c_str()) { 529 | CHAR copy[0xFF] = { 0 }; 530 | wcstombs(copy, playerName.c_str(), sizeof(copy)); 531 | Util::FreeInternal(playerName.c_str()); 532 | 533 | auto centerTop = ImVec2((topLeft.x + bottomRight.x) / 2.0f, topLeft.y); 534 | auto size = ImGui::GetFont()->CalcTextSizeA(window.DrawList->_Data->FontSize, FLT_MAX, 0, copy); 535 | window.DrawList->AddRectFilled(ImVec2(centerTop.x - size.x / 2.0f, centerTop.y - size.y + 3.0f), ImVec2(centerTop.x + size.x / 2.0f, centerTop.y), ImGui::GetColorU32({ 0.0f, 0.0f, 0.0f, 0.4f })); 536 | window.DrawList->AddText(ImVec2(centerTop.x - size.x / 2.0f, centerTop.y - size.y), color, copy); 537 | } 538 | } 539 | } 540 | } 541 | 542 | 543 | 544 | if (Settings.Aimbot && closestPawn && Util::SpoofCall(GetAsyncKeyState, VK_RBUTTON) < 0 && Util::SpoofCall(GetForegroundWindow) == hWnd) { 545 | Core::TargetPawn = closestPawn; 546 | Core::NoSpread = FALSE; 547 | //printf("\nworked?"); 548 | } 549 | else { 550 | Core::TargetPawn = nullptr; 551 | Core::NoSpread = FALSE; 552 | } 553 | if (!Settings.AutoAimbot && Settings.ESP.AimbotFOV) { 554 | window.DrawList->AddCircle(ImVec2(width / 2, height / 2), Settings.AimbotFOV, ImGui::GetColorU32({ 0.0f, 0.0f, 0.0f, 1.0f }), 128); 555 | } 556 | 557 | 558 | 559 | /*printf("\nLocalPlayerController : %p.", Core::LocalPlayerController); 560 | printf("\nSetControlRotation : %p.", Offsets::Engine::Controller::SetControlRotation); 561 | printf("\n Target Pawn : %p.", Core::TargetPawn); 562 | printf("\nClosest Pawn %p.", closestPawn); 563 | auto currentRotation = Util::GetViewInfo().Rotation; 564 | printf("\nCurrent Rotation : %p.", currentRotation); 565 | printf("\nClosest Pawn : %p.", closestPawn); */ 566 | //AddMarker(window, width / 2, height / 2, 120 , pawn ,"not made by impur", ImGui::GetColorU32({ 0.75f, 0.75f, 0.75f, 1.0f }))l 567 | success = TRUE; 568 | } while (FALSE); 569 | 570 | if (!success) { 571 | Core::LocalPlayerController = Core::LocalPlayerPawn = Core::TargetPawn = nullptr; 572 | } 573 | EndScene(window); 574 | //// i had a sleep here :( 575 | return PresentOriginal(swapChain, syncInterval, flags); 576 | } 577 | 578 | 579 | 580 | __declspec(dllexport) HRESULT ResizeHook(IDXGISwapChain* swapChain, UINT bufferCount, UINT width, UINT height, DXGI_FORMAT newFormat, UINT swapChainFlags) { 581 | ImGui_ImplDX11_Shutdown(); 582 | renderTargetView->Release(); 583 | immediateContext->Release(); 584 | device->Release(); 585 | device = nullptr; 586 | 587 | return ResizeOriginal(swapChain, bufferCount, width, height, newFormat, swapChainFlags); 588 | } 589 | 590 | 591 | bool Render::Initialize() { 592 | IDXGISwapChain* swapChain = nullptr; 593 | ID3D11Device* device = nullptr; 594 | ID3D11DeviceContext* context = nullptr; 595 | auto featureLevel = D3D_FEATURE_LEVEL_11_0; 596 | 597 | DXGI_SWAP_CHAIN_DESC sd = { 0 }; 598 | sd.BufferCount = 1; 599 | sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 600 | sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 601 | sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; 602 | sd.OutputWindow = FindWindow((L"UnrealWindow"), (L"Fortnite ")); 603 | sd.SampleDesc.Count = 1; 604 | sd.Windowed = TRUE; 605 | 606 | if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, 0, &featureLevel, 1, D3D11_SDK_VERSION, &sd, &swapChain, &device, nullptr, &context))) { 607 | MessageBox(0, L"Failed to create D3D11 device and swap chain", L"Failure", MB_ICONERROR); 608 | return FALSE; 609 | } 610 | 611 | auto table = *reinterpret_cast(swapChain); 612 | auto present = table[8]; 613 | auto resize = table[13]; 614 | 615 | context->Release(); 616 | device->Release(); 617 | swapChain->Release(); 618 | 619 | MH_CreateHook(present, PresentHook, reinterpret_cast(&PresentOriginal)); 620 | MH_EnableHook(present); 621 | 622 | MH_CreateHook(resize, ResizeHook, reinterpret_cast(&ResizeOriginal)); 623 | MH_EnableHook(resize); 624 | 625 | return TRUE; 626 | } 627 | -------------------------------------------------------------------------------- /imgui/imgui_impl_dx11.cpp: -------------------------------------------------------------------------------- 1 | 2 | // ImGui Win32 + DirectX11 binding 3 | // In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. 4 | 5 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 6 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 7 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 8 | // https://github.com/ocornut/imgui 9 | 10 | #include "imgui.h" 11 | #include "imgui_impl_dx11.h" 12 | #include "imgui_internal.h" 13 | 14 | // DirectX 15 | #include 16 | #define DIRECTINPUT_VERSION 0x0800 17 | #include 18 | 19 | // Data 20 | static INT64 g_Time = 0; 21 | static INT64 g_TicksPerSecond = 0; 22 | 23 | static HWND g_hWnd = 0; 24 | static ID3D11Device* g_pd3dDevice = NULL; 25 | static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; 26 | static ID3D11Buffer* g_pVB = NULL; 27 | static ID3D11Buffer* g_pIB = NULL; 28 | static ID3D11VertexShader* g_pVertexShader = NULL; 29 | static ID3D11InputLayout* g_pInputLayout = NULL; 30 | static ID3D11Buffer* g_pVertexConstantBuffer = NULL; 31 | static ID3D11PixelShader* g_pPixelShader = NULL; 32 | static ID3D11SamplerState* g_pFontSampler = NULL; 33 | static ID3D11ShaderResourceView*g_pFontTextureView = NULL; 34 | static ID3D11RasterizerState* g_pRasterizerState = NULL; 35 | static ID3D11BlendState* g_pBlendState = NULL; 36 | static ID3D11DepthStencilState* g_pDepthStencilState = NULL; 37 | static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; 38 | 39 | struct VERTEX_CONSTANT_BUFFER 40 | { 41 | float mvp[4][4]; 42 | }; 43 | 44 | // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) 45 | // If text or lines are blurry when integrating ImGui in your engine: 46 | // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) 47 | void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) 48 | { 49 | ID3D11DeviceContext* ctx = g_pd3dDeviceContext; 50 | 51 | // Create and grow vertex/index buffers if needed 52 | if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) 53 | { 54 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } 55 | g_VertexBufferSize = draw_data->TotalVtxCount + 5000; 56 | D3D11_BUFFER_DESC desc; 57 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 58 | desc.Usage = D3D11_USAGE_DYNAMIC; 59 | desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); 60 | desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 61 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 62 | desc.MiscFlags = 0; 63 | if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) 64 | return; 65 | } 66 | if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) 67 | { 68 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } 69 | g_IndexBufferSize = draw_data->TotalIdxCount + 10000; 70 | D3D11_BUFFER_DESC desc; 71 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 72 | desc.Usage = D3D11_USAGE_DYNAMIC; 73 | desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); 74 | desc.BindFlags = D3D11_BIND_INDEX_BUFFER; 75 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 76 | if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) 77 | return; 78 | } 79 | 80 | // Copy and convert all vertices into a single contiguous buffer 81 | D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; 82 | if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) 83 | return; 84 | if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) 85 | return; 86 | ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; 87 | ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; 88 | for (int n = 0; n < draw_data->CmdListsCount; n++) 89 | { 90 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 91 | memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); 92 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 93 | vtx_dst += cmd_list->VtxBuffer.Size; 94 | idx_dst += cmd_list->IdxBuffer.Size; 95 | } 96 | ctx->Unmap(g_pVB, 0); 97 | ctx->Unmap(g_pIB, 0); 98 | 99 | // Setup orthographic projection matrix into our constant buffer 100 | { 101 | D3D11_MAPPED_SUBRESOURCE mapped_resource; 102 | if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) 103 | return; 104 | VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; 105 | float L = 0.0f; 106 | float R = ImGui::GetIO().DisplaySize.x; 107 | float B = ImGui::GetIO().DisplaySize.y; 108 | float T = 0.0f; 109 | float mvp[4][4] = 110 | { 111 | { 2.0f / (R - L), 0.0f, 0.0f, 0.0f }, 112 | { 0.0f, 2.0f / (T - B), 0.0f, 0.0f }, 113 | { 0.0f, 0.0f, 0.5f, 0.0f }, 114 | { (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f }, 115 | }; 116 | memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); 117 | ctx->Unmap(g_pVertexConstantBuffer, 0); 118 | } 119 | 120 | // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) 121 | struct BACKUP_DX11_STATE 122 | { 123 | UINT ScissorRectsCount, ViewportsCount; 124 | D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 125 | D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 126 | ID3D11RasterizerState* RS; 127 | ID3D11BlendState* BlendState; 128 | FLOAT BlendFactor[4]; 129 | UINT SampleMask; 130 | UINT StencilRef; 131 | ID3D11DepthStencilState* DepthStencilState; 132 | ID3D11ShaderResourceView* PSShaderResource; 133 | ID3D11SamplerState* PSSampler; 134 | ID3D11PixelShader* PS; 135 | ID3D11VertexShader* VS; 136 | UINT PSInstancesCount, VSInstancesCount; 137 | ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation 138 | D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; 139 | ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; 140 | UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; 141 | DXGI_FORMAT IndexBufferFormat; 142 | ID3D11InputLayout* InputLayout; 143 | }; 144 | BACKUP_DX11_STATE old; 145 | old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; 146 | ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); 147 | ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); 148 | ctx->RSGetState(&old.RS); 149 | ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); 150 | ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); 151 | ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); 152 | ctx->PSGetSamplers(0, 1, &old.PSSampler); 153 | old.PSInstancesCount = old.VSInstancesCount = 256; 154 | ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); 155 | ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); 156 | ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); 157 | ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); 158 | ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); 159 | ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); 160 | ctx->IAGetInputLayout(&old.InputLayout); 161 | 162 | // Setup viewport 163 | D3D11_VIEWPORT vp; 164 | memset(&vp, 0, sizeof(D3D11_VIEWPORT)); 165 | vp.Width = ImGui::GetIO().DisplaySize.x; 166 | vp.Height = ImGui::GetIO().DisplaySize.y; 167 | vp.MinDepth = 0.0f; 168 | vp.MaxDepth = 1.0f; 169 | vp.TopLeftX = vp.TopLeftY = 0.0f; 170 | ctx->RSSetViewports(1, &vp); 171 | 172 | // Bind shader and vertex buffers 173 | unsigned int stride = sizeof(ImDrawVert); 174 | unsigned int offset = 0; 175 | ctx->IASetInputLayout(g_pInputLayout); 176 | ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); 177 | ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); 178 | ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 179 | ctx->VSSetShader(g_pVertexShader, NULL, 0); 180 | ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); 181 | ctx->PSSetShader(g_pPixelShader, NULL, 0); 182 | ctx->PSSetSamplers(0, 1, &g_pFontSampler); 183 | 184 | // Setup render state 185 | const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; 186 | ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); 187 | ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); 188 | ctx->RSSetState(g_pRasterizerState); 189 | 190 | // Render command lists 191 | int vtx_offset = 0; 192 | int idx_offset = 0; 193 | for (int n = 0; n < draw_data->CmdListsCount; n++) 194 | { 195 | const ImDrawList* cmd_list = draw_data->CmdLists[n]; 196 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 197 | { 198 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 199 | if (pcmd->UserCallback) 200 | { 201 | pcmd->UserCallback(cmd_list, pcmd); 202 | } 203 | else 204 | { 205 | const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; 206 | ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); 207 | ctx->RSSetScissorRects(1, &r); 208 | ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); 209 | } 210 | idx_offset += pcmd->ElemCount; 211 | } 212 | vtx_offset += cmd_list->VtxBuffer.Size; 213 | } 214 | 215 | // Restore modified DX state 216 | ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); 217 | ctx->RSSetViewports(old.ViewportsCount, old.Viewports); 218 | ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); 219 | ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); 220 | ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); 221 | ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); 222 | ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); 223 | ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); 224 | for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); 225 | ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); 226 | ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); 227 | for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); 228 | ctx->IASetPrimitiveTopology(old.PrimitiveTopology); 229 | ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); 230 | ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); 231 | ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); 232 | } 233 | 234 | static bool IsAnyMouseButtonDown() 235 | { 236 | ImGuiIO& io = ImGui::GetIO(); 237 | for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) 238 | if (io.MouseDown[n]) 239 | return true; 240 | return false; 241 | } 242 | 243 | // Process Win32 mouse/keyboard inputs. 244 | // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. 245 | // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. 246 | // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. 247 | // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. 248 | // PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. 249 | // 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. 250 | IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 251 | { 252 | ImGuiIO& io = ImGui::GetIO(); 253 | switch (msg) 254 | { 255 | case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: 256 | case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: 257 | case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: 258 | { 259 | int button = 0; 260 | if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; 261 | if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; 262 | if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; 263 | if (!IsAnyMouseButtonDown() && GetCapture() == NULL) 264 | SetCapture(hwnd); 265 | io.MouseDown[button] = true; 266 | return 0; 267 | } 268 | case WM_LBUTTONUP: 269 | case WM_RBUTTONUP: 270 | case WM_MBUTTONUP: 271 | { 272 | int button = 0; 273 | if (msg == WM_LBUTTONUP) button = 0; 274 | if (msg == WM_RBUTTONUP) button = 1; 275 | if (msg == WM_MBUTTONUP) button = 2; 276 | io.MouseDown[button] = false; 277 | if (!IsAnyMouseButtonDown() && GetCapture() == hwnd) 278 | ReleaseCapture(); 279 | return 0; 280 | } 281 | case WM_MOUSEWHEEL: 282 | io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; 283 | return 0; 284 | case WM_MOUSEMOVE: 285 | io.MousePos.x = (signed short)(lParam); 286 | io.MousePos.y = (signed short)(lParam >> 16); 287 | return 0; 288 | case WM_KEYDOWN: 289 | case WM_SYSKEYDOWN: 290 | if (wParam < 256) 291 | io.KeysDown[wParam] = 1; 292 | return 0; 293 | case WM_KEYUP: 294 | case WM_SYSKEYUP: 295 | if (wParam < 256) 296 | io.KeysDown[wParam] = 0; 297 | return 0; 298 | case WM_CHAR: 299 | // You can also use ToAscii()+GetKeyboardState() to retrieve characters. 300 | if (wParam > 0 && wParam < 0x10000) 301 | io.AddInputCharacter((unsigned short)wParam); 302 | return 0; 303 | } 304 | return 0; 305 | } 306 | 307 | static void ImGui_ImplDX11_CreateFontsTexture() 308 | { 309 | // Build texture atlas 310 | ImGuiIO& io = ImGui::GetIO(); 311 | unsigned char* pixels; 312 | int width, height; 313 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 314 | 315 | // Upload texture to graphics system 316 | { 317 | D3D11_TEXTURE2D_DESC desc; 318 | ZeroMemory(&desc, sizeof(desc)); 319 | desc.Width = width; 320 | desc.Height = height; 321 | desc.MipLevels = 1; 322 | desc.ArraySize = 1; 323 | desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 324 | desc.SampleDesc.Count = 1; 325 | desc.Usage = D3D11_USAGE_DEFAULT; 326 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 327 | desc.CPUAccessFlags = 0; 328 | 329 | ID3D11Texture2D *pTexture = NULL; 330 | D3D11_SUBRESOURCE_DATA subResource; 331 | subResource.pSysMem = pixels; 332 | subResource.SysMemPitch = desc.Width * 4; 333 | subResource.SysMemSlicePitch = 0; 334 | g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); 335 | 336 | // Create texture view 337 | D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 338 | ZeroMemory(&srvDesc, sizeof(srvDesc)); 339 | srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 340 | srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 341 | srvDesc.Texture2D.MipLevels = desc.MipLevels; 342 | srvDesc.Texture2D.MostDetailedMip = 0; 343 | g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); 344 | pTexture->Release(); 345 | } 346 | 347 | // Store our identifier 348 | io.Fonts->TexID = (void *)g_pFontTextureView; 349 | 350 | // Create texture sampler 351 | { 352 | D3D11_SAMPLER_DESC desc; 353 | ZeroMemory(&desc, sizeof(desc)); 354 | desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 355 | desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; 356 | desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; 357 | desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; 358 | desc.MipLODBias = 0.f; 359 | desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; 360 | desc.MinLOD = 0.f; 361 | desc.MaxLOD = 0.f; 362 | g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); 363 | } 364 | } 365 | 366 | bool ImGui_ImplDX11_CreateDeviceObjects() 367 | { 368 | if (!g_pd3dDevice) 369 | return false; 370 | if (g_pFontSampler) 371 | ImGui_ImplDX11_InvalidateDeviceObjects(); 372 | 373 | // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) 374 | // If you would like to use this DX11 sample code but remove this dependency you can: 375 | // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] 376 | // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. 377 | // See https://github.com/ocornut/imgui/pull/638 for sources and details. 378 | 379 | // Create the vertex shader 380 | { 381 | static unsigned char vertexBuffer[] = { 0x44, 0x58, 0x42, 0x43, 0xA5, 0x65, 0x6C, 0xBA, 0x38, 0x7A, 0x27, 0x51, 0xAE, 0x7C, 0xE0, 0x18, 0xED, 0xDE, 0xC0, 0xE4, 0x01, 0x00, 0x00, 0x00, 0x78, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xF4, 0x01, 0x00, 0x00, 0xFC, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xD4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFE, 0xFF, 0x00, 0x01, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x00, 0xAB, 0xAB, 0xAB, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x4D, 0x61, 0x74, 0x72, 0x69, 0x78, 0x00, 0xAB, 0xAB, 0xAB, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4C, 0x53, 0x4C, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x69, 0x6C, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2E, 0x30, 0x2E, 0x31, 0x30, 0x30, 0x31, 0x31, 0x2E, 0x31, 0x36, 0x33, 0x38, 0x34, 0x00, 0x49, 0x53, 0x47, 0x4E, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x50, 0x4F, 0x53, 0x49, 0x54, 0x49, 0x4F, 0x4E, 0x00, 0x43, 0x4F, 0x4C, 0x4F, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4F, 0x4F, 0x52, 0x44, 0x00, 0x4F, 0x53, 0x47, 0x4E, 0x6C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x53, 0x56, 0x5F, 0x50, 0x4F, 0x53, 0x49, 0x54, 0x49, 0x4F, 0x4E, 0x00, 0x43, 0x4F, 0x4C, 0x4F, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4F, 0x4F, 0x52, 0x44, 0x00, 0xAB, 0x53, 0x48, 0x44, 0x52, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x03, 0xF2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, 0xF2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xF2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x32, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x08, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x15, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0A, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xF2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xF2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x1E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x32, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 382 | 383 | if (g_pd3dDevice->CreateVertexShader(vertexBuffer, sizeof(vertexBuffer), NULL, &g_pVertexShader) != S_OK) 384 | return false; 385 | 386 | // Create the input layout 387 | D3D11_INPUT_ELEMENT_DESC local_layout[] = { 388 | { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 389 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 390 | { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 391 | }; 392 | if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexBuffer, sizeof(vertexBuffer), &g_pInputLayout) != S_OK) 393 | return false; 394 | 395 | // Create the constant buffer 396 | { 397 | D3D11_BUFFER_DESC desc; 398 | desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); 399 | desc.Usage = D3D11_USAGE_DYNAMIC; 400 | desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 401 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 402 | desc.MiscFlags = 0; 403 | g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); 404 | } 405 | } 406 | 407 | // Create the pixel shader 408 | { 409 | static unsigned char shaderBlob[] = { 0x44, 0x58, 0x42, 0x43, 0xF4, 0x37, 0x3F, 0xAD, 0x4C, 0xA5, 0xBC, 0xD8, 0x5D, 0xCA, 0xD9, 0x4F, 0xE0, 0x7A, 0xCE, 0x9A, 0x01, 0x00, 0x00, 0x00, 0xA0, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x72, 0x30, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x30, 0x00, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4C, 0x53, 0x4C, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x69, 0x6C, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2E, 0x30, 0x2E, 0x31, 0x30, 0x30, 0x31, 0x31, 0x2E, 0x31, 0x36, 0x33, 0x38, 0x34, 0x00, 0xAB, 0xAB, 0x49, 0x53, 0x47, 0x4E, 0x6C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x53, 0x56, 0x5F, 0x50, 0x4F, 0x53, 0x49, 0x54, 0x49, 0x4F, 0x4E, 0x00, 0x43, 0x4F, 0x4C, 0x4F, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4F, 0x4F, 0x52, 0x44, 0x00, 0xAB, 0x4F, 0x53, 0x47, 0x4E, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5F, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0xAB, 0xAB, 0x53, 0x48, 0x44, 0x52, 0x94, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0xF2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xF2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x09, 0xF2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x7E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0xF2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1E, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 410 | 411 | if (g_pd3dDevice->CreatePixelShader(shaderBlob, sizeof(shaderBlob), NULL, &g_pPixelShader) != S_OK) 412 | return false; 413 | } 414 | 415 | // Create the blending setup 416 | { 417 | D3D11_BLEND_DESC desc; 418 | ZeroMemory(&desc, sizeof(desc)); 419 | desc.AlphaToCoverageEnable = false; 420 | desc.RenderTarget[0].BlendEnable = true; 421 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; 422 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 423 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; 424 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; 425 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; 426 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 427 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 428 | g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); 429 | } 430 | 431 | // Create the rasterizer state 432 | { 433 | D3D11_RASTERIZER_DESC desc; 434 | ZeroMemory(&desc, sizeof(desc)); 435 | desc.FillMode = D3D11_FILL_SOLID; 436 | desc.CullMode = D3D11_CULL_NONE; 437 | desc.ScissorEnable = true; 438 | desc.DepthClipEnable = true; 439 | g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); 440 | } 441 | 442 | // Create depth-stencil State 443 | { 444 | D3D11_DEPTH_STENCIL_DESC desc; 445 | ZeroMemory(&desc, sizeof(desc)); 446 | desc.DepthEnable = false; 447 | desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; 448 | desc.DepthFunc = D3D11_COMPARISON_ALWAYS; 449 | desc.StencilEnable = false; 450 | desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 451 | desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 452 | desc.BackFace = desc.FrontFace; 453 | g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); 454 | } 455 | 456 | ImGui_ImplDX11_CreateFontsTexture(); 457 | 458 | return true; 459 | } 460 | 461 | void ImGui_ImplDX11_InvalidateDeviceObjects() 462 | { 463 | if (!g_pd3dDevice) 464 | return; 465 | 466 | if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } 467 | if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. 468 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } 469 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } 470 | 471 | if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } 472 | if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } 473 | if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } 474 | if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } 475 | if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } 476 | if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } 477 | if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } 478 | } 479 | 480 | bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context) 481 | { 482 | g_hWnd = (HWND)hwnd; 483 | g_pd3dDevice = device; 484 | g_pd3dDeviceContext = device_context; 485 | 486 | if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) 487 | return false; 488 | if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) 489 | return false; 490 | 491 | ImGuiIO& io = ImGui::GetIO(); 492 | io.KeyMap[ImGuiKey_Tab] = VK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array that we will update during the application lifetime. 493 | io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; 494 | io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; 495 | io.KeyMap[ImGuiKey_UpArrow] = VK_UP; 496 | io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN; 497 | io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; 498 | io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; 499 | io.KeyMap[ImGuiKey_Home] = VK_HOME; 500 | io.KeyMap[ImGuiKey_End] = VK_END; 501 | io.KeyMap[ImGuiKey_Insert] = VK_INSERT; 502 | io.KeyMap[ImGuiKey_Delete] = VK_DELETE; 503 | io.KeyMap[ImGuiKey_Backspace] = VK_BACK; 504 | io.KeyMap[ImGuiKey_Enter] = VK_RETURN; 505 | io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; 506 | io.KeyMap[ImGuiKey_A] = 'A'; 507 | io.KeyMap[ImGuiKey_C] = 'C'; 508 | io.KeyMap[ImGuiKey_V] = 'V'; 509 | io.KeyMap[ImGuiKey_X] = 'X'; 510 | io.KeyMap[ImGuiKey_Y] = 'Y'; 511 | io.KeyMap[ImGuiKey_Z] = 'Z'; 512 | 513 | io.RenderDrawListsFn = ImGui_ImplDX11_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. 514 | io.ImeWindowHandle = g_hWnd; 515 | 516 | return true; 517 | } 518 | 519 | void ImGui_ImplDX11_Shutdown() 520 | { 521 | ImGui_ImplDX11_InvalidateDeviceObjects(); 522 | ImGui::Shutdown(); 523 | g_pd3dDevice = NULL; 524 | g_pd3dDeviceContext = NULL; 525 | g_hWnd = (HWND)0; 526 | } 527 | 528 | void ImGui_ImplDX11_NewFrame() 529 | { 530 | if (!g_pFontSampler) 531 | ImGui_ImplDX11_CreateDeviceObjects(); 532 | 533 | ImGuiIO& io = ImGui::GetIO(); 534 | 535 | // Setup display size (every frame to accommodate for window resizing) 536 | RECT rect; 537 | GetClientRect(g_hWnd, &rect); 538 | io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); 539 | 540 | // Setup time step 541 | INT64 current_time; 542 | QueryPerformanceCounter((LARGE_INTEGER *)¤t_time); 543 | io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond; 544 | g_Time = current_time; 545 | 546 | // Read keyboard modifiers inputs 547 | io.KeyCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0; 548 | io.KeyShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; 549 | io.KeyAlt = (GetKeyState(VK_MENU) & 0x8000) != 0; 550 | io.KeySuper = false; 551 | // io.KeysDown : filled by WM_KEYDOWN/WM_KEYUP events 552 | // io.MousePos : filled by WM_MOUSEMOVE events 553 | // io.MouseDown : filled by WM_*BUTTON* events 554 | // io.MouseWheel : filled by WM_MOUSEWHEEL events 555 | 556 | // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) 557 | if (io.WantMoveMouse) 558 | { 559 | POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; 560 | ClientToScreen(g_hWnd, &pos); 561 | SetCursorPos(pos.x, pos.y); 562 | } 563 | 564 | // Hide OS mouse cursor if ImGui is drawing it 565 | if (io.MouseDrawCursor) 566 | SetCursor(NULL); 567 | 568 | // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. 569 | ImGui::NewFrame(); 570 | } 571 | -------------------------------------------------------------------------------- /imgui/stb_textedit.h: -------------------------------------------------------------------------------- 1 | // [ImGui] this is a slightly modified version of stb_truetype.h 1.9. Those changes would need to be pushed into nothings/sb 2 | // [ImGui] - fixed linestart handler when over last character of multi-line buffer + simplified existing code (#588, #815) 3 | // [ImGui] - fixed a state corruption/crash bug in stb_text_redo and stb_textedit_discard_redo (#715) 4 | // [ImGui] - fixed a crash bug in stb_textedit_discard_redo (#681) 5 | // [ImGui] - fixed some minor warnings 6 | 7 | // stb_textedit.h - v1.9 - public domain - Sean Barrett 8 | // Development of this library was sponsored by RAD Game Tools 9 | // 10 | // This C header file implements the guts of a multi-line text-editing 11 | // widget; you implement display, word-wrapping, and low-level string 12 | // insertion/deletion, and stb_textedit will map user inputs into 13 | // insertions & deletions, plus updates to the cursor position, 14 | // selection state, and undo state. 15 | // 16 | // It is intended for use in games and other systems that need to build 17 | // their own custom widgets and which do not have heavy text-editing 18 | // requirements (this library is not recommended for use for editing large 19 | // texts, as its performance does not scale and it has limited undo). 20 | // 21 | // Non-trivial behaviors are modelled after Windows text controls. 22 | // 23 | // 24 | // LICENSE 25 | // 26 | // This software is dual-licensed to the public domain and under the following 27 | // license: you are granted a perpetual, irrevocable license to copy, modify, 28 | // publish, and distribute this file as you see fit. 29 | // 30 | // 31 | // DEPENDENCIES 32 | // 33 | // Uses the C runtime function 'memmove', which you can override 34 | // by defining STB_TEXTEDIT_memmove before the implementation. 35 | // Uses no other functions. Performs no runtime allocations. 36 | // 37 | // 38 | // VERSION HISTORY 39 | // 40 | // 1.9 (2016-08-27) customizable move-by-word 41 | // 1.8 (2016-04-02) better keyboard handling when mouse button is down 42 | // 1.7 (2015-09-13) change y range handling in case baseline is non-0 43 | // 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove 44 | // 1.5 (2014-09-10) add support for secondary keys for OS X 45 | // 1.4 (2014-08-17) fix signed/unsigned warnings 46 | // 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary 47 | // 1.2 (2014-05-27) fix some RAD types that had crept into the new code 48 | // 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE ) 49 | // 1.0 (2012-07-26) improve documentation, initial public release 50 | // 0.3 (2012-02-24) bugfixes, single-line mode; insert mode 51 | // 0.2 (2011-11-28) fixes to undo/redo 52 | // 0.1 (2010-07-08) initial version 53 | // 54 | // ADDITIONAL CONTRIBUTORS 55 | // 56 | // Ulf Winklemann: move-by-word in 1.1 57 | // Fabian Giesen: secondary key inputs in 1.5 58 | // Martins Mozeiko: STB_TEXTEDIT_memmove 59 | // 60 | // Bugfixes: 61 | // Scott Graham 62 | // Daniel Keller 63 | // Omar Cornut 64 | // 65 | // USAGE 66 | // 67 | // This file behaves differently depending on what symbols you define 68 | // before including it. 69 | // 70 | // 71 | // Header-file mode: 72 | // 73 | // If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this, 74 | // it will operate in "header file" mode. In this mode, it declares a 75 | // single public symbol, STB_TexteditState, which encapsulates the current 76 | // state of a text widget (except for the string, which you will store 77 | // separately). 78 | // 79 | // To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a 80 | // primitive type that defines a single character (e.g. char, wchar_t, etc). 81 | // 82 | // To save space or increase undo-ability, you can optionally define the 83 | // following things that are used by the undo system: 84 | // 85 | // STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position 86 | // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow 87 | // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer 88 | // 89 | // If you don't define these, they are set to permissive types and 90 | // moderate sizes. The undo system does no memory allocations, so 91 | // it grows STB_TexteditState by the worst-case storage which is (in bytes): 92 | // 93 | // [4 + sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT 94 | // + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT 95 | // 96 | // 97 | // Implementation mode: 98 | // 99 | // If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it 100 | // will compile the implementation of the text edit widget, depending 101 | // on a large number of symbols which must be defined before the include. 102 | // 103 | // The implementation is defined only as static functions. You will then 104 | // need to provide your own APIs in the same file which will access the 105 | // static functions. 106 | // 107 | // The basic concept is that you provide a "string" object which 108 | // behaves like an array of characters. stb_textedit uses indices to 109 | // refer to positions in the string, implicitly representing positions 110 | // in the displayed textedit. This is true for both plain text and 111 | // rich text; even with rich text stb_truetype interacts with your 112 | // code as if there was an array of all the displayed characters. 113 | // 114 | // Symbols that must be the same in header-file and implementation mode: 115 | // 116 | // STB_TEXTEDIT_CHARTYPE the character type 117 | // STB_TEXTEDIT_POSITIONTYPE small type that a valid cursor position 118 | // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow 119 | // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer 120 | // 121 | // Symbols you must define for implementation mode: 122 | // 123 | // STB_TEXTEDIT_STRING the type of object representing a string being edited, 124 | // typically this is a wrapper object with other data you need 125 | // 126 | // STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1)) 127 | // STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters 128 | // starting from character #n (see discussion below) 129 | // STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character 130 | // to the xpos of the i+1'th char for a line of characters 131 | // starting at character #n (i.e. accounts for kerning 132 | // with previous char) 133 | // STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character 134 | // (return type is int, -1 means not valid to insert) 135 | // STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based 136 | // STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize 137 | // as manually wordwrapping for end-of-line positioning 138 | // 139 | // STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i 140 | // STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*) 141 | // 142 | // STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key 143 | // 144 | // STB_TEXTEDIT_K_LEFT keyboard input to move cursor left 145 | // STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right 146 | // STB_TEXTEDIT_K_UP keyboard input to move cursor up 147 | // STB_TEXTEDIT_K_DOWN keyboard input to move cursor down 148 | // STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME 149 | // STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END 150 | // STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME 151 | // STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END 152 | // STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor 153 | // STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor 154 | // STB_TEXTEDIT_K_UNDO keyboard input to perform undo 155 | // STB_TEXTEDIT_K_REDO keyboard input to perform redo 156 | // 157 | // Optional: 158 | // STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode 159 | // STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'), 160 | // required for default WORDLEFT/WORDRIGHT handlers 161 | // STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to 162 | // STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to 163 | // STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT 164 | // STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT 165 | // STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line 166 | // STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line 167 | // STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text 168 | // STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text 169 | // 170 | // Todo: 171 | // STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page 172 | // STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page 173 | // 174 | // Keyboard input must be encoded as a single integer value; e.g. a character code 175 | // and some bitflags that represent shift states. to simplify the interface, SHIFT must 176 | // be a bitflag, so we can test the shifted state of cursor movements to allow selection, 177 | // i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow. 178 | // 179 | // You can encode other things, such as CONTROL or ALT, in additional bits, and 180 | // then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example, 181 | // my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN 182 | // bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit, 183 | // and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the 184 | // API below. The control keys will only match WM_KEYDOWN events because of the 185 | // keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN 186 | // bit so it only decodes WM_CHAR events. 187 | // 188 | // STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed 189 | // row of characters assuming they start on the i'th character--the width and 190 | // the height and the number of characters consumed. This allows this library 191 | // to traverse the entire layout incrementally. You need to compute word-wrapping 192 | // here. 193 | // 194 | // Each textfield keeps its own insert mode state, which is not how normal 195 | // applications work. To keep an app-wide insert mode, update/copy the 196 | // "insert_mode" field of STB_TexteditState before/after calling API functions. 197 | // 198 | // API 199 | // 200 | // void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) 201 | // 202 | // void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) 203 | // void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) 204 | // int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 205 | // int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) 206 | // void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) 207 | // 208 | // Each of these functions potentially updates the string and updates the 209 | // state. 210 | // 211 | // initialize_state: 212 | // set the textedit state to a known good default state when initially 213 | // constructing the textedit. 214 | // 215 | // click: 216 | // call this with the mouse x,y on a mouse down; it will update the cursor 217 | // and reset the selection start/end to the cursor point. the x,y must 218 | // be relative to the text widget, with (0,0) being the top left. 219 | // 220 | // drag: 221 | // call this with the mouse x,y on a mouse drag/up; it will update the 222 | // cursor and the selection end point 223 | // 224 | // cut: 225 | // call this to delete the current selection; returns true if there was 226 | // one. you should FIRST copy the current selection to the system paste buffer. 227 | // (To copy, just copy the current selection out of the string yourself.) 228 | // 229 | // paste: 230 | // call this to paste text at the current cursor point or over the current 231 | // selection if there is one. 232 | // 233 | // key: 234 | // call this for keyboard inputs sent to the textfield. you can use it 235 | // for "key down" events or for "translated" key events. if you need to 236 | // do both (as in Win32), or distinguish Unicode characters from control 237 | // inputs, set a high bit to distinguish the two; then you can define the 238 | // various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit 239 | // set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is 240 | // clear. 241 | // 242 | // When rendering, you can read the cursor position and selection state from 243 | // the STB_TexteditState. 244 | // 245 | // 246 | // Notes: 247 | // 248 | // This is designed to be usable in IMGUI, so it allows for the possibility of 249 | // running in an IMGUI that has NOT cached the multi-line layout. For this 250 | // reason, it provides an interface that is compatible with computing the 251 | // layout incrementally--we try to make sure we make as few passes through 252 | // as possible. (For example, to locate the mouse pointer in the text, we 253 | // could define functions that return the X and Y positions of characters 254 | // and binary search Y and then X, but if we're doing dynamic layout this 255 | // will run the layout algorithm many times, so instead we manually search 256 | // forward in one pass. Similar logic applies to e.g. up-arrow and 257 | // down-arrow movement.) 258 | // 259 | // If it's run in a widget that *has* cached the layout, then this is less 260 | // efficient, but it's not horrible on modern computers. But you wouldn't 261 | // want to edit million-line files with it. 262 | 263 | 264 | //////////////////////////////////////////////////////////////////////////// 265 | //////////////////////////////////////////////////////////////////////////// 266 | //// 267 | //// Header-file mode 268 | //// 269 | //// 270 | 271 | #ifndef INCLUDE_STB_TEXTEDIT_H 272 | #define INCLUDE_STB_TEXTEDIT_H 273 | 274 | //////////////////////////////////////////////////////////////////////// 275 | // 276 | // STB_TexteditState 277 | // 278 | // Definition of STB_TexteditState which you should store 279 | // per-textfield; it includes cursor position, selection state, 280 | // and undo state. 281 | // 282 | 283 | #ifndef STB_TEXTEDIT_UNDOSTATECOUNT 284 | #define STB_TEXTEDIT_UNDOSTATECOUNT 99 285 | #endif 286 | #ifndef STB_TEXTEDIT_UNDOCHARCOUNT 287 | #define STB_TEXTEDIT_UNDOCHARCOUNT 999 288 | #endif 289 | #ifndef STB_TEXTEDIT_CHARTYPE 290 | #define STB_TEXTEDIT_CHARTYPE int 291 | #endif 292 | #ifndef STB_TEXTEDIT_POSITIONTYPE 293 | #define STB_TEXTEDIT_POSITIONTYPE int 294 | #endif 295 | 296 | typedef struct 297 | { 298 | // private data 299 | STB_TEXTEDIT_POSITIONTYPE where; 300 | short insert_length; 301 | short delete_length; 302 | short char_storage; 303 | } StbUndoRecord; 304 | 305 | typedef struct 306 | { 307 | // private data 308 | StbUndoRecord undo_rec[STB_TEXTEDIT_UNDOSTATECOUNT]; 309 | STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; 310 | short undo_point, redo_point; 311 | short undo_char_point, redo_char_point; 312 | } StbUndoState; 313 | 314 | typedef struct 315 | { 316 | ///////////////////// 317 | // 318 | // public data 319 | // 320 | 321 | int cursor; 322 | // position of the text cursor within the string 323 | 324 | int select_start; // selection start point 325 | int select_end; 326 | // selection start and end point in characters; if equal, no selection. 327 | // note that start may be less than or greater than end (e.g. when 328 | // dragging the mouse, start is where the initial click was, and you 329 | // can drag in either direction) 330 | 331 | unsigned char insert_mode; 332 | // each textfield keeps its own insert mode state. to keep an app-wide 333 | // insert mode, copy this value in/out of the app state 334 | 335 | ///////////////////// 336 | // 337 | // private data 338 | // 339 | unsigned char cursor_at_end_of_line; // not implemented yet 340 | unsigned char initialized; 341 | unsigned char has_preferred_x; 342 | unsigned char single_line; 343 | unsigned char padding1, padding2, padding3; 344 | float preferred_x; // this determines where the cursor up/down tries to seek to along x 345 | StbUndoState undostate; 346 | } STB_TexteditState; 347 | 348 | 349 | //////////////////////////////////////////////////////////////////////// 350 | // 351 | // StbTexteditRow 352 | // 353 | // Result of layout query, used by stb_textedit to determine where 354 | // the text in each row is. 355 | 356 | // result of layout query 357 | typedef struct 358 | { 359 | float x0, x1; // starting x location, end x location (allows for align=right, etc) 360 | float baseline_y_delta; // position of baseline relative to previous row's baseline 361 | float ymin, ymax; // height of row above and below baseline 362 | int num_chars; 363 | } StbTexteditRow; 364 | #endif //INCLUDE_STB_TEXTEDIT_H 365 | 366 | 367 | //////////////////////////////////////////////////////////////////////////// 368 | //////////////////////////////////////////////////////////////////////////// 369 | //// 370 | //// Implementation mode 371 | //// 372 | //// 373 | 374 | 375 | // implementation isn't include-guarded, since it might have indirectly 376 | // included just the "header" portion 377 | #ifdef STB_TEXTEDIT_IMPLEMENTATION 378 | 379 | #ifndef STB_TEXTEDIT_memmove 380 | #include 381 | #define STB_TEXTEDIT_memmove memmove 382 | #endif 383 | 384 | 385 | ///////////////////////////////////////////////////////////////////////////// 386 | // 387 | // Mouse input handling 388 | // 389 | 390 | // traverse the layout to locate the nearest character to a display position 391 | static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y) 392 | { 393 | StbTexteditRow r; 394 | int n = STB_TEXTEDIT_STRINGLEN(str); 395 | float base_y = 0, prev_x; 396 | int i = 0, k; 397 | 398 | r.x0 = r.x1 = 0; 399 | r.ymin = r.ymax = 0; 400 | r.num_chars = 0; 401 | 402 | // search rows to find one that straddles 'y' 403 | while (i < n) { 404 | STB_TEXTEDIT_LAYOUTROW(&r, str, i); 405 | if (r.num_chars <= 0) 406 | return n; 407 | 408 | if (i == 0 && y < base_y + r.ymin) 409 | return 0; 410 | 411 | if (y < base_y + r.ymax) 412 | break; 413 | 414 | i += r.num_chars; 415 | base_y += r.baseline_y_delta; 416 | } 417 | 418 | // below all text, return 'after' last character 419 | if (i >= n) 420 | return n; 421 | 422 | // check if it's before the beginning of the line 423 | if (x < r.x0) 424 | return i; 425 | 426 | // check if it's before the end of the line 427 | if (x < r.x1) { 428 | // search characters in row for one that straddles 'x' 429 | prev_x = r.x0; 430 | for (k = 0; k < r.num_chars; ++k) { 431 | float w = STB_TEXTEDIT_GETWIDTH(str, i, k); 432 | if (x < prev_x + w) { 433 | if (x < prev_x + w / 2) 434 | return k + i; 435 | else 436 | return k + i + 1; 437 | } 438 | prev_x += w; 439 | } 440 | // shouldn't happen, but if it does, fall through to end-of-line case 441 | } 442 | 443 | // if the last character is a newline, return that. otherwise return 'after' the last character 444 | if (STB_TEXTEDIT_GETCHAR(str, i + r.num_chars - 1) == STB_TEXTEDIT_NEWLINE) 445 | return i + r.num_chars - 1; 446 | else 447 | return i + r.num_chars; 448 | } 449 | 450 | // API click: on mouse down, move the cursor to the clicked location, and reset the selection 451 | static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) 452 | { 453 | state->cursor = stb_text_locate_coord(str, x, y); 454 | state->select_start = state->cursor; 455 | state->select_end = state->cursor; 456 | state->has_preferred_x = 0; 457 | } 458 | 459 | // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location 460 | static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) 461 | { 462 | int p = stb_text_locate_coord(str, x, y); 463 | if (state->select_start == state->select_end) 464 | state->select_start = state->cursor; 465 | state->cursor = state->select_end = p; 466 | } 467 | 468 | ///////////////////////////////////////////////////////////////////////////// 469 | // 470 | // Keyboard input handling 471 | // 472 | 473 | // forward declarations 474 | static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); 475 | static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state); 476 | static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); 477 | static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); 478 | static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); 479 | 480 | typedef struct 481 | { 482 | float x, y; // position of n'th character 483 | float height; // height of line 484 | int first_char, length; // first char of row, and length 485 | int prev_first; // first char of previous row 486 | } StbFindState; 487 | 488 | // find the x/y location of a character, and remember info about the previous row in 489 | // case we get a move-up event (for page up, we'll have to rescan) 490 | static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line) 491 | { 492 | StbTexteditRow r; 493 | int prev_start = 0; 494 | int z = STB_TEXTEDIT_STRINGLEN(str); 495 | int i = 0, first; 496 | 497 | if (n == z) { 498 | // if it's at the end, then find the last line -- simpler than trying to 499 | // explicitly handle this case in the regular code 500 | if (single_line) { 501 | STB_TEXTEDIT_LAYOUTROW(&r, str, 0); 502 | find->y = 0; 503 | find->first_char = 0; 504 | find->length = z; 505 | find->height = r.ymax - r.ymin; 506 | find->x = r.x1; 507 | } 508 | else { 509 | find->y = 0; 510 | find->x = 0; 511 | find->height = 1; 512 | while (i < z) { 513 | STB_TEXTEDIT_LAYOUTROW(&r, str, i); 514 | prev_start = i; 515 | i += r.num_chars; 516 | } 517 | find->first_char = i; 518 | find->length = 0; 519 | find->prev_first = prev_start; 520 | } 521 | return; 522 | } 523 | 524 | // search rows to find the one that straddles character n 525 | find->y = 0; 526 | 527 | for (;;) { 528 | STB_TEXTEDIT_LAYOUTROW(&r, str, i); 529 | if (n < i + r.num_chars) 530 | break; 531 | prev_start = i; 532 | i += r.num_chars; 533 | find->y += r.baseline_y_delta; 534 | } 535 | 536 | find->first_char = first = i; 537 | find->length = r.num_chars; 538 | find->height = r.ymax - r.ymin; 539 | find->prev_first = prev_start; 540 | 541 | // now scan to find xpos 542 | find->x = r.x0; 543 | i = 0; 544 | for (i = 0; first + i < n; ++i) 545 | find->x += STB_TEXTEDIT_GETWIDTH(str, first, i); 546 | } 547 | 548 | #define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) 549 | 550 | // make the selection/cursor state valid if client altered the string 551 | static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 552 | { 553 | int n = STB_TEXTEDIT_STRINGLEN(str); 554 | if (STB_TEXT_HAS_SELECTION(state)) { 555 | if (state->select_start > n) state->select_start = n; 556 | if (state->select_end > n) state->select_end = n; 557 | // if clamping forced them to be equal, move the cursor to match 558 | if (state->select_start == state->select_end) 559 | state->cursor = state->select_start; 560 | } 561 | if (state->cursor > n) state->cursor = n; 562 | } 563 | 564 | // delete characters while updating undo 565 | static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) 566 | { 567 | stb_text_makeundo_delete(str, state, where, len); 568 | STB_TEXTEDIT_DELETECHARS(str, where, len); 569 | state->has_preferred_x = 0; 570 | } 571 | 572 | // delete the section 573 | static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 574 | { 575 | stb_textedit_clamp(str, state); 576 | if (STB_TEXT_HAS_SELECTION(state)) { 577 | if (state->select_start < state->select_end) { 578 | stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start); 579 | state->select_end = state->cursor = state->select_start; 580 | } 581 | else { 582 | stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end); 583 | state->select_start = state->cursor = state->select_end; 584 | } 585 | state->has_preferred_x = 0; 586 | } 587 | } 588 | 589 | // canoncialize the selection so start <= end 590 | static void stb_textedit_sortselection(STB_TexteditState *state) 591 | { 592 | if (state->select_end < state->select_start) { 593 | int temp = state->select_end; 594 | state->select_end = state->select_start; 595 | state->select_start = temp; 596 | } 597 | } 598 | 599 | // move cursor to first character of selection 600 | static void stb_textedit_move_to_first(STB_TexteditState *state) 601 | { 602 | if (STB_TEXT_HAS_SELECTION(state)) { 603 | stb_textedit_sortselection(state); 604 | state->cursor = state->select_start; 605 | state->select_end = state->select_start; 606 | state->has_preferred_x = 0; 607 | } 608 | } 609 | 610 | // move cursor to last character of selection 611 | static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 612 | { 613 | if (STB_TEXT_HAS_SELECTION(state)) { 614 | stb_textedit_sortselection(state); 615 | stb_textedit_clamp(str, state); 616 | state->cursor = state->select_end; 617 | state->select_start = state->select_end; 618 | state->has_preferred_x = 0; 619 | } 620 | } 621 | 622 | #ifdef STB_TEXTEDIT_IS_SPACE 623 | static int is_word_boundary(STB_TEXTEDIT_STRING *str, int idx) 624 | { 625 | return idx > 0 ? (STB_TEXTEDIT_IS_SPACE(STB_TEXTEDIT_GETCHAR(str, idx - 1)) && !STB_TEXTEDIT_IS_SPACE(STB_TEXTEDIT_GETCHAR(str, idx))) : 1; 626 | } 627 | 628 | #ifndef STB_TEXTEDIT_MOVEWORDLEFT 629 | static int stb_textedit_move_to_word_previous(STB_TEXTEDIT_STRING *str, int c) 630 | { 631 | --c; // always move at least one character 632 | while (c >= 0 && !is_word_boundary(str, c)) 633 | --c; 634 | 635 | if (c < 0) 636 | c = 0; 637 | 638 | return c; 639 | } 640 | #define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous 641 | #endif 642 | 643 | #ifndef STB_TEXTEDIT_MOVEWORDRIGHT 644 | static int stb_textedit_move_to_word_next(STB_TEXTEDIT_STRING *str, int c) 645 | { 646 | const int len = STB_TEXTEDIT_STRINGLEN(str); 647 | ++c; // always move at least one character 648 | while (c < len && !is_word_boundary(str, c)) 649 | ++c; 650 | 651 | if (c > len) 652 | c = len; 653 | 654 | return c; 655 | } 656 | #define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next 657 | #endif 658 | 659 | #endif 660 | 661 | // update selection and cursor to match each other 662 | static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state) 663 | { 664 | if (!STB_TEXT_HAS_SELECTION(state)) 665 | state->select_start = state->select_end = state->cursor; 666 | else 667 | state->cursor = state->select_end; 668 | } 669 | 670 | // API cut: delete selection 671 | static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 672 | { 673 | if (STB_TEXT_HAS_SELECTION(state)) { 674 | stb_textedit_delete_selection(str, state); // implicity clamps 675 | state->has_preferred_x = 0; 676 | return 1; 677 | } 678 | return 0; 679 | } 680 | 681 | // API paste: replace existing selection with passed-in text 682 | static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) 683 | { 684 | STB_TEXTEDIT_CHARTYPE *text = (STB_TEXTEDIT_CHARTYPE *)ctext; 685 | // if there's a selection, the paste should delete it 686 | stb_textedit_clamp(str, state); 687 | stb_textedit_delete_selection(str, state); 688 | // try to insert the characters 689 | if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) { 690 | stb_text_makeundo_insert(state, state->cursor, len); 691 | state->cursor += len; 692 | state->has_preferred_x = 0; 693 | return 1; 694 | } 695 | // remove the undo since we didn't actually insert the characters 696 | if (state->undostate.undo_point) 697 | --state->undostate.undo_point; 698 | return 0; 699 | } 700 | 701 | // API key: process a keyboard input 702 | static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int key) 703 | { 704 | retry: 705 | switch (key) { 706 | default: { 707 | int c = STB_TEXTEDIT_KEYTOTEXT(key); 708 | if (c > 0) { 709 | STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE)c; 710 | 711 | // can't add newline in single-line mode 712 | if (c == '\n' && state->single_line) 713 | break; 714 | 715 | if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { 716 | stb_text_makeundo_replace(str, state, state->cursor, 1, 1); 717 | STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); 718 | if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { 719 | ++state->cursor; 720 | state->has_preferred_x = 0; 721 | } 722 | } 723 | else { 724 | stb_textedit_delete_selection(str, state); // implicity clamps 725 | if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { 726 | stb_text_makeundo_insert(state, state->cursor, 1); 727 | ++state->cursor; 728 | state->has_preferred_x = 0; 729 | } 730 | } 731 | } 732 | break; 733 | } 734 | 735 | #ifdef STB_TEXTEDIT_K_INSERT 736 | case STB_TEXTEDIT_K_INSERT: 737 | state->insert_mode = !state->insert_mode; 738 | break; 739 | #endif 740 | 741 | case STB_TEXTEDIT_K_UNDO: 742 | stb_text_undo(str, state); 743 | state->has_preferred_x = 0; 744 | break; 745 | 746 | case STB_TEXTEDIT_K_REDO: 747 | stb_text_redo(str, state); 748 | state->has_preferred_x = 0; 749 | break; 750 | 751 | case STB_TEXTEDIT_K_LEFT: 752 | // if currently there's a selection, move cursor to start of selection 753 | if (STB_TEXT_HAS_SELECTION(state)) 754 | stb_textedit_move_to_first(state); 755 | else 756 | if (state->cursor > 0) 757 | --state->cursor; 758 | state->has_preferred_x = 0; 759 | break; 760 | 761 | case STB_TEXTEDIT_K_RIGHT: 762 | // if currently there's a selection, move cursor to end of selection 763 | if (STB_TEXT_HAS_SELECTION(state)) 764 | stb_textedit_move_to_last(str, state); 765 | else 766 | ++state->cursor; 767 | stb_textedit_clamp(str, state); 768 | state->has_preferred_x = 0; 769 | break; 770 | 771 | case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: 772 | stb_textedit_clamp(str, state); 773 | stb_textedit_prep_selection_at_cursor(state); 774 | // move selection left 775 | if (state->select_end > 0) 776 | --state->select_end; 777 | state->cursor = state->select_end; 778 | state->has_preferred_x = 0; 779 | break; 780 | 781 | #ifdef STB_TEXTEDIT_MOVEWORDLEFT 782 | case STB_TEXTEDIT_K_WORDLEFT: 783 | if (STB_TEXT_HAS_SELECTION(state)) 784 | stb_textedit_move_to_first(state); 785 | else { 786 | state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); 787 | stb_textedit_clamp(str, state); 788 | } 789 | break; 790 | 791 | case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: 792 | if (!STB_TEXT_HAS_SELECTION(state)) 793 | stb_textedit_prep_selection_at_cursor(state); 794 | 795 | state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); 796 | state->select_end = state->cursor; 797 | 798 | stb_textedit_clamp(str, state); 799 | break; 800 | #endif 801 | 802 | #ifdef STB_TEXTEDIT_MOVEWORDRIGHT 803 | case STB_TEXTEDIT_K_WORDRIGHT: 804 | if (STB_TEXT_HAS_SELECTION(state)) 805 | stb_textedit_move_to_last(str, state); 806 | else { 807 | state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); 808 | stb_textedit_clamp(str, state); 809 | } 810 | break; 811 | 812 | case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: 813 | if (!STB_TEXT_HAS_SELECTION(state)) 814 | stb_textedit_prep_selection_at_cursor(state); 815 | 816 | state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); 817 | state->select_end = state->cursor; 818 | 819 | stb_textedit_clamp(str, state); 820 | break; 821 | #endif 822 | 823 | case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: 824 | stb_textedit_prep_selection_at_cursor(state); 825 | // move selection right 826 | ++state->select_end; 827 | stb_textedit_clamp(str, state); 828 | state->cursor = state->select_end; 829 | state->has_preferred_x = 0; 830 | break; 831 | 832 | case STB_TEXTEDIT_K_DOWN: 833 | case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: { 834 | StbFindState find; 835 | StbTexteditRow row; 836 | int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; 837 | 838 | if (state->single_line) { 839 | // on windows, up&down in single-line behave like left&right 840 | key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); 841 | goto retry; 842 | } 843 | 844 | if (sel) 845 | stb_textedit_prep_selection_at_cursor(state); 846 | else if (STB_TEXT_HAS_SELECTION(state)) 847 | stb_textedit_move_to_last(str, state); 848 | 849 | // compute current position of cursor point 850 | stb_textedit_clamp(str, state); 851 | stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); 852 | 853 | // now find character position down a row 854 | if (find.length) { 855 | float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 856 | float x; 857 | int start = find.first_char + find.length; 858 | state->cursor = start; 859 | STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); 860 | x = row.x0; 861 | for (i = 0; i < row.num_chars; ++i) { 862 | float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); 863 | #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE 864 | if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) 865 | break; 866 | #endif 867 | x += dx; 868 | if (x > goal_x) 869 | break; 870 | ++state->cursor; 871 | } 872 | stb_textedit_clamp(str, state); 873 | 874 | state->has_preferred_x = 1; 875 | state->preferred_x = goal_x; 876 | 877 | if (sel) 878 | state->select_end = state->cursor; 879 | } 880 | break; 881 | } 882 | 883 | case STB_TEXTEDIT_K_UP: 884 | case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: { 885 | StbFindState find; 886 | StbTexteditRow row; 887 | int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; 888 | 889 | if (state->single_line) { 890 | // on windows, up&down become left&right 891 | key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); 892 | goto retry; 893 | } 894 | 895 | if (sel) 896 | stb_textedit_prep_selection_at_cursor(state); 897 | else if (STB_TEXT_HAS_SELECTION(state)) 898 | stb_textedit_move_to_first(state); 899 | 900 | // compute current position of cursor point 901 | stb_textedit_clamp(str, state); 902 | stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); 903 | 904 | // can only go up if there's a previous row 905 | if (find.prev_first != find.first_char) { 906 | // now find character position up a row 907 | float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 908 | float x; 909 | state->cursor = find.prev_first; 910 | STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); 911 | x = row.x0; 912 | for (i = 0; i < row.num_chars; ++i) { 913 | float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); 914 | #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE 915 | if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE) 916 | break; 917 | #endif 918 | x += dx; 919 | if (x > goal_x) 920 | break; 921 | ++state->cursor; 922 | } 923 | stb_textedit_clamp(str, state); 924 | 925 | state->has_preferred_x = 1; 926 | state->preferred_x = goal_x; 927 | 928 | if (sel) 929 | state->select_end = state->cursor; 930 | } 931 | break; 932 | } 933 | 934 | case STB_TEXTEDIT_K_DELETE: 935 | case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: 936 | if (STB_TEXT_HAS_SELECTION(state)) 937 | stb_textedit_delete_selection(str, state); 938 | else { 939 | int n = STB_TEXTEDIT_STRINGLEN(str); 940 | if (state->cursor < n) 941 | stb_textedit_delete(str, state, state->cursor, 1); 942 | } 943 | state->has_preferred_x = 0; 944 | break; 945 | 946 | case STB_TEXTEDIT_K_BACKSPACE: 947 | case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: 948 | if (STB_TEXT_HAS_SELECTION(state)) 949 | stb_textedit_delete_selection(str, state); 950 | else { 951 | stb_textedit_clamp(str, state); 952 | if (state->cursor > 0) { 953 | stb_textedit_delete(str, state, state->cursor - 1, 1); 954 | --state->cursor; 955 | } 956 | } 957 | state->has_preferred_x = 0; 958 | break; 959 | 960 | #ifdef STB_TEXTEDIT_K_TEXTSTART2 961 | case STB_TEXTEDIT_K_TEXTSTART2: 962 | #endif 963 | case STB_TEXTEDIT_K_TEXTSTART: 964 | state->cursor = state->select_start = state->select_end = 0; 965 | state->has_preferred_x = 0; 966 | break; 967 | 968 | #ifdef STB_TEXTEDIT_K_TEXTEND2 969 | case STB_TEXTEDIT_K_TEXTEND2: 970 | #endif 971 | case STB_TEXTEDIT_K_TEXTEND: 972 | state->cursor = STB_TEXTEDIT_STRINGLEN(str); 973 | state->select_start = state->select_end = 0; 974 | state->has_preferred_x = 0; 975 | break; 976 | 977 | #ifdef STB_TEXTEDIT_K_TEXTSTART2 978 | case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: 979 | #endif 980 | case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: 981 | stb_textedit_prep_selection_at_cursor(state); 982 | state->cursor = state->select_end = 0; 983 | state->has_preferred_x = 0; 984 | break; 985 | 986 | #ifdef STB_TEXTEDIT_K_TEXTEND2 987 | case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: 988 | #endif 989 | case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: 990 | stb_textedit_prep_selection_at_cursor(state); 991 | state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); 992 | state->has_preferred_x = 0; 993 | break; 994 | 995 | 996 | #ifdef STB_TEXTEDIT_K_LINESTART2 997 | case STB_TEXTEDIT_K_LINESTART2: 998 | #endif 999 | case STB_TEXTEDIT_K_LINESTART: 1000 | stb_textedit_clamp(str, state); 1001 | stb_textedit_move_to_first(state); 1002 | if (state->single_line) 1003 | state->cursor = 0; 1004 | else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor - 1) != STB_TEXTEDIT_NEWLINE) 1005 | --state->cursor; 1006 | state->has_preferred_x = 0; 1007 | break; 1008 | 1009 | #ifdef STB_TEXTEDIT_K_LINEEND2 1010 | case STB_TEXTEDIT_K_LINEEND2: 1011 | #endif 1012 | case STB_TEXTEDIT_K_LINEEND: { 1013 | int n = STB_TEXTEDIT_STRINGLEN(str); 1014 | stb_textedit_clamp(str, state); 1015 | stb_textedit_move_to_first(state); 1016 | if (state->single_line) 1017 | state->cursor = n; 1018 | else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) 1019 | ++state->cursor; 1020 | state->has_preferred_x = 0; 1021 | break; 1022 | } 1023 | 1024 | #ifdef STB_TEXTEDIT_K_LINESTART2 1025 | case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: 1026 | #endif 1027 | case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: 1028 | stb_textedit_clamp(str, state); 1029 | stb_textedit_prep_selection_at_cursor(state); 1030 | if (state->single_line) 1031 | state->cursor = 0; 1032 | else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor - 1) != STB_TEXTEDIT_NEWLINE) 1033 | --state->cursor; 1034 | state->select_end = state->cursor; 1035 | state->has_preferred_x = 0; 1036 | break; 1037 | 1038 | #ifdef STB_TEXTEDIT_K_LINEEND2 1039 | case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: 1040 | #endif 1041 | case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: { 1042 | int n = STB_TEXTEDIT_STRINGLEN(str); 1043 | stb_textedit_clamp(str, state); 1044 | stb_textedit_prep_selection_at_cursor(state); 1045 | if (state->single_line) 1046 | state->cursor = n; 1047 | else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) 1048 | ++state->cursor; 1049 | state->select_end = state->cursor; 1050 | state->has_preferred_x = 0; 1051 | break; 1052 | } 1053 | 1054 | // @TODO: 1055 | // STB_TEXTEDIT_K_PGUP - move cursor up a page 1056 | // STB_TEXTEDIT_K_PGDOWN - move cursor down a page 1057 | } 1058 | } 1059 | 1060 | ///////////////////////////////////////////////////////////////////////////// 1061 | // 1062 | // Undo processing 1063 | // 1064 | // @OPTIMIZE: the undo/redo buffer should be circular 1065 | 1066 | static void stb_textedit_flush_redo(StbUndoState *state) 1067 | { 1068 | state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; 1069 | state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; 1070 | } 1071 | 1072 | // discard the oldest entry in the undo list 1073 | static void stb_textedit_discard_undo(StbUndoState *state) 1074 | { 1075 | if (state->undo_point > 0) { 1076 | // if the 0th undo state has characters, clean those up 1077 | if (state->undo_rec[0].char_storage >= 0) { 1078 | int n = state->undo_rec[0].insert_length, i; 1079 | // delete n characters from all other records 1080 | state->undo_char_point = state->undo_char_point - (short)n; // vsnet05 1081 | STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t)((size_t)state->undo_char_point * sizeof(STB_TEXTEDIT_CHARTYPE))); 1082 | for (i = 0; i < state->undo_point; ++i) 1083 | if (state->undo_rec[i].char_storage >= 0) 1084 | state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short)n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it 1085 | } 1086 | --state->undo_point; 1087 | STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec + 1, (size_t)((size_t)state->undo_point * sizeof(state->undo_rec[0]))); 1088 | } 1089 | } 1090 | 1091 | // discard the oldest entry in the redo list--it's bad if this 1092 | // ever happens, but because undo & redo have to store the actual 1093 | // characters in different cases, the redo character buffer can 1094 | // fill up even though the undo buffer didn't 1095 | static void stb_textedit_discard_redo(StbUndoState *state) 1096 | { 1097 | int k = STB_TEXTEDIT_UNDOSTATECOUNT - 1; 1098 | 1099 | if (state->redo_point <= k) { 1100 | // if the k'th undo state has characters, clean those up 1101 | if (state->undo_rec[k].char_storage >= 0) { 1102 | int n = state->undo_rec[k].insert_length, i; 1103 | // delete n characters from all other records 1104 | state->redo_char_point = state->redo_char_point + (short)n; // vsnet05 1105 | STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point - n, (size_t)((size_t)(STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point) * sizeof(STB_TEXTEDIT_CHARTYPE))); 1106 | for (i = state->redo_point; i < k; ++i) 1107 | if (state->undo_rec[i].char_storage >= 0) 1108 | state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short)n; // vsnet05 1109 | } 1110 | STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point, state->undo_rec + state->redo_point - 1, (size_t)((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point) * sizeof(state->undo_rec[0]))); 1111 | ++state->redo_point; 1112 | } 1113 | } 1114 | 1115 | static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars) 1116 | { 1117 | // any time we create a new undo record, we discard redo 1118 | stb_textedit_flush_redo(state); 1119 | 1120 | // if we have no free records, we have to make room, by sliding the 1121 | // existing records down 1122 | if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1123 | stb_textedit_discard_undo(state); 1124 | 1125 | // if the characters to store won't possibly fit in the buffer, we can't undo 1126 | if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) { 1127 | state->undo_point = 0; 1128 | state->undo_char_point = 0; 1129 | return NULL; 1130 | } 1131 | 1132 | // if we don't have enough free characters in the buffer, we have to make room 1133 | while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT) 1134 | stb_textedit_discard_undo(state); 1135 | 1136 | return &state->undo_rec[state->undo_point++]; 1137 | } 1138 | 1139 | static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) 1140 | { 1141 | StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); 1142 | if (r == NULL) 1143 | return NULL; 1144 | 1145 | r->where = pos; 1146 | r->insert_length = (short)insert_len; 1147 | r->delete_length = (short)delete_len; 1148 | 1149 | if (insert_len == 0) { 1150 | r->char_storage = -1; 1151 | return NULL; 1152 | } 1153 | else { 1154 | r->char_storage = state->undo_char_point; 1155 | state->undo_char_point = state->undo_char_point + (short)insert_len; 1156 | return &state->undo_char[r->char_storage]; 1157 | } 1158 | } 1159 | 1160 | static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 1161 | { 1162 | StbUndoState *s = &state->undostate; 1163 | StbUndoRecord u, *r; 1164 | if (s->undo_point == 0) 1165 | return; 1166 | 1167 | // we need to do two things: apply the undo record, and create a redo record 1168 | u = s->undo_rec[s->undo_point - 1]; 1169 | r = &s->undo_rec[s->redo_point - 1]; 1170 | r->char_storage = -1; 1171 | 1172 | r->insert_length = u.delete_length; 1173 | r->delete_length = u.insert_length; 1174 | r->where = u.where; 1175 | 1176 | if (u.delete_length) { 1177 | // if the undo record says to delete characters, then the redo record will 1178 | // need to re-insert the characters that get deleted, so we need to store 1179 | // them. 1180 | 1181 | // there are three cases: 1182 | // there's enough room to store the characters 1183 | // characters stored for *redoing* don't leave room for redo 1184 | // characters stored for *undoing* don't leave room for redo 1185 | // if the last is true, we have to bail 1186 | 1187 | if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) { 1188 | // the undo records take up too much character space; there's no space to store the redo characters 1189 | r->insert_length = 0; 1190 | } 1191 | else { 1192 | int i; 1193 | 1194 | // there's definitely room to store the characters eventually 1195 | while (s->undo_char_point + u.delete_length > s->redo_char_point) { 1196 | // there's currently not enough room, so discard a redo record 1197 | stb_textedit_discard_redo(s); 1198 | // should never happen: 1199 | if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1200 | return; 1201 | } 1202 | r = &s->undo_rec[s->redo_point - 1]; 1203 | 1204 | r->char_storage = s->redo_char_point - u.delete_length; 1205 | s->redo_char_point = s->redo_char_point - (short)u.delete_length; 1206 | 1207 | // now save the characters 1208 | for (i = 0; i < u.delete_length; ++i) 1209 | s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); 1210 | } 1211 | 1212 | // now we can carry out the deletion 1213 | STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); 1214 | } 1215 | 1216 | // check type of recorded action: 1217 | if (u.insert_length) { 1218 | // easy case: was a deletion, so we need to insert n characters 1219 | STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); 1220 | s->undo_char_point -= u.insert_length; 1221 | } 1222 | 1223 | state->cursor = u.where + u.insert_length; 1224 | 1225 | s->undo_point--; 1226 | s->redo_point--; 1227 | } 1228 | 1229 | static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) 1230 | { 1231 | StbUndoState *s = &state->undostate; 1232 | StbUndoRecord *u, r; 1233 | if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT) 1234 | return; 1235 | 1236 | // we need to do two things: apply the redo record, and create an undo record 1237 | u = &s->undo_rec[s->undo_point]; 1238 | r = s->undo_rec[s->redo_point]; 1239 | 1240 | // we KNOW there must be room for the undo record, because the redo record 1241 | // was derived from an undo record 1242 | 1243 | u->delete_length = r.insert_length; 1244 | u->insert_length = r.delete_length; 1245 | u->where = r.where; 1246 | u->char_storage = -1; 1247 | 1248 | if (r.delete_length) { 1249 | // the redo record requires us to delete characters, so the undo record 1250 | // needs to store the characters 1251 | 1252 | if (s->undo_char_point + u->insert_length > s->redo_char_point) { 1253 | u->insert_length = 0; 1254 | u->delete_length = 0; 1255 | } 1256 | else { 1257 | int i; 1258 | u->char_storage = s->undo_char_point; 1259 | s->undo_char_point = s->undo_char_point + u->insert_length; 1260 | 1261 | // now save the characters 1262 | for (i = 0; i < u->insert_length; ++i) 1263 | s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); 1264 | } 1265 | 1266 | STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); 1267 | } 1268 | 1269 | if (r.insert_length) { 1270 | // easy case: need to insert n characters 1271 | STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); 1272 | s->redo_char_point += r.insert_length; 1273 | } 1274 | 1275 | state->cursor = r.where + r.insert_length; 1276 | 1277 | s->undo_point++; 1278 | s->redo_point++; 1279 | } 1280 | 1281 | static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length) 1282 | { 1283 | stb_text_createundo(&state->undostate, where, 0, length); 1284 | } 1285 | 1286 | static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) 1287 | { 1288 | int i; 1289 | STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); 1290 | if (p) { 1291 | for (i = 0; i < length; ++i) 1292 | p[i] = STB_TEXTEDIT_GETCHAR(str, where + i); 1293 | } 1294 | } 1295 | 1296 | static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) 1297 | { 1298 | int i; 1299 | STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); 1300 | if (p) { 1301 | for (i = 0; i < old_length; ++i) 1302 | p[i] = STB_TEXTEDIT_GETCHAR(str, where + i); 1303 | } 1304 | } 1305 | 1306 | // reset the state to default 1307 | static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line) 1308 | { 1309 | state->undostate.undo_point = 0; 1310 | state->undostate.undo_char_point = 0; 1311 | state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT; 1312 | state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT; 1313 | state->select_end = state->select_start = 0; 1314 | state->cursor = 0; 1315 | state->has_preferred_x = 0; 1316 | state->preferred_x = 0; 1317 | state->cursor_at_end_of_line = 0; 1318 | state->initialized = 1; 1319 | state->single_line = (unsigned char)is_single_line; 1320 | state->insert_mode = 0; 1321 | } 1322 | 1323 | // API initialize 1324 | static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) 1325 | { 1326 | stb_textedit_clear_state(state, is_single_line); 1327 | } 1328 | #endif//STB_TEXTEDIT_IMPLEMENTATION 1329 | --------------------------------------------------------------------------------