initial
This commit is contained in:
parent
a5d022e7fc
commit
8e30b0033d
370
main.cpp
Normal file
370
main.cpp
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_win32.h"
|
||||||
|
#include "imgui_impl_dx11.h"
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include "comfortaa.h"
|
||||||
|
#include "dripicons.h"
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
#include "imgs.h"
|
||||||
|
|
||||||
|
|
||||||
|
static ID3D11Device* g_pd3dDevice = nullptr;
|
||||||
|
static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr;
|
||||||
|
static IDXGISwapChain* g_pSwapChain = nullptr;
|
||||||
|
static bool g_SwapChainOccluded = false;
|
||||||
|
static UINT g_ResizeWidth = 0, g_ResizeHeight = 0;
|
||||||
|
static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
bool CreateDeviceD3D(HWND hWnd);
|
||||||
|
void CleanupDeviceD3D();
|
||||||
|
void CreateRenderTarget();
|
||||||
|
void CleanupRenderTarget();
|
||||||
|
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
void drawWatermark() {
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(300, 80), ImGuiCond_Always);
|
||||||
|
ImGui::Begin("waterpula", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground);
|
||||||
|
|
||||||
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||||
|
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||||
|
float width = 610;
|
||||||
|
float thickness = 8.0f;
|
||||||
|
|
||||||
|
ImU32 start = IM_COL32(156, 156, 156, 1);
|
||||||
|
ImU32 end = IM_COL32(0, 0, 0, 1);
|
||||||
|
|
||||||
|
draw_list->AddRectFilledMultiColor(
|
||||||
|
ImVec2(p.x, p.y),
|
||||||
|
ImVec2(p.x + width, p.y + thickness),
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
end,
|
||||||
|
start
|
||||||
|
);
|
||||||
|
|
||||||
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + thickness + 4);
|
||||||
|
ImGui::Text("racism enabled");
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**)
|
||||||
|
{
|
||||||
|
|
||||||
|
WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"racism panel", nullptr };
|
||||||
|
::RegisterClassExW(&wc);
|
||||||
|
HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_NOACTIVATE, _T("racism panel"), NULL, WS_POPUP, 0, 0, 1920, 1080, NULL, NULL, wc.hInstance, NULL);
|
||||||
|
SetLayeredWindowAttributes(hwnd, RGB(0,0,0), 0, ULW_COLORKEY);
|
||||||
|
|
||||||
|
// Initialize Direct3D
|
||||||
|
if (!CreateDeviceD3D(hwnd))
|
||||||
|
{
|
||||||
|
CleanupDeviceD3D();
|
||||||
|
::UnregisterClassW(wc.lpszClassName, wc.hInstance);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the window
|
||||||
|
::ShowWindow(hwnd, SW_SHOWDEFAULT);
|
||||||
|
::UpdateWindow(hwnd);
|
||||||
|
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||||
|
|
||||||
|
|
||||||
|
ImGui::StyleColorsDark();
|
||||||
|
|
||||||
|
ImGui_ImplWin32_Init(hwnd);
|
||||||
|
ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
|
||||||
|
|
||||||
|
ImFontConfig font_cfg;
|
||||||
|
font_cfg.FontDataOwnedByAtlas = false;
|
||||||
|
|
||||||
|
ImFontConfig fonticon_cfg;
|
||||||
|
fonticon_cfg.PixelSnapH = true;
|
||||||
|
fonticon_cfg.FontDataOwnedByAtlas = false;
|
||||||
|
|
||||||
|
ImFont* mainfont = io.Fonts->AddFontFromMemoryTTF(comfortaa, comfortaaSize, 15.0f, &font_cfg);
|
||||||
|
ImFont* iconfont = io.Fonts->AddFontFromMemoryTTF(dripicons, dripiconsSize, 20.0f);
|
||||||
|
|
||||||
|
ImVec4* colors = ImGui::GetStyle().Colors;
|
||||||
|
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||||
|
colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
|
||||||
|
colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
|
||||||
|
//colors[ImGuiCol_WindowBg] = ImVec4(0.44f, 0.44f, 0.44f, 0.40f);
|
||||||
|
colors[ImGuiCol_ChildBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.00f);
|
||||||
|
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
|
||||||
|
colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
|
||||||
|
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||||
|
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f);
|
||||||
|
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.40f);
|
||||||
|
colors[ImGuiCol_FrameBgActive] = ImVec4(0.18f, 0.18f, 0.18f, 0.67f);
|
||||||
|
colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
|
||||||
|
colors[ImGuiCol_TitleBgActive] = ImVec4(0.29f, 0.29f, 0.29f, 1.00f);
|
||||||
|
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
|
||||||
|
colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
|
||||||
|
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
|
||||||
|
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
|
||||||
|
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
|
||||||
|
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
|
||||||
|
colors[ImGuiCol_CheckMark] = ImVec4(0.94f, 0.94f, 0.94f, 1.00f);
|
||||||
|
colors[ImGuiCol_SliderGrab] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
|
||||||
|
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
|
||||||
|
colors[ImGuiCol_Button] = ImVec4(0.44f, 0.44f, 0.44f, 0.40f);
|
||||||
|
colors[ImGuiCol_ButtonHovered] = ImVec4(0.46f, 0.47f, 0.48f, 1.00f);
|
||||||
|
colors[ImGuiCol_ButtonActive] = ImVec4(0.42f, 0.42f, 0.42f, 1.00f);
|
||||||
|
colors[ImGuiCol_Header] = ImVec4(0.70f, 0.70f, 0.70f, 0.31f);
|
||||||
|
colors[ImGuiCol_HeaderHovered] = ImVec4(0.70f, 0.70f, 0.70f, 0.80f);
|
||||||
|
colors[ImGuiCol_HeaderActive] = ImVec4(0.48f, 0.50f, 0.52f, 1.00f);
|
||||||
|
colors[ImGuiCol_Separator] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
|
||||||
|
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.72f, 0.72f, 0.72f, 0.78f);
|
||||||
|
colors[ImGuiCol_SeparatorActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
|
||||||
|
colors[ImGuiCol_ResizeGrip] = ImVec4(0.91f, 0.91f, 0.91f, 0.25f);
|
||||||
|
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.81f, 0.81f, 0.81f, 0.67f);
|
||||||
|
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.46f, 0.46f, 0.46f, 0.95f);
|
||||||
|
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||||
|
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
||||||
|
colors[ImGuiCol_PlotHistogram] = ImVec4(0.73f, 0.60f, 0.15f, 1.00f);
|
||||||
|
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
||||||
|
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.87f, 0.87f, 0.87f, 0.35f);
|
||||||
|
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
||||||
|
colors[ImGuiCol_NavHighlight] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
|
||||||
|
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
||||||
|
colors[ImGuiCol_Tab] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
|
||||||
|
colors[ImGuiCol_TabActive] = ImVec4(0.70f, 0.70f, 0.70f, 0.31f);
|
||||||
|
colors[ImGuiCol_TabHovered] = ImVec4(0.70f, 0.70f, 0.70f, 0.31f);
|
||||||
|
auto& style = ImGui::GetStyle();
|
||||||
|
style.WindowRounding = 7.00f;
|
||||||
|
|
||||||
|
bool disable_france = false;
|
||||||
|
bool show_output = false;
|
||||||
|
int time = 0;
|
||||||
|
|
||||||
|
unsigned char* rgba_data = stbi_load_from_memory(kup_data, sizeof(kup_data), &kup_img_width, &kup_img_height, &channels, 4);
|
||||||
|
|
||||||
|
ID3D11ShaderResourceView* kup = nullptr;
|
||||||
|
|
||||||
|
D3D11_TEXTURE2D_DESC desc = {};
|
||||||
|
desc.Width = kup_img_width;
|
||||||
|
desc.Height = kup_img_height;
|
||||||
|
desc.MipLevels = 1;
|
||||||
|
desc.ArraySize = 1;
|
||||||
|
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
|
||||||
|
D3D11_SUBRESOURCE_DATA subResource = {};
|
||||||
|
subResource.pSysMem = rgba_data;
|
||||||
|
subResource.SysMemPitch = kup_img_width * 4;
|
||||||
|
|
||||||
|
ID3D11Texture2D* pTexture = nullptr;
|
||||||
|
HRESULT hr = g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||||
|
srvDesc.Format = desc.Format;
|
||||||
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||||
|
srvDesc.Texture2D.MipLevels = 1;
|
||||||
|
|
||||||
|
hr = g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &kup);
|
||||||
|
|
||||||
|
pTexture->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
stbi_image_free(rgba_data);
|
||||||
|
|
||||||
|
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||||
|
bool done = false;
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
|
||||||
|
MSG msg;
|
||||||
|
while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
|
||||||
|
{
|
||||||
|
::TranslateMessage(&msg);
|
||||||
|
::DispatchMessage(&msg);
|
||||||
|
if (msg.message == WM_QUIT)
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
|
||||||
|
{
|
||||||
|
::Sleep(10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g_SwapChainOccluded = false;
|
||||||
|
|
||||||
|
if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
|
||||||
|
{
|
||||||
|
CleanupRenderTarget();
|
||||||
|
g_pSwapChain->ResizeBuffers(0, g_ResizeWidth, g_ResizeHeight, DXGI_FORMAT_UNKNOWN, 0);
|
||||||
|
g_ResizeWidth = g_ResizeHeight = 0;
|
||||||
|
CreateRenderTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplDX11_NewFrame();
|
||||||
|
ImGui_ImplWin32_NewFrame();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
drawWatermark();
|
||||||
|
|
||||||
|
ImGui::PushFont(mainfont);
|
||||||
|
if (ImGui::Begin("racism panel", NULL, ImGuiWindowFlags_NoCollapse)) {
|
||||||
|
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
|
||||||
|
if (ImGui::BeginTabBar("top secret", tab_bar_flags))
|
||||||
|
{
|
||||||
|
if (ImGui::BeginTabItem("top secret"))
|
||||||
|
{
|
||||||
|
ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - ImGui::CalcTextSize("X").x - 10, 23));
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button("close");
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
exit(0);
|
||||||
|
};
|
||||||
|
ImGui::Checkbox("disable france", &disable_france);
|
||||||
|
ImGui::SliderInt("time to disable (in decades)", &time, 0, 31);
|
||||||
|
if (ImGui::Button("show output")) {
|
||||||
|
show_output = true;
|
||||||
|
}
|
||||||
|
ImGui::PushFont(iconfont);
|
||||||
|
ImGui::Text("k");
|
||||||
|
ImGui::PopFont();
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("download badass mafia toolbar"))
|
||||||
|
ImGui::OpenPopup("success");
|
||||||
|
if (ImGui::BeginPopupModal("success", NULL))
|
||||||
|
{
|
||||||
|
ImGui::Text("successfully added badass mafia toolbar to browser.");
|
||||||
|
if (ImGui::Button("Close"))
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
ImGui::Image((void*)kup, ImVec2(kup_img_width, kup_img_height));
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
ImGui::PopFont();
|
||||||
|
|
||||||
|
if (show_output == true) {
|
||||||
|
ImGui::PushFont(mainfont);
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(750, 550));
|
||||||
|
if (ImGui::Begin("output", NULL, ImGuiWindowFlags_NoResize)) {
|
||||||
|
if (ImGui::Button("close")) {
|
||||||
|
show_output = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
ImGui::PopFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Render();
|
||||||
|
const float clear_color_with_alpha[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
|
||||||
|
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
|
||||||
|
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
|
HRESULT hr = g_pSwapChain->Present(1, 0);
|
||||||
|
g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplDX11_Shutdown();
|
||||||
|
ImGui_ImplWin32_Shutdown();
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
CleanupDeviceD3D();
|
||||||
|
::DestroyWindow(hwnd);
|
||||||
|
::UnregisterClassW(wc.lpszClassName, wc.hInstance);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CreateDeviceD3D(HWND hWnd)
|
||||||
|
{
|
||||||
|
DXGI_SWAP_CHAIN_DESC sd;
|
||||||
|
ZeroMemory(&sd, sizeof(sd));
|
||||||
|
sd.BufferCount = 2;
|
||||||
|
sd.BufferDesc.Width = 0;
|
||||||
|
sd.BufferDesc.Height = 0;
|
||||||
|
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
sd.BufferDesc.RefreshRate.Numerator = 60;
|
||||||
|
sd.BufferDesc.RefreshRate.Denominator = 1;
|
||||||
|
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||||
|
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
sd.OutputWindow = hWnd;
|
||||||
|
sd.SampleDesc.Count = 1;
|
||||||
|
sd.SampleDesc.Quality = 0;
|
||||||
|
sd.Windowed = TRUE;
|
||||||
|
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
|
||||||
|
UINT createDeviceFlags = 0;
|
||||||
|
D3D_FEATURE_LEVEL featureLevel;
|
||||||
|
const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
|
||||||
|
HRESULT res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
|
||||||
|
if (res == DXGI_ERROR_UNSUPPORTED)
|
||||||
|
res = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_WARP, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext);
|
||||||
|
if (res != S_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CreateRenderTarget();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanupDeviceD3D()
|
||||||
|
{
|
||||||
|
CleanupRenderTarget();
|
||||||
|
if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = nullptr; }
|
||||||
|
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = nullptr; }
|
||||||
|
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateRenderTarget()
|
||||||
|
{
|
||||||
|
ID3D11Texture2D* pBackBuffer;
|
||||||
|
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
|
||||||
|
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_mainRenderTargetView);
|
||||||
|
pBackBuffer->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanupRenderTarget()
|
||||||
|
{
|
||||||
|
if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = nullptr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_SIZE:
|
||||||
|
if (wParam == SIZE_MINIMIZED)
|
||||||
|
return 0;
|
||||||
|
g_ResizeWidth = (UINT)LOWORD(lParam);
|
||||||
|
g_ResizeHeight = (UINT)HIWORD(lParam);
|
||||||
|
return 0;
|
||||||
|
case WM_SYSCOMMAND:
|
||||||
|
if ((wParam & 0xfff0) == SC_KEYMENU)
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case WM_DESTROY:
|
||||||
|
::PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ::DefWindowProcW(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
31
racism-panel-remake.sln
Normal file
31
racism-panel-remake.sln
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.11.35219.272
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "racism-panel-remake", "racism-panel-remake.vcxproj", "{12477C0F-1542-416C-BE94-7769B6BDE68E}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{12477C0F-1542-416C-BE94-7769B6BDE68E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{12477C0F-1542-416C-BE94-7769B6BDE68E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{12477C0F-1542-416C-BE94-7769B6BDE68E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{12477C0F-1542-416C-BE94-7769B6BDE68E}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{12477C0F-1542-416C-BE94-7769B6BDE68E}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{12477C0F-1542-416C-BE94-7769B6BDE68E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{12477C0F-1542-416C-BE94-7769B6BDE68E}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{12477C0F-1542-416C-BE94-7769B6BDE68E}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {51E832EB-9611-4DEE-8AFE-C605516048B4}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
166
racism-panel-remake.vcxproj
Normal file
166
racism-panel-remake.vcxproj
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>17.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{12477c0f-1542-416c-be94-7769b6bde68e}</ProjectGuid>
|
||||||
|
<RootNamespace>racismpanelremake</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<IncludePath>$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\backend\;$(ProjectDir)vendor\fonts\;$(ProjectDir)vendor\img\;$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<IncludePath>$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\backend\;$(ProjectDir)vendor\fonts\;$(ProjectDir)vendor\img\;$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>d3d11.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>d3d11.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="vendor\backend\imgui_impl_dx11.cpp" />
|
||||||
|
<ClCompile Include="vendor\backend\imgui_impl_win32.cpp" />
|
||||||
|
<ClCompile Include="vendor\imgui\imgui.cpp" />
|
||||||
|
<ClCompile Include="vendor\imgui\imgui_demo.cpp" />
|
||||||
|
<ClCompile Include="vendor\imgui\imgui_draw.cpp" />
|
||||||
|
<ClCompile Include="vendor\imgui\imgui_tables.cpp" />
|
||||||
|
<ClCompile Include="vendor\imgui\imgui_widgets.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="vendor\backend\imgui_impl_dx11.h" />
|
||||||
|
<ClInclude Include="vendor\backend\imgui_impl_win32.h" />
|
||||||
|
<ClInclude Include="vendor\fonts\comfortaa.h" />
|
||||||
|
<ClInclude Include="vendor\fonts\dripicons.h" />
|
||||||
|
<ClInclude Include="vendor\imgui\imconfig.h" />
|
||||||
|
<ClInclude Include="vendor\imgui\imgui.h" />
|
||||||
|
<ClInclude Include="vendor\imgui\imgui_internal.h" />
|
||||||
|
<ClInclude Include="vendor\imgui\imstb_rectpack.h" />
|
||||||
|
<ClInclude Include="vendor\imgui\imstb_textedit.h" />
|
||||||
|
<ClInclude Include="vendor\imgui\imstb_truetype.h" />
|
||||||
|
<ClInclude Include="vendor\imgui\stb_image.h" />
|
||||||
|
<ClInclude Include="vendor\img\imgs.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
81
racism-panel-remake.vcxproj.filters
Normal file
81
racism-panel-remake.vcxproj.filters
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vendor\backend\imgui_impl_dx11.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vendor\backend\imgui_impl_win32.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vendor\imgui\imgui.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vendor\imgui\imgui_demo.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vendor\imgui\imgui_draw.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vendor\imgui\imgui_tables.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="vendor\imgui\imgui_widgets.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="vendor\backend\imgui_impl_dx11.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\backend\imgui_impl_win32.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\imgui\imconfig.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\imgui\imgui.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\imgui\imgui_internal.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\imgui\imstb_rectpack.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\imgui\imstb_textedit.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\imgui\imstb_truetype.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\fonts\comfortaa.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\fonts\dripicons.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\imgui\stb_image.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="vendor\img\imgs.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
6
racism-panel-remake.vcxproj.user
Normal file
6
racism-panel-remake.vcxproj.user
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ShowAllFiles>true</ShowAllFiles>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
606
vendor/backend/imgui_impl_dx11.cpp
vendored
Normal file
606
vendor/backend/imgui_impl_dx11.cpp
vendored
Normal file
@ -0,0 +1,606 @@
|
|||||||
|
// dear imgui: Renderer Backend for DirectX11
|
||||||
|
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||||
|
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
// Learn about Dear ImGui:
|
||||||
|
// - FAQ https://dearimgui.com/faq
|
||||||
|
// - Getting Started https://dearimgui.com/getting-started
|
||||||
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||||
|
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||||
|
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||||
|
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
|
||||||
|
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
|
||||||
|
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
|
||||||
|
// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||||
|
// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||||
|
// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
|
||||||
|
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
|
||||||
|
// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility.
|
||||||
|
// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions.
|
||||||
|
// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example.
|
||||||
|
// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
||||||
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself.
|
||||||
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
|
// 2016-05-07: DirectX11: Disabling depth-write.
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#ifndef IMGUI_DISABLE
|
||||||
|
#include "imgui_impl_dx11.h"
|
||||||
|
|
||||||
|
// DirectX
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <d3dcompiler.h>
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// DirectX11 data
|
||||||
|
struct ImGui_ImplDX11_Data
|
||||||
|
{
|
||||||
|
ID3D11Device* pd3dDevice;
|
||||||
|
ID3D11DeviceContext* pd3dDeviceContext;
|
||||||
|
IDXGIFactory* pFactory;
|
||||||
|
ID3D11Buffer* pVB;
|
||||||
|
ID3D11Buffer* pIB;
|
||||||
|
ID3D11VertexShader* pVertexShader;
|
||||||
|
ID3D11InputLayout* pInputLayout;
|
||||||
|
ID3D11Buffer* pVertexConstantBuffer;
|
||||||
|
ID3D11PixelShader* pPixelShader;
|
||||||
|
ID3D11SamplerState* pFontSampler;
|
||||||
|
ID3D11ShaderResourceView* pFontTextureView;
|
||||||
|
ID3D11RasterizerState* pRasterizerState;
|
||||||
|
ID3D11BlendState* pBlendState;
|
||||||
|
ID3D11DepthStencilState* pDepthStencilState;
|
||||||
|
int VertexBufferSize;
|
||||||
|
int IndexBufferSize;
|
||||||
|
|
||||||
|
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VERTEX_CONSTANT_BUFFER_DX11
|
||||||
|
{
|
||||||
|
float mvp[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
|
||||||
|
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||||
|
static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
|
||||||
|
{
|
||||||
|
return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
|
||||||
|
{
|
||||||
|
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||||
|
|
||||||
|
// Setup viewport
|
||||||
|
D3D11_VIEWPORT vp;
|
||||||
|
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
|
||||||
|
vp.Width = draw_data->DisplaySize.x;
|
||||||
|
vp.Height = draw_data->DisplaySize.y;
|
||||||
|
vp.MinDepth = 0.0f;
|
||||||
|
vp.MaxDepth = 1.0f;
|
||||||
|
vp.TopLeftX = vp.TopLeftY = 0;
|
||||||
|
ctx->RSSetViewports(1, &vp);
|
||||||
|
|
||||||
|
// Setup shader and vertex buffers
|
||||||
|
unsigned int stride = sizeof(ImDrawVert);
|
||||||
|
unsigned int offset = 0;
|
||||||
|
ctx->IASetInputLayout(bd->pInputLayout);
|
||||||
|
ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
|
||||||
|
ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
||||||
|
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||||
|
ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
|
||||||
|
ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
|
||||||
|
ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
|
||||||
|
ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
|
||||||
|
ctx->GSSetShader(nullptr, nullptr, 0);
|
||||||
|
ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||||
|
ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||||
|
ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
|
||||||
|
|
||||||
|
// Setup blend state
|
||||||
|
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
||||||
|
ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
|
||||||
|
ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
|
||||||
|
ctx->RSSetState(bd->pRasterizerState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render function
|
||||||
|
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||||
|
{
|
||||||
|
// Avoid rendering when minimized
|
||||||
|
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||||
|
ID3D11DeviceContext* ctx = bd->pd3dDeviceContext;
|
||||||
|
|
||||||
|
// Create and grow vertex/index buffers if needed
|
||||||
|
if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
|
||||||
|
{
|
||||||
|
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||||
|
bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||||
|
D3D11_BUFFER_DESC desc;
|
||||||
|
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||||
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
|
desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
|
||||||
|
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||||
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
|
desc.MiscFlags = 0;
|
||||||
|
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
|
||||||
|
{
|
||||||
|
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||||
|
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||||
|
D3D11_BUFFER_DESC desc;
|
||||||
|
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
||||||
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
|
desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
|
||||||
|
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||||
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
|
if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload vertex/index data into a single contiguous GPU buffer
|
||||||
|
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
||||||
|
if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||||
|
return;
|
||||||
|
if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
||||||
|
return;
|
||||||
|
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||||
|
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
|
||||||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||||
|
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||||
|
vtx_dst += cmd_list->VtxBuffer.Size;
|
||||||
|
idx_dst += cmd_list->IdxBuffer.Size;
|
||||||
|
}
|
||||||
|
ctx->Unmap(bd->pVB, 0);
|
||||||
|
ctx->Unmap(bd->pIB, 0);
|
||||||
|
|
||||||
|
// Setup orthographic projection matrix into our constant buffer
|
||||||
|
// 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.
|
||||||
|
{
|
||||||
|
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||||
|
if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
||||||
|
return;
|
||||||
|
VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData;
|
||||||
|
float L = draw_data->DisplayPos.x;
|
||||||
|
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||||
|
float T = draw_data->DisplayPos.y;
|
||||||
|
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||||
|
float mvp[4][4] =
|
||||||
|
{
|
||||||
|
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 0.0f, 0.5f, 0.0f },
|
||||||
|
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||||
|
};
|
||||||
|
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
||||||
|
ctx->Unmap(bd->pVertexConstantBuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
||||||
|
struct BACKUP_DX11_STATE
|
||||||
|
{
|
||||||
|
UINT ScissorRectsCount, ViewportsCount;
|
||||||
|
D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
||||||
|
D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
||||||
|
ID3D11RasterizerState* RS;
|
||||||
|
ID3D11BlendState* BlendState;
|
||||||
|
FLOAT BlendFactor[4];
|
||||||
|
UINT SampleMask;
|
||||||
|
UINT StencilRef;
|
||||||
|
ID3D11DepthStencilState* DepthStencilState;
|
||||||
|
ID3D11ShaderResourceView* PSShaderResource;
|
||||||
|
ID3D11SamplerState* PSSampler;
|
||||||
|
ID3D11PixelShader* PS;
|
||||||
|
ID3D11VertexShader* VS;
|
||||||
|
ID3D11GeometryShader* GS;
|
||||||
|
UINT PSInstancesCount, VSInstancesCount, GSInstancesCount;
|
||||||
|
ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation
|
||||||
|
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
||||||
|
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
|
||||||
|
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
|
||||||
|
DXGI_FORMAT IndexBufferFormat;
|
||||||
|
ID3D11InputLayout* InputLayout;
|
||||||
|
};
|
||||||
|
BACKUP_DX11_STATE old = {};
|
||||||
|
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||||
|
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||||
|
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||||
|
ctx->RSGetState(&old.RS);
|
||||||
|
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
|
||||||
|
ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
||||||
|
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
|
||||||
|
ctx->PSGetSamplers(0, 1, &old.PSSampler);
|
||||||
|
old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256;
|
||||||
|
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
|
||||||
|
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
|
||||||
|
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
|
||||||
|
ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
|
||||||
|
|
||||||
|
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
|
||||||
|
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
|
||||||
|
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
|
||||||
|
ctx->IAGetInputLayout(&old.InputLayout);
|
||||||
|
|
||||||
|
// Setup desired DX state
|
||||||
|
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
|
||||||
|
|
||||||
|
// Render command lists
|
||||||
|
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||||
|
int global_idx_offset = 0;
|
||||||
|
int global_vtx_offset = 0;
|
||||||
|
ImVec2 clip_off = draw_data->DisplayPos;
|
||||||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||||
|
{
|
||||||
|
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||||
|
if (pcmd->UserCallback != nullptr)
|
||||||
|
{
|
||||||
|
// User callback, registered via ImDrawList::AddCallback()
|
||||||
|
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||||
|
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||||
|
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
|
||||||
|
else
|
||||||
|
pcmd->UserCallback(cmd_list, pcmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Project scissor/clipping rectangles into framebuffer space
|
||||||
|
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||||
|
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||||
|
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Apply scissor/clipping rectangle
|
||||||
|
const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
|
||||||
|
ctx->RSSetScissorRects(1, &r);
|
||||||
|
|
||||||
|
// Bind texture, Draw
|
||||||
|
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
|
||||||
|
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
||||||
|
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||||
|
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore modified DX state
|
||||||
|
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
||||||
|
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
||||||
|
ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
|
||||||
|
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
|
||||||
|
ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
|
||||||
|
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
|
||||||
|
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
|
||||||
|
ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
|
||||||
|
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
|
||||||
|
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
|
||||||
|
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
||||||
|
ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
|
||||||
|
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
|
||||||
|
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
|
||||||
|
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
|
||||||
|
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
|
||||||
|
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplDX11_CreateFontsTexture()
|
||||||
|
{
|
||||||
|
// Build texture atlas
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||||
|
unsigned char* pixels;
|
||||||
|
int width, height;
|
||||||
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||||
|
|
||||||
|
// Upload texture to graphics system
|
||||||
|
{
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
ZeroMemory(&desc, sizeof(desc));
|
||||||
|
desc.Width = width;
|
||||||
|
desc.Height = height;
|
||||||
|
desc.MipLevels = 1;
|
||||||
|
desc.ArraySize = 1;
|
||||||
|
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
desc.CPUAccessFlags = 0;
|
||||||
|
|
||||||
|
ID3D11Texture2D* pTexture = nullptr;
|
||||||
|
D3D11_SUBRESOURCE_DATA subResource;
|
||||||
|
subResource.pSysMem = pixels;
|
||||||
|
subResource.SysMemPitch = desc.Width * 4;
|
||||||
|
subResource.SysMemSlicePitch = 0;
|
||||||
|
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||||
|
IM_ASSERT(pTexture != nullptr);
|
||||||
|
|
||||||
|
// Create texture view
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||||
|
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||||
|
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||||
|
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||||
|
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
|
||||||
|
pTexture->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store our identifier
|
||||||
|
io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
|
||||||
|
|
||||||
|
// Create texture sampler
|
||||||
|
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
|
||||||
|
{
|
||||||
|
D3D11_SAMPLER_DESC desc;
|
||||||
|
ZeroMemory(&desc, sizeof(desc));
|
||||||
|
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||||
|
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||||
|
desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||||
|
desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
||||||
|
desc.MipLODBias = 0.f;
|
||||||
|
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
||||||
|
desc.MinLOD = 0.f;
|
||||||
|
desc.MaxLOD = 0.f;
|
||||||
|
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplDX11_CreateDeviceObjects()
|
||||||
|
{
|
||||||
|
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||||
|
if (!bd->pd3dDevice)
|
||||||
|
return false;
|
||||||
|
if (bd->pFontSampler)
|
||||||
|
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||||
|
|
||||||
|
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
||||||
|
// If you would like to use this DX11 sample code but remove this dependency you can:
|
||||||
|
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
||||||
|
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
||||||
|
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
||||||
|
|
||||||
|
// Create the vertex shader
|
||||||
|
{
|
||||||
|
static const char* vertexShader =
|
||||||
|
"cbuffer vertexBuffer : register(b0) \
|
||||||
|
{\
|
||||||
|
float4x4 ProjectionMatrix; \
|
||||||
|
};\
|
||||||
|
struct VS_INPUT\
|
||||||
|
{\
|
||||||
|
float2 pos : POSITION;\
|
||||||
|
float4 col : COLOR0;\
|
||||||
|
float2 uv : TEXCOORD0;\
|
||||||
|
};\
|
||||||
|
\
|
||||||
|
struct PS_INPUT\
|
||||||
|
{\
|
||||||
|
float4 pos : SV_POSITION;\
|
||||||
|
float4 col : COLOR0;\
|
||||||
|
float2 uv : TEXCOORD0;\
|
||||||
|
};\
|
||||||
|
\
|
||||||
|
PS_INPUT main(VS_INPUT input)\
|
||||||
|
{\
|
||||||
|
PS_INPUT output;\
|
||||||
|
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
|
||||||
|
output.col = input.col;\
|
||||||
|
output.uv = input.uv;\
|
||||||
|
return output;\
|
||||||
|
}";
|
||||||
|
|
||||||
|
ID3DBlob* vertexShaderBlob;
|
||||||
|
if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr)))
|
||||||
|
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||||
|
if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &bd->pVertexShader) != S_OK)
|
||||||
|
{
|
||||||
|
vertexShaderBlob->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the input layout
|
||||||
|
D3D11_INPUT_ELEMENT_DESC local_layout[] =
|
||||||
|
{
|
||||||
|
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||||
|
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||||
|
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)offsetof(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||||
|
};
|
||||||
|
if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
|
||||||
|
{
|
||||||
|
vertexShaderBlob->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vertexShaderBlob->Release();
|
||||||
|
|
||||||
|
// Create the constant buffer
|
||||||
|
{
|
||||||
|
D3D11_BUFFER_DESC desc;
|
||||||
|
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX11);
|
||||||
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
|
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||||
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||||
|
desc.MiscFlags = 0;
|
||||||
|
bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the pixel shader
|
||||||
|
{
|
||||||
|
static const char* pixelShader =
|
||||||
|
"struct PS_INPUT\
|
||||||
|
{\
|
||||||
|
float4 pos : SV_POSITION;\
|
||||||
|
float4 col : COLOR0;\
|
||||||
|
float2 uv : TEXCOORD0;\
|
||||||
|
};\
|
||||||
|
sampler sampler0;\
|
||||||
|
Texture2D texture0;\
|
||||||
|
\
|
||||||
|
float4 main(PS_INPUT input) : SV_Target\
|
||||||
|
{\
|
||||||
|
float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
|
||||||
|
return out_col; \
|
||||||
|
}";
|
||||||
|
|
||||||
|
ID3DBlob* pixelShaderBlob;
|
||||||
|
if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr)))
|
||||||
|
return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
||||||
|
if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &bd->pPixelShader) != S_OK)
|
||||||
|
{
|
||||||
|
pixelShaderBlob->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pixelShaderBlob->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the blending setup
|
||||||
|
{
|
||||||
|
D3D11_BLEND_DESC desc;
|
||||||
|
ZeroMemory(&desc, sizeof(desc));
|
||||||
|
desc.AlphaToCoverageEnable = false;
|
||||||
|
desc.RenderTarget[0].BlendEnable = true;
|
||||||
|
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
||||||
|
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
||||||
|
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
||||||
|
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||||
|
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
||||||
|
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||||
|
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||||
|
bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the rasterizer state
|
||||||
|
{
|
||||||
|
D3D11_RASTERIZER_DESC desc;
|
||||||
|
ZeroMemory(&desc, sizeof(desc));
|
||||||
|
desc.FillMode = D3D11_FILL_SOLID;
|
||||||
|
desc.CullMode = D3D11_CULL_NONE;
|
||||||
|
desc.ScissorEnable = true;
|
||||||
|
desc.DepthClipEnable = true;
|
||||||
|
bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create depth-stencil State
|
||||||
|
{
|
||||||
|
D3D11_DEPTH_STENCIL_DESC desc;
|
||||||
|
ZeroMemory(&desc, sizeof(desc));
|
||||||
|
desc.DepthEnable = false;
|
||||||
|
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||||
|
desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
||||||
|
desc.StencilEnable = false;
|
||||||
|
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
||||||
|
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
||||||
|
desc.BackFace = desc.FrontFace;
|
||||||
|
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplDX11_CreateFontsTexture();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplDX11_InvalidateDeviceObjects()
|
||||||
|
{
|
||||||
|
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||||
|
if (!bd->pd3dDevice)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
|
||||||
|
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||||
|
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||||
|
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
|
||||||
|
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
|
||||||
|
if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; }
|
||||||
|
if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; }
|
||||||
|
if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; }
|
||||||
|
if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; }
|
||||||
|
if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; }
|
||||||
|
if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
|
||||||
|
|
||||||
|
// Setup backend capabilities flags
|
||||||
|
ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
|
||||||
|
io.BackendRendererUserData = (void*)bd;
|
||||||
|
io.BackendRendererName = "imgui_impl_dx11";
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
|
||||||
|
// Get factory from device
|
||||||
|
IDXGIDevice* pDXGIDevice = nullptr;
|
||||||
|
IDXGIAdapter* pDXGIAdapter = nullptr;
|
||||||
|
IDXGIFactory* pFactory = nullptr;
|
||||||
|
|
||||||
|
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
|
||||||
|
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
|
||||||
|
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
|
||||||
|
{
|
||||||
|
bd->pd3dDevice = device;
|
||||||
|
bd->pd3dDeviceContext = device_context;
|
||||||
|
bd->pFactory = pFactory;
|
||||||
|
}
|
||||||
|
if (pDXGIDevice) pDXGIDevice->Release();
|
||||||
|
if (pDXGIAdapter) pDXGIAdapter->Release();
|
||||||
|
bd->pd3dDevice->AddRef();
|
||||||
|
bd->pd3dDeviceContext->AddRef();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplDX11_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||||
|
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||||
|
if (bd->pFactory) { bd->pFactory->Release(); }
|
||||||
|
if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
|
||||||
|
if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
|
||||||
|
io.BackendRendererName = nullptr;
|
||||||
|
io.BackendRendererUserData = nullptr;
|
||||||
|
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
|
||||||
|
IM_DELETE(bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplDX11_NewFrame()
|
||||||
|
{
|
||||||
|
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
|
||||||
|
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX11_Init()?");
|
||||||
|
|
||||||
|
if (!bd->pFontSampler)
|
||||||
|
ImGui_ImplDX11_CreateDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#endif // #ifndef IMGUI_DISABLE
|
33
vendor/backend/imgui_impl_dx11.h
vendored
Normal file
33
vendor/backend/imgui_impl_dx11.h
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// dear imgui: Renderer Backend for DirectX11
|
||||||
|
// This needs to be used along with a Platform Backend (e.g. Win32)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||||
|
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
|
||||||
|
|
||||||
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
// Learn about Dear ImGui:
|
||||||
|
// - FAQ https://dearimgui.com/faq
|
||||||
|
// - Getting Started https://dearimgui.com/getting-started
|
||||||
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "imgui.h" // IMGUI_IMPL_API
|
||||||
|
#ifndef IMGUI_DISABLE
|
||||||
|
|
||||||
|
struct ID3D11Device;
|
||||||
|
struct ID3D11DeviceContext;
|
||||||
|
|
||||||
|
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
|
||||||
|
|
||||||
|
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
|
||||||
|
|
||||||
|
#endif // #ifndef IMGUI_DISABLE
|
933
vendor/backend/imgui_impl_win32.cpp
vendored
Normal file
933
vendor/backend/imgui_impl_win32.cpp
vendored
Normal file
@ -0,0 +1,933 @@
|
|||||||
|
// dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications)
|
||||||
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
|
||||||
|
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
|
||||||
|
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
|
||||||
|
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
|
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||||
|
|
||||||
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
// Learn about Dear ImGui:
|
||||||
|
// - FAQ https://dearimgui.com/faq
|
||||||
|
// - Getting Started https://dearimgui.com/getting-started
|
||||||
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
// Configuration flags to add in your imconfig file:
|
||||||
|
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant.
|
||||||
|
|
||||||
|
// CHANGELOG
|
||||||
|
// (minor and older changes stripped away, please see git history for details)
|
||||||
|
// 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768)
|
||||||
|
// 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys.
|
||||||
|
// 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL).
|
||||||
|
// 2023-09-07: Inputs: Added support for keyboard codepage conversion for when application is compiled in MBCS mode and using a non-Unicode window.
|
||||||
|
// 2023-04-19: Added ImGui_ImplWin32_InitForOpenGL() to facilitate combining raw Win32/Winapi with OpenGL. (#3218)
|
||||||
|
// 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen. (#2702)
|
||||||
|
// 2023-02-15: Inputs: Use WM_NCMOUSEMOVE / WM_NCMOUSELEAVE to track mouse position over non-client area (e.g. OS decorations) when app is not focused. (#6045, #6162)
|
||||||
|
// 2023-02-02: Inputs: Flipping WM_MOUSEHWHEEL (horizontal mouse-wheel) value to match other backends and offer consistent horizontal scrolling direction. (#4019, #6096, #1463)
|
||||||
|
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
|
||||||
|
// 2022-09-28: Inputs: Convert WM_CHAR values with MultiByteToWideChar() when window class was registered as MBCS (not Unicode).
|
||||||
|
// 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported).
|
||||||
|
// 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion.
|
||||||
|
// 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[].
|
||||||
|
// 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+).
|
||||||
|
// 2022-01-17: Inputs: always update key mods next and before a key event (not in NewFrame) to fix input queue with very low framerates.
|
||||||
|
// 2022-01-12: Inputs: Update mouse inputs using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback to provide it when focused but not hovered/captured. More standard and will allow us to pass it to future input queue API.
|
||||||
|
// 2022-01-12: Inputs: Maintain our own copy of MouseButtonsDown mask instead of using ImGui::IsAnyMouseDown() which will be obsoleted.
|
||||||
|
// 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range.
|
||||||
|
// 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness.
|
||||||
|
// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages.
|
||||||
|
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus.
|
||||||
|
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events).
|
||||||
|
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||||
|
// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
|
||||||
|
// 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS).
|
||||||
|
// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi).
|
||||||
|
// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1.
|
||||||
|
// 2021-01-25: Inputs: Dynamically loading XInput DLL.
|
||||||
|
// 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed.
|
||||||
|
// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs)
|
||||||
|
// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions.
|
||||||
|
// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT.
|
||||||
|
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
|
||||||
|
// 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter().
|
||||||
|
// 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent.
|
||||||
|
// 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages.
|
||||||
|
// 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
|
||||||
|
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
|
||||||
|
// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
|
||||||
|
// 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads).
|
||||||
|
// 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples.
|
||||||
|
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
|
||||||
|
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling).
|
||||||
|
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||||
|
// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
|
||||||
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||||
|
// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
|
||||||
|
// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert.
|
||||||
|
// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag.
|
||||||
|
// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read.
|
||||||
|
// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging.
|
||||||
|
// 2016-11-12: Inputs: Only call Win32 ::SetCursor(nullptr) when io.MouseDrawCursor is set.
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
#ifndef IMGUI_DISABLE
|
||||||
|
#include "imgui_impl_win32.h"
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
#include <windowsx.h> // GET_X_LPARAM(), GET_Y_LPARAM()
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <dwmapi.h>
|
||||||
|
|
||||||
|
// Using XInput for gamepad (will load DLL dynamically)
|
||||||
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
#include <xinput.h>
|
||||||
|
typedef DWORD(WINAPI* PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
||||||
|
typedef DWORD(WINAPI* PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Clang/GCC warnings with -Weverything
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
|
||||||
|
#pragma GCC diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ImGui_ImplWin32_Data
|
||||||
|
{
|
||||||
|
HWND hWnd;
|
||||||
|
HWND MouseHwnd;
|
||||||
|
int MouseTrackedArea; // 0: not tracked, 1: client area, 2: non-client area
|
||||||
|
int MouseButtonsDown;
|
||||||
|
INT64 Time;
|
||||||
|
INT64 TicksPerSecond;
|
||||||
|
ImGuiMouseCursor LastMouseCursor;
|
||||||
|
UINT32 KeyboardCodePage;
|
||||||
|
|
||||||
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
bool HasGamepad;
|
||||||
|
bool WantUpdateHasGamepad;
|
||||||
|
HMODULE XInputDLL;
|
||||||
|
PFN_XInputGetCapabilities XInputGetCapabilities;
|
||||||
|
PFN_XInputGetState XInputGetState;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
|
||||||
|
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
|
||||||
|
// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
|
||||||
|
// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
|
||||||
|
static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData()
|
||||||
|
{
|
||||||
|
return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
static void ImGui_ImplWin32_UpdateKeyboardCodePage()
|
||||||
|
{
|
||||||
|
// Retrieve keyboard code page, required for handling of non-Unicode Windows.
|
||||||
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||||
|
HKL keyboard_layout = ::GetKeyboardLayout(0);
|
||||||
|
LCID keyboard_lcid = MAKELCID(HIWORD(keyboard_layout), SORT_DEFAULT);
|
||||||
|
if (::GetLocaleInfoA(keyboard_lcid, (LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE), (LPSTR)&bd->KeyboardCodePage, sizeof(bd->KeyboardCodePage)) == 0)
|
||||||
|
bd->KeyboardCodePage = CP_ACP; // Fallback to default ANSI code page when fails.
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IMGUI_CHECKVERSION();
|
||||||
|
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||||
|
|
||||||
|
INT64 perf_frequency, perf_counter;
|
||||||
|
if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency))
|
||||||
|
return false;
|
||||||
|
if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Setup backend capabilities flags
|
||||||
|
ImGui_ImplWin32_Data* bd = IM_NEW(ImGui_ImplWin32_Data)();
|
||||||
|
io.BackendPlatformUserData = (void*)bd;
|
||||||
|
io.BackendPlatformName = "imgui_impl_win32";
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
|
||||||
|
|
||||||
|
bd->hWnd = (HWND)hwnd;
|
||||||
|
bd->TicksPerSecond = perf_frequency;
|
||||||
|
bd->Time = perf_counter;
|
||||||
|
bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
|
||||||
|
ImGui_ImplWin32_UpdateKeyboardCodePage();
|
||||||
|
|
||||||
|
// Set platform dependent data in viewport
|
||||||
|
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||||
|
main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)bd->hWnd;
|
||||||
|
IM_UNUSED(platform_has_own_dc); // Used in 'docking' branch
|
||||||
|
|
||||||
|
// Dynamically load XInput library
|
||||||
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
bd->WantUpdateHasGamepad = true;
|
||||||
|
const char* xinput_dll_names[] =
|
||||||
|
{
|
||||||
|
"xinput1_4.dll", // Windows 8+
|
||||||
|
"xinput1_3.dll", // DirectX SDK
|
||||||
|
"xinput9_1_0.dll", // Windows Vista, Windows 7
|
||||||
|
"xinput1_2.dll", // DirectX SDK
|
||||||
|
"xinput1_1.dll" // DirectX SDK
|
||||||
|
};
|
||||||
|
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
|
||||||
|
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
|
||||||
|
{
|
||||||
|
bd->XInputDLL = dll;
|
||||||
|
bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
|
||||||
|
bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd)
|
||||||
|
{
|
||||||
|
return ImGui_ImplWin32_InitEx(hwnd, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd)
|
||||||
|
{
|
||||||
|
// OpenGL needs CS_OWNDC
|
||||||
|
return ImGui_ImplWin32_InitEx(hwnd, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplWin32_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||||
|
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Unload XInput library
|
||||||
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
if (bd->XInputDLL)
|
||||||
|
::FreeLibrary(bd->XInputDLL);
|
||||||
|
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
|
||||||
|
io.BackendPlatformName = nullptr;
|
||||||
|
io.BackendPlatformUserData = nullptr;
|
||||||
|
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad);
|
||||||
|
IM_DELETE(bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ImGui_ImplWin32_UpdateMouseCursor()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
|
||||||
|
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
|
||||||
|
{
|
||||||
|
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
|
||||||
|
::SetCursor(nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Show OS mouse cursor
|
||||||
|
LPTSTR win32_cursor = IDC_ARROW;
|
||||||
|
switch (imgui_cursor)
|
||||||
|
{
|
||||||
|
case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
|
||||||
|
case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
|
||||||
|
case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||||
|
case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
|
||||||
|
case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
|
||||||
|
case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||||
|
case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||||
|
case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break;
|
||||||
|
case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break;
|
||||||
|
}
|
||||||
|
::SetCursor(::LoadCursor(nullptr, win32_cursor));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsVkDown(int vk)
|
||||||
|
{
|
||||||
|
return (::GetKeyState(vk) & 0x8000) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplWin32_AddKeyEvent(ImGuiKey key, bool down, int native_keycode, int native_scancode = -1)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.AddKeyEvent(key, down);
|
||||||
|
io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To support legacy indexing (<1.87 user code)
|
||||||
|
IM_UNUSED(native_scancode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds()
|
||||||
|
{
|
||||||
|
// Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one.
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && !IsVkDown(VK_LSHIFT))
|
||||||
|
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, false, VK_LSHIFT);
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT))
|
||||||
|
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, false, VK_RSHIFT);
|
||||||
|
|
||||||
|
// Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Win+V on some setups, according to GLFW).
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN))
|
||||||
|
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftSuper, false, VK_LWIN);
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN))
|
||||||
|
ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightSuper, false, VK_RWIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplWin32_UpdateKeyModifiers()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL));
|
||||||
|
io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT));
|
||||||
|
io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU));
|
||||||
|
io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_LWIN) || IsVkDown(VK_RWIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplWin32_UpdateMouseData()
|
||||||
|
{
|
||||||
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IM_ASSERT(bd->hWnd != 0);
|
||||||
|
|
||||||
|
HWND focused_window = ::GetForegroundWindow();
|
||||||
|
const bool is_app_focused = (focused_window == bd->hWnd);
|
||||||
|
if (is_app_focused)
|
||||||
|
{
|
||||||
|
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||||
|
if (io.WantSetMousePos)
|
||||||
|
{
|
||||||
|
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
|
||||||
|
if (::ClientToScreen(bd->hWnd, &pos))
|
||||||
|
::SetCursorPos(pos.x, pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (Optional) Fallback to provide mouse position when focused (WM_MOUSEMOVE already provides this when hovered or captured)
|
||||||
|
// This also fills a short gap when clicking non-client area: WM_NCMOUSELEAVE -> modal OS move -> gap -> WM_NCMOUSEMOVE
|
||||||
|
if (!io.WantSetMousePos && bd->MouseTrackedArea == 0)
|
||||||
|
{
|
||||||
|
POINT pos;
|
||||||
|
if (::GetCursorPos(&pos) && ::ScreenToClient(bd->hWnd, &pos))
|
||||||
|
io.AddMousePosEvent((float)pos.x, (float)pos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gamepad navigation mapping
|
||||||
|
static void ImGui_ImplWin32_UpdateGamepads()
|
||||||
|
{
|
||||||
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||||
|
//if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
|
||||||
|
// Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.
|
||||||
|
if (bd->WantUpdateHasGamepad)
|
||||||
|
{
|
||||||
|
XINPUT_CAPABILITIES caps = {};
|
||||||
|
bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
|
||||||
|
bd->WantUpdateHasGamepad = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||||
|
XINPUT_STATE xinput_state;
|
||||||
|
XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
|
||||||
|
if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||||
|
|
||||||
|
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
|
||||||
|
#define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); }
|
||||||
|
#define MAP_ANALOG(KEY_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); io.AddKeyAnalogEvent(KEY_NO, vn > 0.10f, IM_SATURATE(vn)); }
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadStart, XINPUT_GAMEPAD_START);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadBack, XINPUT_GAMEPAD_BACK);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, XINPUT_GAMEPAD_X);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadFaceRight, XINPUT_GAMEPAD_B);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadFaceUp, XINPUT_GAMEPAD_Y);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadFaceDown, XINPUT_GAMEPAD_A);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, XINPUT_GAMEPAD_DPAD_LEFT);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadDpadRight, XINPUT_GAMEPAD_DPAD_RIGHT);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadDpadUp, XINPUT_GAMEPAD_DPAD_UP);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadDpadDown, XINPUT_GAMEPAD_DPAD_DOWN);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadL1, XINPUT_GAMEPAD_LEFT_SHOULDER);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadR1, XINPUT_GAMEPAD_RIGHT_SHOULDER);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadL2, gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadR2, gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD, 255);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadL3, XINPUT_GAMEPAD_LEFT_THUMB);
|
||||||
|
MAP_BUTTON(ImGuiKey_GamepadR3, XINPUT_GAMEPAD_RIGHT_THUMB);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadLStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadLStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadLStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadLStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadRStickLeft, gamepad.sThumbRX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadRStickRight, gamepad.sThumbRX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadRStickUp, gamepad.sThumbRY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
|
||||||
|
MAP_ANALOG(ImGuiKey_GamepadRStickDown, gamepad.sThumbRY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
|
||||||
|
#undef MAP_BUTTON
|
||||||
|
#undef MAP_ANALOG
|
||||||
|
#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplWin32_NewFrame()
|
||||||
|
{
|
||||||
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||||
|
IM_ASSERT(bd != nullptr && "Context or backend not initialized? Did you call ImGui_ImplWin32_Init()?");
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Setup display size (every frame to accommodate for window resizing)
|
||||||
|
RECT rect = { 0, 0, 0, 0 };
|
||||||
|
::GetClientRect(bd->hWnd, &rect);
|
||||||
|
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
|
||||||
|
|
||||||
|
// Setup time step
|
||||||
|
INT64 current_time = 0;
|
||||||
|
::QueryPerformanceCounter((LARGE_INTEGER*)¤t_time);
|
||||||
|
io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
|
||||||
|
bd->Time = current_time;
|
||||||
|
|
||||||
|
// Update OS mouse position
|
||||||
|
ImGui_ImplWin32_UpdateMouseData();
|
||||||
|
|
||||||
|
// Process workarounds for known Windows key handling issues
|
||||||
|
ImGui_ImplWin32_ProcessKeyEventsWorkarounds();
|
||||||
|
|
||||||
|
// Update OS mouse cursor with the cursor requested by imgui
|
||||||
|
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||||
|
if (bd->LastMouseCursor != mouse_cursor)
|
||||||
|
{
|
||||||
|
bd->LastMouseCursor = mouse_cursor;
|
||||||
|
ImGui_ImplWin32_UpdateMouseCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update game controllers (if enabled and available)
|
||||||
|
ImGui_ImplWin32_UpdateGamepads();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map VK_xxx to ImGuiKey_xxx.
|
||||||
|
// Not static to allow third-party code to use that if they want to (but undocumented)
|
||||||
|
ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
// There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED.
|
||||||
|
if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED))
|
||||||
|
return ImGuiKey_KeypadEnter;
|
||||||
|
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case VK_TAB: return ImGuiKey_Tab;
|
||||||
|
case VK_LEFT: return ImGuiKey_LeftArrow;
|
||||||
|
case VK_RIGHT: return ImGuiKey_RightArrow;
|
||||||
|
case VK_UP: return ImGuiKey_UpArrow;
|
||||||
|
case VK_DOWN: return ImGuiKey_DownArrow;
|
||||||
|
case VK_PRIOR: return ImGuiKey_PageUp;
|
||||||
|
case VK_NEXT: return ImGuiKey_PageDown;
|
||||||
|
case VK_HOME: return ImGuiKey_Home;
|
||||||
|
case VK_END: return ImGuiKey_End;
|
||||||
|
case VK_INSERT: return ImGuiKey_Insert;
|
||||||
|
case VK_DELETE: return ImGuiKey_Delete;
|
||||||
|
case VK_BACK: return ImGuiKey_Backspace;
|
||||||
|
case VK_SPACE: return ImGuiKey_Space;
|
||||||
|
case VK_RETURN: return ImGuiKey_Enter;
|
||||||
|
case VK_ESCAPE: return ImGuiKey_Escape;
|
||||||
|
case VK_OEM_7: return ImGuiKey_Apostrophe;
|
||||||
|
case VK_OEM_COMMA: return ImGuiKey_Comma;
|
||||||
|
case VK_OEM_MINUS: return ImGuiKey_Minus;
|
||||||
|
case VK_OEM_PERIOD: return ImGuiKey_Period;
|
||||||
|
case VK_OEM_2: return ImGuiKey_Slash;
|
||||||
|
case VK_OEM_1: return ImGuiKey_Semicolon;
|
||||||
|
case VK_OEM_PLUS: return ImGuiKey_Equal;
|
||||||
|
case VK_OEM_4: return ImGuiKey_LeftBracket;
|
||||||
|
case VK_OEM_5: return ImGuiKey_Backslash;
|
||||||
|
case VK_OEM_6: return ImGuiKey_RightBracket;
|
||||||
|
case VK_OEM_3: return ImGuiKey_GraveAccent;
|
||||||
|
case VK_CAPITAL: return ImGuiKey_CapsLock;
|
||||||
|
case VK_SCROLL: return ImGuiKey_ScrollLock;
|
||||||
|
case VK_NUMLOCK: return ImGuiKey_NumLock;
|
||||||
|
case VK_SNAPSHOT: return ImGuiKey_PrintScreen;
|
||||||
|
case VK_PAUSE: return ImGuiKey_Pause;
|
||||||
|
case VK_NUMPAD0: return ImGuiKey_Keypad0;
|
||||||
|
case VK_NUMPAD1: return ImGuiKey_Keypad1;
|
||||||
|
case VK_NUMPAD2: return ImGuiKey_Keypad2;
|
||||||
|
case VK_NUMPAD3: return ImGuiKey_Keypad3;
|
||||||
|
case VK_NUMPAD4: return ImGuiKey_Keypad4;
|
||||||
|
case VK_NUMPAD5: return ImGuiKey_Keypad5;
|
||||||
|
case VK_NUMPAD6: return ImGuiKey_Keypad6;
|
||||||
|
case VK_NUMPAD7: return ImGuiKey_Keypad7;
|
||||||
|
case VK_NUMPAD8: return ImGuiKey_Keypad8;
|
||||||
|
case VK_NUMPAD9: return ImGuiKey_Keypad9;
|
||||||
|
case VK_DECIMAL: return ImGuiKey_KeypadDecimal;
|
||||||
|
case VK_DIVIDE: return ImGuiKey_KeypadDivide;
|
||||||
|
case VK_MULTIPLY: return ImGuiKey_KeypadMultiply;
|
||||||
|
case VK_SUBTRACT: return ImGuiKey_KeypadSubtract;
|
||||||
|
case VK_ADD: return ImGuiKey_KeypadAdd;
|
||||||
|
case VK_LSHIFT: return ImGuiKey_LeftShift;
|
||||||
|
case VK_LCONTROL: return ImGuiKey_LeftCtrl;
|
||||||
|
case VK_LMENU: return ImGuiKey_LeftAlt;
|
||||||
|
case VK_LWIN: return ImGuiKey_LeftSuper;
|
||||||
|
case VK_RSHIFT: return ImGuiKey_RightShift;
|
||||||
|
case VK_RCONTROL: return ImGuiKey_RightCtrl;
|
||||||
|
case VK_RMENU: return ImGuiKey_RightAlt;
|
||||||
|
case VK_RWIN: return ImGuiKey_RightSuper;
|
||||||
|
case VK_APPS: return ImGuiKey_Menu;
|
||||||
|
case '0': return ImGuiKey_0;
|
||||||
|
case '1': return ImGuiKey_1;
|
||||||
|
case '2': return ImGuiKey_2;
|
||||||
|
case '3': return ImGuiKey_3;
|
||||||
|
case '4': return ImGuiKey_4;
|
||||||
|
case '5': return ImGuiKey_5;
|
||||||
|
case '6': return ImGuiKey_6;
|
||||||
|
case '7': return ImGuiKey_7;
|
||||||
|
case '8': return ImGuiKey_8;
|
||||||
|
case '9': return ImGuiKey_9;
|
||||||
|
case 'A': return ImGuiKey_A;
|
||||||
|
case 'B': return ImGuiKey_B;
|
||||||
|
case 'C': return ImGuiKey_C;
|
||||||
|
case 'D': return ImGuiKey_D;
|
||||||
|
case 'E': return ImGuiKey_E;
|
||||||
|
case 'F': return ImGuiKey_F;
|
||||||
|
case 'G': return ImGuiKey_G;
|
||||||
|
case 'H': return ImGuiKey_H;
|
||||||
|
case 'I': return ImGuiKey_I;
|
||||||
|
case 'J': return ImGuiKey_J;
|
||||||
|
case 'K': return ImGuiKey_K;
|
||||||
|
case 'L': return ImGuiKey_L;
|
||||||
|
case 'M': return ImGuiKey_M;
|
||||||
|
case 'N': return ImGuiKey_N;
|
||||||
|
case 'O': return ImGuiKey_O;
|
||||||
|
case 'P': return ImGuiKey_P;
|
||||||
|
case 'Q': return ImGuiKey_Q;
|
||||||
|
case 'R': return ImGuiKey_R;
|
||||||
|
case 'S': return ImGuiKey_S;
|
||||||
|
case 'T': return ImGuiKey_T;
|
||||||
|
case 'U': return ImGuiKey_U;
|
||||||
|
case 'V': return ImGuiKey_V;
|
||||||
|
case 'W': return ImGuiKey_W;
|
||||||
|
case 'X': return ImGuiKey_X;
|
||||||
|
case 'Y': return ImGuiKey_Y;
|
||||||
|
case 'Z': return ImGuiKey_Z;
|
||||||
|
case VK_F1: return ImGuiKey_F1;
|
||||||
|
case VK_F2: return ImGuiKey_F2;
|
||||||
|
case VK_F3: return ImGuiKey_F3;
|
||||||
|
case VK_F4: return ImGuiKey_F4;
|
||||||
|
case VK_F5: return ImGuiKey_F5;
|
||||||
|
case VK_F6: return ImGuiKey_F6;
|
||||||
|
case VK_F7: return ImGuiKey_F7;
|
||||||
|
case VK_F8: return ImGuiKey_F8;
|
||||||
|
case VK_F9: return ImGuiKey_F9;
|
||||||
|
case VK_F10: return ImGuiKey_F10;
|
||||||
|
case VK_F11: return ImGuiKey_F11;
|
||||||
|
case VK_F12: return ImGuiKey_F12;
|
||||||
|
case VK_F13: return ImGuiKey_F13;
|
||||||
|
case VK_F14: return ImGuiKey_F14;
|
||||||
|
case VK_F15: return ImGuiKey_F15;
|
||||||
|
case VK_F16: return ImGuiKey_F16;
|
||||||
|
case VK_F17: return ImGuiKey_F17;
|
||||||
|
case VK_F18: return ImGuiKey_F18;
|
||||||
|
case VK_F19: return ImGuiKey_F19;
|
||||||
|
case VK_F20: return ImGuiKey_F20;
|
||||||
|
case VK_F21: return ImGuiKey_F21;
|
||||||
|
case VK_F22: return ImGuiKey_F22;
|
||||||
|
case VK_F23: return ImGuiKey_F23;
|
||||||
|
case VK_F24: return ImGuiKey_F24;
|
||||||
|
case VK_BROWSER_BACK: return ImGuiKey_AppBack;
|
||||||
|
case VK_BROWSER_FORWARD: return ImGuiKey_AppForward;
|
||||||
|
default: return ImGuiKey_None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
|
||||||
|
#ifndef WM_MOUSEHWHEEL
|
||||||
|
#define WM_MOUSEHWHEEL 0x020E
|
||||||
|
#endif
|
||||||
|
#ifndef DBT_DEVNODES_CHANGED
|
||||||
|
#define DBT_DEVNODES_CHANGED 0x0007
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
|
||||||
|
// Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||||
|
// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
|
||||||
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||||
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||||
|
// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags.
|
||||||
|
// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
|
||||||
|
// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
|
||||||
|
#if 0
|
||||||
|
// Copy this line into your .cpp file to forward declare the function.
|
||||||
|
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// See https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages
|
||||||
|
// Prefer to call this at the top of the message handler to avoid the possibility of other Win32 calls interfering with this.
|
||||||
|
static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
|
||||||
|
{
|
||||||
|
LPARAM extra_info = ::GetMessageExtraInfo();
|
||||||
|
if ((extra_info & 0xFFFFFF80) == 0xFF515700)
|
||||||
|
return ImGuiMouseSource_Pen;
|
||||||
|
if ((extra_info & 0xFFFFFF80) == 0xFF515780)
|
||||||
|
return ImGuiMouseSource_TouchScreen;
|
||||||
|
return ImGuiMouseSource_Mouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
// Most backends don't have silent checks like this one, but we need it because WndProc are called early in CreateWindow().
|
||||||
|
// We silently allow both context or just only backend data to be nullptr.
|
||||||
|
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
|
||||||
|
if (bd == nullptr)
|
||||||
|
return 0;
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
case WM_NCMOUSEMOVE:
|
||||||
|
{
|
||||||
|
// We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events
|
||||||
|
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
|
||||||
|
const int area = (msg == WM_MOUSEMOVE) ? 1 : 2;
|
||||||
|
bd->MouseHwnd = hwnd;
|
||||||
|
if (bd->MouseTrackedArea != area)
|
||||||
|
{
|
||||||
|
TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 };
|
||||||
|
TRACKMOUSEEVENT tme_track = { sizeof(tme_track), (DWORD)((area == 2) ? (TME_LEAVE | TME_NONCLIENT) : TME_LEAVE), hwnd, 0 };
|
||||||
|
if (bd->MouseTrackedArea != 0)
|
||||||
|
::TrackMouseEvent(&tme_cancel);
|
||||||
|
::TrackMouseEvent(&tme_track);
|
||||||
|
bd->MouseTrackedArea = area;
|
||||||
|
}
|
||||||
|
POINT mouse_pos = { (LONG)GET_X_LPARAM(lParam), (LONG)GET_Y_LPARAM(lParam) };
|
||||||
|
if (msg == WM_NCMOUSEMOVE && ::ScreenToClient(hwnd, &mouse_pos) == FALSE) // WM_NCMOUSEMOVE are provided in absolute coordinates.
|
||||||
|
return 0;
|
||||||
|
io.AddMouseSourceEvent(mouse_source);
|
||||||
|
io.AddMousePosEvent((float)mouse_pos.x, (float)mouse_pos.y);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_MOUSELEAVE:
|
||||||
|
case WM_NCMOUSELEAVE:
|
||||||
|
{
|
||||||
|
const int area = (msg == WM_MOUSELEAVE) ? 1 : 2;
|
||||||
|
if (bd->MouseTrackedArea == area)
|
||||||
|
{
|
||||||
|
if (bd->MouseHwnd == hwnd)
|
||||||
|
bd->MouseHwnd = nullptr;
|
||||||
|
bd->MouseTrackedArea = 0;
|
||||||
|
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_DESTROY:
|
||||||
|
if (bd->MouseHwnd == hwnd && bd->MouseTrackedArea != 0)
|
||||||
|
{
|
||||||
|
TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 };
|
||||||
|
::TrackMouseEvent(&tme_cancel);
|
||||||
|
bd->MouseHwnd = nullptr;
|
||||||
|
bd->MouseTrackedArea = 0;
|
||||||
|
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
|
||||||
|
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
|
||||||
|
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
|
||||||
|
{
|
||||||
|
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
|
||||||
|
int button = 0;
|
||||||
|
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
|
||||||
|
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
|
||||||
|
if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
|
||||||
|
if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
|
||||||
|
if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr)
|
||||||
|
::SetCapture(hwnd);
|
||||||
|
bd->MouseButtonsDown |= 1 << button;
|
||||||
|
io.AddMouseSourceEvent(mouse_source);
|
||||||
|
io.AddMouseButtonEvent(button, true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
case WM_MBUTTONUP:
|
||||||
|
case WM_XBUTTONUP:
|
||||||
|
{
|
||||||
|
ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
|
||||||
|
int button = 0;
|
||||||
|
if (msg == WM_LBUTTONUP) { button = 0; }
|
||||||
|
if (msg == WM_RBUTTONUP) { button = 1; }
|
||||||
|
if (msg == WM_MBUTTONUP) { button = 2; }
|
||||||
|
if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
|
||||||
|
bd->MouseButtonsDown &= ~(1 << button);
|
||||||
|
if (bd->MouseButtonsDown == 0 && ::GetCapture() == hwnd)
|
||||||
|
::ReleaseCapture();
|
||||||
|
io.AddMouseSourceEvent(mouse_source);
|
||||||
|
io.AddMouseButtonEvent(button, false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
io.AddMouseWheelEvent(0.0f, (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA);
|
||||||
|
return 0;
|
||||||
|
case WM_MOUSEHWHEEL:
|
||||||
|
io.AddMouseWheelEvent(-(float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA, 0.0f);
|
||||||
|
return 0;
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
case WM_KEYUP:
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
{
|
||||||
|
const bool is_key_down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
|
||||||
|
if (wParam < 256)
|
||||||
|
{
|
||||||
|
// Submit modifiers
|
||||||
|
ImGui_ImplWin32_UpdateKeyModifiers();
|
||||||
|
|
||||||
|
// Obtain virtual key code and convert to ImGuiKey
|
||||||
|
const ImGuiKey key = ImGui_ImplWin32_KeyEventToImGuiKey(wParam, lParam);
|
||||||
|
const int vk = (int)wParam;
|
||||||
|
const int scancode = (int)LOBYTE(HIWORD(lParam));
|
||||||
|
|
||||||
|
// Special behavior for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit the key down event.
|
||||||
|
if (key == ImGuiKey_PrintScreen && !is_key_down)
|
||||||
|
ImGui_ImplWin32_AddKeyEvent(key, true, vk, scancode);
|
||||||
|
|
||||||
|
// Submit key event
|
||||||
|
if (key != ImGuiKey_None)
|
||||||
|
ImGui_ImplWin32_AddKeyEvent(key, is_key_down, vk, scancode);
|
||||||
|
|
||||||
|
// Submit individual left/right modifier events
|
||||||
|
if (vk == VK_SHIFT)
|
||||||
|
{
|
||||||
|
// Important: Shift keys tend to get stuck when pressed together, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkarounds()
|
||||||
|
if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); }
|
||||||
|
if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); }
|
||||||
|
}
|
||||||
|
else if (vk == VK_CONTROL)
|
||||||
|
{
|
||||||
|
if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); }
|
||||||
|
if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); }
|
||||||
|
}
|
||||||
|
else if (vk == VK_MENU)
|
||||||
|
{
|
||||||
|
if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); }
|
||||||
|
if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_SETFOCUS:
|
||||||
|
case WM_KILLFOCUS:
|
||||||
|
io.AddFocusEvent(msg == WM_SETFOCUS);
|
||||||
|
return 0;
|
||||||
|
case WM_INPUTLANGCHANGE:
|
||||||
|
ImGui_ImplWin32_UpdateKeyboardCodePage();
|
||||||
|
return 0;
|
||||||
|
case WM_CHAR:
|
||||||
|
if (::IsWindowUnicode(hwnd))
|
||||||
|
{
|
||||||
|
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||||
|
if (wParam > 0 && wParam < 0x10000)
|
||||||
|
io.AddInputCharacterUTF16((unsigned short)wParam);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wchar_t wch = 0;
|
||||||
|
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 1, &wch, 1);
|
||||||
|
io.AddInputCharacter(wch);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
case WM_SETCURSOR:
|
||||||
|
// This is required to restore cursor when transitioning from e.g resize borders to client area.
|
||||||
|
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
case WM_DEVICECHANGE:
|
||||||
|
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||||
|
if ((UINT)wParam == DBT_DEVNODES_CHANGED)
|
||||||
|
bd->WantUpdateHasGamepad = true;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
// DPI-related helpers (optional)
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
// - Use to enable DPI awareness without having to create an application manifest.
|
||||||
|
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
|
||||||
|
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
|
||||||
|
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
|
||||||
|
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||||
|
//---------------------------------------------------------------------------------------------------------
|
||||||
|
// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
|
||||||
|
// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.
|
||||||
|
// If you are trying to implement your own backend for your own engine, you may ignore that noise.
|
||||||
|
//---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Perform our own check with RtlVerifyVersionInfo() instead of using functions from <VersionHelpers.h> as they
|
||||||
|
// require a manifest to be functional for checks above 8.1. See https://github.com/ocornut/imgui/issues/4200
|
||||||
|
static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD)
|
||||||
|
{
|
||||||
|
typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG);
|
||||||
|
static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = nullptr;
|
||||||
|
if (RtlVerifyVersionInfoFn == nullptr)
|
||||||
|
if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll"))
|
||||||
|
RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo");
|
||||||
|
if (RtlVerifyVersionInfoFn == nullptr)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
RTL_OSVERSIONINFOEXW versionInfo = { };
|
||||||
|
ULONGLONG conditionMask = 0;
|
||||||
|
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
|
||||||
|
versionInfo.dwMajorVersion = major;
|
||||||
|
versionInfo.dwMinorVersion = minor;
|
||||||
|
VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||||
|
VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||||
|
return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _IsWindowsVistaOrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA
|
||||||
|
#define _IsWindows8OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8
|
||||||
|
#define _IsWindows8Point1OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE
|
||||||
|
#define _IsWindows10OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0A00), LOBYTE(0x0A00), 0) // _WIN32_WINNT_WINTHRESHOLD / _WIN32_WINNT_WIN10
|
||||||
|
|
||||||
|
#ifndef DPI_ENUMS_DECLARED
|
||||||
|
typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS;
|
||||||
|
typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE;
|
||||||
|
#endif
|
||||||
|
#ifndef _DPI_AWARENESS_CONTEXTS_
|
||||||
|
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
|
||||||
|
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3
|
||||||
|
#endif
|
||||||
|
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
|
||||||
|
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4
|
||||||
|
#endif
|
||||||
|
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
|
||||||
|
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
|
||||||
|
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
|
||||||
|
|
||||||
|
// Helper function to enable DPI awareness without setting up a manifest
|
||||||
|
void ImGui_ImplWin32_EnableDpiAwareness()
|
||||||
|
{
|
||||||
|
if (_IsWindows10OrGreater())
|
||||||
|
{
|
||||||
|
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
|
||||||
|
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext"))
|
||||||
|
{
|
||||||
|
SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_IsWindows8Point1OrGreater())
|
||||||
|
{
|
||||||
|
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
|
||||||
|
if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness"))
|
||||||
|
{
|
||||||
|
SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if _WIN32_WINNT >= 0x0600
|
||||||
|
::SetProcessDPIAware();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(NOGDI)
|
||||||
|
#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
|
||||||
|
{
|
||||||
|
UINT xdpi = 96, ydpi = 96;
|
||||||
|
if (_IsWindows8Point1OrGreater())
|
||||||
|
{
|
||||||
|
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
|
||||||
|
static PFN_GetDpiForMonitor GetDpiForMonitorFn = nullptr;
|
||||||
|
if (GetDpiForMonitorFn == nullptr && shcore_dll != nullptr)
|
||||||
|
GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor");
|
||||||
|
if (GetDpiForMonitorFn != nullptr)
|
||||||
|
{
|
||||||
|
GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
|
||||||
|
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
|
||||||
|
return xdpi / 96.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef NOGDI
|
||||||
|
const HDC dc = ::GetDC(nullptr);
|
||||||
|
xdpi = ::GetDeviceCaps(dc, LOGPIXELSX);
|
||||||
|
ydpi = ::GetDeviceCaps(dc, LOGPIXELSY);
|
||||||
|
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
|
||||||
|
::ReleaseDC(nullptr, dc);
|
||||||
|
#endif
|
||||||
|
return xdpi / 96.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
|
||||||
|
{
|
||||||
|
HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST);
|
||||||
|
return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------
|
||||||
|
// Transparency related helpers (optional)
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// [experimental]
|
||||||
|
// Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c
|
||||||
|
// (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW)
|
||||||
|
void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd)
|
||||||
|
{
|
||||||
|
if (!_IsWindowsVistaOrGreater())
|
||||||
|
return;
|
||||||
|
|
||||||
|
BOOL composition;
|
||||||
|
if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BOOL opaque;
|
||||||
|
DWORD color;
|
||||||
|
if (_IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque))
|
||||||
|
{
|
||||||
|
HRGN region = ::CreateRectRgn(0, 0, -1, -1);
|
||||||
|
DWM_BLURBEHIND bb = {};
|
||||||
|
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
||||||
|
bb.hRgnBlur = region;
|
||||||
|
bb.fEnable = TRUE;
|
||||||
|
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
|
||||||
|
::DeleteObject(region);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DWM_BLURBEHIND bb = {};
|
||||||
|
bb.dwFlags = DWM_BB_ENABLE;
|
||||||
|
::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // #ifndef IMGUI_DISABLE
|
53
vendor/backend/imgui_impl_win32.h
vendored
Normal file
53
vendor/backend/imgui_impl_win32.h
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications)
|
||||||
|
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
|
||||||
|
|
||||||
|
// Implemented features:
|
||||||
|
// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
|
||||||
|
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
|
||||||
|
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
|
||||||
|
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||||
|
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||||
|
|
||||||
|
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||||
|
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||||
|
// Learn about Dear ImGui:
|
||||||
|
// - FAQ https://dearimgui.com/faq
|
||||||
|
// - Getting Started https://dearimgui.com/getting-started
|
||||||
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||||
|
// - Introduction, links and more at the top of imgui.cpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "imgui.h" // IMGUI_IMPL_API
|
||||||
|
#ifndef IMGUI_DISABLE
|
||||||
|
|
||||||
|
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd);
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
|
||||||
|
|
||||||
|
// Win32 message handler your application need to call.
|
||||||
|
// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
|
||||||
|
// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
|
||||||
|
// - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// DPI-related helpers (optional)
|
||||||
|
// - Use to enable DPI awareness without having to create an application manifest.
|
||||||
|
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
|
||||||
|
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
|
||||||
|
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
|
||||||
|
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
|
||||||
|
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
|
||||||
|
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
|
||||||
|
|
||||||
|
// Transparency related helpers (optional) [experimental]
|
||||||
|
// - Use to enable alpha compositing transparency with the desktop.
|
||||||
|
// - Use together with e.g. clearing your framebuffer with zero-alpha.
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd
|
||||||
|
|
||||||
|
#endif // #ifndef IMGUI_DISABLE
|
9284
vendor/fonts/comfortaa.h
vendored
Normal file
9284
vendor/fonts/comfortaa.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3367
vendor/fonts/dripicons.h
vendored
Normal file
3367
vendor/fonts/dripicons.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3569
vendor/img/imgs.h
vendored
Normal file
3569
vendor/img/imgs.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
136
vendor/imgui/imconfig.h
vendored
Normal file
136
vendor/imgui/imconfig.h
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// DEAR IMGUI COMPILE-TIME OPTIONS
|
||||||
|
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||||
|
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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)
|
||||||
|
// 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.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||||
|
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||||
|
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||||
|
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//---- Define assertion handler. Defaults to calling assert().
|
||||||
|
// 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.
|
||||||
|
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||||
|
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||||
|
|
||||||
|
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||||
|
// 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.
|
||||||
|
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||||
|
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||||
|
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
|
||||||
|
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
|
||||||
|
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
|
||||||
|
|
||||||
|
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
||||||
|
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS.
|
||||||
|
|
||||||
|
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
||||||
|
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
||||||
|
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||||
|
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||||
|
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
|
||||||
|
|
||||||
|
//---- Don't implement some functions to reduce linkage requirements.
|
||||||
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||||
|
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||||
|
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||||
|
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||||
|
//#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).
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
|
||||||
|
//#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)
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||||
|
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||||
|
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||||
|
//#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().
|
||||||
|
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||||
|
|
||||||
|
//---- Enable Test Engine / Automation features.
|
||||||
|
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
|
||||||
|
|
||||||
|
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||||
|
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
||||||
|
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||||
|
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
|
||||||
|
|
||||||
|
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||||
|
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||||
|
|
||||||
|
//---- 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...)
|
||||||
|
//#define IMGUI_USE_WCHAR32
|
||||||
|
|
||||||
|
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||||
|
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||||
|
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||||
|
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||||
|
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
||||||
|
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
||||||
|
|
||||||
|
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||||
|
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||||
|
//#define IMGUI_USE_STB_SPRINTF
|
||||||
|
|
||||||
|
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||||
|
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||||
|
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||||
|
//#define IMGUI_ENABLE_FREETYPE
|
||||||
|
|
||||||
|
//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
|
||||||
|
// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
|
||||||
|
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||||
|
// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||||
|
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||||
|
|
||||||
|
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||||
|
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||||
|
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||||
|
|
||||||
|
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||||
|
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||||
|
/*
|
||||||
|
#define IM_VEC2_CLASS_EXTRA \
|
||||||
|
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
||||||
|
operator MyVec2() const { return MyVec2(x,y); }
|
||||||
|
|
||||||
|
#define IM_VEC4_CLASS_EXTRA \
|
||||||
|
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
||||||
|
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||||
|
*/
|
||||||
|
//---- ...Or use Dear ImGui's own very basic math operators.
|
||||||
|
//#define IMGUI_DEFINE_MATH_OPERATORS
|
||||||
|
|
||||||
|
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||||
|
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||||
|
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||||
|
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||||
|
//#define ImDrawIdx unsigned int
|
||||||
|
|
||||||
|
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||||
|
//struct ImDrawList;
|
||||||
|
//struct ImDrawCmd;
|
||||||
|
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||||
|
//#define ImDrawCallback MyImDrawCallback
|
||||||
|
|
||||||
|
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
||||||
|
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||||
|
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||||
|
//#define IM_DEBUG_BREAK __debugbreak()
|
||||||
|
|
||||||
|
//---- Debug Tools: Enable slower asserts
|
||||||
|
//#define IMGUI_DEBUG_PARANOID
|
||||||
|
|
||||||
|
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
||||||
|
/*
|
||||||
|
namespace ImGui
|
||||||
|
{
|
||||||
|
void MyFunction(const char* name, MyMatrix44* mtx);
|
||||||
|
}
|
||||||
|
*/
|
16802
vendor/imgui/imgui.cpp
vendored
Normal file
16802
vendor/imgui/imgui.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3703
vendor/imgui/imgui.h
vendored
Normal file
3703
vendor/imgui/imgui.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10370
vendor/imgui/imgui_demo.cpp
vendored
Normal file
10370
vendor/imgui/imgui_demo.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4641
vendor/imgui/imgui_draw.cpp
vendored
Normal file
4641
vendor/imgui/imgui_draw.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3548
vendor/imgui/imgui_internal.h
vendored
Normal file
3548
vendor/imgui/imgui_internal.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4466
vendor/imgui/imgui_tables.cpp
vendored
Normal file
4466
vendor/imgui/imgui_tables.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10254
vendor/imgui/imgui_widgets.cpp
vendored
Normal file
10254
vendor/imgui/imgui_widgets.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
627
vendor/imgui/imstb_rectpack.h
vendored
Normal file
627
vendor/imgui/imstb_rectpack.h
vendored
Normal file
@ -0,0 +1,627 @@
|
|||||||
|
// [DEAR IMGUI]
|
||||||
|
// This is a slightly modified version of stb_rect_pack.h 1.01.
|
||||||
|
// Grep for [DEAR IMGUI] to find the changes.
|
||||||
|
//
|
||||||
|
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
|
||||||
|
// Sean Barrett 2014
|
||||||
|
//
|
||||||
|
// Useful for e.g. packing rectangular textures into an atlas.
|
||||||
|
// Does not do rotation.
|
||||||
|
//
|
||||||
|
// Before #including,
|
||||||
|
//
|
||||||
|
// #define STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
//
|
||||||
|
// in the file that you want to have the implementation.
|
||||||
|
//
|
||||||
|
// Not necessarily the awesomest packing method, but better than
|
||||||
|
// the totally naive one in stb_truetype (which is primarily what
|
||||||
|
// this is meant to replace).
|
||||||
|
//
|
||||||
|
// Has only had a few tests run, may have issues.
|
||||||
|
//
|
||||||
|
// More docs to come.
|
||||||
|
//
|
||||||
|
// No memory allocations; uses qsort() and assert() from stdlib.
|
||||||
|
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
|
||||||
|
//
|
||||||
|
// This library currently uses the Skyline Bottom-Left algorithm.
|
||||||
|
//
|
||||||
|
// Please note: better rectangle packers are welcome! Please
|
||||||
|
// implement them to the same API, but with a different init
|
||||||
|
// function.
|
||||||
|
//
|
||||||
|
// Credits
|
||||||
|
//
|
||||||
|
// Library
|
||||||
|
// Sean Barrett
|
||||||
|
// Minor features
|
||||||
|
// Martins Mozeiko
|
||||||
|
// github:IntellectualKitty
|
||||||
|
//
|
||||||
|
// Bugfixes / warning fixes
|
||||||
|
// Jeremy Jaussaud
|
||||||
|
// Fabian Giesen
|
||||||
|
//
|
||||||
|
// Version history:
|
||||||
|
//
|
||||||
|
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
|
||||||
|
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||||
|
// 0.99 (2019-02-07) warning fixes
|
||||||
|
// 0.11 (2017-03-03) return packing success/fail result
|
||||||
|
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||||
|
// 0.09 (2016-08-27) fix compiler warnings
|
||||||
|
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||||
|
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||||
|
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||||
|
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||||
|
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||||
|
// 0.01: initial release
|
||||||
|
//
|
||||||
|
// LICENSE
|
||||||
|
//
|
||||||
|
// See end of file for license information.
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// INCLUDE SECTION
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||||
|
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||||
|
|
||||||
|
#define STB_RECT_PACK_VERSION 1
|
||||||
|
|
||||||
|
#ifdef STBRP_STATIC
|
||||||
|
#define STBRP_DEF static
|
||||||
|
#else
|
||||||
|
#define STBRP_DEF extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct stbrp_context stbrp_context;
|
||||||
|
typedef struct stbrp_node stbrp_node;
|
||||||
|
typedef struct stbrp_rect stbrp_rect;
|
||||||
|
|
||||||
|
typedef int stbrp_coord;
|
||||||
|
|
||||||
|
#define STBRP__MAXVAL 0x7fffffff
|
||||||
|
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||||
|
|
||||||
|
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||||
|
// Assign packed locations to rectangles. The rectangles are of type
|
||||||
|
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||||
|
// are 'num_rects' many of them.
|
||||||
|
//
|
||||||
|
// Rectangles which are successfully packed have the 'was_packed' flag
|
||||||
|
// set to a non-zero value and 'x' and 'y' store the minimum location
|
||||||
|
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
|
||||||
|
// if you imagine y increasing downwards). Rectangles which do not fit
|
||||||
|
// have the 'was_packed' flag set to 0.
|
||||||
|
//
|
||||||
|
// You should not try to access the 'rects' array from another thread
|
||||||
|
// while this function is running, as the function temporarily reorders
|
||||||
|
// the array while it executes.
|
||||||
|
//
|
||||||
|
// To pack into another rectangle, you need to call stbrp_init_target
|
||||||
|
// again. To continue packing into the same rectangle, you can call
|
||||||
|
// this function again. Calling this multiple times with multiple rect
|
||||||
|
// arrays will probably produce worse packing results than calling it
|
||||||
|
// a single time with the full rectangle array, but the option is
|
||||||
|
// available.
|
||||||
|
//
|
||||||
|
// The function returns 1 if all of the rectangles were successfully
|
||||||
|
// packed and 0 otherwise.
|
||||||
|
|
||||||
|
struct stbrp_rect
|
||||||
|
{
|
||||||
|
// reserved for your use:
|
||||||
|
int id;
|
||||||
|
|
||||||
|
// input:
|
||||||
|
stbrp_coord w, h;
|
||||||
|
|
||||||
|
// output:
|
||||||
|
stbrp_coord x, y;
|
||||||
|
int was_packed; // non-zero if valid packing
|
||||||
|
|
||||||
|
}; // 16 bytes, nominally
|
||||||
|
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
|
||||||
|
// Initialize a rectangle packer to:
|
||||||
|
// pack a rectangle that is 'width' by 'height' in dimensions
|
||||||
|
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
|
||||||
|
//
|
||||||
|
// You must call this function every time you start packing into a new target.
|
||||||
|
//
|
||||||
|
// There is no "shutdown" function. The 'nodes' memory must stay valid for
|
||||||
|
// the following stbrp_pack_rects() call (or calls), but can be freed after
|
||||||
|
// the call (or calls) finish.
|
||||||
|
//
|
||||||
|
// Note: to guarantee best results, either:
|
||||||
|
// 1. make sure 'num_nodes' >= 'width'
|
||||||
|
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
|
||||||
|
//
|
||||||
|
// If you don't do either of the above things, widths will be quantized to multiples
|
||||||
|
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
|
||||||
|
//
|
||||||
|
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
|
||||||
|
// may run out of temporary storage and be unable to pack some rectangles.
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
|
||||||
|
// Optionally call this function after init but before doing any packing to
|
||||||
|
// change the handling of the out-of-temp-memory scenario, described above.
|
||||||
|
// If you call init again, this will be reset to the default (false).
|
||||||
|
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
|
||||||
|
// Optionally select which packing heuristic the library should use. Different
|
||||||
|
// heuristics will produce better/worse results for different data sets.
|
||||||
|
// If you call init again, this will be reset to the default.
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STBRP_HEURISTIC_Skyline_default=0,
|
||||||
|
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
|
||||||
|
STBRP_HEURISTIC_Skyline_BF_sortHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// the details of the following structures don't matter to you, but they must
|
||||||
|
// be visible so you can handle the memory allocations for them
|
||||||
|
|
||||||
|
struct stbrp_node
|
||||||
|
{
|
||||||
|
stbrp_coord x,y;
|
||||||
|
stbrp_node *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct stbrp_context
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int align;
|
||||||
|
int init_mode;
|
||||||
|
int heuristic;
|
||||||
|
int num_nodes;
|
||||||
|
stbrp_node *active_head;
|
||||||
|
stbrp_node *free_head;
|
||||||
|
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// IMPLEMENTATION SECTION
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
#ifndef STBRP_SORT
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define STBRP_SORT qsort
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STBRP_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#define STBRP_ASSERT assert
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define STBRP__NOTUSED(v) (void)(v)
|
||||||
|
#define STBRP__CDECL __cdecl
|
||||||
|
#else
|
||||||
|
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||||
|
#define STBRP__CDECL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STBRP__INIT_skyline = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
||||||
|
{
|
||||||
|
switch (context->init_mode) {
|
||||||
|
case STBRP__INIT_skyline:
|
||||||
|
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||||
|
context->heuristic = heuristic;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
STBRP_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
|
||||||
|
{
|
||||||
|
if (allow_out_of_mem)
|
||||||
|
// if it's ok to run out of memory, then don't bother aligning them;
|
||||||
|
// this gives better packing, but may fail due to OOM (even though
|
||||||
|
// the rectangles easily fit). @TODO a smarter approach would be to only
|
||||||
|
// quantize once we've hit OOM, then we could get rid of this parameter.
|
||||||
|
context->align = 1;
|
||||||
|
else {
|
||||||
|
// if it's not ok to run out of memory, then quantize the widths
|
||||||
|
// so that num_nodes is always enough nodes.
|
||||||
|
//
|
||||||
|
// I.e. num_nodes * align >= width
|
||||||
|
// align >= width / num_nodes
|
||||||
|
// align = ceil(width/num_nodes)
|
||||||
|
|
||||||
|
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i < num_nodes-1; ++i)
|
||||||
|
nodes[i].next = &nodes[i+1];
|
||||||
|
nodes[i].next = NULL;
|
||||||
|
context->init_mode = STBRP__INIT_skyline;
|
||||||
|
context->heuristic = STBRP_HEURISTIC_Skyline_default;
|
||||||
|
context->free_head = &nodes[0];
|
||||||
|
context->active_head = &context->extra[0];
|
||||||
|
context->width = width;
|
||||||
|
context->height = height;
|
||||||
|
context->num_nodes = num_nodes;
|
||||||
|
stbrp_setup_allow_out_of_mem(context, 0);
|
||||||
|
|
||||||
|
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
|
||||||
|
context->extra[0].x = 0;
|
||||||
|
context->extra[0].y = 0;
|
||||||
|
context->extra[0].next = &context->extra[1];
|
||||||
|
context->extra[1].x = (stbrp_coord) width;
|
||||||
|
context->extra[1].y = (1<<30);
|
||||||
|
context->extra[1].next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find minimum y position if it starts at x1
|
||||||
|
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||||
|
{
|
||||||
|
stbrp_node *node = first;
|
||||||
|
int x1 = x0 + width;
|
||||||
|
int min_y, visited_width, waste_area;
|
||||||
|
|
||||||
|
STBRP__NOTUSED(c);
|
||||||
|
|
||||||
|
STBRP_ASSERT(first->x <= x0);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// skip in case we're past the node
|
||||||
|
while (node->next->x <= x0)
|
||||||
|
++node;
|
||||||
|
#else
|
||||||
|
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STBRP_ASSERT(node->x <= x0);
|
||||||
|
|
||||||
|
min_y = 0;
|
||||||
|
waste_area = 0;
|
||||||
|
visited_width = 0;
|
||||||
|
while (node->x < x1) {
|
||||||
|
if (node->y > min_y) {
|
||||||
|
// raise min_y higher.
|
||||||
|
// we've accounted for all waste up to min_y,
|
||||||
|
// but we'll now add more waste for everything we've visted
|
||||||
|
waste_area += visited_width * (node->y - min_y);
|
||||||
|
min_y = node->y;
|
||||||
|
// the first time through, visited_width might be reduced
|
||||||
|
if (node->x < x0)
|
||||||
|
visited_width += node->next->x - x0;
|
||||||
|
else
|
||||||
|
visited_width += node->next->x - node->x;
|
||||||
|
} else {
|
||||||
|
// add waste area
|
||||||
|
int under_width = node->next->x - node->x;
|
||||||
|
if (under_width + visited_width > width)
|
||||||
|
under_width = width - visited_width;
|
||||||
|
waste_area += under_width * (min_y - node->y);
|
||||||
|
visited_width += under_width;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pwaste = waste_area;
|
||||||
|
return min_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int x,y;
|
||||||
|
stbrp_node **prev_link;
|
||||||
|
} stbrp__findresult;
|
||||||
|
|
||||||
|
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
|
||||||
|
{
|
||||||
|
int best_waste = (1<<30), best_x, best_y = (1 << 30);
|
||||||
|
stbrp__findresult fr;
|
||||||
|
stbrp_node **prev, *node, *tail, **best = NULL;
|
||||||
|
|
||||||
|
// align to multiple of c->align
|
||||||
|
width = (width + c->align - 1);
|
||||||
|
width -= width % c->align;
|
||||||
|
STBRP_ASSERT(width % c->align == 0);
|
||||||
|
|
||||||
|
// if it can't possibly fit, bail immediately
|
||||||
|
if (width > c->width || height > c->height) {
|
||||||
|
fr.prev_link = NULL;
|
||||||
|
fr.x = fr.y = 0;
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = c->active_head;
|
||||||
|
prev = &c->active_head;
|
||||||
|
while (node->x + width <= c->width) {
|
||||||
|
int y,waste;
|
||||||
|
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||||
|
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||||
|
// bottom left
|
||||||
|
if (y < best_y) {
|
||||||
|
best_y = y;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// best-fit
|
||||||
|
if (y + height <= c->height) {
|
||||||
|
// can only use it if it first vertically
|
||||||
|
if (y < best_y || (y == best_y && waste < best_waste)) {
|
||||||
|
best_y = y;
|
||||||
|
best_waste = waste;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = &node->next;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
best_x = (best == NULL) ? 0 : (*best)->x;
|
||||||
|
|
||||||
|
// if doing best-fit (BF), we also have to try aligning right edge to each node position
|
||||||
|
//
|
||||||
|
// e.g, if fitting
|
||||||
|
//
|
||||||
|
// ____________________
|
||||||
|
// |____________________|
|
||||||
|
//
|
||||||
|
// into
|
||||||
|
//
|
||||||
|
// | |
|
||||||
|
// | ____________|
|
||||||
|
// |____________|
|
||||||
|
//
|
||||||
|
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
|
||||||
|
//
|
||||||
|
// This makes BF take about 2x the time
|
||||||
|
|
||||||
|
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
|
||||||
|
tail = c->active_head;
|
||||||
|
node = c->active_head;
|
||||||
|
prev = &c->active_head;
|
||||||
|
// find first node that's admissible
|
||||||
|
while (tail->x < width)
|
||||||
|
tail = tail->next;
|
||||||
|
while (tail) {
|
||||||
|
int xpos = tail->x - width;
|
||||||
|
int y,waste;
|
||||||
|
STBRP_ASSERT(xpos >= 0);
|
||||||
|
// find the left position that matches this
|
||||||
|
while (node->next->x <= xpos) {
|
||||||
|
prev = &node->next;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||||
|
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||||
|
if (y + height <= c->height) {
|
||||||
|
if (y <= best_y) {
|
||||||
|
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||||
|
best_x = xpos;
|
||||||
|
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
|
||||||
|
best_y = y;
|
||||||
|
best_waste = waste;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tail = tail->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fr.prev_link = best;
|
||||||
|
fr.x = best_x;
|
||||||
|
fr.y = best_y;
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
|
||||||
|
{
|
||||||
|
// find best position according to heuristic
|
||||||
|
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
|
||||||
|
stbrp_node *node, *cur;
|
||||||
|
|
||||||
|
// bail if:
|
||||||
|
// 1. it failed
|
||||||
|
// 2. the best node doesn't fit (we don't always check this)
|
||||||
|
// 3. we're out of memory
|
||||||
|
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
|
||||||
|
res.prev_link = NULL;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on success, create new node
|
||||||
|
node = context->free_head;
|
||||||
|
node->x = (stbrp_coord) res.x;
|
||||||
|
node->y = (stbrp_coord) (res.y + height);
|
||||||
|
|
||||||
|
context->free_head = node->next;
|
||||||
|
|
||||||
|
// insert the new node into the right starting point, and
|
||||||
|
// let 'cur' point to the remaining nodes needing to be
|
||||||
|
// stiched back in
|
||||||
|
|
||||||
|
cur = *res.prev_link;
|
||||||
|
if (cur->x < res.x) {
|
||||||
|
// preserve the existing one, so start testing with the next one
|
||||||
|
stbrp_node *next = cur->next;
|
||||||
|
cur->next = node;
|
||||||
|
cur = next;
|
||||||
|
} else {
|
||||||
|
*res.prev_link = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// from here, traverse cur and free the nodes, until we get to one
|
||||||
|
// that shouldn't be freed
|
||||||
|
while (cur->next && cur->next->x <= res.x + width) {
|
||||||
|
stbrp_node *next = cur->next;
|
||||||
|
// move the current node to the free list
|
||||||
|
cur->next = context->free_head;
|
||||||
|
context->free_head = cur;
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stitch the list back in
|
||||||
|
node->next = cur;
|
||||||
|
|
||||||
|
if (cur->x < res.x + width)
|
||||||
|
cur->x = (stbrp_coord) (res.x + width);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
cur = context->active_head;
|
||||||
|
while (cur->x < context->width) {
|
||||||
|
STBRP_ASSERT(cur->x < cur->next->x);
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(cur->next == NULL);
|
||||||
|
|
||||||
|
{
|
||||||
|
int count=0;
|
||||||
|
cur = context->active_head;
|
||||||
|
while (cur) {
|
||||||
|
cur = cur->next;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
cur = context->free_head;
|
||||||
|
while (cur) {
|
||||||
|
cur = cur->next;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(count == context->num_nodes+2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||||
|
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||||
|
if (p->h > q->h)
|
||||||
|
return -1;
|
||||||
|
if (p->h < q->h)
|
||||||
|
return 1;
|
||||||
|
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||||
|
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||||
|
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||||
|
{
|
||||||
|
int i, all_rects_packed = 1;
|
||||||
|
|
||||||
|
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||||
|
for (i=0; i < num_rects; ++i) {
|
||||||
|
rects[i].was_packed = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort according to heuristic
|
||||||
|
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
|
||||||
|
|
||||||
|
for (i=0; i < num_rects; ++i) {
|
||||||
|
if (rects[i].w == 0 || rects[i].h == 0) {
|
||||||
|
rects[i].x = rects[i].y = 0; // empty rect needs no space
|
||||||
|
} else {
|
||||||
|
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
|
||||||
|
if (fr.prev_link) {
|
||||||
|
rects[i].x = (stbrp_coord) fr.x;
|
||||||
|
rects[i].y = (stbrp_coord) fr.y;
|
||||||
|
} else {
|
||||||
|
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsort
|
||||||
|
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
|
||||||
|
|
||||||
|
// set was_packed flags and all_rects_packed status
|
||||||
|
for (i=0; i < num_rects; ++i) {
|
||||||
|
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||||
|
if (!rects[i].was_packed)
|
||||||
|
all_rects_packed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the all_rects_packed status
|
||||||
|
return all_rects_packed;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
ALTERNATIVE A - MIT License
|
||||||
|
Copyright (c) 2017 Sean Barrett
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||||
|
software, either in source code form or as a compiled binary, for any purpose,
|
||||||
|
commercial or non-commercial, and by any means.
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||||
|
software dedicate any and all copyright interest in the software to the public
|
||||||
|
domain. We make this dedication for the benefit of the public at large and to
|
||||||
|
the detriment of our heirs and successors. We intend this dedication to be an
|
||||||
|
overt act of relinquishment in perpetuity of all present and future rights to
|
||||||
|
this software under copyright law.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
*/
|
1469
vendor/imgui/imstb_textedit.h
vendored
Normal file
1469
vendor/imgui/imstb_textedit.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5085
vendor/imgui/imstb_truetype.h
vendored
Normal file
5085
vendor/imgui/imstb_truetype.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7988
vendor/imgui/stb_image.h
vendored
Normal file
7988
vendor/imgui/stb_image.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user