Skip to content

Commit 862f405

Browse files
authored
Merge pull request #2784 from keveleigh/AddControllerFinder
[Solver PR 4] Add controller-tracking support to solvers
2 parents a0c9d31 + 102d1c3 commit 862f405

File tree

7 files changed

+331
-6
lines changed

7 files changed

+331
-6
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using Microsoft.MixedReality.Toolkit.Core.Definitions.Utilities;
5+
using Microsoft.MixedReality.Toolkit.Core.EventDatum.Input;
6+
using Microsoft.MixedReality.Toolkit.Core.Interfaces.Devices;
7+
using Microsoft.MixedReality.Toolkit.Core.Interfaces.InputSystem.Handlers;
8+
using Microsoft.MixedReality.Toolkit.Core.Managers;
9+
using UnityEngine;
10+
11+
namespace Microsoft.MixedReality.Toolkit.SDK.Utilities.Solvers
12+
{
13+
/// <summary>
14+
/// ControllerFinder is a base class providing simple event handling for getting/releasing MotionController Transforms.
15+
/// </summary>
16+
public abstract class ControllerFinder : MonoBehaviour, IMixedRealitySourceStateHandler
17+
{
18+
[SerializeField]
19+
[Tooltip("The handedness of the controller that should be found.")]
20+
private Handedness handedness = Handedness.None;
21+
22+
/// <summary>
23+
/// The handedness of the controller that should be found.
24+
/// </summary>
25+
public Handedness Handedness
26+
{
27+
get { return handedness; }
28+
set
29+
{
30+
// We need to refresh which controller we're attached to if we switch handedness.
31+
if (handedness != value)
32+
{
33+
handedness = value;
34+
RefreshControllerTransform();
35+
}
36+
}
37+
}
38+
39+
/// <summary>
40+
/// The Transform of the currently found controller.
41+
/// </summary>
42+
protected Transform ControllerTransform;
43+
44+
#region MonoBehaviour Implementation
45+
46+
protected virtual void OnEnable()
47+
{
48+
// Look if the controller has loaded.
49+
RefreshControllerTransform();
50+
}
51+
52+
#endregion MonoBehaviour Implementation
53+
54+
#region IMixedRealitySourceStateHandler Implementation
55+
56+
public void OnSourceDetected(SourceStateEventData eventData)
57+
{
58+
if (eventData.Controller.ControllerHandedness == handedness)
59+
{
60+
AddControllerTransform(eventData.Controller);
61+
}
62+
}
63+
64+
public void OnSourceLost(SourceStateEventData eventData)
65+
{
66+
if (eventData.Controller.ControllerHandedness == handedness)
67+
{
68+
RemoveControllerTransform();
69+
}
70+
}
71+
72+
#endregion IMixedRealitySourceStateHandler Implementation
73+
74+
/// <summary>
75+
/// Looks to see if the controller model already exists and registers it if so.
76+
/// </summary>
77+
protected virtual void TryAndAddControllerTransform()
78+
{
79+
// Look if the controller was already loaded. This could happen if the
80+
// GameObject was instantiated at runtime and the model loaded event has already fired.
81+
if (MixedRealityManager.InputSystem == null)
82+
{
83+
// The InputSystem could not be found.
84+
return;
85+
}
86+
87+
foreach (IMixedRealityController controller in MixedRealityManager.InputSystem.DetectedControllers)
88+
{
89+
if (controller.ControllerHandedness == handedness)
90+
{
91+
AddControllerTransform(controller);
92+
return;
93+
}
94+
}
95+
}
96+
97+
/// <summary>
98+
/// Starts to track the passed in controller's transform, assuming it meets the previously set handedness criteria.
99+
/// </summary>
100+
/// <param name="newController">The new controller to be tracked.</param>
101+
protected virtual void AddControllerTransform(IMixedRealityController newController)
102+
{
103+
if (newController.ControllerHandedness == handedness && newController.Visualizer.GameObjectProxy.transform != null && !newController.Visualizer.GameObjectProxy.transform.Equals(ControllerTransform))
104+
{
105+
ControllerTransform = newController.Visualizer.GameObjectProxy.transform;
106+
107+
OnControllerFound();
108+
}
109+
}
110+
111+
/// <summary>
112+
/// Remove whichever controller is currently tracked, if any.
113+
/// </summary>
114+
protected virtual void RemoveControllerTransform()
115+
{
116+
if (ControllerTransform != null)
117+
{
118+
OnControllerLost();
119+
120+
ControllerTransform = null;
121+
}
122+
}
123+
124+
/// <summary>
125+
/// Remove whichever controller is currently tracked, if any, and try to add a new one based on existing sources.
126+
/// </summary>
127+
protected virtual void RefreshControllerTransform()
128+
{
129+
if (ControllerTransform != null)
130+
{
131+
RemoveControllerTransform();
132+
}
133+
134+
TryAndAddControllerTransform();
135+
}
136+
137+
/// <summary>
138+
/// Override this method to act when the correct controller is actually found.
139+
/// This provides similar functionality to overriding AddControllerTransform,
140+
/// without the overhead of needing to check that handedness matches.
141+
/// </summary>
142+
protected virtual void OnControllerFound() { }
143+
144+
/// <summary>
145+
/// Override this method to act when the correct controller is actually lost.
146+
/// This provides similar functionality to overriding AddControllerTransform,
147+
/// without the overhead of needing to check that handedness matches.
148+
/// </summary>
149+
protected virtual void OnControllerLost() { }
150+
}
151+
}

Assets/MixedRealityToolkit-SDK/Features/Utilities/Solvers/ControllerFinder.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/MixedRealityToolkit-SDK/Features/Utilities/Solvers/SolverHandler.cs

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Microsoft.MixedReality.Toolkit.SDK.Utilities.Solvers
1111
/// <summary>
1212
/// This class handles the solver components that are attached to this <see cref="GameObject"/>
1313
/// </summary>
14-
public class SolverHandler : MonoBehaviour
14+
public class SolverHandler : ControllerFinder
1515
{
1616
[SerializeField]
1717
[Tooltip("Tracked object to calculate position and orientation from. If you want to manually override and use a scene object, use the TransformTarget field.")]
@@ -46,7 +46,7 @@ public Vector3 AdditionalOffset
4646
set
4747
{
4848
additionalOffset = value;
49-
TransformTarget = MakeOffsetTransform(TransformTarget);
49+
transformTarget = MakeOffsetTransform(transformTarget);
5050
}
5151
}
5252

@@ -63,7 +63,7 @@ public Vector3 AdditionalRotation
6363
set
6464
{
6565
additionalRotation = value;
66-
TransformTarget = MakeOffsetTransform(TransformTarget);
66+
transformTarget = MakeOffsetTransform(transformTarget);
6767
}
6868
}
6969

@@ -136,7 +136,7 @@ private void Awake()
136136
solvers.AddRange(GetComponents<Solver>());
137137

138138
// TransformTarget overrides TrackedObjectToReference
139-
if (!TransformTarget)
139+
if (!transformTarget)
140140
{
141141
AttachToNewTrackedObject();
142142
}
@@ -174,12 +174,38 @@ protected void OnDestroy()
174174

175175
#endregion MonoBehaviour Implementation
176176

177+
protected override void OnControllerFound()
178+
{
179+
if (!transformTarget)
180+
{
181+
TrackTransform(ControllerTransform);
182+
}
183+
}
184+
185+
protected override void OnControllerLost()
186+
{
187+
transformTarget = null;
188+
189+
if (transformWithOffset != null)
190+
{
191+
Destroy(transformWithOffset);
192+
transformWithOffset = null;
193+
}
194+
}
195+
177196
/// <summary>
178197
/// Clears the transform target and attaches to the current <see cref="TrackedObjectToReference"/>.
179198
/// </summary>
180199
public void RefreshTrackedObject()
181200
{
182201
transformTarget = null;
202+
203+
if (transformWithOffset != null)
204+
{
205+
Destroy(transformWithOffset);
206+
transformWithOffset = null;
207+
}
208+
183209
AttachToNewTrackedObject();
184210
}
185211

@@ -188,15 +214,22 @@ protected virtual void AttachToNewTrackedObject()
188214
switch (TrackedObjectToReference)
189215
{
190216
case TrackedObjectType.Head:
217+
// No need to search for a controller if we've already attached to the head.
218+
Handedness = Handedness.None;
191219
TrackTransform(CameraCache.Main.transform);
192220
break;
193-
// Other cases will come online as ControllerFinder is ported appropriately.
221+
case TrackedObjectType.MotionControllerLeft:
222+
Handedness = Handedness.Left;
223+
break;
224+
case TrackedObjectType.MotionControllerRight:
225+
Handedness = Handedness.Right;
226+
break;
194227
}
195228
}
196229

197230
private void TrackTransform(Transform newTrackedTransform)
198231
{
199-
TransformTarget = RequiresOffset ? MakeOffsetTransform(newTrackedTransform) : newTrackedTransform;
232+
transformTarget = RequiresOffset ? MakeOffsetTransform(newTrackedTransform) : newTrackedTransform;
200233
}
201234

202235
private Transform MakeOffsetTransform(Transform parentTransform)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using Microsoft.MixedReality.Toolkit.SDK.Utilities.Solvers;
5+
using UnityEditor;
6+
using UnityEngine;
7+
8+
namespace Microsoft.MixedReality.Toolkit.SDK.Inspectors.Utilities.Solvers
9+
{
10+
[CustomEditor(typeof(ControllerFinder))]
11+
public abstract class ControllerFinderInspector : Editor
12+
{
13+
private SerializedProperty handednessProperty;
14+
15+
protected virtual void OnEnable()
16+
{
17+
handednessProperty = serializedObject.FindProperty("handedness");
18+
}
19+
20+
public override void OnInspectorGUI()
21+
{
22+
serializedObject.Update();
23+
24+
EditorGUILayout.Space();
25+
EditorGUILayout.LabelField("Controller Options", new GUIStyle("Label") { fontStyle = FontStyle.Bold });
26+
EditorGUILayout.Space();
27+
EditorGUI.indentLevel++;
28+
29+
EditorGUILayout.PropertyField(handednessProperty);
30+
31+
EditorGUI.indentLevel--;
32+
serializedObject.ApplyModifiedProperties();
33+
}
34+
}
35+
}

Assets/MixedRealityToolkit-SDK/Inspectors/Utilities/Solvers/ControllerFinderInspector.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using Microsoft.MixedReality.Toolkit.Core.Definitions.Utilities;
5+
using Microsoft.MixedReality.Toolkit.SDK.Utilities.Solvers;
6+
using UnityEditor;
7+
using UnityEngine;
8+
9+
namespace Microsoft.MixedReality.Toolkit.SDK.Inspectors.Utilities.Solvers
10+
{
11+
[CustomEditor(typeof(SolverHandler))]
12+
[CanEditMultipleObjects]
13+
public class SolverHandlerInspector : ControllerFinderInspector
14+
{
15+
private SerializedProperty trackedObjectProperty;
16+
private SerializedProperty transformTargetProperty;
17+
private SerializedProperty additionalOffsetProperty;
18+
private SerializedProperty additionalRotationProperty;
19+
private SerializedProperty updateSolversProperty;
20+
private SolverHandler solverHandler;
21+
private readonly GUIContent trackedTransformGUIContent = new GUIContent("Tracked Transform");
22+
23+
protected override void OnEnable()
24+
{
25+
base.OnEnable();
26+
27+
trackedObjectProperty = serializedObject.FindProperty("trackedObjectToReference");
28+
transformTargetProperty = serializedObject.FindProperty("transformTarget");
29+
additionalOffsetProperty = serializedObject.FindProperty("additionalOffset");
30+
additionalRotationProperty = serializedObject.FindProperty("additionalRotation");
31+
updateSolversProperty = serializedObject.FindProperty("updateSolvers");
32+
33+
solverHandler = target as SolverHandler;
34+
}
35+
36+
public override void OnInspectorGUI()
37+
{
38+
serializedObject.Update();
39+
EditorGUILayout.Space();
40+
41+
bool trackedObjectChanged = false;
42+
43+
if (transformTargetProperty.objectReferenceValue == null || Application.isPlaying)
44+
{
45+
EditorGUI.BeginChangeCheck();
46+
EditorGUILayout.PropertyField(trackedObjectProperty);
47+
trackedObjectChanged = EditorGUI.EndChangeCheck();
48+
}
49+
50+
EditorGUILayout.PropertyField(transformTargetProperty, trackedTransformGUIContent);
51+
52+
EditorGUI.BeginChangeCheck();
53+
EditorGUILayout.PropertyField(additionalOffsetProperty);
54+
EditorGUILayout.PropertyField(additionalRotationProperty);
55+
bool additionalOffsetChanged = EditorGUI.EndChangeCheck();
56+
57+
EditorGUILayout.PropertyField(updateSolversProperty);
58+
59+
serializedObject.ApplyModifiedProperties();
60+
61+
if (Application.isPlaying && trackedObjectChanged)
62+
{
63+
solverHandler.RefreshTrackedObject();
64+
}
65+
66+
if (Application.isPlaying && additionalOffsetChanged)
67+
{
68+
solverHandler.AdditionalOffset = additionalOffsetProperty.vector3Value;
69+
solverHandler.AdditionalRotation = additionalRotationProperty.vector3Value;
70+
}
71+
}
72+
}
73+
}

Assets/MixedRealityToolkit-SDK/Inspectors/Utilities/Solvers/SolverHandlerInspector.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)