Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 2 additions & 75 deletions Assets/Scenes/SampleScene.unity
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &394699778
MonoBehaviour:
Expand All @@ -165,78 +165,5 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
WorkInBackground: 1
Async: 0
InterceptMessages: 0
--- !u!1 &1620130889
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1620130893}
- component: {fileID: 1620130892}
m_Layer: 0
m_Name: MainCamera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!20 &1620130892
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1620130889}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &1620130893
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1620130889}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
11 changes: 10 additions & 1 deletion Assets/Scripts/LogRawKeyInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,27 @@ public class LogRawKeyInput : MonoBehaviour
{
public bool WorkInBackground;
public bool InterceptMessages;
public RawKey DisableInterceptKey = RawKey.Escape;

private void OnEnable ()
{
RawKeyInput.Start(WorkInBackground);
RawKeyInput.OnKeyUp += LogKeyUp;
RawKeyInput.OnKeyDown += LogKeyDown;
RawKeyInput.OnKeyDown += DisableIntercept;
}

private void OnDisable ()
{
RawKeyInput.Stop();
RawKeyInput.OnKeyUp -= LogKeyUp;
RawKeyInput.OnKeyDown -= LogKeyDown;
RawKeyInput.OnKeyDown -= DisableIntercept;
}

private void OnValidate ()
{
// Used for testing purposes, won't work in builds.
// Used for testing purposes, won't work in build.
// OnValidate is invoked only in the editor.
RawKeyInput.InterceptMessages = InterceptMessages;
}
Expand All @@ -36,4 +39,10 @@ private void LogKeyDown (RawKey key)
{
Debug.Log("Key Down: " + key);
}

private void DisableIntercept (RawKey key)
{
if (RawKeyInput.InterceptMessages && key == DisableInterceptKey)
RawKeyInput.InterceptMessages = InterceptMessages = false;
}
}
29 changes: 29 additions & 0 deletions Assets/UnityRawInput/Runtime/HookArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Runtime.InteropServices;

namespace UnityRawInput
{
[StructLayout(LayoutKind.Sequential)]
public struct KeyboardArgs
{
public uint Code;
public uint ScanCode;
public KeyboardFlags Flags;
public uint Time;
public UIntPtr ExtraInfo;

public static KeyboardArgs FromPtr (IntPtr ptr)
{
return (KeyboardArgs)Marshal.PtrToStructure(ptr, typeof(KeyboardArgs));
}
}

[Flags]
public enum KeyboardFlags : uint
{
Extended = 0x01,
Injected = 0x10,
AltDown = 0x20,
Up = 0x80,
}
}
29 changes: 0 additions & 29 deletions Assets/UnityRawInput/Runtime/KbDllHookStruct.cs

This file was deleted.

85 changes: 53 additions & 32 deletions Assets/UnityRawInput/Runtime/RawKeyInput.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using AOT;

namespace UnityRawInput
{
Expand All @@ -17,7 +18,7 @@ public static class RawKeyInput
/// <summary>
/// Whether the service is running and input messages are being processed.
/// </summary>
public static bool IsRunning => hookPtr != IntPtr.Zero;
public static bool IsRunning => hooks.Count > 0;
/// <summary>
/// Whether any key is currently pressed.
/// </summary>
Expand All @@ -32,7 +33,7 @@ public static class RawKeyInput
public static bool InterceptMessages { get; set; }

private static readonly HashSet<RawKey> pressedKeys = new HashSet<RawKey>();
private static IntPtr hookPtr = IntPtr.Zero;
private static readonly List<IntPtr> hooks = new List<IntPtr>();

/// <summary>
/// Initializes the service and starts processing input messages.
Expand All @@ -43,15 +44,16 @@ public static bool Start (bool workInBackground)
{
if (IsRunning) return false;
WorkInBackground = workInBackground;
return SetHook();
SetHooks();
return hooks.TrueForAll(h => h != IntPtr.Zero);
}

/// <summary>
/// Terminates the service and stops processing input messages.
/// </summary>
public static void Stop ()
{
RemoveHook();
RemoveHooks();
pressedKeys.Clear();
}

Expand All @@ -63,67 +65,86 @@ public static bool IsKeyDown (RawKey key)
return pressedKeys.Contains(key);
}

private static bool SetHook ()
private static void SetHooks ()
{
if (hookPtr == IntPtr.Zero)
{
if (WorkInBackground) hookPtr = Win32API.SetWindowsHookEx(HookType.WH_KEYBOARD_LL, HandleLowLevelHookProc, IntPtr.Zero, 0);
else hookPtr = Win32API.SetWindowsHookEx(HookType.WH_KEYBOARD, HandleHookProc, IntPtr.Zero, (int)Win32API.GetCurrentThreadId());
}
hooks.Add(SetKeyboardHook());
hooks.Add(SetMouseHook());
}

if (hookPtr == IntPtr.Zero) return false;
private static void RemoveHooks ()
{
foreach (var pointer in hooks)
if (pointer != IntPtr.Zero)
Win32API.UnhookWindowsHookEx(pointer);
hooks.Clear();
}

return true;
private static IntPtr SetKeyboardHook ()
{
if (WorkInBackground) return Win32API.SetWindowsHookEx(HookType.WH_KEYBOARD_LL, HandleLowLevelKeyboardProc, IntPtr.Zero, 0);
return Win32API.SetWindowsHookEx(HookType.WH_KEYBOARD, HandleKeyboardProc, IntPtr.Zero, (int)Win32API.GetCurrentThreadId());
}

private static void RemoveHook ()
private static IntPtr SetMouseHook ()
{
if (hookPtr != IntPtr.Zero)
{
Win32API.UnhookWindowsHookEx(hookPtr);
hookPtr = IntPtr.Zero;
}
if (WorkInBackground) return Win32API.SetWindowsHookEx(HookType.WH_MOUSE_LL, HandleMouseProc, IntPtr.Zero, 0);
return Win32API.SetWindowsHookEx(HookType.WH_MOUSE, HandleMouseProc, IntPtr.Zero, (int)Win32API.GetCurrentThreadId());
}

[AOT.MonoPInvokeCallback(typeof(Win32API.HookProc))]
private static int HandleHookProc (int code, IntPtr wParam, IntPtr lParam)
[MonoPInvokeCallback(typeof(Win32API.HookProc))]
private static int HandleKeyboardProc (int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0) return Win32API.CallNextHookEx(hookPtr, code, wParam, lParam);
if (code < 0) return Win32API.CallNextHookEx(IntPtr.Zero, code, wParam, lParam);

var isKeyDown = ((int)lParam & (1 << 31)) == 0;
var key = (RawKey)wParam;

if (isKeyDown) HandleKeyDown(key);
else HandleKeyUp(key);

return InterceptMessages ? 1 : Win32API.CallNextHookEx(hookPtr, 0, wParam, lParam);
return InterceptMessages ? 1 : Win32API.CallNextHookEx(IntPtr.Zero, 0, wParam, lParam);
}

[AOT.MonoPInvokeCallback(typeof(Win32API.HookProc))]
private static int HandleLowLevelHookProc (int code, IntPtr wParam, IntPtr lParam)
[MonoPInvokeCallback(typeof(Win32API.HookProc))]
private static int HandleLowLevelKeyboardProc (int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0) return Win32API.CallNextHookEx(hookPtr, code, wParam, lParam);
if (code < 0) return Win32API.CallNextHookEx(IntPtr.Zero, code, wParam, lParam);

var kbd = KBDLLHOOKSTRUCT.CreateFromPtr(lParam);
var keyState = (RawKeyState)wParam;
var key = (RawKey)kbd.vkCode;
var args = KeyboardArgs.FromPtr(lParam);
var state = (RawKeyState)wParam;
var key = (RawKey)args.Code;

if (keyState == RawKeyState.KeyDown || keyState == RawKeyState.SysKeyDown) HandleKeyDown(key);
if (state == RawKeyState.KeyDown || state == RawKeyState.SysKeyDown) HandleKeyDown(key);
else HandleKeyUp(key);

return InterceptMessages ? 1 : Win32API.CallNextHookEx(hookPtr, 0, wParam, lParam);
return InterceptMessages ? 1 : Win32API.CallNextHookEx(IntPtr.Zero, 0, wParam, lParam);
}

[MonoPInvokeCallback(typeof(Win32API.HookProc))]
private static int HandleMouseProc (int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0) return Win32API.CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
var state = (RawMouseState)wParam;
if (state == RawMouseState.LeftButtonDown) HandleKeyDown(RawKey.LeftButton);
else if (state == RawMouseState.MiddleButtonDown) HandleKeyDown(RawKey.MiddleButton);
else if (state == RawMouseState.RightButtonDown) HandleKeyDown(RawKey.RightButton);
else if (state == RawMouseState.LeftButtonUp) HandleKeyUp(RawKey.LeftButton);
else if (state == RawMouseState.MiddleButtonUp) HandleKeyUp(RawKey.MiddleButton);
else if (state == RawMouseState.RightButtonUp) HandleKeyUp(RawKey.RightButton);
else return Win32API.CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
return InterceptMessages ? 1 : Win32API.CallNextHookEx(IntPtr.Zero, 0, wParam, lParam);
}

private static void HandleKeyDown (RawKey key)
{
var added = pressedKeys.Add(key);
if (added && OnKeyDown != null) OnKeyDown.Invoke(key);
if (added) OnKeyDown?.Invoke(key);
}

private static void HandleKeyUp (RawKey key)
{
pressedKeys.Remove(key);
if (OnKeyUp != null) OnKeyUp.Invoke(key);
OnKeyUp?.Invoke(key);
}
}
}
14 changes: 14 additions & 0 deletions Assets/UnityRawInput/Runtime/RawMouseState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace UnityRawInput
{
public enum RawMouseState
{
MouseMove = 0x0200,
LeftButtonDown = 0x0201,
LeftButtonUp = 0x0202,
MouseWheel = 0x020A,
MiddleButtonDown = 0x0207,
MiddleButtonUp = 0x0208,
RightButtonDown = 0x0204,
RightButtonUp = 0x0205
}
}
3 changes: 3 additions & 0 deletions Assets/UnityRawInput/Runtime/RawMouseState.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ProjectSettings/ProjectSettings.asset
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ PlayerSettings:
androidBlitType: 0
defaultIsNativeResolution: 1
macRetinaSupport: 1
runInBackground: 0
runInBackground: 1
captureSingleScreen: 0
muteOtherAudioSources: 0
Prepare IOS For Recording: 0
Expand Down
Loading