313 lines
7.2 KiB
C++
313 lines
7.2 KiB
C++
|
# include "platform.h"
|
||
|
# include "setup.h"
|
||
|
|
||
|
# if BACKEND(IMGUI_WIN32)
|
||
|
|
||
|
# include "application.h"
|
||
|
# include "renderer.h"
|
||
|
|
||
|
# define NOMINMAX
|
||
|
# define WIN32_LEAN_AND_MEAN
|
||
|
# include <windows.h>
|
||
|
# include <tchar.h>
|
||
|
# include <string>
|
||
|
|
||
|
# include <imgui.h>
|
||
|
# include "imgui_impl_win32.h"
|
||
|
|
||
|
# if defined(_UNICODE)
|
||
|
std::wstring Utf8ToNative(const std::string& str)
|
||
|
{
|
||
|
int size = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), nullptr, 0);
|
||
|
std::wstring result(size, 0);
|
||
|
MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), (wchar_t*)result.data(), size);
|
||
|
return result;
|
||
|
}
|
||
|
# else
|
||
|
std::string Utf8ToNative(const std::string& str)
|
||
|
{
|
||
|
return str;
|
||
|
}
|
||
|
# endif
|
||
|
|
||
|
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
struct PlatformWin32 final
|
||
|
: Platform
|
||
|
{
|
||
|
static PlatformWin32* s_Instance;
|
||
|
|
||
|
PlatformWin32(Application& application);
|
||
|
|
||
|
bool ApplicationStart(int argc, char** argv) override;
|
||
|
void ApplicationStop() override;
|
||
|
bool OpenMainWindow(const char* title, int width, int height) override;
|
||
|
bool CloseMainWindow() override;
|
||
|
void* GetMainWindowHandle() const override;
|
||
|
void SetMainWindowTitle(const char* title) override;
|
||
|
void ShowMainWindow() override;
|
||
|
bool ProcessMainWindowEvents() override;
|
||
|
bool IsMainWindowVisible() const override;
|
||
|
void SetRenderer(Renderer* renderer) override;
|
||
|
void NewFrame() override;
|
||
|
void FinishFrame() override;
|
||
|
void Quit() override;
|
||
|
|
||
|
void SetDpiScale(float dpiScale);
|
||
|
|
||
|
LRESULT WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
Application& m_Application;
|
||
|
WNDCLASSEX m_WindowClass = {};
|
||
|
HWND m_MainWindowHandle = nullptr;
|
||
|
bool m_IsMinimized = false;
|
||
|
bool m_WasMinimized = false;
|
||
|
bool m_CanCloseResult = false;
|
||
|
Renderer* m_Renderer = nullptr;
|
||
|
};
|
||
|
|
||
|
std::unique_ptr<Platform> CreatePlatform(Application& application)
|
||
|
{
|
||
|
return std::make_unique<PlatformWin32>(application);
|
||
|
}
|
||
|
|
||
|
PlatformWin32* PlatformWin32::s_Instance = nullptr;
|
||
|
|
||
|
PlatformWin32::PlatformWin32(Application& application)
|
||
|
: m_Application(application)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
bool PlatformWin32::ApplicationStart(int argc, char** argv)
|
||
|
{
|
||
|
if (s_Instance)
|
||
|
return false;
|
||
|
|
||
|
s_Instance = this;
|
||
|
|
||
|
auto winProc = [](HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -> LRESULT
|
||
|
{
|
||
|
return s_Instance->WinProc(hWnd, msg, wParam, lParam);
|
||
|
};
|
||
|
|
||
|
m_WindowClass =
|
||
|
{
|
||
|
sizeof(WNDCLASSEX),
|
||
|
CS_CLASSDC,
|
||
|
winProc,
|
||
|
0L,
|
||
|
0L,
|
||
|
GetModuleHandle(nullptr),
|
||
|
LoadIcon(GetModuleHandle(nullptr),
|
||
|
IDI_APPLICATION),
|
||
|
LoadCursor(nullptr, IDC_ARROW),
|
||
|
nullptr,
|
||
|
nullptr,
|
||
|
_T("imgui-node-editor-application"),
|
||
|
LoadIcon(GetModuleHandle(nullptr),
|
||
|
IDI_APPLICATION)
|
||
|
};
|
||
|
|
||
|
if (!RegisterClassEx(&m_WindowClass))
|
||
|
{
|
||
|
s_Instance = nullptr;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
ImGui_ImplWin32_EnableDpiAwareness();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void PlatformWin32::ApplicationStop()
|
||
|
{
|
||
|
if (!s_Instance)
|
||
|
return;
|
||
|
|
||
|
UnregisterClass(m_WindowClass.lpszClassName, m_WindowClass.hInstance);
|
||
|
|
||
|
s_Instance = nullptr;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool PlatformWin32::OpenMainWindow(const char* title, int width, int height)
|
||
|
{
|
||
|
if (m_MainWindowHandle)
|
||
|
return false;
|
||
|
|
||
|
m_MainWindowHandle = CreateWindow(
|
||
|
m_WindowClass.lpszClassName,
|
||
|
Utf8ToNative(title).c_str(),
|
||
|
WS_OVERLAPPEDWINDOW,
|
||
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
||
|
width < 0 ? CW_USEDEFAULT : width,
|
||
|
height < 0 ? CW_USEDEFAULT : height,
|
||
|
nullptr, nullptr, m_WindowClass.hInstance, nullptr);
|
||
|
|
||
|
if (!m_MainWindowHandle)
|
||
|
return false;
|
||
|
|
||
|
if (!ImGui_ImplWin32_Init(m_MainWindowHandle))
|
||
|
{
|
||
|
DestroyWindow(m_MainWindowHandle);
|
||
|
m_MainWindowHandle = nullptr;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
SetDpiScale(ImGui_ImplWin32_GetDpiScaleForHwnd(m_MainWindowHandle));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool PlatformWin32::CloseMainWindow()
|
||
|
{
|
||
|
if (m_MainWindowHandle == nullptr)
|
||
|
return true;
|
||
|
|
||
|
SendMessage(m_MainWindowHandle, WM_CLOSE, 0, 0);
|
||
|
|
||
|
return m_CanCloseResult;
|
||
|
}
|
||
|
|
||
|
void* PlatformWin32::GetMainWindowHandle() const
|
||
|
{
|
||
|
return m_MainWindowHandle;
|
||
|
}
|
||
|
|
||
|
void PlatformWin32::SetMainWindowTitle(const char* title)
|
||
|
{
|
||
|
SetWindowText(m_MainWindowHandle, Utf8ToNative(title).c_str());
|
||
|
}
|
||
|
|
||
|
void PlatformWin32::ShowMainWindow()
|
||
|
{
|
||
|
if (m_MainWindowHandle == nullptr)
|
||
|
return;
|
||
|
|
||
|
//ShowWindow(m_MainWindowHandle, SW_SHOWMAXIMIZED);
|
||
|
ShowWindow(m_MainWindowHandle, SW_SHOW);
|
||
|
UpdateWindow(m_MainWindowHandle);
|
||
|
}
|
||
|
|
||
|
bool PlatformWin32::ProcessMainWindowEvents()
|
||
|
{
|
||
|
if (m_MainWindowHandle == nullptr)
|
||
|
return false;
|
||
|
|
||
|
auto fetchMessage = [this](MSG* msg) -> bool
|
||
|
{
|
||
|
if (!m_IsMinimized)
|
||
|
return PeekMessage(msg, nullptr, 0U, 0U, PM_REMOVE) != 0;
|
||
|
else
|
||
|
return GetMessage(msg, nullptr, 0U, 0U) != 0;
|
||
|
};
|
||
|
|
||
|
MSG msg = {};
|
||
|
while (fetchMessage(&msg))
|
||
|
{
|
||
|
if (msg.message == WM_KEYDOWN && (msg.wParam == VK_ESCAPE))
|
||
|
PostQuitMessage(0);
|
||
|
|
||
|
if (msg.message == WM_QUIT)
|
||
|
return false;
|
||
|
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool PlatformWin32::IsMainWindowVisible() const
|
||
|
{
|
||
|
if (m_MainWindowHandle == nullptr)
|
||
|
return false;
|
||
|
|
||
|
if (m_IsMinimized)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void PlatformWin32::SetRenderer(Renderer* renderer)
|
||
|
{
|
||
|
m_Renderer = renderer;
|
||
|
}
|
||
|
|
||
|
void PlatformWin32::NewFrame()
|
||
|
{
|
||
|
ImGui_ImplWin32_NewFrame();
|
||
|
|
||
|
if (m_WasMinimized)
|
||
|
{
|
||
|
ImGui::GetIO().DeltaTime = 0.1e-6f;
|
||
|
m_WasMinimized = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PlatformWin32::FinishFrame()
|
||
|
{
|
||
|
if (m_Renderer)
|
||
|
m_Renderer->Present();
|
||
|
}
|
||
|
|
||
|
void PlatformWin32::Quit()
|
||
|
{
|
||
|
PostQuitMessage(0);
|
||
|
}
|
||
|
|
||
|
void PlatformWin32::SetDpiScale(float dpiScale)
|
||
|
{
|
||
|
SetWindowScale(dpiScale);
|
||
|
SetFramebufferScale(dpiScale);
|
||
|
}
|
||
|
|
||
|
LRESULT PlatformWin32::WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
|
||
|
return 1;
|
||
|
|
||
|
switch (msg)
|
||
|
{
|
||
|
case WM_CLOSE:
|
||
|
m_CanCloseResult = m_Application.CanClose();
|
||
|
if (m_CanCloseResult)
|
||
|
{
|
||
|
ImGui_ImplWin32_Shutdown();
|
||
|
DestroyWindow(hWnd);
|
||
|
}
|
||
|
return 0;
|
||
|
|
||
|
case WM_SIZE:
|
||
|
if (wParam == SIZE_MINIMIZED)
|
||
|
{
|
||
|
m_IsMinimized = true;
|
||
|
m_WasMinimized = true;
|
||
|
}
|
||
|
else if (wParam == SIZE_RESTORED && m_IsMinimized)
|
||
|
{
|
||
|
m_IsMinimized = false;
|
||
|
}
|
||
|
|
||
|
if (m_Renderer != nullptr && wParam != SIZE_MINIMIZED)
|
||
|
m_Renderer->Resize(static_cast<int>(LOWORD(lParam)), static_cast<int>(HIWORD(lParam)));
|
||
|
return 0;
|
||
|
|
||
|
case WM_SYSCOMMAND:
|
||
|
if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
|
||
|
return 0;
|
||
|
break;
|
||
|
|
||
|
case WM_DPICHANGED:
|
||
|
SetDpiScale(ImGui_ImplWin32_GetDpiScaleForHwnd(hWnd));
|
||
|
return 0;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
PostQuitMessage(0);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
# endif // BACKEND(IMGUI_WIN32)
|