Skip to content

Commit 53a0e98

Browse files
authored
Merge branch 'develop' into fix-project-wide-actions-override-playerinput
2 parents 93a4c69 + 581d5da commit 53a0e98

File tree

3 files changed

+103
-44
lines changed

3 files changed

+103
-44
lines changed

Assets/Tests/InputSystem/Plugins/XRTests.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,40 @@ public void Components_TrackedPoseDriver_RetainsPoseWhenTrackedDeviceRemoved()
728728
}
729729
}
730730

731+
[Test]
732+
[Category("Components")]
733+
[TestCase(false)]
734+
[TestCase(true)]
735+
public void Components_TrackedPoseDriver_RetainsPoseWhenNoActionIsBound(bool ignoreTrackingState)
736+
{
737+
// Tests/reproduces the scenario described in https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-699
738+
// i.e. that rotation and/or position is not updated if device is not connected.
739+
740+
var position = new Vector3(1f, 2f, 3f);
741+
var rotation = new Quaternion(0.09853293f, 0.09853293f, 0.09853293f, 0.9853293f);
742+
743+
// Setup GameObject to have a position and rotation that is different from identity transform
744+
var go = new GameObject();
745+
go.transform.position = position;
746+
go.transform.rotation = rotation;
747+
748+
// Configure TrackedPoseDriver
749+
var tpd = go.AddComponent<TrackedPoseDriver>();
750+
tpd.updateType = TrackedPoseDriver.UpdateType.Update;
751+
tpd.trackingType = TrackedPoseDriver.TrackingType.RotationAndPosition;
752+
tpd.ignoreTrackingState = ignoreTrackingState;
753+
754+
var transform = tpd.transform;
755+
Assert.That(transform.position, Is.EqualTo(position));
756+
Assert.That(transform.rotation, Is.EqualTo(rotation));
757+
758+
// Ensure that position and/or rotation is not affected by update.
759+
InputSystem.Update(InputUpdateType.Dynamic);
760+
761+
Assert.That(transform.position, Is.EqualTo(position));
762+
Assert.That(transform.rotation, Is.EqualTo(rotation));
763+
}
764+
731765
[Test]
732766
[Category("Layouts")]
733767
public void Layouts_PoseControlsCanBeCreatedBySubcontrols()
@@ -739,7 +773,7 @@ public void Layouts_PoseControlsCanBeCreatedBySubcontrols()
739773
var generatedLayout = InputSystem.LoadLayout("XRInputV1::XRManufacturer::XRDevice");
740774
Assert.That(generatedLayout, Is.Not.Null);
741775

742-
// A Pose control parent was created based off subcontrols
776+
// A Pose control parent was created based off sub-controls
743777
var pose = generatedLayout["PoseControl"];
744778
Assert.That(pose.layout, Is.EqualTo(new InternedString("Pose")));
745779
}

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ however, it has to be formatted properly to pass verification tests.
2727
- Fixed arrow key navigation of Input Actions after Action rename. [ISXB-1024](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1024)
2828
- Fixed gamepad navigation in UI Toolkit TextField when using InputSystemUIInputModule. [UUM-77364](https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-77364)
2929
- Fixed issue where asset editor window splitter positions were not persisted [ISXB-1316]
30+
- Fixed a bug that would cause `TrackedPoseDriver` to update position and rotation when no HMD device is connected [ISXB-699](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-699) instead of keeping it unchanged.
3031

3132
### Changed
3233
- Changed default input action asset name from New Controls to New Actions.

Packages/com.unity.inputsystem/InputSystem/Plugins/XR/TrackedPoseDriver.cs

Lines changed: 67 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using UnityEngine.InputSystem.LowLevel;
3+
using UnityEngine.UIElements;
34

45
namespace 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

Comments
 (0)