11using System ;
22using UnityEngine . InputSystem . LowLevel ;
3+ using UnityEngine . UIElements ;
34
45namespace UnityEngine . InputSystem . XR
56{
@@ -307,7 +308,7 @@ void BindTrackingState()
307308 }
308309 }
309310
310- private void RenameAndEnable ( InputAction action , string name )
311+ private static void RenameAndEnable ( InputAction action , string name )
311312 {
312313#if UNITY_EDITOR
313314 Editor . InputExitPlayModeAnalytic . suppress = true ;
@@ -468,14 +469,21 @@ protected void UpdateCallback()
468469 if ( m_IsFirstUpdate )
469470 {
470471 // Update current input values if this is the first update since becoming enabled
471- // since the performed callbacks may not have been executed
472- if ( m_PositionInput . action != null )
472+ // since the performed callbacks may not have been executed. In case there is no bound control
473+ // we preserve current transform by extracting transform values as initial values instead.
474+ var hasResolvedPositionInputControl = HasResolvedControl ( m_PositionInput . action ) ;
475+ if ( hasResolvedPositionInputControl )
473476 m_CurrentPosition = m_PositionInput . action . ReadValue < Vector3 > ( ) ;
477+ else
478+ m_CurrentPosition = transform . localPosition ;
474479
475- if ( m_RotationInput . action != null )
480+ var hasResolvedRotationInputControl = HasResolvedControl ( m_RotationInput . action ) ;
481+ if ( hasResolvedRotationInputControl )
476482 m_CurrentRotation = m_RotationInput . action . ReadValue < Quaternion > ( ) ;
483+ else
484+ m_CurrentRotation = transform . localRotation ;
477485
478- ReadTrackingState ( ) ;
486+ ReadTrackingState ( hasResolvedPositionInputControl , hasResolvedRotationInputControl ) ;
479487
480488 m_IsFirstUpdate = false ;
481489 }
@@ -486,7 +494,7 @@ protected void UpdateCallback()
486494 OnUpdate ( ) ;
487495 }
488496
489- void ReadTrackingState ( )
497+ void ReadTrackingState ( bool hasResolvedPositionInputControl , bool hasResolvedRotationInputControl )
490498 {
491499 var trackingStateAction = m_TrackingStateInput . action ;
492500 if ( trackingStateAction != null && ! trackingStateAction . enabled )
@@ -500,46 +508,24 @@ void ReadTrackingState()
500508 {
501509 // Treat an Input Action Reference with no reference the same as
502510 // an enabled Input Action with no authored bindings, and allow driving the Transform pose.
503- m_CurrentTrackingState = TrackingStates . Position | TrackingStates . Rotation ;
504- return ;
511+ // Check if we have transform and rotation controls to drive the pose.
512+ if ( hasResolvedPositionInputControl && hasResolvedRotationInputControl )
513+ m_CurrentTrackingState = TrackingStates . Position | TrackingStates . Rotation ;
514+ else if ( hasResolvedPositionInputControl )
515+ m_CurrentTrackingState = TrackingStates . Position ;
516+ else if ( hasResolvedRotationInputControl )
517+ m_CurrentTrackingState = TrackingStates . Rotation ;
518+ else
519+ m_CurrentTrackingState = TrackingStates . None ;
505520 }
506-
507- // Grab state.
508- var actionMap = trackingStateAction . GetOrCreateActionMap ( ) ;
509- actionMap . ResolveBindingsIfNecessary ( ) ;
510- var state = actionMap . m_State ;
511-
512- // Get list of resolved controls to determine if a device actually has tracking state.
513- var hasResolvedControl = false ;
514- if ( state != null )
521+ else if ( HasResolvedControl ( trackingStateAction ) )
515522 {
516- var actionIndex = trackingStateAction . m_ActionIndexInState ;
517- var totalBindingCount = state . totalBindingCount ;
518- for ( var i = 0 ; i < totalBindingCount ; ++ i )
519- {
520- unsafe
521- {
522- ref var bindingState = ref state . bindingStates [ i ] ;
523- if ( bindingState . actionIndex != actionIndex )
524- continue ;
525- if ( bindingState . isComposite )
526- continue ;
527-
528- if ( bindingState . controlCount > 0 )
529- {
530- hasResolvedControl = true ;
531- break ;
532- }
533- }
534- }
535- }
536-
537- // Retain the current value if there is no resolved binding.
538- // Since the field initializes to allowing position and rotation,
539- // this allows for driving the Transform pose always when the device
540- // doesn't support reporting the tracking state.
541- if ( hasResolvedControl )
523+ // Retain the current value if there is no resolved binding.
524+ // Since the field initializes to allowing position and rotation,
525+ // this allows for driving the Transform pose always when the device
526+ // doesn't support reporting the tracking state.
542527 m_CurrentTrackingState = ( TrackingStates ) trackingStateAction . ReadValue < int > ( ) ;
528+ }
543529 }
544530
545531 /// <summary>
@@ -585,6 +571,8 @@ protected virtual void PerformUpdate()
585571 /// <param name="newRotation">The new local rotation to possibly set.</param>
586572 protected virtual void SetLocalTransform ( Vector3 newPosition , Quaternion newRotation )
587573 {
574+ // Note that tracking state will be set to reflect whether the position and/or rotation
575+ // actions can provide applicable values.
588576 var positionValid = m_IgnoreTrackingState || ( m_CurrentTrackingState & TrackingStates . Position ) != 0 ;
589577 var rotationValid = m_IgnoreTrackingState || ( m_CurrentTrackingState & TrackingStates . Rotation ) != 0 ;
590578
@@ -616,6 +604,42 @@ bool HasStereoCamera(out Camera cameraComponent)
616604 return TryGetComponent ( out cameraComponent ) && cameraComponent . stereoEnabled ;
617605 }
618606
607+ // Evaluates whether the given action has at least one resolved control and may generate input.
608+ private static bool HasResolvedControl ( InputAction action )
609+ {
610+ // Action cannot have controls if null.
611+ if ( action == null )
612+ return false ;
613+
614+ // Attempt to grab state and resolve bindings unless already resolved.
615+ var actionMap = action . GetOrCreateActionMap ( ) ;
616+ actionMap . ResolveBindingsIfNecessary ( ) ;
617+ var state = actionMap . m_State ;
618+ if ( state == null )
619+ return false ;
620+
621+ // Get list of resolved controls to determine if a device actually has a tracking state.
622+ var actionIndex = action . m_ActionIndexInState ;
623+ var totalBindingCount = state . totalBindingCount ;
624+ for ( var i = 0 ; i < totalBindingCount ; ++ i )
625+ {
626+ unsafe
627+ {
628+ ref var bindingState = ref state . bindingStates [ i ] ;
629+ if ( bindingState . actionIndex != actionIndex )
630+ continue ;
631+
632+ if ( bindingState . isComposite )
633+ continue ;
634+
635+ if ( bindingState . controlCount > 0 )
636+ return true ;
637+ }
638+ }
639+
640+ return false ;
641+ }
642+
619643 #region DEPRECATED
620644
621645 // Disable warnings that these fields are never assigned to. They are set during Unity deserialization and migrated.
0 commit comments