From 44e726cecac291870dce50635d75d881cf61aac1 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Tue, 22 Mar 2022 19:39:08 +0200 Subject: [PATCH] Implement RawInput (WIP) --- Source/Engine/Input/Input.cpp | 17 +++ Source/Engine/Input/InputDevice.h | 1 + Source/Engine/Input/Mouse.h | 19 ++- .../Engine/Platform/Windows/WindowsInput.cpp | 117 ++++++++++++++++++ 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Input/Input.cpp b/Source/Engine/Input/Input.cpp index 0faa26f39..5c24f2c49 100644 --- a/Source/Engine/Input/Input.cpp +++ b/Source/Engine/Input/Input.cpp @@ -174,7 +174,9 @@ void InputSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* m void Mouse::OnMouseMoved(const Float2& newPosition) { _prevState.MousePosition = newPosition; + _prevState.MouseWasReset = true; _state.MousePosition = newPosition; + _state.MouseWasReset = true; } void Mouse::OnMouseDown(const Float2& position, const MouseButton button, Window* target) @@ -221,6 +223,14 @@ void Mouse::OnMouseMove(const Float2& position, Window* target) e.MouseData.Position = position; } +void Mouse::OnMouseMoveDelta(const Vector2& delta, Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::MouseMoveDelta; + e.Target = target; + e.MouseData.Position = delta; +} + void Mouse::OnMouseLeave(Window* target) { Event& e = _queue.AddOne(); @@ -245,6 +255,7 @@ void Mouse::ResetState() _state.Clear(); } +#include "Engine/Core/Log.h" bool Mouse::Update(EventQueue& queue) { // Move the current state to the previous @@ -256,6 +267,7 @@ bool Mouse::Update(EventQueue& queue) // Handle events _state.MouseWheelDelta = 0; + _state.MouseDelta = Vector2::Zero; for (int32 i = 0; i < _queue.Count(); i++) { const Event& e = _queue[i]; @@ -286,6 +298,11 @@ bool Mouse::Update(EventQueue& queue) _state.MousePosition = e.MouseData.Position; break; } + case EventType::MouseMoveDelta: + { + _state.MouseDelta += e.MouseData.Position; + break; + } case EventType::MouseLeave: { break; diff --git a/Source/Engine/Input/InputDevice.h b/Source/Engine/Input/InputDevice.h index 20c66d2ff..63bfc3273 100644 --- a/Source/Engine/Input/InputDevice.h +++ b/Source/Engine/Input/InputDevice.h @@ -25,6 +25,7 @@ public: MouseDoubleClick, MouseWheel, MouseMove, + MouseMoveDelta, MouseLeave, TouchDown, TouchMove, diff --git a/Source/Engine/Input/Mouse.h b/Source/Engine/Input/Mouse.h index cb43ed1e1..a4ad64931 100644 --- a/Source/Engine/Input/Mouse.h +++ b/Source/Engine/Input/Mouse.h @@ -24,6 +24,16 @@ public: /// Float2 MousePosition; + /// + /// The mouse position delta. + /// + Vector2 MouseDelta; + + /// + /// Set when application moved the mouse. + /// + bool MouseWasReset; + /// /// The mouse wheel delta. /// @@ -73,7 +83,7 @@ public: /// API_PROPERTY() FORCE_INLINE Float2 GetPositionDelta() const { - return _state.MousePosition - _prevState.MousePosition; + return _state.MouseDelta; } /// @@ -158,6 +168,13 @@ public: /// The target window to receive this event, otherwise input system will pick the window automatically. void OnMouseMove(const Float2& position, Window* target = nullptr); + /// + /// Called when mouse moves. + /// + /// The mouse position. + /// The target window to receive this event, otherwise input system will pick the window automatically. + void OnMouseMoveDelta(const Vector2& delta, Window* target = nullptr); + /// /// Called when mouse leaves the input source area. /// diff --git a/Source/Engine/Platform/Windows/WindowsInput.cpp b/Source/Engine/Platform/Windows/WindowsInput.cpp index 5d4b3e12f..7924d1988 100644 --- a/Source/Engine/Platform/Windows/WindowsInput.cpp +++ b/Source/Engine/Platform/Windows/WindowsInput.cpp @@ -10,6 +10,7 @@ #include "Engine/Input/Gamepad.h" #include "Engine/Engine/Engine.h" #include "Engine/Profiler/ProfilerCPU.h" +#include "Engine/Core/Math/Int2.h" #include "../Win32/IncludeWindowsHeaders.h" #define DIRECTINPUT_VERSION 0x0800 @@ -107,12 +108,36 @@ namespace WindowsInputImpl bool XInputGamepads[XUSER_MAX_COUNT] = { false }; WindowsMouse* Mouse = nullptr; WindowsKeyboard* Keyboard = nullptr; + bool RawInput = true; } +#include void WindowsInput::Init() { Input::Mouse = WindowsInputImpl::Mouse = New(); Input::Keyboard = WindowsInputImpl::Keyboard = New(); + + if (WindowsInputImpl::RawInput) + { + RAWINPUTDEVICE Rid[2]; + + // register mouse + Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; + Rid[0].dwFlags = (RIDEV_NOLEGACY*0); // adds mouse and also ignores legacy mouse messages + Rid[0].hwndTarget = 0; + + // register keyboard + Rid[1].usUsagePage = HID_USAGE_PAGE_GENERIC; + Rid[1].usUsage = HID_USAGE_GENERIC_KEYBOARD; + Rid[1].dwFlags = (RIDEV_NOLEGACY*0); // adds keyboard and also ignores legacy keyboard messages + Rid[1].hwndTarget = 0; + + if (!RegisterRawInputDevices(Rid, 2, sizeof(Rid[0]))) + { + //registration failed. Call GetLastError for the cause of the error + } + } } void WindowsInput::Update() @@ -138,6 +163,8 @@ void WindowsInput::Update() } } } + + // TODO: handle raw input device detection here } bool WindowsInput::WndProc(Window* window, Windows::UINT msg, Windows::WPARAM wParam, Windows::LPARAM lParam) @@ -149,6 +176,76 @@ bool WindowsInput::WndProc(Window* window, Windows::UINT msg, Windows::WPARAM wP return false; } +bool OnRawInput(Vector2 mousePosition, Window* window, HRAWINPUT input) +{ + uint32 dataSize; + static BYTE* dataBuffer = nullptr; + static uint32 dataBufferSize = 0; + + GetRawInputData(input, RID_INPUT, nullptr, &dataSize, sizeof(RAWINPUTHEADER)); + if (dataSize > dataBufferSize) + { + if (dataBuffer != nullptr) + delete[] dataBuffer; + dataBuffer = new BYTE[dataSize]; + dataBufferSize = dataSize; + } + + GetRawInputData(input, RID_INPUT, dataBuffer, &dataSize, sizeof(RAWINPUTHEADER)); + + if (((RAWINPUT*)dataBuffer)->header.dwType == RIM_TYPEKEYBOARD) + { + RAWKEYBOARD rawKeyboard = ((RAWINPUT*)dataBuffer)->data.keyboard; + + if ((rawKeyboard.Flags & RI_KEY_BREAK) != 0) + Input::Keyboard->OnKeyUp(static_cast(rawKeyboard.VKey), window); + else + Input::Keyboard->OnKeyDown(static_cast(rawKeyboard.VKey), window); + } + else if (((RAWINPUT*)dataBuffer)->header.dwType == RIM_TYPEMOUSE) + { + const RAWMOUSE rawMouse = ((RAWINPUT*)dataBuffer)->data.mouse; + Vector2 mousePos; + if ((rawMouse.usFlags & MOUSE_MOVE_ABSOLUTE) != 0) + { + const bool virtualDesktop = (rawMouse.usFlags & MOUSE_VIRTUAL_DESKTOP) != 0; + const int width = GetSystemMetrics(virtualDesktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); + const int height = GetSystemMetrics(virtualDesktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); + mousePos = Vector2(Int2( + static_cast((rawMouse.lLastX / 65535.0f) * width), + static_cast((rawMouse.lLastY / 65535.0f) * height))); + + Input::Mouse->OnMouseMove(mousePos, window); + } + else + { + // FIXME: This is wrong. The current mouse position does not include + // delta movement accumulated during this frame. + mousePos = mousePosition; + + const Vector2 mouseDelta(Int2(rawMouse.lLastX, rawMouse.lLastY)); + mousePos += mouseDelta; + + if (!mouseDelta.IsZero()) + { + //Input::Mouse->OnMouseMove(mousePos, window); + Input::Mouse->OnMouseMoveDelta(mouseDelta, window); + } + } + + if ((rawMouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) != 0) + Input::Mouse->OnMouseDown(mousePos, MouseButton::Left, window); + if ((rawMouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) != 0) + Input::Mouse->OnMouseUp(mousePos, MouseButton::Left, window); + if ((rawMouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) != 0) + Input::Mouse->OnMouseDown(mousePos, MouseButton::Right, window); + if ((rawMouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) != 0) + Input::Mouse->OnMouseUp(mousePos, MouseButton::Right, window); + } + + return true; +} + bool WindowsKeyboard::WndProc(Window* window, const Windows::UINT msg, Windows::WPARAM wParam, Windows::LPARAM lParam) { bool result = false; @@ -197,6 +294,21 @@ bool WindowsMouse::WndProc(Window* window, const UINT msg, WPARAM wParam, LPARAM { case WM_MOUSEMOVE: { + if (!WindowsInputImpl::RawInput) + { + static Vector2 lastPos = mousePos; + if (_state.MouseWasReset) + { + lastPos = _state.MousePosition; + _state.MouseWasReset = false; + } + + Vector2 deltaPos = mousePos - lastPos; + if (!deltaPos.IsZero()) + OnMouseMoveDelta(deltaPos, window); + lastPos = mousePos; + } + OnMouseMove(mousePos, window); result = true; break; @@ -293,6 +405,11 @@ bool WindowsMouse::WndProc(Window* window, const UINT msg, WPARAM wParam, LPARAM result = true; break; } + case WM_INPUT: + { + result = OnRawInput(_state.MousePosition, window, reinterpret_cast(lParam)); + break; + } } return result;