Raw Input and some ImGuiExtension changes

This commit is contained in:
Simon Lübeß
2022-11-26 15:24:33 +01:00
parent 8f22cbb8bc
commit d47ac23e1b
9 changed files with 408 additions and 87 deletions
@@ -1,11 +1,14 @@
#if BF_PLATFORM_WINDOWS
using System;
using GlitchyEngine.Events;
using DirectX.Windows.VirtualKeyCodes;
using DirectX.Windows;
using GlitchyEngine.Math;
using DirectX.Windows.Winuser;
using DirectX.Windows.Winuser.RawInput;
using DirectX.Windows.VirtualKeyCodes;
using System;
using System.Interop;
using GlitchyEngine.Events;
using GlitchyEngine.Math;
using static System.Windows;
namespace GlitchyEngine
@@ -13,12 +16,43 @@ namespace GlitchyEngine
/// Windows (WinApi) specific implementation of the Input-class
extension Input
{
//[CLink, CallingConvention(.Stdcall)]
//static extern int16 GetKeyState(int32 keycode);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool GetCursorPos(out Int2 p);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool SetCursorPos(c_int x, c_int y);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool ScreenToClient(HWnd hWnd, ref Int2 p);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool ClientToScreen(HWnd hWnd, ref Int2 p);
[Import("user32.lib"), CLink]
public static extern IntBool RegisterRawInputDevices(RAWINPUTDEVICE* pRawInputDevices, uint32 uiNumDevices, uint32 cbSize);
public static void RegisterRIDs()
{
RAWINPUTDEVICE rid;
rid.UsagePage = 0x01;
rid.Usage = 0x02;
rid.Flags = 0;
rid.Target = 0;
if(RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == 0)
{
Log.EngineLogger.Error("Failed to register raw input devices: {0}", GetLastError());
Log.EngineLogger.AssertDebug(false, "Failed to register raw input device.");
}
}
/// Represents the state of the input devices on the windows platform (WinApi that is).
struct WindowsInputState
{
public int8[256] KeyStates;
public Int2 CursorPosition;
public Int2 CursorPositionDifference;
public Int2 RawCursorMovement;
}
static WindowsInputState[2] IputStates;
@@ -119,8 +153,16 @@ namespace GlitchyEngine
return state >= 0;
}
public override static bool IsMouseButtonPressing(MouseButton button) => IsMouseButtonPressed(button) && WasMouseButtonReleased(button);
public override static bool IsMouseButtonReleasing(MouseButton button) => IsMouseButtonReleased(button) && WasMouseButtonPressed(button);
public override static Int2 GetMousePosition() => CurrentState.CursorPosition;
public override static Int2 GetMouseMovement() => CurrentState.CursorPositionDifference;
public override static Int2 GetRawMouseMovement() => CurrentState.RawCursorMovement;
public override static int32 GetMouseX() => CurrentState.CursorPosition.X;
public override static int32 GetMouseY() => CurrentState.CursorPosition.Y;
@@ -141,33 +183,38 @@ namespace GlitchyEngine
}
public override static Int2 GetLastMousePosition() => LastState.CursorPosition;
public override static Int2 GetLastMouseMovement() => LastState.CursorPositionDifference;
public override static Int2 GetLastRawMouseMovement() => LastState.RawCursorMovement;
public override static int32 GetLastMouseX() => LastState.CursorPosition.X;
public override static int32 GetLastMouseY() => LastState.CursorPosition.Y;
//
// Mouse state transition
//
public override static bool IsMouseButtonPressing(MouseButton button) => IsMouseButtonPressed(button) && WasMouseButtonReleased(button);
public override static bool IsMouseButtonReleasing(MouseButton button) => IsMouseButtonReleased(button) && WasMouseButtonPressed(button);
public override static Int2 GetMouseMovement() => CurrentState.CursorPositionDifference;
public override static void SetMousePosition(Int2 pos) => SetCursorPos(pos.X, pos.Y);
//[CLink, CallingConvention(.Stdcall)]
//static extern int16 GetKeyState(int32 keycode);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool GetCursorPos(out Int2 p);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool SetCursorPos(c_int x, c_int y);
[CLink, CallingConvention(.Stdcall)]
static extern IntBool ScreenToClient(HWnd hWnd, ref Int2 p);
public override static void NewFrame()
public override static void SetMousePosition(Int2 pos)
{
HWnd windowHandle = (HWnd)(int)Application.Get().Window.NativeWindow;
var pos;
// TODO: can fail
ClientToScreen(windowHandle, ref pos);
SetCursorPos(pos.X, pos.Y);
}
public override static void Init()
{
RegisterRIDs();
}
//public override
public override static void Impl_NewFrame()
{
Window window = Application.Get().Window;
Debug.Profiler.ProfileFunction!();
Swap!(CurrentState, LastState);
@@ -182,7 +229,7 @@ namespace GlitchyEngine
// Get the current mouse position
if (GetCursorPos(out CurrentState.CursorPosition) != 0)
{
HWnd windowHandle = (HWnd)(int)Application.Get().Window.NativeWindow;
HWnd windowHandle = (HWnd)(int)window.NativeWindow;
if (ScreenToClient(windowHandle, ref CurrentState.CursorPosition) == 0)
{
DirectX.Common.HResult errorCode = (.)GetLastError();
@@ -195,8 +242,25 @@ namespace GlitchyEngine
Log.EngineLogger.Error($"Failed to get mouse position. Message({(int32)errorCode}){errorCode}:");
}
// Calculate cursor movement
CurrentState.CursorPositionDifference = CurrentState.CursorPosition - LastState.CursorPosition;
CurrentState.RawCursorMovement = window.[Friend]_rawMouseMovementAccumulator;
if (Mouse.LockedPosition == null)
{
// Calculate cursor movement
CurrentState.CursorPositionDifference = CurrentState.CursorPosition - LastState.CursorPosition;
}
else
{
// Calculate cursor movement
CurrentState.CursorPositionDifference = CurrentState.CursorPosition - Mouse.LockedPosition.Value;
CurrentState.CursorPosition = Mouse.LockedPosition.Value;
}
}
public override static void Impl_EndFrame()
{
Application.Get().Window.[Friend]_rawMouseMovementAccumulator = .Zero;
}
}
}
@@ -10,6 +10,7 @@ using GlitchyEngine.Events;
using System.Diagnostics;
using GlitchyEngine.Math;
using GlitchyEngine.Renderer;
using DirectX.Windows.Winuser.RawInput;
using static System.Windows;
using internal GlitchyEngine;
@@ -262,6 +263,8 @@ namespace GlitchyEngine
return .Ok;
}
internal Int2 _rawMouseMovementAccumulator;
private static LRESULT MessageHandler(HWND hwnd, uint32 uMsg, WPARAM wParam, LPARAM lParam)
{
void* windowPtr = (void*)GetWindowLongPtrW(hwnd, GWL_USERDATA);
@@ -458,6 +461,28 @@ namespace GlitchyEngine
var event = scope MouseMovedEvent(x, y);
window._eventCallback(event);
}
case WM_INPUT:
{
uint32 dataSize = ?;
GetRawInputData((.)lParam, RID_INPUT, null, &dataSize, sizeof(RAWINPUTHEADER));
if (dataSize > 0)
{
uint8[] rawData = scope .[dataSize];
if (GetRawInputData((.)lParam, RID_INPUT, rawData.CArray(), &dataSize, sizeof(RAWINPUTHEADER)) == dataSize)
{
RAWINPUT* raw = (.)rawData.CArray();
if (raw.Header.Type == RIM_TYPEMOUSE)
{
var event = scope MouseMovedEvent(raw.Data.Mouse.lLastX, raw.Data.Mouse.lLastY);
window._eventCallback(event);
// We accumulate the raw movements an collect them once each frame in WindowsInput.Impl_NewFrame()
window._rawMouseMovementAccumulator += Int2(raw.Data.Mouse.lLastX, raw.Data.Mouse.lLastY);
}
}
}
}
// Todo: DirectInput