feat: 添加独立的输入系统和平台抽象层
- 新增 Platform 模块:PlatformTypes.h, Window.h, WindowsWindow - 新增 Input 模块:InputTypes, InputEvent, InputAxis, InputModule, InputManager - 新增 WindowsInputModule 处理 Win32 消息转换 - 将 RHI 集成测试从 render_model 迁移到 sphere - 更新 CMakeLists.txt 添加 Platform 和 Input 模块
This commit is contained in:
191
engine/src/Platform/Windows/WindowsWindow.cpp
Normal file
191
engine/src/Platform/Windows/WindowsWindow.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
#include "Platform/Windows/WindowsWindow.h"
|
||||
#include <Windows.h>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Platform {
|
||||
|
||||
static const char WINDOW_CLASS_NAME[] = "XCEngineWindowClass";
|
||||
|
||||
WindowsWindow::WindowsWindow()
|
||||
: m_hwnd(nullptr)
|
||||
, m_hInstance(nullptr)
|
||||
, m_fullscreen(false)
|
||||
, m_shouldClose(false)
|
||||
, m_minimized(false) {
|
||||
}
|
||||
|
||||
WindowsWindow::~WindowsWindow() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool WindowsWindow::Create(const WindowDesc& desc) {
|
||||
m_hInstance = GetModuleHandle(nullptr);
|
||||
|
||||
RegisterWindowClass();
|
||||
|
||||
DWORD style = WS_OVERLAPPEDWINDOW;
|
||||
DWORD exStyle = WS_EX_APPWINDOW;
|
||||
|
||||
RECT rect = {0, 0, static_cast<LONG>(desc.width), static_cast<LONG>(desc.height)};
|
||||
AdjustWindowRect(&rect, style, FALSE);
|
||||
|
||||
m_hwnd = CreateWindowExA(
|
||||
exStyle,
|
||||
WINDOW_CLASS_NAME,
|
||||
desc.title.CStr(),
|
||||
style,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
nullptr,
|
||||
nullptr,
|
||||
m_hInstance,
|
||||
this
|
||||
);
|
||||
|
||||
if (!m_hwnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fullscreen = desc.fullscreen;
|
||||
if (m_fullscreen) {
|
||||
SetFullscreen(true);
|
||||
}
|
||||
|
||||
ShowWindow(m_hwnd, SW_SHOWNORMAL);
|
||||
UpdateWindow(m_hwnd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowsWindow::Destroy() {
|
||||
if (m_hwnd) {
|
||||
DestroyWindow(m_hwnd);
|
||||
m_hwnd = nullptr;
|
||||
}
|
||||
|
||||
UnregisterClassA(WINDOW_CLASS_NAME, m_hInstance);
|
||||
m_hInstance = nullptr;
|
||||
}
|
||||
|
||||
void WindowsWindow::PumpEvents() {
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
m_shouldClose = true;
|
||||
break;
|
||||
}
|
||||
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsWindow::SetTitle(const Containers::String& title) {
|
||||
if (m_hwnd) {
|
||||
SetWindowTextA(m_hwnd, title.CStr());
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsWindow::SetFullscreen(bool fullscreen) {
|
||||
if (!m_hwnd) return;
|
||||
|
||||
if (fullscreen) {
|
||||
MONITORINFO mi = {sizeof(mi)};
|
||||
GetWindowRect(m_hwnd, &m_oldWindowRect);
|
||||
GetMonitorInfo(MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTOPRIMARY), &mi);
|
||||
SetWindowLong(m_hwnd, GWL_STYLE, WS_POPUP | WS_SYSMENU);
|
||||
SetWindowPos(m_hwnd, HWND_TOP,
|
||||
mi.rcMonitor.left, mi.rcMonitor.top,
|
||||
mi.rcMonitor.right - mi.rcMonitor.left,
|
||||
mi.rcMonitor.bottom - mi.rcMonitor.top,
|
||||
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
|
||||
m_fullscreen = true;
|
||||
} else {
|
||||
SetWindowLong(m_hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
|
||||
SetWindowPos(m_hwnd, HWND_NOTOPMOST,
|
||||
m_oldWindowRect.left, m_oldWindowRect.top,
|
||||
m_oldWindowRect.right - m_oldWindowRect.left,
|
||||
m_oldWindowRect.bottom - m_oldWindowRect.top,
|
||||
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
|
||||
m_fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsWindow::Minimize() {
|
||||
if (m_hwnd) {
|
||||
ShowWindow(m_hwnd, SW_MINIMIZE);
|
||||
m_minimized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsWindow::Maximize() {
|
||||
if (m_hwnd) {
|
||||
ShowWindow(m_hwnd, SW_MAXIMIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsWindow::Restore() {
|
||||
if (m_hwnd) {
|
||||
ShowWindow(m_hwnd, SW_RESTORE);
|
||||
m_minimized = false;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsWindow::SetMessageCallback(std::function<void(HWND, UINT, WPARAM, LPARAM)> callback) {
|
||||
m_messageCallback = callback;
|
||||
}
|
||||
|
||||
void WindowsWindow::RegisterWindowClass() {
|
||||
WNDCLASSEXA wc = {};
|
||||
wc.cbSize = sizeof(WNDCLASSEX);
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = m_hInstance;
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.lpszClassName = WINDOW_CLASS_NAME;
|
||||
|
||||
RegisterClassExA(&wc);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WindowsWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
WindowsWindow* window = nullptr;
|
||||
|
||||
if (msg == WM_NCCREATE) {
|
||||
CREATESTRUCTA* cs = reinterpret_cast<CREATESTRUCTA*>(lParam);
|
||||
window = reinterpret_cast<WindowsWindow*>(cs->lpCreateParams);
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(window));
|
||||
} else {
|
||||
window = reinterpret_cast<WindowsWindow*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
}
|
||||
|
||||
if (window && window->m_messageCallback) {
|
||||
window->m_messageCallback(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
switch (msg) {
|
||||
case WM_CLOSE:
|
||||
if (window) window->m_shouldClose = true;
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
|
||||
case WM_SIZE:
|
||||
if (window) {
|
||||
if (wParam == SIZE_MINIMIZED) {
|
||||
window->m_minimized = true;
|
||||
} else {
|
||||
window->m_minimized = false;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user