mirror of
https://gitea.tendokyu.moe/beerpsi/segatools-configurator.git
synced 2024-11-27 16:40:48 +01:00
241 lines
7.8 KiB
C++
241 lines
7.8 KiB
C++
|
#include <format>
|
||
|
|
||
|
#include <imgui.h>
|
||
|
#include <backends/imgui_impl_dx9.h>
|
||
|
#include <backends/imgui_impl_win32.h>
|
||
|
#include <d3d9.h>
|
||
|
#include <tchar.h>
|
||
|
|
||
|
#include "imgui_internal.h"
|
||
|
#include "configurator.h"
|
||
|
|
||
|
// Data
|
||
|
static LPDIRECT3D9 g_pD3D = nullptr;
|
||
|
static LPDIRECT3DDEVICE9 g_pd3dDevice = nullptr;
|
||
|
static UINT g_ResizeWidth = 0, g_ResizeHeight = 0;
|
||
|
static D3DPRESENT_PARAMETERS g_d3dpp = {};
|
||
|
static Configurator* g_Configurator = nullptr;
|
||
|
|
||
|
bool CreateDeviceD3D(HWND hWnd);
|
||
|
void CleanupDeviceD3D();
|
||
|
void ResetDevice();
|
||
|
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
|
||
|
// Create application window
|
||
|
//ImGui_ImplWin32_EnableDpiAwareness();
|
||
|
WNDCLASSEXW wc = {
|
||
|
sizeof(wc),
|
||
|
CS_CLASSDC,
|
||
|
WndProc,
|
||
|
0L,
|
||
|
0L,
|
||
|
GetModuleHandle(nullptr),
|
||
|
nullptr,
|
||
|
nullptr,
|
||
|
nullptr,
|
||
|
nullptr,
|
||
|
L"SegaTools Configurator",
|
||
|
nullptr
|
||
|
};
|
||
|
|
||
|
RegisterClassExW(&wc);
|
||
|
|
||
|
HWND hwnd = CreateWindowW(
|
||
|
wc.lpszClassName,
|
||
|
L"SegaTools Configurator",
|
||
|
WS_OVERLAPPEDWINDOW,
|
||
|
100, 100, 800, 600,
|
||
|
nullptr,
|
||
|
nullptr,
|
||
|
wc.hInstance,
|
||
|
nullptr
|
||
|
);
|
||
|
|
||
|
// Initialize Direct3D
|
||
|
if (!CreateDeviceD3D(hwnd)) {
|
||
|
CleanupDeviceD3D();
|
||
|
UnregisterClassW(wc.lpszClassName, wc.hInstance);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
ShowWindow(hwnd, SW_SHOWDEFAULT);
|
||
|
UpdateWindow(hwnd);
|
||
|
|
||
|
// Setup Dear ImGui context
|
||
|
IMGUI_CHECKVERSION();
|
||
|
ImGui::CreateContext();
|
||
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||
|
|
||
|
// Setup Dear ImGui style
|
||
|
ImGui::StyleColorsDark();
|
||
|
|
||
|
// Setup Platform/Renderer backends
|
||
|
ImGui_ImplWin32_Init(hwnd);
|
||
|
ImGui_ImplDX9_Init(g_pd3dDevice);
|
||
|
|
||
|
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||
|
|
||
|
bool done = false;
|
||
|
g_Configurator = new Configurator();
|
||
|
|
||
|
while (!done) {
|
||
|
// Poll and handle messages (inputs, window resize, etc.)
|
||
|
// See the WndProc() function below for our to dispatch events to the Win32 backend.
|
||
|
MSG msg;
|
||
|
|
||
|
while (PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) {
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
if (msg.message == WM_QUIT)
|
||
|
done = true;
|
||
|
}
|
||
|
|
||
|
if (done) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Handle window resize (we don't resize directly in the WM_SIZE handler)
|
||
|
if (g_ResizeWidth != 0 && g_ResizeHeight != 0) {
|
||
|
g_d3dpp.BackBufferWidth = g_ResizeWidth;
|
||
|
g_d3dpp.BackBufferHeight = g_ResizeHeight;
|
||
|
g_ResizeWidth = g_ResizeHeight = 0;
|
||
|
ResetDevice();
|
||
|
}
|
||
|
|
||
|
// Start the Dear ImGui frame
|
||
|
ImGui_ImplDX9_NewFrame();
|
||
|
ImGui_ImplWin32_NewFrame();
|
||
|
ImGui::NewFrame();
|
||
|
|
||
|
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||
|
ImGui::SetNextWindowPos(viewport->Pos);
|
||
|
|
||
|
ImVec2 viewportSize = viewport->Size;
|
||
|
ImGui::SetNextWindowSize(viewportSize);
|
||
|
// ImGui::SetNextWindowViewport(viewport->ID);
|
||
|
|
||
|
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
|
||
|
ImGuiWindowFlags_NoMove;
|
||
|
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||
|
|
||
|
static bool p_open = true;
|
||
|
ImGui::Begin("segatools configurator", &p_open, window_flags);
|
||
|
|
||
|
g_Configurator->build_content();
|
||
|
|
||
|
ImGui::End();
|
||
|
|
||
|
// Rendering
|
||
|
ImGui::EndFrame();
|
||
|
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||
|
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||
|
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
|
||
|
|
||
|
D3DCOLOR clear_col_dx = D3DCOLOR_RGBA(
|
||
|
(int)(clear_color.x * clear_color.w * 255.0f),
|
||
|
(int)(clear_color.y * clear_color.w * 255.0f),
|
||
|
(int)(clear_color.z * clear_color.w * 255.0f),
|
||
|
(int)(clear_color.w * 255.0f)
|
||
|
);
|
||
|
|
||
|
g_pd3dDevice->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0);
|
||
|
|
||
|
if (g_pd3dDevice->BeginScene() >= 0) {
|
||
|
ImGui::Render();
|
||
|
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
|
||
|
g_pd3dDevice->EndScene();
|
||
|
}
|
||
|
|
||
|
HRESULT result = g_pd3dDevice->Present(nullptr, nullptr, nullptr, nullptr);
|
||
|
|
||
|
// Handle loss of D3D9 device
|
||
|
if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) {
|
||
|
ResetDevice();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
ImGui_ImplDX9_Shutdown();
|
||
|
ImGui_ImplWin32_Shutdown();
|
||
|
ImGui::DestroyContext();
|
||
|
|
||
|
CleanupDeviceD3D();
|
||
|
DestroyWindow(hwnd);
|
||
|
UnregisterClassW(wc.lpszClassName, wc.hInstance);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Helper functions
|
||
|
|
||
|
bool CreateDeviceD3D(HWND hWnd) {
|
||
|
if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == nullptr)
|
||
|
return false;
|
||
|
|
||
|
// Create the D3DDevice
|
||
|
ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
|
||
|
g_d3dpp.Windowed = TRUE;
|
||
|
g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||
|
g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Need to use an explicit format with alpha if needing per-pixel alpha composition.
|
||
|
g_d3dpp.EnableAutoDepthStencil = TRUE;
|
||
|
g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
|
||
|
g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // Present with vsync
|
||
|
//g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync, maximum unthrottled framerate
|
||
|
if (g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CleanupDeviceD3D() {
|
||
|
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = nullptr; }
|
||
|
if (g_pD3D) { g_pD3D->Release(); g_pD3D = nullptr; }
|
||
|
}
|
||
|
|
||
|
void ResetDevice() {
|
||
|
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||
|
HRESULT hr = g_pd3dDevice->Reset(&g_d3dpp);
|
||
|
if (hr == D3DERR_INVALIDCALL)
|
||
|
IM_ASSERT(0);
|
||
|
ImGui_ImplDX9_CreateDeviceObjects();
|
||
|
}
|
||
|
|
||
|
// Forward declare message handler from imgui_impl_win32.cpp
|
||
|
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
// Win32 message handler
|
||
|
// 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.
|
||
|
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); // Queue resize
|
||
|
g_ResizeHeight = (UINT)HIWORD(lParam);
|
||
|
return 0;
|
||
|
case WM_SYSCOMMAND:
|
||
|
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
|
||
|
return 0;
|
||
|
break;
|
||
|
case WM_DESTROY:
|
||
|
PostQuitMessage(0);
|
||
|
return 0;
|
||
|
case WM_KEYDOWN:
|
||
|
g_Configurator->set_key_code(wParam);
|
||
|
default:
|
||
|
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
||
|
}
|
||
|
|