Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Binding to Primary Mouse button?

Discussion in 'Input System' started by Evyatron7, Dec 3, 2019.

  1. Evyatron7

    Evyatron7

    Joined:
    Mar 6, 2019
    Posts:
    18
    Hello,

    In the old Input System, using GetMouseButton(0) is checking the operating system's Primary button.
    However in the new System you can only bind actions to either Left or Right buttons - not Primary or Secondary.

    This means that if I use the mouse in my left hand, changing my Windows settings so my primary button is right one - the UI (and any other actions using the mouse) stops working.
    And testing Input.GetMouseButton(0) is called correctly according to whichever button I set as the primary one.

    Am I missing an obvious solution for this?
    In the Input System UI Input Module the Left Click is assigned the UI/Click action.
    The UI/Click action is bound to the Left Button [Mouse].
     
  2. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Heh, I seriously had to go check the source code for that as the docs don't mention it. And even in the code, I'm wondering whether it's just a side effect or was expressly done this way. But you're right, in the old system mouse input is picked up via two different code paths. Some from RawInput but most from WM_ messages which indeed flip the meaning of "left button" according to the system setting (as reflected by the test you've done).

    Unfortunately, no. It's missing on our side. I've made a note in the backlog (ISX-322).
     
  3. Evyatron7

    Evyatron7

    Joined:
    Mar 6, 2019
    Posts:
    18
    The docs actually mention this specifically:
    Code (CSharp):
    1. button values are 0 for the primary button (often the left button), 1 for secondary button, and 2 for the middle button.
    I also thought the docs might be wrong so had to actually write the code and change my Primary button on the fly to make sure it actually works :)

    Thanks for the reply! Is there a workaround you can think of? I thought about:
    1. Creating a Custom Device and setting its state with the old Input.GetMouseDown. This works, BUT apparently the InputSystemUIInputModule does not actually use the bound actions it seems.
    2. Changing InputSystemUIInputModule so when it sends the UI events it uses the old Input System behind the scenes. Looking specifically at InputSystemUIInputModule.ProcessMouse.

    Thanks again!
     
    Last edited: Dec 3, 2019
  4. Evyatron7

    Evyatron7

    Joined:
    Mar 6, 2019
    Posts:
    18
    I think the "right" approach (and by right I mean something I can do myself without digging too deep into the low-level code), is replace the Process Mouse functionality with something that reads the old Input data and constructs a pointer event data from that.

    Since I assume the old Input Module created the Pointer Event Data like that - is there a reference anywhere where I can see that code and copy just the relevant bit over?
     
  5. Evyatron7

    Evyatron7

    Joined:
    Mar 6, 2019
    Posts:
    18
    Hi @Rene-Damm

    Any chance of any follow-up on this?
    Not sure how long it would take the fix now it's in the backlog, but it would be great if you could point me in the right direction to fixing this locally, hacky or otherwise.

    Cheers
     
  6. Evyatron7

    Evyatron7

    Joined:
    Mar 6, 2019
    Posts:
    18
    Bumping this after two months, seeing a new version of the Input System was released but this hasn't been addressed.

    Would really appreciate any kind of help how to circumvent this locally in my project instead of waiting for the powers that be to fix it!
     
  7. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Sorry for the lack of (good) news.

    My suggested workaround would be to PInvoke into the Win32 API to find the setting and then alter the binding in the UI input module accordingly. The module does pick up input entirely through actions so depending on what you read out from the system setting, you could swap the left and right click action on the fly.
     
  8. Evyatron7

    Evyatron7

    Joined:
    Mar 6, 2019
    Posts:
    18
    Thanks for the reply!
    Out of interest - is that how the old input system does that when doing GetMouseButton(0)?
    If so, any chance you could share the relevant code here?
     
  9. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    The old one picks up mouse buttons from WM_ messages and thus implicitly gets the mapping.
     
  10. Evyatron7

    Evyatron7

    Joined:
    Mar 6, 2019
    Posts:
    18
    Right, so if I wanted to use that it would essentially be creating a "new" mouse input with new controls and invoking them myself I suppose?
    A bit more than I had hoped!

    Is there any info you can share about priority on your end? Is the issue small and will likely be fixed in any upcoming versions? Or is it too much of a pain and will likely not get fixed, in which case I should solve it on my own anyway?

    Thanks!
     
  11. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Luckily, it's simpler than that. Basically like this (typing this out on the fly in a chat box so no guarantees this even compiles :)).

    Code (CSharp):
    1. public class MyWin32ButtonSwapFixer : MonoBehaviour
    2. {
    3. #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
    4.     [DllImport("User32.dll")]
    5.     private static int GetSystemMetrics(int);
    6.  
    7.     public void OnEnable()
    8.     {
    9.         // Determine if button is swapped.
    10.         if (GetSystemMetrics(23) == 0) // 23 is SM_SWAPBUTTON
    11.             return; // No.
    12.  
    13.         // Override left button bindings to refer to right button and vice versa.
    14.         var playerInput = GetComponent<PlayerInput>();
    15.         var actions = playerInput.actions;
    16.         foreach (var map in actions.actionMaps)
    17.         {
    18.             var bindings = map.bindings;
    19.             for (var i = 0; i < bindingsCount; ++i)
    20.                 if (bindings[i].effectivePath == "<Mouse>/leftButton";
    21.                     map.ApplyBindingOverride(i, new InputBinding { overridePath = "<Mouse>/rightButton" });
    22.                 else if (bindings[i].effectivePath == "<Mouse>/rightButton";
    23.                     map.ApplyBindingOverride(i, new InputBinding { overridePath = "<Mouse>/leftButton" });
    24.         }
    25.     }
    26. #endif
    27. }
    The effect could be applied may different ways (different control schemes, switch statement if polling devices directly, swapping path strings from Mouse.current["leftButton"] to Mouse.current["rightButton"], etc).

    It's a small change. Unfortunately it's one in the native backend so makes this a bit more painful. It'll get fixed but not for 1.0.

    To apply some extra pressure, feel free to file a bug report in case you haven't already :)
     
    Last edited: Feb 13, 2020
    MaZy and kulesz like this.
  12. Evyatron7

    Evyatron7

    Joined:
    Mar 6, 2019
    Posts:
    18
    Perfect, this is working flawlessly - thank you so much!
    I'll put in a bug report as well :)

    Thanks again!
     
  13. kulesz

    kulesz

    Joined:
    Jul 1, 2012
    Posts:
    137
    @Rene-Damm
    Was it changed somehow since that time?
    I'm on Input System 1.3.0 and the issue still occurs - Input System seems to ignore system settings.

    Is there any way to change/alter this behavior or do I still need to read system settings manually (and swap buttons by myself somewhere during input processing)?
     
    pawelduda and bk_mechanistry like this.
  14. ChristopherKroll

    ChristopherKroll

    Joined:
    Feb 12, 2015
    Posts:
    7
    @Rene-Damm @kulesz
    I am having the same problem with Input System 1.3.0. I tried the workaround posted above and I can't get it to work.
     
  15. ChristopherKroll

    ChristopherKroll

    Joined:
    Feb 12, 2015
    Posts:
    7
    pawelduda likes this.
  16. unity_t81ob4qZliI4nQ

    unity_t81ob4qZliI4nQ

    Joined:
    Jul 4, 2020
    Posts:
    1
  17. MaZy

    MaZy

    Joined:
    Jun 29, 2012
    Posts:
    100
    Last edited: Apr 20, 2023