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