66using System ;
77using System . Collections . Generic ;
88using System . Linq ;
9+ using System . Runtime . InteropServices ;
910using System . Text . RegularExpressions ;
1011using UnityEngine ;
1112using UnityEngine . InputSystem ;
1516using UnityEngine . InputSystem . Utilities ;
1617using UnityEngine . InputSystem . XR ;
1718using TrackingState = UnityEngine . XR . InputTrackingState ;
19+ #if VIU_UIS_POSE_CONTROL
1820using UnityPoseControl = UnityEngine . InputSystem . XR . PoseControl ;
21+ #endif
1922#if VIU_OPENXR_PLUGIN_POSE_CONTROL
2023using OpenXRPoseControl = UnityEngine . XR . OpenXR . Input . PoseControl ;
2124#endif
@@ -26,6 +29,25 @@ public struct VIUSyntheticDeviceState : IInputStateTypeInfo
2629 {
2730 public FourCC format => new FourCC ( 'V' , 'I' , 'U' , 'D' ) ;
2831
32+ [ StructLayout ( LayoutKind . Explicit , Size = kSizeInBytes ) ]
33+ public struct PoseState : IInputStateTypeInfo
34+ {
35+ internal const int kSizeInBytes = 60 ;
36+ public FourCC format => new FourCC ( 'P' , 'o' , 's' , 'e' ) ;
37+ [ FieldOffset ( 0 ) , InputControl ( displayName = "Is Tracked" , layout = "Button" ) ]
38+ public bool isTracked ;
39+ [ FieldOffset ( 4 ) , InputControl ( displayName = "Tracking State" , layout = "Integer" ) ]
40+ public TrackingState trackingState ;
41+ [ FieldOffset ( 8 ) , InputControl ( displayName = "Position" , noisy = true ) ]
42+ public Vector3 position ;
43+ [ FieldOffset ( 20 ) , InputControl ( displayName = "Rotation" , noisy = true ) ]
44+ public Quaternion rotation ;
45+ [ FieldOffset ( 36 ) , InputControl ( displayName = "Velocity" , noisy = true ) ]
46+ public Vector3 velocity ;
47+ [ FieldOffset ( 48 ) , InputControl ( displayName = "Angular Velocity" , noisy = true ) ]
48+ public Vector3 angularVelocity ;
49+ }
50+
2951 [ InputControl ( name = "pose" , layout = "Pose" ) ]
3052 public PoseState pose ;
3153
@@ -270,7 +292,9 @@ private void OnRoleValueMappingChanged(ViveRole.IMap map, ViveRole.MappingChange
270292 public StickControl pad { get ; private set ; }
271293 public StickControl joystick { get ; private set ; }
272294
295+ #if VIU_UIS_POSE_CONTROL
273296 public UnityPoseControl pose { get ; private set ; }
297+ #endif
274298#if VIU_OPENXR_PLUGIN_POSE_CONTROL
275299 public OpenXRPoseControl openxr_pose { get ; private set ; }
276300#endif
@@ -443,7 +467,7 @@ void IInputUpdateCallbackReceiver.OnUpdate()
443467 middlePinch = ctrlState . GetAxis ( ControllerAxis . MiddlePinch ) ,
444468 ringPinch = ctrlState . GetAxis ( ControllerAxis . RingPinch ) ,
445469 pinkyPinch = ctrlState . GetAxis ( ControllerAxis . PinkyPinch ) ,
446- pose = new PoseState ( )
470+ pose = new VIUSyntheticDeviceState . PoseState ( )
447471 {
448472 isTracked = deviceState . isPoseValid ,
449473 trackingState = TrackingState . Position | TrackingState . Rotation | TrackingState . Velocity | TrackingState . AngularVelocity ,
@@ -509,10 +533,11 @@ protected override void FinishSetup()
509533 {
510534 base . FinishSetup ( ) ;
511535
512- var poseGeneric = GetChildControl ( "pose" ) ;
513- pose = poseGeneric as UnityPoseControl ;
536+ #if VIU_UIS_POSE_CONTROL
537+ pose = GetChildControl ( "pose" ) as UnityPoseControl ;
538+ #endif
514539#if VIU_OPENXR_PLUGIN_POSE_CONTROL
515- openxr_pose = poseGeneric as OpenXRPoseControl ;
540+ openxr_pose = GetChildControl ( "pose" ) as OpenXRPoseControl ;
516541#endif
517542 isTracked = GetChildControl < ButtonControl > ( "pose/isTracked" ) ;
518543 trackingState = GetChildControl < IntegerControl > ( "pose/trackingState" ) ;
@@ -543,62 +568,134 @@ protected override void FinishSetup()
543568 }
544569 }
545570
571+ [ StructLayout ( LayoutKind . Explicit , Size = kSizeInBytes ) ]
546572 public struct VIUSyntheticXRHMDState : IInputStateTypeInfo
547573 {
574+ public const int kSizeInBytes = 120 ;
548575 public FourCC format => new FourCC ( 'V' , 'I' , 'U' , 'H' ) ;
549-
550- public TrackingState trackingState ;
576+ [ FieldOffset ( 0 ) , InputControl ( layout = "Button" ) ]
551577 public bool isTracked ;
578+ [ FieldOffset ( 4 ) , InputControl ( layout = "Integer" ) ]
579+ public TrackingState trackingState ;
580+ [ FieldOffset ( 8 ) , InputControl ( noisy = true ) ]
552581 public Vector3 devicePosition ;
582+ [ FieldOffset ( 20 ) , InputControl ( noisy = true ) ]
553583 public Quaternion deviceRotation ;
554584
585+ [ FieldOffset ( 36 ) , InputControl ( noisy = true ) ]
555586 public Vector3 leftEyePosition ;
587+ [ FieldOffset ( 48 ) , InputControl ( noisy = true ) ]
556588 public Quaternion leftEyeRotation ;
589+ [ FieldOffset ( 64 ) , InputControl ( noisy = true ) ]
557590 public Vector3 rightEyePosition ;
591+ [ FieldOffset ( 76 ) , InputControl ( noisy = true ) ]
558592 public Quaternion rightEyeRotation ;
593+ [ FieldOffset ( 92 ) , InputControl ( noisy = true ) ]
559594 public Vector3 centerEyePosition ;
595+ [ FieldOffset ( 104 ) , InputControl ( noisy = true ) ]
560596 public Quaternion centerEyeRotation ;
561597 }
562598
563- //[InputControlLayout(displayName = "VIU Synthetic XR HMD", stateType = typeof(VIUSyntheticXRHMDState), hideInUI = true)]
564- //public class VIUSyntheticXRHMD : XRHMD, IInputUpdateCallbackReceiver
565- //{
566- // //private
567- // private ViveRole.IMap<DeviceRole> roleMap;
568-
569- // void IInputUpdateCallbackReceiver.OnUpdate()
570- // {
571- // if (roleMap == null) { return; }
572- // var deviceIndex = roleMap.GetMappedDeviceByRoleValue((int)DeviceRole.Hmd);
573- // var deviceState = VRModule.GetCurrentDeviceState(deviceIndex);
574- // var UnityEngine.XR.InputDevices.GetDeviceAtXRNode(UnityEngine.XR.XRNode.Head);
575- // InputSystem.QueueStateEvent(this, new VIUSyntheticXRHMDState()
576- // {
577- // isTracked = deviceState.isPoseValid,
578- // trackingState = TrackingState.Position | TrackingState.Rotation | TrackingState.Velocity | TrackingState.AngularVelocity,
579- // position = deviceState.position,
580- // rotation = deviceState.rotation,
581- // velocity = deviceState.velocity,
582- // angularVelocity = deviceState.angularVelocity,
583- // });
584- // }
585-
586- // protected override void FinishSetup()
587- // {
588- // base.FinishSetup();
589-
590- // roleMap = ViveRole.GetMap<DeviceRole>();
591- // }
592- //}
599+ #if UNITY_EDITOR
600+ [ UnityEditor . InitializeOnLoad ]
601+ #endif
602+ [ InputControlLayout ( displayName = "VIU Synthetic XR HMD" , stateType = typeof ( VIUSyntheticXRHMDState ) , hideInUI = true ) ]
603+ public class VIUSyntheticXRHMD : XRHMD , IInputUpdateCallbackReceiver
604+ {
605+ private ViveInput . ICtrlState < DeviceRole > ctrlState ;
606+ private static VIUSyntheticXRHMD hmdDevice ;
607+ private static readonly RigidPose leftEyeLocalPose = new RigidPose ( new Vector3 ( - 0.033f , 0f , 0f ) , Quaternion . identity ) ;
608+ private static readonly RigidPose rightEyeLocalPose = new RigidPose ( new Vector3 ( 0.033f , 0f , 0f ) , Quaternion . identity ) ;
609+
610+ static VIUSyntheticXRHMD ( )
611+ {
612+ InputSystem . RegisterLayout < VIUSyntheticXRHMD > ( ) ;
613+
614+ #if UNITY_EDITOR
615+ if ( UnityEditor . EditorApplication . isPlayingOrWillChangePlaymode )
616+ #endif
617+ {
618+ var roleMap = ViveRole . GetMap < DeviceRole > ( ) ;
619+
620+ HandleDevice ( ref hmdDevice , VRModule . IsValidDeviceIndex ( roleMap . GetMappedDeviceByRole ( DeviceRole . Hmd ) ) ) ;
593621
622+ roleMap . onRoleMappingChanged += ( map , arg ) =>
623+ {
624+ if ( arg . role == DeviceRole . Hmd )
625+ {
626+ HandleDevice ( ref hmdDevice , VRModule . IsValidDeviceIndex ( arg . currentDeviceIndex ) ) ;
627+ }
628+ } ;
629+ }
630+ }
594631
632+ private static void HandleDevice ( ref VIUSyntheticXRHMD device , bool connected )
633+ {
634+ try
635+ {
636+ if ( connected )
637+ {
638+ if ( device == null )
639+ {
640+ device = InputSystem . AddDevice < VIUSyntheticXRHMD > ( "VIUSyntheticXRHMD" ) ;
641+ device . ctrlState = ViveInput . GetState ( DeviceRole . Hmd ) ;
642+ }
643+ else
644+ {
645+ InputSystem . AddDevice ( device ) ;
646+ }
647+ }
648+ else
649+ {
650+ if ( device != null )
651+ {
652+ InputSystem . RemoveDevice ( device ) ;
653+ }
654+ }
655+ }
656+ catch ( Exception e )
657+ {
658+ Debug . LogException ( e ) ;
659+ }
660+ }
661+
662+ void IInputUpdateCallbackReceiver . OnUpdate ( )
663+ {
664+ if ( ctrlState == null ) { return ; }
665+
666+ var deviceIndex = ctrlState . RoleMap . GetMappedDeviceByRoleValue ( ctrlState . RoleValue ) ;
667+ var deviceState = VRModule . GetCurrentDeviceState ( deviceIndex ) ;
668+ var leftEyePose = deviceState . pose * leftEyeLocalPose ;
669+ var rightEyePose = deviceState . pose * rightEyeLocalPose ;
670+ InputSystem . QueueStateEvent ( this , new VIUSyntheticXRHMDState ( )
671+ {
672+ isTracked = deviceState . isPoseValid ,
673+ trackingState = TrackingState . Position | TrackingState . Rotation ,
674+ devicePosition = deviceState . position ,
675+ deviceRotation = deviceState . rotation ,
676+ // TODO: should get eye pose from IPD property or eye tracking sdk
677+ leftEyePosition = leftEyePose . pos ,
678+ leftEyeRotation = leftEyePose . rot ,
679+ rightEyePosition = rightEyePose . pos ,
680+ rightEyeRotation = rightEyePose . rot ,
681+ centerEyePosition = deviceState . position ,
682+ centerEyeRotation = deviceState . rotation ,
683+ } ) ;
684+ }
685+ }
686+
687+ [ StructLayout ( LayoutKind . Explicit , Size = kSizeInBytes ) ]
595688 public struct VIUSyntheticXRControllerState : IInputStateTypeInfo
596689 {
690+ public const int kSizeInBytes = 36 ;
597691 public FourCC format => new FourCC ( 'V' , 'I' , 'U' , 'C' ) ;
598-
599- public TrackingState trackingState ;
692+ [ FieldOffset ( 0 ) , InputControl ( layout = "Button" ) ]
600693 public bool isTracked ;
694+ [ FieldOffset ( 4 ) , InputControl ( layout = "Integer" ) ]
695+ public TrackingState trackingState ;
696+ [ FieldOffset ( 8 ) , InputControl ( noisy = true ) ]
601697 public Vector3 devicePosition ;
698+ [ FieldOffset ( 20 ) , InputControl ( noisy = true ) ]
602699 public Quaternion deviceRotation ;
603700 }
604701
@@ -649,13 +746,7 @@ private static void HandleDevice(ref VIUSyntheticXRController device, HandRole h
649746 if ( device == null )
650747 {
651748 device = InputSystem . AddDevice < VIUSyntheticXRController > ( "VIUSyntheticXRController" + hand . ToString ( ) ) ;
652- //device = InputSystem.AddDevice(new InputDeviceDescription()
653- //{
654- // interfaceName = typeof(VIUSyntheticXRController).Name,
655- // manufacturer = "HTC ViveSoftware",
656- //}) as VIUSyntheticXRController;
657-
658- InputSystem . AddDeviceUsage ( rightDevice , handStr ) ;
749+ InputSystem . AddDeviceUsage ( device , handStr ) ;
659750 device . ctrlState = ViveInput . GetState ( hand ) ;
660751 }
661752 else
@@ -690,12 +781,6 @@ void IInputUpdateCallbackReceiver.OnUpdate()
690781 devicePosition = deviceState . position ,
691782 deviceRotation = deviceState . rotation ,
692783 } ) ;
693-
694- //Debug.Log("IInputUpdateCallbackReceiver.OnUpdate " + name + " "
695- // + isTracked.ReadValue() + " "
696- // + trackingState.ReadValue() + " "
697- // + devicePosition.ReadValue().ToString("0.00") + " "
698- // + deviceRotation.ReadValue().eulerAngles.ToString("0"));
699784 }
700785 }
701786}
0 commit comments