Advertisement
Guest User

UXRU : XR Tracker ( alpha )

a guest
Aug 30th, 2019
689
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 22.28 KB | None | 0 0
  1.  using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.XR;
  6.  
  7. namespace Utils.XR
  8. {
  9.     // Minimum requirments: Unity version 2019.2
  10.     // Based on: https://forum.unity.com/threads/any-example-of-the-new-2019-1-xr-input-system.629824/#post-4513171
  11.     // Note: install [ XR Legacy Input Helpers ] package
  12.  
  13.     public class XRTracker : MonoBehaviour
  14.     {
  15.                             //Keep this around to avoid creating heap garbage
  16.         static              List<InputDevice> devices = new List<InputDevice>();
  17.        
  18.         [Tooltip("UnityEngine.XR.InputDeviceRole")]
  19.         [SerializeField]    InputDeviceRole role = InputDeviceRole.Generic;
  20.  
  21.         [HideInInspector] public bool trackPosition = true;
  22.         [HideInInspector] public bool trackRotation = true;
  23.  
  24.         [HideInInspector]   public InputDevice trackedDevice;
  25.  
  26.         public UpdateFlags trackTransformation = UpdateFlags.Always;
  27.        
  28.         [Tooltip("By default local space is used")]
  29.         [SerializeField]    bool useWorldSpace = false;
  30.  
  31.         [HideInInspector]   public List<InputFeatureUsage> features = new List<InputFeatureUsage>();
  32.         [HideInInspector]   public List<string> featureNames;
  33.  
  34.         [HideInInspector]   public List<InputFeatureUsage<bool>> trackedButtons    = new List<InputFeatureUsage<bool>>();
  35.         [HideInInspector]   public List<bool> trackedButtons_pressed               = new List<bool>();
  36.         [HideInInspector]   public List<bool> trackedButtons_released              = new List<bool>();
  37.         [HideInInspector]   public List<bool> trackedButtons_state                 = new List<bool>();
  38.  
  39.         public bool HasFeature( string featureName, bool throwException = false )
  40.         {
  41.             // Feature validity is unknown when device is not connected
  42.             if( ! trackedDevice.isValid ) return false;
  43.  
  44.             // From when the device was connected and FeatureUsages was captured
  45.             bool has_feature = featureNames.Contains( featureName );
  46.  
  47.             if( ! has_feature && throwException )
  48.                
  49.                 throw new Exception("Unsupported feature " + featureName + " for device " + trackedDevice.name );
  50.  
  51.             return has_feature;
  52.         }
  53.  
  54.         public bool HasAxisPrimary() { return HasFeature( CommonUsages.primary2DAxis.name ); }
  55.         /// Returns primary Axis (2D) vector
  56.         public Vector2 GetAxisPrimary()
  57.         {
  58.             if( ! HasAxisPrimary() ) return Vector2.zero;
  59.  
  60.             Vector2 axis;
  61.  
  62.             if( ! trackedDevice.TryGetFeatureValue( CommonUsages.primary2DAxis, out axis ) )
  63.             {
  64.                 XRUtil.LogError("Failed to get feature value");
  65.                 return Vector2.zero;
  66.             }
  67.  
  68.             return axis;
  69.         }
  70.  
  71.         // public bool HasAxisSecondary() { return HasFeature( CommonUsages.secondary2DAxis.name ); }
  72.         // /// Returns secondary Axis (2D) vector
  73.         // public Vector2 GetAxisSecondary()
  74.         // {
  75.         //     if( ! HasAxisSecondary() ) return Vector2.zero;
  76.  
  77.         //     Vector2 axis;
  78.  
  79.         //     if( ! trackedDevice.TryGetFeatureValue( CommonUsages.secondary2DAxis, out axis ) )
  80.         //     {
  81.         //         XRUtil.LogError("Failed to get feature value");
  82.         //         return Vector2.zero;
  83.         //     }
  84.  
  85.         //     return axis;
  86.         // }
  87.  
  88.         public bool HasAxisTrigger() { return HasFeature( CommonUsages.trigger.name ); }
  89.         /// Returns trigger Axis (1D) value from 0 to 1 ( index finger )
  90.         public float GetAxisTrigger()
  91.         {  
  92.             // If trigger Axis is not supported, return it's button alternative when avalible
  93.             if( ! HasAxisTrigger() && HasFeature( CommonUsages.triggerButton.name ) )
  94.                 return GetButton( CommonUsages.triggerButton ) ? 1 : 0;
  95.  
  96.             float value;
  97.  
  98.             if( ! trackedDevice.TryGetFeatureValue( CommonUsages.trigger, out value ) )
  99.             {
  100.                 XRUtil.LogError("Failed to get feature value");
  101.                 return 0;
  102.             }
  103.  
  104.             return value;
  105.         }
  106.  
  107.         public bool HasAxisGrip() { return HasFeature( CommonUsages.grip.name ); }
  108.         /// Returns grip Axis (1D) value from 0 to 1
  109.         public float GetAxisGrip()
  110.         {
  111.             // If grip Axis is not supported, return it's button alternative when avalible
  112.             if( ! HasAxisGrip() && HasFeature( CommonUsages.gripButton.name ) )
  113.                 return GetButton( CommonUsages.gripButton ) ? 1 : 0;
  114.  
  115.             float value;
  116.  
  117.             if( ! trackedDevice.TryGetFeatureValue( CommonUsages.grip, out value ) )
  118.             {
  119.                 XRUtil.LogError("Failed to get feature value");
  120.                 return 0;
  121.             }
  122.  
  123.             return value;
  124.         }
  125.  
  126.         /// Returns true while the button is held down ( See XRTracker.Buttons )
  127.         public bool GetButton( InputFeatureUsage<bool> button )
  128.         {
  129.             int index = trackedButtons.IndexOf( button );
  130.             if( index == -1 ) TrackButton( button );
  131.             else return trackedButtons_state[ index ];
  132.             return false;
  133.         }
  134.  
  135.         /// Returns true during the frame the user pressed down the button ( See XRTracker.Buttons )
  136.         public bool GetButtonDown( InputFeatureUsage<bool> button )
  137.         {
  138.             int index = trackedButtons.IndexOf( button );
  139.             if( index == -1 ) TrackButton( button );
  140.             else return trackedButtons_pressed[ index ];
  141.             return false;
  142.         }
  143.  
  144.         /// Returns true the first frame the user releases the button ( See XRTracker.Buttons )
  145.         public bool GetButtonUp( InputFeatureUsage<bool> button )
  146.         {
  147.             int index = trackedButtons.IndexOf( button );
  148.             if( index == -1 ) TrackButton( button );
  149.             else return trackedButtons_released[ index ];
  150.             return false;
  151.         }
  152.  
  153.         void TrackButton( InputFeatureUsage<bool> button )
  154.         {
  155.             if( trackedButtons.Contains( button ) ) return;
  156.  
  157.             trackedButtons              .Add( button );
  158.             trackedButtons_pressed      .Add( false );
  159.             trackedButtons_released     .Add( false );
  160.             trackedButtons_state        .Add( false );
  161.         }
  162.  
  163.         static readonly float MinValue_Touch = 0.001f;
  164.         static readonly float MinValue_Button = 0.5f;
  165.  
  166.         bool GetCustomButtonValue( InputFeatureUsage<bool> usage )
  167.         {
  168.             float value = 0f;
  169.  
  170.             if( usage.name.Contains("_Grip") )      value = GetAxisGrip();
  171.             if( usage.name.Contains("_Trigger") )   value = GetAxisTrigger();
  172.            
  173.             if( usage.name.Contains("_Touch") )       return value >=  MinValue_Touch;
  174.             if( usage.name.Contains("_Button") )      return value >= MinValue_Button;
  175.  
  176.             return false;
  177.         }
  178.  
  179.         void UpdateButtons( bool reset )
  180.         {
  181.             for( int i = 0; i < trackedButtons.Count; ++i )
  182.             {
  183.                 if( reset )
  184.                 {
  185.                     trackedButtons_pressed[ i ] = false;
  186.                     trackedButtons_released[ i ] = false;
  187.                 }
  188.  
  189.                 InputFeatureUsage<bool> input_device = trackedButtons[ i ];
  190.  
  191.                 bool is_pressed = false;
  192.  
  193.                 if( CustomButtons.Contains( input_device ) )
  194.                 {
  195.                     is_pressed = GetCustomButtonValue( input_device );
  196.                 }
  197.                 else if( ! trackedDevice.TryGetFeatureValue( input_device, out is_pressed ) )
  198.                 {
  199.                     continue;
  200.                 }
  201.                
  202.                 if( trackedButtons_state[ i ] != is_pressed )
  203.                 {
  204.                     if( is_pressed )    trackedButtons_pressed[ i ] = true;
  205.                     else                trackedButtons_released[ i ] = true;
  206.                 }
  207.  
  208.                 trackedButtons_state[ i ] = is_pressed;
  209.             }
  210.         }
  211.  
  212.         void Awake()
  213.         {
  214.             trackedDevice = new InputDevice();
  215.             features = new List<InputFeatureUsage>();
  216.         }
  217.  
  218.         void OnEnable()
  219.         {
  220.             InputDevices.deviceConnected        += OnDeviceConnected;
  221.             InputDevices.deviceDisconnected     += OnDeviceDisconnected;
  222.             // // Application.onBeforeRender          += OnBeforeRender;
  223.  
  224.             InputDevices.GetDevicesWithRole( role, devices );
  225.  
  226.             if ( devices.Count > 0) OnDeviceConnected( devices[0] );
  227.         }
  228.  
  229.         void Start()
  230.         {
  231.  
  232.         }
  233.  
  234.         void OnDisable()
  235.         {
  236.             InputDevices.deviceConnected        -= OnDeviceConnected;
  237.             InputDevices.deviceDisconnected     -= OnDeviceDisconnected;
  238.             // Application.onBeforeRender          -= OnBeforeRender;
  239.         }
  240.  
  241.         bool oscillator = false;
  242.  
  243.         void Update()
  244.         {
  245.             if ( trackedDevice.isValid )
  246.             {
  247.                 if( trackTransformation.HasFlag( UpdateFlags.DuringUpdate ) )
  248.  
  249.                     TrackDeviceTransform( trackedDevice );
  250.  
  251.                 UpdateButtons( oscillator = ! oscillator );
  252.             }
  253.         }
  254.  
  255.         void OnBeforeRender()
  256.         {
  257.             if ( trackedDevice.isValid )
  258.             {
  259.                 if( trackTransformation.HasFlag( UpdateFlags.BeforeRender ) )
  260.  
  261.                     TrackDeviceTransform( trackedDevice );
  262.             }
  263.         }
  264.  
  265.         void OnDeviceConnected( InputDevice device )
  266.         {
  267.             if ( ! trackedDevice.isValid && device.role == role )
  268.             {
  269.                 trackedDevice = device;
  270.                
  271.                 if( trackedDevice.TryGetFeatureUsages( features ) )
  272.                    
  273.                     featureNames = features.Select( feature => feature.name ).ToList();
  274.  
  275.                 // TODO: add error reporting everywhere that uses a [TryGet"Something"] pattern
  276.                 else XRUtil.LogError("Failed to get feature usages");
  277.             }
  278.         }
  279.  
  280.         void OnDeviceDisconnected( InputDevice device )
  281.         {
  282.             if (device == trackedDevice)
  283.             {
  284.                 // Set current as empty
  285.                 trackedDevice = new InputDevice();
  286.             }
  287.         }
  288.  
  289.         void TrackDeviceTransform( InputDevice trackedDevice )
  290.         {
  291.             if( trackPosition )
  292.             {
  293.                 Vector3 position;
  294.                
  295.                 if ( trackedDevice.TryGetFeatureValue( CommonUsages.devicePosition, out position ) )
  296.                 {  
  297.                     if( useWorldSpace ) this.transform.position = position;
  298.                     else this.transform.localPosition = position;
  299.                 }
  300.             }
  301.  
  302.             if( trackRotation )
  303.             {
  304.                 Quaternion rotation;
  305.  
  306.                 if( trackedDevice.TryGetFeatureValue( CommonUsages.deviceRotation, out rotation ) )
  307.                 {
  308.                     if( useWorldSpace ) this.transform.rotation = rotation;
  309.                     else this.transform.localRotation = rotation;
  310.                 }
  311.             }
  312.         }
  313.  
  314.         [Flags]
  315.         public enum UpdateFlags
  316.         {
  317.             Never = 0,
  318.             DuringUpdate = 1 << 0,
  319.             BeforeRender = 1 << 1,
  320.             Always = -1
  321.         }
  322.  
  323.         // public static class Axis
  324.         // {
  325.         //     public static InputFeatureUsage<float> batteryLevel = CommonUsages.batteryLevel;
  326.         //     public static InputFeatureUsage<float> grip = CommonUsages.grip;
  327.         //     public static InputFeatureUsage<float> trigger = CommonUsages.trigger;
  328.         //     public static InputFeatureUsage<Vector2> primary2DAxis = CommonUsages.primary2DAxis;
  329.         // }
  330.  
  331.         public static class Buttons
  332.         {
  333.             // public static InputFeatureUsage<bool> isTracked = CommonUsages.isTracked;
  334.             public static InputFeatureUsage<bool> primaryButton         = CommonUsages.primaryButton;
  335.             public static InputFeatureUsage<bool> primaryTouch          = CommonUsages.primaryTouch;
  336.             public static InputFeatureUsage<bool> secondaryButton       = CommonUsages.secondaryButton;
  337.             public static InputFeatureUsage<bool> secondaryTouch        = CommonUsages.secondaryTouch;
  338.             public static InputFeatureUsage<bool> gripButton            = new InputFeatureUsage<bool>("_Grip_Button");
  339.             public static InputFeatureUsage<bool> gripTouch             = new InputFeatureUsage<bool>("_Grip_Touch");
  340.             public static InputFeatureUsage<bool> triggerButton         = new InputFeatureUsage<bool>("_Trigger_Button");
  341.             // Oculus Rift S - this is actually the trigger touch and it works very well
  342.             public static InputFeatureUsage<bool> triggerTouch          = CommonUsages.triggerButton;
  343.             // public static InputFeatureUsage<bool> triggerButton         = new InputFeatureUsage<bool>("_Trigger_Touch");
  344.             public static InputFeatureUsage<bool> menuButton            = CommonUsages.menuButton;
  345.             public static InputFeatureUsage<bool> primary2DAxisClick    = CommonUsages.primary2DAxisClick;
  346.             public static InputFeatureUsage<bool> primary2DAxisTouch    = CommonUsages.primary2DAxisTouch;
  347.             // public static InputFeatureUsage<bool> secondary2DAxisClick = CommonUsages.secondary2DAxisClick;
  348.             // public static InputFeatureUsage<bool> secondary2DAxisTouch = CommonUsages.secondary2DAxisTouch;
  349.         }
  350.  
  351.         static List<InputFeatureUsage<bool>> CustomButtons = new List<InputFeatureUsage<bool>>
  352.         {
  353.             Buttons.gripButton,
  354.             Buttons.gripTouch,
  355.             Buttons.triggerButton,
  356.             // Buttons.triggerTouch,
  357.         };
  358.  
  359.         static List<InputFeatureUsage<bool>> ButtonsList = new List<InputFeatureUsage<bool>>
  360.         {
  361.             Buttons.primaryButton,
  362.             Buttons.primaryTouch,
  363.             Buttons.secondaryButton,
  364.             Buttons.secondaryTouch,
  365.             Buttons.gripButton,
  366.             Buttons.gripTouch,
  367.             Buttons.triggerButton,
  368.             Buttons.triggerTouch,
  369.             Buttons.menuButton,
  370.             Buttons.primary2DAxisClick,
  371.             Buttons.primary2DAxisTouch,
  372.         };
  373.  
  374.         static public InputFeatureUsage<bool> ButtonGet( ButtonEnum button )
  375.         {
  376.             return ButtonsList[ ( int ) button ];
  377.         }
  378.  
  379.         public enum ButtonEnum
  380.         {
  381.             primaryButton,
  382.             primaryTouch,
  383.             secondaryButton,
  384.             secondaryTouch,
  385.             gripButton,
  386.             gripTouch,
  387.             triggerButton,
  388.             triggerTouch,
  389.             menuButton,
  390.             primary2DAxisClick,
  391.             primary2DAxisTouch
  392.         }
  393.  
  394.         // public class CommonUsage
  395.         // {
  396.         //     public Type type;
  397.         //     public string name;
  398.         //     public string link;
  399.         //     public CommonUsage() { }
  400.         // }
  401.  
  402.         // public static List<CommonUsage> usages = new List<CommonUsage>
  403.         // {
  404.         //     new CommonUsage { type = typeof( bool )                 , name = "isTracked"                        , link = "IsTracked" },
  405.         //     new CommonUsage { type = typeof( bool )                 , name = "primaryButton"                    , link = "PrimaryButton" },
  406.         //     new CommonUsage { type = typeof( bool )                 , name = "primaryTouch"                     , link = "PrimaryTouch" },
  407.         //     new CommonUsage { type = typeof( bool )                 , name = "secondaryButton"                  , link = "SecondaryButton" },
  408.         //     new CommonUsage { type = typeof( bool )                 , name = "secondaryTouch"                   , link = "SecondaryTouch" },
  409.         //     new CommonUsage { type = typeof( bool )                 , name = "gripButton"                       , link = "GripButton" },
  410.         //     new CommonUsage { type = typeof( bool )                 , name = "triggerButton"                    , link = "TriggerButton" },
  411.         //     new CommonUsage { type = typeof( bool )                 , name = "menuButton"                       , link = "MenuButton" },
  412.         //     new CommonUsage { type = typeof( bool )                 , name = "primary2DAxisClick"               , link = "Primary2DAxisClick" },
  413.         //     new CommonUsage { type = typeof( bool )                 , name = "primary2DAxisTouch"               , link = "Primary2DAxisTouch" },
  414.         //     new CommonUsage { type = typeof( bool )                 , name = "secondary2DAxisClick"             , link = "Secondary2DAxisClick" },
  415.         //     new CommonUsage { type = typeof( bool )                 , name = "secondary2DAxisTouch"             , link = "Secondary2DAxisTouch" },
  416.         //     new CommonUsage { type = typeof( InputTrackingState )   , name = "trackingState"                    , link = "TrackingState" },
  417.         //     new CommonUsage { type = typeof( float )                , name = "batteryLevel"                     , link = "BatteryLevel" },
  418.         //     new CommonUsage { type = typeof( float )                , name = "trigger"                          , link = "Trigger" },
  419.         //     new CommonUsage { type = typeof( float )                , name = "grip"                             , link = "Grip" },
  420.         //     new CommonUsage { type = typeof( Vector2 )              , name = "primary2DAxis"                    , link = "Primary2DAxis" },
  421.         //     new CommonUsage { type = typeof( Vector2 )              , name = "secondary2DAxis"                  , link = "Secondary2DAxis" },
  422.         //     new CommonUsage { type = typeof( Vector3 )              , name = "devicePosition"                   , link = "DevicePosition" },
  423.         //     new CommonUsage { type = typeof( Vector3 )              , name = "leftEyePosition"                  , link = "LeftEyePosition" },
  424.         //     new CommonUsage { type = typeof( Vector3 )              , name = "rightEyePosition"                 , link = "RightEyePosition" },
  425.         //     new CommonUsage { type = typeof( Vector3 )              , name = "centerEyePosition"                , link = "CenterEyePosition" },
  426.         //     new CommonUsage { type = typeof( Vector3 )              , name = "colorCameraPosition"              , link = "CameraPosition" },
  427.         //     new CommonUsage { type = typeof( Vector3 )              , name = "deviceVelocity"                   , link = "DeviceVelocity" },
  428.         //     new CommonUsage { type = typeof( Vector3 )              , name = "deviceAngularVelocity"            , link = "DeviceAngularVelocity" },
  429.         //     new CommonUsage { type = typeof( Vector3 )              , name = "leftEyeVelocity"                  , link = "LeftEyeVelocity" },
  430.         //     new CommonUsage { type = typeof( Vector3 )              , name = "leftEyeAngularVelocity"           , link = "LeftEyeAngularVelocity" },
  431.         //     new CommonUsage { type = typeof( Vector3 )              , name = "rightEyeVelocity"                 , link = "RightEyeVelocity" },
  432.         //     new CommonUsage { type = typeof( Vector3 )              , name = "rightEyeAngularVelocity"          , link = "RightEyeAngularVelocity" },
  433.         //     new CommonUsage { type = typeof( Vector3 )              , name = "centerEyeVelocity"                , link = "CenterEyeVelocity" },
  434.         //     new CommonUsage { type = typeof( Vector3 )              , name = "centerEyeAngularVelocity"         , link = "CenterEyeAngularVelocity" },
  435.         //     new CommonUsage { type = typeof( Vector3 )              , name = "colorCameraVelocity"              , link = "CameraVelocity" },
  436.         //     new CommonUsage { type = typeof( Vector3 )              , name = "colorCameraAngularVelocity"       , link = "CameraAngularVelocity" },
  437.         //     new CommonUsage { type = typeof( Vector3 )              , name = "deviceAcceleration"               , link = "DeviceAcceleration" },
  438.         //     new CommonUsage { type = typeof( Vector3 )              , name = "deviceAngularAcceleration"        , link = "DeviceAngularAcceleration" },
  439.         //     new CommonUsage { type = typeof( Vector3 )              , name = "leftEyeAcceleration"              , link = "LeftEyeAcceleration" },
  440.         //     new CommonUsage { type = typeof( Vector3 )              , name = "leftEyeAngularAcceleration"       , link = "LeftEyeAngularAcceleration" },
  441.         //     new CommonUsage { type = typeof( Vector3 )              , name = "rightEyeAcceleration"             , link = "RightEyeAcceleration" },
  442.         //     new CommonUsage { type = typeof( Vector3 )              , name = "rightEyeAngularAcceleration"      , link = "RightEyeAngularAcceleration" },
  443.         //     new CommonUsage { type = typeof( Vector3 )              , name = "centerEyeAcceleration"            , link = "CenterEyeAcceleration" },
  444.         //     new CommonUsage { type = typeof( Vector3 )              , name = "centerEyeAngularAcceleration"     , link = "CenterEyeAngularAcceleration" },
  445.         //     new CommonUsage { type = typeof( Vector3 )              , name = "colorCameraAcceleration"          , link = "CameraAcceleration" },
  446.         //     new CommonUsage { type = typeof( Vector3 )              , name = "colorCameraAngularAcceleration"   , link = "CameraAngularAcceleration" },
  447.         //     new CommonUsage { type = typeof( Quaternion )           , name = "deviceRotation"                   , link = "DeviceRotation" },
  448.         //     new CommonUsage { type = typeof( Quaternion )           , name = "leftEyeRotation"                  , link = "LeftEyeRotation" },
  449.         //     new CommonUsage { type = typeof( Quaternion )           , name = "rightEyeRotation"                 , link = "RightEyeRotation" },
  450.         //     new CommonUsage { type = typeof( Quaternion )           , name = "centerEyeRotation"                , link = "CenterEyeRotation" },
  451.         //     new CommonUsage { type = typeof( Quaternion )           , name = "colorCameraRotation"              , link = "CameraRotation" },
  452.         //     new CommonUsage { type = typeof( Hand )                 , name = "handData"                         , link = "HandData" },
  453.         //     new CommonUsage { type = typeof( Eyes )                 , name = "eyesData"                         , link = "EyesData" },
  454.         // };
  455.     }
  456. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement