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:
2026-03-22 15:21:52 +08:00
parent 6af872e9eb
commit 36d3decef6
29 changed files with 2896 additions and 236 deletions

View 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