diff --git a/README.md b/README.md index f770961a5..78f73afcc 100644 --- a/README.md +++ b/README.md @@ -48,10 +48,9 @@ MRTK3 requires Unity 2021.3.21 or higher. In addition, you need the [Mixed Reali In previous versions of MRTK (HoloToolkit and MRTK v2), all packages were released as a complete set, marked with the same version number (ex: 2.8.0). Starting with MRTK3 GA, each package will be individually versioned, following the [Semantic Versioning 2.0.0 specification](https://semver.org/spec/v2.0.0.html). (As a result, the '3' in MRTK3 is not a version number!) - Individual versioning will enable faster servicing while providing improved developer understanding of the magnitude of changes and reducing the number of packages needing to be updated to acquire the desired fix(es). -For example, if a non-breaking new feature is added to the UX core package, which contains the logic for user interface behavior the minor version number will increase (from 3.0.x to 3.1.0). Since the change is non-breaking, the UX components package, which depends upon UX core, is not required to be updated. +For example, if a non-breaking new feature is added to the UX core package, which contains the logic for user interface behavior the minor version number will increase (from 3.0.x to 3.1.0). Since the change is non-breaking, the UX components package, which depends upon UX core, is not required to be updated. As a result of this change, there is not a unified MRTK3 product version. @@ -89,14 +88,14 @@ MRTK3 has been upgraded to use [Unity's XR Interaction Toolkit 3+](https://docs. * The new controllers and rig retake the original names of the obsolete controllers. * New controllers structure have been modified so that all of them have the same structure. * The deprecated XRI2 XRController component has been removed from the controllers and its input actions have been moved to their interactors. - * The new controllers now have a Tracked Pose Driver components that holds references to the device's position, rotation, and tracking state input actions. + * The new controllers now have a Tracked Pose Driver components that holds references to the device's position, rotation, and tracking state input actions. * Interactors now have a Tracked Pose Driver field that holds a reference to the Tracked Pose Driver component of the parent controller. * Interactors now have a Mode Managed Root that holds a reference to the parent controller GameObject. * Added new unity-tests for the new XRI3 functionality + components. * Updated several unity-tests. * Updated several scripts so that they work with both obsolete XRI2 and new XRI3 prefabs. * Updated all scenes to use the new XRI3 rig + controllers. - * Made a copy of the old HandInteractionExamples scene and renamed as ObsoleteHandInteractionExample, this scene still consumes the old rig + controllers. + * Made a copy of the old HandInteractionExamples scene and renamed as ObsoleteHandInteractionExample, this scene still consumes the old rig + controllers. A more detailed explanation of the changes can be found in [XRI2TOXRI3MIGRATIONGUIDE.md](./XRI2TOXRI3MIGRATIONGUIDE.md). The guide can also help others as a path for migrating their own solutions or MRTK3 forks from XRI2 to XRI3. @@ -104,4 +103,4 @@ A more detailed explanation of the changes can be found in [XRI2TOXRI3MIGRATIONG For information on how the Mixed Reality Toolkit for Unity Project is governed, please read [GOVERNANCE.md](./GOVERNANCE.md). -All projects under the Mixed Reality Toolkit organization are governed by the Steering Committee. The Steering Committee is responsible for all technical oversight, project approval and oversight, policy oversight, and trademark management for the Organization. To learn more about the Steering Committee, visit this link: https://github.com/MixedRealityToolkit/MixedRealityToolkit-MVG/blob/main/org-docs/CHARTER.md +All projects under the Mixed Reality Toolkit organization are governed by the Steering Committee. The Steering Committee is responsible for all technical oversight, project approval and oversight, policy oversight, and trademark management for the Organization. To learn more about the Steering Committee, visit this link: diff --git a/XRI2TOXRI3MIGRATIONGUIDE.md b/XRI2TOXRI3MIGRATIONGUIDE.md index e1e18dd04..f41fba4f2 100644 --- a/XRI2TOXRI3MIGRATIONGUIDE.md +++ b/XRI2TOXRI3MIGRATIONGUIDE.md @@ -2,7 +2,7 @@ ## Introduction -Thank you for choosing MRTK as your Mixed Reality framework. MRTK has been upgraded to follow XRI3 patterns and consume [Unity's XR Interaction Toolkit 3+](https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@3.0/manual/whats-new-3.0.html) package. The upgrade encompasses various changes from the previous MRTK version and we want to share our experience during the upgrade so that the community is aware of the changes that had to be implemented. We also want to provide an overall roadmap for others to do their own upgrades in their forks or propietary solutions and therefore we created this guide. We created this guide to empower you and your organization to achieve more in Mixed Reality solutions. +Thank you for choosing MRTK as your Mixed Reality framework. MRTK has been upgraded to follow XRI3 patterns and consume [Unity's XR Interaction Toolkit 3+](https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@3.0/manual/whats-new-3.0.html) package. The upgrade encompasses various changes from the previous MRTK version and we want to share our experience during the upgrade so that the community is aware of the changes that had to be implemented. We also want to provide an overall roadmap for others to do their own upgrades in their forks or proprietary solutions and therefore we created this guide. We created this guide to empower you and your organization to achieve more in Mixed Reality solutions. ## Original MRTK rig structure @@ -10,7 +10,7 @@ Previous to XRI3 upgrade the MRTK3 rig had a structure similar to the one shown ![Original MRTK rig structure](Images/XRI2ToXRI3Guide/MRTK3XRI2RigStructure.png) -The MRTK3 rig prefab is the root GameObject with the Camera Offset ([XROrigin](https://docs.unity3d.com/Packages/com.unity.xr.core-utils@2.0/api/Unity.XR.CoreUtils.XROrigin.html)) child that has the multiple controllers (LeftHand, RightHand, and Gaze) as children. Next is a screenshot of the now obsolete MRTK XR Rig. +The MRTK3 rig prefab is the root GameObject with the Camera Offset ([XROrigin](https://docs.unity3d.com/Packages/com.unity.xr.core-utils@2.0/api/Unity.XR.CoreUtils.XROrigin.html)) child that has the multiple controllers (LeftHand, RightHand, and Gaze) as children. Next is a screenshot of the now obsolete MRTK XR Rig. ![Obsolete MRTK rig](Images/XRI2ToXRI3Guide/ObsoleteMRTKXRRig.png) @@ -22,43 +22,43 @@ The new, XRI3, MRTK rig + controllers have a slightly different structure which ![New MRTK rig structure](Images/XRI2ToXRI3Guide/MRTK3XRI3RigStructure.png) -In essence, the main difference is that the [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) component has been removed and replaced with a [Tracked Pose Driver](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.TrackedPoseDriver.html) component which stores references to the Position, Rotation, and Tracking State actions (these can be and are the same as in the old structure). The other input actions (e.g. Select, Activate, UIPress, etc) are moved from the Controller to the Interactor. They are stored in fields already defined in the [Unity's XR Interaction Toolkit 3+](https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@3.0/manual/whats-new-3.0.html) package. +In essence, the main difference is that the [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) component has been removed and replaced with a [Tracked Pose Driver](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.TrackedPoseDriver.html) component which stores references to the Position, Rotation, and Tracking State actions (these can be and are the same as in the old structure). The other input actions (e.g. Select, Activate, UIPress, etc) are moved from the Controller to the Interactor. They are stored in fields already defined in the [Unity's XR Interaction Toolkit 3+](https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@3.0/manual/whats-new-3.0.html) package. -The XRI3 migration consisted of a set of steps to remove deprecated components and reference the existing Input Actions in their new homes. We recommend that the first step is to move the Position, Rotation and Tracking State actions to their new home according to the new [Unity's XR Interaction Toolkit 3+](https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@3.0/manual/whats-new-3.0.html). +The XRI3 migration consisted of a set of steps to remove deprecated components and reference the existing Input Actions in their new homes. We recommend that the first step is to move the Position, Rotation and Tracking State actions to their new home according to the new [Unity's XR Interaction Toolkit 3+](https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@3.0/manual/whats-new-3.0.html). -## Step 1 - Move Position, Rotation and Tracking State actions +## Step 1 - Move Position, Rotation, and Tracking State actions -Unity introduced a new [Tracked Pose Driver](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.TrackedPoseDriver.html) component which is the new home for the Position, Rotation, and Tracking State input actions. Add such component (or a class derived from it) to your controller(s) and add references to the already existing Position, Rotation, and Tracking State actions that were referenced in the removed XRController, as shown the next figure: +Unity introduced a new [Tracked Pose Driver](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.TrackedPoseDriver.html) component which is the new home for the Position, Rotation, and Tracking State input actions. Add such component (or a class derived from it) to your controller(s) and add references to the already existing Position, Rotation, and Tracking State actions that were referenced in the removed XRController, as shown the next figure: ![Step 1](Images/XRI2ToXRI3Guide/XRI2ToXRI3Step1.png) ## Step 2 - Implement your own Model functionality -The next step would be to implement your own controller Model functionality if you use it at all. Unity kindly shared that they have no plans to implement a new home for the Model functionality of the [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) because of its simplicity so we had to implement it. Fortunately, they are correct and their implementation is quite easy, we recommend you to check MRTK's HandModel MonoBehaviour for an example of its implementation. The next figure shows the new home for the [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) Model functionality in the new MRTK Controller: +The next step would be to implement your own controller Model functionality if you use it at all. Unity kindly shared that they have no plans to implement a new home for the Model functionality of the [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) because of its simplicity so we had to implement it. Fortunately, they are correct and their implementation is quite easy, we recommend you to check MRTK's HandModel MonoBehaviour for an example of its implementation. The next figure shows the new home for the [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) Model functionality in the new MRTK Controller: ![Step 2](Images/XRI2ToXRI3Guide/XRI2ToXRI3Step2.png) ### Input Compatibility Mode -As you make progress in upgrading your Controllers and Interactors to XRI3 it is a good idea to keep an eye on the deprecated XR Controller Configuration Input Compatibility Mode field. This mode controls whether the Interactor uses the new input readers or use the deprecated XR Controller component as per [Unity's changelog](https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@3.0/changelog/CHANGELOG.html#changed-3). It defaults to *Automatic*, however, **this behavior may show false-positive correct behaviors** if you have not removed the [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) component from the Controller. +As you make progress in upgrading your Controllers and Interactors to XRI3, it is a good idea to keep an eye on the deprecated XR Controller Configuration Input Compatibility Mode field. This mode controls whether the Interactor uses the new input readers or use the deprecated XR Controller component as per [Unity's changelog](https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@3.0/changelog/CHANGELOG.html#changed-3). It defaults to *Automatic*, however, **this behavior may show false-positive correct behaviors** if you have not removed the [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) component from the Controller. -The Input Compatibility Mode can be found via Inspector under the *(Deprecated) XR Controller Configuration* group as shown next: +The Input Compatibility Mode can be found via Inspector under the *(Deprecated) XR Controller Configuration* group as shown here: ![Input Compatibility Mode](Images/XRI2ToXRI3Guide/InputCompatibilityMode.png) ## Step 3 - Move the remaining [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) input actions to their respective Interactors -Once you have moved the device tracking input actions to the [Tracked Pose Driver](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.TrackedPoseDriver.html) component and implemented your own Model functionality then you can move the remaining input actions from the original [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) to the Interactors themselves. The following image highlights the new controller prefab interactors fields that we needed to update for the XRI3 migration. +Once you have moved the device tracking input actions to the [Tracked Pose Driver](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.TrackedPoseDriver.html) component and implemented your own Model functionality then you can move the remaining input actions from the original [XRController](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.XRController.html) to the Interactors themselves. The following image highlights the new controller prefab interactors fields that we needed to update for the XRI3 migration. ![Step 3](Images/XRI2ToXRI3Guide/XRI2ToXRI3Step3.png) ### MRTK InputReaders -As you may have noticed already MRTK controller prefabs now have a new child in which we group Input actions for pinch and UI interaction. These are shown in the next figure: +As you may have noticed that MRTK controller prefabs now have a new child in which we group Input actions for pinch and UI interaction. These are shown in the next figure: ![MRTK Input Readers](Images/XRI2ToXRI3Guide/MRTKInputReaders.png) -We added this child + script as a workaround for devices without interaction profiles for hands, however, if your solution does not have a use-case without hands interactions profiles then you can safely map the MRTK's InputReaders' input actions directly in their corresponding Interactor fields. +We added this child + script as a workaround for devices without interaction profiles for hands; however, if your solution does not have a use-case without hands interactions profiles then you can safely map the MRTK's InputReaders' input actions directly in their corresponding Interactor fields. ### TrackedPoseDriver and ModeManagedRoot references @@ -66,7 +66,7 @@ In addition to the InputReaders child you may have also noticed that MRTK intera ![TrackedPoseDriver and ModeManagedRoot](Images/XRI2ToXRI3Guide/TPDandMMR.png) -These are just convenient fields to hold references to the parent controller [Tracked Pose Driver](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.TrackedPoseDriver.html) component and GameObject. These are not mandatory for a successful XRI3 migration but they facilitate coding as well as writing Unity-tests. +These are just convenient fields to hold references to the parent controller [Tracked Pose Driver](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/api/UnityEngine.InputSystem.XR.TrackedPoseDriver.html) component and GameObject. These are not mandatory for a successful XRI3 migration but they facilitate coding as well as writing Unity tests. ## Step 4 - Update scripts @@ -75,12 +75,19 @@ For the XRI3 migration we modified our scripts with two goals: * Adhere to the new XRI3 patterns. * Provide backward compatibility. -As you will notice in the code many of our changes query the Input Compatibility Mode field to differentiate between XRI2 functionality and XRI3 functionality. This is not mandatory for a successful XRI3 migration, however, we wanted to create a smooth transition for all of you and did our best to ensure backward compatibily as you migrate your forks or solutions. +As you will notice in the code many of our changes query the Input Compatibility Mode field to differentiate between XRI2 functionality and XRI3 functionality. This is not mandatory for a successful XRI3 migration, however, we wanted to create a smooth transition for all of you and did our best to ensure backward compatibility as you migrate your forks or solutions. We encourage you to check the code in each script as well as the commit history to get a sense of the changes that were needed. -## Step 5 - Update Unity-tests +If you have any custom interactors based on MRTK interfaces, the following table will help you move from deprecated MRTK interfaces to XRI3-compatible interfaces: -Last but not least, Unity-tests! We created several new Unity-tests to ensure the correct functionality of the new XRI3 MRTK rig as well as the old functionality. We encourage you to visit the code and commit history related to Unity-tests to get a sense of the changes. Note that the changes focus mostly on where and how the input actions are queried but the overall functionality test remains the same. +| MRTK3 interface | XRI3 interface | +| --- | --- | +| `MixedReality.Toolkit.IHandedInteractor` | `UnityEngine.XR.Interaction.Toolkit.Interactors.IXRInteractor` | +| `MixedReality.Toolkit.IVariableSelectInteractor` | `UnityEngine.XR.Interaction.Toolkit.Interactors.IXRInteractionStrengthInteractor` | -Thank you for reading this guide, we hope it empowers you to achieve more. Please feel free to submit an issue if you have comments or questions. \ No newline at end of file +## Step 5 - Update Unity tests + +Last but not least, Unity tests! We created several new Unity tests to ensure the correct functionality of the new XRI3 MRTK rig as well as the old functionality. We encourage you to visit the code and commit history related to Unity tests to get a sense of the changes. Note that the changes focus mostly on where and how the input actions are queried but the overall functionality test remains the same. + +Thank you for reading this guide, we hope it empowers you to achieve more. Please feel free to submit an issue if you have comments or questions. diff --git a/org.mixedrealitytoolkit.core/CHANGELOG.md b/org.mixedrealitytoolkit.core/CHANGELOG.md index ffe977dc0..0d102ee06 100644 --- a/org.mixedrealitytoolkit.core/CHANGELOG.md +++ b/org.mixedrealitytoolkit.core/CHANGELOG.md @@ -2,12 +2,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## Unreleased + +### Changed + +* Updated `StatefulInteractable` to work across all `IXRInteractionStrengthInteractor` implementations, instead of just MRTK-specific `IVariableSelectInteractor` implementations. [PR #1085](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1085) + +### Deprecated + +* Deprecated `IVariableSelectInteractor`, as its info is duplicative with `IXRInteractionStrengthInteractor`. [PR #1085](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1085) + ## [4.0.0-pre.2] - 2025-12-05 ### Added * Added input action focus handling to disable controller/hand tracked state when the application goes out of focus. [PR #1039](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1039) -* Added ToInteractorHandedness extension for XRNode. [PR #1042](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1042) +* Added `ToInteractorHandedness` extension for `XRNode`. [PR #1042](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1042) ### Changed @@ -16,18 +26,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Removed -* Removed ITrackedInteractor, as it was supporting an unused codepath and there are better ways to get this data (like querying the attach transform). [PR #1044](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1044) +* Removed `ITrackedInteractor`, as it was supporting an unused codepath and there are better ways to get this data (like querying the attach transform). [PR #1044](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1044) ### Deprecated -* Deprecated IHandedInteractor, as its info is now queryable directly from IXRInteractor's handedness property. [PR #1042](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1042) -* Deprecated FindObjectUtility, as it was a backwards-compatibility layer for pre-2021.3.18. Since our min version is now 2022.3, we can just call the API directly. [PR #1058](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1058) +* Deprecated `IHandedInteractor`, as its info is now queryable directly from `IXRInteractor`'s `handedness` property. [PR #1042](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1042) +* Deprecated `FindObjectUtility`, as it was a backwards-compatibility layer for pre-2021.3.18. Since our min version is now 2022.3, we can just call the API directly. [PR #1058](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1058) ## [4.0.0-pre.1] - 2024-07-09 ### Added -* Added ITrackedInteractor to represent interactor with parent pose backed by a tracked input device. +* Added `ITrackedInteractor` to represent interactor with parent pose backed by a tracked input device. ### Changed diff --git a/org.mixedrealitytoolkit.core/Interactables/StatefulInteractable.cs b/org.mixedrealitytoolkit.core/Interactables/StatefulInteractable.cs index 8019f5502..248876f47 100644 --- a/org.mixedrealitytoolkit.core/Interactables/StatefulInteractable.cs +++ b/org.mixedrealitytoolkit.core/Interactables/StatefulInteractable.cs @@ -263,8 +263,8 @@ protected override void OnDestroy() /// /// Derived classes should override this method to specify custom selection math. /// The default implementation allows for variable selection from - /// objects, calculated using - /// . + /// objects, calculated using + /// . /// public virtual float GetSelectionProgress() { @@ -272,20 +272,32 @@ public virtual float GetSelectionProgress() { float selectionProgress = 0.0f; - foreach (var interactor in interactorsHovering) + foreach (IXRHoverInteractor interactor in interactorsHovering) { - if (interactor is IVariableSelectInteractor variableSelectInteractor) + if (interactor is IXRInteractionStrengthInteractor interactionStrengthInteractor) + { + selectionProgress = Mathf.Max(selectionProgress, GetInteractionStrength(interactor)); + } +#pragma warning disable CS0618 // Type or member is obsolete + else if (interactor is IVariableSelectInteractor variableSelectInteractor) { selectionProgress = Mathf.Max(selectionProgress, variableSelectInteractor.SelectProgress); } +#pragma warning restore CS0618 // Type or member is obsolete } - foreach (var interactor in interactorsSelecting) + foreach (IXRSelectInteractor interactor in interactorsSelecting) { - if (interactor is IVariableSelectInteractor variableSelectInteractor) + if (interactor is IXRInteractionStrengthInteractor interactionStrengthInteractor) + { + selectionProgress = Mathf.Max(selectionProgress, GetInteractionStrength(interactor)); + } +#pragma warning disable CS0618 // Type or member is obsolete + else if (interactor is IVariableSelectInteractor variableSelectInteractor) { selectionProgress = Mathf.Max(selectionProgress, variableSelectInteractor.SelectProgress); } +#pragma warning restore CS0618 // Type or member is obsolete else { selectionProgress = 1.0f; diff --git a/org.mixedrealitytoolkit.core/Interactors/IGazePinchInteractor.cs b/org.mixedrealitytoolkit.core/Interactors/IGazePinchInteractor.cs index 6f5b0458d..9027a20be 100644 --- a/org.mixedrealitytoolkit.core/Interactors/IGazePinchInteractor.cs +++ b/org.mixedrealitytoolkit.core/Interactors/IGazePinchInteractor.cs @@ -6,8 +6,9 @@ namespace MixedReality.Toolkit /// /// An interface that all gaze-pinch-like interactors must implement. /// - public interface IGazePinchInteractor : IVariableSelectInteractor - { - - } -} \ No newline at end of file + public interface IGazePinchInteractor : +#pragma warning disable CS0618 // Type or member is obsolete + IVariableSelectInteractor +#pragma warning restore CS0618 // Type or member is obsolete + { } +} diff --git a/org.mixedrealitytoolkit.core/Interactors/IHandedInteractor.cs b/org.mixedrealitytoolkit.core/Interactors/IHandedInteractor.cs index a50317286..1258b5ae1 100644 --- a/org.mixedrealitytoolkit.core/Interactors/IHandedInteractor.cs +++ b/org.mixedrealitytoolkit.core/Interactors/IHandedInteractor.cs @@ -9,13 +9,13 @@ namespace MixedReality.Toolkit /// /// An interface that all interactors with the concept of handedness implement. /// - [Obsolete("Use handedness from IXRInteractor instead.")] + [Obsolete(nameof(IHandedInteractor) + " has been deprecated in version 4.0.0. Use " + nameof(IXRInteractor) + " instead.")] public interface IHandedInteractor : IXRInteractor { /// /// Returns the Handedness of this interactor. /// - [Obsolete("Use handedness from IXRInteractor instead.")] + [Obsolete("This property has been deprecated in version 4.0.0. Use " + nameof(handedness) + " instead.")] public Handedness Handedness { get; } } } diff --git a/org.mixedrealitytoolkit.core/Interactors/IVariableSelectInteractor.cs b/org.mixedrealitytoolkit.core/Interactors/IVariableSelectInteractor.cs index 134ecaae7..5c21de73b 100644 --- a/org.mixedrealitytoolkit.core/Interactors/IVariableSelectInteractor.cs +++ b/org.mixedrealitytoolkit.core/Interactors/IVariableSelectInteractor.cs @@ -1,6 +1,7 @@ // Copyright (c) Mixed Reality Toolkit Contributors // Licensed under the BSD 3-Clause +using System; using UnityEngine.XR.Interaction.Toolkit.Interactors; namespace MixedReality.Toolkit @@ -9,6 +10,7 @@ namespace MixedReality.Toolkit /// An interface that all interactors which offer /// variable selection must implement. /// + [Obsolete(nameof(IVariableSelectInteractor) + " has been deprecated in version 4.0.0. Use " + nameof(IXRInteractionStrengthInteractor) + " instead.")] public interface IVariableSelectInteractor : IXRSelectInteractor, IXRHoverInteractor { /// @@ -19,6 +21,7 @@ public interface IVariableSelectInteractor : IXRSelectInteractor, IXRHoverIntera /// For gaze-pinch interactors, this is the pinch progress. /// For motion controllers, this is the analog trigger press amount. /// + [Obsolete("This property has been deprecated in version 4.0.0. Use " + nameof(IXRInteractionStrengthInteractor.GetInteractionStrength) + " or " + nameof(IXRInteractionStrengthInteractor.largestInteractionStrength) + " instead.")] float SelectProgress { get; } } } diff --git a/org.mixedrealitytoolkit.input/CHANGELOG.md b/org.mixedrealitytoolkit.input/CHANGELOG.md index bb0000f72..5692cad62 100644 --- a/org.mixedrealitytoolkit.input/CHANGELOG.md +++ b/org.mixedrealitytoolkit.input/CHANGELOG.md @@ -2,6 +2,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## Unreleased + +### Changed + +* Updated `MRTKLineVisual` and `RingReticle` to work across all `IXRInteractionStrengthInteractor` implementations, instead of just MRTK-specific `IVariableSelectInteractor` implementations. [PR #1085](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1085) + +### Deprecated + +* Deprecated `IVariableSelectInteractor` across the interactor implementations, as its info is duplicative with `IXRInteractionStrengthInteractor`. [PR #1085](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1085) + ## [4.0.0-pre.2] - 2025-12-05 ### Changed @@ -11,7 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Deprecated -* Deprecated IHandedInteractor across the interactor implementations, as its info is now queryable directly from IXRInteractor's handedness property. [PR #1042](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1042) +* Deprecated `IHandedInteractor` across the interactor implementations, as its info is now queryable directly from `IXRInteractor`'s `handedness` property. [PR #1042](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1042) ### Removed diff --git a/org.mixedrealitytoolkit.input/Interactors/GazePinch/GazePinchInteractor.cs b/org.mixedrealitytoolkit.input/Interactors/GazePinch/GazePinchInteractor.cs index e4c3f3a2d..51104a152 100644 --- a/org.mixedrealitytoolkit.input/Interactors/GazePinch/GazePinchInteractor.cs +++ b/org.mixedrealitytoolkit.input/Interactors/GazePinch/GazePinchInteractor.cs @@ -196,44 +196,30 @@ private bool IsTracked #region IHandedInteractor /// - [Obsolete("Use handedness from IXRInteractor instead.")] - Handedness IHandedInteractor.Handedness - { - get - { - if (forceDeprecatedInput) - { - return handController.HandNode.ToHandedness(); - } - - return handedness.ToHandedness(); - } - } + [Obsolete("This property has been deprecated in version 4.0.0. Use " + nameof(IXRInteractor.handedness) + " instead.")] + Handedness IHandedInteractor.Handedness => forceDeprecatedInput ? handController.HandNode.ToHandedness() : handedness.ToHandedness(); #endregion IHandedInteractor #region IVariableSelectInteractor /// - public float SelectProgress + [Obsolete("This property has been deprecated in version 4.0.0. Use " + nameof(IXRInteractionStrengthInteractor.GetInteractionStrength) + " or " + nameof(IXRInteractionStrengthInteractor.largestInteractionStrength) + " instead.")] + float IVariableSelectInteractor.SelectProgress { get { -#pragma warning disable CS0618 // Type or member is obsolete if (forceDeprecatedInput) { return handController.selectInteractionState.value; } -#pragma warning restore CS0618 // Type or member is obsolete else if (selectInput != null) { return selectInput.ReadValue(); } - else - { - Debug.LogWarning($"Unable to determine SelectProgress of {name} because there is no Select Input Configuration set for this interactor."); - } - return 0.0f; + + Debug.LogWarning($"Unable to determine SelectProgress of {name} because there is no Select Input Configuration set for this interactor."); + return 0; } } @@ -286,7 +272,7 @@ public override void GetValidTargets(List targets) // If we are hovering something and also have gone past the sticky hover threshold, // we should *only* consider the current hover target, regardless of what the // gaze is currently actually looking at. (Sticky hover, ADO#1941) - if (hasHover && SelectProgress > stickyHoverThreshold) + if (hasHover && largestInteractionStrength.Value > stickyHoverThreshold) { targets.Add(interactablesHovered[0]); } @@ -404,7 +390,7 @@ public override bool CanHover(IXRHoverInteractable interactable) // If so, should we be allowed to initiate a new hover on it? // This prevents us from "rolling off" one target and immediately // semi-pressing another. - bool canHoverNew = !isNew || SelectProgress < relaxationThreshold; + bool canHoverNew = !isNew || largestInteractionStrength.Value < relaxationThreshold; return base.CanHover(interactable) && stickySelect && ready && canHoverNew; } diff --git a/org.mixedrealitytoolkit.input/Interactors/HandJointInteractor.cs b/org.mixedrealitytoolkit.input/Interactors/HandJointInteractor.cs index b00630872..de4d66b7f 100644 --- a/org.mixedrealitytoolkit.input/Interactors/HandJointInteractor.cs +++ b/org.mixedrealitytoolkit.input/Interactors/HandJointInteractor.cs @@ -61,7 +61,7 @@ public GameObject ModeManagedRoot #region IHandedInteractor /// - [Obsolete("Use handedness from IXRInteractor instead.")] + [Obsolete("This property has been deprecated in version 4.0.0. Use " + nameof(IXRInteractor.handedness) + " instead.")] Handedness IHandedInteractor.Handedness { get diff --git a/org.mixedrealitytoolkit.input/Interactors/InteractorVisuals/MRTKLineVisual.cs b/org.mixedrealitytoolkit.input/Interactors/InteractorVisuals/MRTKLineVisual.cs index 652e6aa70..dbfb57810 100644 --- a/org.mixedrealitytoolkit.input/Interactors/InteractorVisuals/MRTKLineVisual.cs +++ b/org.mixedrealitytoolkit.input/Interactors/InteractorVisuals/MRTKLineVisual.cs @@ -391,20 +391,19 @@ private void UpdateLineVisual() // Now handle coloring the line visual // If our interactor is a variable select interactor, change the material property based on select progress - IVariableSelectInteractor variableSelectInteractor = rayInteractor as IVariableSelectInteractor; - if (variableSelectInteractor != null) + if (rayInteractor != null) { lineRenderer.GetPropertyBlock(propertyBlock); - propertyBlock.SetFloat("_Shift_", variableSelectInteractor.SelectProgress); + propertyBlock.SetFloat("_Shift_", rayInteractor.largestInteractionStrength.Value); lineRenderer.SetPropertyBlock(propertyBlock); } // If we are hovering over a valid object or are currently selecting one, lerp the color based on selectedness if (rayHasHit || rayInteractor.hasSelection) { - if (variableSelectInteractor != null) + if (rayInteractor != null) { - cachedGradient = ColorUtilities.GradientLerp(ValidColorGradient, SelectActiveColorGradient, variableSelectInteractor.SelectProgress); + cachedGradient = ColorUtilities.GradientLerp(ValidColorGradient, SelectActiveColorGradient, rayInteractor.largestInteractionStrength.Value); } else { diff --git a/org.mixedrealitytoolkit.input/Interactors/InteractorVisuals/RingReticle.cs b/org.mixedrealitytoolkit.input/Interactors/InteractorVisuals/RingReticle.cs index 82ca06a51..177a00c7d 100644 --- a/org.mixedrealitytoolkit.input/Interactors/InteractorVisuals/RingReticle.cs +++ b/org.mixedrealitytoolkit.input/Interactors/InteractorVisuals/RingReticle.cs @@ -100,10 +100,16 @@ public void UpdateVisual(ReticleVisualUpdateArgs args) { if (displaySelectionProgress) { - if (args.Interactor is IVariableSelectInteractor variableSelectInteractor) + if (args.Interactor is IXRInteractionStrengthInteractor interactionStrengthInteractor) + { + UpdateReticleProgressVisual(interactionStrengthInteractor.largestInteractionStrength.Value); + } +#pragma warning disable CS0618 // Type or member is obsolete + else if (args.Interactor is IVariableSelectInteractor variableSelectInteractor) { UpdateReticleProgressVisual(variableSelectInteractor.SelectProgress); } +#pragma warning restore CS0618 // Type or member is obsolete else if (args.Interactor is IXRSelectInteractor selectInteractor) { UpdateReticleProgressVisual(selectInteractor.isSelectActive ? 1 : 0); diff --git a/org.mixedrealitytoolkit.input/Interactors/Poke/PokeInteractor.cs b/org.mixedrealitytoolkit.input/Interactors/Poke/PokeInteractor.cs index 1aace6efe..94d9796f4 100644 --- a/org.mixedrealitytoolkit.input/Interactors/Poke/PokeInteractor.cs +++ b/org.mixedrealitytoolkit.input/Interactors/Poke/PokeInteractor.cs @@ -106,7 +106,7 @@ xrController is ArticulatedHandController handController && #region IHandedInteractor /// - [Obsolete("Use handedness from IXRInteractor instead.")] + [Obsolete("This property has been deprecated in version 4.0.0. Use " + nameof(IXRInteractor.handedness) + " instead.")] Handedness IHandedInteractor.Handedness { get diff --git a/org.mixedrealitytoolkit.input/Interactors/Ray/MRTKRayInteractor.cs b/org.mixedrealitytoolkit.input/Interactors/Ray/MRTKRayInteractor.cs index 821f223a7..a353566da 100644 --- a/org.mixedrealitytoolkit.input/Interactors/Ray/MRTKRayInteractor.cs +++ b/org.mixedrealitytoolkit.input/Interactors/Ray/MRTKRayInteractor.cs @@ -27,9 +27,9 @@ namespace MixedReality.Toolkit.Input public class MRTKRayInteractor : XRRayInteractor, IRayInteractor, - IVariableSelectInteractor, IModeManagedInteractor, #pragma warning disable CS0618 // Type or member is obsolete + IVariableSelectInteractor, IHandedInteractor #pragma warning restore CS0618 // Type or member is obsolete { @@ -142,36 +142,26 @@ private bool IsTracked #region IHandedInteractor /// - [Obsolete("Use handedness from IXRInteractor instead.")] - Handedness IHandedInteractor.Handedness - { - get - { - if (forceDeprecatedInput && - xrController is ArticulatedHandController handController) - { - return handController.HandNode.ToHandedness(); - } - - return handedness.ToHandedness(); - } - } + [Obsolete("This property has been deprecated in version 4.0.0. Use " + nameof(IXRInteractor.handedness) + " instead.")] + Handedness IHandedInteractor.Handedness => forceDeprecatedInput && + xrController is ArticulatedHandController handController + ? handController.HandNode.ToHandedness() + : handedness.ToHandedness(); #endregion IHandedInteractor #region IVariableSelectInteractor /// - public float SelectProgress + [Obsolete("This property has been deprecated in version 4.0.0. Use " + nameof(IXRInteractionStrengthInteractor.GetInteractionStrength) + " or " + nameof(IXRInteractionStrengthInteractor.largestInteractionStrength) + " instead.")] + float IVariableSelectInteractor.SelectProgress { get { -#pragma warning disable CS0618 // Type or member is obsolete if (forceDeprecatedInput) { return xrController.selectInteractionState.value; } -#pragma warning restore CS0618 else if (selectInput != null) { return selectInput.ReadValue(); @@ -206,7 +196,7 @@ public override bool CanHover(IXRHoverInteractable interactable) // If so, should we be allowed to initiate a new hover on it? // This prevents us from "rolling off" one target and immediately // semi-pressing another. - bool canHoverNew = !isNew || SelectProgress < relaxationThreshold; + bool canHoverNew = !isNew || largestInteractionStrength.Value < relaxationThreshold; return ready && base.CanHover(interactable) && canHoverNew; } @@ -307,7 +297,7 @@ public override void ProcessInteractor(XRInteractionUpdateOrder.UpdatePhase upda if (updatePhase == XRInteractionUpdateOrder.UpdatePhase.Dynamic) { // If we've fully relaxed, we can begin hovering/selecting a new target. - if (SelectProgress < relaxationThreshold) + if (largestInteractionStrength.Value < relaxationThreshold) { isRelaxedBeforeSelect = true; } diff --git a/org.mixedrealitytoolkit.uxcomponents.noncanvas/Tests/Runtime/PressableButtonTests.cs b/org.mixedrealitytoolkit.uxcomponents.noncanvas/Tests/Runtime/PressableButtonTests.cs index d971652f8..4a15d4ef1 100644 --- a/org.mixedrealitytoolkit.uxcomponents.noncanvas/Tests/Runtime/PressableButtonTests.cs +++ b/org.mixedrealitytoolkit.uxcomponents.noncanvas/Tests/Runtime/PressableButtonTests.cs @@ -77,7 +77,6 @@ public IEnumerator ButtonInstantiateDisableThenEnableBeforeStart([ValueSource(na PressableButton buttonComponent = testButton.GetComponent(); - // We don't get inheritdoc summaries here for some reason? var selectedness = buttonComponent.GetSelectionProgress(); Assert.IsTrue(selectedness == 0.0f, "The button prefabs should start with 0 selectedness"); diff --git a/org.mixedrealitytoolkit.uxcore/Button/PressableButton.cs b/org.mixedrealitytoolkit.uxcore/Button/PressableButton.cs index ac95cde2c..196b60ed0 100644 --- a/org.mixedrealitytoolkit.uxcore/Button/PressableButton.cs +++ b/org.mixedrealitytoolkit.uxcore/Button/PressableButton.cs @@ -200,7 +200,7 @@ public SpaceMode DistanceSpaceMode /// /// If the value is smoothed to within this threshold of 0 or 1, the will snap to 0 or 1. /// - private const float selectionProgressEpsilon = 0.00001f; + private const float SelectionProgressEpsilon = 0.00001f; #endregion Private Members @@ -416,20 +416,34 @@ public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase up foreach (var interactor in interactorsHovering) { - if (interactor is IVariableSelectInteractor variableSelectInteractor) + if (interactor is IXRInteractionStrengthInteractor interactionStrengthInteractor) + { + totalPressProgress = Mathf.Max(totalPressProgress, GetInteractionStrength(interactor)); + isVariablySelected = true; + } +#pragma warning disable CS0618 // Type or member is obsolete + else if (interactor is IVariableSelectInteractor variableSelectInteractor) { totalPressProgress = Mathf.Max(totalPressProgress, variableSelectInteractor.SelectProgress); isVariablySelected = true; } +#pragma warning restore CS0618 // Type or member is obsolete } foreach (var interactor in interactorsSelecting) { - if (interactor is IVariableSelectInteractor variableSelectInteractor) + if (interactor is IXRInteractionStrengthInteractor interactionStrengthInteractor) + { + totalPressProgress = Mathf.Max(totalPressProgress, GetInteractionStrength(interactor)); + isVariablySelected = true; + } +#pragma warning disable CS0618 // Type or member is obsolete + else if (interactor is IVariableSelectInteractor variableSelectInteractor) { totalPressProgress = Mathf.Max(totalPressProgress, variableSelectInteractor.SelectProgress); isVariablySelected = true; } +#pragma warning restore CS0618 // Type or member is obsolete else if (!(interactor is IPokeInteractor)) // Exclude PokeInteractors because we've already counted them. { totalPressProgress = 1.0f; @@ -445,12 +459,11 @@ public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase up selectionProgress = Mathf.Lerp(selectionProgress, totalPressProgress, totalPressProgress == 1 ? extendSpeed : returnSpeed); // Snap selectionProgress to ends of range, plus/minus selectionProgressEpsilon. - if (selectionProgress < selectionProgressEpsilon) + if (selectionProgress < SelectionProgressEpsilon) { selectionProgress = 0; } - - if (selectionProgress > 1 - selectionProgressEpsilon) + else if (selectionProgress > 1 - SelectionProgressEpsilon) { selectionProgress = 1; } diff --git a/org.mixedrealitytoolkit.uxcore/CHANGELOG.md b/org.mixedrealitytoolkit.uxcore/CHANGELOG.md index bfed8e569..a43874f52 100644 --- a/org.mixedrealitytoolkit.uxcore/CHANGELOG.md +++ b/org.mixedrealitytoolkit.uxcore/CHANGELOG.md @@ -2,12 +2,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## Unreleased + +### Changed + +* Updated `PressableButton` to work across all `IXRInteractionStrengthInteractor` implementations, instead of just MRTK-specific `IVariableSelectInteractor` implementations. [PR #1085](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1085) + ## [4.0.0-pre.2] - 2025-12-05 ### Changed * Updated the minimum editor version to 2022.3.6f1 [PR #1003](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1003) -* Updated InteractablePulse to work across all IXRInteractor implementations, instead of just MRTK-specific IHandedInteractor implementations. [PR #1042](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1042) +* Updated `InteractablePulse` to work across all `IXRInteractor` implementations, instead of just MRTK-specific `IHandedInteractor` implementations. [PR #1042](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1042) ## [4.0.0-pre.1] - 2024-07-09