Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,26 @@ MonoBehaviour:
company: Unity
priority: 0
required: 0
--- !u!114 &-5000202051992085229
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30587bb28b5390644ae70f801841a073, type: 3}
m_Name: MRTKFocusFeature Android
m_EditorClassIdentifier:
m_enabled: 1
nameUi: MRTK3 Session Focus
version: 4.0.0
featureIdInternal: org.mixedreality.toolkit.input.focus
openxrExtensionStrings:
company: Mixed Reality Toolkit Contributors
priority: 0
required: 0
--- !u!114 &-4989097037534641705
MonoBehaviour:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -394,6 +414,7 @@ MonoBehaviour:
- {fileID: -5492763381520605560}
- {fileID: 720212866400260749}
- {fileID: -2783824018031006640}
- {fileID: -4614918767838866102}
- {fileID: 4334429337943452973}
- {fileID: -5448262054166454653}
- {fileID: -9173909432611776730}
Expand Down Expand Up @@ -429,6 +450,26 @@ MonoBehaviour:
company: Unity
priority: 0
required: 0
--- !u!114 &-4614918767838866102
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30587bb28b5390644ae70f801841a073, type: 3}
m_Name: MRTKFocusFeature Standalone
m_EditorClassIdentifier:
m_enabled: 1
nameUi: MRTK3 Session Focus
version: 4.0.0
featureIdInternal: org.mixedreality.toolkit.input.focus
openxrExtensionStrings:
company: Mixed Reality Toolkit Contributors
priority: 0
required: 0
--- !u!114 &-3765664599707111037
MonoBehaviour:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -536,6 +577,7 @@ MonoBehaviour:
- {fileID: -7229825001273466666}
- {fileID: 4508051287823359615}
- {fileID: 2835676197965704550}
- {fileID: -5000202051992085229}
- {fileID: -7431403579802858517}
- {fileID: -3273436338079595365}
- {fileID: 8773911662759437579}
Expand Down Expand Up @@ -651,6 +693,26 @@ MonoBehaviour:
company: Unity
priority: 0
required: 0
--- !u!114 &-1685409458817180080
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30587bb28b5390644ae70f801841a073, type: 3}
m_Name: MRTKFocusFeature Metro
m_EditorClassIdentifier:
m_enabled: 1
nameUi: MRTK3 Session Focus
version: 4.0.0
featureIdInternal: org.mixedreality.toolkit.input.focus
openxrExtensionStrings:
company: Mixed Reality Toolkit Contributors
priority: 0
required: 0
--- !u!114 &-1310172892294911860
MonoBehaviour:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -934,6 +996,7 @@ MonoBehaviour:
- {fileID: 8785654261743502636}
- {fileID: 2622006578924267534}
- {fileID: -6733472631637007722}
- {fileID: -1685409458817180080}
- {fileID: 4575689165844638740}
- {fileID: 6698335440458243644}
- {fileID: -2219742231848666541}
Expand Down
6 changes: 6 additions & 0 deletions org.mixedrealitytoolkit.core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## Unreleased

### Removed

* Removed input action focus handling from `MRTKLifecycleManager` and moved to the Input package. [PR #1057](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1057)

## [4.0.0-pre.2] - 2025-12-05

### Added
Expand Down
32 changes: 2 additions & 30 deletions org.mixedrealitytoolkit.core/Subsystems/MRTKLifecycleManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Collections.Generic;
using Unity.Profiling;
using UnityEngine;
using UnityEngine.InputSystem;

namespace MixedReality.Toolkit.Subsystems
{
Expand All @@ -19,15 +18,12 @@ public class MRTKLifecycleManager :
MonoBehaviour,
IDisposable
{
[SerializeField, Tooltip("A set of input actions to enable/disable according to the app's focus state.")]
private InputActionReference[] inputActionReferences;

private List<IMRTKManagedSubsystem> managedSubsystems = new List<IMRTKManagedSubsystem>();

/// <summary>
/// The list of <see cref="IMRTKManagedSubsystem"/> objects being managed by this class.
/// </summary>
protected List<IMRTKManagedSubsystem> ManagedSubsystems
protected List<IMRTKManagedSubsystem> ManagedSubsystems
{
get => managedSubsystems;
set => managedSubsystems = value;
Expand Down Expand Up @@ -115,7 +111,7 @@ private void OnDisable()

/// <summary>
/// A Unity event function that is called when the script component has been enabled.
/// </summary>
/// </summary>
private void OnEnable()
{
using (OnEnableProfilerMarker.Auto())
Expand Down Expand Up @@ -180,30 +176,6 @@ private void LateUpdate()
}
}

/// <summary>
/// Sent to all GameObjects when the player gets or loses focus.
/// </summary>
/// <param name="focus"><see langword="true"/> if the GameObjects have focus, else <see langword="false"/>.</param>
protected void OnApplicationFocus(bool focus)
{
// We want to ensure we're focused for input, as some runtimes continue reporting "tracked" while pose updates are paused.
// This is allowed, per-spec, as a "should": "Runtimes should make input actions inactive while the application is unfocused,
// and applications should react to an inactive input action by skipping rendering of that action's input avatar
// (depictions of hands or other tracked objects controlled by the user)."

foreach (InputActionReference reference in inputActionReferences)
{
if (focus)
{
reference.action.Enable();
}
else
{
reference.action.Disable();
}
}
}

#endregion MonoBehaviour

/// <summary>
Expand Down
13 changes: 13 additions & 0 deletions org.mixedrealitytoolkit.input/Assets/Prefabs/MRTK XR Rig.prefab
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ GameObject:
- component: {fileID: 2351505567455720332}
- component: {fileID: 4160709927669568829}
- component: {fileID: 6400715630075217958}
- component: {fileID: 1798554929582623642}
m_Layer: 0
m_Name: MRTK XR Rig
m_TagString: Untagged
Expand Down Expand Up @@ -377,6 +378,18 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 1a107350295baaf4489642caa92f05de, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &1798554929582623642
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2351505567455720334}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 671b97df530b06e46893c4189b3ceab4, type: 3}
m_Name:
m_EditorClassIdentifier:
inputActionReferences:
- {fileID: -7613329581162844239, guid: 18c412191cdc9274897f101c7fd5316f, type: 3}
- {fileID: 3239510804178183174, guid: 18c412191cdc9274897f101c7fd5316f, type: 3}
Expand Down
7 changes: 7 additions & 0 deletions org.mixedrealitytoolkit.input/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## Unreleased

### Added

* Added `MRTKFocusFeature` to provide XrSession focus info to MRTK components. [PR #1057](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1057)
* Added input action focus handling to disable controller/hand tracked state when the XrSession goes out of focus. [PR #1057](https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity/pull/1057)

## [4.0.0-pre.2] - 2025-12-05

### Changed
Expand Down
45 changes: 34 additions & 11 deletions org.mixedrealitytoolkit.input/Controllers/HandModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the BSD 3-Clause

using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.Interaction.Toolkit.Inputs.Readers;

namespace MixedReality.Toolkit.Input
Expand Down Expand Up @@ -60,15 +59,31 @@ public Transform ModelPrefab

#endregion Associated hand select values

/// <summary>
/// See <see cref="MonoBehaviour"/>.
/// </summary>
protected virtual void Awake()
{
// Create empty container transform for the model if none specified.
// This is not strictly necessary to create since this GameObject could be used
// as the parent for the instantiated prefab, but doing so anyway for backwards compatibility.
if (modelParent == null)
{
modelParent = new GameObject($"[{gameObject.name}] Model Parent").transform;
modelParent.SetParent(transform, false);
modelParent.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
}
}

/// <summary>
/// A Unity event function that is called on the frame when a script is enabled just before any of the update methods are called the first time.
/// </summary>
protected virtual void Start()
{
// Instantiate the model prefab if it is set
if (ModelPrefab != null)
if (modelPrefab != null)
{
model = Instantiate(ModelPrefab, ModelParent);
model = Instantiate(modelPrefab, modelParent);

Debug.Assert(selectInput != null, $"The Select Input reader for {name} is not set and will not be used with the instantiated hand model.");

Expand All @@ -78,21 +93,29 @@ protected virtual void Start()
selectInputVisualizer.SelectInput = selectInput;
}
}

MRTKFocusFeature.XrSessionFocused.SubscribeAndUpdate(OnXrSessionFocus);
}

/// <summary>
/// See <see cref="MonoBehaviour"/>.
/// </summary>
protected virtual void Awake()
private void OnDestroy() => MRTKFocusFeature.XrSessionFocused.Unsubscribe(OnXrSessionFocus);

/// <summary>
/// Sent when the XrSession gains or loses focus.
/// </summary>
/// <param name="focus"><see langword="true"/> if the XrSession has focus, else <see langword="false"/>.</param>
private void OnXrSessionFocus(bool focus)
{
// Create empty container transform for the model if none specified.
// This is not strictly necessary to create since this GameObject could be used
// as the parent for the instantiated prefab, but doing so anyway for backwards compatibility.
if (modelParent == null)
// We want to ensure we're focused for input visualization, as some runtimes continue reporting "tracked" while pose updates are paused.
// This is allowed, per-spec, as a "should": "Runtimes should make input actions inactive while the application is unfocused,
// and applications should react to an inactive input action by skipping rendering of that action's input avatar
// (depictions of hands or other tracked objects controlled by the user)."

if (modelParent != null)
{
modelParent = new GameObject($"[{gameObject.name}] Model Parent").transform;
modelParent.SetParent(transform, false);
modelParent.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
modelParent.gameObject.SetActive(focus);
}
}
}
Expand Down
58 changes: 53 additions & 5 deletions org.mixedrealitytoolkit.input/Editor/InputValidation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,40 @@ private static void AddInputValidationRule()
{
foreach (var buildTargetGroup in MRTKProjectValidation.BuildTargetGroups)
{
MRTKProjectValidation.AddTargetDependentRules(new List<BuildValidationRule>() { GenerateSpeechInteractorRule(buildTargetGroup) }, buildTargetGroup);
MRTKProjectValidation.AddTargetDependentRules(new List<BuildValidationRule>() {
GenerateSpeechInteractorRule(buildTargetGroup)
}, buildTargetGroup);

#if UNITY_OPENXR_PRESENT
// Skip the standalone target as the hand subsystem rule for it is already present for all build targets
if (buildTargetGroup != BuildTargetGroup.Standalone)
{
MRTKProjectValidation.AddTargetDependentRules(new List<BuildValidationRule>() { GenerateUnityHandsRule(buildTargetGroup) }, buildTargetGroup);
MRTKProjectValidation.AddTargetDependentRules(new List<BuildValidationRule>() {
GenerateUnityHandsRule(buildTargetGroup),
GenerateMRTKFocusFeatureRule(buildTargetGroup)
}, buildTargetGroup);
}
#endif
}
MRTKProjectValidation.AddTargetIndependentRules(new List<BuildValidationRule>() { GenerateSkinWeightsRule(), GenerateGLTFastRule(),
MRTKProjectValidation.AddTargetIndependentRules(new List<BuildValidationRule>() {
GenerateSkinWeightsRule(),
GenerateGLTFastRule(),
#if UNITY_OPENXR_PRESENT
GenerateUnityHandsRule(BuildTargetGroup.Standalone),
#endif
});

// Only generate the KTX rule for platforms related to Meta
MRTKProjectValidation.AddTargetDependentRules(new List<BuildValidationRule>() { GenerateKTXRule(),
MRTKProjectValidation.AddTargetDependentRules(new List<BuildValidationRule>() {
GenerateKTXRule(),
#if UNITY_OPENXR_PRESENT
GenerateAndroidHandsRule(),
#endif
}, BuildTargetGroup.Android);
MRTKProjectValidation.AddTargetDependentRules(new List<BuildValidationRule>() { GenerateKTXRule() }, BuildTargetGroup.Standalone);

MRTKProjectValidation.AddTargetDependentRules(new List<BuildValidationRule>() {
GenerateKTXRule()
}, BuildTargetGroup.Standalone);
}

private static BuildValidationRule GenerateSpeechInteractorRule(BuildTargetGroup buildTargetGroup)
Expand Down Expand Up @@ -197,6 +208,43 @@ private static BuildValidationRule GenerateAndroidHandsRule()
};
#pragma warning restore CS0618 // Type or member is obsolete
}

private static BuildValidationRule GenerateMRTKFocusFeatureRule(BuildTargetGroup buildTargetGroup)
{
return new BuildValidationRule()
{
Category = "MRTK3",
Message = $"For MRTK3 input to work correctly on OpenXR, enable {MRTKFocusFeature.FriendlyName} in the OpenXR Settings.",
CheckPredicate = () =>
{
OpenXRSettings settings = OpenXRSettings.GetSettingsForBuildTargetGroup(buildTargetGroup);
if (settings == null)
{
return false;
}

MRTKFocusFeature focusFeature = settings.GetFeature<MRTKFocusFeature>();
return focusFeature != null && focusFeature.enabled;
},
FixIt = () =>
{
OpenXRSettings settings = OpenXRSettings.GetSettingsForBuildTargetGroup(buildTargetGroup);
if (settings == null)
{
return;
}

MRTKFocusFeature focusFeature = settings.GetFeature<MRTKFocusFeature>();
if (focusFeature != null)
{
focusFeature.enabled = true;
EditorUtility.SetDirty(settings);
}
},
FixItMessage = $"Enable {nameof(MRTKFocusFeature)} in the OpenXR settings.",
Error = true
};
}
#endif
}
}
Loading