Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Any example of the new 2019.1 XR input system?

Discussion in 'AR/VR (XR) Discussion' started by fariazz, Feb 15, 2019.

  1. kavanavak

    kavanavak

    Joined:
    Sep 30, 2015
    Posts:
    50
    That looks about right. I made an input script to take all input and send out events when buttons are pressed, which I house on my main controller object. I link those events through the editor to GO scripts nested in that main controller, scripts that have generic TriggerPressed() or ActionType() values that perform their own controller specific functions when called.

    Code (CSharp):
    1. private void Start()
    2.     {
    3.         //INPUT DATA
    4.         m_Controller = GetComponentInParent<XRController>();
    5.         m_Node = m_Controller.controllerNode;
    6.         InitializeDevice();
    7.     }
    8.  
    9.     private void InitializeDevice()
    10.     {
    11.         m_InputDevice = InputDevices.GetDeviceAtXRNode(m_Node);
    12.         if (m_Node == XRNode.LeftHand)
    13.         {
    14.             GetComponent<ControllerStatus>().isLeftController = true;
    15.         }
    16.         if (m_Node == XRNode.RightHand)
    17.         {
    18.             GetComponent<ControllerStatus>().isRightController = true;
    19.         }
    20.     }
    21. private void Update()
    22.     {
    23. if (m_InputDevice == null)
    24.         {
    25.             Debug.LogError("no device found on " + m_Node);
    26.             return;
    27.         }
    28.  
    29.         if (m_ControllersEnabled)
    30.         {
    31.             //TRIGGER
    32.             m_InputDevice.TryGetFeatureValue(CommonUsages.trigger, out m_TriggerValue);//m_InputDevice.TryGetFeatureValue(new InputFeatureUsage<float>("Trigger"), out m_TriggerValue);
    33.             m_InputDevice.TryGetFeatureValue(new InputFeatureUsage<bool>("TriggerButton"), out m_TriggerButtonStatus);
    34.             if ((m_TriggerValue == 1) & !m_TriggerAlreadyActive)
    35.             {
    36.                 Trigger();
    37.                 m_TriggerAlreadyActive = true;
    38.             }
    39.             if ((m_TriggerValue != 1) & m_TriggerAlreadyActive)
    40.             {
    41.                 m_TriggerAlreadyActive = false;
    42.             }
    43. ...
    44.  
     
  2. Loths

    Loths

    Joined:
    Aug 18, 2017
    Posts:
    9
    Looks pretty similar to what I'm attempting, don't really see anything that wouldn't make it work on my end. Is there anything outside of the script that needs to be set up? Anything in input or player settings or something like that?
     
  3. Loths

    Loths

    Joined:
    Aug 18, 2017
    Posts:
    9
    Turns out it was working all along and the input just wasn't coming through. Apparently that's an issue with oculus, this thread solved it for me: https://forum.unity.com/threads/oculus-touch-input-not-detected.546942/
     
    kavanavak likes this.
  4. Alverik

    Alverik

    Joined:
    Apr 15, 2016
    Posts:
    409
    Tried making a VrInput class which works a little more like the regular input class. And since I wanted it to be usable for multiple devices at the same time I created a special class that holds the "keys" and hand to be checked per device (the intention is to return a result based on what device is plugged in... but I mostly intend to use it for Rift and Vive). But still has a few things that need to be improved, or verified because I only have an old Rift to test (which was pretty hard to get where I live). Some of the device names seem to be different depending on the backend in use, so I can't guarantee it'll work without some tweaks (I'm using the device names to know what result to provide, but I have no way to test for a while)... Seems to work as expected using the new backend and the Rift though.

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. namespace Clunia
    5. {
    6.     public class VrInputEvents : MonoBehaviour
    7.     {
    8.         public delegate void EventHandler(HandType hand);
    9.         public delegate void HmdEventHandler();
    10.    
    11.         public static event HmdEventHandler OnHmdMounted;
    12.         public static event HmdEventHandler OnHmdUnmounted;
    13.    
    14.         public static event EventHandler OnPrimary2DAxisClickDown;
    15.         public static event EventHandler OnSecondary2DAxisClickDown;
    16.    
    17.         public static event EventHandler OnPrimary2DAxisTouchDown;
    18.         public static event EventHandler OnPrimaryTouchDown;
    19.         public static event EventHandler OnSecondaryTouchDown;
    20.    
    21.         public static event EventHandler OnPrimaryButtonDown;
    22.         public static event EventHandler OnSecondaryButtonDown;
    23.         public static event EventHandler OnGripButtonDown;
    24.         public static event EventHandler OnTriggerButtonDown;
    25.         public static event EventHandler OnMenuButtonDown;
    26.         public static event EventHandler OnUserPresenceDown;
    27.  
    28.    
    29.    
    30.         public static event EventHandler OnPrimary2DAxisClickUp;
    31.         public static event EventHandler OnSecondary2DAxisClickUp;
    32.    
    33.         public static event EventHandler OnPrimary2DAxisTouchUp;
    34.         public static event EventHandler OnPrimaryTouchUp;
    35.         public static event EventHandler OnSecondaryTouchUp;
    36.    
    37.         public static event EventHandler OnPrimaryButtonUp;
    38.         public static event EventHandler OnSecondaryButtonUp;
    39.         public static event EventHandler OnGripButtonUp;
    40.         public static event EventHandler OnTriggerButtonUp;
    41.         public static event EventHandler OnMenuButtonUp;
    42.         public static event EventHandler OnUserPresenceUp;
    43.  
    44.         public static bool LeftControllerActive { get; private set; }
    45.         public static bool RightControllerActive { get; private set; }
    46.    
    47.  
    48.         protected static void Primary2DAxisClickDownCaller(HandType hand)
    49.         {
    50.             OnPrimary2DAxisClickDown?.Invoke(hand);
    51.         }
    52.    
    53.         protected static void Secondary2DAxisClickDownCaller(HandType hand)
    54.         {
    55.             OnSecondary2DAxisClickDown?.Invoke(hand);
    56.         }
    57.    
    58.         protected static void Primary2DAxisTouchDownCaller(HandType hand)
    59.         {
    60.             OnPrimary2DAxisTouchDown?.Invoke(hand);
    61.         }
    62.    
    63.         protected static void PrimaryTouchDownCaller(HandType hand)
    64.         {
    65.             OnPrimaryTouchDown?.Invoke(hand);
    66.         }
    67.    
    68.         protected static void SecondaryTouchDownCaller(HandType hand)
    69.         {
    70.             OnSecondaryTouchDown?.Invoke(hand);
    71.         }
    72.    
    73.         protected static void PrimaryButtonDownCaller(HandType hand)
    74.         {
    75.             OnPrimaryButtonDown?.Invoke(hand);
    76.         }
    77.    
    78.         protected static void SecondaryButtonDownCaller(HandType hand)
    79.         {
    80.             OnSecondaryButtonDown?.Invoke(hand);
    81.         }
    82.    
    83.         protected static void GripButtonDownCaller(HandType hand)
    84.         {
    85.             OnGripButtonDown?.Invoke(hand);
    86.         }
    87.    
    88.         protected static void TriggerButtonDownCaller(HandType hand)
    89.         {
    90.             OnTriggerButtonDown?.Invoke(hand);
    91.         }
    92.    
    93.         protected static void MenuButtonDownCaller(HandType hand)
    94.         {
    95.             OnMenuButtonDown?.Invoke(hand);
    96.         }
    97.    
    98.         protected static void UserPresenceDownCaller(HandType hand)
    99.         {
    100.             switch (hand)
    101.             {
    102.                 case HandType.Left:
    103.                     LeftControllerActive = true;
    104.                     break;
    105.                 case HandType.Right:
    106.                     RightControllerActive = true;
    107.                     break;
    108.             }
    109.        
    110.             OnUserPresenceDown?.Invoke(hand);
    111.         }
    112.    
    113.         //------------------
    114.    
    115.         protected static void Primary2DAxisClickUpCaller(HandType hand)
    116.         {
    117.             OnPrimary2DAxisClickUp?.Invoke(hand);
    118.         }
    119.    
    120.         protected static void Secondary2DAxisClickUpCaller(HandType hand)
    121.         {
    122.             OnSecondary2DAxisClickUp?.Invoke(hand);
    123.         }
    124.    
    125.         protected static void Primary2DAxisTouchUpCaller(HandType hand)
    126.         {
    127.             OnPrimary2DAxisTouchUp?.Invoke(hand);
    128.         }
    129.    
    130.         protected static void PrimaryTouchUpCaller(HandType hand)
    131.         {
    132.             OnPrimaryTouchUp?.Invoke(hand);
    133.         }
    134.    
    135.         protected static void SecondaryTouchUpCaller(HandType hand)
    136.         {
    137.             OnSecondaryTouchUp?.Invoke(hand);
    138.         }
    139.    
    140.         protected static void PrimaryButtonUpCaller(HandType hand)
    141.         {
    142.             OnPrimaryButtonUp?.Invoke(hand);
    143.         }
    144.    
    145.         protected static void SecondaryButtonUpCaller(HandType hand)
    146.         {
    147.             OnSecondaryButtonUp?.Invoke(hand);
    148.         }
    149.    
    150.         protected static void GripButtonUpCaller(HandType hand)
    151.         {
    152.             OnGripButtonUp?.Invoke(hand);
    153.         }
    154.    
    155.         protected static void TriggerButtonUpCaller(HandType hand)
    156.         {
    157.             OnTriggerButtonUp?.Invoke(hand);
    158.         }
    159.    
    160.         protected static void MenuButtonUpCaller(HandType hand)
    161.         {
    162.             OnMenuButtonUp?.Invoke(hand);
    163.         }
    164.    
    165.         protected static void UserPresenceUpCaller(HandType hand)
    166.         {
    167.             switch (hand)
    168.             {
    169.                 case HandType.Left:
    170.                     LeftControllerActive = false;
    171.                     break;
    172.                 case HandType.Right:
    173.                     RightControllerActive = false;
    174.                     break;
    175.             }
    176.        
    177.             OnUserPresenceUp?.Invoke(hand);
    178.         }
    179.    
    180.         //-----------------------
    181.  
    182.         protected static void HmdMountedCaller()
    183.         {
    184.             OnHmdMounted?.Invoke();
    185.         }
    186.    
    187.         protected static void HmdUnmountedCaller()
    188.         {
    189.             OnHmdUnmounted?.Invoke();
    190.         }
    191.  
    192.     }
    193. }
    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.XR;
    4. using System.Collections.Generic;
    5. using UnityEngine.PlayerLoop;
    6. using UnityEngine.SpatialTracking;
    7. using UnityEngine.XR.Interaction.Toolkit;
    8.  
    9. namespace Clunia
    10. {
    11.  
    12.     #region public enums
    13.     public enum RiftKeyCodes
    14.     {
    15.         None,
    16.         Trigger,
    17.         Grip,
    18.         Menu,
    19.         ButtonOne,
    20.         ButtonTwo,
    21.         ThumbStick,
    22.         ButtonOneTouch,
    23.         ButtonTwoTouch,
    24.         ThumbStickTouch
    25.     }
    26.  
    27.     public enum ViveKeyCodes
    28.     {
    29.         None,
    30.         Trigger,
    31.         Grip,
    32.         Menu,
    33.         Trackpad,
    34.         TrackpadUp,
    35.         TrackpadDown,
    36.         TrackpadLeft,
    37.         TrackpadRight,
    38.         TrackpadRightUp,
    39.         TrackpadRightDown,
    40.         TrackpadLeftUp,
    41.         TrackpadLeftDown
    42.     }
    43.     public enum ViveKnuckleKeyCodes
    44.     {
    45.         None,
    46.         Trigger,
    47.         Grip,
    48.         Primary,
    49.         Alternate,
    50.         Joystick,
    51.         JoystickTouch
    52.     }
    53.  
    54.     public enum GearVrKeyCodes
    55.     {
    56.         None,
    57.         Trigger,
    58.         Touchpad,
    59.         TouchpadTouch
    60.     }
    61.  
    62.     public enum HandType
    63.     {
    64.         Left,Right
    65.     }
    66.  
    67.     public enum GetKeyType
    68.     {
    69.         Get,GetDown,GetUp
    70.     }
    71.  
    72. #endregion
    73.  
    74.     public class VrInput : VrInputEvents
    75.     {
    76.         private enum TrackpadDirection
    77.         {
    78.             Left,Right,Up,Down,
    79.             LeftUp, RightUp, LeftDown,RightDown
    80.         }
    81.  
    82.         public static string LoadedDeviceName => XRSettings.loadedDeviceName;
    83.         public static bool XrPresent { get; private set; }
    84.  
    85.         //device name constants
    86.         private const string OpenVrDeviceName = "OpenVR";
    87.         private const string OculusDeviceName = "Oculus";
    88.         private const string OculusDeviceNameB = "oculus display";
    89.         private const string GearVrDeviceName = "GearVr";
    90.  
    91.         #region Raw Inputs
    92.    
    93.         private static List<InputDevice> _headDevices = new List<InputDevice>();
    94.         private static List<InputDevice> _leftHandDevices = new List<InputDevice>();
    95.         private static List<InputDevice> _rightHandDevices = new List<InputDevice>();
    96.  
    97.         private static InputDevice Head { get; set; }
    98.         private static InputDevice LeftHand { get; set; }
    99.         private static InputDevice RightHand { get; set; }
    100.  
    101.         public static bool LeftControllerConnected { get; private set; } = true;
    102.         public static bool RightControllerConnected { get; private set; } = true;
    103.  
    104.  
    105.         public class InputBase
    106.         {
    107.             public class KeyData
    108.             {
    109.                 public bool Pressed;
    110.                 public bool Down;
    111.                 public bool Up;
    112.  
    113.                 public bool Last { get; private set; }
    114.  
    115.                 public void Update()
    116.                 {
    117.                     Last = Pressed;
    118.                 }
    119.             }
    120.        
    121.             public void SetDevice(InputDevice device)
    122.             {
    123.                 Device = device;
    124.             }
    125.        
    126.             protected InputDevice Device { get; private set; }
    127.        
    128.             public Vector3 Position => Get3DAxis(Device, CommonUsages.devicePosition);
    129.  
    130.             public Quaternion Rotation => GetRot(Device, CommonUsages.deviceRotation);
    131.        
    132.             public Vector3 Velocity => Get3DAxis(Device, CommonUsages.deviceVelocity);
    133.             public Vector3 Acceleration => Get3DAxis(Device, CommonUsages.deviceAcceleration);
    134.             public Vector3 AngularVelocity => Get3DAxis(Device, CommonUsages.deviceAngularVelocity);
    135.             public Vector3 AngularAcceleration => Get3DAxis(Device, CommonUsages.deviceAngularAcceleration);
    136.  
    137.             public float BatteryLevel => GetAxis(Device, CommonUsages.batteryLevel);
    138.        
    139.             protected Vector3 Get3DAxis(InputDevice device, InputFeatureUsage<Vector3> usage)
    140.             {
    141.                 device.TryGetFeatureValue(usage, out var val);
    142.                 return val;
    143.             }
    144.        
    145.             protected Quaternion GetRot(InputDevice device, InputFeatureUsage<Quaternion> usage)
    146.             {
    147.                 device.TryGetFeatureValue(usage, out var val);
    148.                 return val;
    149.             }
    150.        
    151.             protected bool GetKey(InputDevice device, InputFeatureUsage<bool> usage)
    152.             {
    153.                 device.TryGetFeatureValue(usage, out var val);
    154.                 return val;
    155.             }
    156.        
    157.             protected float GetAxis(InputDevice device, InputFeatureUsage<float> usage)
    158.             {
    159.                 device.TryGetFeatureValue(usage, out var val);
    160.                 return val;
    161.             }
    162.    
    163.             protected Vector2 Get2DAxis(InputDevice device, InputFeatureUsage<Vector2> usage)
    164.             {
    165.                 device.TryGetFeatureValue(usage, out var val);
    166.                 return val;
    167.             }
    168.         }
    169.  
    170.         public class HeadsetInputs : InputBase
    171.         {
    172.             public KeyData UserPresence = new KeyData();
    173.  
    174.             public void Update()
    175.             {
    176.                 UserPresence.Pressed = GetKey(Device, CommonUsages.userPresence);
    177.            
    178.                 GetState(UserPresence.Pressed, UserPresence.Last, out UserPresence.Down,
    179.                     out UserPresence.Up,HmdMountedCaller,HmdUnmountedCaller);
    180.            
    181.                 UserPresence.Update();
    182.             }
    183.        
    184.             void GetState(bool cur, bool prev, out bool keyDown, out bool keyUp,
    185.                 Action mounted, Action unmounted)
    186.             {
    187.                 if (cur != prev) //if changed
    188.                 {
    189.                     if (cur)
    190.                     {
    191.                         keyDown = true;
    192.                         keyUp = false;
    193.                         mounted?.Invoke();
    194.                         HmdMounted = true;
    195.                         //Debug.Log("Hmd put on");
    196.                     }
    197.                     else
    198.                     {
    199.                         keyUp = true;
    200.                         keyDown = false;
    201.                         unmounted?.Invoke();
    202.                         HmdMounted = false;
    203.                         //Debug.Log("Hmd put removed");
    204.                     }
    205.                     return;
    206.                 }
    207.                 //if same as previous, button is held or not being pressed at all
    208.                 keyDown = false;
    209.                 keyUp = false;
    210.             }
    211.         }
    212.  
    213.         public class ControllerInputs: InputBase
    214.         {
    215.             public ControllerInputs(HandType hand)
    216.             {
    217.                 Hand = hand;
    218.             }
    219.        
    220.             private HandType Hand { get; }
    221.        
    222.        
    223.             public Vector3 Primary2DAxis => Get2DAxis(Device, CommonUsages.primary2DAxis);
    224.             public Vector3 Secondary2DAxis => Get2DAxis(Device, CommonUsages.secondary2DAxis);
    225.    
    226.             public float Grip => GetAxis(Device, CommonUsages.grip);
    227.             public float Trigger => GetAxis(Device, CommonUsages.trigger);
    228.  
    229.  
    230.             //get key
    231.             public KeyData Primary2DAxisClick = new KeyData();
    232.             public KeyData Secondary2DAxisClick = new KeyData();
    233.    
    234.             public KeyData Primary2DAxisTouch = new KeyData();
    235.             public KeyData PrimaryTouch = new KeyData();
    236.             public KeyData SecondaryTouch = new KeyData();
    237.    
    238.             public KeyData PrimaryButton = new KeyData();
    239.             public KeyData SecondaryButton = new KeyData();
    240.             public KeyData GripButton = new KeyData();
    241.             public KeyData TriggerButton = new KeyData();
    242.             public KeyData MenuButton = new KeyData();
    243.             public KeyData UserPresence = new KeyData();
    244.  
    245.             public void Update()
    246.             {
    247.                 //Debug.Log(Hand + " - Primary Axis: "+ Primary2DAxis + " - Time: " + Time.realtimeSinceStartup);
    248.                 Primary2DAxisClick.Pressed = GetKey(Device, CommonUsages.primary2DAxisClick);
    249.                 Secondary2DAxisClick.Pressed = GetKey(Device, CommonUsages.secondary2DAxisClick);
    250.            
    251.                 Primary2DAxisTouch.Pressed = GetKey(Device, CommonUsages.primary2DAxisTouch);
    252.                 PrimaryTouch.Pressed = GetKey(Device, CommonUsages.primaryTouch);
    253.                 SecondaryTouch.Pressed = GetKey(Device, CommonUsages.secondaryTouch);
    254.            
    255.                 PrimaryButton.Pressed = GetKey(Device, CommonUsages.primaryButton);
    256.                 SecondaryButton.Pressed = GetKey(Device, CommonUsages.secondaryButton);
    257.                 GripButton.Pressed = GetKey(Device, CommonUsages.gripButton);
    258.                 TriggerButton.Pressed = GetKey(Device, CommonUsages.triggerButton);
    259.                 MenuButton.Pressed = GetKey(Device, CommonUsages.menuButton);
    260.                 UserPresence.Pressed = GetKey(Device, CommonUsages.userPresence);
    261.  
    262.                 //check for changes
    263.  
    264.                 GetState(Primary2DAxisClick.Pressed, Primary2DAxisClick.Last, out Primary2DAxisClick.Down,
    265.                     out Primary2DAxisClick.Up, Primary2DAxisClickDownCaller, Primary2DAxisClickUpCaller);
    266.            
    267.                 GetState(Secondary2DAxisClick.Pressed, Secondary2DAxisClick.Last, out Secondary2DAxisClick.Down,
    268.                     out Secondary2DAxisClick.Up,Secondary2DAxisClickDownCaller,Secondary2DAxisClickUpCaller);
    269.            
    270.                 GetState(Primary2DAxisTouch.Pressed, Primary2DAxisTouch.Last, out Primary2DAxisTouch.Down,
    271.                     out Primary2DAxisTouch.Up,Primary2DAxisTouchDownCaller,Primary2DAxisTouchUpCaller);
    272.            
    273.                 GetState(PrimaryTouch.Pressed, PrimaryTouch.Last, out PrimaryTouch.Down,
    274.                     out PrimaryTouch.Up,PrimaryTouchDownCaller,PrimaryTouchUpCaller);
    275.            
    276.                 GetState(SecondaryTouch.Pressed, SecondaryTouch.Last, out SecondaryTouch.Down,
    277.                     out SecondaryTouch.Up, SecondaryTouchDownCaller, SecondaryTouchUpCaller);
    278.            
    279.            
    280.            
    281.                 GetState(PrimaryButton.Pressed, PrimaryButton.Last, out PrimaryButton.Down,
    282.                     out PrimaryButton.Up,PrimaryButtonDownCaller,PrimaryButtonUpCaller);
    283.            
    284.                 GetState(SecondaryButton.Pressed, SecondaryButton.Last, out SecondaryButton.Down,
    285.                     out SecondaryButton.Up,SecondaryButtonDownCaller,SecondaryButtonUpCaller);
    286.            
    287.                 GetState(GripButton.Pressed, GripButton.Last, out GripButton.Down,
    288.                     out GripButton.Up,GripButtonDownCaller,GripButtonUpCaller);
    289.            
    290.                 GetState(TriggerButton.Pressed, TriggerButton.Last, out TriggerButton.Down,
    291.                     out TriggerButton.Up,TriggerButtonDownCaller,TriggerButtonUpCaller);
    292.            
    293.                 GetState(MenuButton.Pressed, MenuButton.Last, out MenuButton.Down,
    294.                     out MenuButton.Up,MenuButtonDownCaller,MenuButtonUpCaller);
    295.            
    296.                 GetState(UserPresence.Pressed, UserPresence.Last, out UserPresence.Down,
    297.                     out UserPresence.Up,UserPresenceDownCaller,UserPresenceUpCaller);
    298.            
    299.                 //Then record frame
    300.                 Primary2DAxisClick.Update();
    301.                 Secondary2DAxisClick.Update();
    302.            
    303.                 Primary2DAxisTouch.Update();
    304.                 PrimaryTouch.Update();
    305.                 SecondaryTouch.Update();
    306.  
    307.                 PrimaryButton.Update();
    308.                 SecondaryButton.Update();
    309.                 GripButton.Update();
    310.                 TriggerButton.Update();
    311.                 MenuButton.Update();
    312.                 UserPresence.Update();
    313.  
    314.             }
    315.  
    316.             void GetState(bool cur, bool prev, out bool keyDown, out bool keyUp,
    317.                 Action<HandType> onKeyDown, Action<HandType> onKeyUp)
    318.             {
    319.                 if (cur != prev) //if changed
    320.                 {
    321.                     if (cur)
    322.                     {
    323.                         keyDown = true;
    324.                         keyUp = false;
    325.                         onKeyDown?.Invoke(Hand);
    326.                     }
    327.                     else
    328.                     {
    329.                         keyUp = true;
    330.                         keyDown = false;
    331.                         onKeyUp?.Invoke(Hand);
    332.                     }
    333.                     return;
    334.                 }
    335.                 //if same as previous, button is held or not being pressed at all
    336.                 keyDown = false;
    337.                 keyUp = false;
    338.             }
    339.         }
    340.  
    341.    
    342.         private static HeadsetInputs HeadInput { get; set; }
    343.         private static ControllerInputs LeftInput { get; set; }
    344.         private static ControllerInputs RightInput { get; set; }
    345.  
    346.         #endregion
    347.  
    348.         #region General Data
    349.  
    350.         //------Hmd
    351.         public static TrackedPoseDriver HmdTrackedPoseDriver { get; private set; }
    352.         public static Vector3 PositionHmd => Head.isValid ? HeadInput.Position : Vector3.zero;
    353.         public static Quaternion RotationHmd => Head.isValid ? HeadInput.Rotation : Quaternion.identity;
    354.    
    355.         public static Vector3 VelocityHmd => Head.isValid ? HeadInput.Velocity : Vector3.zero;
    356.         public static Vector3 AccelerationHmd => Head.isValid ? HeadInput.Acceleration : Vector3.zero;
    357.         public static Vector3 AngularVelocityHmd => Head.isValid ? HeadInput.AngularVelocity : Vector3.zero;
    358.         public static Vector3 AngularAccelerationHmd => Head.isValid ? HeadInput.AngularAcceleration : Vector3.zero;
    359.    
    360.         public static float BatteryLevelHmd => Head.isValid ? HeadInput.BatteryLevel : 0;
    361.         public static bool HmdMounted { get; private set; }
    362.    
    363.    
    364.         //------Left hand
    365.         public static XRController LeftXrController { get; private set; }
    366.         public static Vector3 PositionL => LeftHand.isValid ? LeftInput.Position : Vector3.zero;
    367.         public static Quaternion RotationL => LeftHand.isValid ? LeftInput.Rotation : Quaternion.identity;
    368.    
    369.         public static Vector3 VelocityL => LeftHand.isValid ? LeftInput.Velocity : Vector3.zero;
    370.         public static Vector3 AccelerationL => LeftHand.isValid ? LeftInput.Acceleration : Vector3.zero;
    371.         public static Vector3 AngularVelocityL => LeftHand.isValid ? LeftInput.AngularVelocity : Vector3.zero;
    372.         public static Vector3 AngularAccelerationL => LeftHand.isValid ? LeftInput.AngularAcceleration : Vector3.zero;
    373.         public static Vector3 Primary2DAxisL => LeftHand.isValid ? LeftInput.Primary2DAxis : Vector3.zero;
    374.         public static Vector3 Secondary2DAxisL => LeftHand.isValid ? LeftInput.Secondary2DAxis : Vector3.zero;
    375.  
    376.         public static float GripPressureL => LeftHand.isValid ? LeftInput.Grip : 0;
    377.         public static float TriggerPressureL => LeftHand.isValid ? LeftInput.Trigger : 0;
    378.         public static float BatteryLevelL => LeftHand.isValid ? LeftInput.BatteryLevel : 0;
    379.    
    380.         //------Right hand
    381.  
    382.         public static XRController RightXrController { get; private set; }
    383.         public static Vector3 PositionR => RightHand.isValid ? RightInput.Position : Vector3.zero;
    384.         public static Quaternion RotationR => RightHand.isValid ? RightInput.Rotation: Quaternion.identity;
    385.    
    386.         public static Vector3 VelocityR => RightHand.isValid ? RightInput.Velocity : Vector3.zero;
    387.         public static Vector3 AccelerationR => RightHand.isValid ? RightInput.Acceleration : Vector3.zero;
    388.         public static Vector3 AngularVelocityR => RightHand.isValid ? RightInput.AngularVelocity : Vector3.zero;
    389.         public static Vector3 AngularAccelerationR => RightHand.isValid ? RightInput.AngularAcceleration : Vector3.zero;
    390.         public static Vector3 Primary2DAxisR => RightHand.isValid ? RightInput.Primary2DAxis : Vector3.zero;
    391.         public static Vector3 Secondary2DAxisR => RightHand.isValid ? RightInput.Secondary2DAxis : Vector3.zero;
    392.  
    393.         public static float GripPressureR => RightHand.isValid ? RightInput.Grip : 0;
    394.         public static float TriggerPressureR => RightHand.isValid ? RightInput.Trigger : 0;
    395.         public static float BatteryLevelR => RightHand.isValid ? RightInput.BatteryLevel : 0;
    396.  
    397.         #endregion
    398.    
    399.         #region unity event and init
    400.         public static void Init(GameObject go)
    401.         {
    402.             XrPresent = !LoadedDeviceName.Equals("");
    403.             if (!XrPresent) return;
    404.             go.AddComponent<VrInput>();
    405.         }
    406.    
    407.         private void OnEnable()
    408.         {
    409.             InputDevices.deviceConnected += Connected;
    410.             InputDevices.deviceDisconnected += Disconnected;
    411.        
    412.             HeadInput= new HeadsetInputs();
    413.             LeftInput = new ControllerInputs(HandType.Left);
    414.             RightInput = new ControllerInputs(HandType.Right);
    415.  
    416.             var controllers = FindObjectsOfType<XRController>();
    417.             foreach (var c in controllers)
    418.             {
    419.                 switch (c.controllerNode)
    420.                 {
    421.                     case XRNode.LeftHand:
    422.                         LeftXrController = c;
    423.                         break;
    424.                     case XRNode.RightHand:
    425.                         RightXrController = c;
    426.                         break;
    427.                 }
    428.             }
    429.  
    430.             HmdTrackedPoseDriver = FindObjectOfType<TrackedPoseDriver>();
    431.  
    432.             Debug.Log("Loaded hmd: "+ LoadedDeviceName);
    433.             // OpenVR Controller(Vive Controller MV) - Left
    434.             // OpenVR Controller(Knuckles EV3.0 Left) - Left
    435.         }
    436.  
    437.         private void OnDisable()
    438.         {
    439.             InputDevices.deviceConnected -= Connected;
    440.             InputDevices.deviceDisconnected -= Disconnected;
    441.         }
    442.  
    443.  
    444.         static void UpdateControllerObjects()
    445.         {
    446.             if (!Head.isValid)
    447.             {
    448.                 _headDevices = new List<InputDevice>();
    449.                 InputDevices.GetDevicesAtXRNode(XRNode.Head, _headDevices);
    450.            
    451.                 if (_headDevices.Count > 0)
    452.                 {
    453.                     Head = _headDevices[0];
    454.  
    455.                     foreach (var d in _headDevices)
    456.                     {
    457.                         Debug.Log("Head Device: " + d.name);
    458.                     }
    459.                
    460.                     HeadInput.SetDevice(Head);
    461.                 }
    462.                 else
    463.                     Debug.Log("No headset found!");
    464.            
    465.                 if(_headDevices.Count > 1)
    466.                     Debug.Log("Found more than one headset!");
    467.            
    468.             }
    469.  
    470.             if (!LeftHand.isValid)
    471.             {
    472.                 _leftHandDevices = new List<InputDevice>();
    473.                 InputDevices.GetDevicesAtXRNode(XRNode.LeftHand, _leftHandDevices);
    474.            
    475.                 if (_leftHandDevices.Count > 0)
    476.                 {
    477.                     LeftHand = _leftHandDevices[0];
    478.  
    479.                     foreach (var d in _leftHandDevices)
    480.                     {
    481.                         Debug.Log("Left Device: " + d.name);
    482.                     }
    483.            
    484.                     LeftInput.SetDevice(LeftHand);
    485.                 }
    486.                 else
    487.                     Debug.Log("No left hand found!");
    488.            
    489.                 if(_leftHandDevices.Count > 1)
    490.                     Debug.Log("Found more than one left hand!");
    491.             }
    492.        
    493.             if (!RightHand.isValid)
    494.             {
    495.                 _rightHandDevices = new List<InputDevice>();
    496.                 InputDevices.GetDevicesAtXRNode(XRNode.RightHand, _rightHandDevices);
    497.            
    498.                 if (_rightHandDevices.Count > 0)
    499.                 {
    500.                     foreach (var d in _rightHandDevices)
    501.                     {
    502.                         Debug.Log("Right Device: " + d.name);
    503.                     }
    504.            
    505.                     RightHand = _rightHandDevices[0];
    506.                     RightInput.SetDevice(RightHand);
    507.                 }
    508.                 else
    509.                     Debug.Log("No right hand found!");
    510.            
    511.                 if(_rightHandDevices.Count > 1)
    512.                     Debug.Log("Found more than one right hand!");
    513.             }
    514.         }
    515.  
    516.         private static void Connected(InputDevice device)
    517.         {
    518.             if (device == LeftHand) LeftControllerConnected = true;
    519.             if (device == RightHand) RightControllerConnected = true;
    520.         }
    521.    
    522.         private static void Disconnected(InputDevice device)
    523.         {
    524.             if (device == LeftHand) LeftControllerConnected = false;
    525.             if (device == RightHand) RightControllerConnected = false;
    526.         }
    527.  
    528.         void Update()
    529.         {
    530.             UpdateControllerObjects();
    531.        
    532.             if (Head.isValid) HeadInput.Update();
    533.             if (LeftHand.isValid) LeftInput.Update();
    534.             if (RightHand.isValid) RightInput.Update();
    535.        
    536.             //Debug.Log(" Right hand - Primary Axis: "+ Primary2DAxisR + " - Time: " + Time.realtimeSinceStartup);
    537.         }
    538.  
    539.  
    540.         #endregion
    541.  
    542.  
    543.         #region Merged GetKey methods
    544.         /// <summary>
    545.         /// Returns pressed state of key.
    546.         /// Checks controllers based on active headset
    547.         /// </summary>
    548.         public static bool GetKey(RiftKeyCodes rkey,ViveKeyCodes vkey, ViveKnuckleKeyCodes kKey, GearVrKeyCodes gKey,
    549.             HandType hand, GetKeyType type, bool useKnuckles)
    550.         {
    551.             if (!XrPresent) return false;
    552.        
    553.             switch (XRSettings.loadedDeviceName)
    554.             {
    555.                 case OpenVrDeviceName:
    556.                     return useKnuckles ? GetKey(kKey, hand, type) : GetKey(vkey, hand, type);
    557.                 case OculusDeviceName:
    558.                 case OculusDeviceNameB:
    559.                     return GetKey(rkey, hand,type);
    560.                 case GearVrDeviceName:
    561.                     return GetKey(gKey, hand,type);
    562.             }
    563.  
    564.             return false;
    565.         }
    566.  
    567.         public static bool GetKey(VrKeyCode inputs,GetKeyType type = GetKeyType.Get)
    568.         {
    569.             if (!XrPresent) return false;
    570.        
    571.             //Debug.Log(loadedDeviceName);
    572.             var riftHand = inputs.OculusHand;
    573.             var viveHand = inputs.ViveHand;
    574.             var knuckleHand = inputs.KnuclesHand;
    575.             var gearVrHand = inputs.GearVrHand;
    576.  
    577.             var riftKey = inputs.OculusKey;
    578.             var viveKey = inputs.ViveKey;
    579.             var kKey = inputs.KnuckleKey;
    580.             var gKey = inputs.GearVrKey;
    581.  
    582.             var useKnuckles = inputs.UseKnuckles;
    583.        
    584.             if (riftHand == viveHand &&
    585.                 knuckleHand == gearVrHand &&
    586.                 riftHand == knuckleHand)//if they use the same hand, use unified method
    587.             {
    588.                 return GetKey(riftKey, viveKey,kKey, gKey, riftHand, type, useKnuckles);
    589.             }
    590.  
    591.             switch (LoadedDeviceName)
    592.             {
    593.                 case OpenVrDeviceName:
    594.                     return useKnuckles ? GetKey(kKey, knuckleHand, type) :
    595.                         GetKey(viveKey, viveHand, type);
    596.                 case OculusDeviceName:
    597.                 case OculusDeviceNameB:
    598.                     return GetKey(riftKey, riftHand, type);
    599.                 case GearVrDeviceName:
    600.                     return GetKey(gKey, gearVrHand, type);
    601.                 default:
    602.                     return false;
    603.             }
    604.  
    605.         }
    606.         #endregion
    607.  
    608.         #region Oculus Public methods
    609.         public static  bool GetKey(RiftKeyCodes key,HandType hand)
    610.         {
    611.             return XrPresent && GetKey(key, hand, GetKeyType.Get);
    612.         }
    613.    
    614.         public static  bool GetKeyDown(RiftKeyCodes key,HandType hand)
    615.         {
    616.             return XrPresent && GetKey(key, hand, GetKeyType.GetDown);
    617.         }
    618.    
    619.         public static  bool GetKeyUp(RiftKeyCodes key,HandType hand)
    620.         {
    621.             return XrPresent && GetKey(key, hand, GetKeyType.GetUp);
    622.         }
    623.         #endregion
    624.    
    625.         #region vive Public methods
    626.         public static  bool GetKey(ViveKeyCodes key,HandType hand)
    627.         {
    628.             return XrPresent && GetKey(key, hand, GetKeyType.Get);
    629.         }
    630.    
    631.         public static  bool GetKeyDown(ViveKeyCodes key,HandType hand)
    632.         {
    633.             return XrPresent && GetKey(key, hand, GetKeyType.GetDown);
    634.         }
    635.    
    636.         public static  bool GetKeyUp(ViveKeyCodes key,HandType hand)
    637.         {
    638.             return XrPresent && GetKey(key, hand, GetKeyType.GetUp);
    639.         }
    640.         #endregion
    641.    
    642.         #region Vive Knuckle Public methods
    643.         public static  bool GetKey(ViveKnuckleKeyCodes key,HandType hand)
    644.         {
    645.             return XrPresent && GetKey(key, hand, GetKeyType.Get);
    646.         }
    647.    
    648.         public static  bool GetKeyDown(ViveKnuckleKeyCodes key,HandType hand)
    649.         {
    650.             return XrPresent && GetKey(key, hand, GetKeyType.GetDown);
    651.         }
    652.    
    653.         public static  bool GetKeyUp(ViveKnuckleKeyCodes key,HandType hand)
    654.         {
    655.             return XrPresent && GetKey(key, hand, GetKeyType.GetUp);
    656.         }
    657.         #endregion
    658.    
    659.         #region GearVr Public methods
    660.         public static  bool GetKey(GearVrKeyCodes key,HandType hand)
    661.         {
    662.             return XrPresent && GetKey(key, hand, GetKeyType.Get);
    663.         }
    664.    
    665.         public static  bool GetKeyDown(GearVrKeyCodes key,HandType hand)
    666.         {
    667.             return XrPresent && GetKey(key, hand, GetKeyType.GetDown);
    668.         }
    669.    
    670.         public static  bool GetKeyUp(GearVrKeyCodes key,HandType hand)
    671.         {
    672.             return XrPresent && GetKey(key, hand, GetKeyType.GetUp);
    673.         }
    674.         #endregion
    675.    
    676.         #region GetKey methods
    677.         static bool GetKey(InputBase.KeyData d, GetKeyType type)
    678.         {
    679.             switch (type)
    680.             {
    681.                 case GetKeyType.GetDown:
    682.                     return d.Down;
    683.                 case GetKeyType.GetUp:
    684.                     return d.Up;
    685.                 default:
    686.                     return d.Pressed;
    687.             }
    688.         }
    689.    
    690.    
    691.         static bool GetKey(RiftKeyCodes key,HandType hand, GetKeyType type)
    692.         {
    693.             if (!HandValid(hand) || key == RiftKeyCodes.None) return false;
    694.  
    695.             var device = hand == HandType.Left ? LeftInput : RightInput;
    696.  
    697.             if (!XrPresent) return SimGetKey(key, type);
    698.        
    699.             switch (key)
    700.             {
    701.                 case RiftKeyCodes.Trigger:
    702.                     return GetKey(device.TriggerButton, type);
    703.                 case RiftKeyCodes.Grip:
    704.                     return GetKey(device.GripButton, type);
    705.                 case RiftKeyCodes.Menu:
    706.                     return GetKey(device.MenuButton, type);
    707.                 case RiftKeyCodes.ButtonOne:
    708.                     return GetKey(device.PrimaryButton, type);
    709.                 case RiftKeyCodes.ButtonTwo:
    710.                     return GetKey(device.SecondaryButton, type);
    711.                 case RiftKeyCodes.ThumbStick:
    712.                     return GetKey(device.Primary2DAxisClick, type);
    713.  
    714.                 case RiftKeyCodes.ButtonOneTouch:
    715.                     return GetKey(device.PrimaryTouch, type);
    716.                 case RiftKeyCodes.ButtonTwoTouch:
    717.                     return GetKey(device.SecondaryTouch, type);
    718.            
    719.                 case RiftKeyCodes.ThumbStickTouch:
    720.                     return GetKey(device.Primary2DAxisTouch, type);
    721.             }
    722.  
    723.             return false;
    724.         }
    725.    
    726.         static bool GetKey(ViveKeyCodes key,HandType hand, GetKeyType type)
    727.         {
    728.             if (!HandValid(hand) || key == ViveKeyCodes.None) return false;
    729.  
    730.             var device = hand == HandType.Left ? LeftInput : RightInput;
    731.  
    732.             if (!XrPresent) return SimGetKey(key, type);
    733.        
    734.             switch (key)
    735.             {
    736.                 case ViveKeyCodes.Trigger:
    737.                     return GetKey(device.TriggerButton, type);
    738.                 case ViveKeyCodes.Grip:
    739.                     return GetKey(device.GripButton, type);
    740.                 case ViveKeyCodes.Menu:
    741.                     return GetKey(device.PrimaryButton, type);
    742.  
    743.                 case ViveKeyCodes.Trackpad:
    744.                     return GetKey(device.Primary2DAxisClick, type);
    745.            
    746.                 case ViveKeyCodes.TrackpadUp:
    747.                     return GetTrackpad(device, TrackpadDirection.Up, type);
    748.                 case ViveKeyCodes.TrackpadDown:
    749.                     return GetTrackpad(device, TrackpadDirection.Down, type);
    750.                 case ViveKeyCodes.TrackpadLeft:
    751.                     return GetTrackpad(device, TrackpadDirection.Left, type);
    752.                 case ViveKeyCodes.TrackpadRight:
    753.                     return GetTrackpad(device, TrackpadDirection.Right, type);
    754.            
    755.                 case ViveKeyCodes.TrackpadRightUp:
    756.                     return GetTrackpad(device, TrackpadDirection.RightUp, type);
    757.                 case ViveKeyCodes.TrackpadRightDown:
    758.                     return GetTrackpad(device, TrackpadDirection.RightDown, type);
    759.                 case ViveKeyCodes.TrackpadLeftUp:
    760.                     return GetTrackpad(device, TrackpadDirection.LeftUp, type);
    761.                 case ViveKeyCodes.TrackpadLeftDown:
    762.                     return GetTrackpad(device, TrackpadDirection.LeftDown, type);
    763.             }
    764.  
    765.             return false;
    766.         }
    767.    
    768.         static bool GetKey(ViveKnuckleKeyCodes key,HandType hand, GetKeyType type)
    769.         {
    770.             if (!HandValid(hand) || key == ViveKnuckleKeyCodes.None) return false;
    771.  
    772.             var device = hand == HandType.Left ? LeftInput : RightInput;
    773.  
    774.             if (!XrPresent) return SimGetKey(key, type);
    775.        
    776.             switch (key)
    777.             {
    778.                 case ViveKnuckleKeyCodes.Trigger:
    779.                     return GetKey(device.TriggerButton, type);
    780.                 case ViveKnuckleKeyCodes.Grip:
    781.                     return GetKey(device.GripButton, type);
    782.                 case ViveKnuckleKeyCodes.Primary:
    783.                     return GetKey(device.PrimaryButton, type);
    784.                 case ViveKnuckleKeyCodes.Alternate:
    785.                     return GetKey(device.SecondaryButton, type);
    786.            
    787.                 case ViveKnuckleKeyCodes.Joystick:
    788.                     return GetKey(device.Primary2DAxisClick, type);
    789.  
    790.                 case ViveKnuckleKeyCodes.JoystickTouch:
    791.                     return GetKey(device.Primary2DAxisTouch, type);
    792.             }
    793.  
    794.             return false;
    795.         }
    796.    
    797.         static bool GetKey(GearVrKeyCodes key,HandType hand, GetKeyType type)
    798.         {
    799.             if (!HandValid(hand) || key == GearVrKeyCodes.None) return false;
    800.  
    801.             var device = hand == HandType.Left ? LeftInput : RightInput;
    802.  
    803.             if (!XrPresent) return SimGetKey(key, type);
    804.        
    805.             switch (key)
    806.             {
    807.                 case GearVrKeyCodes.Trigger:
    808.                     return GetKey(device.TriggerButton, type);
    809.                 case GearVrKeyCodes.Touchpad:
    810.                     return GetKey(device.Primary2DAxisClick, type);
    811.                 case GearVrKeyCodes.TouchpadTouch:
    812.                     return GetKey(device.Primary2DAxisTouch, type);
    813.             }
    814.  
    815.             return false;
    816.         }
    817.         #endregion
    818.  
    819.         #region Sim GetKey methods
    820.         static bool SimGetKey(RiftKeyCodes key, GetKeyType type)
    821.         {
    822.             if (key == RiftKeyCodes.None) return false;
    823.  
    824.             switch (type)
    825.             {
    826.                 case GetKeyType.GetDown:
    827.                     return Input.GetKeyDown(GetSimKeyId(key));
    828.                 case GetKeyType.GetUp:
    829.                     return Input.GetKeyUp(GetSimKeyId(key));
    830.                 default:
    831.                     return Input.GetKey(GetSimKeyId(key));
    832.             }
    833.        
    834.         }
    835.    
    836.         static bool SimGetKey(ViveKeyCodes key, GetKeyType type)
    837.         {
    838.             if (key == ViveKeyCodes.None) return false;
    839.  
    840.             bool GetCombo(KeyCode a, KeyCode b)
    841.             {
    842.                 switch (type)
    843.                 {
    844.                     case GetKeyType.GetDown:
    845.                         return Input.GetKeyDown(a) && Input.GetKeyDown(b);
    846.                     case GetKeyType.GetUp:
    847.                         return Input.GetKeyUp(a) && Input.GetKeyUp(b);
    848.                     default:
    849.                         return Input.GetKey(a) && Input.GetKey(b);
    850.                 }
    851.             }
    852.  
    853.             switch (key)
    854.             {
    855.                 case ViveKeyCodes.TrackpadRightUp:
    856.                     return GetCombo(KeyCode.D, KeyCode.W);
    857.                 case ViveKeyCodes.TrackpadLeftDown:
    858.                     return GetCombo(KeyCode.A, KeyCode.S);
    859.                 case ViveKeyCodes.TrackpadLeftUp:
    860.                     return GetCombo(KeyCode.A, KeyCode.W);
    861.                 case ViveKeyCodes.TrackpadRightDown:
    862.                     return GetCombo(KeyCode.D, KeyCode.S);
    863.             }
    864.                
    865.             switch (type)
    866.             {
    867.                 case GetKeyType.GetDown:
    868.                     return Input.GetKeyDown(GetSimKeyId(key));
    869.                 case GetKeyType.GetUp:
    870.                     return Input.GetKeyUp(GetSimKeyId(key));
    871.                 default:
    872.                     return Input.GetKey(GetSimKeyId(key));
    873.             }
    874.         }
    875.    
    876.         static bool SimGetKey(ViveKnuckleKeyCodes key, GetKeyType type)
    877.         {
    878.             if (key == ViveKnuckleKeyCodes.None) return false;
    879.             switch (type)
    880.             {
    881.                 case GetKeyType.GetDown:
    882.                     return Input.GetKeyDown(GetSimKeyId(key));
    883.                 case GetKeyType.GetUp:
    884.                     return Input.GetKeyUp(GetSimKeyId(key));
    885.                 default:
    886.                     return Input.GetKey(GetSimKeyId(key));
    887.             }
    888.         }
    889.    
    890.         static bool SimGetKey(GearVrKeyCodes key, GetKeyType type)
    891.         {
    892.             if (key == GearVrKeyCodes.None) return false;
    893.             switch (type)
    894.             {
    895.                 case GetKeyType.GetDown:
    896.                     return Input.GetKeyDown(GetSimKeyId(key));
    897.                 case GetKeyType.GetUp:
    898.                     return Input.GetKeyUp(GetSimKeyId(key));
    899.                 default:
    900.                     return Input.GetKey(GetSimKeyId(key));
    901.             }
    902.         }
    903.         #endregion
    904.    
    905.         #region Simulator KeyId methods
    906.         static KeyCode GetSimKeyId(RiftKeyCodes key)
    907.         {
    908.             switch (key)
    909.             {
    910.                 case RiftKeyCodes.Trigger:
    911.                     return KeyCode.Mouse1;
    912.                 case RiftKeyCodes.Grip:
    913.                     return KeyCode.Mouse0;
    914.                 case RiftKeyCodes.Menu:
    915.                     return KeyCode.KeypadEnter;
    916.                 case RiftKeyCodes.ButtonOne:
    917.                     return KeyCode.E;
    918.                 case RiftKeyCodes.ButtonTwo:
    919.                     return KeyCode.Q;
    920.            
    921.                 case RiftKeyCodes.ThumbStick:
    922.                     return KeyCode.End;
    923.                 case RiftKeyCodes.ButtonOneTouch:
    924.                     return KeyCode.Alpha1;
    925.                 case RiftKeyCodes.ButtonTwoTouch:
    926.                     return KeyCode.Alpha3;
    927.                 case RiftKeyCodes.ThumbStickTouch:
    928.                     return KeyCode.X;
    929.             }
    930.  
    931.             return KeyCode.Mouse0;
    932.         }
    933.    
    934.         static KeyCode GetSimKeyId(ViveKeyCodes key)
    935.         {
    936.             switch (key)
    937.             {
    938.                 case ViveKeyCodes.Trigger:
    939.                     return KeyCode.Mouse1;
    940.                 case ViveKeyCodes.Grip:
    941.                     return KeyCode.Mouse0;
    942.                 case ViveKeyCodes.Menu:
    943.                     return KeyCode.KeypadEnter;
    944.  
    945.                 case ViveKeyCodes.Trackpad:
    946.                     return KeyCode.End;
    947.  
    948.                 case ViveKeyCodes.TrackpadUp:
    949.                     return KeyCode.W;
    950.                 case ViveKeyCodes.TrackpadDown:
    951.                     return KeyCode.S;
    952.                 case ViveKeyCodes.TrackpadLeft:
    953.                     return KeyCode.A;
    954.                 case ViveKeyCodes.TrackpadRight:
    955.                     return KeyCode.D;
    956.             }
    957.  
    958.             return KeyCode.Mouse0;
    959.         }
    960.    
    961.         static KeyCode GetSimKeyId(ViveKnuckleKeyCodes key)
    962.         {
    963.             switch (key)
    964.             {
    965.                 case ViveKnuckleKeyCodes.Trigger:
    966.                     return KeyCode.Mouse1;
    967.                 case ViveKnuckleKeyCodes.Grip:
    968.                     return KeyCode.Mouse0;
    969.                 case ViveKnuckleKeyCodes.Primary:
    970.                     return KeyCode.E;
    971.                 case ViveKnuckleKeyCodes.Alternate:
    972.                     return KeyCode.Q;
    973.            
    974.                 case ViveKnuckleKeyCodes.Joystick:
    975.                     return KeyCode.End;
    976.                 case ViveKnuckleKeyCodes.JoystickTouch:
    977.                     return KeyCode.X;
    978.             }
    979.  
    980.             return KeyCode.Mouse0;
    981.         }
    982.    
    983.         static KeyCode GetSimKeyId(GearVrKeyCodes key)
    984.         {
    985.             switch (key)
    986.             {
    987.                 case GearVrKeyCodes.Trigger:
    988.                     return KeyCode.Mouse1;
    989.                 case GearVrKeyCodes.Touchpad:
    990.                     return KeyCode.End;
    991.                 case GearVrKeyCodes.TouchpadTouch:
    992.                     return KeyCode.X;
    993.             }
    994.  
    995.             return KeyCode.Mouse0;
    996.         }
    997.    
    998.         static Vector2 GetSim2DAxis()
    999.         {
    1000.             float x = 0, y = 0;
    1001.        
    1002.             if (Input.GetKey(KeyCode.D))
    1003.             {
    1004.                 x = -1;
    1005.             }
    1006.             else if (Input.GetKey(KeyCode.A))
    1007.             {
    1008.                 x = 1;
    1009.             }
    1010.        
    1011.             if (Input.GetKey(KeyCode.S))
    1012.             {
    1013.                 y = -1;
    1014.             }
    1015.             else if (Input.GetKey(KeyCode.W))
    1016.             {
    1017.                 y = 1;
    1018.             }
    1019.  
    1020.             return new Vector2(x, y);
    1021.         }
    1022.    
    1023.         static float GetSim1DAxis()
    1024.         {
    1025.             float y = 0;
    1026.        
    1027.             if (Input.GetKey(KeyCode.UpArrow))
    1028.             {
    1029.                 y = -1;
    1030.             }
    1031.             else if (Input.GetKey(KeyCode.DownArrow))
    1032.             {
    1033.                 y = 1;
    1034.             }
    1035.  
    1036.             return y;
    1037.         }
    1038.         #endregion
    1039.  
    1040.         #region Trackpad methods
    1041.         static bool GetTrackpad(ControllerInputs device,TrackpadDirection dir, GetKeyType type)
    1042.         {
    1043.  
    1044.             switch (type)
    1045.             {
    1046.                 case GetKeyType.Get:
    1047.                     if (!device.Primary2DAxisClick.Pressed) return false;
    1048.                     break;
    1049.                 case GetKeyType.GetDown:
    1050.                     if (!device.Primary2DAxisClick.Down) return false;
    1051.                     break;
    1052.                 case GetKeyType.GetUp:
    1053.                     if (!device.Primary2DAxisClick.Up) return false;
    1054.                     break;
    1055.             }
    1056.        
    1057.             return GetTrackpadDirection(device.Primary2DAxis, dir);
    1058.         }
    1059.  
    1060.         static bool GetTrackpadDirection(Vector2 curAxis,TrackpadDirection dir)
    1061.         {
    1062.             switch (dir)
    1063.             {
    1064.                 case TrackpadDirection.Left:
    1065.                     //if left and not a diagonal
    1066.                     if (curAxis.x < -0.65f &&
    1067.                         curAxis.y < 0.65f && curAxis.y > -0.65f)
    1068.                     {
    1069.                         //Debug.Log("Trackpad - Pressed Left");
    1070.                         return true;
    1071.                     }
    1072.                     break;
    1073.                 case TrackpadDirection.Right:
    1074.                     //if right and not a diagonal
    1075.                     if (curAxis.x > 0.65f &&
    1076.                         curAxis.y < 0.65f && curAxis.y > -0.65f)
    1077.                     {
    1078.                         //Debug.Log("Trackpad - Pressed Right");
    1079.                         return true;
    1080.                     }
    1081.                     break;
    1082.                 case TrackpadDirection.Up:
    1083.                     //if up and not a diagonal
    1084.                     if (curAxis.y > 0.65f &&
    1085.                         curAxis.x > -0.65f && curAxis.x < 0.65f)
    1086.                     {
    1087.                         //Debug.Log("Trackpad - Pressed up");
    1088.                         return true;
    1089.                     }
    1090.                     break;
    1091.                 case TrackpadDirection.Down:
    1092.                     //if down and not a diagonal
    1093.                     if (curAxis.y < -0.65f &&
    1094.                         curAxis.x > -0.65f && curAxis.x < 0.65f)
    1095.                     {
    1096.                         //Debug.Log("Trackpad - Pressed Down");
    1097.                         return true;
    1098.                     }
    1099.                     break;
    1100.                 case TrackpadDirection.LeftUp:
    1101.                     if (curAxis.x < -0.65f && curAxis.y > 0.65f)
    1102.                     {
    1103.                         //Debug.Log("Trackpad - Pressed LeftUp");
    1104.                         return true;
    1105.                     }
    1106.                     break;
    1107.                 case TrackpadDirection.RightUp:
    1108.                     if (curAxis.x > 0.65f && curAxis.y > 0.65f)
    1109.                     {
    1110.                         //Debug.Log("Trackpad - Pressed RightUp");
    1111.                         return true;
    1112.                     }
    1113.                     break;
    1114.                 case TrackpadDirection.LeftDown:
    1115.                     if (curAxis.x < -0.4f && curAxis.y < -0.65f)
    1116.                     {
    1117.                         //Debug.Log("Trackpad - Pressed LeftDown");
    1118.                         return true;
    1119.                     }
    1120.                     break;
    1121.                 case TrackpadDirection.RightDown:
    1122.                     if (curAxis.x > 0.4f && curAxis.y < -0.65f)
    1123.                     {
    1124.                         //Debug.Log("Trackpad - Pressed RightDown");
    1125.                         return true;
    1126.                     }
    1127.                     break;
    1128.             }
    1129.        
    1130.             return false;
    1131.         }
    1132.         #endregion
    1133.  
    1134.         #region Haptics
    1135.  
    1136.         public static void HapticImpulse(HandType hand,float amplitude = 0.5f, float duration = 0.2f, uint channel = 0)
    1137.         {
    1138.             if (!XrPresent) return;
    1139.             Impulse(hand == HandType.Left ? LeftHand : RightHand, amplitude, duration, channel);
    1140.         }
    1141.  
    1142.         static void Impulse(InputDevice device,float amplitude, float duration, uint channel)
    1143.         {
    1144.             if (!device.TryGetHapticCapabilities(out var capabilities)) return;
    1145.             if (capabilities.supportsImpulse)
    1146.             {
    1147.                 device.SendHapticImpulse(channel, amplitude, duration);
    1148.             }
    1149.         }
    1150.  
    1151.         #endregion
    1152.    
    1153.         static bool HandValid(HandType hand)
    1154.         {
    1155.             switch (hand)
    1156.             {
    1157.                 case HandType.Left:
    1158.                     return LeftHand.isValid;
    1159.                 default:
    1160.                     return RightHand.isValid;
    1161.             }
    1162.         }
    1163.     }
    1164.  
    1165.     [System.Serializable]
    1166.     public class VrKeyCode
    1167.     {
    1168.         public bool UseKnuckles = true;
    1169.    
    1170.         public RiftKeyCodes OculusKey = RiftKeyCodes.Trigger;
    1171.         public ViveKeyCodes ViveKey = ViveKeyCodes.Trigger;
    1172.         public ViveKnuckleKeyCodes KnuckleKey = ViveKnuckleKeyCodes.Trigger;
    1173.         public GearVrKeyCodes GearVrKey = GearVrKeyCodes.Trigger;
    1174.    
    1175.         public HandType OculusHand = HandType.Right;
    1176.         public HandType ViveHand = HandType.Right;
    1177.         public HandType KnuclesHand = HandType.Right;
    1178.         public HandType GearVrHand = HandType.Right;
    1179.    
    1180.    
    1181.         public bool ExpandInEditor = true;
    1182.     }
    1183.  
    1184. }
    1185.  
    1186.  
    Editor code example:

    Code (CSharp):
    1.                         EditorGUILayout.LabelField(varName);
    2.                    
    3.                         if(!i.VrKeyCode.ExpandInEditor) return;
    4.  
    5.                         EditorGUILayout.BeginVertical("box");
    6.                    
    7.  
    8.                         BoolSelector(ref i.VrKeyCode.UseKnuckles, "Use Vive knuckle mapping",150);
    9.                    
    10.                         EditorGUILayout.BeginHorizontal("helpbox");
    11.                         EditorGUILayout.LabelField("Oculus", GUILayout.Width(90));
    12.                         i.VrKeyCode.OculusKey = (RiftKeyCodes) EditorGUILayout.EnumPopup(i.VrKeyCode.OculusKey);
    13.                         EditorGUILayout.LabelField("Hand", GUILayout.Width(40));
    14.                         i.VrKeyCode.OculusHand = (HandType) EditorGUILayout.EnumPopup(i.VrKeyCode.OculusHand);
    15.                         EditorGUILayout.EndHorizontal();
    16.  
    17.                         if (i.VrKeyCode.UseKnuckles)
    18.                         {
    19.                             EditorGUILayout.BeginHorizontal("helpbox");
    20.                             EditorGUILayout.LabelField("Vive Knuckles", GUILayout.Width(90));
    21.                             i.VrKeyCode.KnuckleKey = (ViveKnuckleKeyCodes) EditorGUILayout.EnumPopup(i.VrKeyCode.KnuckleKey);
    22.                             EditorGUILayout.LabelField("Hand", GUILayout.Width(40));
    23.                             i.VrKeyCode.KnuclesHand = (HandType) EditorGUILayout.EnumPopup(i.VrKeyCode.KnuclesHand);
    24.                             EditorGUILayout.EndHorizontal();
    25.                         }
    26.                         else
    27.                         {
    28.                             EditorGUILayout.BeginHorizontal("helpbox");
    29.                             EditorGUILayout.LabelField("Vive", GUILayout.Width(90));
    30.                             i.VrKeyCode.ViveKey = (ViveKeyCodes) EditorGUILayout.EnumPopup(i.VrKeyCode.ViveKey);
    31.                             EditorGUILayout.LabelField("Hand", GUILayout.Width(40));
    32.                             i.VrKeyCode.ViveHand = (HandType) EditorGUILayout.EnumPopup(i.VrKeyCode.ViveHand);
    33.                             EditorGUILayout.EndHorizontal();
    34.                         }
    35.  
    36.                         EditorGUILayout.BeginHorizontal("helpbox");
    37.                         EditorGUILayout.LabelField("GearVr", GUILayout.Width(90));
    38.                         i.VrKeyCode.GearVrKey = (GearVrKeyCodes) EditorGUILayout.EnumPopup(i.VrKeyCode.GearVrKey);
    39.                         EditorGUILayout.LabelField("Hand", GUILayout.Width(40));
    40.                         i.VrKeyCode.GearVrHand = (HandType) EditorGUILayout.EnumPopup(i.VrKeyCode.GearVrHand);
    41.                         EditorGUILayout.EndHorizontal();
    42.                    
    43.                         EditorGUILayout.EndVertical();
    Code (CSharp):
    1.         public static void BoolSelector(ref bool var, string varName = "", float width = -1)
    2.         {
    3.             string[] options = {"True","False"};
    4.             int selected = var ? 0 : 1;
    5.  
    6.             if (width <= 0)
    7.             {
    8.                 selected = varName.Equals("")
    9.                     ? EditorGUILayout.Popup(selected, options)
    10.                     : EditorGUILayout.Popup(varName, selected, options);
    11.             }
    12.             else
    13.             {
    14.                 if (varName.Equals(""))
    15.                 {
    16.                     selected = EditorGUILayout.Popup(selected, options, GUILayout.Width(width));
    17.                 }
    18.                 else
    19.                 {
    20.                     EditorGUILayout.BeginHorizontal();
    21.                     {
    22.                         EditorGUILayout.LabelField(varName, GUILayout.Width(width));
    23.                         selected = EditorGUILayout.Popup(selected, options);
    24.                     }
    25.                     EditorGUILayout.EndHorizontal();
    26.                 }
    27.             }
    28.  
    29.  
    30.             var = selected == 0;
    31.         }
    You got to call the VrInput.Init(gameObject); method in your PersistentEngine or GameEngine script (or delete that and just added it to your GameEngine object I guess).
     
    Last edited: May 8, 2020
  5. Alverik

    Alverik

    Joined:
    Apr 15, 2016
    Posts:
    409
    Haven't used it in a while but it would go like this:

    Code (CSharp):
    1.      
    2. var hand = HandType.Left;
    3.  
    4. var gripInput = new VrKeyCode
    5.             {
    6.                 OculusKey = RiftKeyCodes.Grip,
    7.                 ViveKey = ViveKeyCodes.Grip,
    8.                 KnuckleKey = ViveKnuckleKeyCodes.Grip,
    9.                 GearVrKey = GearVrKeyCodes.Touchpad,
    10.                 OculusHand = hand,
    11.                 ViveHand = hand,
    12.                 KnuclesHand = hand,
    13.                 GearVrHand = hand
    14.             };
    15.  
    16.                 if (VrInput.GetKey(gripInput, GetKeyType.GetDown))
    17.                 {
    18.     //grip press down
    19.                 }
    20.  
    21.  
    The intention is you can select different buttons on different devices (and different hands), and get a different result based on the device connected. And you can make the keycode public so you can select the buttons and hands per device on your script, or change them via UI, etc. (But there are some static methods to check specific devices too).
    Hope later I can fix it so it knows if you are using the Vive knuckles right away (probably verifying the device names at the beginning too).

    And haptics:

    Code (CSharp):
    1.  
    2.  
    3. var amplitud = .5f;
    4. var duration = .2f;
    5. var channel = 0;
    6.  
    7. VrInput.HapticImpulse(Hand, amplitude, duration, (uint) channel);
    8.  
     
    Last edited: May 8, 2020
  6. wpetillo

    wpetillo

    Joined:
    May 23, 2017
    Posts:
    19
    Here is a simple way to get XR input on the Oculus Quest, haven't tested yet if it also works on Vive. First getting basic button presses:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Events;
    4. using UnityEngine.XR;
    5. using UnityEngine.XR.Interaction.Toolkit;
    6.  
    7. [Serializable] public class BoolEvent : UnityEvent<bool> { }
    8.  
    9. public class XRInput : MonoBehaviour
    10. {
    11.     [SerializeField] XRController controller;      
    12.     [SerializeField] XRBinding[] bindings;
    13.              
    14.     void Update()
    15.     {            
    16.         foreach (var binding in bindings)
    17.             binding.Update(controller.inputDevice);
    18.     }
    19. }
    20.  
    21. [Serializable]
    22. public class XRBinding
    23. {
    24.     [SerializeField] XRButton button;
    25.     [SerializeField] PressType condition;
    26.     [SerializeField] UnityEvent OnActive;
    27.  
    28.     bool isPressed;
    29.     bool wasPressed;
    30.  
    31.     public void Update(InputDevice device)
    32.     {
    33.         device.TryGetFeatureValue(XRStatics.GetFeature(button), out isPressed);
    34.      
    35.         switch (condition)
    36.         {
    37.             case PressType.Continuous: if (isPressed) OnActive.Invoke(); break;
    38.             case PressType.Begin: if (isPressed && !wasPressed) OnActive.Invoke(); break;
    39.             case PressType.End: if (!isPressed && wasPressed) OnActive.Invoke(); break;
    40.         }
    41.      
    42.         wasPressed = isPressed;
    43.     }
    44. }
    45.  
    46. public static class XRStatics
    47. {
    48.     public static InputFeatureUsage<bool> GetFeature(XRButton button)
    49.     {
    50.         switch (button)
    51.         {
    52.             case XRButton.Trigger: return CommonUsages.triggerButton;
    53.             case XRButton.Grip: return CommonUsages.gripButton;
    54.             case XRButton.Primary: return CommonUsages.primaryButton;
    55.             case XRButton.PrimaryTouch: return CommonUsages.primaryTouch;
    56.             case XRButton.Secondary: return CommonUsages.secondaryButton;
    57.             case XRButton.SecondaryTouch: return CommonUsages.secondaryTouch;
    58.             case XRButton.Primary2DAxisClick: return CommonUsages.primary2DAxisClick;
    59.             case XRButton.Primary2DAxisTouch: return CommonUsages.primary2DAxisTouch;
    60.             case XRButton.Thumbrest: return CommonUsages.thumbrest;
    61.             case XRButton.Menu: return CommonUsages.menuButton;
    62.             default: Debug.LogError(button + " not found"); return CommonUsages.primaryButton;
    63.         }
    64.     }
    65. }
    66.  
    67. public enum PressType
    68. {
    69.     Begin, End, Continuous
    70. }
    71.  
    72. public enum XRButton
    73. {
    74.     Trigger,
    75.     Grip,
    76.     Primary,
    77.     PrimaryTouch,
    78.     Secondary,
    79.     SecondaryTouch,
    80.     Primary2DAxisClick,
    81.     Primary2DAxisTouch,
    82.     Thumbrest,
    83.     Menu
    84. }
    Setup by attaching this script as a component to any object and drop in a hand object that has an XRController component attached. Assign as many bindings as you like. For each binding, select which button to use and whether to respond on the first frame of a press (or touch), the last frame, or every frame.

    Next, getting joystick position:

    Code (CSharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using UnityEngine.Events;
    5. using UnityEngine.XR;
    6. using UnityEngine.XR.Interaction.Toolkit;
    7.  
    8. [Serializable] public class Vector2Event : UnityEvent<Vector2> { }
    9.  
    10. public class XRInput2D : MonoBehaviour
    11. {
    12.     [SerializeField] XRController controller;    
    13.     [SerializeField] Vector2Event OnActive;
    14.    
    15.     Vector2 value;
    16.                
    17.     public void GetAxisValue()
    18.     {      
    19.         controller.inputDevice.TryGetFeatureValue(CommonUsages.primary2DAxis, out value);
    20.         OnActive.Invoke(value);
    21.     }
    22. }
    23.  
    Setup by attaching to any object, preferably the same as XRInput. Create a binding in XRInput setting the button field to Primary2DAxisTouch or Primary2DAxisClick, the condition field to Continuous, and calling XRInput2D.GetAxisValue(). Whenever there is input, XRInput2D will then send out the Vector2 value via OnActive.
     
    Last edited: May 11, 2020
  7. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    140
    I've implemented a system for detecting and configuring controllers in my project using InputDevices.deviceConnected, and it's been working great from the editor (2019.2.11f1). Unfortunately, deviceConnected is never called from builds. If a (Vive) controller is off when the app is launched, it'll never be detected until you completely restart the app with the controller already powered on.

    @StayTalm_Unity Is there something i'm missing?

    Code (CSharp):
    1.  
    2. private List<InputDevice> allInputDevices = new List<InputDevice>();
    3.  
    4. //Called once from a singleton game manager after splash screens are initialized.
    5. public void Initialize() {
    6.     XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale);
    7.  
    8.     GetInputDevices();
    9.  
    10.     InputDevices.deviceConnected += OnInputDeviceConnected;
    11.     InputDevices.deviceDisconnected += OnInputDeviceDisconnected;
    12. }
    13.  
    14. private void GetInputDevices() {
    15.     InputDevices.GetDevices(allInputDevices);
    16.  
    17.     for (int i = 0; i < allInputDevices.Count; i++) {
    18.         SortInputDevice(allInputDevices[i]);
    19.     }
    20.    
    21.     allInputDevices.Clear();
    22. }
    23.  
    24. private void OnInputDeviceConnected(InputDevice obj) {
    25.     SortInputDevice(obj);
    26. }
    27.  
    28. private void OnInputDeviceDisconnected(InputDevice obj) {
    29.     if(obj == null) { return; }
    30.    
    31.     //Unload associated visuals and events.
    32.    
    33.     Debug.Log("Disconnected Device: " + obj.name + " of role: " + obj.role);
    34. }
    35.  
    36. private void SortInputDevice(InputDevice obj) {
    37.     //Sorts input device by role and configures visuals & control mapping as required
    38. }
    39.  
     
  8. RetroFlight

    RetroFlight

    Joined:
    Nov 16, 2019
    Posts:
    35
    Thanks for posting all of this... I have a question on how you would use it in another script. How would you, say, write an if statement for the trigger being pulled? I have spent the whole day trying to figure it out before asking. I am good with basic C# but still very green.

    Thanks!
     
  9. wpetillo

    wpetillo

    Joined:
    May 23, 2017
    Posts:
    19
    You wouldn't. The point of the UnityEvent based approach that the script using is to prevent other scripts from being dependent on your input system--or your input system dependent on other game logic. Instead, have public methods in your other scripts that respond to trigger presses (at the beginning of the press, the end, or continuously each frame), and connect them to the input component via the inspector.

    The advantages of a decoupled approach are that it allows for re-usability (for example, an AI character, a player with a VR trackpad, and a regular keyboard to all share the same logic for movement, animation, etc.) and makes it possible to limit the scope of a script so that once it is fully tested, streamlined, and fleshed out to include low-hanging variations it is DONE and never has to be edited or really thought about much again--because any additional features are out of scope and better added through a separate script.

    As an example, here is a link to an open-source character controller I am working on: https://github.com/Will9371/Character-Template/tree/master/Assets/Playcraft/VR. Parts of the repo are very much a work in progress (especially the 3rd person animations), but nearly all of it follows the same pattern, and the section I linked to includes controlling a third person humanoid character with the joystick on a Quest (like in Moss).
     
  10. Reahreic

    Reahreic

    Joined:
    Mar 23, 2011
    Posts:
    140
    Integrated with the singleton detection script i previously posted we register and manage controller events from anywhere using helper methods for the event type. (Button, Trigger, Touchpad) Essentially having one start and one end 'listening for event' method that's responsible for initializing the actual event attachment. This allows us to keep a list of registered events so that we can apply them automagically to a newly added/reconnected controller as part of it's initialization.

    Because we keep a tracked list of active controllers, when we call the method to attach the event we identify the controller via it's 'handedness' (left, right, both), which component (button, trigger, touchpad) we wan't to listen to using it's 'identity', the specific component event we want to listen for, and a callback method.

    Our Controller classes (Base, Derived), which are what is initialized and tracked as the 'controller' in my first paragraph, is then responsible for listening to the physical device, broadcasting it's list of active events, and managing it's own visual model.

    It's a tad more complicated that just directly tying into a controller, but it works well for handling controllers in a platform agnostic way allowing me to not need to revisit this part of the code as i develop my application. And if i add a new VR platform, i don't need to go back and anything in my game except add a new controller type.

    I can't paste all the code here as the UserInputModule is not open source (up to our client) and around 3k lines of code, but the above should give you a high level idea to work with, and the below is the basic 'controller level' functionality. (took like 60 mins to extract from our module)

    Example:
    Code (CSharp):
    1. //Acquire device tracking data value example, Look into 'UnityEngine.XR.CommonUsages' for all the things you could listen for
    2. Vector3 pos = Vector3.zero;
    3. if (!UnityEngine.XR.InputDevice.TryGetFeatureValue(UnityEngine.XR.CommonUsages.devicePosition, out pos)) {
    4.     Debug.LogWarning("Unable to get feature: '" + UnityEngine.XRCommonUsages.devicePosition.ToString());
    5. }
    6.          
    7. //Acquire state for button identified by  identity -> UnityEngine.XR.CommonUsages.primaryButton
    8. bool buttonState = false;
    9. if (UnityEngine.XR.InputDevice.TryGetFeatureValue(identity, out outState)) {
    10.     Debug.LogWarning("Unable to get feature: '" + UnityEngine.XRCommonUsages.primaryButton.ToString());
    11. }
    12.  
    13. //Acquire state for trigger.
    14. //Note the trigger can respond as both a slider (float) and a button (bool), depending on which identity you use
    15. //identity -> UnityEngine.XR.CommonUsages.trigger or .triggerButton
    16. float triggerState = 0f;
    17. if (parent.device.TryGetFeatureValue(identity, out outState)) {
    18.     Debug.LogWarning("Unable to get feature: '" + UnityEngine.XRCommonUsages.trigger .ToString());
    19. }
    20.  
    21. //Touchpad support is a essentially the same see the 'TryGetCustomTouchpadValues' method below, however because we detect gesture, touch and position, press and press position with it we had to extend it's identity to handle the different input methods being tracked and their return data types. (bool, vector3, customGestureEnum)
    22.  
    23. //As such the below is an excerpt and won't work for you as-is, but should give you a mental model to work from.
    24. public class ControllerTouchPad{
    25.     public Action<ControllerTouchPad> OnStartTouch;
    26.     private void OnTouchPadStartTouch() {
    27.         OnStartTouch?.Invoke(this);
    28.     }
    29.  
    30.     private TouchPadEventData _currentState = TouchPadEventData.none;
    31.     public new TouchPadEventData state {
    32.         get {
    33.             return _currentState;
    34.         }
    35.         private set {
    36.             //Ensures changes can be determined prior to updating values for simultaneous events
    37.             bool isStartTouch = value.isTouching && !_currentState.isTouching;
    38.             bool isTouching = value.isTouching && _currentState.isTouching;
    39.             bool isEndTouch = !value.isTouching && _currentState.isTouching;
    40.          
    41.             bool posChanged = value.touchPosition != _currentState.touchPosition;
    42.  
    43.             bool isStartPress = value.isPressing && !_currentState.isPressing;
    44.             bool isPressing = value.isPressing && _currentState.isPressing;
    45.             bool isEndPress = !value.isPressing && _currentState.isPressing;
    46.  
    47.             _currentState = value;
    48.  
    49.             if (isStartTouch) {
    50.                 //OnTouchPadStartTouch();
    51.  
    52.             } else if (isTouching) {
    53.                 //OnTouchPadTouching();
    54.  
    55.             if (posChanged) {
    56.                 //OnTouchPadPositionChange(); <- this is where you can detect gestures such as swiping
    57.             }
    58.  
    59.             } else if (isEndTouch) {
    60.                 //OnTouchPadEndTouch();
    61.             }
    62.  
    63.             if (isStartPress) {
    64.                 //OnTouchPadPress();
    65.  
    66.             } else if (isPressing) {
    67.                 //OnTouchPadHeldDown();
    68.  
    69.             } else if (isEndPress) {
    70.                 //OnTouchPadRelease();
    71.             }
    72.         }
    73.     }
    74.  
    75.     private update(){
    76.         state = TryGetCustomTouchpadValues();
    77.     }
    78.     private TouchPadEventData TryGetCustomTouchpadValues() {
    79.         bool touchState = false;
    80.         supportsTouch = parent.device.TryGetFeatureValue(CommonUsages.primary2DAxisTouch, out touchState);
    81.  
    82.         bool pressState = false;
    83.         supportsPress = parent.device.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out pressState);
    84.  
    85.         Vector2 touchPos = Vector2.zero;
    86.         supportsPosition = parent.device.TryGetFeatureValue(CommonUsages.primary2DAxis, out touchPos);
    87.  
    88.         return new TouchPadEventData(touchState, pressState, touchPos, GetTouchpadQuadrant(touchPos), state.gesture);
    89.     }
    90. }
    Edit: Fixed a stupid
     
    Last edited: Jun 12, 2020
  11. Riiich

    Riiich

    Joined:
    Sep 30, 2014
    Posts:
    6
    How do you handle controller disconnects? :D
     
  12. josrodes

    josrodes

    Joined:
    Nov 15, 2017
    Posts:
    9
    Code (CSharp):
    1.  
    2.     private void Awake()
    3.     {
    4.         InputDevices.deviceConnected += InputDevices_deviceConnected;
    5.         InputDevices.deviceDisconnected += InputDevices_deviceDisconnected;
    6.         InputDevices.deviceConfigChanged += InputDevices_deviceConfigChanged;
    7.     }
    8.  
    9.     private void OnDestroy()
    10.     {
    11.         InputDevices.deviceConnected -= InputDevices_deviceConnected;
    12.         InputDevices.deviceDisconnected -= InputDevices_deviceDisconnected;
    13.         InputDevices.deviceConfigChanged -= InputDevices_deviceConfigChanged;
    14.     }
    15.  
    16.     private void InputDevices_deviceDisconnected(InputDevice device)
    17.     {
    18.         CheckForControllers();
    19.     }
    20.  
    21.     private void InputDevices_deviceConfigChanged(InputDevice device)
    22.     {
    23.         CheckForControllers();
    24.     }
    25.  
    26.     private void InputDevices_deviceConnected(InputDevice device)
    27.     {
    28.         CheckForControllers();
    29.     }
    30.  
    31.    
    32. public void CheckForControllers()
    33.     {
    34.         bool controllerFound = false;
    35.  
    36.         List<InputDevice> leftHandDevices = new List<InputDevice>();
    37.         InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.Left, leftHandDevices);
    38.  
    39.         if (leftHandDevices.Count > 0)
    40.         {
    41.             controllerFound = true;
    42.         }
    43.        
    44.         List<InputDevice> rightHandDevices = new List<InputDevice>();
    45.         InputDevices.GetDevicesWithCharacteristics(InputDeviceCharacteristics.Right, rightHandDevices);
    46.         if (rightHandDevices.Count > 0)
    47.         {
    48.             controllerFound = true;
    49.         }
    50.        
    51.         if (!controllerFound)
    52.         {
    53.             //A controller is required, please reconnect to continue;
    54.         }
    55.     }
     
  13. stevendimmerse

    stevendimmerse

    Joined:
    Aug 7, 2018
    Posts:
    4
    This doesn't seem to be working on quest atm for the Stationary mode

    subSystem.GetTrackingOriginMode() == TrackingOriginModeFlags.Device is false

    XRDevice.GetTrackingSpaceType() == TrackingSpaceType.Stationary this is true

    For now im just using GetTrackingSpaceType

    using 2019.4.3 with xr 1.0.1 and oculus xr 1.4.0
     
  14. skidvis

    skidvis

    Joined:
    Jun 3, 2017
    Posts:
    1
    Hi, This sounds like a great idea.. can you provide an example of how you did this?

    [edit] I seem to have figured it out.. Is this how you do it?
    Code (CSharp):
    1. var _teleportationProvider = GetComponent<TeleportationProvider>();
    2. var teleportRequest = new TeleportRequest();
    3. teleportRequest.destinationPosition = newPosition.transform.position;
    4. _teleportationProvider.QueueTeleportRequest(teleportRequest);
     
    Last edited: Aug 2, 2020
unityunity