From fa2d2713d7d46057b77ffc8b61c8ad6ecc34a008 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sun, 22 Mar 2026 17:14:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=20Window=20=E4=B8=8E?= =?UTF-8?q?=20InputModule=20=E6=B6=88=E6=81=AF=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- engine/CMakeLists.txt | 1 + engine/include/XCEngine/Input/InputModule.h | 2 + .../Input/Platform/WindowsInputModule.h | 15 +- engine/include/XCEngine/Platform/Window.h | 10 + .../src/Input/Windows/WindowsInputModule.cpp | 32 +-- engine/src/Platform/Window.cpp | 11 + engine/src/Platform/Windows/WindowsWindow.cpp | 14 ++ tests/Input/CMakeLists.txt | 1 + tests/Input/test_windows_input_module.cpp | 194 ++++++++++++++++++ 9 files changed, 256 insertions(+), 24 deletions(-) create mode 100644 engine/src/Platform/Window.cpp create mode 100644 tests/Input/test_windows_input_module.cpp diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index b674778f..eedf01c8 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -227,6 +227,7 @@ add_library(XCEngine STATIC ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Platform/PlatformTypes.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Platform/Window.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Platform/Windows/WindowsWindow.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/Platform/Window.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Platform/Windows/WindowsWindow.cpp # Input diff --git a/engine/include/XCEngine/Input/InputModule.h b/engine/include/XCEngine/Input/InputModule.h index 7aef2d00..51b0e2d9 100644 --- a/engine/include/XCEngine/Input/InputModule.h +++ b/engine/include/XCEngine/Input/InputModule.h @@ -1,4 +1,5 @@ #pragma once +#include namespace XCEngine { namespace Input { @@ -10,6 +11,7 @@ public: virtual void Initialize(void* windowHandle) = 0; virtual void Shutdown() = 0; virtual void PumpEvents() = 0; + virtual void HandleMessage(size_t hwnd, unsigned int msg, size_t wParam, size_t lParam) = 0; protected: InputModule() = default; diff --git a/engine/include/XCEngine/Input/Platform/WindowsInputModule.h b/engine/include/XCEngine/Input/Platform/WindowsInputModule.h index 3357a05f..69f49510 100644 --- a/engine/include/XCEngine/Input/Platform/WindowsInputModule.h +++ b/engine/include/XCEngine/Input/Platform/WindowsInputModule.h @@ -16,16 +16,15 @@ public: void Initialize(void* windowHandle) override; void Shutdown() override; void PumpEvents() override; - - void HandleMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); + void HandleMessage(size_t hwnd, unsigned int msg, size_t wParam, size_t lParam) override; private: - void ProcessKeyDown(WPARAM wParam, LPARAM lParam); - void ProcessKeyUp(WPARAM wParam); - void ProcessMouseMove(WPARAM wParam, LPARAM lParam); - void ProcessMouseButton(WPARAM wParam, LPARAM lParam, bool pressed, MouseButton button); - void ProcessMouseWheel(WPARAM wParam, LPARAM lParam); - void ProcessCharInput(WPARAM wParam); + void ProcessKeyDown(size_t wParam, size_t lParam); + void ProcessKeyUp(size_t wParam); + void ProcessMouseMove(size_t wParam, size_t lParam); + void ProcessMouseButton(size_t wParam, size_t lParam, bool pressed, MouseButton button); + void ProcessMouseWheel(size_t wParam, size_t lParam); + void ProcessCharInput(size_t wParam); KeyCode VKCodeToKeyCode(int vkCode); diff --git a/engine/include/XCEngine/Platform/Window.h b/engine/include/XCEngine/Platform/Window.h index 6ac4ef90..a967495c 100644 --- a/engine/include/XCEngine/Platform/Window.h +++ b/engine/include/XCEngine/Platform/Window.h @@ -2,6 +2,10 @@ #include "PlatformTypes.h" namespace XCEngine { +namespace Input { +class InputModule; +} + namespace Platform { class Window { @@ -23,6 +27,12 @@ public: virtual bool ShouldClose() const = 0; virtual void* GetNativeHandle() = 0; + + void SetInputModule(Input::InputModule* module); + Input::InputModule* GetInputModule() const { return m_inputModule; } + +protected: + Input::InputModule* m_inputModule = nullptr; }; } // namespace Platform diff --git a/engine/src/Input/Windows/WindowsInputModule.cpp b/engine/src/Input/Windows/WindowsInputModule.cpp index f59fe181..682cc1f4 100644 --- a/engine/src/Input/Windows/WindowsInputModule.cpp +++ b/engine/src/Input/Windows/WindowsInputModule.cpp @@ -33,7 +33,7 @@ void WindowsInputModule::Shutdown() { void WindowsInputModule::PumpEvents() { } -void WindowsInputModule::HandleMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { +void WindowsInputModule::HandleMessage(size_t hwnd, unsigned int message, size_t wParam, size_t lParam) { if (!m_isInitialized) return; switch (message) { @@ -83,17 +83,17 @@ void WindowsInputModule::HandleMessage(HWND hwnd, UINT message, WPARAM wParam, L case WM_XBUTTONDOWN: ProcessMouseButton(wParam, lParam, true, - (HIWORD(wParam) == 1) ? MouseButton::Button4 : MouseButton::Button5); + (HIWORD(static_cast(wParam)) == 1) ? MouseButton::Button4 : MouseButton::Button5); break; case WM_XBUTTONUP: ProcessMouseButton(wParam, lParam, false, - (HIWORD(wParam) == 1) ? MouseButton::Button4 : MouseButton::Button5); + (HIWORD(static_cast(wParam)) == 1) ? MouseButton::Button4 : MouseButton::Button5); break; } } -void WindowsInputModule::ProcessKeyDown(WPARAM wParam, LPARAM lParam) { +void WindowsInputModule::ProcessKeyDown(size_t wParam, size_t lParam) { bool repeat = (lParam & (1 << 30)) != 0; KeyCode keyCode = VKCodeToKeyCode(static_cast(wParam)); @@ -107,7 +107,7 @@ void WindowsInputModule::ProcessKeyDown(WPARAM wParam, LPARAM lParam) { } } -void WindowsInputModule::ProcessKeyUp(WPARAM wParam) { +void WindowsInputModule::ProcessKeyUp(size_t wParam) { KeyCode keyCode = VKCodeToKeyCode(static_cast(wParam)); bool alt = (GetKeyState(VK_MENU) & 0x8000) != 0; @@ -120,9 +120,9 @@ void WindowsInputModule::ProcessKeyUp(WPARAM wParam) { } } -void WindowsInputModule::ProcessMouseMove(WPARAM wParam, LPARAM lParam) { - int x = LOWORD(lParam); - int y = HIWORD(lParam); +void WindowsInputModule::ProcessMouseMove(size_t wParam, size_t lParam) { + int x = LOWORD(static_cast(lParam)); + int y = HIWORD(static_cast(lParam)); int deltaX = x - static_cast(m_lastMousePosition.x); int deltaY = y - static_cast(m_lastMousePosition.y); @@ -133,22 +133,22 @@ void WindowsInputModule::ProcessMouseMove(WPARAM wParam, LPARAM lParam) { InputManager::Get().ProcessMouseMove(x, y, deltaX, deltaY); } -void WindowsInputModule::ProcessMouseButton(WPARAM wParam, LPARAM lParam, bool pressed, MouseButton button) { - int x = LOWORD(lParam); - int y = HIWORD(lParam); +void WindowsInputModule::ProcessMouseButton(size_t wParam, size_t lParam, bool pressed, MouseButton button) { + int x = LOWORD(static_cast(lParam)); + int y = HIWORD(static_cast(lParam)); InputManager::Get().ProcessMouseButton(button, pressed, x, y); } -void WindowsInputModule::ProcessMouseWheel(WPARAM wParam, LPARAM lParam) { - int x = LOWORD(lParam); - int y = HIWORD(lParam); - short delta = static_cast(HIWORD(wParam)); +void WindowsInputModule::ProcessMouseWheel(size_t wParam, size_t lParam) { + int x = LOWORD(static_cast(lParam)); + int y = HIWORD(static_cast(lParam)); + short delta = static_cast(HIWORD(static_cast(wParam))); InputManager::Get().ProcessMouseWheel(static_cast(delta) / 120.0f, x, y); } -void WindowsInputModule::ProcessCharInput(WPARAM wParam) { +void WindowsInputModule::ProcessCharInput(size_t wParam) { char c = static_cast(wParam); if (c >= 32 && c < 127) { diff --git a/engine/src/Platform/Window.cpp b/engine/src/Platform/Window.cpp new file mode 100644 index 00000000..6e06647c --- /dev/null +++ b/engine/src/Platform/Window.cpp @@ -0,0 +1,11 @@ +#include "Platform/Window.h" + +namespace XCEngine { +namespace Platform { + +void Window::SetInputModule(Input::InputModule* module) { + m_inputModule = module; +} + +} // namespace Platform +} // namespace XCEngine \ No newline at end of file diff --git a/engine/src/Platform/Windows/WindowsWindow.cpp b/engine/src/Platform/Windows/WindowsWindow.cpp index 83314221..7c21961c 100644 --- a/engine/src/Platform/Windows/WindowsWindow.cpp +++ b/engine/src/Platform/Windows/WindowsWindow.cpp @@ -1,4 +1,5 @@ #include "Platform/Windows/WindowsWindow.h" +#include "Input/Platform/WindowsInputModule.h" #include namespace XCEngine { @@ -80,6 +81,10 @@ void WindowsWindow::PumpEvents() { TranslateMessage(&msg); DispatchMessage(&msg); } + + if (m_inputModule) { + m_inputModule->PumpEvents(); + } } void WindowsWindow::SetTitle(const Containers::String& title) { @@ -164,6 +169,15 @@ LRESULT CALLBACK WindowsWindow::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR window->m_messageCallback(hwnd, msg, wParam, lParam); } + if (window && window->m_inputModule) { + window->m_inputModule->HandleMessage( + reinterpret_cast(hwnd), + static_cast(msg), + static_cast(wParam), + static_cast(lParam) + ); + } + switch (msg) { case WM_CLOSE: if (window) window->m_shouldClose = true; diff --git a/tests/Input/CMakeLists.txt b/tests/Input/CMakeLists.txt index d6be6e53..a90ea5fc 100644 --- a/tests/Input/CMakeLists.txt +++ b/tests/Input/CMakeLists.txt @@ -4,6 +4,7 @@ set(INPUT_TEST_SOURCES test_input_manager.cpp + test_windows_input_module.cpp ) add_executable(xcengine_input_tests ${INPUT_TEST_SOURCES}) diff --git a/tests/Input/test_windows_input_module.cpp b/tests/Input/test_windows_input_module.cpp new file mode 100644 index 00000000..243488d1 --- /dev/null +++ b/tests/Input/test_windows_input_module.cpp @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include +#include + +using namespace XCEngine::Input; +using namespace XCEngine::Math; +using namespace XCEngine::Containers; +using namespace XCEngine::Input::Platform; + +namespace { + +TEST(WindowsInputModule, Construction) { + WindowsInputModule module; +} + +TEST(WindowsInputModule, InitializeShutdown) { + WindowsInputModule module; + module.Initialize(nullptr); + module.Shutdown(); +} + +TEST(WindowsInputModule, HandleKeyDown) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + EXPECT_FALSE(InputManager::Get().IsKeyDown(KeyCode::A)); + + module.HandleMessage(0, 0x0100, 'A', 0); + + EXPECT_TRUE(InputManager::Get().IsKeyDown(KeyCode::A)); + + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, HandleKeyUp) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + module.HandleMessage(0, 0x0100, 'A', 0); + EXPECT_TRUE(InputManager::Get().IsKeyDown(KeyCode::A)); + + module.HandleMessage(0, 0x0101, 'A', 0); + EXPECT_FALSE(InputManager::Get().IsKeyDown(KeyCode::A)); + + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, HandleMouseMove) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + module.HandleMessage(0, 0x0200, 0, 0x00320078); + + Vector2 pos = InputManager::Get().GetMousePosition(); + EXPECT_EQ(pos.x, 120.0f); + EXPECT_EQ(pos.y, 50.0f); + + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, HandleLeftMouseButtonDown) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + module.HandleMessage(0, 0x0201, 0, 0x00320078); + + EXPECT_TRUE(InputManager::Get().IsMouseButtonDown(MouseButton::Left)); + + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, HandleLeftMouseButtonUp) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + module.HandleMessage(0, 0x0201, 0, 0x00320078); + EXPECT_TRUE(InputManager::Get().IsMouseButtonDown(MouseButton::Left)); + + module.HandleMessage(0, 0x0202, 0, 0x00320078); + EXPECT_FALSE(InputManager::Get().IsMouseButtonDown(MouseButton::Left)); + + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, HandleRightMouseButton) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + module.HandleMessage(0, 0x0204, 0, 0x00320078); + EXPECT_TRUE(InputManager::Get().IsMouseButtonDown(MouseButton::Right)); + + module.HandleMessage(0, 0x0205, 0, 0x00320078); + EXPECT_FALSE(InputManager::Get().IsMouseButtonDown(MouseButton::Right)); + + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, HandleMiddleMouseButton) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + module.HandleMessage(0, 0x0207, 0, 0x00320078); + EXPECT_TRUE(InputManager::Get().IsMouseButtonDown(MouseButton::Middle)); + + module.HandleMessage(0, 0x0208, 0, 0x00320078); + EXPECT_FALSE(InputManager::Get().IsMouseButtonDown(MouseButton::Middle)); + + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, HandleMouseWheel) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + module.HandleMessage(0, 0x020A, 0x00030000, 0x00780078); + + float scrollDelta = InputManager::Get().GetMouseScrollDelta(); + EXPECT_EQ(scrollDelta, 0.025f); + + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, HandleTextInput) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module; + module.Initialize(nullptr); + + bool eventFired = false; + char capturedChar = 0; + + uint64_t id = InputManager::Get().OnTextInput().Subscribe([&eventFired, &capturedChar](const TextInputEvent& e) { + eventFired = true; + capturedChar = e.character; + }); + + module.HandleMessage(0, 0x0102, 'X', 0); + + EXPECT_TRUE(eventFired); + EXPECT_EQ(capturedChar, 'X'); + + InputManager::Get().OnTextInput().Unsubscribe(id); + module.Shutdown(); + InputManager::Get().Shutdown(); +} + +TEST(WindowsInputModule, MultipleModules) { + InputManager::Get().Initialize(nullptr); + + WindowsInputModule module1; + WindowsInputModule module2; + + module1.Initialize(nullptr); + module2.Initialize(nullptr); + + module1.HandleMessage(0, 0x0100, 'A', 0); + EXPECT_TRUE(InputManager::Get().IsKeyDown(KeyCode::A)); + + module2.HandleMessage(0, 0x0100, 'B', 0); + EXPECT_TRUE(InputManager::Get().IsKeyDown(KeyCode::B)); + + module1.Shutdown(); + module2.Shutdown(); + InputManager::Get().Shutdown(); +} + +} // namespace \ No newline at end of file