├── LICENSE
├── README.md
├── base.sln
├── base.vcxproj
├── base.vcxproj.filters
├── base.vcxproj.user
├── fonts.hpp
├── image.png
├── imgui
├── imconfig.h
├── imgui.cpp
├── imgui.h
├── imgui_demo.cpp
├── imgui_draw.cpp
├── imgui_impl_dx9.cpp
├── imgui_impl_dx9.h
├── imgui_impl_win32.cpp
├── imgui_impl_win32.h
├── imgui_internal.h
├── imgui_widgets.cpp
├── imstb_rectpack.h
├── imstb_textedit.h
└── imstb_truetype.h
├── imgui_external_base
├── base.sln
├── base.vcxproj
├── base.vcxproj.filters
├── base.vcxproj.user
├── fonts.hpp
├── imgui
│ ├── imconfig.h
│ ├── imgui.cpp
│ ├── imgui.h
│ ├── imgui_demo.cpp
│ ├── imgui_draw.cpp
│ ├── imgui_impl_dx9.cpp
│ ├── imgui_impl_dx9.h
│ ├── imgui_impl_win32.cpp
│ ├── imgui_impl_win32.h
│ ├── imgui_internal.h
│ ├── imgui_widgets.cpp
│ ├── imstb_rectpack.h
│ ├── imstb_textedit.h
│ └── imstb_truetype.h
├── menu.hpp
├── source.cpp
├── source.hpp
└── xorstr.hpp
├── includes.hpp
├── injector.hpp
├── menu.hpp
├── source.cpp
├── source.hpp
├── util.hpp
└── xorstr.hpp
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 xo1337
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # imgui-external-base
2 | 
3 |
4 | External Dear ImGui menu base. Tired of using trash source codes that are unreadable, unusable? I've just solved your problem. I've decided to create this external imgui menu base to fill the void where actual quality source codes meet reality. In here is nothing special, but just something to get you started with.
5 |
--------------------------------------------------------------------------------
/base.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.33328.57
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XO IMGUI EXTERNAL", "base.vcxproj", "{AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}"
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 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Debug|x64.ActiveCfg = Debug|x64
17 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Debug|x64.Build.0 = Debug|x64
18 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Debug|x86.ActiveCfg = Debug|Win32
19 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Debug|x86.Build.0 = Debug|Win32
20 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Release|x64.ActiveCfg = Release|x64
21 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Release|x64.Build.0 = Release|x64
22 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Release|x86.ActiveCfg = Release|Win32
23 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {95108900-D6DA-46A2-AC73-0B8E77EAA354}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/base.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {aeaa4cef-8d6d-4061-bcf1-c31cddcca231}
25 | LoaderBase
26 | 10.0
27 | base
28 |
29 |
30 |
31 | Application
32 | true
33 | v142
34 | Unicode
35 |
36 |
37 | Application
38 | false
39 | v142
40 | true
41 | Unicode
42 |
43 |
44 | Application
45 | true
46 | v142
47 | MultiByte
48 |
49 |
50 | Application
51 | false
52 | v142
53 | true
54 | MultiByte
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | true
76 |
77 |
78 | false
79 |
80 |
81 | true
82 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)/imgui;$(ProjectDir);$(IncludePath)
83 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;$(LibraryPath)
84 |
85 |
86 | false
87 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)/imgui;$(ProjectDir);$(IncludePath)
88 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;$(LibraryPath)
89 |
90 |
91 |
92 | Level3
93 | true
94 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
95 | true
96 |
97 |
98 | Console
99 | true
100 |
101 |
102 |
103 |
104 | Level3
105 | true
106 | true
107 | true
108 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
109 | true
110 |
111 |
112 | Console
113 | true
114 | true
115 | true
116 |
117 |
118 |
119 |
120 | Level3
121 | true
122 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
123 | true
124 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)/imgui
125 |
126 |
127 | Windows
128 | true
129 |
130 |
131 |
132 |
133 | TurnOffAllWarnings
134 | true
135 | true
136 | true
137 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
138 | true
139 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)/imgui
140 | stdcpp17
141 | MinSpace
142 | stdc17
143 |
144 |
145 | Windows
146 | true
147 | true
148 | false
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
--------------------------------------------------------------------------------
/base.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {39dbd3a4-bda5-4317-a3ef-50064f12ff10}
10 |
11 |
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files\imgui
18 |
19 |
20 | Source Files\imgui
21 |
22 |
23 | Source Files\imgui
24 |
25 |
26 | Source Files\imgui
27 |
28 |
29 | Source Files\imgui
30 |
31 |
32 | Source Files\imgui
33 |
34 |
35 |
36 |
37 | Source Files\imgui
38 |
39 |
40 | Source Files\imgui
41 |
42 |
43 | Source Files\imgui
44 |
45 |
46 | Source Files\imgui
47 |
48 |
49 | Source Files\imgui
50 |
51 |
52 | Source Files\imgui
53 |
54 |
55 | Source Files\imgui
56 |
57 |
58 | Source Files\imgui
59 |
60 |
61 | Source Files
62 |
63 |
64 | Source Files
65 |
66 |
67 | Source Files
68 |
69 |
70 | Source Files
71 |
72 |
73 | Source Files
74 |
75 |
76 | Source Files
77 |
78 |
79 | Source Files
80 |
81 |
82 |
--------------------------------------------------------------------------------
/base.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
--------------------------------------------------------------------------------
/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xo1337/imgui-external-base/619d07bcf5b70b744603960f48a085093c9fbc31/image.png
--------------------------------------------------------------------------------
/imgui/imconfig.h:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------------
2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI
3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
5 | //-----------------------------------------------------------------------------
6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
8 | //-----------------------------------------------------------------------------
9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
12 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
13 | //-----------------------------------------------------------------------------
14 |
15 | #pragma once
16 |
17 | //---- Define assertion handler. Defaults to calling assert().
18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
21 |
22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
23 | // Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
24 | //#define IMGUI_API __declspec( dllexport )
25 | //#define IMGUI_API __declspec( dllimport )
26 |
27 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
28 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
29 |
30 | //---- Disable all of Dear ImGui or don't implement standard windows.
31 | // It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
32 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
33 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
34 | //#define IMGUI_DISABLE_METRICS_WINDOW // Disable debug/metrics window: ShowMetricsWindow() will be empty.
35 |
36 | //---- Don't implement some functions to reduce linkage requirements.
37 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
38 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
39 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
40 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
41 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
42 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
43 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
44 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
45 |
46 | //---- Include imgui_user.h at the end of imgui.h as a convenience
47 | //#define IMGUI_INCLUDE_IMGUI_USER_H
48 |
49 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
50 | //#define IMGUI_USE_BGRA_PACKED_COLOR
51 |
52 | //---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
53 | //#define IMGUI_USE_WCHAR32
54 |
55 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
56 | // By default the embedded implementations are declared static and not available outside of imgui cpp files.
57 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
58 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
59 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
60 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
61 |
62 | //---- Unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined, use the much faster STB sprintf library implementation of vsnprintf instead of the one from the default C library.
63 | // Note that stb_sprintf.h is meant to be provided by the user and available in the include path at compile time. Also, the compatibility checks of the arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
64 | // #define IMGUI_USE_STB_SPRINTF
65 |
66 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
67 | // This will be inlined as part of ImVec2 and ImVec4 class declarations.
68 | /*
69 | #define IM_VEC2_CLASS_EXTRA \
70 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
71 | operator MyVec2() const { return MyVec2(x,y); }
72 |
73 | #define IM_VEC4_CLASS_EXTRA \
74 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
75 | operator MyVec4() const { return MyVec4(x,y,z,w); }
76 | */
77 |
78 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
79 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
80 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
81 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
82 | //#define ImDrawIdx unsigned int
83 |
84 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
85 | //struct ImDrawList;
86 | //struct ImDrawCmd;
87 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
88 | //#define ImDrawCallback MyImDrawCallback
89 |
90 | //---- Debug Tools: Macro to break in Debugger
91 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
92 | //#define IM_DEBUG_BREAK IM_ASSERT(0)
93 | //#define IM_DEBUG_BREAK __debugbreak()
94 |
95 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
96 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
97 | // This adds a small runtime cost which is why it is not enabled by default.
98 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
99 |
100 | //---- Debug Tools: Enable slower asserts
101 | //#define IMGUI_DEBUG_PARANOID
102 |
103 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
104 | /*
105 | namespace ImGui
106 | {
107 | void MyFunction(const char* name, const MyMatrix44& v);
108 | }
109 | */
110 |
--------------------------------------------------------------------------------
/imgui/imgui_impl_dx9.cpp:
--------------------------------------------------------------------------------
1 | // dear imgui: Renderer Backend for DirectX9
2 | // This needs to be used along with a Platform Backend (e.g. Win32)
3 |
4 | // Implemented features:
5 | // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
6 | // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
7 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
8 |
9 | // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs
12 |
13 | // CHANGELOG
14 | // (minor and older changes stripped away, please see git history for details)
15 | // 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
16 | // 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
17 | // 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
18 | // 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
19 | // 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
20 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
21 | // 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
22 | // 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
23 | // 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud.
24 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
25 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
26 |
27 | #include "imgui.h"
28 | #include "imgui_impl_dx9.h"
29 |
30 | // DirectX
31 | #include
32 | #define DIRECTINPUT_VERSION 0x0800
33 | #include
34 |
35 | // DirectX data
36 | static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
37 | static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
38 | static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
39 | static LPDIRECT3DTEXTURE9 g_FontTexture = NULL;
40 | static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
41 |
42 | struct CUSTOMVERTEX
43 | {
44 | float pos[3];
45 | D3DCOLOR col;
46 | float uv[2];
47 | };
48 | #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
49 |
50 | // Forward Declarations
51 | static void ImGui_ImplDX9_InitPlatformInterface();
52 | static void ImGui_ImplDX9_ShutdownPlatformInterface();
53 | static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows();
54 | static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
55 |
56 | static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
57 | {
58 | // Setup viewport
59 | D3DVIEWPORT9 vp;
60 | vp.X = vp.Y = 0;
61 | vp.Width = (DWORD)draw_data->DisplaySize.x;
62 | vp.Height = (DWORD)draw_data->DisplaySize.y;
63 | vp.MinZ = 0.0f;
64 | vp.MaxZ = 1.0f;
65 | g_pd3dDevice->SetViewport(&vp);
66 |
67 | // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
68 | g_pd3dDevice->SetPixelShader(NULL);
69 | g_pd3dDevice->SetVertexShader(NULL);
70 | g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
71 | g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
72 | g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
73 | g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
74 | g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
75 | g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
76 | g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
77 | g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
78 | g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
79 | g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
80 | g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
81 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
82 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
83 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
84 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
85 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
86 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
87 | g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
88 | g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
89 |
90 | // Setup orthographic projection matrix
91 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
92 | // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
93 | {
94 | float L = draw_data->DisplayPos.x + 0.5f;
95 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
96 | float T = draw_data->DisplayPos.y + 0.5f;
97 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
98 | D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
99 | D3DMATRIX mat_projection =
100 | { { {
101 | 2.0f/(R-L), 0.0f, 0.0f, 0.0f,
102 | 0.0f, 2.0f/(T-B), 0.0f, 0.0f,
103 | 0.0f, 0.0f, 0.5f, 0.0f,
104 | (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
105 | } } };
106 | g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
107 | g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
108 | g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
109 | }
110 | }
111 |
112 | // Render function.
113 | void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
114 | {
115 | // Avoid rendering when minimized
116 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
117 | return;
118 |
119 | // Create and grow buffers if needed
120 | if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
121 | {
122 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
123 | g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
124 | if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
125 | return;
126 | }
127 | if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
128 | {
129 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
130 | g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
131 | if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0)
132 | return;
133 | }
134 |
135 | // Backup the DX9 state
136 | IDirect3DStateBlock9* d3d9_state_block = NULL;
137 | if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
138 | return;
139 |
140 | // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
141 | D3DMATRIX last_world, last_view, last_projection;
142 | g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
143 | g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
144 | g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
145 |
146 | // Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
147 | // FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and
148 | // 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
149 | // 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
150 | CUSTOMVERTEX* vtx_dst;
151 | ImDrawIdx* idx_dst;
152 | if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
153 | return;
154 | if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
155 | return;
156 | for (int n = 0; n < draw_data->CmdListsCount; n++)
157 | {
158 | const ImDrawList* cmd_list = draw_data->CmdLists[n];
159 | const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
160 | for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
161 | {
162 | vtx_dst->pos[0] = vtx_src->pos.x;
163 | vtx_dst->pos[1] = vtx_src->pos.y;
164 | vtx_dst->pos[2] = 0.0f;
165 | vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000) >> 16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9
166 | vtx_dst->uv[0] = vtx_src->uv.x;
167 | vtx_dst->uv[1] = vtx_src->uv.y;
168 | vtx_dst++;
169 | vtx_src++;
170 | }
171 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
172 | idx_dst += cmd_list->IdxBuffer.Size;
173 | }
174 | g_pVB->Unlock();
175 | g_pIB->Unlock();
176 | g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
177 | g_pd3dDevice->SetIndices(g_pIB);
178 | g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
179 |
180 | // Setup desired DX state
181 | ImGui_ImplDX9_SetupRenderState(draw_data);
182 |
183 | // Render command lists
184 | // (Because we merged all buffers into a single one, we maintain our own offset into them)
185 | int global_vtx_offset = 0;
186 | int global_idx_offset = 0;
187 | ImVec2 clip_off = draw_data->DisplayPos;
188 | for (int n = 0; n < draw_data->CmdListsCount; n++)
189 | {
190 | const ImDrawList* cmd_list = draw_data->CmdLists[n];
191 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
192 | {
193 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
194 | if (pcmd->UserCallback != NULL)
195 | {
196 | // User callback, registered via ImDrawList::AddCallback()
197 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
198 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
199 | ImGui_ImplDX9_SetupRenderState(draw_data);
200 | else
201 | pcmd->UserCallback(cmd_list, pcmd);
202 | }
203 | else
204 | {
205 | const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
206 | const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->TextureId;
207 | g_pd3dDevice->SetTexture(0, texture);
208 | g_pd3dDevice->SetScissorRect(&r);
209 | g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
210 | }
211 | }
212 | global_idx_offset += cmd_list->IdxBuffer.Size;
213 | global_vtx_offset += cmd_list->VtxBuffer.Size;
214 | }
215 |
216 | // When using multi-viewports, it appears that there's an odd logic in DirectX9 which prevent subsequent windows
217 | // from rendering until the first window submits at least one draw call, even once. That's our workaround. (see #2560)
218 | if (global_vtx_offset == 0)
219 | g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 0, 0, 0);
220 |
221 | // Restore the DX9 transform
222 | g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
223 | g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
224 | g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
225 |
226 | // Restore the DX9 state
227 | d3d9_state_block->Apply();
228 | d3d9_state_block->Release();
229 | }
230 |
231 | bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
232 | {
233 | // Setup backend capabilities flags
234 | ImGuiIO& io = ImGui::GetIO();
235 | io.BackendRendererName = "imgui_impl_dx9";
236 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
237 | io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
238 |
239 | g_pd3dDevice = device;
240 | g_pd3dDevice->AddRef();
241 |
242 | if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
243 | ImGui_ImplDX9_InitPlatformInterface();
244 |
245 | return true;
246 | }
247 |
248 | void ImGui_ImplDX9_Shutdown()
249 | {
250 | ImGui_ImplDX9_ShutdownPlatformInterface();
251 | ImGui_ImplDX9_InvalidateDeviceObjects();
252 | if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
253 | }
254 |
255 | static bool ImGui_ImplDX9_CreateFontsTexture()
256 | {
257 | // Build texture atlas
258 | ImGuiIO& io = ImGui::GetIO();
259 | unsigned char* pixels;
260 | int width, height, bytes_per_pixel;
261 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
262 |
263 | // Upload texture to graphics system
264 | g_FontTexture = NULL;
265 | if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0)
266 | return false;
267 | D3DLOCKED_RECT tex_locked_rect;
268 | if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK)
269 | return false;
270 | for (int y = 0; y < height; y++)
271 | memcpy((unsigned char*)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel));
272 | g_FontTexture->UnlockRect(0);
273 |
274 | // Store our identifier
275 | io.Fonts->TexID = (ImTextureID)g_FontTexture;
276 |
277 | return true;
278 | }
279 |
280 | bool ImGui_ImplDX9_CreateDeviceObjects()
281 | {
282 | if (!g_pd3dDevice)
283 | return false;
284 | if (!ImGui_ImplDX9_CreateFontsTexture())
285 | return false;
286 | ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows();
287 | return true;
288 | }
289 |
290 | void ImGui_ImplDX9_InvalidateDeviceObjects()
291 | {
292 | if (!g_pd3dDevice)
293 | return;
294 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
295 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
296 | if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
297 | ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
298 | }
299 |
300 | void ImGui_ImplDX9_NewFrame()
301 | {
302 | if (!g_FontTexture)
303 | ImGui_ImplDX9_CreateDeviceObjects();
304 | }
305 |
306 | //--------------------------------------------------------------------------------------------------------
307 | // MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
308 | // This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
309 | // If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
310 | //--------------------------------------------------------------------------------------------------------
311 |
312 | // Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
313 | struct ImGuiViewportDataDx9
314 | {
315 | IDirect3DSwapChain9* SwapChain;
316 | D3DPRESENT_PARAMETERS d3dpp;
317 |
318 | ImGuiViewportDataDx9() { SwapChain = NULL; ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); }
319 | ~ImGuiViewportDataDx9() { IM_ASSERT(SwapChain == NULL); }
320 | };
321 |
322 | static void ImGui_ImplDX9_CreateWindow(ImGuiViewport* viewport)
323 | {
324 | ImGuiViewportDataDx9* data = IM_NEW(ImGuiViewportDataDx9)();
325 | viewport->RendererUserData = data;
326 |
327 | // PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
328 | // Some backends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
329 | HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
330 | IM_ASSERT(hwnd != 0);
331 |
332 | ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
333 | data->d3dpp.Windowed = TRUE;
334 | data->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
335 | data->d3dpp.BackBufferWidth = (UINT)viewport->Size.x;
336 | data->d3dpp.BackBufferHeight = (UINT)viewport->Size.y;
337 | data->d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
338 | data->d3dpp.hDeviceWindow = hwnd;
339 | data->d3dpp.EnableAutoDepthStencil = FALSE;
340 | data->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
341 | data->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync
342 |
343 | HRESULT hr = g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain); IM_UNUSED(hr);
344 | IM_ASSERT(hr == D3D_OK);
345 | IM_ASSERT(data->SwapChain != NULL);
346 | }
347 |
348 | static void ImGui_ImplDX9_DestroyWindow(ImGuiViewport* viewport)
349 | {
350 | // The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
351 | if (ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData)
352 | {
353 | if (data->SwapChain)
354 | data->SwapChain->Release();
355 | data->SwapChain = NULL;
356 | ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
357 | IM_DELETE(data);
358 | }
359 | viewport->RendererUserData = NULL;
360 | }
361 |
362 | static void ImGui_ImplDX9_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
363 | {
364 | ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
365 | if (data->SwapChain)
366 | {
367 | data->SwapChain->Release();
368 | data->SwapChain = NULL;
369 | data->d3dpp.BackBufferWidth = (UINT)size.x;
370 | data->d3dpp.BackBufferHeight = (UINT)size.y;
371 | HRESULT hr = g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain); IM_UNUSED(hr);
372 | IM_ASSERT(hr == D3D_OK);
373 | }
374 | }
375 |
376 | static void ImGui_ImplDX9_RenderWindow(ImGuiViewport* viewport, void*)
377 | {
378 | ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
379 | ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
380 |
381 | LPDIRECT3DSURFACE9 render_target = NULL;
382 | LPDIRECT3DSURFACE9 last_render_target = NULL;
383 | LPDIRECT3DSURFACE9 last_depth_stencil = NULL;
384 | data->SwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &render_target);
385 | g_pd3dDevice->GetRenderTarget(0, &last_render_target);
386 | g_pd3dDevice->GetDepthStencilSurface(&last_depth_stencil);
387 | g_pd3dDevice->SetRenderTarget(0, render_target);
388 | g_pd3dDevice->SetDepthStencilSurface(NULL);
389 |
390 | if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
391 | {
392 | D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x*255.0f), (int)(clear_color.y*255.0f), (int)(clear_color.z*255.0f), (int)(clear_color.w*255.0f));
393 | g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, clear_col_dx, 1.0f, 0);
394 | }
395 |
396 | ImGui_ImplDX9_RenderDrawData(viewport->DrawData);
397 |
398 | // Restore render target
399 | g_pd3dDevice->SetRenderTarget(0, last_render_target);
400 | g_pd3dDevice->SetDepthStencilSurface(last_depth_stencil);
401 | render_target->Release();
402 | last_render_target->Release();
403 | if (last_depth_stencil) last_depth_stencil->Release();
404 | }
405 |
406 | static void ImGui_ImplDX9_SwapBuffers(ImGuiViewport* viewport, void*)
407 | {
408 | ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
409 | HRESULT hr = data->SwapChain->Present(NULL, NULL, data->d3dpp.hDeviceWindow, NULL, NULL);
410 | // Let main application handle D3DERR_DEVICELOST by resetting the device.
411 | IM_ASSERT(hr == D3D_OK || hr == D3DERR_DEVICELOST);
412 | }
413 |
414 | static void ImGui_ImplDX9_InitPlatformInterface()
415 | {
416 | ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
417 | platform_io.Renderer_CreateWindow = ImGui_ImplDX9_CreateWindow;
418 | platform_io.Renderer_DestroyWindow = ImGui_ImplDX9_DestroyWindow;
419 | platform_io.Renderer_SetWindowSize = ImGui_ImplDX9_SetWindowSize;
420 | platform_io.Renderer_RenderWindow = ImGui_ImplDX9_RenderWindow;
421 | platform_io.Renderer_SwapBuffers = ImGui_ImplDX9_SwapBuffers;
422 | }
423 |
424 | static void ImGui_ImplDX9_ShutdownPlatformInterface()
425 | {
426 | ImGui::DestroyPlatformWindows();
427 | }
428 |
429 | static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows()
430 | {
431 | ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
432 | for (int i = 1; i < platform_io.Viewports.Size; i++)
433 | if (!platform_io.Viewports[i]->RendererUserData)
434 | ImGui_ImplDX9_CreateWindow(platform_io.Viewports[i]);
435 | }
436 |
437 | static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows()
438 | {
439 | ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
440 | for (int i = 1; i < platform_io.Viewports.Size; i++)
441 | if (platform_io.Viewports[i]->RendererUserData)
442 | ImGui_ImplDX9_DestroyWindow(platform_io.Viewports[i]);
443 | }
444 |
--------------------------------------------------------------------------------
/imgui/imgui_impl_dx9.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Renderer Backend for DirectX9
2 | // This needs to be used along with a Platform Backend (e.g. Win32)
3 |
4 | // Implemented features:
5 | // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
6 | // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
7 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
8 |
9 | // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs
12 |
13 | #pragma once
14 | #include "imgui.h" // IMGUI_IMPL_API
15 |
16 | struct IDirect3DDevice9;
17 |
18 | IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
19 | IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
20 | IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame();
21 | IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
22 |
23 | // Use if you want to reset your rendering device without losing Dear ImGui state.
24 | IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
25 | IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
26 |
--------------------------------------------------------------------------------
/imgui/imgui_impl_win32.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
3 |
4 | // Implemented features:
5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
9 | // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
10 |
11 | // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs
14 |
15 | #pragma once
16 | #include "imgui.h" // IMGUI_IMPL_API
17 |
18 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
19 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
20 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
21 |
22 | // Configuration
23 | // - Disable gamepad support or linking with xinput.lib
24 | //#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
25 | //#define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT
26 |
27 | // Win32 message handler your application need to call.
28 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper.
29 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
30 | #if 0
31 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
32 | #endif
33 |
34 | // DPI-related helpers (optional)
35 | // - Use to enable DPI awareness without having to create an application manifest.
36 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
37 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
38 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
39 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
40 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
41 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
42 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
43 |
--------------------------------------------------------------------------------
/imgui/imstb_rectpack.h:
--------------------------------------------------------------------------------
1 | // [DEAR IMGUI]
2 | // This is a slightly modified version of stb_rect_pack.h 1.00.
3 | // Those changes would need to be pushed into nothings/stb:
4 | // - Added STBRP__CDECL
5 | // Grep for [DEAR IMGUI] to find the changes.
6 |
7 | // stb_rect_pack.h - v1.00 - public domain - rectangle packing
8 | // Sean Barrett 2014
9 | //
10 | // Useful for e.g. packing rectangular textures into an atlas.
11 | // Does not do rotation.
12 | //
13 | // Not necessarily the awesomest packing method, but better than
14 | // the totally naive one in stb_truetype (which is primarily what
15 | // this is meant to replace).
16 | //
17 | // Has only had a few tests run, may have issues.
18 | //
19 | // More docs to come.
20 | //
21 | // No memory allocations; uses qsort() and assert() from stdlib.
22 | // Can override those by defining STBRP_SORT and STBRP_ASSERT.
23 | //
24 | // This library currently uses the Skyline Bottom-Left algorithm.
25 | //
26 | // Please note: better rectangle packers are welcome! Please
27 | // implement them to the same API, but with a different init
28 | // function.
29 | //
30 | // Credits
31 | //
32 | // Library
33 | // Sean Barrett
34 | // Minor features
35 | // Martins Mozeiko
36 | // github:IntellectualKitty
37 | //
38 | // Bugfixes / warning fixes
39 | // Jeremy Jaussaud
40 | // Fabian Giesen
41 | //
42 | // Version history:
43 | //
44 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
45 | // 0.99 (2019-02-07) warning fixes
46 | // 0.11 (2017-03-03) return packing success/fail result
47 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings
48 | // 0.09 (2016-08-27) fix compiler warnings
49 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
50 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
51 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
52 | // 0.05: added STBRP_ASSERT to allow replacing assert
53 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support
54 | // 0.01: initial release
55 | //
56 | // LICENSE
57 | //
58 | // See end of file for license information.
59 |
60 | //////////////////////////////////////////////////////////////////////////////
61 | //
62 | // INCLUDE SECTION
63 | //
64 |
65 | #ifndef STB_INCLUDE_STB_RECT_PACK_H
66 | #define STB_INCLUDE_STB_RECT_PACK_H
67 |
68 | #define STB_RECT_PACK_VERSION 1
69 |
70 | #ifdef STBRP_STATIC
71 | #define STBRP_DEF static
72 | #else
73 | #define STBRP_DEF extern
74 | #endif
75 |
76 | #ifdef __cplusplus
77 | extern "C" {
78 | #endif
79 |
80 | typedef struct stbrp_context stbrp_context;
81 | typedef struct stbrp_node stbrp_node;
82 | typedef struct stbrp_rect stbrp_rect;
83 |
84 | #ifdef STBRP_LARGE_RECTS
85 | typedef int stbrp_coord;
86 | #else
87 | typedef unsigned short stbrp_coord;
88 | #endif
89 |
90 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
91 | // Assign packed locations to rectangles. The rectangles are of type
92 | // 'stbrp_rect' defined below, stored in the array 'rects', and there
93 | // are 'num_rects' many of them.
94 | //
95 | // Rectangles which are successfully packed have the 'was_packed' flag
96 | // set to a non-zero value and 'x' and 'y' store the minimum location
97 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left
98 | // if you imagine y increasing downwards). Rectangles which do not fit
99 | // have the 'was_packed' flag set to 0.
100 | //
101 | // You should not try to access the 'rects' array from another thread
102 | // while this function is running, as the function temporarily reorders
103 | // the array while it executes.
104 | //
105 | // To pack into another rectangle, you need to call stbrp_init_target
106 | // again. To continue packing into the same rectangle, you can call
107 | // this function again. Calling this multiple times with multiple rect
108 | // arrays will probably produce worse packing results than calling it
109 | // a single time with the full rectangle array, but the option is
110 | // available.
111 | //
112 | // The function returns 1 if all of the rectangles were successfully
113 | // packed and 0 otherwise.
114 |
115 | struct stbrp_rect
116 | {
117 | // reserved for your use:
118 | int id;
119 |
120 | // input:
121 | stbrp_coord w, h;
122 |
123 | // output:
124 | stbrp_coord x, y;
125 | int was_packed; // non-zero if valid packing
126 |
127 | }; // 16 bytes, nominally
128 |
129 |
130 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
131 | // Initialize a rectangle packer to:
132 | // pack a rectangle that is 'width' by 'height' in dimensions
133 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long
134 | //
135 | // You must call this function every time you start packing into a new target.
136 | //
137 | // There is no "shutdown" function. The 'nodes' memory must stay valid for
138 | // the following stbrp_pack_rects() call (or calls), but can be freed after
139 | // the call (or calls) finish.
140 | //
141 | // Note: to guarantee best results, either:
142 | // 1. make sure 'num_nodes' >= 'width'
143 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
144 | //
145 | // If you don't do either of the above things, widths will be quantized to multiples
146 | // of small integers to guarantee the algorithm doesn't run out of temporary storage.
147 | //
148 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm
149 | // may run out of temporary storage and be unable to pack some rectangles.
150 |
151 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
152 | // Optionally call this function after init but before doing any packing to
153 | // change the handling of the out-of-temp-memory scenario, described above.
154 | // If you call init again, this will be reset to the default (false).
155 |
156 |
157 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
158 | // Optionally select which packing heuristic the library should use. Different
159 | // heuristics will produce better/worse results for different data sets.
160 | // If you call init again, this will be reset to the default.
161 |
162 | enum
163 | {
164 | STBRP_HEURISTIC_Skyline_default=0,
165 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
166 | STBRP_HEURISTIC_Skyline_BF_sortHeight
167 | };
168 |
169 |
170 | //////////////////////////////////////////////////////////////////////////////
171 | //
172 | // the details of the following structures don't matter to you, but they must
173 | // be visible so you can handle the memory allocations for them
174 |
175 | struct stbrp_node
176 | {
177 | stbrp_coord x,y;
178 | stbrp_node *next;
179 | };
180 |
181 | struct stbrp_context
182 | {
183 | int width;
184 | int height;
185 | int align;
186 | int init_mode;
187 | int heuristic;
188 | int num_nodes;
189 | stbrp_node *active_head;
190 | stbrp_node *free_head;
191 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
192 | };
193 |
194 | #ifdef __cplusplus
195 | }
196 | #endif
197 |
198 | #endif
199 |
200 | //////////////////////////////////////////////////////////////////////////////
201 | //
202 | // IMPLEMENTATION SECTION
203 | //
204 |
205 | #ifdef STB_RECT_PACK_IMPLEMENTATION
206 | #ifndef STBRP_SORT
207 | #include
208 | #define STBRP_SORT qsort
209 | #endif
210 |
211 | #ifndef STBRP_ASSERT
212 | #include
213 | #define STBRP_ASSERT assert
214 | #endif
215 |
216 | // [DEAR IMGUI] Added STBRP__CDECL
217 | #ifdef _MSC_VER
218 | #define STBRP__NOTUSED(v) (void)(v)
219 | #define STBRP__CDECL __cdecl
220 | #else
221 | #define STBRP__NOTUSED(v) (void)sizeof(v)
222 | #define STBRP__CDECL
223 | #endif
224 |
225 | enum
226 | {
227 | STBRP__INIT_skyline = 1
228 | };
229 |
230 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
231 | {
232 | switch (context->init_mode) {
233 | case STBRP__INIT_skyline:
234 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
235 | context->heuristic = heuristic;
236 | break;
237 | default:
238 | STBRP_ASSERT(0);
239 | }
240 | }
241 |
242 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
243 | {
244 | if (allow_out_of_mem)
245 | // if it's ok to run out of memory, then don't bother aligning them;
246 | // this gives better packing, but may fail due to OOM (even though
247 | // the rectangles easily fit). @TODO a smarter approach would be to only
248 | // quantize once we've hit OOM, then we could get rid of this parameter.
249 | context->align = 1;
250 | else {
251 | // if it's not ok to run out of memory, then quantize the widths
252 | // so that num_nodes is always enough nodes.
253 | //
254 | // I.e. num_nodes * align >= width
255 | // align >= width / num_nodes
256 | // align = ceil(width/num_nodes)
257 |
258 | context->align = (context->width + context->num_nodes-1) / context->num_nodes;
259 | }
260 | }
261 |
262 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
263 | {
264 | int i;
265 | #ifndef STBRP_LARGE_RECTS
266 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
267 | #endif
268 |
269 | for (i=0; i < num_nodes-1; ++i)
270 | nodes[i].next = &nodes[i+1];
271 | nodes[i].next = NULL;
272 | context->init_mode = STBRP__INIT_skyline;
273 | context->heuristic = STBRP_HEURISTIC_Skyline_default;
274 | context->free_head = &nodes[0];
275 | context->active_head = &context->extra[0];
276 | context->width = width;
277 | context->height = height;
278 | context->num_nodes = num_nodes;
279 | stbrp_setup_allow_out_of_mem(context, 0);
280 |
281 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
282 | context->extra[0].x = 0;
283 | context->extra[0].y = 0;
284 | context->extra[0].next = &context->extra[1];
285 | context->extra[1].x = (stbrp_coord) width;
286 | #ifdef STBRP_LARGE_RECTS
287 | context->extra[1].y = (1<<30);
288 | #else
289 | context->extra[1].y = 65535;
290 | #endif
291 | context->extra[1].next = NULL;
292 | }
293 |
294 | // find minimum y position if it starts at x1
295 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
296 | {
297 | stbrp_node *node = first;
298 | int x1 = x0 + width;
299 | int min_y, visited_width, waste_area;
300 |
301 | STBRP__NOTUSED(c);
302 |
303 | STBRP_ASSERT(first->x <= x0);
304 |
305 | #if 0
306 | // skip in case we're past the node
307 | while (node->next->x <= x0)
308 | ++node;
309 | #else
310 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
311 | #endif
312 |
313 | STBRP_ASSERT(node->x <= x0);
314 |
315 | min_y = 0;
316 | waste_area = 0;
317 | visited_width = 0;
318 | while (node->x < x1) {
319 | if (node->y > min_y) {
320 | // raise min_y higher.
321 | // we've accounted for all waste up to min_y,
322 | // but we'll now add more waste for everything we've visted
323 | waste_area += visited_width * (node->y - min_y);
324 | min_y = node->y;
325 | // the first time through, visited_width might be reduced
326 | if (node->x < x0)
327 | visited_width += node->next->x - x0;
328 | else
329 | visited_width += node->next->x - node->x;
330 | } else {
331 | // add waste area
332 | int under_width = node->next->x - node->x;
333 | if (under_width + visited_width > width)
334 | under_width = width - visited_width;
335 | waste_area += under_width * (min_y - node->y);
336 | visited_width += under_width;
337 | }
338 | node = node->next;
339 | }
340 |
341 | *pwaste = waste_area;
342 | return min_y;
343 | }
344 |
345 | typedef struct
346 | {
347 | int x,y;
348 | stbrp_node **prev_link;
349 | } stbrp__findresult;
350 |
351 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
352 | {
353 | int best_waste = (1<<30), best_x, best_y = (1 << 30);
354 | stbrp__findresult fr;
355 | stbrp_node **prev, *node, *tail, **best = NULL;
356 |
357 | // align to multiple of c->align
358 | width = (width + c->align - 1);
359 | width -= width % c->align;
360 | STBRP_ASSERT(width % c->align == 0);
361 |
362 | // if it can't possibly fit, bail immediately
363 | if (width > c->width || height > c->height) {
364 | fr.prev_link = NULL;
365 | fr.x = fr.y = 0;
366 | return fr;
367 | }
368 |
369 | node = c->active_head;
370 | prev = &c->active_head;
371 | while (node->x + width <= c->width) {
372 | int y,waste;
373 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
374 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
375 | // bottom left
376 | if (y < best_y) {
377 | best_y = y;
378 | best = prev;
379 | }
380 | } else {
381 | // best-fit
382 | if (y + height <= c->height) {
383 | // can only use it if it first vertically
384 | if (y < best_y || (y == best_y && waste < best_waste)) {
385 | best_y = y;
386 | best_waste = waste;
387 | best = prev;
388 | }
389 | }
390 | }
391 | prev = &node->next;
392 | node = node->next;
393 | }
394 |
395 | best_x = (best == NULL) ? 0 : (*best)->x;
396 |
397 | // if doing best-fit (BF), we also have to try aligning right edge to each node position
398 | //
399 | // e.g, if fitting
400 | //
401 | // ____________________
402 | // |____________________|
403 | //
404 | // into
405 | //
406 | // | |
407 | // | ____________|
408 | // |____________|
409 | //
410 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
411 | //
412 | // This makes BF take about 2x the time
413 |
414 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
415 | tail = c->active_head;
416 | node = c->active_head;
417 | prev = &c->active_head;
418 | // find first node that's admissible
419 | while (tail->x < width)
420 | tail = tail->next;
421 | while (tail) {
422 | int xpos = tail->x - width;
423 | int y,waste;
424 | STBRP_ASSERT(xpos >= 0);
425 | // find the left position that matches this
426 | while (node->next->x <= xpos) {
427 | prev = &node->next;
428 | node = node->next;
429 | }
430 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
431 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
432 | if (y + height <= c->height) {
433 | if (y <= best_y) {
434 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
435 | best_x = xpos;
436 | STBRP_ASSERT(y <= best_y);
437 | best_y = y;
438 | best_waste = waste;
439 | best = prev;
440 | }
441 | }
442 | }
443 | tail = tail->next;
444 | }
445 | }
446 |
447 | fr.prev_link = best;
448 | fr.x = best_x;
449 | fr.y = best_y;
450 | return fr;
451 | }
452 |
453 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
454 | {
455 | // find best position according to heuristic
456 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
457 | stbrp_node *node, *cur;
458 |
459 | // bail if:
460 | // 1. it failed
461 | // 2. the best node doesn't fit (we don't always check this)
462 | // 3. we're out of memory
463 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
464 | res.prev_link = NULL;
465 | return res;
466 | }
467 |
468 | // on success, create new node
469 | node = context->free_head;
470 | node->x = (stbrp_coord) res.x;
471 | node->y = (stbrp_coord) (res.y + height);
472 |
473 | context->free_head = node->next;
474 |
475 | // insert the new node into the right starting point, and
476 | // let 'cur' point to the remaining nodes needing to be
477 | // stiched back in
478 |
479 | cur = *res.prev_link;
480 | if (cur->x < res.x) {
481 | // preserve the existing one, so start testing with the next one
482 | stbrp_node *next = cur->next;
483 | cur->next = node;
484 | cur = next;
485 | } else {
486 | *res.prev_link = node;
487 | }
488 |
489 | // from here, traverse cur and free the nodes, until we get to one
490 | // that shouldn't be freed
491 | while (cur->next && cur->next->x <= res.x + width) {
492 | stbrp_node *next = cur->next;
493 | // move the current node to the free list
494 | cur->next = context->free_head;
495 | context->free_head = cur;
496 | cur = next;
497 | }
498 |
499 | // stitch the list back in
500 | node->next = cur;
501 |
502 | if (cur->x < res.x + width)
503 | cur->x = (stbrp_coord) (res.x + width);
504 |
505 | #ifdef _DEBUG
506 | cur = context->active_head;
507 | while (cur->x < context->width) {
508 | STBRP_ASSERT(cur->x < cur->next->x);
509 | cur = cur->next;
510 | }
511 | STBRP_ASSERT(cur->next == NULL);
512 |
513 | {
514 | int count=0;
515 | cur = context->active_head;
516 | while (cur) {
517 | cur = cur->next;
518 | ++count;
519 | }
520 | cur = context->free_head;
521 | while (cur) {
522 | cur = cur->next;
523 | ++count;
524 | }
525 | STBRP_ASSERT(count == context->num_nodes+2);
526 | }
527 | #endif
528 |
529 | return res;
530 | }
531 |
532 | // [DEAR IMGUI] Added STBRP__CDECL
533 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
534 | {
535 | const stbrp_rect *p = (const stbrp_rect *) a;
536 | const stbrp_rect *q = (const stbrp_rect *) b;
537 | if (p->h > q->h)
538 | return -1;
539 | if (p->h < q->h)
540 | return 1;
541 | return (p->w > q->w) ? -1 : (p->w < q->w);
542 | }
543 |
544 | // [DEAR IMGUI] Added STBRP__CDECL
545 | static int STBRP__CDECL rect_original_order(const void *a, const void *b)
546 | {
547 | const stbrp_rect *p = (const stbrp_rect *) a;
548 | const stbrp_rect *q = (const stbrp_rect *) b;
549 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
550 | }
551 |
552 | #ifdef STBRP_LARGE_RECTS
553 | #define STBRP__MAXVAL 0xffffffff
554 | #else
555 | #define STBRP__MAXVAL 0xffff
556 | #endif
557 |
558 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
559 | {
560 | int i, all_rects_packed = 1;
561 |
562 | // we use the 'was_packed' field internally to allow sorting/unsorting
563 | for (i=0; i < num_rects; ++i) {
564 | rects[i].was_packed = i;
565 | }
566 |
567 | // sort according to heuristic
568 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
569 |
570 | for (i=0; i < num_rects; ++i) {
571 | if (rects[i].w == 0 || rects[i].h == 0) {
572 | rects[i].x = rects[i].y = 0; // empty rect needs no space
573 | } else {
574 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
575 | if (fr.prev_link) {
576 | rects[i].x = (stbrp_coord) fr.x;
577 | rects[i].y = (stbrp_coord) fr.y;
578 | } else {
579 | rects[i].x = rects[i].y = STBRP__MAXVAL;
580 | }
581 | }
582 | }
583 |
584 | // unsort
585 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
586 |
587 | // set was_packed flags and all_rects_packed status
588 | for (i=0; i < num_rects; ++i) {
589 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
590 | if (!rects[i].was_packed)
591 | all_rects_packed = 0;
592 | }
593 |
594 | // return the all_rects_packed status
595 | return all_rects_packed;
596 | }
597 | #endif
598 |
599 | /*
600 | ------------------------------------------------------------------------------
601 | This software is available under 2 licenses -- choose whichever you prefer.
602 | ------------------------------------------------------------------------------
603 | ALTERNATIVE A - MIT License
604 | Copyright (c) 2017 Sean Barrett
605 | Permission is hereby granted, free of charge, to any person obtaining a copy of
606 | this software and associated documentation files (the "Software"), to deal in
607 | the Software without restriction, including without limitation the rights to
608 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
609 | of the Software, and to permit persons to whom the Software is furnished to do
610 | so, subject to the following conditions:
611 | The above copyright notice and this permission notice shall be included in all
612 | copies or substantial portions of the Software.
613 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
614 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
615 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
616 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
617 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
618 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
619 | SOFTWARE.
620 | ------------------------------------------------------------------------------
621 | ALTERNATIVE B - Public Domain (www.unlicense.org)
622 | This is free and unencumbered software released into the public domain.
623 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
624 | software, either in source code form or as a compiled binary, for any purpose,
625 | commercial or non-commercial, and by any means.
626 | In jurisdictions that recognize copyright laws, the author or authors of this
627 | software dedicate any and all copyright interest in the software to the public
628 | domain. We make this dedication for the benefit of the public at large and to
629 | the detriment of our heirs and successors. We intend this dedication to be an
630 | overt act of relinquishment in perpetuity of all present and future rights to
631 | this software under copyright law.
632 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
633 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
634 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
635 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
636 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
637 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
638 | ------------------------------------------------------------------------------
639 | */
640 |
--------------------------------------------------------------------------------
/imgui_external_base/base.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.33328.57
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XO IMGUI EXTERNAL", "base.vcxproj", "{AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}"
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 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Debug|x64.ActiveCfg = Debug|x64
17 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Debug|x64.Build.0 = Debug|x64
18 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Debug|x86.ActiveCfg = Debug|Win32
19 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Debug|x86.Build.0 = Debug|Win32
20 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Release|x64.ActiveCfg = Release|x64
21 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Release|x64.Build.0 = Release|x64
22 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Release|x86.ActiveCfg = Release|Win32
23 | {AEAA4CEF-8D6D-4061-BCF1-C31CDDCCA231}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {95108900-D6DA-46A2-AC73-0B8E77EAA354}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/imgui_external_base/base.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {aeaa4cef-8d6d-4061-bcf1-c31cddcca231}
25 | LoaderBase
26 | 10.0
27 | XO IMGUI EXTERNAL
28 |
29 |
30 |
31 | Application
32 | true
33 | v142
34 | Unicode
35 |
36 |
37 | Application
38 | false
39 | v142
40 | true
41 | Unicode
42 |
43 |
44 | Application
45 | true
46 | v142
47 | MultiByte
48 |
49 |
50 | Application
51 | false
52 | v142
53 | true
54 | MultiByte
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | true
76 |
77 |
78 | false
79 |
80 |
81 | true
82 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)/imgui;$(ProjectDir);$(IncludePath)
83 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;$(LibraryPath)
84 |
85 |
86 | false
87 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)/imgui;$(ProjectDir);$(IncludePath)
88 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;$(LibraryPath)
89 |
90 |
91 |
92 | Level3
93 | true
94 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
95 | true
96 |
97 |
98 | Console
99 | true
100 |
101 |
102 |
103 |
104 | Level3
105 | true
106 | true
107 | true
108 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
109 | true
110 |
111 |
112 | Console
113 | true
114 | true
115 | true
116 |
117 |
118 |
119 |
120 | Level3
121 | true
122 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
123 | true
124 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)/imgui
125 |
126 |
127 | Windows
128 | true
129 |
130 |
131 |
132 |
133 | TurnOffAllWarnings
134 | true
135 | true
136 | true
137 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
138 | true
139 | C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(SolutionDir)/imgui
140 | stdcpp17
141 | MinSpace
142 | stdc17
143 |
144 |
145 | Windows
146 | true
147 | true
148 | false
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/imgui_external_base/base.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {39dbd3a4-bda5-4317-a3ef-50064f12ff10}
10 |
11 |
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files\imgui
18 |
19 |
20 | Source Files\imgui
21 |
22 |
23 | Source Files\imgui
24 |
25 |
26 | Source Files\imgui
27 |
28 |
29 | Source Files\imgui
30 |
31 |
32 | Source Files\imgui
33 |
34 |
35 |
36 |
37 | Source Files\imgui
38 |
39 |
40 | Source Files\imgui
41 |
42 |
43 | Source Files\imgui
44 |
45 |
46 | Source Files\imgui
47 |
48 |
49 | Source Files\imgui
50 |
51 |
52 | Source Files\imgui
53 |
54 |
55 | Source Files\imgui
56 |
57 |
58 | Source Files\imgui
59 |
60 |
61 | Source Files
62 |
63 |
64 | Source Files
65 |
66 |
67 | Source Files
68 |
69 |
70 | Source Files
71 |
72 |
73 |
--------------------------------------------------------------------------------
/imgui_external_base/base.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
--------------------------------------------------------------------------------
/imgui_external_base/imgui/imconfig.h:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------------
2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI
3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
5 | //-----------------------------------------------------------------------------
6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
8 | //-----------------------------------------------------------------------------
9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
12 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
13 | //-----------------------------------------------------------------------------
14 |
15 | #pragma once
16 |
17 | //---- Define assertion handler. Defaults to calling assert().
18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
21 |
22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
23 | // Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
24 | //#define IMGUI_API __declspec( dllexport )
25 | //#define IMGUI_API __declspec( dllimport )
26 |
27 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
28 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
29 |
30 | //---- Disable all of Dear ImGui or don't implement standard windows.
31 | // It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
32 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
33 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
34 | //#define IMGUI_DISABLE_METRICS_WINDOW // Disable debug/metrics window: ShowMetricsWindow() will be empty.
35 |
36 | //---- Don't implement some functions to reduce linkage requirements.
37 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
38 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
39 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
40 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
41 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
42 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
43 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
44 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
45 |
46 | //---- Include imgui_user.h at the end of imgui.h as a convenience
47 | //#define IMGUI_INCLUDE_IMGUI_USER_H
48 |
49 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
50 | //#define IMGUI_USE_BGRA_PACKED_COLOR
51 |
52 | //---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
53 | //#define IMGUI_USE_WCHAR32
54 |
55 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
56 | // By default the embedded implementations are declared static and not available outside of imgui cpp files.
57 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
58 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
59 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
60 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
61 |
62 | //---- Unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined, use the much faster STB sprintf library implementation of vsnprintf instead of the one from the default C library.
63 | // Note that stb_sprintf.h is meant to be provided by the user and available in the include path at compile time. Also, the compatibility checks of the arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
64 | // #define IMGUI_USE_STB_SPRINTF
65 |
66 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
67 | // This will be inlined as part of ImVec2 and ImVec4 class declarations.
68 | /*
69 | #define IM_VEC2_CLASS_EXTRA \
70 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
71 | operator MyVec2() const { return MyVec2(x,y); }
72 |
73 | #define IM_VEC4_CLASS_EXTRA \
74 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
75 | operator MyVec4() const { return MyVec4(x,y,z,w); }
76 | */
77 |
78 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
79 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
80 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
81 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
82 | //#define ImDrawIdx unsigned int
83 |
84 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
85 | //struct ImDrawList;
86 | //struct ImDrawCmd;
87 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
88 | //#define ImDrawCallback MyImDrawCallback
89 |
90 | //---- Debug Tools: Macro to break in Debugger
91 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
92 | //#define IM_DEBUG_BREAK IM_ASSERT(0)
93 | //#define IM_DEBUG_BREAK __debugbreak()
94 |
95 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
96 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
97 | // This adds a small runtime cost which is why it is not enabled by default.
98 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
99 |
100 | //---- Debug Tools: Enable slower asserts
101 | //#define IMGUI_DEBUG_PARANOID
102 |
103 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
104 | /*
105 | namespace ImGui
106 | {
107 | void MyFunction(const char* name, const MyMatrix44& v);
108 | }
109 | */
110 |
--------------------------------------------------------------------------------
/imgui_external_base/imgui/imgui_impl_dx9.cpp:
--------------------------------------------------------------------------------
1 | // dear imgui: Renderer Backend for DirectX9
2 | // This needs to be used along with a Platform Backend (e.g. Win32)
3 |
4 | // Implemented features:
5 | // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
6 | // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
7 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
8 |
9 | // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs
12 |
13 | // CHANGELOG
14 | // (minor and older changes stripped away, please see git history for details)
15 | // 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
16 | // 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
17 | // 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
18 | // 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
19 | // 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
20 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
21 | // 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
22 | // 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
23 | // 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud.
24 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
25 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
26 |
27 | #include "imgui.h"
28 | #include "imgui_impl_dx9.h"
29 |
30 | // DirectX
31 | #include
32 | #define DIRECTINPUT_VERSION 0x0800
33 | #include
34 |
35 | // DirectX data
36 | static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
37 | static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
38 | static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
39 | static LPDIRECT3DTEXTURE9 g_FontTexture = NULL;
40 | static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
41 |
42 | struct CUSTOMVERTEX
43 | {
44 | float pos[3];
45 | D3DCOLOR col;
46 | float uv[2];
47 | };
48 | #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
49 |
50 | // Forward Declarations
51 | static void ImGui_ImplDX9_InitPlatformInterface();
52 | static void ImGui_ImplDX9_ShutdownPlatformInterface();
53 | static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows();
54 | static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
55 |
56 | static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
57 | {
58 | // Setup viewport
59 | D3DVIEWPORT9 vp;
60 | vp.X = vp.Y = 0;
61 | vp.Width = (DWORD)draw_data->DisplaySize.x;
62 | vp.Height = (DWORD)draw_data->DisplaySize.y;
63 | vp.MinZ = 0.0f;
64 | vp.MaxZ = 1.0f;
65 | g_pd3dDevice->SetViewport(&vp);
66 |
67 | // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
68 | g_pd3dDevice->SetPixelShader(NULL);
69 | g_pd3dDevice->SetVertexShader(NULL);
70 | g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
71 | g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
72 | g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
73 | g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
74 | g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
75 | g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
76 | g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
77 | g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
78 | g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
79 | g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
80 | g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
81 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
82 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
83 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
84 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
85 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
86 | g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
87 | g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
88 | g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
89 |
90 | // Setup orthographic projection matrix
91 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
92 | // Being agnostic of whether or can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
93 | {
94 | float L = draw_data->DisplayPos.x + 0.5f;
95 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
96 | float T = draw_data->DisplayPos.y + 0.5f;
97 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
98 | D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
99 | D3DMATRIX mat_projection =
100 | { { {
101 | 2.0f/(R-L), 0.0f, 0.0f, 0.0f,
102 | 0.0f, 2.0f/(T-B), 0.0f, 0.0f,
103 | 0.0f, 0.0f, 0.5f, 0.0f,
104 | (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
105 | } } };
106 | g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
107 | g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
108 | g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
109 | }
110 | }
111 |
112 | // Render function.
113 | void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
114 | {
115 | // Avoid rendering when minimized
116 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
117 | return;
118 |
119 | // Create and grow buffers if needed
120 | if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
121 | {
122 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
123 | g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
124 | if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
125 | return;
126 | }
127 | if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
128 | {
129 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
130 | g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
131 | if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0)
132 | return;
133 | }
134 |
135 | // Backup the DX9 state
136 | IDirect3DStateBlock9* d3d9_state_block = NULL;
137 | if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
138 | return;
139 |
140 | // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
141 | D3DMATRIX last_world, last_view, last_projection;
142 | g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
143 | g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
144 | g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
145 |
146 | // Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
147 | // FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and
148 | // 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
149 | // 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
150 | CUSTOMVERTEX* vtx_dst;
151 | ImDrawIdx* idx_dst;
152 | if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
153 | return;
154 | if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
155 | return;
156 | for (int n = 0; n < draw_data->CmdListsCount; n++)
157 | {
158 | const ImDrawList* cmd_list = draw_data->CmdLists[n];
159 | const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
160 | for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
161 | {
162 | vtx_dst->pos[0] = vtx_src->pos.x;
163 | vtx_dst->pos[1] = vtx_src->pos.y;
164 | vtx_dst->pos[2] = 0.0f;
165 | vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000) >> 16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9
166 | vtx_dst->uv[0] = vtx_src->uv.x;
167 | vtx_dst->uv[1] = vtx_src->uv.y;
168 | vtx_dst++;
169 | vtx_src++;
170 | }
171 | memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
172 | idx_dst += cmd_list->IdxBuffer.Size;
173 | }
174 | g_pVB->Unlock();
175 | g_pIB->Unlock();
176 | g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
177 | g_pd3dDevice->SetIndices(g_pIB);
178 | g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
179 |
180 | // Setup desired DX state
181 | ImGui_ImplDX9_SetupRenderState(draw_data);
182 |
183 | // Render command lists
184 | // (Because we merged all buffers into a single one, we maintain our own offset into them)
185 | int global_vtx_offset = 0;
186 | int global_idx_offset = 0;
187 | ImVec2 clip_off = draw_data->DisplayPos;
188 | for (int n = 0; n < draw_data->CmdListsCount; n++)
189 | {
190 | const ImDrawList* cmd_list = draw_data->CmdLists[n];
191 | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
192 | {
193 | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
194 | if (pcmd->UserCallback != NULL)
195 | {
196 | // User callback, registered via ImDrawList::AddCallback()
197 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
198 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
199 | ImGui_ImplDX9_SetupRenderState(draw_data);
200 | else
201 | pcmd->UserCallback(cmd_list, pcmd);
202 | }
203 | else
204 | {
205 | const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
206 | const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->TextureId;
207 | g_pd3dDevice->SetTexture(0, texture);
208 | g_pd3dDevice->SetScissorRect(&r);
209 | g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
210 | }
211 | }
212 | global_idx_offset += cmd_list->IdxBuffer.Size;
213 | global_vtx_offset += cmd_list->VtxBuffer.Size;
214 | }
215 |
216 | // When using multi-viewports, it appears that there's an odd logic in DirectX9 which prevent subsequent windows
217 | // from rendering until the first window submits at least one draw call, even once. That's our workaround. (see #2560)
218 | if (global_vtx_offset == 0)
219 | g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 0, 0, 0);
220 |
221 | // Restore the DX9 transform
222 | g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
223 | g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
224 | g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
225 |
226 | // Restore the DX9 state
227 | d3d9_state_block->Apply();
228 | d3d9_state_block->Release();
229 | }
230 |
231 | bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
232 | {
233 | // Setup backend capabilities flags
234 | ImGuiIO& io = ImGui::GetIO();
235 | io.BackendRendererName = "imgui_impl_dx9";
236 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
237 | io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional)
238 |
239 | g_pd3dDevice = device;
240 | g_pd3dDevice->AddRef();
241 |
242 | if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
243 | ImGui_ImplDX9_InitPlatformInterface();
244 |
245 | return true;
246 | }
247 |
248 | void ImGui_ImplDX9_Shutdown()
249 | {
250 | ImGui_ImplDX9_ShutdownPlatformInterface();
251 | ImGui_ImplDX9_InvalidateDeviceObjects();
252 | if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
253 | }
254 |
255 | static bool ImGui_ImplDX9_CreateFontsTexture()
256 | {
257 | // Build texture atlas
258 | ImGuiIO& io = ImGui::GetIO();
259 | unsigned char* pixels;
260 | int width, height, bytes_per_pixel;
261 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
262 |
263 | // Upload texture to graphics system
264 | g_FontTexture = NULL;
265 | if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0)
266 | return false;
267 | D3DLOCKED_RECT tex_locked_rect;
268 | if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK)
269 | return false;
270 | for (int y = 0; y < height; y++)
271 | memcpy((unsigned char*)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel));
272 | g_FontTexture->UnlockRect(0);
273 |
274 | // Store our identifier
275 | io.Fonts->TexID = (ImTextureID)g_FontTexture;
276 |
277 | return true;
278 | }
279 |
280 | bool ImGui_ImplDX9_CreateDeviceObjects()
281 | {
282 | if (!g_pd3dDevice)
283 | return false;
284 | if (!ImGui_ImplDX9_CreateFontsTexture())
285 | return false;
286 | ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows();
287 | return true;
288 | }
289 |
290 | void ImGui_ImplDX9_InvalidateDeviceObjects()
291 | {
292 | if (!g_pd3dDevice)
293 | return;
294 | if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
295 | if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
296 | if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
297 | ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
298 | }
299 |
300 | void ImGui_ImplDX9_NewFrame()
301 | {
302 | if (!g_FontTexture)
303 | ImGui_ImplDX9_CreateDeviceObjects();
304 | }
305 |
306 | //--------------------------------------------------------------------------------------------------------
307 | // MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
308 | // This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
309 | // If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
310 | //--------------------------------------------------------------------------------------------------------
311 |
312 | // Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
313 | struct ImGuiViewportDataDx9
314 | {
315 | IDirect3DSwapChain9* SwapChain;
316 | D3DPRESENT_PARAMETERS d3dpp;
317 |
318 | ImGuiViewportDataDx9() { SwapChain = NULL; ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); }
319 | ~ImGuiViewportDataDx9() { IM_ASSERT(SwapChain == NULL); }
320 | };
321 |
322 | static void ImGui_ImplDX9_CreateWindow(ImGuiViewport* viewport)
323 | {
324 | ImGuiViewportDataDx9* data = IM_NEW(ImGuiViewportDataDx9)();
325 | viewport->RendererUserData = data;
326 |
327 | // PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL_Window*).
328 | // Some backends will leave PlatformHandleRaw NULL, in which case we assume PlatformHandle will contain the HWND.
329 | HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
330 | IM_ASSERT(hwnd != 0);
331 |
332 | ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
333 | data->d3dpp.Windowed = TRUE;
334 | data->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
335 | data->d3dpp.BackBufferWidth = (UINT)viewport->Size.x;
336 | data->d3dpp.BackBufferHeight = (UINT)viewport->Size.y;
337 | data->d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
338 | data->d3dpp.hDeviceWindow = hwnd;
339 | data->d3dpp.EnableAutoDepthStencil = FALSE;
340 | data->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
341 | data->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync
342 |
343 | HRESULT hr = g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain); IM_UNUSED(hr);
344 | IM_ASSERT(hr == D3D_OK);
345 | IM_ASSERT(data->SwapChain != NULL);
346 | }
347 |
348 | static void ImGui_ImplDX9_DestroyWindow(ImGuiViewport* viewport)
349 | {
350 | // The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
351 | if (ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData)
352 | {
353 | if (data->SwapChain)
354 | data->SwapChain->Release();
355 | data->SwapChain = NULL;
356 | ZeroMemory(&data->d3dpp, sizeof(D3DPRESENT_PARAMETERS));
357 | IM_DELETE(data);
358 | }
359 | viewport->RendererUserData = NULL;
360 | }
361 |
362 | static void ImGui_ImplDX9_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
363 | {
364 | ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
365 | if (data->SwapChain)
366 | {
367 | data->SwapChain->Release();
368 | data->SwapChain = NULL;
369 | data->d3dpp.BackBufferWidth = (UINT)size.x;
370 | data->d3dpp.BackBufferHeight = (UINT)size.y;
371 | HRESULT hr = g_pd3dDevice->CreateAdditionalSwapChain(&data->d3dpp, &data->SwapChain); IM_UNUSED(hr);
372 | IM_ASSERT(hr == D3D_OK);
373 | }
374 | }
375 |
376 | static void ImGui_ImplDX9_RenderWindow(ImGuiViewport* viewport, void*)
377 | {
378 | ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
379 | ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
380 |
381 | LPDIRECT3DSURFACE9 render_target = NULL;
382 | LPDIRECT3DSURFACE9 last_render_target = NULL;
383 | LPDIRECT3DSURFACE9 last_depth_stencil = NULL;
384 | data->SwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &render_target);
385 | g_pd3dDevice->GetRenderTarget(0, &last_render_target);
386 | g_pd3dDevice->GetDepthStencilSurface(&last_depth_stencil);
387 | g_pd3dDevice->SetRenderTarget(0, render_target);
388 | g_pd3dDevice->SetDepthStencilSurface(NULL);
389 |
390 | if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
391 | {
392 | D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x*255.0f), (int)(clear_color.y*255.0f), (int)(clear_color.z*255.0f), (int)(clear_color.w*255.0f));
393 | g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, clear_col_dx, 1.0f, 0);
394 | }
395 |
396 | ImGui_ImplDX9_RenderDrawData(viewport->DrawData);
397 |
398 | // Restore render target
399 | g_pd3dDevice->SetRenderTarget(0, last_render_target);
400 | g_pd3dDevice->SetDepthStencilSurface(last_depth_stencil);
401 | render_target->Release();
402 | last_render_target->Release();
403 | if (last_depth_stencil) last_depth_stencil->Release();
404 | }
405 |
406 | static void ImGui_ImplDX9_SwapBuffers(ImGuiViewport* viewport, void*)
407 | {
408 | ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
409 | HRESULT hr = data->SwapChain->Present(NULL, NULL, data->d3dpp.hDeviceWindow, NULL, NULL);
410 | // Let main application handle D3DERR_DEVICELOST by resetting the device.
411 | IM_ASSERT(hr == D3D_OK || hr == D3DERR_DEVICELOST);
412 | }
413 |
414 | static void ImGui_ImplDX9_InitPlatformInterface()
415 | {
416 | ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
417 | platform_io.Renderer_CreateWindow = ImGui_ImplDX9_CreateWindow;
418 | platform_io.Renderer_DestroyWindow = ImGui_ImplDX9_DestroyWindow;
419 | platform_io.Renderer_SetWindowSize = ImGui_ImplDX9_SetWindowSize;
420 | platform_io.Renderer_RenderWindow = ImGui_ImplDX9_RenderWindow;
421 | platform_io.Renderer_SwapBuffers = ImGui_ImplDX9_SwapBuffers;
422 | }
423 |
424 | static void ImGui_ImplDX9_ShutdownPlatformInterface()
425 | {
426 | ImGui::DestroyPlatformWindows();
427 | }
428 |
429 | static void ImGui_ImplDX9_CreateDeviceObjectsForPlatformWindows()
430 | {
431 | ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
432 | for (int i = 1; i < platform_io.Viewports.Size; i++)
433 | if (!platform_io.Viewports[i]->RendererUserData)
434 | ImGui_ImplDX9_CreateWindow(platform_io.Viewports[i]);
435 | }
436 |
437 | static void ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows()
438 | {
439 | ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
440 | for (int i = 1; i < platform_io.Viewports.Size; i++)
441 | if (platform_io.Viewports[i]->RendererUserData)
442 | ImGui_ImplDX9_DestroyWindow(platform_io.Viewports[i]);
443 | }
444 |
--------------------------------------------------------------------------------
/imgui_external_base/imgui/imgui_impl_dx9.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Renderer Backend for DirectX9
2 | // This needs to be used along with a Platform Backend (e.g. Win32)
3 |
4 | // Implemented features:
5 | // [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
6 | // [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
7 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
8 |
9 | // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
10 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
11 | // Read online: https://github.com/ocornut/imgui/tree/master/docs
12 |
13 | #pragma once
14 | #include "imgui.h" // IMGUI_IMPL_API
15 |
16 | struct IDirect3DDevice9;
17 |
18 | IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
19 | IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
20 | IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame();
21 | IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
22 |
23 | // Use if you want to reset your rendering device without losing Dear ImGui state.
24 | IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
25 | IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
26 |
--------------------------------------------------------------------------------
/imgui_external_base/imgui/imgui_impl_win32.h:
--------------------------------------------------------------------------------
1 | // dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
3 |
4 | // Implemented features:
5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
9 | // [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
10 |
11 | // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs
14 |
15 | #pragma once
16 | #include "imgui.h" // IMGUI_IMPL_API
17 |
18 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
19 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
20 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
21 |
22 | // Configuration
23 | // - Disable gamepad support or linking with xinput.lib
24 | //#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
25 | //#define IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT
26 |
27 | // Win32 message handler your application need to call.
28 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper.
29 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
30 | #if 0
31 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
32 | #endif
33 |
34 | // DPI-related helpers (optional)
35 | // - Use to enable DPI awareness without having to create an application manifest.
36 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
37 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
38 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
39 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
40 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
41 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
42 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
43 |
--------------------------------------------------------------------------------
/imgui_external_base/imgui/imstb_rectpack.h:
--------------------------------------------------------------------------------
1 | // [DEAR IMGUI]
2 | // This is a slightly modified version of stb_rect_pack.h 1.00.
3 | // Those changes would need to be pushed into nothings/stb:
4 | // - Added STBRP__CDECL
5 | // Grep for [DEAR IMGUI] to find the changes.
6 |
7 | // stb_rect_pack.h - v1.00 - public domain - rectangle packing
8 | // Sean Barrett 2014
9 | //
10 | // Useful for e.g. packing rectangular textures into an atlas.
11 | // Does not do rotation.
12 | //
13 | // Not necessarily the awesomest packing method, but better than
14 | // the totally naive one in stb_truetype (which is primarily what
15 | // this is meant to replace).
16 | //
17 | // Has only had a few tests run, may have issues.
18 | //
19 | // More docs to come.
20 | //
21 | // No memory allocations; uses qsort() and assert() from stdlib.
22 | // Can override those by defining STBRP_SORT and STBRP_ASSERT.
23 | //
24 | // This library currently uses the Skyline Bottom-Left algorithm.
25 | //
26 | // Please note: better rectangle packers are welcome! Please
27 | // implement them to the same API, but with a different init
28 | // function.
29 | //
30 | // Credits
31 | //
32 | // Library
33 | // Sean Barrett
34 | // Minor features
35 | // Martins Mozeiko
36 | // github:IntellectualKitty
37 | //
38 | // Bugfixes / warning fixes
39 | // Jeremy Jaussaud
40 | // Fabian Giesen
41 | //
42 | // Version history:
43 | //
44 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
45 | // 0.99 (2019-02-07) warning fixes
46 | // 0.11 (2017-03-03) return packing success/fail result
47 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings
48 | // 0.09 (2016-08-27) fix compiler warnings
49 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
50 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
51 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
52 | // 0.05: added STBRP_ASSERT to allow replacing assert
53 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support
54 | // 0.01: initial release
55 | //
56 | // LICENSE
57 | //
58 | // See end of file for license information.
59 |
60 | //////////////////////////////////////////////////////////////////////////////
61 | //
62 | // INCLUDE SECTION
63 | //
64 |
65 | #ifndef STB_INCLUDE_STB_RECT_PACK_H
66 | #define STB_INCLUDE_STB_RECT_PACK_H
67 |
68 | #define STB_RECT_PACK_VERSION 1
69 |
70 | #ifdef STBRP_STATIC
71 | #define STBRP_DEF static
72 | #else
73 | #define STBRP_DEF extern
74 | #endif
75 |
76 | #ifdef __cplusplus
77 | extern "C" {
78 | #endif
79 |
80 | typedef struct stbrp_context stbrp_context;
81 | typedef struct stbrp_node stbrp_node;
82 | typedef struct stbrp_rect stbrp_rect;
83 |
84 | #ifdef STBRP_LARGE_RECTS
85 | typedef int stbrp_coord;
86 | #else
87 | typedef unsigned short stbrp_coord;
88 | #endif
89 |
90 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
91 | // Assign packed locations to rectangles. The rectangles are of type
92 | // 'stbrp_rect' defined below, stored in the array 'rects', and there
93 | // are 'num_rects' many of them.
94 | //
95 | // Rectangles which are successfully packed have the 'was_packed' flag
96 | // set to a non-zero value and 'x' and 'y' store the minimum location
97 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left
98 | // if you imagine y increasing downwards). Rectangles which do not fit
99 | // have the 'was_packed' flag set to 0.
100 | //
101 | // You should not try to access the 'rects' array from another thread
102 | // while this function is running, as the function temporarily reorders
103 | // the array while it executes.
104 | //
105 | // To pack into another rectangle, you need to call stbrp_init_target
106 | // again. To continue packing into the same rectangle, you can call
107 | // this function again. Calling this multiple times with multiple rect
108 | // arrays will probably produce worse packing results than calling it
109 | // a single time with the full rectangle array, but the option is
110 | // available.
111 | //
112 | // The function returns 1 if all of the rectangles were successfully
113 | // packed and 0 otherwise.
114 |
115 | struct stbrp_rect
116 | {
117 | // reserved for your use:
118 | int id;
119 |
120 | // input:
121 | stbrp_coord w, h;
122 |
123 | // output:
124 | stbrp_coord x, y;
125 | int was_packed; // non-zero if valid packing
126 |
127 | }; // 16 bytes, nominally
128 |
129 |
130 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
131 | // Initialize a rectangle packer to:
132 | // pack a rectangle that is 'width' by 'height' in dimensions
133 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long
134 | //
135 | // You must call this function every time you start packing into a new target.
136 | //
137 | // There is no "shutdown" function. The 'nodes' memory must stay valid for
138 | // the following stbrp_pack_rects() call (or calls), but can be freed after
139 | // the call (or calls) finish.
140 | //
141 | // Note: to guarantee best results, either:
142 | // 1. make sure 'num_nodes' >= 'width'
143 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
144 | //
145 | // If you don't do either of the above things, widths will be quantized to multiples
146 | // of small integers to guarantee the algorithm doesn't run out of temporary storage.
147 | //
148 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm
149 | // may run out of temporary storage and be unable to pack some rectangles.
150 |
151 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
152 | // Optionally call this function after init but before doing any packing to
153 | // change the handling of the out-of-temp-memory scenario, described above.
154 | // If you call init again, this will be reset to the default (false).
155 |
156 |
157 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
158 | // Optionally select which packing heuristic the library should use. Different
159 | // heuristics will produce better/worse results for different data sets.
160 | // If you call init again, this will be reset to the default.
161 |
162 | enum
163 | {
164 | STBRP_HEURISTIC_Skyline_default=0,
165 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
166 | STBRP_HEURISTIC_Skyline_BF_sortHeight
167 | };
168 |
169 |
170 | //////////////////////////////////////////////////////////////////////////////
171 | //
172 | // the details of the following structures don't matter to you, but they must
173 | // be visible so you can handle the memory allocations for them
174 |
175 | struct stbrp_node
176 | {
177 | stbrp_coord x,y;
178 | stbrp_node *next;
179 | };
180 |
181 | struct stbrp_context
182 | {
183 | int width;
184 | int height;
185 | int align;
186 | int init_mode;
187 | int heuristic;
188 | int num_nodes;
189 | stbrp_node *active_head;
190 | stbrp_node *free_head;
191 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
192 | };
193 |
194 | #ifdef __cplusplus
195 | }
196 | #endif
197 |
198 | #endif
199 |
200 | //////////////////////////////////////////////////////////////////////////////
201 | //
202 | // IMPLEMENTATION SECTION
203 | //
204 |
205 | #ifdef STB_RECT_PACK_IMPLEMENTATION
206 | #ifndef STBRP_SORT
207 | #include
208 | #define STBRP_SORT qsort
209 | #endif
210 |
211 | #ifndef STBRP_ASSERT
212 | #include
213 | #define STBRP_ASSERT assert
214 | #endif
215 |
216 | // [DEAR IMGUI] Added STBRP__CDECL
217 | #ifdef _MSC_VER
218 | #define STBRP__NOTUSED(v) (void)(v)
219 | #define STBRP__CDECL __cdecl
220 | #else
221 | #define STBRP__NOTUSED(v) (void)sizeof(v)
222 | #define STBRP__CDECL
223 | #endif
224 |
225 | enum
226 | {
227 | STBRP__INIT_skyline = 1
228 | };
229 |
230 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
231 | {
232 | switch (context->init_mode) {
233 | case STBRP__INIT_skyline:
234 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
235 | context->heuristic = heuristic;
236 | break;
237 | default:
238 | STBRP_ASSERT(0);
239 | }
240 | }
241 |
242 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
243 | {
244 | if (allow_out_of_mem)
245 | // if it's ok to run out of memory, then don't bother aligning them;
246 | // this gives better packing, but may fail due to OOM (even though
247 | // the rectangles easily fit). @TODO a smarter approach would be to only
248 | // quantize once we've hit OOM, then we could get rid of this parameter.
249 | context->align = 1;
250 | else {
251 | // if it's not ok to run out of memory, then quantize the widths
252 | // so that num_nodes is always enough nodes.
253 | //
254 | // I.e. num_nodes * align >= width
255 | // align >= width / num_nodes
256 | // align = ceil(width/num_nodes)
257 |
258 | context->align = (context->width + context->num_nodes-1) / context->num_nodes;
259 | }
260 | }
261 |
262 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
263 | {
264 | int i;
265 | #ifndef STBRP_LARGE_RECTS
266 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
267 | #endif
268 |
269 | for (i=0; i < num_nodes-1; ++i)
270 | nodes[i].next = &nodes[i+1];
271 | nodes[i].next = NULL;
272 | context->init_mode = STBRP__INIT_skyline;
273 | context->heuristic = STBRP_HEURISTIC_Skyline_default;
274 | context->free_head = &nodes[0];
275 | context->active_head = &context->extra[0];
276 | context->width = width;
277 | context->height = height;
278 | context->num_nodes = num_nodes;
279 | stbrp_setup_allow_out_of_mem(context, 0);
280 |
281 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
282 | context->extra[0].x = 0;
283 | context->extra[0].y = 0;
284 | context->extra[0].next = &context->extra[1];
285 | context->extra[1].x = (stbrp_coord) width;
286 | #ifdef STBRP_LARGE_RECTS
287 | context->extra[1].y = (1<<30);
288 | #else
289 | context->extra[1].y = 65535;
290 | #endif
291 | context->extra[1].next = NULL;
292 | }
293 |
294 | // find minimum y position if it starts at x1
295 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
296 | {
297 | stbrp_node *node = first;
298 | int x1 = x0 + width;
299 | int min_y, visited_width, waste_area;
300 |
301 | STBRP__NOTUSED(c);
302 |
303 | STBRP_ASSERT(first->x <= x0);
304 |
305 | #if 0
306 | // skip in case we're past the node
307 | while (node->next->x <= x0)
308 | ++node;
309 | #else
310 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
311 | #endif
312 |
313 | STBRP_ASSERT(node->x <= x0);
314 |
315 | min_y = 0;
316 | waste_area = 0;
317 | visited_width = 0;
318 | while (node->x < x1) {
319 | if (node->y > min_y) {
320 | // raise min_y higher.
321 | // we've accounted for all waste up to min_y,
322 | // but we'll now add more waste for everything we've visted
323 | waste_area += visited_width * (node->y - min_y);
324 | min_y = node->y;
325 | // the first time through, visited_width might be reduced
326 | if (node->x < x0)
327 | visited_width += node->next->x - x0;
328 | else
329 | visited_width += node->next->x - node->x;
330 | } else {
331 | // add waste area
332 | int under_width = node->next->x - node->x;
333 | if (under_width + visited_width > width)
334 | under_width = width - visited_width;
335 | waste_area += under_width * (min_y - node->y);
336 | visited_width += under_width;
337 | }
338 | node = node->next;
339 | }
340 |
341 | *pwaste = waste_area;
342 | return min_y;
343 | }
344 |
345 | typedef struct
346 | {
347 | int x,y;
348 | stbrp_node **prev_link;
349 | } stbrp__findresult;
350 |
351 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
352 | {
353 | int best_waste = (1<<30), best_x, best_y = (1 << 30);
354 | stbrp__findresult fr;
355 | stbrp_node **prev, *node, *tail, **best = NULL;
356 |
357 | // align to multiple of c->align
358 | width = (width + c->align - 1);
359 | width -= width % c->align;
360 | STBRP_ASSERT(width % c->align == 0);
361 |
362 | // if it can't possibly fit, bail immediately
363 | if (width > c->width || height > c->height) {
364 | fr.prev_link = NULL;
365 | fr.x = fr.y = 0;
366 | return fr;
367 | }
368 |
369 | node = c->active_head;
370 | prev = &c->active_head;
371 | while (node->x + width <= c->width) {
372 | int y,waste;
373 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
374 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
375 | // bottom left
376 | if (y < best_y) {
377 | best_y = y;
378 | best = prev;
379 | }
380 | } else {
381 | // best-fit
382 | if (y + height <= c->height) {
383 | // can only use it if it first vertically
384 | if (y < best_y || (y == best_y && waste < best_waste)) {
385 | best_y = y;
386 | best_waste = waste;
387 | best = prev;
388 | }
389 | }
390 | }
391 | prev = &node->next;
392 | node = node->next;
393 | }
394 |
395 | best_x = (best == NULL) ? 0 : (*best)->x;
396 |
397 | // if doing best-fit (BF), we also have to try aligning right edge to each node position
398 | //
399 | // e.g, if fitting
400 | //
401 | // ____________________
402 | // |____________________|
403 | //
404 | // into
405 | //
406 | // | |
407 | // | ____________|
408 | // |____________|
409 | //
410 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
411 | //
412 | // This makes BF take about 2x the time
413 |
414 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
415 | tail = c->active_head;
416 | node = c->active_head;
417 | prev = &c->active_head;
418 | // find first node that's admissible
419 | while (tail->x < width)
420 | tail = tail->next;
421 | while (tail) {
422 | int xpos = tail->x - width;
423 | int y,waste;
424 | STBRP_ASSERT(xpos >= 0);
425 | // find the left position that matches this
426 | while (node->next->x <= xpos) {
427 | prev = &node->next;
428 | node = node->next;
429 | }
430 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
431 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
432 | if (y + height <= c->height) {
433 | if (y <= best_y) {
434 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
435 | best_x = xpos;
436 | STBRP_ASSERT(y <= best_y);
437 | best_y = y;
438 | best_waste = waste;
439 | best = prev;
440 | }
441 | }
442 | }
443 | tail = tail->next;
444 | }
445 | }
446 |
447 | fr.prev_link = best;
448 | fr.x = best_x;
449 | fr.y = best_y;
450 | return fr;
451 | }
452 |
453 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
454 | {
455 | // find best position according to heuristic
456 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
457 | stbrp_node *node, *cur;
458 |
459 | // bail if:
460 | // 1. it failed
461 | // 2. the best node doesn't fit (we don't always check this)
462 | // 3. we're out of memory
463 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
464 | res.prev_link = NULL;
465 | return res;
466 | }
467 |
468 | // on success, create new node
469 | node = context->free_head;
470 | node->x = (stbrp_coord) res.x;
471 | node->y = (stbrp_coord) (res.y + height);
472 |
473 | context->free_head = node->next;
474 |
475 | // insert the new node into the right starting point, and
476 | // let 'cur' point to the remaining nodes needing to be
477 | // stiched back in
478 |
479 | cur = *res.prev_link;
480 | if (cur->x < res.x) {
481 | // preserve the existing one, so start testing with the next one
482 | stbrp_node *next = cur->next;
483 | cur->next = node;
484 | cur = next;
485 | } else {
486 | *res.prev_link = node;
487 | }
488 |
489 | // from here, traverse cur and free the nodes, until we get to one
490 | // that shouldn't be freed
491 | while (cur->next && cur->next->x <= res.x + width) {
492 | stbrp_node *next = cur->next;
493 | // move the current node to the free list
494 | cur->next = context->free_head;
495 | context->free_head = cur;
496 | cur = next;
497 | }
498 |
499 | // stitch the list back in
500 | node->next = cur;
501 |
502 | if (cur->x < res.x + width)
503 | cur->x = (stbrp_coord) (res.x + width);
504 |
505 | #ifdef _DEBUG
506 | cur = context->active_head;
507 | while (cur->x < context->width) {
508 | STBRP_ASSERT(cur->x < cur->next->x);
509 | cur = cur->next;
510 | }
511 | STBRP_ASSERT(cur->next == NULL);
512 |
513 | {
514 | int count=0;
515 | cur = context->active_head;
516 | while (cur) {
517 | cur = cur->next;
518 | ++count;
519 | }
520 | cur = context->free_head;
521 | while (cur) {
522 | cur = cur->next;
523 | ++count;
524 | }
525 | STBRP_ASSERT(count == context->num_nodes+2);
526 | }
527 | #endif
528 |
529 | return res;
530 | }
531 |
532 | // [DEAR IMGUI] Added STBRP__CDECL
533 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
534 | {
535 | const stbrp_rect *p = (const stbrp_rect *) a;
536 | const stbrp_rect *q = (const stbrp_rect *) b;
537 | if (p->h > q->h)
538 | return -1;
539 | if (p->h < q->h)
540 | return 1;
541 | return (p->w > q->w) ? -1 : (p->w < q->w);
542 | }
543 |
544 | // [DEAR IMGUI] Added STBRP__CDECL
545 | static int STBRP__CDECL rect_original_order(const void *a, const void *b)
546 | {
547 | const stbrp_rect *p = (const stbrp_rect *) a;
548 | const stbrp_rect *q = (const stbrp_rect *) b;
549 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
550 | }
551 |
552 | #ifdef STBRP_LARGE_RECTS
553 | #define STBRP__MAXVAL 0xffffffff
554 | #else
555 | #define STBRP__MAXVAL 0xffff
556 | #endif
557 |
558 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
559 | {
560 | int i, all_rects_packed = 1;
561 |
562 | // we use the 'was_packed' field internally to allow sorting/unsorting
563 | for (i=0; i < num_rects; ++i) {
564 | rects[i].was_packed = i;
565 | }
566 |
567 | // sort according to heuristic
568 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
569 |
570 | for (i=0; i < num_rects; ++i) {
571 | if (rects[i].w == 0 || rects[i].h == 0) {
572 | rects[i].x = rects[i].y = 0; // empty rect needs no space
573 | } else {
574 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
575 | if (fr.prev_link) {
576 | rects[i].x = (stbrp_coord) fr.x;
577 | rects[i].y = (stbrp_coord) fr.y;
578 | } else {
579 | rects[i].x = rects[i].y = STBRP__MAXVAL;
580 | }
581 | }
582 | }
583 |
584 | // unsort
585 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
586 |
587 | // set was_packed flags and all_rects_packed status
588 | for (i=0; i < num_rects; ++i) {
589 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
590 | if (!rects[i].was_packed)
591 | all_rects_packed = 0;
592 | }
593 |
594 | // return the all_rects_packed status
595 | return all_rects_packed;
596 | }
597 | #endif
598 |
599 | /*
600 | ------------------------------------------------------------------------------
601 | This software is available under 2 licenses -- choose whichever you prefer.
602 | ------------------------------------------------------------------------------
603 | ALTERNATIVE A - MIT License
604 | Copyright (c) 2017 Sean Barrett
605 | Permission is hereby granted, free of charge, to any person obtaining a copy of
606 | this software and associated documentation files (the "Software"), to deal in
607 | the Software without restriction, including without limitation the rights to
608 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
609 | of the Software, and to permit persons to whom the Software is furnished to do
610 | so, subject to the following conditions:
611 | The above copyright notice and this permission notice shall be included in all
612 | copies or substantial portions of the Software.
613 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
614 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
615 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
616 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
617 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
618 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
619 | SOFTWARE.
620 | ------------------------------------------------------------------------------
621 | ALTERNATIVE B - Public Domain (www.unlicense.org)
622 | This is free and unencumbered software released into the public domain.
623 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
624 | software, either in source code form or as a compiled binary, for any purpose,
625 | commercial or non-commercial, and by any means.
626 | In jurisdictions that recognize copyright laws, the author or authors of this
627 | software dedicate any and all copyright interest in the software to the public
628 | domain. We make this dedication for the benefit of the public at large and to
629 | the detriment of our heirs and successors. We intend this dedication to be an
630 | overt act of relinquishment in perpetuity of all present and future rights to
631 | this software under copyright law.
632 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
633 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
634 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
635 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
636 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
637 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
638 | ------------------------------------------------------------------------------
639 | */
640 |
--------------------------------------------------------------------------------
/imgui_external_base/menu.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | namespace Menu {
10 |
11 | typedef struct Variables {
12 | std::vector products = {
13 | xorstr_("FiveM"),
14 | xorstr_("Overwatch"),
15 | xorstr_("Warzone")
16 | };
17 |
18 | int selected = 0;
19 | };
20 |
21 | inline Variables* Data = nullptr;
22 |
23 | inline bool Initialize() {
24 |
25 | Data = new Variables{};
26 |
27 | ImGuiIO& io = ImGui::GetIO();
28 | ImGuiStyle& style = ImGui::GetStyle();
29 |
30 | const auto size = sizeof(style.Colors) / sizeof(style.Colors[0]);
31 | ImVec4(&colors)[size] = style.Colors;
32 |
33 | style.WindowTitleAlign = ImVec2(0.5f, 0.5f);
34 |
35 | colors[ImGuiCol_TitleBg] = ImColor(40, 40, 40);
36 | colors[ImGuiCol_TitleBgActive] = ImColor(40, 40, 40);
37 | colors[ImGuiCol_TitleBgCollapsed] = ImColor(40, 40, 40);
38 |
39 | colors[ImGuiCol_FrameBg] = ImColor(24, 24, 24);
40 | colors[ImGuiCol_FrameBgActive] = ImColor(26, 26, 26);
41 | colors[ImGuiCol_FrameBgHovered] = ImColor(26, 26, 26);
42 |
43 | colors[ImGuiCol_Header] = ImColor(50, 50, 50);
44 | colors[ImGuiCol_HeaderActive] = ImColor(50, 50, 50);
45 | colors[ImGuiCol_HeaderHovered] = ImColor(50, 50, 50);
46 |
47 | colors[ImGuiCol_Button] = ImColor(26, 26, 26);
48 | colors[ImGuiCol_ButtonActive] = ImColor(26, 26, 26);
49 | colors[ImGuiCol_ButtonHovered] = ImColor(26, 26, 26);
50 |
51 | return true;
52 | }
53 |
54 | inline void Render() {
55 |
56 | const int flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize;
57 |
58 | ImGui::SetNextWindowSize(ImVec2(250, 300));
59 |
60 | ImGui::Begin(xorstr_("Example"), 0, flags);
61 |
62 | const ImVec2 avail = ImGui::GetContentRegionAvail();
63 | const float padding = 16.0f;
64 |
65 | ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + padding, ImGui::GetCursorPosY() + padding));
66 |
67 | ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
68 | ImGui::ListBoxHeader(xorstr_("##listbox_header"), ImVec2(avail.x - (padding * 2.0f), avail.y - (padding * 4.0f)));
69 |
70 | for (int index = 0;
71 | index < Data->products.size(); index++) {
72 |
73 | bool selected = (index == Data->selected);
74 |
75 | std::string& name = Data->products[index];
76 | if (ImGui::Selectable(name.c_str(), &selected))
77 | Data->selected = index;
78 |
79 | if (selected)
80 | ImGui::SetItemDefaultFocus();
81 | }
82 |
83 | ImGui::ListBoxFooter();
84 |
85 | ImVec2 button_size = { avail.x - (padding * 2.0f), 24.0f };
86 |
87 | ImGui::SetCursorPosX(ImGui::GetCursorPosX() + padding);
88 | if (ImGui::Button("Launch", button_size)) {
89 |
90 | /*
91 |
92 | Do your launch functionality here . . .
93 |
94 | */
95 |
96 | }
97 |
98 | ImGui::PopStyleVar();
99 | ImGui::End();
100 |
101 | }
102 | }
--------------------------------------------------------------------------------
/imgui_external_base/source.cpp:
--------------------------------------------------------------------------------
1 | #include "source.hpp"
2 | #include "fonts.hpp"
3 | #include "menu.hpp"
4 |
5 | /*
6 | Make sure to compile on x64 DEBUG/RELEASE.
7 | Enjoy! xo1337.
8 |
9 | Credits:
10 | - https://github.com/noteffex/ImGui-Loader-Base/ (External ImGui)
11 | - https://github.com/JustasMasiulis/xorstr (JustasMasiulis, xorstr_)
12 | */
13 |
14 | int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
15 | {
16 | WNDCLASSEX window_class = {
17 | sizeof(WNDCLASSEX),
18 | CS_CLASSDC,
19 | [](HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)->LRESULT {
20 | if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
21 | return true;
22 |
23 | switch (msg)
24 | {
25 | case WM_SIZE:
26 | if (device_handle != 0 && wParam != SIZE_MINIMIZED)
27 | {
28 | device_parameters.BackBufferWidth = LOWORD(lParam);
29 | device_parameters.BackBufferHeight = HIWORD(lParam);
30 | ResetDevice();
31 | }
32 | return 0;
33 | case WM_SYSCOMMAND:
34 | if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
35 | return 0;
36 | break;
37 | case WM_DESTROY:
38 | ExitProcess(0);
39 | return 0;
40 | }
41 | return DefWindowProcA(hWnd, msg, wParam, lParam);
42 | },
43 | 0L,
44 | 0L,
45 | GetModuleHandleA(0),
46 | 0,
47 | 0,
48 | 0,
49 | 0,
50 | "XO BASE",
51 | 0
52 | };
53 |
54 | RegisterClassExA(&window_class);
55 | window_handle = CreateWindowExA(0, window_class.lpszClassName, "XO BASE", WS_POPUP, 0, 0, 5, 5, 0, 0, window_class.hInstance, 0);
56 |
57 | if (!CreateDeviceD3D(window_handle))
58 | {
59 | CleanupDeviceD3D();
60 | UnregisterClassA(window_class.lpszClassName, window_class.hInstance);
61 | return 1;
62 | }
63 |
64 | ShowWindow(window_handle, SW_HIDE);
65 | UpdateWindow(window_handle);
66 |
67 | ImGui::CreateContext();
68 |
69 | ImGuiIO& io = ImGui::GetIO();
70 | io.IniFilename = nullptr;
71 | io.LogFilename = nullptr;
72 | io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
73 |
74 | static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
75 | ImFontConfig icons_config;
76 |
77 | io.IniFilename = nullptr;
78 | io.LogFilename = nullptr;
79 |
80 | icons_config.MergeMode = true;
81 | icons_config.PixelSnapH = true;
82 | icons_config.OversampleH = 3;
83 | icons_config.OversampleV = 3;
84 |
85 | ImFontConfig rubik;
86 | rubik.FontDataOwnedByAtlas = false;
87 |
88 | io.Fonts->AddFontFromMemoryTTF(const_cast(font_rubik), sizeof(font_rubik), 19.5, &rubik);
89 | io.Fonts->AddFontFromMemoryCompressedTTF(font_awesome_data, font_awesome_size, 32.5f, &icons_config, icons_ranges);
90 | io.Fonts->AddFontDefault();
91 |
92 | ImGuiStyle& style = ImGui::GetStyle();
93 | if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
94 | {
95 | style.WindowRounding = 0.0f;
96 | style.Colors[ImGuiCol_WindowBg].w = 1.0f;
97 | }
98 |
99 | if (!Menu::Initialize())
100 | {
101 | CleanupDeviceD3D();
102 | UnregisterClassA(window_class.lpszClassName, window_class.hInstance);
103 | return 1;
104 | }
105 |
106 | ImGui_ImplWin32_Init(window_handle);
107 | ImGui_ImplDX9_Init(device_handle);
108 |
109 | while (true)
110 | {
111 | MSG message;
112 | if (PeekMessageA(&message, 0, 0U, 0U, PM_REMOVE))
113 | {
114 | TranslateMessage(&message);
115 | DispatchMessageA(&message);
116 | continue;
117 | }
118 |
119 | if (message.message == WM_QUIT)
120 | break;
121 |
122 | ImGui_ImplDX9_NewFrame();
123 | ImGui_ImplWin32_NewFrame();
124 | ImGui::NewFrame();
125 |
126 | Menu::Render();
127 |
128 | ImGui::EndFrame();
129 |
130 | device_handle->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
131 | if (device_handle->BeginScene() >= 0)
132 | {
133 | ImGui::Render();
134 | ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
135 | device_handle->EndScene();
136 | }
137 |
138 | if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
139 | {
140 | ImGui::UpdatePlatformWindows();
141 | ImGui::RenderPlatformWindowsDefault();
142 | }
143 |
144 | HRESULT result = device_handle->Present(0, 0, 0, 0);
145 | if (result == D3DERR_DEVICELOST && device_handle->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) {
146 | ResetDevice();
147 | }
148 | }
149 |
150 | return 0;
151 | }
152 |
--------------------------------------------------------------------------------
/imgui_external_base/source.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 | #pragma comment(lib,"d3d9.lib")
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | HWND window_handle;
14 | LPDIRECT3DDEVICE9 device_handle;
15 | D3DPRESENT_PARAMETERS device_parameters;
16 | LPDIRECT3D9 device_direct;
17 |
18 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
19 | LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
20 |
21 | const int WINDOW_WIDTH = 1200;
22 | const int WINDOW_HEIGHT = 800;
23 |
24 | bool CreateDeviceD3D(HWND hWnd)
25 | {
26 | if ((device_direct = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
27 | return false;
28 |
29 | memset(&device_parameters, 0, sizeof(device_parameters));
30 |
31 | device_parameters.Windowed = TRUE;
32 | device_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
33 | device_parameters.BackBufferFormat = D3DFMT_UNKNOWN;
34 | device_parameters.EnableAutoDepthStencil = TRUE;
35 | device_parameters.AutoDepthStencilFormat = D3DFMT_D16;
36 | device_parameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
37 |
38 | if (device_direct->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &device_parameters, &device_handle) < 0)
39 | return false;
40 |
41 | return true;
42 | }
43 |
44 | void CleanupDeviceD3D()
45 | {
46 | if (device_handle)
47 | {
48 | device_handle->Release();
49 | device_handle = 0;
50 | }
51 |
52 | if (device_direct)
53 | {
54 | device_direct->Release();
55 | device_direct = 0;
56 | }
57 | }
58 |
59 | void ResetDevice()
60 | {
61 | ImGui_ImplDX9_InvalidateDeviceObjects();
62 | HRESULT Result = device_handle->Reset(&device_parameters);
63 | if (Result == D3DERR_INVALIDCALL)
64 | IM_ASSERT(0);
65 | ImGui_ImplDX9_CreateDeviceObjects();
66 | }
--------------------------------------------------------------------------------
/imgui_external_base/xorstr.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 - 2021 Justas Masiulis
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #define JM_XORSTR_DISABLE_AVX_INTRINSICS
18 |
19 | #ifndef JM_XORSTR_HPP
20 | #define JM_XORSTR_HPP
21 |
22 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__)
23 | #include
24 | #elif defined(_M_X64) || defined(__amd64__) || defined(_M_IX86) || defined(__i386__)
25 | #include
26 | #else
27 | #error Unsupported platform
28 | #endif
29 |
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #define xorstr(str) ::jm::xor_string([]() { return str; }, std::integral_constant{}, std::make_index_sequence<::jm::detail::_buffer_size()>{})
36 | #define xorstr_(str) xorstr(str).crypt_get()
37 |
38 | #ifdef _MSC_VER
39 | #define XORSTR_FORCEINLINE __forceinline
40 | #else
41 | #define XORSTR_FORCEINLINE __attribute__((always_inline)) inline
42 | #endif
43 |
44 | namespace jm {
45 |
46 | namespace detail {
47 |
48 | template
49 | XORSTR_FORCEINLINE constexpr std::size_t _buffer_size()
50 | {
51 | return ((Size / 16) + (Size % 16 != 0)) * 2;
52 | }
53 |
54 | template
55 | XORSTR_FORCEINLINE constexpr std::uint32_t key4() noexcept
56 | {
57 | std::uint32_t value = Seed;
58 | for (char c : __TIME__)
59 | value = static_cast((value ^ c) * 16777619ull);
60 | return value;
61 | }
62 |
63 | template
64 | XORSTR_FORCEINLINE constexpr std::uint64_t key8()
65 | {
66 | constexpr auto first_part = key4<2166136261 + S>();
67 | constexpr auto second_part = key4();
68 | return (static_cast(first_part) << 32) | second_part;
69 | }
70 |
71 | // loads up to 8 characters of string into uint64 and xors it with the key
72 | template
73 | XORSTR_FORCEINLINE constexpr std::uint64_t
74 | load_xored_str8(std::uint64_t key, std::size_t idx, const CharT* str) noexcept
75 | {
76 | using cast_type = typename std::make_unsigned::type;
77 | constexpr auto value_size = sizeof(CharT);
78 | constexpr auto idx_offset = 8 / value_size;
79 |
80 | std::uint64_t value = key;
81 | for (std::size_t i = 0; i < idx_offset && i + idx * idx_offset < N; ++i)
82 | value ^=
83 | (std::uint64_t{ static_cast(str[i + idx * idx_offset]) }
84 | << ((i % idx_offset) * 8 * value_size));
85 |
86 | return value;
87 | }
88 |
89 | // forces compiler to use registers instead of stuffing constants in rdata
90 | XORSTR_FORCEINLINE std::uint64_t load_from_reg(std::uint64_t value) noexcept
91 | {
92 | #if defined(__clang__) || defined(__GNUC__)
93 | asm("" : "=r"(value) : "0"(value) : );
94 | return value;
95 | #else
96 | volatile std::uint64_t reg = value;
97 | return reg;
98 | #endif
99 | }
100 |
101 | } // namespace detail
102 |
103 | template
104 | class xor_string;
105 |
106 | template
107 | class xor_string, std::index_sequence> {
108 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS
109 | constexpr static inline std::uint64_t alignment = ((Size > 16) ? 32 : 16);
110 | #else
111 | constexpr static inline std::uint64_t alignment = 16;
112 | #endif
113 |
114 | alignas(alignment) std::uint64_t _storage[sizeof...(Keys)];
115 |
116 | public:
117 | using value_type = CharT;
118 | using size_type = std::size_t;
119 | using pointer = CharT*;
120 | using const_pointer = const CharT*;
121 |
122 | template
123 | XORSTR_FORCEINLINE xor_string(L l, std::integral_constant, std::index_sequence) noexcept
124 | : _storage{ ::jm::detail::load_from_reg((std::integral_constant(Keys, Indices, l())>::value))... }
125 | {}
126 |
127 | XORSTR_FORCEINLINE constexpr size_type size() const noexcept
128 | {
129 | return Size - 1;
130 | }
131 |
132 | XORSTR_FORCEINLINE void crypt() noexcept
133 | {
134 | // everything is inlined by hand because a certain compiler with a certain linker is _very_ slow
135 | #if defined(__clang__)
136 | alignas(alignment)
137 | std::uint64_t arr[]{ ::jm::detail::load_from_reg(Keys)... };
138 | std::uint64_t* keys =
139 | (std::uint64_t*)::jm::detail::load_from_reg((std::uint64_t)arr);
140 | #else
141 | alignas(alignment) std::uint64_t keys[]{ ::jm::detail::load_from_reg(Keys)... };
142 | #endif
143 |
144 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__)
145 | #if defined(__clang__)
146 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : __builtin_neon_vst1q_v(
147 | reinterpret_cast(_storage) + Indices * 2,
148 | veorq_u64(__builtin_neon_vld1q_v(reinterpret_cast(_storage) + Indices * 2, 51),
149 | __builtin_neon_vld1q_v(reinterpret_cast(keys) + Indices * 2, 51)),
150 | 51)), ...);
151 | #else // GCC, MSVC
152 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : vst1q_u64(
153 | reinterpret_cast(_storage) + Indices * 2,
154 | veorq_u64(vld1q_u64(reinterpret_cast(_storage) + Indices * 2),
155 | vld1q_u64(reinterpret_cast(keys) + Indices * 2)))), ...);
156 | #endif
157 | #elif !defined(JM_XORSTR_DISABLE_AVX_INTRINSICS)
158 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256(
159 | reinterpret_cast<__m256i*>(_storage) + Indices,
160 | _mm256_xor_si256(
161 | _mm256_load_si256(reinterpret_cast(_storage) + Indices),
162 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...);
163 |
164 | if constexpr (sizeof(_storage) % 32 != 0)
165 | _mm_store_si128(
166 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2),
167 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)),
168 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2))));
169 | #else
170 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128(
171 | reinterpret_cast<__m128i*>(_storage) + Indices,
172 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices),
173 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...);
174 | #endif
175 | }
176 |
177 | XORSTR_FORCEINLINE const_pointer get() const noexcept
178 | {
179 | return reinterpret_cast(_storage);
180 | }
181 |
182 | XORSTR_FORCEINLINE pointer get() noexcept
183 | {
184 | return reinterpret_cast(_storage);
185 | }
186 |
187 | XORSTR_FORCEINLINE pointer crypt_get() noexcept
188 | {
189 | // crypt() is inlined by hand because a certain compiler with a certain linker is _very_ slow
190 | #if defined(__clang__)
191 | alignas(alignment)
192 | std::uint64_t arr[]{ ::jm::detail::load_from_reg(Keys)... };
193 | std::uint64_t* keys =
194 | (std::uint64_t*)::jm::detail::load_from_reg((std::uint64_t)arr);
195 | #else
196 | alignas(alignment) std::uint64_t keys[]{ ::jm::detail::load_from_reg(Keys)... };
197 | #endif
198 |
199 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__)
200 | #if defined(__clang__)
201 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : __builtin_neon_vst1q_v(
202 | reinterpret_cast(_storage) + Indices * 2,
203 | veorq_u64(__builtin_neon_vld1q_v(reinterpret_cast(_storage) + Indices * 2, 51),
204 | __builtin_neon_vld1q_v(reinterpret_cast(keys) + Indices * 2, 51)),
205 | 51)), ...);
206 | #else // GCC, MSVC
207 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : vst1q_u64(
208 | reinterpret_cast(_storage) + Indices * 2,
209 | veorq_u64(vld1q_u64(reinterpret_cast(_storage) + Indices * 2),
210 | vld1q_u64(reinterpret_cast(keys) + Indices * 2)))), ...);
211 | #endif
212 | #elif !defined(JM_XORSTR_DISABLE_AVX_INTRINSICS)
213 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256(
214 | reinterpret_cast<__m256i*>(_storage) + Indices,
215 | _mm256_xor_si256(
216 | _mm256_load_si256(reinterpret_cast(_storage) + Indices),
217 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...);
218 |
219 | if constexpr (sizeof(_storage) % 32 != 0)
220 | _mm_store_si128(
221 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2),
222 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)),
223 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2))));
224 | #else
225 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128(
226 | reinterpret_cast<__m128i*>(_storage) + Indices,
227 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices),
228 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...);
229 | #endif
230 |
231 | return (pointer)(_storage);
232 | }
233 | };
234 |
235 | template
236 | xor_string(L l, std::integral_constant, std::index_sequence)->xor_string<
237 | std::remove_const_t>,
238 | Size,
239 | std::integer_sequence()...>,
240 | std::index_sequence>;
241 |
242 | } // namespace jm
243 |
244 | #endif // include guard
--------------------------------------------------------------------------------
/includes.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 | #pragma comment(lib,"d3d9.lib")
17 |
18 | #include
19 | #include
20 | #include
21 | #include
--------------------------------------------------------------------------------
/injector.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace injector {
6 |
7 | namespace data {
8 | inline HANDLE handle = INVALID_HANDLE_VALUE;
9 | inline uint32_t process_id = 0;
10 | }
11 |
12 | inline uint32_t find_process_id(const char* name) {
13 |
14 | HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
15 | PROCESSENTRY32 pe32{ sizeof(PROCESSENTRY32) };
16 |
17 | Process32First(snapshot, &pe32);
18 | while (Process32Next(snapshot, &pe32)) {
19 | if (strcmp(pe32.szExeFile, name) == 0) {
20 | CloseHandle(snapshot);
21 | return static_cast(pe32.th32ProcessID);
22 | }
23 | }
24 |
25 | CloseHandle(snapshot);
26 | return 0;
27 | }
28 |
29 | inline bool inject(const char* name, const char* file_path) {
30 |
31 | data::process_id = find_process_id(name);
32 | if (!data::process_id)
33 | return false;
34 |
35 | std::vector buffer;
36 | std::ifstream file_ifstream(file_path, std::ios::binary);
37 |
38 | if (!file_ifstream)
39 | return false;
40 |
41 | buffer.assign((std::istreambuf_iterator(file_ifstream)), std::istreambuf_iterator());
42 | file_ifstream.close();
43 |
44 | data::handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, data::process_id);
45 | if (!data::handle || data::handle == INVALID_HANDLE_VALUE)
46 | return false;
47 |
48 | int length = strlen(file_path);
49 |
50 | void* allocated_memory = VirtualAllocEx(data::handle, 0, length + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
51 | if (!allocated_memory)
52 | return false;
53 |
54 | if (!WriteProcessMemory(data::handle, 0, file_path, (length + 1), 0))
55 | return false;
56 |
57 | HANDLE thread = CreateRemoteThread(data::handle, 0, 0, reinterpret_cast(LoadLibraryA), allocated_memory, 0, 0);
58 | if (!thread || thread == INVALID_HANDLE_VALUE)
59 | return false;
60 |
61 | WaitForSingleObject(thread, INFINITE);
62 | VirtualFreeEx(data::handle, allocated_memory, length + 1, MEM_RELEASE);
63 |
64 | CloseHandle(data::handle);
65 | CloseHandle(thread);
66 | return true;
67 | }
68 | }
--------------------------------------------------------------------------------
/menu.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace Menu {
7 |
8 | typedef struct ProductVariable {
9 | std::string name;
10 | std::string process_identifier;
11 | };
12 |
13 | typedef struct Variables {
14 | std::vector products = {
15 | { xorstr_("FiveM"), xorstr_("FiveM_GTAProcess.exe") },
16 | { xorstr_("Overwatch"), xorstr_("overwatch.exe") },
17 | { xorstr_("Warzone"), xorstr_("cod.exe") }
18 | };
19 |
20 | int selected = 0;
21 | };
22 |
23 | inline Variables* Data = nullptr;
24 |
25 | inline bool Initialize() {
26 |
27 | Data = new Variables;
28 |
29 | ImGuiIO& io = ImGui::GetIO();
30 | ImGuiStyle& style = ImGui::GetStyle();
31 |
32 | const auto size = sizeof(style.Colors) / sizeof(style.Colors[0]);
33 | ImVec4(&colors)[size] = style.Colors;
34 |
35 | style.WindowTitleAlign = ImVec2(0.5f, 0.5f);
36 |
37 | colors[ImGuiCol_TitleBg] = ImColor(40, 40, 40);
38 | colors[ImGuiCol_TitleBgActive] = ImColor(40, 40, 40);
39 | colors[ImGuiCol_TitleBgCollapsed] = ImColor(40, 40, 40);
40 |
41 | colors[ImGuiCol_FrameBg] = ImColor(24, 24, 24);
42 | colors[ImGuiCol_FrameBgActive] = ImColor(26, 26, 26);
43 | colors[ImGuiCol_FrameBgHovered] = ImColor(26, 26, 26);
44 |
45 | colors[ImGuiCol_Header] = ImColor(50, 50, 50);
46 | colors[ImGuiCol_HeaderActive] = ImColor(50, 50, 50);
47 | colors[ImGuiCol_HeaderHovered] = ImColor(50, 50, 50);
48 |
49 | colors[ImGuiCol_Button] = ImColor(26, 26, 26);
50 | colors[ImGuiCol_ButtonActive] = ImColor(26, 26, 26);
51 | colors[ImGuiCol_ButtonHovered] = ImColor(26, 26, 26);
52 |
53 | return true;
54 | }
55 |
56 | inline void Render() {
57 |
58 | const int flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize;
59 |
60 | ImGui::SetNextWindowSize(ImVec2(250, 300));
61 |
62 | ImGui::Begin(xorstr_("Launcher"), 0, flags);
63 |
64 | const ImVec2 avail = ImGui::GetContentRegionAvail();
65 | const float padding = 16.0f;
66 |
67 | ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + padding, ImGui::GetCursorPosY() + padding));
68 |
69 | ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
70 | ImGui::ListBoxHeader(xorstr_("##listbox_header"), ImVec2(avail.x - (padding * 2.0f), avail.y - (padding * 4.0f)));
71 |
72 | for (int index = 0;
73 | index < Data->products.size(); index++) {
74 |
75 | bool selected = (index == Data->selected);
76 |
77 | std::string& name = Data->products[index].name;
78 |
79 | ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f, 0.5f));
80 | if (ImGui::Selectable(name.c_str(), &selected))
81 | Data->selected = index;
82 | ImGui::PopStyleVar();
83 |
84 | if (selected)
85 | ImGui::SetItemDefaultFocus();
86 | }
87 |
88 | ImGui::ListBoxFooter();
89 |
90 | ImVec2 button_size = { avail.x - (padding * 2.0f), 24.0f };
91 | static std::string launch_result = {};
92 |
93 | ImGui::SetCursorPosX(ImGui::GetCursorPosX() + padding);
94 | if (ImGui::Button(std::string("Launch ").append(launch_result).c_str(), button_size)) {
95 |
96 | const auto& product = Data->products[Data->selected];
97 | static std::string file_path = "C:\\Example.dll";
98 |
99 | bool success = injector::inject(product.process_identifier.c_str(), file_path.c_str());
100 | launch_result = (success ? "(Success)" : "(Failed)");
101 |
102 | }
103 |
104 | ImGui::PopStyleVar();
105 | ImGui::End();
106 |
107 | }
108 | }
--------------------------------------------------------------------------------
/source.cpp:
--------------------------------------------------------------------------------
1 | #include "source.hpp"
2 | #include "fonts.hpp"
3 | #include "menu.hpp"
4 | #include "util.hpp"
5 |
6 | /*
7 | Make sure to compile on x64 DEBUG/RELEASE.
8 | Enjoy! xo1337.
9 |
10 | Credits:
11 | - https://github.com/noteffex/ImGui-Loader-Base/ (External ImGui)
12 | - https://github.com/JustasMasiulis/xorstr (JustasMasiulis, xorstr_)
13 | */
14 |
15 | int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
16 | {
17 | std::string random_title = util::rand_str(16);
18 |
19 | WNDCLASSEX window_class = {
20 | sizeof(WNDCLASSEX),
21 | CS_CLASSDC,
22 | [](HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)->LRESULT {
23 | if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
24 | return true;
25 |
26 | switch (msg)
27 | {
28 | case WM_SIZE:
29 | if (device_handle != 0 && wParam != SIZE_MINIMIZED)
30 | {
31 | device_parameters.BackBufferWidth = LOWORD(lParam);
32 | device_parameters.BackBufferHeight = HIWORD(lParam);
33 | ResetDevice();
34 | }
35 | return 0;
36 | case WM_SYSCOMMAND:
37 | if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
38 | return 0;
39 | break;
40 | case WM_DESTROY:
41 | ExitProcess(0);
42 | return 0;
43 | }
44 | return DefWindowProcA(hWnd, msg, wParam, lParam);
45 | },
46 | 0L,
47 | 0L,
48 | GetModuleHandleA(0),
49 | 0,
50 | 0,
51 | 0,
52 | 0,
53 | random_title.c_str(),
54 | 0
55 | };
56 |
57 | RegisterClassExA(&window_class);
58 | window_handle = CreateWindowExA(0, window_class.lpszClassName, random_title.c_str(), WS_POPUP, 0, 0, 5, 5, 0, 0, window_class.hInstance, 0);
59 |
60 | if (!CreateDeviceD3D(window_handle))
61 | {
62 | CleanupDeviceD3D();
63 | UnregisterClassA(window_class.lpszClassName, window_class.hInstance);
64 | return 1;
65 | }
66 |
67 | ShowWindow(window_handle, SW_HIDE);
68 | UpdateWindow(window_handle);
69 |
70 | ImGui::CreateContext();
71 |
72 | ImGuiIO& io = ImGui::GetIO();
73 | io.IniFilename = nullptr;
74 | io.LogFilename = nullptr;
75 | io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
76 |
77 | static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 };
78 | ImFontConfig icons_config;
79 |
80 | io.IniFilename = nullptr;
81 | io.LogFilename = nullptr;
82 |
83 | icons_config.MergeMode = true;
84 | icons_config.PixelSnapH = true;
85 | icons_config.OversampleH = 3;
86 | icons_config.OversampleV = 3;
87 |
88 | ImFontConfig rubik;
89 | rubik.FontDataOwnedByAtlas = false;
90 |
91 | io.Fonts->AddFontFromMemoryTTF(const_cast(font_rubik), sizeof(font_rubik), 19.5, &rubik);
92 | io.Fonts->AddFontFromMemoryCompressedTTF(font_awesome_data, font_awesome_size, 32.5f, &icons_config, icons_ranges);
93 | io.Fonts->AddFontDefault();
94 |
95 | ImGuiStyle& style = ImGui::GetStyle();
96 | if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
97 | {
98 | style.WindowRounding = 0.0f;
99 | style.Colors[ImGuiCol_WindowBg].w = 1.0f;
100 | }
101 |
102 | if (!Menu::Initialize())
103 | {
104 | CleanupDeviceD3D();
105 | UnregisterClassA(window_class.lpszClassName, window_class.hInstance);
106 | return 1;
107 | }
108 |
109 | ImGui_ImplWin32_Init(window_handle);
110 | ImGui_ImplDX9_Init(device_handle);
111 |
112 | while (true)
113 | {
114 | MSG message;
115 | if (PeekMessageA(&message, 0, 0U, 0U, PM_REMOVE))
116 | {
117 | TranslateMessage(&message);
118 | DispatchMessageA(&message);
119 | continue;
120 | }
121 |
122 | if (message.message == WM_QUIT)
123 | break;
124 |
125 | ImGui_ImplDX9_NewFrame();
126 | ImGui_ImplWin32_NewFrame();
127 | ImGui::NewFrame();
128 |
129 | Menu::Render();
130 |
131 | ImGui::EndFrame();
132 |
133 | device_handle->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
134 | if (device_handle->BeginScene() >= 0)
135 | {
136 | ImGui::Render();
137 | ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
138 | device_handle->EndScene();
139 | }
140 |
141 | if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
142 | {
143 | ImGui::UpdatePlatformWindows();
144 | ImGui::RenderPlatformWindowsDefault();
145 | }
146 |
147 | HRESULT result = device_handle->Present(0, 0, 0, 0);
148 | if (result == D3DERR_DEVICELOST && device_handle->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) {
149 | ResetDevice();
150 | }
151 | }
152 |
153 | return 0;
154 | }
155 |
--------------------------------------------------------------------------------
/source.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | HWND window_handle;
5 | LPDIRECT3DDEVICE9 device_handle;
6 | D3DPRESENT_PARAMETERS device_parameters;
7 | LPDIRECT3D9 device_direct;
8 |
9 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
10 | LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
11 |
12 | const int WINDOW_WIDTH = 1200;
13 | const int WINDOW_HEIGHT = 800;
14 |
15 | bool CreateDeviceD3D(HWND hWnd)
16 | {
17 | if ((device_direct = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
18 | return false;
19 |
20 | memset(&device_parameters, 0, sizeof(device_parameters));
21 |
22 | device_parameters.Windowed = TRUE;
23 | device_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
24 | device_parameters.BackBufferFormat = D3DFMT_UNKNOWN;
25 | device_parameters.EnableAutoDepthStencil = TRUE;
26 | device_parameters.AutoDepthStencilFormat = D3DFMT_D16;
27 | device_parameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
28 |
29 | if (device_direct->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &device_parameters, &device_handle) < 0)
30 | return false;
31 |
32 | return true;
33 | }
34 |
35 | void CleanupDeviceD3D()
36 | {
37 | if (device_handle)
38 | {
39 | device_handle->Release();
40 | device_handle = 0;
41 | }
42 |
43 | if (device_direct)
44 | {
45 | device_direct->Release();
46 | device_direct = 0;
47 | }
48 | }
49 |
50 | void ResetDevice()
51 | {
52 | ImGui_ImplDX9_InvalidateDeviceObjects();
53 | device_handle->Reset(&device_parameters);
54 | ImGui_ImplDX9_CreateDeviceObjects();
55 | }
--------------------------------------------------------------------------------
/util.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace util {
6 |
7 | std::string rand_str(std::size_t length) {
8 | static std::string characters = xorstr_("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
9 |
10 | std::random_device rd;
11 | std::mt19937 generator(rd());
12 | std::uniform_int_distribution distribution(0, sizeof(characters) - 2);
13 |
14 | std::string string;
15 | for (std::size_t i = 0; i < length; ++i)
16 | string += characters[distribution(generator)];
17 |
18 | return string;
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/xorstr.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 - 2021 Justas Masiulis
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #define JM_XORSTR_DISABLE_AVX_INTRINSICS
18 |
19 | #ifndef JM_XORSTR_HPP
20 | #define JM_XORSTR_HPP
21 |
22 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__)
23 | #include
24 | #elif defined(_M_X64) || defined(__amd64__) || defined(_M_IX86) || defined(__i386__)
25 | #include
26 | #else
27 | #error Unsupported platform
28 | #endif
29 |
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #define xorstr(str) ::jm::xor_string([]() { return str; }, std::integral_constant{}, std::make_index_sequence<::jm::detail::_buffer_size()>{})
36 | #define xorstr_(str) xorstr(str).crypt_get()
37 |
38 | #ifdef _MSC_VER
39 | #define XORSTR_FORCEINLINE __forceinline
40 | #else
41 | #define XORSTR_FORCEINLINE __attribute__((always_inline)) inline
42 | #endif
43 |
44 | namespace jm {
45 |
46 | namespace detail {
47 |
48 | template
49 | XORSTR_FORCEINLINE constexpr std::size_t _buffer_size()
50 | {
51 | return ((Size / 16) + (Size % 16 != 0)) * 2;
52 | }
53 |
54 | template
55 | XORSTR_FORCEINLINE constexpr std::uint32_t key4() noexcept
56 | {
57 | std::uint32_t value = Seed;
58 | for (char c : __TIME__)
59 | value = static_cast((value ^ c) * 16777619ull);
60 | return value;
61 | }
62 |
63 | template
64 | XORSTR_FORCEINLINE constexpr std::uint64_t key8()
65 | {
66 | constexpr auto first_part = key4<2166136261 + S>();
67 | constexpr auto second_part = key4();
68 | return (static_cast(first_part) << 32) | second_part;
69 | }
70 |
71 | // loads up to 8 characters of string into uint64 and xors it with the key
72 | template
73 | XORSTR_FORCEINLINE constexpr std::uint64_t
74 | load_xored_str8(std::uint64_t key, std::size_t idx, const CharT* str) noexcept
75 | {
76 | using cast_type = typename std::make_unsigned::type;
77 | constexpr auto value_size = sizeof(CharT);
78 | constexpr auto idx_offset = 8 / value_size;
79 |
80 | std::uint64_t value = key;
81 | for (std::size_t i = 0; i < idx_offset && i + idx * idx_offset < N; ++i)
82 | value ^=
83 | (std::uint64_t{ static_cast(str[i + idx * idx_offset]) }
84 | << ((i % idx_offset) * 8 * value_size));
85 |
86 | return value;
87 | }
88 |
89 | // forces compiler to use registers instead of stuffing constants in rdata
90 | XORSTR_FORCEINLINE std::uint64_t load_from_reg(std::uint64_t value) noexcept
91 | {
92 | #if defined(__clang__) || defined(__GNUC__)
93 | asm("" : "=r"(value) : "0"(value) : );
94 | return value;
95 | #else
96 | volatile std::uint64_t reg = value;
97 | return reg;
98 | #endif
99 | }
100 |
101 | } // namespace detail
102 |
103 | template
104 | class xor_string;
105 |
106 | template
107 | class xor_string, std::index_sequence> {
108 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS
109 | constexpr static inline std::uint64_t alignment = ((Size > 16) ? 32 : 16);
110 | #else
111 | constexpr static inline std::uint64_t alignment = 16;
112 | #endif
113 |
114 | alignas(alignment) std::uint64_t _storage[sizeof...(Keys)];
115 |
116 | public:
117 | using value_type = CharT;
118 | using size_type = std::size_t;
119 | using pointer = CharT*;
120 | using const_pointer = const CharT*;
121 |
122 | template
123 | XORSTR_FORCEINLINE xor_string(L l, std::integral_constant, std::index_sequence) noexcept
124 | : _storage{ ::jm::detail::load_from_reg((std::integral_constant(Keys, Indices, l())>::value))... }
125 | {}
126 |
127 | XORSTR_FORCEINLINE constexpr size_type size() const noexcept
128 | {
129 | return Size - 1;
130 | }
131 |
132 | XORSTR_FORCEINLINE void crypt() noexcept
133 | {
134 | // everything is inlined by hand because a certain compiler with a certain linker is _very_ slow
135 | #if defined(__clang__)
136 | alignas(alignment)
137 | std::uint64_t arr[]{ ::jm::detail::load_from_reg(Keys)... };
138 | std::uint64_t* keys =
139 | (std::uint64_t*)::jm::detail::load_from_reg((std::uint64_t)arr);
140 | #else
141 | alignas(alignment) std::uint64_t keys[]{ ::jm::detail::load_from_reg(Keys)... };
142 | #endif
143 |
144 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__)
145 | #if defined(__clang__)
146 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : __builtin_neon_vst1q_v(
147 | reinterpret_cast(_storage) + Indices * 2,
148 | veorq_u64(__builtin_neon_vld1q_v(reinterpret_cast(_storage) + Indices * 2, 51),
149 | __builtin_neon_vld1q_v(reinterpret_cast(keys) + Indices * 2, 51)),
150 | 51)), ...);
151 | #else // GCC, MSVC
152 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : vst1q_u64(
153 | reinterpret_cast(_storage) + Indices * 2,
154 | veorq_u64(vld1q_u64(reinterpret_cast(_storage) + Indices * 2),
155 | vld1q_u64(reinterpret_cast(keys) + Indices * 2)))), ...);
156 | #endif
157 | #elif !defined(JM_XORSTR_DISABLE_AVX_INTRINSICS)
158 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256(
159 | reinterpret_cast<__m256i*>(_storage) + Indices,
160 | _mm256_xor_si256(
161 | _mm256_load_si256(reinterpret_cast(_storage) + Indices),
162 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...);
163 |
164 | if constexpr (sizeof(_storage) % 32 != 0)
165 | _mm_store_si128(
166 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2),
167 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)),
168 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2))));
169 | #else
170 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128(
171 | reinterpret_cast<__m128i*>(_storage) + Indices,
172 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices),
173 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...);
174 | #endif
175 | }
176 |
177 | XORSTR_FORCEINLINE const_pointer get() const noexcept
178 | {
179 | return reinterpret_cast(_storage);
180 | }
181 |
182 | XORSTR_FORCEINLINE pointer get() noexcept
183 | {
184 | return reinterpret_cast(_storage);
185 | }
186 |
187 | XORSTR_FORCEINLINE pointer crypt_get() noexcept
188 | {
189 | // crypt() is inlined by hand because a certain compiler with a certain linker is _very_ slow
190 | #if defined(__clang__)
191 | alignas(alignment)
192 | std::uint64_t arr[]{ ::jm::detail::load_from_reg(Keys)... };
193 | std::uint64_t* keys =
194 | (std::uint64_t*)::jm::detail::load_from_reg((std::uint64_t)arr);
195 | #else
196 | alignas(alignment) std::uint64_t keys[]{ ::jm::detail::load_from_reg(Keys)... };
197 | #endif
198 |
199 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__)
200 | #if defined(__clang__)
201 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : __builtin_neon_vst1q_v(
202 | reinterpret_cast(_storage) + Indices * 2,
203 | veorq_u64(__builtin_neon_vld1q_v(reinterpret_cast(_storage) + Indices * 2, 51),
204 | __builtin_neon_vld1q_v(reinterpret_cast(keys) + Indices * 2, 51)),
205 | 51)), ...);
206 | #else // GCC, MSVC
207 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : vst1q_u64(
208 | reinterpret_cast(_storage) + Indices * 2,
209 | veorq_u64(vld1q_u64(reinterpret_cast(_storage) + Indices * 2),
210 | vld1q_u64(reinterpret_cast(keys) + Indices * 2)))), ...);
211 | #endif
212 | #elif !defined(JM_XORSTR_DISABLE_AVX_INTRINSICS)
213 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256(
214 | reinterpret_cast<__m256i*>(_storage) + Indices,
215 | _mm256_xor_si256(
216 | _mm256_load_si256(reinterpret_cast(_storage) + Indices),
217 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...);
218 |
219 | if constexpr (sizeof(_storage) % 32 != 0)
220 | _mm_store_si128(
221 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2),
222 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)),
223 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2))));
224 | #else
225 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128(
226 | reinterpret_cast<__m128i*>(_storage) + Indices,
227 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices),
228 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...);
229 | #endif
230 |
231 | return (pointer)(_storage);
232 | }
233 | };
234 |
235 | template
236 | xor_string(L l, std::integral_constant, std::index_sequence)->xor_string<
237 | std::remove_const_t>,
238 | Size,
239 | std::integer_sequence()...>,
240 | std::index_sequence>;
241 |
242 | } // namespace jm
243 |
244 | #endif // include guard
--------------------------------------------------------------------------------