zoukankan      html  css  js  c++  java
  • Windows RawInputPluginForUE4(2)

    知乎链接: 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方法内:
     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         }
    View Code
    • ProcessMessage方法内通过DeviceName进行多设备的区分:
     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                     }
    View Code
    • 其他细节请参考github上的代码(应该没什么了)
    • 因为要支持两个摇杆,所有我将aixs增加至了16个,button增加至了40个,后期如果需要,也可以修改为动态映射和动态识别设备,目前识别设备只能在启动ue4时识别。
    • 以上就是所有内容,祝大家工作愉快,Have Fun!!!
  • 相关阅读:
    Visual Studio统计有效代码行数
    Release 下调试代码设置 (VS2005/2008)(转)
    vs2008编译出来的程序不能运行或需要安装vcredist_x86.exe才能运行解决办法
    优化3D图形流水线
    (转)地形碰撞高度计算
    stlport调试watch查看容器里面的值
    JavaScript调试、测试和发布工具
    MYGUI/CEGUI中文输入的问题
    jar包的生成及运行
    安卓百度地图开发so文件引用失败问题研究
  • 原文地址:https://www.cnblogs.com/LynnVon/p/10302836.html
Copyright © 2011-2022 走看看