From 726d72c103f13be6d24ab72c7ba0d39b77f307f3 Mon Sep 17 00:00:00 2001 From: Souryo Date: Sat, 16 Jul 2016 16:25:57 -0400 Subject: [PATCH] Input: DirectInput support - most controllers/gamepads should now work. XInput is still prioritized when available. --- Core/ControlManager.cpp | 3 + Core/IKeyManager.h | 1 + GUI.NET/Config/InputInfo.cs | 29 ++ .../Config/ctrlStandardController.Designer.cs | 188 +++++------ .../Forms/Config/ctrlStandardController.resx | 2 +- GUI.NET/Forms/Config/frmGetKey.cs | 1 + .../Forms/Config/frmInputConfig.Designer.cs | 4 +- GUI.NET/Forms/Config/frmInputConfig.cs | 2 + GUI.NET/InteropEmu.cs | 1 + InteropDLL/ConsoleWrapper.cpp | 5 +- InteropDLL/InteropDLL.vcxproj | 16 +- Windows/DirectInputManager.cpp | 235 ++++++++++++++ Windows/DirectInputManager.h | 33 ++ Windows/Windows.vcxproj | 6 +- Windows/Windows.vcxproj.filters | 18 +- Windows/WindowsKeyManager.cpp | 248 ++++++++++++++- Windows/WindowsKeyManager.h | 292 +----------------- Windows/{GamePad.cpp => XInputManager.cpp} | 19 +- Windows/{GamePad.h => XInputManager.h} | 5 +- 19 files changed, 697 insertions(+), 411 deletions(-) create mode 100644 Windows/DirectInputManager.cpp create mode 100644 Windows/DirectInputManager.h rename Windows/{GamePad.cpp => XInputManager.cpp} (79%) rename Windows/{GamePad.h => XInputManager.h} (76%) diff --git a/Core/ControlManager.cpp b/Core/ControlManager.cpp index 1b4edeca..2465852d 100644 --- a/Core/ControlManager.cpp +++ b/Core/ControlManager.cpp @@ -213,6 +213,9 @@ void ControlManager::WriteRAM(uint16_t addr, uint8_t value) void ControlManager::Reset(bool softReset) { + if(_keyManager != nullptr) { + _keyManager->UpdateDevices(); + } } void ControlManager::StreamState(bool saving) diff --git a/Core/IKeyManager.h b/Core/IKeyManager.h index 3eb8a017..aea7a3c5 100644 --- a/Core/IKeyManager.h +++ b/Core/IKeyManager.h @@ -13,6 +13,7 @@ class IKeyManager { public: virtual void RefreshState() = 0; + virtual void UpdateDevices() = 0; virtual bool IsMouseButtonPressed(MouseButton button) = 0; virtual bool IsKeyPressed(uint32_t keyCode) = 0; virtual uint32_t GetPressedKey() = 0; diff --git a/GUI.NET/Config/InputInfo.cs b/GUI.NET/Config/InputInfo.cs index 62a5a592..45501e98 100644 --- a/GUI.NET/Config/InputInfo.cs +++ b/GUI.NET/Config/InputInfo.cs @@ -42,6 +42,7 @@ namespace Mesen.GUI.Config TurboA = "Z"; TurboB = "X"; } else if(keySetIndex == 1) { + //XInput Default (Xbox controllers) A = "Pad1 A"; B = "Pad1 X"; Select = "Pad1 Back"; @@ -53,6 +54,19 @@ namespace Mesen.GUI.Config TurboA = "Pad1 B"; TurboB = "Pad1 Y"; + } else if(keySetIndex == 2) { + //DirectInput Default (Used PS4 controller as a default) + A = "Joy1 But2"; + B = "Joy1 But1"; + Select = "Joy1 But9"; + Start = "Joy1 But10"; + Up = "Joy1 DPad Up"; + Down = "Joy1 DPad Down"; + Left = "Joy1 DPad Left"; + Right = "Joy1 DPad Right"; + + TurboA = "Joy1 But3"; + TurboB = "Joy1 But4"; } } else if(controllerIndex == 1) { if(keySetIndex == 0) { @@ -68,6 +82,7 @@ namespace Mesen.GUI.Config TurboA = "B"; TurboB = "N"; } else if(keySetIndex == 1) { + //XInput Default (Xbox controllers) A = "Pad2 A"; B = "Pad2 X"; Select = "Pad2 Back"; @@ -79,6 +94,19 @@ namespace Mesen.GUI.Config TurboA = "Pad2 B"; TurboB = "Pad2 Y"; + } else if(keySetIndex == 2) { + //DirectInput Default (Used PS4 controller as a default) + A = "Joy2 But2"; + B = "Joy2 But1"; + Select = "Joy2 But9"; + Start = "Joy2 But10"; + Up = "Joy2 DPad Up"; + Down = "Joy2 DPad Down"; + Left = "Joy2 DPad Left"; + Right = "Joy2 DPad Right"; + + TurboA = "Joy2 But3"; + TurboB = "Joy2 But4"; } } } @@ -144,6 +172,7 @@ namespace Mesen.GUI.Config if(Controllers.Count <= 1) { controllerInfo.Keys.Add(new KeyMappings(Controllers.Count, 0)); controllerInfo.Keys.Add(new KeyMappings(Controllers.Count, 1)); + controllerInfo.Keys.Add(new KeyMappings(Controllers.Count, 2)); } Controllers.Add(controllerInfo); } diff --git a/GUI.NET/Forms/Config/ctrlStandardController.Designer.cs b/GUI.NET/Forms/Config/ctrlStandardController.Designer.cs index 38ab6c58..bba9d526 100644 --- a/GUI.NET/Forms/Config/ctrlStandardController.Designer.cs +++ b/GUI.NET/Forms/Config/ctrlStandardController.Designer.cs @@ -29,17 +29,17 @@ { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ctrlStandardController)); this.panel2 = new System.Windows.Forms.Panel(); - this.picControllerLayout = new System.Windows.Forms.PictureBox(); - this.btnA = new System.Windows.Forms.Button(); - this.btnDown = new System.Windows.Forms.Button(); - this.btnUp = new System.Windows.Forms.Button(); - this.btnStart = new System.Windows.Forms.Button(); - this.btnB = new System.Windows.Forms.Button(); - this.btnTurboA = new System.Windows.Forms.Button(); - this.btnLeft = new System.Windows.Forms.Button(); - this.btnSelect = new System.Windows.Forms.Button(); - this.btnRight = new System.Windows.Forms.Button(); this.btnTurboB = new System.Windows.Forms.Button(); + this.btnRight = new System.Windows.Forms.Button(); + this.btnSelect = new System.Windows.Forms.Button(); + this.btnLeft = new System.Windows.Forms.Button(); + this.btnTurboA = new System.Windows.Forms.Button(); + this.btnB = new System.Windows.Forms.Button(); + this.btnStart = new System.Windows.Forms.Button(); + this.btnUp = new System.Windows.Forms.Button(); + this.btnDown = new System.Windows.Forms.Button(); + this.btnA = new System.Windows.Forms.Button(); + this.picControllerLayout = new System.Windows.Forms.PictureBox(); this.panel2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.picControllerLayout)).BeginInit(); this.SuspendLayout(); @@ -64,64 +64,45 @@ this.panel2.Size = new System.Drawing.Size(585, 210); this.panel2.TabIndex = 3; // - // picControllerLayout + // btnTurboB // - this.picControllerLayout.Image = ((System.Drawing.Image)(resources.GetObject("picControllerLayout.Image"))); - this.picControllerLayout.Location = new System.Drawing.Point(0, 0); - this.picControllerLayout.Name = "picControllerLayout"; - this.picControllerLayout.Size = new System.Drawing.Size(615, 211); - this.picControllerLayout.TabIndex = 11; - this.picControllerLayout.TabStop = false; + this.btnTurboB.Location = new System.Drawing.Point(417, 17); + this.btnTurboB.Name = "btnTurboB"; + this.btnTurboB.Size = new System.Drawing.Size(61, 59); + this.btnTurboB.TabIndex = 21; + this.btnTurboB.Text = "B"; + this.btnTurboB.UseVisualStyleBackColor = true; + this.btnTurboB.Click += new System.EventHandler(this.btnMapping_Click); // - // btnA + // btnRight // - this.btnA.Location = new System.Drawing.Point(499, 105); - this.btnA.Name = "btnA"; - this.btnA.Size = new System.Drawing.Size(61, 59); - this.btnA.TabIndex = 14; - this.btnA.Text = "A"; - this.btnA.UseVisualStyleBackColor = true; - this.btnA.Click += new System.EventHandler(this.btnMapping_Click); + this.btnRight.Location = new System.Drawing.Point(105, 90); + this.btnRight.Name = "btnRight"; + this.btnRight.Size = new System.Drawing.Size(69, 35); + this.btnRight.TabIndex = 16; + this.btnRight.Text = "Right"; + this.btnRight.UseVisualStyleBackColor = true; + this.btnRight.Click += new System.EventHandler(this.btnMapping_Click); // - // btnDown + // btnSelect // - this.btnDown.Location = new System.Drawing.Point(68, 141); - this.btnDown.Name = "btnDown"; - this.btnDown.Size = new System.Drawing.Size(64, 35); - this.btnDown.TabIndex = 19; - this.btnDown.Text = "Down"; - this.btnDown.UseVisualStyleBackColor = true; - this.btnDown.Click += new System.EventHandler(this.btnMapping_Click); + this.btnSelect.Location = new System.Drawing.Point(228, 131); + this.btnSelect.Name = "btnSelect"; + this.btnSelect.Size = new System.Drawing.Size(73, 37); + this.btnSelect.TabIndex = 12; + this.btnSelect.Text = "Q"; + this.btnSelect.UseVisualStyleBackColor = true; + this.btnSelect.Click += new System.EventHandler(this.btnMapping_Click); // - // btnUp + // btnLeft // - this.btnUp.Location = new System.Drawing.Point(68, 34); - this.btnUp.Name = "btnUp"; - this.btnUp.Size = new System.Drawing.Size(64, 35); - this.btnUp.TabIndex = 18; - this.btnUp.Text = "Up"; - this.btnUp.UseVisualStyleBackColor = true; - this.btnUp.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnStart - // - this.btnStart.Location = new System.Drawing.Point(316, 131); - this.btnStart.Name = "btnStart"; - this.btnStart.Size = new System.Drawing.Size(61, 37); - this.btnStart.TabIndex = 13; - this.btnStart.Text = "W"; - this.btnStart.UseVisualStyleBackColor = true; - this.btnStart.Click += new System.EventHandler(this.btnMapping_Click); - // - // btnB - // - this.btnB.Location = new System.Drawing.Point(417, 105); - this.btnB.Name = "btnB"; - this.btnB.Size = new System.Drawing.Size(61, 59); - this.btnB.TabIndex = 15; - this.btnB.Text = "B"; - this.btnB.UseVisualStyleBackColor = true; - this.btnB.Click += new System.EventHandler(this.btnMapping_Click); + this.btnLeft.Location = new System.Drawing.Point(27, 90); + this.btnLeft.Name = "btnLeft"; + this.btnLeft.Size = new System.Drawing.Size(69, 35); + this.btnLeft.TabIndex = 17; + this.btnLeft.Text = "Left"; + this.btnLeft.UseVisualStyleBackColor = true; + this.btnLeft.Click += new System.EventHandler(this.btnMapping_Click); // // btnTurboA // @@ -133,45 +114,64 @@ this.btnTurboA.UseVisualStyleBackColor = true; this.btnTurboA.Click += new System.EventHandler(this.btnMapping_Click); // - // btnLeft + // btnB // - this.btnLeft.Location = new System.Drawing.Point(29, 90); - this.btnLeft.Name = "btnLeft"; - this.btnLeft.Size = new System.Drawing.Size(64, 35); - this.btnLeft.TabIndex = 17; - this.btnLeft.Text = "Left"; - this.btnLeft.UseVisualStyleBackColor = true; - this.btnLeft.Click += new System.EventHandler(this.btnMapping_Click); + this.btnB.Location = new System.Drawing.Point(417, 105); + this.btnB.Name = "btnB"; + this.btnB.Size = new System.Drawing.Size(61, 59); + this.btnB.TabIndex = 15; + this.btnB.Text = "B"; + this.btnB.UseVisualStyleBackColor = true; + this.btnB.Click += new System.EventHandler(this.btnMapping_Click); // - // btnSelect + // btnStart // - this.btnSelect.Location = new System.Drawing.Point(234, 131); - this.btnSelect.Name = "btnSelect"; - this.btnSelect.Size = new System.Drawing.Size(61, 37); - this.btnSelect.TabIndex = 12; - this.btnSelect.Text = "Q"; - this.btnSelect.UseVisualStyleBackColor = true; - this.btnSelect.Click += new System.EventHandler(this.btnMapping_Click); + this.btnStart.Location = new System.Drawing.Point(310, 131); + this.btnStart.Name = "btnStart"; + this.btnStart.Size = new System.Drawing.Size(73, 37); + this.btnStart.TabIndex = 13; + this.btnStart.Text = "W"; + this.btnStart.UseVisualStyleBackColor = true; + this.btnStart.Click += new System.EventHandler(this.btnMapping_Click); // - // btnRight + // btnUp // - this.btnRight.Location = new System.Drawing.Point(108, 90); - this.btnRight.Name = "btnRight"; - this.btnRight.Size = new System.Drawing.Size(64, 35); - this.btnRight.TabIndex = 16; - this.btnRight.Text = "Right"; - this.btnRight.UseVisualStyleBackColor = true; - this.btnRight.Click += new System.EventHandler(this.btnMapping_Click); + this.btnUp.Location = new System.Drawing.Point(61, 34); + this.btnUp.Name = "btnUp"; + this.btnUp.Size = new System.Drawing.Size(79, 35); + this.btnUp.TabIndex = 18; + this.btnUp.Text = "Up"; + this.btnUp.UseVisualStyleBackColor = true; + this.btnUp.Click += new System.EventHandler(this.btnMapping_Click); // - // btnTurboB + // btnDown // - this.btnTurboB.Location = new System.Drawing.Point(417, 17); - this.btnTurboB.Name = "btnTurboB"; - this.btnTurboB.Size = new System.Drawing.Size(61, 59); - this.btnTurboB.TabIndex = 21; - this.btnTurboB.Text = "B"; - this.btnTurboB.UseVisualStyleBackColor = true; - this.btnTurboB.Click += new System.EventHandler(this.btnMapping_Click); + this.btnDown.Location = new System.Drawing.Point(61, 141); + this.btnDown.Name = "btnDown"; + this.btnDown.Size = new System.Drawing.Size(79, 35); + this.btnDown.TabIndex = 19; + this.btnDown.Text = "Down"; + this.btnDown.UseVisualStyleBackColor = true; + this.btnDown.Click += new System.EventHandler(this.btnMapping_Click); + // + // btnA + // + this.btnA.Location = new System.Drawing.Point(499, 105); + this.btnA.Name = "btnA"; + this.btnA.Size = new System.Drawing.Size(61, 59); + this.btnA.TabIndex = 14; + this.btnA.Text = "A"; + this.btnA.UseVisualStyleBackColor = true; + this.btnA.Click += new System.EventHandler(this.btnMapping_Click); + // + // picControllerLayout + // + this.picControllerLayout.Image = ((System.Drawing.Image)(resources.GetObject("picControllerLayout.Image"))); + this.picControllerLayout.Location = new System.Drawing.Point(0, 0); + this.picControllerLayout.Name = "picControllerLayout"; + this.picControllerLayout.Size = new System.Drawing.Size(615, 211); + this.picControllerLayout.TabIndex = 11; + this.picControllerLayout.TabStop = false; // // ctrlStandardController // @@ -192,7 +192,6 @@ private System.Windows.Forms.Button btnTurboB; private System.Windows.Forms.Button btnRight; private System.Windows.Forms.Button btnSelect; - private System.Windows.Forms.Button btnLeft; private System.Windows.Forms.Button btnTurboA; private System.Windows.Forms.Button btnB; private System.Windows.Forms.Button btnStart; @@ -200,5 +199,6 @@ private System.Windows.Forms.Button btnDown; private System.Windows.Forms.Button btnA; private System.Windows.Forms.PictureBox picControllerLayout; + private System.Windows.Forms.Button btnLeft; } } diff --git a/GUI.NET/Forms/Config/ctrlStandardController.resx b/GUI.NET/Forms/Config/ctrlStandardController.resx index 4f6c473c..3987fb71 100644 --- a/GUI.NET/Forms/Config/ctrlStandardController.resx +++ b/GUI.NET/Forms/Config/ctrlStandardController.resx @@ -121,7 +121,7 @@ iVBORw0KGgoAAAANSUhEUgAAAkkAAADQCAYAAAATdvWWAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - vQAADr0BR/uQrQAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAJNpJREFUeF7t3Qm0 + vAAADrwBlbxySQAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC41ZYUyZQAAJNpJREFUeF7t3Qm0 LFtd33EH1Cc85IHMM4iC+hhEoqBomFTCEEFBEUGJosKKWWGtkKwMJpiY2aVkxQEFFAgODBGCKIoI7ykR UVRQEGWeZZ4RNCjk9+3ade3bd29ud93d53RVf39rfQ69e3efc26dXW//qV1d9Wmf/OQnJUmStKH6pCRJ 0rH7uwd5KEmSdOwskiRJkiqaRdLYliRJOiabtVCzQ5Ik6Zhs1kLNDkmSpGOyWQs1OyRJko7JZi3U7JAk diff --git a/GUI.NET/Forms/Config/frmGetKey.cs b/GUI.NET/Forms/Config/frmGetKey.cs index 170acafb..f4d8a318 100644 --- a/GUI.NET/Forms/Config/frmGetKey.cs +++ b/GUI.NET/Forms/Config/frmGetKey.cs @@ -15,6 +15,7 @@ namespace Mesen.GUI.Forms.Config public frmGetKey() { InitializeComponent(); + InteropEmu.UpdateInputDevices(); } public string BindedKey { get; set; } diff --git a/GUI.NET/Forms/Config/frmInputConfig.Designer.cs b/GUI.NET/Forms/Config/frmInputConfig.Designer.cs index 1ca3f28d..339ffa6a 100644 --- a/GUI.NET/Forms/Config/frmInputConfig.Designer.cs +++ b/GUI.NET/Forms/Config/frmInputConfig.Designer.cs @@ -232,7 +232,7 @@ this.btnSetupP1.AutoSize = true; this.btnSetupP1.Location = new System.Drawing.Point(282, 55); this.btnSetupP1.Name = "btnSetupP1"; - this.btnSetupP1.Size = new System.Drawing.Size(45, 23); + this.btnSetupP1.Size = new System.Drawing.Size(56, 23); this.btnSetupP1.TabIndex = 9; this.btnSetupP1.Text = "Setup"; this.btnSetupP1.UseVisualStyleBackColor = true; @@ -243,7 +243,7 @@ this.btnSetupP2.AutoSize = true; this.btnSetupP2.Location = new System.Drawing.Point(282, 84); this.btnSetupP2.Name = "btnSetupP2"; - this.btnSetupP2.Size = new System.Drawing.Size(45, 23); + this.btnSetupP2.Size = new System.Drawing.Size(56, 23); this.btnSetupP2.TabIndex = 10; this.btnSetupP2.Text = "Setup"; this.btnSetupP2.UseVisualStyleBackColor = true; diff --git a/GUI.NET/Forms/Config/frmInputConfig.cs b/GUI.NET/Forms/Config/frmInputConfig.cs index a7065a91..abdedbe3 100644 --- a/GUI.NET/Forms/Config/frmInputConfig.cs +++ b/GUI.NET/Forms/Config/frmInputConfig.cs @@ -17,6 +17,8 @@ namespace Mesen.GUI.Forms.Config { InitializeComponent(); + InteropEmu.UpdateInputDevices(); + Entity = ConfigManager.Config.InputInfo; if(ConfigManager.Config.InputInfo.AutoConfigureInput) { diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 584a9f06..4698825a 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -46,6 +46,7 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern ExpansionPortDevice GetExpansionDevice(); [DllImport(DLLPath)] public static extern ConsoleType GetConsoleType(); + [DllImport(DLLPath)] public static extern void UpdateInputDevices(); [DllImport(DLLPath)] public static extern UInt32 GetPressedKey(); [DllImport(DLLPath)] public static extern UInt32 GetKeyCode([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string keyName); [DllImport(DLLPath, EntryPoint="GetKeyName")] private static extern IntPtr GetKeyNameWrapper(UInt32 key); diff --git a/InteropDLL/ConsoleWrapper.cpp b/InteropDLL/ConsoleWrapper.cpp index 3c72ee2a..dc2ab802 100644 --- a/InteropDLL/ConsoleWrapper.cpp +++ b/InteropDLL/ConsoleWrapper.cpp @@ -21,6 +21,7 @@ NES::Renderer *_renderer = nullptr; SoundManager *_soundManager = nullptr; +IKeyManager *_keyManager = nullptr; HWND _windowHandle = nullptr; HWND _viewerHandle = nullptr; string _returnString; @@ -70,8 +71,9 @@ namespace InteropEmu { _renderer = new NES::Renderer(_viewerHandle); _soundManager = new SoundManager(_windowHandle); + _keyManager = new WindowsKeyManager(_windowHandle); - ControlManager::RegisterKeyManager(new WindowsKeyManager(_windowHandle)); + ControlManager::RegisterKeyManager(_keyManager); } } @@ -105,6 +107,7 @@ namespace InteropEmu { DllExport void __stdcall SetMousePosition(double x, double y) { ControlManager::SetMousePosition(x, y); } + DllExport void __stdcall UpdateInputDevices() { _keyManager->UpdateDevices(); } DllExport uint32_t __stdcall GetPressedKey() { return ControlManager::GetPressedKey(); } DllExport const char* __stdcall GetKeyName(uint32_t keyCode) { diff --git a/InteropDLL/InteropDLL.vcxproj b/InteropDLL/InteropDLL.vcxproj index 7e15ecdb..b53bd48b 100644 --- a/InteropDLL/InteropDLL.vcxproj +++ b/InteropDLL/InteropDLL.vcxproj @@ -187,7 +187,7 @@ Windows true - Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib + dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; $(OutDir);%(AdditionalLibraryDirectories) @@ -207,7 +207,7 @@ Windows true - Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; + dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; $(OutDir);%(AdditionalLibraryDirectories) @@ -230,7 +230,7 @@ true true true - Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; + dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; $(OutDir);%(AdditionalLibraryDirectories) @@ -253,7 +253,7 @@ true true true - Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; + dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; PGInstrument $(OutDir);%(AdditionalLibraryDirectories) @@ -276,7 +276,7 @@ true true true - Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; + dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; PGOptimization $(OutDir);%(AdditionalLibraryDirectories) @@ -300,7 +300,7 @@ true true true - Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; + dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; $(OutDir);%(AdditionalLibraryDirectories) @@ -323,7 +323,7 @@ true true true - Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; + dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; PGInstrument $(OutDir);%(AdditionalLibraryDirectories) @@ -346,7 +346,7 @@ true true true - Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; + dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; PGOptimization $(OutDir);%(AdditionalLibraryDirectories) diff --git a/Windows/DirectInputManager.cpp b/Windows/DirectInputManager.cpp new file mode 100644 index 00000000..72a3b396 --- /dev/null +++ b/Windows/DirectInputManager.cpp @@ -0,0 +1,235 @@ +#include "stdafx.h" + +#define DIRECTINPUT_VERSION 0x0800 +#include +#include +#include +#include +#include "DirectInputManager.h" + +LPDIRECTINPUT8 DirectInputManager::_directInput = nullptr; +vector DirectInputManager::_joysticks; + +bool DirectInputManager::Initialize() +{ + HRESULT hr; + + // Register with the DirectInput subsystem and get a pointer to a IDirectInput interface we can use. + // Create a DInput object + if(FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&_directInput, nullptr))) { + return false; + } + + IDirectInputJoyConfig8* pJoyConfig = nullptr; + if(FAILED(hr = _directInput->QueryInterface(IID_IDirectInputJoyConfig8, (void**)&pJoyConfig))) { + return false; + } + + if(pJoyConfig) { + pJoyConfig->Release(); + } + + return UpdateDeviceList(); +} + +bool DirectInputManager::UpdateDeviceList() +{ + HRESULT hr; + + for(DirectInputData &data : _joysticks) { + data.joystick->Unacquire(); + data.joystick->Release(); + } + _joysticks.clear(); + + // Enumerate devices + if(FAILED(hr = _directInput->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, nullptr, DIEDFL_ALLDEVICES))) { + return false; + } + + // Make sure we got a joystick + if(_joysticks.empty()) { + return false; + } + + for(DirectInputData& data : _joysticks) { + // Set the data format to "simple joystick" - a predefined data format + // A data format specifies which controls on a device we are interested in, and how they should be reported. + // This tells DInput that we will be passing a DIJOYSTATE2 structure to IDirectInputDevice::GetDeviceState(). + if(FAILED(hr = data.joystick->SetDataFormat(&c_dfDIJoystick2))) { + return false; + } + + // Set the cooperative level to let DInput know how this device should interact with the system and with other DInput applications. + if(FAILED(hr = data.joystick->SetCooperativeLevel(_hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))) { + return false; + } + + // Enumerate the joystick objects. The callback function enabled user interface elements for objects that are found, and sets the min/max values property for discovered axes. + if(FAILED(hr = data.joystick->EnumObjects(EnumObjectsCallback, data.joystick, DIDFT_ALL))) { + return false; + } + } + + //Sleeping apparently lets us read accurate "default" values, otherwise a PS4 controller returns all 0s, despite not doing so normally + RefreshState(); + std::this_thread::sleep_for(std::chrono::duration(100)); + RefreshState(); + for(DirectInputData &joystick : _joysticks) { + joystick.defaultState = joystick.state; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Name: EnumJoysticksCallback() +// Desc: Called once for each enumerated joystick. If we find one, create a +// device interface on it so we can play with it. +//----------------------------------------------------------------------------- +int DirectInputManager::EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, void* pContext) +{ + HRESULT hr; + + // Obtain an interface to the enumerated joystick. + LPDIRECTINPUTDEVICE8 pJoystick = nullptr; + hr = _directInput->CreateDevice(pdidInstance->guidInstance, &pJoystick, nullptr); + + if(SUCCEEDED(hr)) { + DIJOYSTATE2 state; + memset(&state, 0, sizeof(state)); + DirectInputData data{ pJoystick, state, state }; + _joysticks.push_back(data); + } + return DIENUM_CONTINUE; +} + +//----------------------------------------------------------------------------- +// Name: EnumObjectsCallback() +// Desc: Callback function for enumerating objects (axes, buttons, POVs) on a +// joystick. This function enables user interface elements for objects +// that are found to exist, and scales axes min/max values. +//----------------------------------------------------------------------------- +int DirectInputManager::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, void* pContext) +{ + LPDIRECTINPUTDEVICE8 joystick = (LPDIRECTINPUTDEVICE8)pContext; + + static int nSliderCount = 0; // Number of returned slider controls + static int nPOVCount = 0; // Number of returned POV controls + + // For axes that are returned, set the DIPROP_RANGE property for the enumerated axis in order to scale min/max values. + if(pdidoi->dwType & DIDFT_AXIS) { + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis + diprg.lMin = -1000; + diprg.lMax = +1000; + + // Set the range for the axis + if(FAILED(joystick->SetProperty(DIPROP_RANGE, &diprg.diph))) { + return DIENUM_STOP; + } + } + + return DIENUM_CONTINUE; +} + + +void DirectInputManager::RefreshState() +{ + for(DirectInputData &joystick : _joysticks) { + UpdateInputState(joystick); + } +} + +int DirectInputManager::GetJoystickCount() +{ + return (int)_joysticks.size(); +} + +bool DirectInputManager::IsPressed(int port, int button) +{ + if(port >= _joysticks.size()) { + return false; + } + + DIJOYSTATE2& state = _joysticks[port].state; + DIJOYSTATE2& defaultState = _joysticks[port].defaultState; + int deadRange = 500; + + bool povCentered = (LOWORD(state.rgdwPOV[0]) == 0xFFFF); + + switch(button) { + case 0x00: return state.lY - defaultState.lY < -deadRange; + case 0x01: return state.lY - defaultState.lY > deadRange; + case 0x02: return state.lX - defaultState.lX < -deadRange; + case 0x03: return state.lX - defaultState.lX > deadRange; + case 0x04: return state.lRy - defaultState.lRy < -deadRange; + case 0x05: return state.lRy - defaultState.lRy > deadRange; + case 0x06: return state.lRx - defaultState.lRx < -deadRange; + case 0x07: return state.lRx - defaultState.lRx > deadRange; + case 0x08: return state.lZ - defaultState.lZ < -deadRange; + case 0x09: return state.lZ - defaultState.lZ > deadRange; + case 0x0A: return state.lRz - defaultState.lRz < -deadRange; + case 0x0B: return state.lRz - defaultState.lRz > deadRange; + case 0x0C: return !povCentered && (state.rgdwPOV[0] >= 31500 || state.rgdwPOV[0] <= 4500); + case 0x0D: return !povCentered && state.rgdwPOV[0] >= 13500 && state.rgdwPOV[0] <= 22500; + case 0x0E: return !povCentered && state.rgdwPOV[0] >= 4500 && state.rgdwPOV[0] <= 13500; + case 0x0F: return !povCentered && state.rgdwPOV[0] >= 22500 && state.rgdwPOV[0] <= 31500; + default: return state.rgbButtons[button - 0x10] != 0; + } + + return false; +} + +bool DirectInputManager::UpdateInputState(DirectInputData &data) +{ + HRESULT hr; + + // Poll the device to read the current state + hr = data.joystick->Poll(); + if(FAILED(hr)) { + // DInput is telling us that the input stream has been interrupted. We aren't tracking any state between polls, so + // we don't have any special reset that needs to be done. We just re-acquire and try again. + hr = data.joystick->Acquire(); + while(hr == DIERR_INPUTLOST) { + hr = data.joystick->Acquire(); + } + + // hr may be DIERR_OTHERAPPHASPRIO or other errors. This may occur when the app is minimized or in the process of + // switching, so just try again later + if(FAILED(hr)) { + return true; + } + } + + // Get the input's device state + if(FAILED(hr = data.joystick->GetDeviceState(sizeof(DIJOYSTATE2), &data.state))) { + return false; // The device should have been acquired during the Poll() + } + + return true; +} + + +DirectInputManager::DirectInputManager(HWND hWnd) +{ + _hWnd = hWnd; + Initialize(); +} + +DirectInputManager::~DirectInputManager() +{ + for(DirectInputData &data: _joysticks) { + data.joystick->Unacquire(); + data.joystick->Release(); + } + _joysticks.clear(); + + if(_directInput) { + _directInput->Release(); + _directInput = nullptr; + } +} diff --git a/Windows/DirectInputManager.h b/Windows/DirectInputManager.h new file mode 100644 index 00000000..37f0c532 --- /dev/null +++ b/Windows/DirectInputManager.h @@ -0,0 +1,33 @@ +#pragma once +#include "stdafx.h" +#include +#include "../Utilities/SimpleLock.h" + +struct DirectInputData +{ + LPDIRECTINPUTDEVICE8 joystick; + DIJOYSTATE2 state; + DIJOYSTATE2 defaultState; +}; + +class DirectInputManager +{ +private: + HWND _hWnd; + static LPDIRECTINPUT8 _directInput; + static vector _joysticks; + + bool Initialize(); + bool UpdateInputState(DirectInputData& joystick); + static int __stdcall EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, void* pContext); + static int __stdcall EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, void* pContext); + +public: + DirectInputManager(HWND window); + ~DirectInputManager(); + + void RefreshState(); + bool UpdateDeviceList(); + int GetJoystickCount(); + bool IsPressed(int port, int button); +}; diff --git a/Windows/Windows.vcxproj b/Windows/Windows.vcxproj index 7c0d56d5..c0815ab7 100644 --- a/Windows/Windows.vcxproj +++ b/Windows/Windows.vcxproj @@ -296,6 +296,7 @@ + @@ -311,7 +312,7 @@ - + @@ -319,7 +320,8 @@ - + + false diff --git a/Windows/Windows.vcxproj.filters b/Windows/Windows.vcxproj.filters index fafe84f0..c74e0675 100644 --- a/Windows/Windows.vcxproj.filters +++ b/Windows/Windows.vcxproj.filters @@ -20,9 +20,6 @@ Header Files - - Header Files - Header Files @@ -77,14 +74,17 @@ Header Files + + Header Files + + + Header Files + Source Files - - Source Files - Source Files @@ -94,6 +94,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/Windows/WindowsKeyManager.cpp b/Windows/WindowsKeyManager.cpp index 880a2410..8985ec0e 100644 --- a/Windows/WindowsKeyManager.cpp +++ b/Windows/WindowsKeyManager.cpp @@ -2,9 +2,229 @@ #include "WindowsKeyManager.h" #include "../Core/ControlManager.h" +static vector _keyDefinitions = { + //{ "VK_LBUTTON", 0x01, "Left mouse button" }, + //{ "VK_RBUTTON", 0x02, "Right mouse button" }, + { "VK_CANCEL", 0x03, "Control-break processing" }, + //{ "VK_MBUTTON", 0x04, "Middle mouse button (three-button mouse)" }, + //{ "VK_XBUTTON1", 0x05, "X1 mouse button" }, + //{ "VK_XBUTTON2", 0x06, "X2 mouse button" }, + { "-", 0x07, "Undefined" }, + { "VK_BACK", 0x08, "Backspace" }, + { "VK_TAB", 0x09, "Tab" }, + //{ "-", 0x0A - 0B, "Reserved" }, + { "VK_CLEAR", 0x0C, "Clear" }, + { "VK_RETURN", 0x0D, "Enter" }, + //{ "-", 0x0E - 0F, "Undefined" }, + { "VK_SHIFT", 0x10, "Shift" }, + { "VK_CONTROL", 0x11, "Ctrl" }, + { "VK_MENU", 0x12, "Alt" }, + { "VK_PAUSE", 0x13, "Pause" }, + { "VK_CAPITAL", 0x14, "Caps Lock" }, + { "VK_KANA", 0x15, "IME Kana mode" }, + { "VK_HANGUEL", 0x15, "IME Hanguel mode" }, + { "VK_HANGUL", 0x15, "IME Hangul mode" }, + //{ "-", 0x16, "Undefined" }, + { "VK_JUNJA", 0x17, "IME Junja mode" }, + { "VK_FINAL", 0x18, "IME final mode" }, + { "VK_HANJA", 0x19, "IME Hanja mode" }, + { "VK_KANJI", 0x19, "IME Kanji mode" }, + //{ "-", 0x1A, "Undefined" }, + { "VK_ESCAPE", 0x1B, "Esc" }, + { "VK_CONVERT", 0x1C, "IME convert" }, + { "VK_NONCONVERT", 0x1D, "IME nonconvert" }, + { "VK_ACCEPT", 0x1E, "IME accept" }, + { "VK_MODECHANGE", 0x1F, "IME mode change request" }, + { "VK_SPACE", 0x20, "Spacebar" }, + { "VK_PRIOR", 0x21, "Page Up" }, + { "VK_NEXT", 0x22, "Page Down" }, + { "VK_END", 0x23, "End" }, + { "VK_HOME", 0x24, "Home" }, + { "VK_LEFT", 0x25, "Left Arrow" }, + { "VK_UP", 0x26, "Up Arrow" }, + { "VK_RIGHT", 0x27, "Right Arrow" }, + { "VK_DOWN", 0x28, "Down Arrow" }, + { "VK_SELECT", 0x29, "Select" }, + { "VK_PRINT", 0x2A, "Print" }, + { "VK_EXECUTE", 0x2B, "Execute" }, + { "VK_SNAPSHOT", 0x2C, "Print Screen" }, + { "VK_INSERT", 0x2D, "Ins" }, + { "VK_DELETE", 0x2E, "Del" }, + { "VK_HELP", 0x2F, "Help" }, + { "0", 0x30, "0" }, + { "1", 0x31, "1" }, + { "2", 0x32, "2" }, + { "3", 0x33, "3" }, + { "4", 0x34, "4" }, + { "5", 0x35, "5" }, + { "6", 0x36, "6" }, + { "7", 0x37, "7" }, + { "8", 0x38, "8" }, + { "9", 0x39, "9" }, + //{ "undefined", 0x3A - 40, "undefined" }, + { "A", 0x41, "A" }, + { "B", 0x42, "B" }, + { "C", 0x43, "C" }, + { "D", 0x44, "D" }, + { "E", 0x45, "E" }, + { "F", 0x46, "F" }, + { "G", 0x47, "G" }, + { "H", 0x48, "H" }, + { "I", 0x49, "I" }, + { "J", 0x4A, "J" }, + { "K", 0x4B, "K" }, + { "L", 0x4C, "L" }, + { "M", 0x4D, "M" }, + { "N", 0x4E, "N" }, + { "O", 0x4F, "O" }, + { "P", 0x50, "P" }, + { "Q", 0x51, "Q" }, + { "R", 0x52, "R" }, + { "S", 0x53, "S" }, + { "T", 0x54, "T" }, + { "U", 0x55, "U" }, + { "V", 0x56, "V" }, + { "W", 0x57, "W" }, + { "X", 0x58, "X" }, + { "Y", 0x59, "Y" }, + { "Z", 0x5A, "Z" }, + { "VK_LWIN", 0x5B, "Left Windows" }, + { "VK_RWIN", 0x5C, "Right Windows" }, + { "VK_APPS", 0x5D, "Applications Key" }, + //{ "-", 0x5E, "Reserved" }, + { "VK_SLEEP", 0x5F, "Computer Sleep" }, + { "VK_NUMPAD0", 0x60, "Keypad 0" }, + { "VK_NUMPAD1", 0x61, "Keypad 1" }, + { "VK_NUMPAD2", 0x62, "Keypad 2" }, + { "VK_NUMPAD3", 0x63, "Keypad 3" }, + { "VK_NUMPAD4", 0x64, "Keypad 4" }, + { "VK_NUMPAD5", 0x65, "Keypad 5" }, + { "VK_NUMPAD6", 0x66, "Keypad 6" }, + { "VK_NUMPAD7", 0x67, "Keypad 7" }, + { "VK_NUMPAD8", 0x68, "Keypad 8" }, + { "VK_NUMPAD9", 0x69, "Keypad 9" }, + { "VK_MULTIPLY", 0x6A, "Multiply" }, + { "VK_ADD", 0x6B, "Add" }, + { "VK_SEPARATOR", 0x6C, "Separator" }, + { "VK_SUBTRACT", 0x6D, "Subtract" }, + { "VK_DECIMAL", 0x6E, "Decimal" }, + { "VK_DIVIDE", 0x6F, "Divide" }, + { "VK_F1", 0x70, "F1" }, + { "VK_F2", 0x71, "F2" }, + { "VK_F3", 0x72, "F3" }, + { "VK_F4", 0x73, "F4" }, + { "VK_F5", 0x74, "F5" }, + { "VK_F6", 0x75, "F6" }, + { "VK_F7", 0x76, "F7" }, + { "VK_F8", 0x77, "F8" }, + { "VK_F9", 0x78, "F9" }, + { "VK_F10", 0x79, "F10" }, + { "VK_F11", 0x7A, "F11" }, + { "VK_F12", 0x7B, "F12" }, + { "VK_F13", 0x7C, "F13" }, + { "VK_F14", 0x7D, "F14" }, + { "VK_F15", 0x7E, "F15" }, + { "VK_F16", 0x7F, "F16" }, + { "VK_F17", 0x80, "F17" }, + { "VK_F18", 0x81, "F18" }, + { "VK_F19", 0x82, "F19" }, + { "VK_F20", 0x83, "F20" }, + { "VK_F21", 0x84, "F21" }, + { "VK_F22", 0x85, "F22" }, + { "VK_F23", 0x86, "F23" }, + { "VK_F24", 0x87, "F24" }, + //{ "-", 0x88 - 8F, "Unassigned" }, + { "VK_NUMLOCK", 0x90, "Num Lock" }, + { "VK_SCROLL", 0x91, "Scroll Lock" }, + //{"-", 0x92-96,"OEM specific"}, + //{ "-", 0x97 - 9F, "Unassigned" }, + { "VK_LSHIFT", 0xA0, "Left Shift" }, + { "VK_RSHIFT", 0xA1, "Right Shift" }, + { "VK_LCONTROL", 0xA2, "Left Control" }, + { "VK_RCONTROL", 0xA3, "Right Control" }, + { "VK_LMENU", 0xA4, "Left Menu" }, + { "VK_RMENU", 0xA5, "Right Menu" }, + { "VK_BROWSER_BACK", 0xA6, "Browser Back" }, + { "VK_BROWSER_FORWARD", 0xA7, "Browser Forward" }, + { "VK_BROWSER_REFRESH", 0xA8, "Browser Refresh" }, + { "VK_BROWSER_STOP", 0xA9, "Browser Stop" }, + { "VK_BROWSER_SEARCH", 0xAA, "Browser Search" }, + { "VK_BROWSER_FAVORITES", 0xAB, "Browser Favorites" }, + { "VK_BROWSER_HOME", 0xAC, "Browser Start and Home" }, + { "VK_VOLUME_MUTE", 0xAD, "Volume Mute" }, + { "VK_VOLUME_DOWN", 0xAE, "Volume Down" }, + { "VK_VOLUME_UP", 0xAF, "Volume Up" }, + { "VK_MEDIA_NEXT_TRACK", 0xB0, "Next Track" }, + { "VK_MEDIA_PREV_TRACK", 0xB1, "Previous Track" }, + { "VK_MEDIA_STOP", 0xB2, "Stop Media" }, + { "VK_MEDIA_PLAY_PAUSE", 0xB3, "Play/Pause Media" }, + { "VK_LAUNCH_MAIL", 0xB4, "Start Mail" }, + { "VK_LAUNCH_MEDIA_SELECT", 0xB5, "Select Media" }, + { "VK_LAUNCH_APP1", 0xB6, "Start Application 1" }, + { "VK_LAUNCH_APP2", 0xB7, "Start Application 2" }, + //{ "-", 0xB8 - B9, "Reserved" }, + { "VK_OEM_1", 0xBA, "Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the \';:\' key VK_OEM_PLUS" }, + { "VK_OEM_PLUS", 0xBB, "+" }, + { "VK_OEM_COMMA", 0xBC, "," }, + { "VK_OEM_MINUS", 0xBD, "-" }, + { "VK_OEM_PERIOD", 0xBE, "." }, + { "VK_OEM_2", 0xBF, "/" }, + { "VK_OEM_3", 0xC0, "`" }, + //{ "-", 0xC1 - D7, "Reserved" }, + //{ "-", 0xD8 - DA, "Unassigned" }, + { "VK_OEM_4", 0xDB, "[" }, + { "VK_OEM_5", 0xDC, "\\" }, + { "VK_OEM_6", 0xDD, "]" }, + { "VK_OEM_7", 0xDE, "'" }, + { "VK_OEM_8", 0xDF, "Used for miscellaneous characters; it can vary by keyboard." }, + //{ "-", 0xE0, "Reserved" }, + //{ "-", 0xE1, "OEM specific" }, + { "VK_OEM_102", 0xE2, "Either the angle bracket key or the backslash key on the RT 102-key keyboard" }, + //{ "-", 0xE3 - E4, "OEM specific" }, + { "VK_PROCESSKEY", 0xE5, "IME PROCESS" }, + //{ "-", 0xE6, "OEM specific" }, + { "VK_PACKET", 0xE7, "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP" }, + //{ "-", 0xE8, "Unassigned" }, + // {"-",0xE6,"OEM specific"}, + { "VK_PACKET", 0xE7, "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP" }, + // {"-",0xE8,"Unassigned"}, + //{ "-", 0xE9 - F5, "OEM specific" }, + { "VK_ATTN", 0xF6, "Attn" }, + { "VK_CRSEL", 0xF7, "CrSel" }, + { "VK_EXSEL", 0xF8, "ExSel" }, + { "VK_EREOF", 0xF9, "Erase EOF" }, + { "VK_PLAY", 0xFA, "Play" }, + { "VK_ZOOM", 0xFB, "Zoom" }, + { "VK_NONAME", 0xFC, "Reserved" }, + { "VK_PA1", 0xFD, "PA1" }, + { "VK_OEM_CLEAR", 0xFE, "Clear" } +}; + WindowsKeyManager::WindowsKeyManager(HWND hWnd) { _hWnd = hWnd; + + //Init XInput buttons + vector buttonNames = { "Up", "Down", "Left", "Right", "Start", "Back", "L3", "R3", "L1", "R1", "?", "?", "A", "B", "X", "Y", "L2", "R2", "RT Up", "RT Down", "RT Up", "RT Left", "RT Right" }; + for(int i = 0; i < 4; i++) { + for(int j = 0; j < buttonNames.size(); j++) { + _keyDefinitions.push_back({ "", (uint32_t)(0xFFFF + i * 0x100 + j + 1), "Pad" + std::to_string(i + 1) + " " + buttonNames[j] }); + } + } + + //Init DirectInput buttons + vector diButtonNames = { "Y+", "Y-", "X-", "X+", "Y2+", "Y2-", "X2-", "X2+", "Z+", "Z-", "Z2+", "Z2-", "DPad Up", "DPad Down", "DPad Right", "DPad Left" }; + for(int i = 0; i < 16; i++) { + for(int j = 0; j < diButtonNames.size(); j++) { + _keyDefinitions.push_back({ "", (uint32_t)(0x11000 + i * 0x100 + j), "Joy" + std::to_string(i + 1) + " " + diButtonNames[j] }); + } + + for(int j = 0; j < 128; j++) { + _keyDefinitions.push_back({ "", (uint32_t)(0x11000 + i * 0x100 + j + 0x10), "Joy" + std::to_string(i + 1) + " But" + std::to_string(j+1)}); + } + } + + _directInput.reset(new DirectInput(hWnd)); } WindowsKeyManager::~WindowsKeyManager() @@ -14,15 +234,23 @@ WindowsKeyManager::~WindowsKeyManager() void WindowsKeyManager::RefreshState() { _gamePad.RefreshState(); + _directInput->RefreshState(); } bool WindowsKeyManager::IsKeyPressed(uint32_t key) { if(key >= 0x10000) { - //XInput key - uint8_t gamepadPort = (key - 0xFFFF) / 0x100; - uint8_t gamepadButton = (key - 0xFFFF) % 0x100; - return _gamePad.IsPressed(gamepadPort, gamepadButton); + if(key >= 0x11000) { + //Directinput key + uint8_t gamepadPort = (key - 0x11000) / 0x100; + uint8_t gamepadButton = (key - 0x11000) % 0x100; + return _directInput->IsButtonPressed(gamepadPort, gamepadButton); + } else { + //XInput key + uint8_t gamepadPort = (key - 0xFFFF) / 0x100; + uint8_t gamepadButton = (key - 0xFFFF) % 0x100; + return _gamePad.IsPressed(gamepadPort, gamepadButton); + } } else { return (GetAsyncKeyState(key) & 0x8000) == 0x8000; } @@ -44,7 +272,6 @@ bool WindowsKeyManager::IsMouseButtonPressed(MouseButton button) uint32_t WindowsKeyManager::GetPressedKey() { _gamePad.RefreshState(); - for(int i = 0; i < XUSER_MAX_COUNT; i++) { for(int j = 1; j <= 22; j++) { if(_gamePad.IsPressed(i, j)) { @@ -53,6 +280,15 @@ uint32_t WindowsKeyManager::GetPressedKey() } } + _directInput->RefreshState(); + for(int i = _directInput->GetJoystickCount() - 1; i >= 0; i--) { + for(int j = 0; j < 0x29; j++) { + if(_directInput->IsButtonPressed(i, j)) { + return 0x11000 + i * 0x100 + j; + } + } + } + for(int i = 0; i < 0xFF; i++) { if((GetAsyncKeyState(i) & 0x8000) == 0x8000) { return i; @@ -79,4 +315,4 @@ uint32_t WindowsKeyManager::GetKeyCode(string keyName) } } return 0; -} \ No newline at end of file +} diff --git a/Windows/WindowsKeyManager.h b/Windows/WindowsKeyManager.h index 807457be..2f66a8b4 100644 --- a/Windows/WindowsKeyManager.h +++ b/Windows/WindowsKeyManager.h @@ -2,7 +2,9 @@ #include "stdafx.h" #include "../Core/IKeyManager.h" -#include "GamePad.h" +#include "../Utilities/Timer.h" +#include "XInputManager.h" +#include "DirectInputManager.h" struct KeyDefinition { string name; @@ -10,293 +12,13 @@ struct KeyDefinition { string description; }; -const KeyDefinition _keyDefinitions[] = { - //{ "VK_LBUTTON", 0x01, "Left mouse button" }, - //{ "VK_RBUTTON", 0x02, "Right mouse button" }, - { "VK_CANCEL", 0x03, "Control-break processing" }, - //{ "VK_MBUTTON", 0x04, "Middle mouse button (three-button mouse)" }, - //{ "VK_XBUTTON1", 0x05, "X1 mouse button" }, - //{ "VK_XBUTTON2", 0x06, "X2 mouse button" }, - { "-", 0x07, "Undefined" }, - { "VK_BACK", 0x08, "Backspace" }, - { "VK_TAB", 0x09, "Tab" }, - //{ "-", 0x0A - 0B, "Reserved" }, - { "VK_CLEAR", 0x0C, "Clear" }, - { "VK_RETURN", 0x0D, "Enter" }, - //{ "-", 0x0E - 0F, "Undefined" }, - { "VK_SHIFT", 0x10, "Shift" }, - { "VK_CONTROL", 0x11, "Ctrl" }, - { "VK_MENU", 0x12, "Alt" }, - { "VK_PAUSE", 0x13, "Pause" }, - { "VK_CAPITAL", 0x14, "Caps Lock" }, - { "VK_KANA", 0x15, "IME Kana mode" }, - { "VK_HANGUEL", 0x15, "IME Hanguel mode" }, - { "VK_HANGUL", 0x15, "IME Hangul mode" }, - //{ "-", 0x16, "Undefined" }, - { "VK_JUNJA", 0x17, "IME Junja mode" }, - { "VK_FINAL", 0x18, "IME final mode" }, - { "VK_HANJA", 0x19, "IME Hanja mode" }, - { "VK_KANJI", 0x19, "IME Kanji mode" }, - //{ "-", 0x1A, "Undefined" }, - { "VK_ESCAPE", 0x1B, "Esc" }, - { "VK_CONVERT", 0x1C, "IME convert" }, - { "VK_NONCONVERT", 0x1D, "IME nonconvert" }, - { "VK_ACCEPT", 0x1E, "IME accept" }, - { "VK_MODECHANGE", 0x1F, "IME mode change request" }, - { "VK_SPACE", 0x20, "Spacebar" }, - { "VK_PRIOR", 0x21, "Page Up" }, - { "VK_NEXT", 0x22, "Page Down" }, - { "VK_END", 0x23, "End" }, - { "VK_HOME", 0x24, "Home" }, - { "VK_LEFT", 0x25, "Left Arrow" }, - { "VK_UP", 0x26, "Up Arrow" }, - { "VK_RIGHT", 0x27, "Right Arrow" }, - { "VK_DOWN", 0x28, "Down Arrow" }, - { "VK_SELECT", 0x29, "Select" }, - { "VK_PRINT", 0x2A, "Print" }, - { "VK_EXECUTE", 0x2B, "Execute" }, - { "VK_SNAPSHOT", 0x2C, "Print Screen" }, - { "VK_INSERT", 0x2D, "Ins" }, - { "VK_DELETE", 0x2E, "Del" }, - { "VK_HELP", 0x2F, "Help" }, - { "0", 0x30, "0" }, - { "1", 0x31, "1" }, - { "2", 0x32, "2" }, - { "3", 0x33, "3" }, - { "4", 0x34, "4" }, - { "5", 0x35, "5" }, - { "6", 0x36, "6" }, - { "7", 0x37, "7" }, - { "8", 0x38, "8" }, - { "9", 0x39, "9" }, - //{ "undefined", 0x3A - 40, "undefined" }, - { "A", 0x41, "A" }, - { "B", 0x42, "B" }, - { "C", 0x43, "C" }, - { "D", 0x44, "D" }, - { "E", 0x45, "E" }, - { "F", 0x46, "F" }, - { "G", 0x47, "G" }, - { "H", 0x48, "H" }, - { "I", 0x49, "I" }, - { "J", 0x4A, "J" }, - { "K", 0x4B, "K" }, - { "L", 0x4C, "L" }, - { "M", 0x4D, "M" }, - { "N", 0x4E, "N" }, - { "O", 0x4F, "O" }, - { "P", 0x50, "P" }, - { "Q", 0x51, "Q" }, - { "R", 0x52, "R" }, - { "S", 0x53, "S" }, - { "T", 0x54, "T" }, - { "U", 0x55, "U" }, - { "V", 0x56, "V" }, - { "W", 0x57, "W" }, - { "X", 0x58, "X" }, - { "Y", 0x59, "Y" }, - { "Z", 0x5A, "Z" }, - { "VK_LWIN", 0x5B, "Left Windows" }, - { "VK_RWIN", 0x5C, "Right Windows" }, - { "VK_APPS", 0x5D, "Applications Key" }, - //{ "-", 0x5E, "Reserved" }, - { "VK_SLEEP", 0x5F, "Computer Sleep" }, - { "VK_NUMPAD0", 0x60, "Keypad 0" }, - { "VK_NUMPAD1", 0x61, "Keypad 1" }, - { "VK_NUMPAD2", 0x62, "Keypad 2" }, - { "VK_NUMPAD3", 0x63, "Keypad 3" }, - { "VK_NUMPAD4", 0x64, "Keypad 4" }, - { "VK_NUMPAD5", 0x65, "Keypad 5" }, - { "VK_NUMPAD6", 0x66, "Keypad 6" }, - { "VK_NUMPAD7", 0x67, "Keypad 7" }, - { "VK_NUMPAD8", 0x68, "Keypad 8" }, - { "VK_NUMPAD9", 0x69, "Keypad 9" }, - { "VK_MULTIPLY", 0x6A, "Multiply" }, - { "VK_ADD", 0x6B, "Add" }, - { "VK_SEPARATOR", 0x6C, "Separator" }, - { "VK_SUBTRACT", 0x6D, "Subtract" }, - { "VK_DECIMAL", 0x6E, "Decimal" }, - { "VK_DIVIDE", 0x6F, "Divide" }, - { "VK_F1", 0x70, "F1" }, - { "VK_F2", 0x71, "F2" }, - { "VK_F3", 0x72, "F3" }, - { "VK_F4", 0x73, "F4" }, - { "VK_F5", 0x74, "F5" }, - { "VK_F6", 0x75, "F6" }, - { "VK_F7", 0x76, "F7" }, - { "VK_F8", 0x77, "F8" }, - { "VK_F9", 0x78, "F9" }, - { "VK_F10", 0x79, "F10" }, - { "VK_F11", 0x7A, "F11" }, - { "VK_F12", 0x7B, "F12" }, - { "VK_F13", 0x7C, "F13" }, - { "VK_F14", 0x7D, "F14" }, - { "VK_F15", 0x7E, "F15" }, - { "VK_F16", 0x7F, "F16" }, - { "VK_F17", 0x80, "F17" }, - { "VK_F18", 0x81, "F18" }, - { "VK_F19", 0x82, "F19" }, - { "VK_F20", 0x83, "F20" }, - { "VK_F21", 0x84, "F21" }, - { "VK_F22", 0x85, "F22" }, - { "VK_F23", 0x86, "F23" }, - { "VK_F24", 0x87, "F24" }, - //{ "-", 0x88 - 8F, "Unassigned" }, - { "VK_NUMLOCK", 0x90, "Num Lock" }, - { "VK_SCROLL", 0x91, "Scroll Lock" }, - //{"-", 0x92-96,"OEM specific"}, - //{ "-", 0x97 - 9F, "Unassigned" }, - { "VK_LSHIFT", 0xA0, "Left Shift" }, - { "VK_RSHIFT", 0xA1, "Right Shift" }, - { "VK_LCONTROL", 0xA2, "Left Control" }, - { "VK_RCONTROL", 0xA3, "Right Control" }, - { "VK_LMENU", 0xA4, "Left Menu" }, - { "VK_RMENU", 0xA5, "Right Menu" }, - { "VK_BROWSER_BACK", 0xA6, "Browser Back" }, - { "VK_BROWSER_FORWARD", 0xA7, "Browser Forward" }, - { "VK_BROWSER_REFRESH", 0xA8, "Browser Refresh" }, - { "VK_BROWSER_STOP", 0xA9, "Browser Stop" }, - { "VK_BROWSER_SEARCH", 0xAA, "Browser Search" }, - { "VK_BROWSER_FAVORITES", 0xAB, "Browser Favorites" }, - { "VK_BROWSER_HOME", 0xAC, "Browser Start and Home" }, - { "VK_VOLUME_MUTE", 0xAD, "Volume Mute" }, - { "VK_VOLUME_DOWN", 0xAE, "Volume Down" }, - { "VK_VOLUME_UP", 0xAF, "Volume Up" }, - { "VK_MEDIA_NEXT_TRACK", 0xB0, "Next Track" }, - { "VK_MEDIA_PREV_TRACK", 0xB1, "Previous Track" }, - { "VK_MEDIA_STOP", 0xB2, "Stop Media" }, - { "VK_MEDIA_PLAY_PAUSE", 0xB3, "Play/Pause Media" }, - { "VK_LAUNCH_MAIL", 0xB4, "Start Mail" }, - { "VK_LAUNCH_MEDIA_SELECT", 0xB5, "Select Media" }, - { "VK_LAUNCH_APP1", 0xB6, "Start Application 1" }, - { "VK_LAUNCH_APP2", 0xB7, "Start Application 2" }, - //{ "-", 0xB8 - B9, "Reserved" }, - { "VK_OEM_1", 0xBA, "Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the \';:\' key VK_OEM_PLUS" }, - { "VK_OEM_PLUS", 0xBB, "+" }, - { "VK_OEM_COMMA", 0xBC, "," }, - { "VK_OEM_MINUS", 0xBD, "-" }, - { "VK_OEM_PERIOD", 0xBE, "." }, - { "VK_OEM_2", 0xBF, "/" }, - { "VK_OEM_3", 0xC0, "`" }, - //{ "-", 0xC1 - D7, "Reserved" }, - //{ "-", 0xD8 - DA, "Unassigned" }, - { "VK_OEM_4", 0xDB, "[" }, - { "VK_OEM_5", 0xDC, "\\" }, - { "VK_OEM_6", 0xDD, "]" }, - { "VK_OEM_7", 0xDE, "'" }, - { "VK_OEM_8", 0xDF, "Used for miscellaneous characters; it can vary by keyboard." }, - //{ "-", 0xE0, "Reserved" }, - //{ "-", 0xE1, "OEM specific" }, - { "VK_OEM_102", 0xE2, "Either the angle bracket key or the backslash key on the RT 102-key keyboard" }, - //{ "-", 0xE3 - E4, "OEM specific" }, - { "VK_PROCESSKEY", 0xE5, "IME PROCESS" }, - //{ "-", 0xE6, "OEM specific" }, - { "VK_PACKET", 0xE7, "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP" }, - //{ "-", 0xE8, "Unassigned" }, - // {"-",0xE6,"OEM specific"}, - { "VK_PACKET", 0xE7, "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP" }, - // {"-",0xE8,"Unassigned"}, - //{ "-", 0xE9 - F5, "OEM specific" }, - { "VK_ATTN", 0xF6, "Attn" }, - { "VK_CRSEL", 0xF7, "CrSel" }, - { "VK_EXSEL", 0xF8, "ExSel" }, - { "VK_EREOF", 0xF9, "Erase EOF" }, - { "VK_PLAY", 0xFA, "Play" }, - { "VK_ZOOM", 0xFB, "Zoom" }, - { "VK_NONAME", 0xFC, "Reserved" }, - { "VK_PA1", 0xFD, "PA1" }, - { "VK_OEM_CLEAR", 0xFE, "Clear" }, - - { "", 0xFFFF + 0x01, "Pad1 Up" }, - { "", 0xFFFF + 0x02, "Pad1 Down" }, - { "", 0xFFFF + 0x03, "Pad1 Left" }, - { "", 0xFFFF + 0x04, "Pad1 Right" }, - { "", 0xFFFF + 0x05, "Pad1 Start" }, - { "", 0xFFFF + 0x06, "Pad1 Back" }, - { "", 0xFFFF + 0x07, "Pad1 L3" }, - { "", 0xFFFF + 0x08, "Pad1 R3" }, - { "", 0xFFFF + 0x09, "Pad1 L1" }, - { "", 0xFFFF + 0x0A, "Pad1 R1" }, - { "", 0xFFFF + 0x0D, "Pad1 A" }, - { "", 0xFFFF + 0x0E, "Pad1 B" }, - { "", 0xFFFF + 0x0F, "Pad1 X" }, - { "", 0xFFFF + 0x10, "Pad1 Y" }, - { "", 0xFFFF + 0x11, "Pad1 L2" }, - { "", 0xFFFF + 0x12, "Pad1 R2" }, - { "", 0xFFFF + 0x13, "Pad1 RT Up" }, - { "", 0xFFFF + 0x14, "Pad1 RT Down" }, - { "", 0xFFFF + 0x15, "Pad1 RT Left" }, - { "", 0xFFFF + 0x16, "Pad1 RT Right" }, - - { "", 0xFFFF + 0x101, "Pad2 Up" }, - { "", 0xFFFF + 0x102, "Pad2 Down" }, - { "", 0xFFFF + 0x103, "Pad2 Left" }, - { "", 0xFFFF + 0x104, "Pad2 Right" }, - { "", 0xFFFF + 0x105, "Pad2 Start" }, - { "", 0xFFFF + 0x106, "Pad2 Back" }, - { "", 0xFFFF + 0x107, "Pad2 Left Thumb" }, - { "", 0xFFFF + 0x108, "Pad2 Right Thumb" }, - { "", 0xFFFF + 0x109, "Pad2 Left Bumper" }, - { "", 0xFFFF + 0x10A, "Pad2 Right Bumper" }, - { "", 0xFFFF + 0x10D, "Pad2 A" }, - { "", 0xFFFF + 0x10E, "Pad2 B" }, - { "", 0xFFFF + 0x10F, "Pad2 X" }, - { "", 0xFFFF + 0x110, "Pad2 Y" }, - { "", 0xFFFF + 0x111, "Pad2 L2" }, - { "", 0xFFFF + 0x112, "Pad2 R2" }, - { "", 0xFFFF + 0x113, "Pad2 RT Up" }, - { "", 0xFFFF + 0x114, "Pad2 RT Down" }, - { "", 0xFFFF + 0x115, "Pad2 RT Left" }, - { "", 0xFFFF + 0x116, "Pad2 RT Right" }, - - { "", 0xFFFF + 0x201, "Pad3 Up" }, - { "", 0xFFFF + 0x202, "Pad3 Down" }, - { "", 0xFFFF + 0x203, "Pad3 Left" }, - { "", 0xFFFF + 0x204, "Pad3 Right" }, - { "", 0xFFFF + 0x205, "Pad3 Start" }, - { "", 0xFFFF + 0x206, "Pad3 Back" }, - { "", 0xFFFF + 0x207, "Pad3 Left Thumb" }, - { "", 0xFFFF + 0x208, "Pad3 Right Thumb" }, - { "", 0xFFFF + 0x209, "Pad3 Left Bumper" }, - { "", 0xFFFF + 0x20A, "Pad3 Right Bumper" }, - { "", 0xFFFF + 0x20D, "Pad3 A" }, - { "", 0xFFFF + 0x20E, "Pad3 B" }, - { "", 0xFFFF + 0x20F, "Pad3 X" }, - { "", 0xFFFF + 0x210, "Pad3 Y" }, - { "", 0xFFFF + 0x211, "Pad3 L2" }, - { "", 0xFFFF + 0x212, "Pad3 R2" }, - { "", 0xFFFF + 0x213, "Pad3 RT Up" }, - { "", 0xFFFF + 0x214, "Pad3 RT Down" }, - { "", 0xFFFF + 0x215, "Pad3 RT Left" }, - { "", 0xFFFF + 0x216, "Pad3 RT Right" }, - - { "", 0xFFFF + 0x301, "Pad4 Up" }, - { "", 0xFFFF + 0x302, "Pad4 Down" }, - { "", 0xFFFF + 0x303, "Pad4 Left" }, - { "", 0xFFFF + 0x304, "Pad4 Right" }, - { "", 0xFFFF + 0x305, "Pad4 Start" }, - { "", 0xFFFF + 0x306, "Pad4 Back" }, - { "", 0xFFFF + 0x307, "Pad4 Left Thumb" }, - { "", 0xFFFF + 0x308, "Pad4 Right Thumb" }, - { "", 0xFFFF + 0x309, "Pad4 Left Bumper" }, - { "", 0xFFFF + 0x30A, "Pad4 Right Bumper" }, - { "", 0xFFFF + 0x30D, "Pad4 A" }, - { "", 0xFFFF + 0x30E, "Pad4 B" }, - { "", 0xFFFF + 0x30F, "Pad4 X" }, - { "", 0xFFFF + 0x310, "Pad4 Y" }, - { "", 0xFFFF + 0x311, "Pad4 L2" }, - { "", 0xFFFF + 0x312, "Pad4 R2" }, - { "", 0xFFFF + 0x313, "Pad4 RT Up" }, - { "", 0xFFFF + 0x314, "Pad4 RT Down" }, - { "", 0xFFFF + 0x315, "Pad4 RT Left" }, - { "", 0xFFFF + 0x316, "Pad4 RT Right" } -}; - class WindowsKeyManager : public IKeyManager { private: - GamePad _gamePad; + Timer _timer; HWND _hWnd; + unique_ptr _directInput; + unique_ptr _xInput; public: WindowsKeyManager(HWND hWnd); @@ -308,4 +30,6 @@ class WindowsKeyManager : public IKeyManager uint32_t GetPressedKey(); string GetKeyName(uint32_t key); uint32_t GetKeyCode(string keyName); + + void UpdateDevices(); }; diff --git a/Windows/GamePad.cpp b/Windows/XInputManager.cpp similarity index 79% rename from Windows/GamePad.cpp rename to Windows/XInputManager.cpp index 2fc9c425..3837a4b6 100644 --- a/Windows/GamePad.cpp +++ b/Windows/XInputManager.cpp @@ -1,28 +1,37 @@ #include "stdafx.h" -#include "GamePad.h" +#include "XInputManager.h" -GamePad::GamePad() +XInputManager::XInputManager() { for(int i = 0; i < XUSER_MAX_COUNT; i++) { _gamePadStates.push_back(shared_ptr(new XINPUT_STATE())); } } -void GamePad::RefreshState() +void XInputManager::RefreshState() { for(DWORD i = 0; i < XUSER_MAX_COUNT; i++) { if(_gamePadStates[i] != nullptr) { ZeroMemory(_gamePadStates[i].get(), sizeof(XINPUT_STATE)); if(XInputGetState(i, _gamePadStates[i].get()) != ERROR_SUCCESS) { //XInputGetState is incredibly slow when no controller is plugged in - //TODO: Periodically detect if a controller has been plugged in to allow controllers to be plugged in after the emu is started _gamePadStates[i] = nullptr; } } } } -bool GamePad::IsPressed(uint8_t gamepadPort, uint8_t button) +void XInputManager::UpdateDeviceList() +{ + //Periodically detect if a controller has been plugged in to allow controllers to be plugged in after the emu is started + for(int i = 0; i < XUSER_MAX_COUNT; i++) { + if(_gamePadStates[i] == nullptr) { + _gamePadStates[i] = shared_ptr(new XINPUT_STATE()); + } + } +} + +bool XInputManager::IsPressed(uint8_t gamepadPort, uint8_t button) { if(_gamePadStates[gamepadPort] != nullptr) { XINPUT_GAMEPAD &gamepad = _gamePadStates[gamepadPort]->Gamepad; diff --git a/Windows/GamePad.h b/Windows/XInputManager.h similarity index 76% rename from Windows/GamePad.h rename to Windows/XInputManager.h index 63d83b95..3dff2fec 100644 --- a/Windows/GamePad.h +++ b/Windows/XInputManager.h @@ -3,14 +3,15 @@ #include "stdafx.h" #include -class GamePad +class XInputManager { private: vector> _gamePadStates; public: - GamePad(); + XInputManager(); + void UpdateDeviceList(); void RefreshState(); bool IsPressed(uint8_t gamepadPort, uint8_t button); };