diff --git a/Code/DanBias.sln b/Code/DanBias.sln
index 033e050e..6835e750 100644
--- a/Code/DanBias.sln
+++ b/Code/DanBias.sln
@@ -49,6 +49,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LevelLoader", "Game\LevelLo
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameServerDebugEnvironment", "Game\LanServer\GameServerDebugEnvironment\GameServerDebugEnvironment.vcxproj", "{67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lab", "Lab", "{46A660B9-6BE9-411C-B366-235FD8F8A9BD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RawDeviceLab", "LabProjects\RawDeviceLab\RawDeviceLab.vcxproj", "{32DD438B-8C9C-49EF-9EA5-EB48951D869A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -751,6 +755,38 @@ Global
{67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|x64.ActiveCfg = Release|Win32
{67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{67D0FB00-FF1F-4DE4-84BD-664AE93D25EE}.RelWithDebInfo|x86.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Debug|Win32.Build.0 = Debug|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Debug|x64.ActiveCfg = Debug|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Debug|x86.ActiveCfg = Debug|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Debug|x86.Build.0 = Debug|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.MinSizeRel|Any CPU.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.MinSizeRel|x64.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.MinSizeRel|x86.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.MinSizeRel|x86.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Release|Any CPU.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Release|Win32.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Release|Win32.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Release|x64.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Release|x86.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.Release|x86.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.RelWithDebInfo|x64.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}.RelWithDebInfo|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -774,5 +810,6 @@ Global
{604A12A7-07BF-4482-BDF3-7101C811F121} = {C83A6FAD-E71F-4B1E-9D63-E93E61DDC012}
{C8CBA520-5D7D-4D61-A8DA-6E05FD132BCB} = {C83A6FAD-E71F-4B1E-9D63-E93E61DDC012}
{67D0FB00-FF1F-4DE4-84BD-664AE93D25EE} = {C83A6FAD-E71F-4B1E-9D63-E93E61DDC012}
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A} = {46A660B9-6BE9-411C-B366-235FD8F8A9BD}
EndGlobalSection
EndGlobal
diff --git a/Code/LabProjects/RawDeviceLab/RawDeviceLab.vcxproj b/Code/LabProjects/RawDeviceLab/RawDeviceLab.vcxproj
new file mode 100644
index 00000000..27eb0513
--- /dev/null
+++ b/Code/LabProjects/RawDeviceLab/RawDeviceLab.vcxproj
@@ -0,0 +1,72 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {32DD438B-8C9C-49EF-9EA5-EB48951D869A}
+ Test
+
+
+
+ Application
+ true
+ v110
+ MultiByte
+
+
+ Application
+ false
+ v110
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ Disabled
+ true
+
+
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Code/LabProjects/RawDeviceLab/main.cpp b/Code/LabProjects/RawDeviceLab/main.cpp
new file mode 100644
index 00000000..b636fbe7
--- /dev/null
+++ b/Code/LabProjects/RawDeviceLab/main.cpp
@@ -0,0 +1,243 @@
+#include
+
+const unsigned short raw_input_usage_keyboard = 6;
+const unsigned short raw_input_usage_mouse = 2;
+HWND winHandle;
+bool isPointAndClickMode;
+float normalizedMousePosX, normalizedMousePosY;
+
+LRESULT CALLBACK RawWindowCallback(HWND h, UINT m, WPARAM w, LPARAM l);
+LRESULT RawInputParser(HWND h, LPARAM l);
+void Update( );
+
+//int main()
+int WINAPI WinMain( HINSTANCE hinst, HINSTANCE prevInst, PSTR cmdLine, int cmdShow)
+{
+ WNDCLASSEXW wc;
+ wc.cbSize = sizeof(WNDCLASSEXW);
+ wc.hIconSm = NULL;
+ wc.style = NULL;
+ wc.lpfnWndProc = RawWindowCallback;
+ wc.cbClsExtra = NULL;
+ wc.cbWndExtra = NULL;
+ wc.hInstance = hinst;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = L"RawInputTest";
+
+ if( !RegisterClassExW(&wc) )
+ {
+ const char *breakpoint = "";
+ }
+
+ winHandle = CreateWindowExW( 0, L"RawInputTest", L"RawInputTest", WS_OVERLAPPEDWINDOW | WS_CAPTION, 0, 0, 600, 400, NULL, NULL, hinst, NULL );
+ ShowWindow( winHandle, cmdShow );
+
+ if( !winHandle )
+ {
+ const char *breakpoint = "";
+ }
+
+ isPointAndClickMode = true;
+ normalizedMousePosX =
+ normalizedMousePosY = 0.5f;
+
+ MSG msg = {0};
+ while( true )
+ {
+ if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
+ {
+ if (msg.message == WM_QUIT) break;
+ DispatchMessage(&msg);
+ }
+ else
+ {
+ Update();
+ }
+ }
+ return 0;
+}
+
+LRESULT CALLBACK RawWindowCallback(HWND h, UINT m, WPARAM w, LPARAM l)
+{
+ LRESULT val = 0;
+ switch (m)
+ {
+ case WM_INPUT:
+ {
+ RawInputParser( h, l );
+ }
+ break;
+ case WM_KEYUP:
+ {
+ if( w == 16 )
+ {
+ const char *breakpoint = "";
+
+ RAWINPUTDEVICE rid;
+ rid.usUsagePage = 0x01;
+ rid.hwndTarget = winHandle;
+ rid.usUsage = raw_input_usage_keyboard;
+ rid.dwFlags = RIDEV_NOLEGACY;
+ if( RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == FALSE )
+ {
+ const char *breakpoint = "";
+ }
+ }
+ }
+ break;
+ case WM_RBUTTONUP:
+ {
+ const char *breakpoint = "";
+
+ RAWINPUTDEVICE rid;
+ rid.usUsagePage = 0x01;
+ rid.hwndTarget = winHandle;
+ rid.usUsage = raw_input_usage_mouse;
+ rid.dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE;
+ if( RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == TRUE )
+ {
+ ShowCursor( false );
+ isPointAndClickMode = false;
+ }
+ else
+ {
+ const char *breakpoint = "";
+ }
+ }
+ break;
+ case WM_ACTIVATE:
+ {
+ const char *breakpoint = "";
+ }
+ break;
+ break;
+ case WM_CREATE:
+ {
+ const char *breakpoint = "";
+ }
+ break;
+ case WM_DESTROY:
+ PostQuitMessage( 0 );
+ break;
+ default: break;
+ }
+
+ return DefWindowProc(h, m, w, l);
+}
+
+LRESULT RawInputParser(HWND h, LPARAM l)
+{
+ //Get The size of the raw data buffer
+ UINT bufferSize;
+ GetRawInputData((HRAWINPUT)l, RID_INPUT, NULL, &bufferSize, sizeof(RAWINPUTHEADER));
+ if (bufferSize < 1)
+ { return 0; }
+
+ //Create and read the raw input data
+ LPBYTE rawBuffer = new BYTE[bufferSize];
+ UINT readBytes = GetRawInputData((HRAWINPUT)l, RID_INPUT, rawBuffer, &bufferSize, sizeof(RAWINPUTHEADER));
+ if ( readBytes != bufferSize )
+ {
+ delete [] rawBuffer;
+ return 0;
+ }
+
+ HRESULT result = 0;
+ RAWINPUT* raw = (RAWINPUT*)rawBuffer;
+
+ if( raw->header.dwType == RIM_TYPEKEYBOARD )
+ {
+ if( (raw->data.keyboard.Flags & RI_KEY_BREAK) && raw->data.keyboard.VKey == 16 )
+ {
+ const char *breakpoint = "";
+
+ RAWINPUTDEVICE rid;
+ rid.usUsagePage = 0x01;
+ rid.hwndTarget = NULL;
+ rid.usUsage = raw_input_usage_keyboard;
+ rid.dwFlags = RIDEV_REMOVE;
+ if( RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == FALSE )
+ {
+ const char *breakpoint = "";
+ }
+ }
+ }
+ else if( raw->header.dwType == RIM_TYPEMOUSE )
+ {
+ if( raw->data.mouse.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP )
+ {
+ const char *breakpoint = "";
+
+ RAWINPUTDEVICE rid;
+ rid.usUsagePage = 0x01;
+ rid.hwndTarget = NULL;
+ rid.usUsage = raw_input_usage_mouse;
+ rid.dwFlags = RIDEV_REMOVE;
+ if( RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == TRUE )
+ {
+ RECT winRect;
+ GetWindowRect( winHandle, &winRect );
+ SetCursorPos( (winRect.left + winRect.right) >> 1, (winRect.top + winRect.bottom) >> 1 );
+ isPointAndClickMode = true;
+ }
+ else
+ {
+ const char *breakpoint = "";
+ }
+ }
+ }
+ else result = DefRawInputProc(&raw, 1, sizeof(RAWINPUTHEADER));
+
+ delete [] rawBuffer;
+ return result;
+}
+
+void Update( )
+{
+ if( isPointAndClickMode )
+ {
+ { // Calculating and storing the normalizedMousePos values
+ POINT clientReach, clientCenter, mousePos;
+
+ RECT winRect, clientRect;
+ GetClientRect( winHandle, &clientRect );
+ GetWindowRect( winHandle, &winRect );
+
+ LONG borderThickness = (winRect.right - winRect.left - clientRect.right) >> 1;
+
+ clientReach.x = clientRect.right >> 1;
+ clientReach.y = clientRect.bottom >> 1;
+
+ clientCenter.x = (winRect.left + winRect.right) >> 1;
+ clientCenter.y = winRect.bottom - clientReach.y - borderThickness;
+
+ GetCursorPos( &mousePos );
+
+ normalizedMousePosX = ((float)(mousePos.x - clientCenter.x + clientReach.x)) / (float)clientRect.right;
+ normalizedMousePosY = ((float)(mousePos.y - clientCenter.y + clientReach.y)) / (float)clientRect.bottom;
+ }
+
+ // Check if normalizedMousePos intersects client surface [(0,0), (1,1)]
+ bool mouseIsNowWithinBounds = true;
+ if ( normalizedMousePosX < 0.0f ) mouseIsNowWithinBounds = false;
+ else if( normalizedMousePosX > 1.0f ) mouseIsNowWithinBounds = false;
+ else if( normalizedMousePosY < 0.0f ) mouseIsNowWithinBounds = false;
+ else if( normalizedMousePosY > 1.0f ) mouseIsNowWithinBounds = false;
+
+ // Detect onEnter or onExit case
+ static bool mouseWereWithinBounds = false;
+ if( mouseIsNowWithinBounds & !mouseWereWithinBounds )
+ { // onEnter
+ ShowCursor( false );
+ mouseWereWithinBounds = mouseIsNowWithinBounds;
+ }
+ else if( !mouseIsNowWithinBounds & mouseWereWithinBounds )
+ { // onExit
+ ShowCursor( true );
+ mouseWereWithinBounds = mouseIsNowWithinBounds;
+ }
+ }
+}
\ No newline at end of file