Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Overrriding HID Device Layout Matching

Discussion in 'Input System' started by james7132, Aug 1, 2018.

  1. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    I've got a input device that is detected properly by the Input System, but is not structured the correct way for it to be seen as a Gamepad. However, as it is detected, a separate HID layout is added, and the device is matched against it instead of the custom control layout I specify, no matter how specific I make the InputDeviceMatcher.

    The MatchPercentage for both profiles seems to be the same at 1.0, is there a way to have it favor user created layouts?

    Side note: from the Input Debugger, the Dpad on this controller seems to use a enum for it's state instead of a bit per individual Dpad button. What would implementing it correctly entail?
     
  2. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    Found the cause: due to how MatchPercentage and HID generated control layouts are created, it is currently impossible to create an override. The HID generated control layouts always has a 100% match, and is seemingly loaded before any overrides are. This causes TryFindMatchingLayout to always choose the HID generated layout over the override.

    I do see that in InputManager.TryFindMatchingControlLayout, there is a TODO to support this use case. Is this planned to be implemented in the near future?

    A quick and dirty workaround would be to change the > in TryFindMatchingLayout to >=, to take the last listed layout instead of the first, though that might not be preferable for other reasons. EDIT: This also doesn't seem to work.

    Filed a GitHub issue for this: https://github.com/Unity-Technologies/InputSystem/issues/193
     
    Last edited: Aug 1, 2018
  3. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Is this with a specific gamepad you want to support or with HID gamepads in general?

    The idea with the HID layout generation code is that it will only kick in if the system has no existing layout matching the device. For example, the DualShockGamepadHID layout matches a DualShock controller HID and prevents the HID layout generation from doing anything with the device.

    So, if it is about supporting a specific gamepad, the way to override HID layout generation would be to simply register a layout specifically for your device.

    Caveat: ATM the way the system takes itself across domain reloads (i.e. script recompilation and entering play mode) means that it may not pick up this change except if Unity is restarted. I.e. the device will continue to use the layout it had before the reload rather than changing to your newly registered layout. Something that we need to fix.

    As for tweaking the layout matching system such that overriding works better (the generated HID layouts should probably always get pretty low-scores; I'm toying with the idea of marking certain layouts explicitly as fallbacks and giving every layout that isn't one a constant boost to its score; something like that), that's definitely a TODO still.

    Also, we need to decide what to do with gamepads in the HID layout generator. HID joysticks we will probably end up into proper joysticks by extending the Joystick layout. Gamepads are a little trickier as they have more controls and we can't really guarantee that based on an arbitrary HID gamepad, we manage to figure out the individual controls correctly. Might be they should end up being joysticks, too. Or we do generate a Gamepad layout and just live with the fact that 5 times out of 10, we generate a Gamepad that works only partially. Not sure.

    The HID layout generation code should now support this. It may not set things up correctly for all possible hat switch configurations, though.

    To see how to set up an enum dpad in a layout, check out the "dpad" setup in DualShockHIDInputReport. It requires hooking up individual DiscreteButtons for each direction that all share the same state but act on different values.

    Code (CSharp):
    1.  
    2.         [InputControl(name = "dpad", format = "BIT", layout = "Dpad", sizeInBits = 4, defaultState = 8)]
    3.         [InputControl(name = "dpad/up", format = "BIT", layout = "DiscreteButton", parameters = "minValue=7,maxValue=1,nullValue=8,wrapAtValue=7", bit = 0, sizeInBits = 4)]
    4.         [InputControl(name = "dpad/right", format = "BIT", layout = "DiscreteButton", parameters = "minValue=1,maxValue=3", bit = 0, sizeInBits = 4)]
    5.         [InputControl(name = "dpad/down", format = "BIT", layout = "DiscreteButton", parameters = "minValue=3,maxValue=5", bit = 0, sizeInBits = 4)]
    6.         [InputControl(name = "dpad/left", format = "BIT", layout = "DiscreteButton", parameters = "minValue=5, maxValue=7", bit = 0, sizeInBits = 4)]
    7.  
    8.  
    So, it's four bits shared by all the dpad children. Up is 7,0,1 (8 is null state). Right is 1,2,3. Down is 3,4,5. Left is 5,6,7.
     
    Last edited: Aug 1, 2018
  4. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    This is specifically for the MAYFLASH GameCube Controller Adapter. The players for my project seem to really want support for GameCube controllers.

    That's the thing I hadn't tried. I was under the impression that it would be simply be added and take over where possible. Perhaps a check post-domain reload to decimate HID layouts and rerun those checks is a valid solution? Currently cannot check if this produces a valid result, will report back later when I have time to experiment with this.

    Alright, I'll check it out! Thanks.

    Tangentially related: is there any future plans to support community contribution for control layouts? Perhaps by GitHub PR or something similar. There doesn't seem to be a contributor agreement or license in the repo, so I'm not sure what the situation regarding that is.

    The idea that the control layouts can be described easily from JSON seems to suggest that it should also be possible to serve them via some remote service, as a fallback between explicitly created layouts built into the system and relegating to auto-generated layouts via processes like HID.
     
    Last edited: Aug 1, 2018
  5. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    I've pushed two changes that should resolve the issue (see here and here).

    We may still need to tweak what happens during domain reload but the mechanism should now (hopefully) always end up finding the best match in the end.

    Hopefully that's what's happening now :)

    We'll probably have to make a number of tweaks to the domain reload logic. Amongst other things, it's way too slow (200ms in my test project). With the RegisterControlLayout() changes above, it should however arrive at the right solution now eventually.

    We're still figuring that one out.

    I'm concerned about adding device support directly to the main package if we can't guarantee QA for it -- a resource that has decidedly finite limits. Once we're out of preview, for devices that have support directly in the main package, I'd really like to give a hard guarantee of "this works; wherever it happens not to, we'll jump on it".

    However, at the same time I think we absolutely should source and collect control layouts created by users. So maybe the solution is to create a separate package containing 3rd party layouts we can't QA ourselves and to promote whatever we can QA from the separate package to the main one.

    Just thoughts at this point.

    If you want to create a PR adding a new device (with tests, of course :)), you're absolutely welcome to. It'll force us to make a decision on this. Which is a good thing IMO.

    Yup, exactly. The idea is to eventually be able to provision shipped games with support for new devices that didn't even exist when the game went final. It's a multi-front effort but being able to wire up a new device entirely in JSON is definitely part of it.