知乎链接: https://zhuanlan.zhihu.com/p/55437022
Github: https://github.com/Lynnvon/RawInputPluginForUE4
- 第一章主要解决了HIDStatusBufferTooSmall的错误和增加axis与button数量的问题,这篇文章主要解决原生插件不支持多设备的问题。
- 通过阅读原生插件源代码,发现原插件在注册HID设备时,只注册找到的第一个设备,如果你只有一个USB 设备,那没有任何问题,但当你的设备为2个甚至更多时,原插件是没有注册后边的设备的,这导致了当你的设备多于1个时,多个设备的数据相互混合了(虽然没有注册设备,但获取获取并没有区分是否注册,而是获取所有设备的数据),完全无法使用。
- 那思路就很简单了,只需要在RawInputWindows.cpp的RegisterInputDevice方法内修改为注册全部设备,然后在ProcessMessage方法内进行DeviceName比对,就可以区分开不同设备的数据。
- RegisterInputDevice方法内:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 QueryConnectedDevices(); 2 // If this doesn't already exist in our internal list add it 3 DeviceHandle = FindRegisteredDeviceHandle(DeviceData); 4 if (DeviceHandle == INDEX_NONE) 5 { 6 /* 7 DeviceHandle = GetNextInputHandle(); 8 9 //只在此处设置RegisteredDeviceList的值 10 RegisteredDeviceList.Add(DeviceHandle, DeviceData); 11 // Now see if the device is connected 12 */ 13 bool bWasConnected = false; 14 for (const FConnectedDeviceInfo &ConnectedDeviceInfo : ConnectedDeviceInfoList) 15 { 16 17 if (CompareDeviceInfo(ConnectedDeviceInfo.RIDDeviceInfo, DeviceData)) 18 { 19 20 DeviceHandle = GetNextInputHandle(); 21 22 //只在此处设置RegisteredDeviceList的值 23 RegisteredDeviceList.Add(DeviceHandle, DeviceData); 24 // Now see if the device is connected 25 bWasConnected = false; 26 27 FRawWindowsDeviceEntry &RegisteredDeviceInfo = RegisteredDeviceList[DeviceHandle]; 28 RegisteredDeviceInfo.bIsConnected = true; 29 RegisteredDeviceInfo.DeviceData.DeviceName = ConnectedDeviceInfo.DeviceName; 30 31 if (DeviceData.DeviceType == RIM_TYPEHID) 32 { 33 RegisteredDeviceInfo.DeviceData.VendorID = ConnectedDeviceInfo.RIDDeviceInfo.hid.dwVendorId; 34 RegisteredDeviceInfo.DeviceData.ProductID = ConnectedDeviceInfo.RIDDeviceInfo.hid.dwProductId; 35 } 36 37 UE_LOG(LogRawInputWindows, Log, TEXT("VenderID:%x ProductID:%x"), RegisteredDeviceInfo.DeviceData.VendorID, RegisteredDeviceInfo.DeviceData.ProductID); 38 39 bWasConnected = true; 40 41 //break; 42 if (bWasConnected) 43 { 44 SetupBindings(DeviceHandle, true); 45 46 UE_LOG(LogRawInputWindows, Log, TEXT("Device was registered succesfully and is connected (Usage:%d UsagePage:%d)"), DeviceData.Usage, DeviceData.UsagePage); 47 } 48 else 49 { 50 DeviceHandle = INDEX_NONE; 51 UE_LOG(LogRawInputWindows, Warning, TEXT("Device was registered succesfully but not connected (Usage:%d UsagePage:%d)"), DeviceData.Usage, DeviceData.UsagePage); 52 } 53 } 54 } 55 }
- ProcessMessage方法内通过DeviceName进行多设备的区分:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 if (RawInputDataBuffer->header.dwType == RIM_TYPEHID) 2 { 3 // First we need to get the pre-parsed data 4 uint32 BufferSize; 5 6 uint32 NameLen = 0; 7 8 //Force the use of ANSI versions of these calls 9 //先获取当前hid设备的名称,然后做比对,避免多个设备之间互相干扰 10 if (GetRawInputDeviceInfoA(RawInputDataBuffer->header.hDevice, RIDI_DEVICENAME, nullptr, &NameLen) != RAW_INPUT_ERROR) 11 { 12 DeviceNameBuffer.SetNumUninitialized(NameLen + 1, false); 13 14 if (GetRawInputDeviceInfoA(RawInputDataBuffer->header.hDevice, RIDI_DEVICENAME, DeviceNameBuffer.GetData(), &NameLen) != RAW_INPUT_ERROR) 15 { 16 DeviceNameBuffer[NameLen] = 0; 17 FString DeviceName = ANSI_TO_TCHAR(DeviceNameBuffer.GetData()); 18 DeviceName.ReplaceInline(TEXT("#"), TEXT("\\"), ESearchCase::CaseSensitive); 19 20 if (::GetRawInputDeviceInfo(RawInputDataBuffer->header.hDevice, RIDI_PREPARSEDDATA, nullptr, &BufferSize) != RAW_INPUT_ERROR) 21 { 22 PreParsedData.SetNumUninitialized(BufferSize + 1, false); 23 24 if (::GetRawInputDeviceInfo(RawInputDataBuffer->header.hDevice, RIDI_PREPARSEDDATA, PreParsedData.GetData(), &BufferSize) != RAW_INPUT_ERROR) 25 { 26 HIDP_CAPS Caps; 27 28 // now that we have the PP data we need to get the caps, check those and see if this is a device we registered and if it is store it so we can send it 29 if (DLLPointers.HidP_GetCaps((PHIDP_PREPARSED_DATA)PreParsedData.GetData(), &Caps) == HIDP_STATUS_SUCCESS) 30 { 31 32 FRawInputRegisteredDevice DeviceData(RawInputDataBuffer->header.dwType, Caps.Usage, Caps.UsagePage); 33 34 // Win32 doesn't correctly report the device ID, so at least for now just trust it is from the device we want 35 //if (DeviceData == EachEntry.DeviceData) 36 //很重要,需要先比对设备,再解析数据,否则多个hid设备时会数据混乱 37 if(DeviceName == EachEntry.DeviceData.DeviceName) 38 { 39 bIsRegisteredDevice = true; 40 ParseInputData(DeviceEntryPair.Key, RawInputDataBuffer, (PHIDP_PREPARSED_DATA)PreParsedData.GetData(), Caps); 41 } 42 } 43 } 44 } 45 } 46 } 47 48 }
- 其他细节请参考github上的代码(应该没什么了)
- 因为要支持两个摇杆,所有我将aixs增加至了16个,button增加至了40个,后期如果需要,也可以修改为动态映射和动态识别设备,目前识别设备只能在启动ue4时识别。
- 以上就是所有内容,祝大家工作愉快,Have Fun!!!