Search Unity

Rewired - Advanced Input for Unity

Discussion in 'Assets and Asset Store' started by guavaman, Sep 25, 2014.

  1. longroadhwy

    longroadhwy

    Joined:
    May 4, 2014
    Posts:
    1,551
    What version of Rewired are you using? Hopefully the latest version in the asset store which is 1.1.3.0.
    What platform are you running on?

    I believe these sections from the Rewired documentation will help.

    http://guavaman.com/projects/rewired/docs/HowTos.html#get-contributing-input-sources

    http://guavaman.com/projects/rewired/docs/HowTos.html#last-used-controller
     
    guavaman likes this.
  2. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
  3. Morchen

    Morchen

    Joined:
    May 19, 2016
    Posts:
    8
    Hey, i'm currently trying the trial and try to get my camera working through mouse movement.
    When i set the Element in my mouse maps i get this error:

    Unity: 2017.1.0b10 (.Net 4.5)
    Rewired: 1.1.2.0.U5 (Downloaded on Sunday)

    Some idea what might be wrong? I hesitate to buy the asset because of this error. :/ Everything else was very good so far.
     
  4. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Unity 2017 is not supported as it's a beta and not finalized. Nothing has been tested in Unity 2017. And you are also using .Net 4.5 which has not been tested.

    The code that is choking is this:
    Code (csharp):
    1. Type unityMouseSource = Type.GetType(Consts.defaultNamespace + ".UnityUnifiedMouseSource, Rewired_Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", true);
    2. object elementTypeObj = unityMouseSource.InvokeMember("GetHardwareElementType", BindingFlags.InvokeMethod | BindingFlags.Static, null, null, new object[] { actionMap.elementIdentifierId } );
    The editor uses reflection to invoke a static method on a class. This works 100% in all versions of Unity 4 and Unity 5. Clearly something has changed in .Net 4.5 that is preventing this InvokeMember method from working. I will have to determine why this simple reflection call does not function under the .NET 4.5 runtime.

    When Unity 2017 is supported, there will be a separate download for this. Your version is 1.1.2.0.U5. The release would say 1.1.2.0.U2017. This will be submitted separately to the Unity Asset Store just like Unity 4 and Unity 5 are submitted separately. The trial page will offer a Unity 4, Unity 5, and Unity 2017 download.

    Unity major releases break things. They defer deprecations, removal of deprecated API members, and major core changes such as the .NET runtime to major updates with the expectation that developers update their projects carefully and specifically for these major releases. Unity's Asset Store allows separate uploads for the different major versions of Unity because of this. That process of removing all references to deprecated things and validation on the new systems still needs to be done for Rewired.
     
    Last edited: Jun 21, 2017
    Morchen likes this.
  5. Morchen

    Morchen

    Joined:
    May 19, 2016
    Posts:
    8
    Thank you couldn't find anywhere weather work had already been done to support Beta 2017 or not. I will wait for the 2017 release than.

    Thanks for the quick answer and good work so far. Everything i could use worked perfectly and the documentation is flawless. :)
     
  6. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    It works fine with 2017.1 b10 (latest)? edit: I see, I'm only using joystick and keyboard maps.
     
  7. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Thanks!

    I can confirm this bug does occur in 2017.1 b10, but only when the Scripting Runtime Version is set to Experimental (.NET 4.6 Equivalent)
     
  8. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    I found the reason:

    The binding flags passed to InvokeMember was missing the BindingFlags.Public flag.

    Code (csharp):
    1. Type unityMouseSource = Type.GetType(Consts.defaultNamespace + ".UnityUnifiedMouseSource, Rewired_Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", true);
    2. object elementTypeObj = unityMouseSource.InvokeMember("GetHardwareElementType", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, new object[] { actionMap.elementIdentifierId } );
     
    Last edited: Jun 21, 2017
  9. Morchen

    Morchen

    Joined:
    May 19, 2016
    Posts:
    8
    Well at least it helped that i tried it. ;) good work!
     
  10. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Indeed. Thanks! I should have the Unity 2017 version ready by the time it's out of beta.
     
  11. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    @Morchen It looks like there are some other very serious problems with using the Experimental .Net 4.6 scripting backend.

    Creating an empty scene with a new but blank Rewired Input Manager and running it twice in succession in the editor causes a series of exceptions that ultimately break Unity until you quit and restart the editor:

    999+ errors are reported in the console:
    These missing methods/classes referenced in the errors are part of Mono, not Rewired.

    All MonoBehaviour inspectors are permanently broken and the message displayed:
    The referenced script on this Behaviour is missing!

    Every time you enter Play mode from that point on even in a completely empty scene the same 999+ errors appear in the console.

    It looks like the feature is labeled "Experimental" for a reason. Due to these issues, Rewired will not be supporting this experimental .Net back end on the first Unity 2017 release. It's been my policy to not support beta releases because of errors like this that are ultimately fixed by the final release because the process of discovering issues and finding workarounds for bugs is extremely time consuming and clutters up the code with special cases.
     
    Last edited: Jun 21, 2017
    TeagansDad likes this.
  12. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    I've boiled this issue down to a very specific structure and sequence of events involving dynamically loading an assembly which contains a class that inherits from another assembly that is already loaded by Unity and getting that class type by reflection. In short, it appears that Mono is forcibly unloading the dependency assembly when the dynamically loaded assembly is unloaded. This causes Unity to choke and throw exceptions everywhere because, in the case of Rewired, the Rewired_Core assembly is forcibly unloaded and that assembly contains MonoBehaviors and ScriptableObjects and is required by the editor scripts and Rewired editor assembly. I've recreated the issue in a very simple project and filed it as a bug report to Unity.

    Thus far, apart from a deprecated API warning on the editor assembly, Rewired looks to work just fine in Unity 2017.1 b10 as long as you are using the .Net 3.5 scripting backend.
     
    Morchen likes this.
  13. KJoanette

    KJoanette

    Joined:
    Jun 8, 2013
    Posts:
    59
    I'm having a strange issue:

    I'm trying to add a CustomController (I have previously added one) but the editor for it is not showing the data for naming Axes/Buttons at all. When I add an Axis or button the editor that is supposed to show up to the right of the list is missing.

    As a note: I am using Unity 5.6.1p3

    EDIT: NVM I see there is an update with this fix mentioned.
     
  14. Steve-Tack

    Steve-Tack

    Joined:
    Mar 12, 2013
    Posts:
    1,240
    Hi, I'm curious about methods like GetButtonLongPress and GetButtonShortPress.

    I have a slightly strange scenario where I want to increment/decrement a value in my game by 1 when the D-Pad up/down (or arrow keys or hat switch) is tapped, but set the value to min or max when held down.

    I've got something working that I'm basically happy with using a combination of GetButtonDown, GetButtonUp, and GetButton using a timer and a flag for each direction.

    The only down side is that when doing single increments or decrements, it doesn't feel 100% as responsive as everything else I'm doing with just GetButtonDown. The single "tap" value changes don't kick in until the button is released. I don't know if there's logically a way around that.

    Basically I'm considering it a "tap" if the button is released in less than 0.7 seconds. If the button is held down longer than that, it's a "hold."

    So I'm curious if methods like GetButtonLongPress or anything else in Rewired would make this any cleaner the next time I run into something like this. I played with them some, but when you're checking the same button for a tap or a hold, it gets interesting.

    Here's what I ended up doing. _holdDownTime is 0.7.

    Code (csharp):
    1.  
    2.                 if (rewired.GetButtonDown(ActionId.Select_Hardpoint_U))
    3.                 {
    4.                     // Reset the timer on ButtonDown and start counting the time the button is held down
    5.                     _holdPowerIncTimer = 0;
    6.                     _holdPowerIncPending = true;
    7.                 }
    8.                 else if (_holdPowerIncPending &&
    9.                     rewired.GetButtonUp(ActionId.Select_Hardpoint_U) &&
    10.                     (_holdPowerIncTimer < _holdDownTime))
    11.                 {
    12.                     // The button was released when held down less than 0.7 seconds
    13.  
    14.                     // Do the "tap" thing here...
    15.  
    16.                     // Reset the pending button press
    17.                     _holdPowerIncPending = false;
    18.                 }
    19.  
    20.                 if (_holdPowerIncPending && rewired.GetButton(ActionId.Select_Hardpoint_U))
    21.                 {
    22.                     // Increment the timer as long as the button is held down
    23.                     _holdPowerIncTimer += Time.deltaTime;
    24.  
    25.                     // If the button has been held >= 0.7 seconds, MAX the value and reset the timer
    26.                     if (_holdPowerIncTimer >= _holdDownTime)
    27.                     {
    28.                         // Do the "hold down" thing here...
    29.  
    30.                         // Reset the pending button press
    31.                         _holdPowerIncPending = false;
    32.                     }
    33.                 }
    34.  
     
  15. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    If I'm understanding your use case, it seems to me the most responsive way to handle this would be to:
    1) On GetButtonDown, increment your value by +/- 1.
    2) On GetButtonShortPressDown, set your value to min/max.

    This way, it feels more responsive because you are instantly incrementing, but when they hold it a little longer it maxes out. I'm not sure if that's unacceptable because it increments before maxing or not. It would feel something like a key repeat delay.

    The short press duration can be set in the Input Behavior.
     
    Last edited: Jun 23, 2017
  16. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    @Steve-Tack You could also use the Player.GetButtonTimePressed to determine how long it's been held down. Unfortunately this doesn't help when the button is just released because it's instantly cleared to zero. If you recorded the previous frame's time pressed, you could easily make comparisons and do it more cleanly:

    Code (csharp):
    1. float timePressedPrev;
    2.  
    3. void Update() {
    4.     Player player = ReInput.players.GetPlayer(0);
    5.  
    6.     float timePressed = player.GetButtonTimePressed("SomeAction");
    7.  
    8.     if(player.GetButtonUp("SomeAction") && timePressedPrev < 0.7f) {
    9.         // increment
    10.     } else if(player.GetButton("SomeAction") && timePressed >= 0.7f) {
    11.         // max out
    12.     }
    13.  
    14.     timePressedPrev = timePressed;
    15. }
    You could also use player.GetButtonShort/LongPressDown instead of GetButton and the time comparison, but it doesn't shorten the code any since you're already having to get the timePressed value to store the prev value.

    I don't think using a short press + long press would help much here since it will have the potential to miss instant taps < 0.01 seconds (the min duration for a short press).

    If I stored the timePressedPrev and exposed that it would prevent you from having to store the value manually. Or if I made short press allow a min duration of 0 you could use a short and long press check together with expires in. Without one or the other change, I don't think you could make the code any cleaner.
     
  17. rxmarccall

    rxmarccall

    Joined:
    Oct 13, 2011
    Posts:
    353
    @guavaman
    So I'm surprised no one else has posted about this (must be my fault?)... but I've been having an issue ever since i updated Rewired at the end of May. Basically it is no longer dynamically handling controllers being connected while the game is running. In the past on V1.0.0.106.U5 A player could have controllers on before launching the game, or turn them on and have them connect while the game is running and my game would see them and respond correctly. With the update in V1.1.2.0 I have to restart my game completely if someone tries to connect a controller while the game is running as it won't recognize or handle the newly connected controller.

    I suppose it's possible I broke something but this is behavior I've noticed since the commit when I updated. I also just tried updated to the June 13th update and it still has the issue.

    I have auto-assign joysticks enabled, distribute joysticks evenly enabled and reassign joystick to previous owner enabled. (as i have in the past)

    Is there anything you can think of that might be wrong? Or anything that I might have mistakenly done when updating to cause this broken behavior?
     
  18. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    There are no scenarios that I know of where this is possible on any platform.

    On Windows, Raw Input, Direct Input, and XInput, connection events are received from Windows directly which triggers Rewired to poll the devices and proceed to add and remove connections. There is nothing I have ever encountered or heard of that can break this unless Windows itself is not sending the messages to the window. Nothing in any Rewired update has ever changed this behavior.
    1. Can you reproduce it in the editor?
    2. Can you reproduce it in a build? 32/64 bit?
    3. Can you reproduce it on a different computer?
    4. Can you reproduce it using different controllers?
    5. Can you reproduce it using a new project and a clean install of Rewired? Eight Player demo is a good test.
    6. What is your Max Joysticks Per Player setting?
    7. Have you installed any Unity plugins that may hook or change the window handle? Anything that uses with Direct Input or similar.
    8. Have you recently enabled VR support in Unity?
    9. What other things have changed since then? Did you do a major Windows update? (Creators edition) Did you install some new driver or device mapping program?
    10. Have you installed an external program that may modify window handles and/or intercept messages such as a window video recorder?
    11. Is Steam involved and has the client been updated recently?
     
    Last edited: Jun 23, 2017
  19. Steve-Tack

    Steve-Tack

    Joined:
    Mar 12, 2013
    Posts:
    1,240
    @guavaman, thanks for the reply!!!

    Yeah, I initially had GetButtonDown go ahead and apply the + or - instantly, and then apply the min or max after it was held down longer, but it didn't mesh well with what happens when you min or max a value (a very game-specific thing). Before that I played with double-tapping vs single-tapping, but I found that trying to detect the difference between sequential single taps and double-taps to be problematic. The "hold down" approach felt better during gameplay anyway.

    I think it's one of those things where there's no perfect answer, but not a big deal given how very specific it is. More than once, there's been a Rewired feature that I didn't know about or wasn't using optimally, so I mostly just wanted a reality check. Which I got. :D
     
  20. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    For the most effortless user implementation, a GetButtonTapped would be the solution.

    With the silly number of convenience methods in most classes, I can understand how one might expect there would be some obscure method somewhere for every use, but not in this case.
     
  21. rxmarccall

    rxmarccall

    Joined:
    Oct 13, 2011
    Posts:
    353
    @guavaman
    Allllright. I didn't realize that when I would do the following on my Character Select screen:
    Code (CSharp):
    1.  
    2. foreach (var player in ReInput.players.Players)
    3.         {
    4.             player.controllers.maps.SetMapsEnabled(true, "PlayerAssignment");
    5. }
    6.  
    That this only affects currently active / connected controllers on a player. As such, when a new controller then was connected after this code has run, then my "PlayerAssignment" map was defaulted to false. (Which is how I had it in my Player Input Manager).

    oops! Sorry and thank you for the quick response
     
  22. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Oh yeah, that one catches a lot of people. Everyone assumes SetMapsEnabled is a persistent flag in the Player. I've tried to make this clear in the documentation by noting it in 3 separate places, but people still miss it. I recently added the explanation to every single method overload and variant in the XML documentation in the last update to hopefully get the message across more clearly.

    These SetMapsEnabled methods are convenience methods that were added quite a while after the initial Rewired release so you wouldn't have to iterate the Controller Maps. Another thing that people assume is a persistent flag also is loading something in a Layout.

    I'm glad it's resolved.

    Enabling and disabling Controller Maps

    NOTE: The above SetMapsEnabled and SetAllMapsEnabled methods are not persistent flags in Player that will set a certain category of map enabled/disabled upon loading. They are simply shortcuts for the below methods that iterate the maps currently loaded in the Player and set them enabled/disabled at the time the method is called. When new Controller Maps are loaded in the Player, either manually or when a Joystick is assigned, the newly loaded maps will be enabled/disabled based on the default enabled state settings for these maps on the Player page in the Rewired Input Manager, not based on previous calls to SetMapsEnabled.
     
    rxmarccall likes this.
  23. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    @rxmarccall

    I should add that when a joystick is disconnected and reconnected to the same Player, the last maps are re-used so you don't have the controller maps going back to their defaults in this scenario. What was enabled before the disconnection is enabled after reconnecting, or if you've removed or loaded maps, that will persist for the lifetime of the Rewired Input Manager.
     
    rxmarccall likes this.
  24. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    @Steve-Tack I've decided to change the GetButtonTimedPress and GetButtonTimedPressUp (and short/long/negative variants) to accept a time value of 0. This way you can use the expires in property to achieve what you want:

    Code (csharp):
    1. if(player.GetButtonTimedPressUp("Action", 0f, 0.7f)) { // button must be released in 0.7 seconds or less
    2.     // Do tap
    3. } else if(player.GetButtonTimedPressDown("Action", 0.7f)) { // button must be pressed 0.7 seconds or longer
    4.     // Do press
    5. }
    You could do the same using ShortPressUp and LongPressDown.

    You can actually do this now without any code changes, but only if you specify a tiny time value in GetButtonTimedPressUp like 0.00001f. It will always return true on up if you send 0 currently regardless of the expires in. You also cannot set the values in short/long press to < 0.01 in the editor currently. With the change, there won't ever be any chance of missing an extremely fast tap. Of course, with a value of 0.00001f, the only way you could miss it is if your game is running > 100,000 fps. :D
     
    Last edited: Jun 24, 2017
    Steve-Tack likes this.
  25. Steve-Tack

    Steve-Tack

    Joined:
    Mar 12, 2013
    Posts:
    1,240
    Very cool!!! That would make my code cleaner (and I'm doing it for two different controls, which makes it, well, twice as ugly).


    I'm not quite that optimized yet. :p
     
    guavaman likes this.
  26. longroadhwy

    longroadhwy

    Joined:
    May 4, 2014
    Posts:
    1,551
    @Steve-Tack idea is interesting. I was thinking something like this could be used on HOTAS systems to emulate a two stage trigger. For flight controllers that do not have a two stage trigger in hardware like ThrustMaster's Warthog.
     
  27. mmalavasi

    mmalavasi

    Joined:
    Jun 21, 2017
    Posts:
    13
    @guavaman
    Hi, I hope this question hasn't already been asked... I'm trying to show the icon of the buttons available in a menu, so that if for instance A is mapped to the action Purchase and you change map so that B is now mapped to Purchase, it will show you the icon of B. For this I need a list of all the button names that Rewired has, so that in the menu when I say "Display the icon for the action Purchase", rewired gives me B and I, somewhere, have a kind of dictionary which says "For B the icon is B.ico". So how do I get all the button names that Rewired has, in order to fill the dictionary with <ButtonName, Icon>? Thanks!
     
  28. longroadhwy

    longroadhwy

    Joined:
    May 4, 2014
    Posts:
    1,551
    This is what I see in the documentation which sounds like what you are looking for.

    http://guavaman.com/projects/rewired/docs/HowTos.html#display-glyph-for-action

    http://guavaman.com/projects/rewired/docs/HowTos.html#display-glyph-for-active-elements
     
    guavaman and mmalavasi like this.
  29. mmalavasi

    mmalavasi

    Joined:
    Jun 21, 2017
    Posts:
    13
  30. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
  31. idunbardev

    idunbardev

    Joined:
    Dec 23, 2013
    Posts:
    1
    @guavaman
    Hello! I am in the process of evaluating Rewired for use in my project and my main question is in relation to defining actions at runtime. Modding is going to be a very important aspect of the game and I foresee modders wishing to add their own actions. Essentially my question is, can I create and map actions without using the editor gui?
     
  32. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Hi,

    No, Rewired does not support modifying the Action, Action Category, Controller Map, Input Behavior, Custom Controller, or Player lists at runtime. You can modify data in the game-side maps during runtime, but you cannot modify the contents of the Rewired Input Manager serialized data. All objects are instantiated at runtime from the serialized data and are fixed throughout the game session. Any hacked modifications such as changing things through undocumented methods and/or reflection would require the entire system to be shut down and restarted in order for the changes to take effect. Rewired is probably not the right tool for your game.
     
  33. mmalavasi

    mmalavasi

    Joined:
    Jun 21, 2017
    Posts:
    13
    @guavaman
    Hi,
    Sorry but I can't find a way to get all the buttons mapped to a certain action if the controller is not plugged in... I need to display all the available buttons in a screen which is active also when no controller is plugged.
    Since we are here, what is the correct way to get an action name given an elementIdentifierId? I wasn't able to find anything with that.
    Many thanks
     
  34. longroadhwy

    longroadhwy

    Joined:
    May 4, 2014
    Posts:
    1,551
    (1) Is your game single player or multi-player?

    (2) Are you using the Rewired controller templates or mapping individual controllers?

    (3) Display all buttons for all controllers that are not plugged in correct?

    Based on the supported controller list that is going to be a very large list of buttons.

    http://guavaman.com/projects/rewired/docs/SupportedControllers.html

    Most of the flight controllers have a minimum of 20+ buttons per controller. For example I will use these 5 flight controllers Saitek X-55, Saitek X-56, CH FighterStick, ThrustMaster Warthog, and Gladiator MKII. Some of these controllers are technically two usb devices. So this is probably closer to 200 buttons is a low estimate when we factor in multiple usb devices. That is only from 5 flight controllers.

    Then add all of the flight controllers, all of the racing wheels, all of the gamepads, and all of the specialty controllers and that is a huge number of buttons. Your customers are going to be doing a large amount of scrolling to list all of those buttons. Is that what you are expecting for your game.

    Since my game is Flight Simulation oriented so I always like lots of buttons to configure. Just thinking of 10,000 buttons to configure sounds exciting to me.

    (4) Element mapped to Action.

    From the Rewired documentation I believe you are looking for this.

    http://guavaman.com/projects/rewire...lerHelper_MapHelper_ElementMapsWithAction.htm
     
    mmalavasi likes this.
  35. CinnoMan

    CinnoMan

    Joined:
    Jan 27, 2014
    Posts:
    16
    Hi!
    I was wondering if, using Rewire, I can make the xbox one controller's triggers rumble independently from each other. The feature seems to be only included in the new windows.gaming.input API, and I'm a bit confused whether that only works for UWP games, sold through the windows store.

    Also, are there any plans to do native Steam Controller support?
    Thank you for clarifying!
     
  36. mmalavasi

    mmalavasi

    Joined:
    Jun 21, 2017
    Posts:
    13
    Thanks for the answer.
    Probably I wasn't clear, sorry. The thing is that I have already all the system working ok, so for example I do _player.controllers.maps.GetFirstElementMapWithAction(controllerType, actionId, false); and it works fine. I thought that this was working fine until.. I disconnected the controller :D (yes, I did all the tests with the controller plugged in). When the controller is disconnected this does not work. Since my game only supports xbox controllers, is it possible to get the actions mapped to the specific controller even if it is not plugged in at the moment?
     
  37. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    You can't map controls in-game for joysticks that aren't plugged in. There are many reasons for this. primary of which is that there's no way to know what hardware definition and therefore what controller map will be loaded for a joystick until it is plugged in and the identifying information is available. At any time, one or more input sources may be in use. Which input source will ultimately control the joystick is based on the identifying information from the joystick. In some cases, like the Xbox One controller on Windows 10 (due to MS driver bug workarounds), it has to choose among as many as 3 different input sources depending on certain things which will ultimately affect what hardware definition and sub-per-platform definition and/or variant will be loaded, which in turn determines which Controller Maps are finally loaded.

    If your intention is to allow users to pre-map some universal gamepad layout before having any controllers plugged in, this is even more problematic because Rewired does not instantiate controllers as "Gamepad" objects just because they match the Dual Analog Gamepad template. All joysticks are individual. The templates exist to convert developer-defined default mappings to device-specific mappings at load time. After the device-specific mapping is loaded, there is no relation to the Dual Analog Gamepad template anymore. If you plug in two controllers such as a DS4 and a Xbox 360 controller and map these in-game and save the mappings to XML, it will save mappings for each device individually, not a global "Gamepad" mapping that will apply to all gamepads attached.

    If you only care about one particular joystick type and you want to try to do it, there are no run-time methods that will get you a hardware definition. There is a published list of all recognized controllers with element identifiers here: http://guavaman.com/projects/rewired/docs/HowTos.html#display-glyph-for-action

    On Windows, if "Use XInput" is enabled, you can be assured that XInput devices will load the Xbox 360 Controller definition. If XInput is disabled or on any other platform, you cannot be assured which definition it will be matched to (Xbox One controller may load the Xbox One definition on OSX when using Native input, but will load the Standardized Gamepad definition on SDL2, etc.)

    >> what is the correct way to get an action name given an elementIdentifierId

    There is no one single Action name for an element identifier id. Any number of Actions can be mapped to a single element identifier id.

    The convenience methods in Player look up the reverse: ActionElementMap for Action. There are no convenience methods for going in reverse.

    Get the Controller Map and use the methods there:
    http://guavaman.com/projects/rewired/docs/api-reference/html/T_Rewired_ControllerMap.htm

    If generating some garbage is okay, these would work:
    http://guavaman.com/projects/rewire...red_ControllerMap_GetFirstElementMapMatch.htm
    http://guavaman.com/projects/rewire...ired_ControllerMap_ForEachElementMapMatch.htm

    Otherwise, you'd have to iterate the ActionElementMaps and check the elementIdentifierId property for a match, then get the actionId from ActionElementMap.actionId.

    More on working with Controller Maps:
    http://guavaman.com/projects/rewired/docs/HowTos.html#managing-controller-maps-runtime
     
    Last edited: Jul 14, 2017
    mmalavasi and Dwight_Everhart like this.
  38. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Sorry, I missed this message.

    Rewired can only control trigger vibration on the Xbox One controller on the UWP platform. Rewired cannot access anything on the controllers that's no provided by XInput. XInput does not allow for control of more than 2 motors.

    There are no plans to implement native Steam Controller support. I've looked into it twice before in the past and it is fraught with difficulties and issues because of Steam initialization problems (if Rewired initializes it and you do so again in with some plugin, chaos can ensue) and because of the fact that it's just a square-peg-round-hole problem. Rewired is designed to read data from controllers and abstract that into a Player-Action system. Steam, since their API overhaul a couple of years ago, is already a Player-Action system. You can't access the controller elements as buttons and axes -- only resulting Action values. This makes it very problematic because one would have to cross-map Rewired Actions and Categories to Steam Actions and Action sets and do all kinds of juggling to make things happen when the user starts remapping their Steam controller controls in the Steam interface. Suddenly Action values are coming from different buttons than before. Synchronizing Actions between the two systems would also require a number of exporter, importer, conversion, and editor tools. And when Steam changes something in the API, everything breaks and I have to be constantly updating to keep up with their changes. Steam and Rewired are trying to play the same role here of abstracting controller-based input into Action-based input and it just doesn't mesh well at all.
     
    Last edited: Jul 17, 2017
    Dwight_Everhart likes this.
  39. phosphoer

    phosphoer

    Joined:
    Jan 11, 2015
    Posts:
    3
    Hello @guavaman, is there a version of Rewired yet that supports 2017 with .NET 4.5? I'm getting hit with the InvokeMember issue mentioned above.
     
  40. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    No there isn't. Even when the InvokeMember issue is fixed, Rewired is completely unusable using the Experimental .Net 4.6 back end. See the 2 messages above for details:

    https://forum.unity3d.com/threads/rewired-advanced-input-for-unity.270693/page-66#post-3116639

    https://forum.unity3d.com/threads/rewired-advanced-input-for-unity.270693/page-66#post-3116485

    There isn't a workaround for this. The bugs are going to have to be fixed in the system before Rewired will run.
     
  41. CinnoMan

    CinnoMan

    Joined:
    Jan 27, 2014
    Posts:
    16
    Thanks for your reply and taking the time to explain!

    This has me a bit confused, though: so does the first sentence mean if I build for UWP I can actually access both trigger vibration motors?

    Also, about the incompatibilities with the steam controller; considering both are based on a Player-Action system, is there anything (other than the extra work) that stands in the way of me implementing both in my game (using Rewired for everything that's not Steam Controller and then adding Steam Controller support on the side)? Like both interfering somehow with each other or something?
     
  42. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Yes. http://guavaman.com/projects/rewired/docs/FAQ.html#force-feedback

    Yes, there is: Steam's XInput emulation. The last time I looked into this, there was no way from the Steam API to tell it to disable XInput emulation or to be able to determine which XInput id the Steam Controller's emulated device associated to. This means the Steam Controller will appear as both an XInput device and as a native Steam controller. Rewired will see and use the XInput device and if you get input from the Steam API, the Steam Controller will appear there too. They may have changed something by now, but this was the state of things the last time I checked and another reason why I did not implement native support -- because of issues I have no control over.
     
  43. dearamy

    dearamy

    Joined:
    Mar 17, 2015
    Posts:
    68
    Is there any way to manually moving mouse position/cursor with the joystick?
     
  44. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Rewired doesn't control the hardware mouse cursor in any way on any platform. Sorry.
     
  45. mmalavasi

    mmalavasi

    Joined:
    Jun 21, 2017
    Posts:
    13
    Sorry but I don't know if I'm not understanding your answer or I'm capable of explaining myself well (probably both :D). I understand that I cannot map joypad not plugged in. Suppose then that I want just the list of the mapping Actioname -> joypadButton that I made in Unity with the rewired editor. I want to display in a menu that I (the programmer) mapped the action "Fire" to the button RT of the 360 controller. This information is saved in the rewired editor, so it is there even if the joypad is not plugged in, no? If I try to get this information in game and the joypad is plugged in then it works, otherwise it won't. Why you need the joypad plugged if it is a static info saved in the rewired editor (if I open it in the editor, I can see the info even without joypad plugged in)...
     
  46. Tony707

    Tony707

    Joined:
    Jun 15, 2015
    Posts:
    38
    Hi,

    Is there a way we can black list a set of buttons when using the input mapper ?
    For example I'd like to avoid the user to use the left and right mouse button ?

    (Rewired version 1.1.3.0.05)

    Thank you,
     
  47. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Based on what I explained above, when you look at "Microsoft Xbox One Controller" in the Rewired Editor for example, you are looking at a mapping made for the hardware definition for the Microsoft Xbox One Controller. When a user plugs in an Xbox One Controller, there is no guarantee that the "Microsoft Xbox One Controller" definition will be loaded. This is all determined by the identifying information found in the hardware device and the input source that ultimately takes charge of that controller. As explained here, there are many case where the controller definition you think will be used is not actually the definition that will be ultimately used. This varies by platform and device. In this case, if you have Use XInput enabled (the default), it will actually load the Xbox 360 Controller definition for an Xbox One Controller, not the Xbox One Controller definition. This is to illustrate that you cannot know which definition will be chosen beforehand until the device is plugged in. It's not always as simplistic as this case.

    Getting the actual Controller Map for a specific controller without the controller plugged in is extremely problematic for all the reasons outlined in my previous post. However, getting the list of controls you've defined in the Rewired Input Manager would be less-so because it doesn't have to also choose from the many variants within a hardware definition to get the actual mappings. While it could be done, there are no exposed methods to get any of this information. The data defined in the Rewired Input Manager is not considered run-time data. It's all considered "developer-defined defaults" and not accessible at runtime. The serialized data in the Rewired Input Manager is not editable at runtime nor is it possible to save over it except in the editor. They are the defaults that are used when a controller is attached, but they do not denote the "current configuration" of a controller.

    To understand what I mean consider the situation of user saving/loading of data. If you allow your users to save their controller mappings, those mappings are the new current configuration for a controller. When a controller is plugged in and assigned to that Player, the mappings will be loaded from XML, not from the read-only developer-defined default stored in the Rewired Input Manager. Showing your user a list of mappings from the Rewired Input Manager would be misleading and incorrect in this situation because once they plug in a controller, their mappings will reflect the saved values and not the default values.

    Further complicating this is the fact that most developers will use the Dual Analog Gamepad Template to define their defaults rather than the specific controller. This Dual Analog Gamepad Template stores the data in a generalized format and only maps to the final Controller Map at the time the map is loaded for the specific hardware definition in use. Again, you cannot know which hardware definition and sub-variant will be used until the controller is connected.

    If you really want to do this, it is possible but you'd have to go hacking around in undocumented code meant for internal use in the UserData class (the class that stores all the data in the Rewired Input Manager):

    Code (csharp):
    1. private void SomeMethod() {
    2.  
    3.     // the Guid of the joystick definition
    4.     // See: http://guavaman.com/projects/rewired/docs/HowTos.html#identifying-recognized-controllers
    5.     Guid hardwareGuid = new Guid("350e-fe8b-4e9e-bbcd-efff16d341154115");
    6.  
    7.     // Log the default mappings for the Xbox 360 definition for a particular category and layout
    8.     LogDefaultMappingsForJoystick(hardwareGuid, "SomeCategory", "SomeLayout");
    9. }
    10.  
    11. private void LogDefaultMappingsForJoystick(Guid hardwareGuid, string category, string layout) {
    12.  
    13.     // Get the category id from the string
    14.     int categoryId = ReInput.mapping.GetMapCategoryId(category);
    15.  
    16.     // Get the layout id from the string
    17.     int layoutId = ReInput.mapping.GetLayoutId(ControllerType.Joystick, layout);
    18.  
    19.     // Get the Rewired input manager instance
    20.     Rewired.InputManager rewiredInputManager = UnityEngine.GameObject.FindObjectOfType<Rewired.InputManager>();
    21.     if(rewiredInputManager == null) return; // no Rewired Input Manager found in the scene
    22.  
    23.     // Get the UserData object
    24.     Rewired.Data.UserData userData = rewiredInputManager.userData;
    25.  
    26.     // Get the ControllerDataFiles object
    27.     Rewired.Data.ControllerDataFiles controllerDataFiles = rewiredInputManager.dataFiles;
    28.  
    29.     // Get a specific joystick map for this joystick
    30.     var joystickMap = userData.GetJoystickMap(categoryId, hardwareGuid, layoutId);
    31.     if(joystickMap == null) return;
    32.  
    33.     // Go through each ActionElementMap
    34.     foreach(var aem in joystickMap.actionElementMaps) {
    35.  
    36.         // Get the Action from the action id
    37.         var action = ReInput.mapping.GetAction(aem.actionId);
    38.         if(action == null) continue; // this is not mapped to an Action
    39.  
    40.         // Certain data in the aem will not be available because this is not a game-side
    41.         // Controller Map. Convenience data has not been baked into it from the controller hardware definition
    42.         // The following properties are invalid, so they have to be retrieved manually if available:
    43.         //   elementIdentifierName
    44.         //   elementIndex (not available)
    45.         //   controllerMap (not available)
    46.         //   id (not available)
    47.  
    48.         // To get the name for a particular identifier without the controller attached:
    49.  
    50.         // Get the hardware definiton
    51.         var definition = controllerDataFiles.GetHardwareJoystickMap(hardwareGuid);
    52.         if(definition == null) continue; // could not find a definition for the joystick in question
    53.  
    54.         // Find the element identifier from the mapping
    55.         var elementIdentifier = definition.GetElementIdentifier(aem.elementIdentifierId);
    56.         if(elementIdentifier == null) continue; // could not find the element identifier
    57.  
    58.         // The +/- for the positive and negative poles is also not baked so it has to be obtained manually
    59.  
    60.         string name = "";
    61.  
    62.         if(aem.elementType == ControllerElementType.Axis) {
    63.  
    64.             name = elementIdentifier.name;
    65.  
    66.             if(aem.axisRange == AxisRange.Positive) {
    67.                 name += " +";
    68.             } else if(aem.axisRange == AxisRange.Negative) {
    69.                 name += " -";
    70.             }
    71.  
    72.         } else if(aem.elementType == ControllerElementType.Button) {
    73.             name = elementIdentifier.name;
    74.         }
    75.  
    76.         // Debug log the mapping
    77.         Debug.Log(action.descriptiveName + " is mapped to " + aem.elementIdentifierId);
    78.     }
    79. }
    As you can tell, this isn't a process that was intended for public use. You could also do a similar thing to get data from a Template.
     
    Last edited: Jul 19, 2017
    mmalavasi and Dwight_Everhart like this.
  48. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    No there isn't. There was going to be a callback but the format and information it was to return was never finalized. I was never happy with how much effort it would be to determine which elements to exclude. (Element identifier lookups, etc.)

    This is somewhat ugly but it should work. It is not tested:

    Code (csharp):
    1. InputMapper mapper = new InputMapper();
    2. InputMapper.Context context = new InputMapper.Context();
    3. ActionElementMap oldMapCopy;
    4.  
    5. void StartInputMapper(ControllerMap map, ActionElementMap aemToReplace, int actionId, AxisRange actionRange) {
    6.     oldMapCopy = aemToReplace != null ? new ActionElementMap(aemToReplace) : null; // store the original we're modifying aem first
    7.     context.controllerMap = map;
    8.     context.actionId = actionId;
    9.     context.actionRange = actionRange;
    10.     context.actionElementMapToReplace = aemToReplace; // replace it
    11.     mapper.InputMappedEvent += OnInputMapped; // subscribe to the mapped event
    12.     mapper.Start(context); // start the mapper
    13. }
    14.  
    15. void OnInputMapped(InputMapper.InputMappedEventData data) {
    16.  
    17.     // Detect left/right buttons on mouse
    18.     if(data.actionElementMap.controllerMap.controllerType == ControllerType.Mouse &&
    19.         data.actionElementMap.elementType == ControllerElementType.Button &&
    20.         (data.actionElementMap.elementIndex == 0 || data.actionElementMap.elementIndex == 1)) {
    21.          
    22.             // Delete the new ActionElementMap
    23.             context.controllerMap.DeleteElementMap(data.actionElementMap.id);
    24.  
    25.             // Replace it back with the copy we saved
    26.             ActionElementMap aem = null;
    27.             if(oldMapCopy != null) {
    28.                 context.controllerMap.CreateElementMap(
    29.                     ElementAssignment.CompleteAssignment(
    30.                         context.controllerMap.controllerType,
    31.                         oldMapCopy.elementType,
    32.                         oldMapCopy.elementIdentifierId,
    33.                         oldMapCopy.axisRange,
    34.                         oldMapCopy.keyCode,
    35.                         oldMapCopy.modifierKeyFlags,
    36.                         oldMapCopy.actionId,
    37.                         oldMapCopy.axisContribution,
    38.                         oldMapCopy.invert
    39.                     ), out aem
    40.                 );
    41.             }
    42.             // Cancel and restart input mapper
    43.             StartInputMapper(context.controllerMap, aem, context.actionId, context.actionRange);
    44.  
    45.     } else {
    46.         // accept it
    47.  
    48.      
    49.     }
    50. }
    51.  
    The copying of the existing ActionElementMap first and replacing it if a mouse button is used is ugly, but the only way to undo the assignment that was already made.
     
    Last edited: Jul 19, 2017
    Dwight_Everhart and Tony707 like this.
  49. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,625
    Rewired 1.1.4.0 is now available for registered users. If you would like to register to receive early access to updates, please contact me here. The update has been submitted to the Unity Asset Store. I will post a notification here when the Asset Store approves the update.

    Be sure to read Updating Rewired before updating.

    Release Notes:

    1.1.4.0:

    Changes:
    - Updated for Unity 2017 compatibility.
    - Added native support for WebGL platform. (Unity 5.0+)
    - Windows Standalone, Raw Input, Direct Input: Added Native Keyboard Handling option.
    - Windows Standalone with Native Keyboard Handling and Native Mouse Handling enabled: Disabling "Ignore Input When App Not In Focus" now allows mouse and keyboard input as well as joystick input when the application is not in focus in a build.
    - Added Use XInput and Support HID Devices options to Windows UWP platform settings in Rewired Input Manager.
    - Rewired Standalone Input Module: Changed to disable all mouse input if no physical mouse is present to match Unity's changes to the Standalone Input Module.
    - UserDataStore_PlayerPrefs: Added options to save and load controller assignments.
    - Player.GetTimedButtonPress, Player.GetTimedButtonPressUp, and negative button variants now accept a time value of 0.
    - Input Behavior Button Short Press Time and Button Long Press Time can now be set to a value of 0.
    - 8-way hats on unrecognized controllers now respect the "Force 4-way Hats" option at the Joystick level.
    - iOS/tvOS: Joystick.name now reports the joystick name as reported by the device instead of "Controller" for MFi controllers.
    - Added new SDL2 controller mappings

    New Controllers with Extended Support:
    - GameSir G3
    - GameSir G3s
    - GameSir G3v
    - GameSir G3w
    - GameSir G4
    - GameSir G4s
    - 8Bitdo RB8-64 N64 Controller
    - Microsoft SideWinder Precision 2
    - TigerGame PS/PS2 Game Controller Adapter

    Modified Controller Definitions:
    - Sony DualShock 4
    - Linux Native: Added variant for changes made in the Ubuntu 17.04 driver.
    - Linux Fallback: Dropped support for Linux Fallback due to the inability to differentiate driver
    versions.
    - Microsoft Xbox One, Linux Native, Linux Fallback: Added matching info for older firmware versions.
    - Microsoft Xbox One, UWP Native: Added mappings when XInput is disabled.
    - Microsoft Xbox 360, UWP Native: Added mappings when XInput is disabled.
    - Logitech F310, UWP Native: Added mappings when XInput is disabled.
    - Logitech F710, UWP Native: Added mappings when XInput is disabled.
    - 8Bitdo NES30: Combined definitions for different connection modes into new definition file.
    - 8Bitdo SNES30: Combined definitions for different connection modes into new definition file.
    - 8Bitdo NES30 Pro: Combined definitions for different connection modes into new definition file.
    - Sony DualShock 2: Combined definitions for different PS2 adapters into one definition file.
    - Added native WebGL mappings for:
    - Microsoft Xbox 360 Controller
    - Microsoft Xbox One Controller
    - Microsoft Xbox One S Controller
    - Sony DualShock 4

    API Changes:
    - Added ReInput.ConfigManager.nativeKeyboardSupport property.
    - Added ReInput.ConfigManager.windowsUWPSupportHIDDevices property.
    - Added UserDataStore_PlayerPrefs.LoadJoystickAssignments property.
    - Added UserDataStore_PlayerPrefs.LoadMouseAssignments property.
    - Added UserDataStore_PlayerPrefs.LoadKeyboardAssignments property.
    - Added ReInput.ConfigHelper.webGLPrimaryInputSource property.

    Bug Fixes:
    - Windows Raw Input, Direct Input, XInput: Eliminated 500 byte memory allocations generated periodically when polling for new devices.
    - Unity 2017.1.b10, .NET 4.6 Experimental Scripting Backend: Fixed issue with method calls made by reflection.
    - Windows 10 Universal, .NET scripting backend: Fixed possible freeze during device enumeration when HID device support enabled in app manifest.
    - Windows 10 Universal, IL2CPP scripting backend: Fixed possible crash when closing app when HID device support enabled in app manifest.
     
    Last edited: Jul 21, 2017
  50. longroadhwy

    longroadhwy

    Joined:
    May 4, 2014
    Posts:
    1,551
    This is yet another wonderful update. Another 9 new controllers added to the long list of supported controllers. You would have to get one of those big billboards to display them all. :)

    That native keyboard handling sounds very useful. Have to read up on the new UserDataStore_PlayerPrefs features too.

    Hopefully the asset store can release this today.