diff --git a/Definitions/Devices/ControllerMappingLibrary.cs b/Definitions/Devices/ControllerMappingLibrary.cs index 6809b77ff..89f57abd2 100644 --- a/Definitions/Devices/ControllerMappingLibrary.cs +++ b/Definitions/Devices/ControllerMappingLibrary.cs @@ -8,7 +8,6 @@ using UnityEngine; using XRTK.Definitions.Utilities; using XRTK.Providers.Controllers; -using XRTK.Services; using XRTK.Utilities.Editor; #endif @@ -21,6 +20,31 @@ public static class ControllerMappingLibrary { #region Constants + /// + /// Built in mouse x input axis + /// + public const string MouseY = "Mouse Y"; + + /// + /// Built in mouse y input axis + /// + public const string MouseX = "Mouse X"; + + /// + /// Built in mouse scroll input axis + /// + public const string MouseScroll = "Mouse ScrollWheel"; + + /// + /// Built in horizontal input axis + /// + public const string Horizontal = "Horizontal"; + + /// + /// Built in vertical input axis + /// + public const string Vertical = "Vertical"; + /// /// Mouse: Position Horizontal Movement /// HTC Vive Controller: Left Controller Trackpad (2) Horizontal Movement @@ -253,6 +277,7 @@ public static Texture2D GetControllerTexture(BaseMixedRealityControllerMappingPr /// /// Gets a scaled texture for the based on a list of the active . /// + /// /// /// /// The scaled texture for the controller type, if none found then a generic texture is returned. diff --git a/EventDatum/Input/GraphicInputEventData.cs b/EventDatum/Input/GraphicInputEventData.cs index d14ca6a6a..c83403069 100644 --- a/EventDatum/Input/GraphicInputEventData.cs +++ b/EventDatum/Input/GraphicInputEventData.cs @@ -43,7 +43,6 @@ public void Clear() pressPosition = Vector2.zero; rawPointerPress = null; scrollDelta = Vector2.zero; - selectedObject = null; useDragThreshold = false; } } diff --git a/Extensions/GameObjectExtensions.cs b/Extensions/GameObjectExtensions.cs index 713dddaf7..bb4d18183 100644 --- a/Extensions/GameObjectExtensions.cs +++ b/Extensions/GameObjectExtensions.cs @@ -206,5 +206,29 @@ public static GameObject FindCommonRoot(this GameObject g1, GameObject g2) return null; } + + /// + /// Checks if the provided GameObjects are child/parent related. + /// + /// + /// + /// True if either GameObject is the parent of the other or if they are the same + public static bool IsParentOrChildOf(this GameObject g1, GameObject g2) + { + if (g1 == null || g2 == null) + { + return false; + } + + var t1 = g1.transform; + var t2 = g2.transform; + + if (t1 == null || t2 == null) + { + return false; + } + + return t1.IsParentOrChildOf(t2); + } } } diff --git a/Extensions/TransformExtensions.cs b/Extensions/TransformExtensions.cs index 7ad7598a7..4b3f40812 100644 --- a/Extensions/TransformExtensions.cs +++ b/Extensions/TransformExtensions.cs @@ -100,11 +100,11 @@ private static IEnumerable EnumerateHierarchyCore(this Transform root /// If no colliders attached, returns a bounds of center and extents 0 public static Bounds GetColliderBounds(this Transform transform) { - Collider[] colliders = transform.GetComponentsInChildren(); + var colliders = transform.GetComponentsInChildren(); - if (colliders.Length == 0) { return new Bounds(); } + if (colliders.Length == 0) { return default; } - Bounds bounds = colliders[0].bounds; + var bounds = colliders[0].bounds; for (int i = 1; i < colliders.Length; i++) { @@ -132,7 +132,7 @@ public static bool IsParentOrChildOf(this Transform transform1, Transform transf /// The component of type . Null if it none was found. public static T FindAncestorComponent(this Transform startTransform, bool includeSelf = true) where T : Component { - foreach (Transform transform in startTransform.EnumerateAncestors(includeSelf)) + foreach (var transform in startTransform.EnumerateAncestors(includeSelf)) { T component = transform.GetComponent(); @@ -158,7 +158,7 @@ public static IEnumerable EnumerateAncestors(this Transform startTran startTransform = startTransform.parent; } - for (Transform transform = startTransform; transform != null; transform = transform.parent) + for (var transform = startTransform; transform != null; transform = transform.parent) { yield return transform; } @@ -256,6 +256,24 @@ public static bool TryGetDepth(Transform target, Transform parent, ref int depth return false; } + /// + /// Get a point on the edge in the specified direction + /// + /// + /// + /// + public static Vector3 GetPointOnBoundsEdge(this Transform transform, Vector3 direction) + { + if (direction != Vector3.zero) + { + direction /= Mathf.Max(Mathf.Max(Mathf.Abs(direction.x), Mathf.Abs(direction.y), Mathf.Abs(direction.y))); + } + + var bounds = transform.GetColliderBounds(); + direction = bounds.center + Vector3.Scale(bounds.size, direction * 0.5f); + return direction; + } + /// /// Given 2 Transforms, return a common root Transform (or null). /// @@ -268,6 +286,8 @@ public static Transform FindCommonRoot(this Transform t1, Transform t2) return null; } + var t2root = t2; + while (t1 != null) { while (t2 != null) @@ -278,9 +298,13 @@ public static Transform FindCommonRoot(this Transform t1, Transform t2) } t2 = t2.parent; - } - t1 = t1.parent; + if (t2 == null) + { + t1 = t1.parent; + t2 = t2root; + } + } } return null; diff --git a/Extensions/VectorExtensions.cs b/Extensions/VectorExtensions.cs index 80f5aa6d9..ef2e5a157 100644 --- a/Extensions/VectorExtensions.cs +++ b/Extensions/VectorExtensions.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; +using UnityEngine.EventSystems; namespace XRTK.Extensions { @@ -234,12 +235,32 @@ public static Vector3 RadialMapping(Vector3 source, float radialRange, float rad /// The source to be mapped to cylinder /// This is a for the radius of the cylinder /// - public static Vector3 ScatterMapping(Vector3 source, float radius) + public static Vector3 ScatterMapping(this Vector3 source, float radius) { source.x = UnityEngine.Random.Range(-radius, radius); source.y = UnityEngine.Random.Range(-radius, radius); return source; } + /// + /// Determine the move direction based off of the direction provided + /// + /// + /// + /// + public static MoveDirection DetermineMoveDirection(this Vector2 direction, float deadZone = 0.6f) + { + if (direction.sqrMagnitude < deadZone * deadZone) + { + return MoveDirection.None; + } + + if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y)) + { + return direction.x > 0 ? MoveDirection.Right : MoveDirection.Left; + } + + return direction.y > 0 ? MoveDirection.Up : MoveDirection.Down; + } } } diff --git a/Inspectors/ControllerPopupWindow.cs b/Inspectors/ControllerPopupWindow.cs index d90d97393..6068851d7 100644 --- a/Inspectors/ControllerPopupWindow.cs +++ b/Inspectors/ControllerPopupWindow.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -11,10 +10,8 @@ using XRTK.Definitions.InputSystem; using XRTK.Definitions.Utilities; using XRTK.Inspectors.Data; -using XRTK.Inspectors.Profiles; using XRTK.Inspectors.Utilities; using XRTK.Providers.Controllers; -using XRTK.Services; using XRTK.Utilities.Editor; namespace XRTK.Inspectors @@ -47,10 +44,10 @@ public class ControllerPopupWindow : EditorWindow private static readonly int[] InvertAxisValues = { 0, 1, 2, 3 }; + private static readonly Vector2 HorizontalSpace = new Vector2(8f, 0f); private static readonly Vector2 InputActionLabelPosition = new Vector2(256f, 0f); private static readonly Vector2 InputActionDropdownPosition = new Vector2(88f, 0f); private static readonly Vector2 InputActionFlipTogglePosition = new Vector2(-24f, 0f); - private static readonly Vector2 HorizontalSpace = new Vector2(8f, 0f); private static readonly Rect ControllerRectPosition = new Rect(new Vector2(128f, 0f), new Vector2(512f, 512f)); @@ -95,7 +92,7 @@ public class ControllerPopupWindow : EditorWindow private ControllerInputActionOption currentControllerOption; private MixedRealityInputSystemProfile inputSystemProfile; - private static BaseMixedRealityControllerMappingProfile mappingProfile; + private BaseMixedRealityControllerMappingProfile mappingProfile; private bool IsCustomController => currentControllerType == SupportedControllerType.GenericOpenVR || currentControllerType == SupportedControllerType.GenericUnity; @@ -103,11 +100,21 @@ public class ControllerPopupWindow : EditorWindow private void OnFocus() { + if (window == null) + { + Close(); + } + currentControllerTexture = ControllerMappingLibrary.GetControllerTexture(mappingProfile, currentControllerType, currentHandedness); inputSystemProfile = mappingProfile.ParentProfile.ParentProfile as MixedRealityInputSystemProfile; - #region Interaction Constraint Setup + if (inputSystemProfile == null) + { + Debug.LogWarning("No Input System Profile found. Be sure to assign this mapping profile to an input system."); + return; + } + #region Interaction Constraint Setup actionIds = inputSystemProfile.InputActionsProfile.InputActions .Select(action => (int)action.Id) @@ -115,6 +122,11 @@ private void OnFocus() axisLabels = ControllerMappingLibrary.UnityInputManagerAxes .Select(axis => new GUIContent(axis.Name)) + .Prepend(new GUIContent(ControllerMappingLibrary.MouseScroll)) + .Prepend(new GUIContent(ControllerMappingLibrary.MouseY)) + .Prepend(new GUIContent(ControllerMappingLibrary.MouseX)) + .Prepend(new GUIContent(ControllerMappingLibrary.Vertical)) + .Prepend(new GUIContent(ControllerMappingLibrary.Horizontal)) .Prepend(new GUIContent("None")).ToArray(); actionIds = inputSystemProfile.InputActionsProfile.InputActions @@ -201,15 +213,24 @@ private void OnFocus() public static void Show(BaseMixedRealityControllerMappingProfile profile, SupportedControllerType controllerType, SerializedProperty interactionsList, Handedness handedness = Handedness.None, bool isLocked = false) { - window = (ControllerPopupWindow)CreateInstance(typeof(ControllerPopupWindow)); var handednessTitleText = handedness != Handedness.None ? $"{handedness} Hand " : string.Empty; + + if (window != null) + { + window.Close(); + } + + window = (ControllerPopupWindow)CreateInstance(typeof(ControllerPopupWindow)); window.titleContent = new GUIContent($"{controllerType} {handednessTitleText}Input Action Assignment"); - window.currentControllerType = controllerType; - window.currentHandedness = handedness; window.isLocked = isLocked; + window.mappingProfile = profile; + window.currentHandedness = handedness; + window.currentControllerType = controllerType; window.currentInteractionList = interactionsList; + window.currentControllerTexture = ControllerMappingLibrary.GetControllerTexture(profile, controllerType, handedness); + isMouseInRects = new bool[interactionsList.arraySize]; - mappingProfile = profile; + var asset = AssetDatabase.LoadAssetAtPath(EditorWindowOptionsPath); if (asset == null) @@ -253,8 +274,9 @@ public static void Show(BaseMixedRealityControllerMappingProfile profile, Suppor } } + var windowSize = new Vector2(window.IsCustomController || window.currentControllerTexture == null ? 896f : 768f, 512f); + window.ShowUtility(); - var windowSize = new Vector2(controllerType == SupportedControllerType.GenericOpenVR || controllerType == SupportedControllerType.GenericUnity ? 896f : 768f, 512f); window.maxSize = windowSize; window.minSize = windowSize; window.CenterOnMainWin(); @@ -290,26 +312,30 @@ private void OnGUI() try { - RenderInteractionList(currentInteractionList, IsCustomController); + RenderInteractionList(currentInteractionList, IsCustomController || currentControllerTexture == null); } - catch (Exception e) + catch { - Debug.LogError($"{e.Message}\n{e.StackTrace}"); + Close(); } } private void RenderInteractionList(SerializedProperty interactionList, bool useCustomInteractionMapping) { GUI.enabled = !isLocked; - if (interactionList == null) { throw new Exception("No interaction list found!"); } + if (interactionList == null) + { + Debug.LogError("No interaction list found!"); + Close(); + return; + } bool noInteractions = interactionList.arraySize == 0; if (currentControllerOption != null) { - if (currentControllerOption.IsLabelFlipped == null || - currentControllerOption.IsLabelFlipped.Length != interactionList.arraySize) + if (currentControllerOption.IsLabelFlipped.Length != interactionList.arraySize) { var newArray = new bool[interactionList.arraySize]; @@ -321,8 +347,7 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC currentControllerOption.IsLabelFlipped = newArray; } - if (currentControllerOption.InputLabelPositions == null || - currentControllerOption.InputLabelPositions.Length != interactionList.arraySize) + if (currentControllerOption.InputLabelPositions.Length != interactionList.arraySize) { var newArray = new Vector2[interactionList.arraySize]; @@ -337,6 +362,11 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC GUILayout.BeginVertical(); + if (useCustomInteractionMapping) + { + useCustomInteractionMapping = !(currentControllerType == SupportedControllerType.WindowsMixedReality && currentHandedness == Handedness.None); + } + if (useCustomInteractionMapping) { horizontalScrollPosition = EditorGUILayout.BeginScrollView(horizontalScrollPosition, false, false, GUILayout.ExpandWidth(true), GUILayout.ExpandWidth(true)); @@ -434,7 +464,7 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC for (int i = 0; i < interactionList.arraySize; i++) { EditorGUILayout.BeginHorizontal(); - SerializedProperty interaction = interactionList.GetArrayElementAtIndex(i); + var interaction = interactionList.GetArrayElementAtIndex(i); if (useCustomInteractionMapping) { @@ -457,8 +487,8 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC switch ((AxisType)interactionAxisConstraint.intValue) { + // case AxisType.None: default: - case AxisType.None: labels = actionLabels; ids = actionIds; break; @@ -600,14 +630,17 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC var actionId = action.FindPropertyRelative("id"); var actionDescription = action.FindPropertyRelative("description"); var actionConstraint = action.FindPropertyRelative("axisConstraint"); + var invertXAxis = interaction.FindPropertyRelative("invertXAxis"); + var invertYAxis = interaction.FindPropertyRelative("invertYAxis"); - GUIContent[] labels; int[] ids; + GUIContent[] labels; + var axisConstraint = (AxisType)interactionAxisConstraint.intValue; - switch ((AxisType)interactionAxisConstraint.intValue) + switch (axisConstraint) { + // case AxisType.None: default: - case AxisType.None: labels = actionLabels; ids = actionIds; break; @@ -647,54 +680,120 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC { bool skip = false; var description = interactionDescription.stringValue; + if (currentControllerType == SupportedControllerType.WindowsMixedReality && currentHandedness == Handedness.None) { - if (description == "Grip Press" || - description == "Trigger Position" || - description == "Trigger Touched" || - description == "Touchpad Position" || - description == "Touchpad Touch" || - description == "Touchpad Press" || - description == "Menu Press" || - description == "Thumbstick Position" || - description == "Thumbstick Press" - ) - { - skip = true; - } - - if (description == "Trigger Press (Select)") + switch (description) { - description = "Air Tap (Select)"; + case "Grip Press": + case "Trigger Position": + case "Trigger Touched": + case "Touchpad Position": + case "Touchpad Touch": + case "Touchpad Press": + case "Menu Press": + case "Thumbstick Position": + case "Thumbstick Press": + skip = true; + break; + case "Trigger Press (Select)": + description = "Air Tap (Select)"; + break; } } if (!skip) { + var currentLabelWidth = EditorGUIUtility.labelWidth; + + if (axisConstraint == AxisType.SingleAxis || + axisConstraint == AxisType.DualAxis) + { + EditorGUIUtility.labelWidth = 12f; + EditorGUILayout.LabelField("Invert:"); + invertXAxis.boolValue = EditorGUILayout.Toggle("X", invertXAxis.boolValue); + } + + if (axisConstraint == AxisType.DualAxis) + { + invertYAxis.boolValue = EditorGUILayout.Toggle("Y", invertYAxis.boolValue); + } + + EditorGUIUtility.labelWidth = currentLabelWidth; actionId.intValue = EditorGUILayout.IntPopup(GUIContent.none, actionId.intValue, labels, ids, GUILayout.Width(80f)); EditorGUILayout.LabelField(description, GUILayout.ExpandWidth(true)); + GUILayout.FlexibleSpace(); } } else { + var flipped = currentControllerOption.IsLabelFlipped[i]; var rectPosition = currentControllerOption.InputLabelPositions[i]; - var rectSize = InputActionLabelPosition + InputActionDropdownPosition + new Vector2(currentControllerOption.IsLabelFlipped[i] ? 0f : 8f, EditorGUIUtility.singleLineHeight); + var rectSize = InputActionLabelPosition + InputActionDropdownPosition + new Vector2(flipped ? 0f : 8f, EditorGUIUtility.singleLineHeight); + GUI.Box(new Rect(rectPosition, rectSize), GUIContent.none, EditorGUIUtility.isProSkin ? "ObjectPickerBackground" : "ObjectPickerResultsEven"); - var offset = currentControllerOption.IsLabelFlipped[i] ? InputActionLabelPosition : Vector2.zero; + + var offset = flipped ? InputActionLabelPosition : Vector2.zero; var popupRect = new Rect(rectPosition + offset, new Vector2(InputActionDropdownPosition.x, EditorGUIUtility.singleLineHeight)); actionId.intValue = EditorGUI.IntPopup(popupRect, actionId.intValue, labels, ids); - offset = currentControllerOption.IsLabelFlipped[i] ? Vector2.zero : InputActionDropdownPosition; + offset = flipped ? Vector2.zero : InputActionDropdownPosition; var labelRect = new Rect(rectPosition + offset, new Vector2(InputActionLabelPosition.x, EditorGUIUtility.singleLineHeight)); - EditorGUI.LabelField(labelRect, interactionDescription.stringValue, currentControllerOption.IsLabelFlipped[i] ? flippedLabelStyle : EditorStyles.label); + EditorGUI.LabelField(labelRect, interactionDescription.stringValue, flipped ? flippedLabelStyle : EditorStyles.label); + + if (!editInputActionPositions) + { + offset = flipped + ? InputActionLabelPosition + InputActionDropdownPosition + HorizontalSpace + : Vector2.zero; + + if (axisConstraint == AxisType.SingleAxis || + axisConstraint == AxisType.DualAxis) + { + if (!flipped) + { + if (axisConstraint == AxisType.DualAxis) + { + offset += new Vector2(-112f, 0f); + } + else + { + offset += new Vector2(-76f, 0f); + } + } + + var boxSize = axisConstraint == AxisType.DualAxis ? new Vector2(112f, EditorGUIUtility.singleLineHeight) : new Vector2(76f, EditorGUIUtility.singleLineHeight); + + GUI.Box(new Rect(rectPosition + offset, boxSize), GUIContent.none, EditorGUIUtility.isProSkin ? "ObjectPickerBackground" : "ObjectPickerResultsEven"); + + labelRect = new Rect(rectPosition + offset, new Vector2(48f, EditorGUIUtility.singleLineHeight)); + EditorGUI.LabelField(labelRect, "Invert X", flipped ? flippedLabelStyle : EditorStyles.label); + offset += new Vector2(52f, 0f); + var toggleXAxisRect = new Rect(rectPosition + offset, new Vector2(12f, EditorGUIUtility.singleLineHeight)); + invertXAxis.boolValue = EditorGUI.Toggle(toggleXAxisRect, invertXAxis.boolValue); + } - if (editInputActionPositions) + if (axisConstraint == AxisType.DualAxis) + { + offset += new Vector2(24f, 0f); + labelRect = new Rect(rectPosition + offset, new Vector2(8f, EditorGUIUtility.singleLineHeight)); + EditorGUI.LabelField(labelRect, "Y", flipped ? flippedLabelStyle : EditorStyles.label); + offset += new Vector2(12f, 0f); + var toggleYAxisRect = new Rect(rectPosition + offset, new Vector2(12f, EditorGUIUtility.singleLineHeight)); + invertYAxis.boolValue = EditorGUI.Toggle(toggleYAxisRect, invertYAxis.boolValue); + } + } + else { - offset = currentControllerOption.IsLabelFlipped[i] ? InputActionLabelPosition + InputActionDropdownPosition + HorizontalSpace : InputActionFlipTogglePosition; + offset = flipped + ? InputActionLabelPosition + InputActionDropdownPosition + HorizontalSpace + : InputActionFlipTogglePosition; + var toggleRect = new Rect(rectPosition + offset, new Vector2(-InputActionFlipTogglePosition.x, EditorGUIUtility.singleLineHeight)); EditorGUI.BeginChangeCheck(); - currentControllerOption.IsLabelFlipped[i] = EditorGUI.Toggle(toggleRect, currentControllerOption.IsLabelFlipped[i]); + + currentControllerOption.IsLabelFlipped[i] = EditorGUI.Toggle(toggleRect, flipped); if (EditorGUI.EndChangeCheck()) { @@ -710,24 +809,21 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC if (!isMouseInRects.Any(value => value) || isMouseInRects[i]) { - if (Event.current.type == EventType.MouseDrag && labelRect.Contains(Event.current.mousePosition) && !isMouseInRects[i]) - { - isMouseInRects[i] = true; - mouseDragOffset = Event.current.mousePosition - currentControllerOption.InputLabelPositions[i]; - } - else if (Event.current.type == EventType.Repaint && isMouseInRects[i]) - { - currentControllerOption.InputLabelPositions[i] = Event.current.mousePosition - mouseDragOffset; - } - else if (Event.current.type == EventType.DragUpdated && isMouseInRects[i]) + switch (Event.current.type) { - currentControllerOption.InputLabelPositions[i] = Event.current.mousePosition - mouseDragOffset; - } - else if (Event.current.type == EventType.MouseUp && isMouseInRects[i]) - { - currentControllerOption.InputLabelPositions[i] = Event.current.mousePosition - mouseDragOffset; - mouseDragOffset = Vector2.zero; - isMouseInRects[i] = false; + case EventType.MouseDrag when labelRect.Contains(Event.current.mousePosition) && !isMouseInRects[i]: + isMouseInRects[i] = true; + mouseDragOffset = Event.current.mousePosition - currentControllerOption.InputLabelPositions[i]; + break; + case EventType.Repaint when isMouseInRects[i]: + case EventType.DragUpdated when isMouseInRects[i]: + currentControllerOption.InputLabelPositions[i] = Event.current.mousePosition - mouseDragOffset; + break; + case EventType.MouseUp when isMouseInRects[i]: + currentControllerOption.InputLabelPositions[i] = Event.current.mousePosition - mouseDragOffset; + mouseDragOffset = Vector2.zero; + isMouseInRects[i] = false; + break; } } } @@ -735,9 +831,9 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC if (EditorGUI.EndChangeCheck()) { - MixedRealityInputAction inputAction = actionId.intValue == 0 ? - MixedRealityInputAction.None : - inputSystemProfile.InputActionsProfile.InputActions[actionId.intValue - 1]; + var inputAction = actionId.intValue == 0 + ? MixedRealityInputAction.None + : inputSystemProfile.InputActionsProfile.InputActions[actionId.intValue - 1]; actionId.intValue = (int)inputAction.Id; actionDescription.stringValue = inputAction.Description; actionConstraint.enumValueIndex = (int)inputAction.AxisConstraint; @@ -759,13 +855,13 @@ private void RenderInteractionList(SerializedProperty interactionList, bool useC private static void RenderAxisPopup(SerializedProperty axisCode, float customLabelWidth) { - var axisId = -1; + int axisId = -1; - for (int j = 0; j < ControllerMappingLibrary.UnityInputManagerAxes.Length; j++) + for (int i = 0; i < axisLabels.Length; i++) { - if (ControllerMappingLibrary.UnityInputManagerAxes[j].Name == axisCode.stringValue) + if (axisLabels[i].text.Equals(axisCode.stringValue)) { - axisId = j + 1; + axisId = i; break; } } @@ -775,23 +871,10 @@ private static void RenderAxisPopup(SerializedProperty axisCode, float customLab if (EditorGUI.EndChangeCheck()) { - if (axisId == 0) - { - axisCode.stringValue = string.Empty; - axisCode.serializedObject.ApplyModifiedProperties(); - } - else - { - for (int j = 0; j < ControllerMappingLibrary.UnityInputManagerAxes.Length; j++) - { - if (axisId - 1 == j) - { - axisCode.stringValue = ControllerMappingLibrary.UnityInputManagerAxes[j].Name; - axisCode.serializedObject.ApplyModifiedProperties(); - break; - } - } - } + axisCode.stringValue = axisId == 0 + ? string.Empty + : axisLabels[axisId].text; + axisCode.serializedObject.ApplyModifiedProperties(); } } } diff --git a/Inspectors/Data/EditorWindowOptions.json b/Inspectors/Data/EditorWindowOptions.json index 0a86a64f5..e1fd5afe9 100644 --- a/Inspectors/Data/EditorWindowOptions.json +++ b/Inspectors/Data/EditorWindowOptions.json @@ -17,40 +17,40 @@ "y": 283.0 }, { - "x": 486.0, + "x": 502.0, "y": 144.0 }, { "x": -84.0, - "y": 158.0 + "y": 161.0 }, { "x": -82.0, "y": 136.0 }, { - "x": 484.0, - "y": 190.0 + "x": 500.0, + "y": 188.0 }, { - "x": 484.0, - "y": 231.0 + "x": 502.0, + "y": 235.0 }, { - "x": 484.0, - "y": 211.0 + "x": 501.0, + "y": 212.0 }, { - "x": -70.0, - "y": 241.0 + "x": -46.0, + "y": 248.0 }, { - "x": -77.0, - "y": 191.0 + "x": -95.0, + "y": 192.0 }, { - "x": -78.0, - "y": 211.0 + "x": -96.0, + "y": 215.0 } ], "IsLabelFlipped": [ @@ -85,8 +85,8 @@ "y": 283.0 }, { - "x": -67.0, - "y": 145.0 + "x": -81.0, + "y": 140.0 }, { "x": 500.0, @@ -97,28 +97,28 @@ "y": 137.0 }, { - "x": -68.0, - "y": 182.0 + "x": -83.0, + "y": 179.0 }, { - "x": -69.0, - "y": 205.0 + "x": -84.0, + "y": 203.0 }, { - "x": -69.0, - "y": 226.0 + "x": -83.0, + "y": 228.0 }, { - "x": 488.0, - "y": 238.0 + "x": 463.0, + "y": 243.0 }, { - "x": 499.0, - "y": 190.0 + "x": 509.0, + "y": 192.0 }, { - "x": 499.0, - "y": 211.0 + "x": 508.0, + "y": 215.0 } ], "IsLabelFlipped": [ @@ -141,32 +141,32 @@ "Handedness": 0, "InputLabelPositions": [ { - "x": 15.0, + "x": -100.0, "y": 398.0 }, { - "x": 14.0, - "y": 419.0 + "x": -101.0, + "y": 420.0 }, { - "x": 418.0, + "x": 498.0, "y": 399.0 }, { - "x": 418.0, - "y": 420.0 + "x": 498.0, + "y": 424.0 }, { - "x": -188.0, - "y": 338.0 + "x": -100.0, + "y": 444.0 }, { "x": 298.0, "y": 54.0 }, { - "x": -132.0, - "y": 134.0 + "x": -133.0, + "y": 127.0 }, { "x": 551.0, @@ -249,8 +249,8 @@ "y": 309.0 }, { - "x": 436.0, - "y": 272.0 + "x": 434.0, + "y": 268.0 }, { "x": 267.0, @@ -415,35 +415,35 @@ }, { "x": 545.0, - "y": 215.0 + "y": 211.0 }, { - "x": 543.0, + "x": 545.0, "y": 233.0 }, { - "x": 543.0, - "y": 251.0 + "x": 545.0, + "y": 254.0 }, { "x": 542.0, "y": 298.0 }, { - "x": -131.0, - "y": 216.0 + "x": -130.0, + "y": 214.0 }, { "x": -131.0, - "y": 256.0 + "y": 257.0 }, { "x": -131.0, "y": 235.0 }, { - "x": -125.0, - "y": 173.0 + "x": -131.0, + "y": 176.0 } ], "IsLabelFlipped": [ @@ -483,16 +483,16 @@ "y": 285.0 }, { - "x": 563.0, - "y": 212.0 + "x": 565.0, + "y": 210.0 }, { "x": 565.0, - "y": 252.0 + "y": 254.0 }, { - "x": 563.0, - "y": 232.0 + "x": 565.0, + "y": 231.0 }, { "x": 568.0, @@ -640,6 +640,74 @@ false ] }, + { + "Controller": 6, + "Handedness": 0, + "InputLabelPositions": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0, + "y": 0.0 + } + ], + "IsLabelFlipped": [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false + ] + }, { "Controller": 12, "Handedness": 3, diff --git a/Interfaces/InputSystem/Handlers/IMixedRealityPointerHandler.cs b/Interfaces/InputSystem/Handlers/IMixedRealityPointerHandler.cs index cc68cc9fd..a2a8d9eef 100644 --- a/Interfaces/InputSystem/Handlers/IMixedRealityPointerHandler.cs +++ b/Interfaces/InputSystem/Handlers/IMixedRealityPointerHandler.cs @@ -12,16 +12,16 @@ namespace XRTK.Interfaces.InputSystem.Handlers public interface IMixedRealityPointerHandler : IEventSystemHandler { /// - /// When a pointer up event is raised, this method is used to pass along the event data to the input handler. + /// When a pointer down event is raised, this method is used to pass along the event data to the input handler. /// /// - void OnPointerUp(MixedRealityPointerEventData eventData); + void OnPointerDown(MixedRealityPointerEventData eventData); /// - /// When a pointer down event is raised, this method is used to pass along the event data to the input handler. + /// When a pointer up event is raised, this method is used to pass along the event data to the input handler. /// /// - void OnPointerDown(MixedRealityPointerEventData eventData); + void OnPointerUp(MixedRealityPointerEventData eventData); /// /// When a pointer clicked event is raised, this method is used to pass along the event data to the input handler. diff --git a/Interfaces/InputSystem/IMixedRealityFocusProvider.cs b/Interfaces/InputSystem/IMixedRealityFocusProvider.cs index be761289b..a94ad761d 100644 --- a/Interfaces/InputSystem/IMixedRealityFocusProvider.cs +++ b/Interfaces/InputSystem/IMixedRealityFocusProvider.cs @@ -29,13 +29,6 @@ public interface IMixedRealityFocusProvider : IMixedRealitySourceStateHandler, I /// Every uGUI in your scene should use this camera as its event camera. Camera UIRaycastCamera { get; } - /// - /// To tap on a hologram even when not focused on, - /// set OverrideFocusedObject to desired game object. - /// If it's null, then focused object will be used. - /// - GameObject OverrideFocusedObject { get; set; } - /// /// Gets the currently focused object for the pointing source. /// diff --git a/Interfaces/InputSystem/IMixedRealityInputSystem.cs b/Interfaces/InputSystem/IMixedRealityInputSystem.cs index 84483b2a1..9c50494f3 100644 --- a/Interfaces/InputSystem/IMixedRealityInputSystem.cs +++ b/Interfaces/InputSystem/IMixedRealityInputSystem.cs @@ -269,6 +269,15 @@ public interface IMixedRealityInputSystem : IMixedRealityEventSystem #endregion Pointer Up + /// + /// Raise teh pointer scroll event. + /// + /// + /// + /// + /// + void RaisePointerScroll(IMixedRealityPointer pointer, MixedRealityInputAction scrollAction, Vector2 scrollDelta, IMixedRealityInputSource inputSource = null); + #endregion Pointers #region Generic Input Events diff --git a/Interfaces/InputSystem/IMixedRealityPointer.cs b/Interfaces/InputSystem/IMixedRealityPointer.cs index 7b104d7c6..5a421e960 100644 --- a/Interfaces/InputSystem/IMixedRealityPointer.cs +++ b/Interfaces/InputSystem/IMixedRealityPointer.cs @@ -4,9 +4,9 @@ using System.Collections; using UnityEngine; using XRTK.Definitions.Physics; -using XRTK.Interfaces.Providers.Controllers; using XRTK.Interfaces.InputSystem.Handlers; using XRTK.Interfaces.Physics; +using XRTK.Interfaces.Providers.Controllers; using XRTK.Interfaces.TeleportSystem; namespace XRTK.Interfaces.InputSystem @@ -16,11 +16,6 @@ namespace XRTK.Interfaces.InputSystem /// public interface IMixedRealityPointer : IEqualityComparer { - /// - /// The pointer's current controller reference. - /// - IMixedRealityController Controller { get; set; } - /// /// This pointer's id. /// @@ -31,6 +26,11 @@ public interface IMixedRealityPointer : IEqualityComparer /// string PointerName { get; set; } + /// + /// The pointer's current controller reference. + /// + IMixedRealityController Controller { get; set; } + /// /// This pointer's input source parent. /// @@ -61,6 +61,11 @@ public interface IMixedRealityPointer : IEqualityComparer /// bool IsFocusLocked { get; set; } + /// + /// Specifies whether the pointer's target position (cursor) is locked to the target object when focus is locked. + /// + bool IsTargetPositionLockedOnFocusLock { get; set; } + /// /// The pointer's maximum extent when raycasting. /// @@ -115,11 +120,6 @@ public interface IMixedRealityPointer : IEqualityComparer /// float PointerOrientation { get; } - /// - /// Specifies whether the pointer's target position (cursor) is locked to the target object when focus is locked. - /// - bool IsTargetPositionLockedOnFocusLock { get; set; } - /// /// Called before all rays have casted. /// diff --git a/Providers/Controllers/UnityInput/MouseController.cs b/Providers/Controllers/UnityInput/MouseController.cs index 04db3b28b..37d4b7376 100644 --- a/Providers/Controllers/UnityInput/MouseController.cs +++ b/Providers/Controllers/UnityInput/MouseController.cs @@ -31,8 +31,8 @@ public MouseController(TrackingState trackingState, Handedness controllerHandedn public override MixedRealityInteractionMapping[] DefaultInteractions { get; } = { new MixedRealityInteractionMapping(0, "Spatial Mouse Position", AxisType.SixDof, DeviceInputType.SpatialPointer, MixedRealityInputAction.None), - new MixedRealityInteractionMapping(1, "Mouse Delta Position", AxisType.DualAxis, DeviceInputType.PointerPosition, MixedRealityInputAction.None), - new MixedRealityInteractionMapping(2, "Mouse Scroll Position", AxisType.DualAxis, DeviceInputType.Scroll, ControllerMappingLibrary.AXIS_3), + new MixedRealityInteractionMapping(1, "Mouse Delta Position", AxisType.DualAxis, DeviceInputType.PointerPosition, ControllerMappingLibrary.MouseX, ControllerMappingLibrary.MouseY), + new MixedRealityInteractionMapping(2, "Mouse Scroll Position", AxisType.DualAxis, DeviceInputType.Scroll, ControllerMappingLibrary.MouseScroll, ControllerMappingLibrary.MouseScroll, true, true), new MixedRealityInteractionMapping(3, "Left Mouse Button", AxisType.Digital, DeviceInputType.ButtonPress, MixedRealityInputAction.None, KeyCode.Mouse0), new MixedRealityInteractionMapping(4, "Right Mouse Button", AxisType.Digital, DeviceInputType.ButtonPress, MixedRealityInputAction.None, KeyCode.Mouse1), new MixedRealityInteractionMapping(5, "Mouse Button 2", AxisType.Digital, DeviceInputType.ButtonPress, MixedRealityInputAction.None, KeyCode.Mouse2), @@ -74,11 +74,11 @@ public void Update() } // Don't ask me why it's mapped weird. Bc Unity... - mouseDelta.x = -Input.GetAxis("Mouse Y"); - mouseDelta.y = Input.GetAxis("Mouse X"); + mouseDelta.x = Input.GetAxis(Interactions[1].AxisCodeX); + mouseDelta.y = Input.GetAxis(Interactions[1].AxisCodeY); + MixedRealityToolkit.InputSystem?.RaiseSourcePositionChanged(InputSource, this, mouseDelta); MixedRealityToolkit.InputSystem?.RaiseSourcePoseChanged(InputSource, this, controllerPose); - MixedRealityToolkit.InputSystem?.RaiseSourcePositionChanged(InputSource, this, Input.mouseScrollDelta); for (int i = 0; i < Interactions?.Length; i++) { diff --git a/Providers/Controllers/UnityInput/UnityTouchController.cs b/Providers/Controllers/UnityInput/UnityTouchController.cs index 04b195035..dc5465318 100644 --- a/Providers/Controllers/UnityInput/UnityTouchController.cs +++ b/Providers/Controllers/UnityInput/UnityTouchController.cs @@ -220,8 +220,8 @@ public void EndTouch() Lifetime = 0.0f; isTouched = false; - Interactions[1].PoseData = MixedRealityPose.ZeroIdentity; Interactions[0].Vector2Data = Vector2.zero; + Interactions[1].PoseData = MixedRealityPose.ZeroIdentity; } } } \ No newline at end of file diff --git a/Providers/Controllers/UnityInput/UnityTouchDataProvider.cs b/Providers/Controllers/UnityInput/UnityTouchDataProvider.cs index 121624a94..29af3fbb3 100644 --- a/Providers/Controllers/UnityInput/UnityTouchDataProvider.cs +++ b/Providers/Controllers/UnityInput/UnityTouchDataProvider.cs @@ -88,7 +88,7 @@ public override void Disable() private void AddTouchController(Touch touch, Ray ray) { - if (!ActiveTouches.TryGetValue(touch.fingerId, out UnityTouchController controller)) + if (!ActiveTouches.TryGetValue(touch.fingerId, out var controller)) { IMixedRealityInputSource inputSource = null; @@ -127,7 +127,7 @@ private void AddTouchController(Touch touch, Ray ray) private static void UpdateTouchData(Touch touch, Ray ray) { - if (!ActiveTouches.TryGetValue(touch.fingerId, out UnityTouchController controller)) + if (!ActiveTouches.TryGetValue(touch.fingerId, out var controller)) { return; } @@ -140,7 +140,7 @@ private static void UpdateTouchData(Touch touch, Ray ray) private static void RemoveTouchController(Touch touch) { - if (!ActiveTouches.TryGetValue(touch.fingerId, out UnityTouchController controller)) + if (!ActiveTouches.TryGetValue(touch.fingerId, out var controller)) { return; } diff --git a/Services/BaseEventSystem.cs b/Services/BaseEventSystem.cs index ed80df0d7..773db87cc 100644 --- a/Services/BaseEventSystem.cs +++ b/Services/BaseEventSystem.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. +using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; @@ -52,7 +53,15 @@ public virtual async void Register(GameObject listener) if (eventExecutionDepth > 0) { - await eventExecutionDepth.WaitUntil(depth => depth == 0); + try + { + await eventExecutionDepth.WaitUntil(depth => eventExecutionDepth == 0); + } + catch (Exception e) + { + Debug.LogError($"{e.Message}\n{e.StackTrace}"); + return; + } } EventListeners.Add(listener); @@ -65,7 +74,15 @@ public virtual async void Unregister(GameObject listener) if (eventExecutionDepth > 0) { - await eventExecutionDepth.WaitUntil(depth => depth == 0); + try + { + await eventExecutionDepth.WaitUntil(depth => eventExecutionDepth == 0); + } + catch (Exception e) + { + Debug.LogError($"{e.Message}\n{e.StackTrace}"); + return; + } } EventListeners.Remove(listener); diff --git a/Services/InputSystem/FocusProvider.cs b/Services/InputSystem/FocusProvider.cs index 525a60b45..5d725e181 100644 --- a/Services/InputSystem/FocusProvider.cs +++ b/Services/InputSystem/FocusProvider.cs @@ -90,9 +90,6 @@ public Camera UIRaycastCamera } } - /// - public GameObject OverrideFocusedObject { get; set; } - #endregion IFocusProvider Properties /// @@ -451,21 +448,19 @@ public override void Destroy() /// public GameObject GetFocusedObject(IMixedRealityPointer pointingSource) { - if (OverrideFocusedObject != null) { return OverrideFocusedObject; } - if (pointingSource == null) { Debug.LogError("No Pointer passed to get focused object"); return null; } - return !TryGetFocusDetails(pointingSource, out FocusDetails focusDetails) ? null : focusDetails.Object; + return !TryGetFocusDetails(pointingSource, out var focusDetails) ? null : focusDetails.Object; } /// public bool TryGetFocusDetails(IMixedRealityPointer pointer, out FocusDetails focusDetails) { - if (TryGetPointerData(pointer, out PointerData pointerData)) + if (TryGetPointerData(pointer, out var pointerData)) { focusDetails = pointerData.Details; return true; @@ -478,7 +473,7 @@ public bool TryGetFocusDetails(IMixedRealityPointer pointer, out FocusDetails fo /// public bool TryGetSpecificPointerGraphicEventData(IMixedRealityPointer pointer, out GraphicInputEventData graphicInputEventData) { - if (TryGetPointerData(pointer, out PointerData pointerData)) + if (TryGetPointerData(pointer, out var pointerData)) { Debug.Assert(pointerData.GraphicEventData != null); graphicInputEventData = pointerData.GraphicEventData; @@ -489,7 +484,6 @@ public bool TryGetSpecificPointerGraphicEventData(IMixedRealityPointer pointer, graphicInputEventData = null; return false; } - #endregion Focus Details by IMixedRealityPointer #region Utilities @@ -559,7 +553,7 @@ public void UpdateCanvasEventSystems() { if (sceneCanvases[i].isRootCanvas && sceneCanvases[i].renderMode == RenderMode.WorldSpace) { - sceneCanvases[i].worldCamera = UIRaycastCamera; + sceneCanvases[i].worldCamera = uiRaycastCamera; } } } @@ -614,7 +608,8 @@ public bool UnregisterPointer(IMixedRealityPointer pointer) foreach (var otherPointer in pointers) { - if (otherPointer.Pointer.PointerId != pointer.PointerId && otherPointer.CurrentPointerTarget == unfocusedObject) + if (otherPointer.Pointer.PointerId != pointer.PointerId && + otherPointer.CurrentPointerTarget == unfocusedObject) { objectIsStillFocusedByOtherPointer = true; break; @@ -663,25 +658,27 @@ private void UpdatePointers() { UpdatePointer(pointer); + // TODO remove profile call here and use a value set on the pointer itself. var pointerProfile = MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.PointerProfile; - if (pointerProfile != null && pointerProfile.DebugDrawPointingRays) - { - MixedRealityRaycaster.DebugEnabled = MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.PointerProfile.DebugDrawPointingRays; + if (pointerProfile == null || !pointerProfile.DebugDrawPointingRays) { continue; } - Color rayColor; + // TODO Let's only set this once on start.This will overwrite the property each update. + MixedRealityRaycaster.DebugEnabled = MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.PointerProfile.DebugDrawPointingRays; - if ((pointerProfile.DebugDrawPointingRayColors != null) && (pointerProfile.DebugDrawPointingRayColors.Length > 0)) - { - rayColor = pointerProfile.DebugDrawPointingRayColors[pointerCount++ % pointerProfile.DebugDrawPointingRayColors.Length]; - } - else - { - rayColor = Color.green; - } + Color rayColor; - Debug.DrawRay(pointer.StartPoint, (pointer.Details.Point - pointer.StartPoint), rayColor); + if (pointerProfile.DebugDrawPointingRayColors != null && + pointerProfile.DebugDrawPointingRayColors.Length > 0) + { + rayColor = pointerProfile.DebugDrawPointingRayColors[pointerCount++ % pointerProfile.DebugDrawPointingRayColors.Length]; } + else + { + rayColor = Color.green; + } + + Debug.DrawRay(pointer.StartPoint, (pointer.Details.Point - pointer.StartPoint), rayColor); } } @@ -852,11 +849,15 @@ private static void UpdatePointerRayOnHit(RayStep[] raySteps, RaycastHit physics /// private void RaycastGraphics(IMixedRealityPointer pointer, PointerEventData graphicEventData, LayerMask[] prioritizedLayerMasks, PointerHitResult hitResult) { - Debug.Assert(UIRaycastCamera != null, "Missing UIRaycastCamera!"); + if (UIRaycastCamera == null) + { + Debug.LogError("Missing UIRaycastCamera!"); + return; + } - if (!UIRaycastCamera.nearClipPlane.Equals(0.01f)) + if (!uiRaycastCamera.nearClipPlane.Equals(0.01f)) { - UIRaycastCamera.nearClipPlane = 0.01f; + uiRaycastCamera.nearClipPlane = 0.01f; } if (pointer.Rays == null) @@ -876,53 +877,65 @@ private void RaycastGraphics(IMixedRealityPointer pointer, PointerEventData grap for (int i = 0; i < pointer.Rays.Length; i++) { - if (RaycastGraphicsStep(graphicEventData, pointer.Rays[i], prioritizedLayerMasks, out var raycastResult)) + if (RaycastGraphicsStep(graphicEventData, pointer.Rays[i], prioritizedLayerMasks, out var raycastResult) && + raycastResult.isValid && + raycastResult.distance < pointer.Rays[i].Length && + raycastResult.module != null && + raycastResult.module.eventCamera == UIRaycastCamera) { - if (raycastResult.isValid && - raycastResult.distance < pointer.Rays[i].Length && - raycastResult.module != null && - raycastResult.module.eventCamera == UIRaycastCamera) - { - totalDistance += raycastResult.distance; + totalDistance += raycastResult.distance; - newUiRaycastPosition.x = raycastResult.screenPosition.x; - newUiRaycastPosition.y = raycastResult.screenPosition.y; - newUiRaycastPosition.z = raycastResult.distance; + newUiRaycastPosition.x = raycastResult.screenPosition.x; + newUiRaycastPosition.y = raycastResult.screenPosition.y; + newUiRaycastPosition.z = raycastResult.distance; - var worldPos = UIRaycastCamera.ScreenToWorldPoint(newUiRaycastPosition); - var normal = -raycastResult.gameObject.transform.forward; + var worldPos = uiRaycastCamera.ScreenToWorldPoint(newUiRaycastPosition); + var normal = -raycastResult.gameObject.transform.forward; - hitResult.Set(raycastResult, worldPos, normal, pointer.Rays[i], i, totalDistance); - return; - } + hitResult.Set(raycastResult, worldPos, normal, pointer.Rays[i], i, totalDistance); + return; } totalDistance += pointer.Rays[i].Length; } } + /// /// Raycasts each graphic + /// /// /// /// /// - /// private bool RaycastGraphicsStep(PointerEventData graphicEventData, RayStep step, LayerMask[] prioritizedLayerMasks, out RaycastResult uiRaycastResult) { - Debug.Assert(step.Direction != Vector3.zero, "RayStep Direction is Invalid."); + uiRaycastResult = default; + var currentEventSystem = EventSystem.current; + + if (currentEventSystem == null) + { + Debug.LogError("Current Event System is Invalid!"); + return false; + } + + if (step.Direction == Vector3.zero) + { + Debug.LogError("RayStep Direction is Invalid!"); + return false; + } // Move the uiRaycast camera to the current pointer's position. - UIRaycastCamera.transform.position = step.Origin; - UIRaycastCamera.transform.rotation = Quaternion.LookRotation(step.Direction, Vector3.up); + uiRaycastCamera.transform.position = step.Origin; + uiRaycastCamera.transform.rotation = Quaternion.LookRotation(step.Direction, Vector3.up); // We always raycast from the center of the camera. var newPosition = graphicRaycastMultiplier; - newPosition.x *= UIRaycastCamera.pixelWidth; - newPosition.y *= UIRaycastCamera.pixelHeight; + newPosition.x *= uiRaycastCamera.pixelWidth; + newPosition.y *= uiRaycastCamera.pixelHeight; graphicEventData.position = newPosition; // Graphics raycast - uiRaycastResult = EventSystem.current.Raycast(graphicEventData, prioritizedLayerMasks); + uiRaycastResult = currentEventSystem.Raycast(graphicEventData, prioritizedLayerMasks); graphicEventData.pointerCurrentRaycast = uiRaycastResult; return uiRaycastCamera.gameObject != null; @@ -947,22 +960,21 @@ private void UpdateFocusedObjects() foreach (var pointer in pointers) { - if (pointer.PreviousPointerTarget != pointer.CurrentPointerTarget) - { - pendingPointerSpecificFocusChange.Add(pointer); + if (pointer.PreviousPointerTarget == pointer.CurrentPointerTarget) { continue; } - // Initially, we assume all pointer-specific focus changes will - // also result in an overall focus change... + pendingPointerSpecificFocusChange.Add(pointer); - if (pointer.PreviousPointerTarget != null) - { - pendingOverallFocusExitSet.Add(pointer.PreviousPointerTarget); - } + // Initially, we assume all pointer-specific focus changes will + // also result in an overall focus change... - if (pointer.CurrentPointerTarget != null) - { - pendingOverallFocusEnterSet.Add(pointer.CurrentPointerTarget); - } + if (pointer.PreviousPointerTarget != null) + { + pendingOverallFocusExitSet.Add(pointer.PreviousPointerTarget); + } + + if (pointer.CurrentPointerTarget != null) + { + pendingOverallFocusEnterSet.Add(pointer.CurrentPointerTarget); } } diff --git a/Services/InputSystem/MixedRealityInputSystem.cs b/Services/InputSystem/MixedRealityInputSystem.cs index 401c3d35c..c8b51425c 100644 --- a/Services/InputSystem/MixedRealityInputSystem.cs +++ b/Services/InputSystem/MixedRealityInputSystem.cs @@ -255,12 +255,12 @@ public override void HandleEvent(BaseEventData eventData, ExecuteEvents.Event // Get the focused object for each pointer of the event source for (int i = 0; i < baseInputEventData.InputSource.Pointers.Length; i++) { - GameObject focusedObject = FocusProvider?.GetFocusedObject(baseInputEventData.InputSource.Pointers[i]); + var focusedObject = FocusProvider?.GetFocusedObject(baseInputEventData.InputSource.Pointers[i]); // Handle modal input if one exists if (modalInputStack.Count > 0 && !modalEventHandled) { - GameObject modalInput = modalInputStack.Peek(); + var modalInput = modalInputStack.Peek(); if (modalInput != null) { @@ -269,7 +269,9 @@ public override void HandleEvent(BaseEventData eventData, ExecuteEvents.Event // If there is a focused object in the hierarchy of the modal handler, start the event bubble there if (focusedObject != null && focusedObject.transform.IsChildOf(modalInput.transform)) { - if (ExecuteEvents.ExecuteHierarchy(focusedObject, baseInputEventData, eventHandler) && baseInputEventData.used) + ExecuteEvents.ExecuteHierarchy(focusedObject, baseInputEventData, eventHandler); + + if (baseInputEventData.used) { return; } @@ -277,7 +279,9 @@ public override void HandleEvent(BaseEventData eventData, ExecuteEvents.Event // Otherwise, just invoke the event on the modal handler itself else { - if (ExecuteEvents.ExecuteHierarchy(modalInput, baseInputEventData, eventHandler) && baseInputEventData.used) + ExecuteEvents.ExecuteHierarchy(modalInput, baseInputEventData, eventHandler); + + if (baseInputEventData.used) { return; } @@ -292,7 +296,9 @@ public override void HandleEvent(BaseEventData eventData, ExecuteEvents.Event // If event was not handled by modal, pass it on to the current focused object if (focusedObject != null) { - if (ExecuteEvents.ExecuteHierarchy(focusedObject, baseInputEventData, eventHandler) && baseInputEventData.used) + ExecuteEvents.ExecuteHierarchy(focusedObject, baseInputEventData, eventHandler); + + if (baseInputEventData.used) { return; } @@ -302,10 +308,16 @@ public override void HandleEvent(BaseEventData eventData, ExecuteEvents.Event // If event was not handled by the focused object, pass it on to any fallback handlers if (fallbackInputStack.Count > 0) { - GameObject fallbackInput = fallbackInputStack.Peek(); - if (ExecuteEvents.ExecuteHierarchy(fallbackInput, baseInputEventData, eventHandler) && baseInputEventData.used) + var fallbackInput = fallbackInputStack.Peek(); + + if (fallbackInput != null) { - // return; + ExecuteEvents.ExecuteHierarchy(fallbackInput, baseInputEventData, eventHandler); + + if (baseInputEventData.used) + { + // return; + } } } } @@ -688,11 +700,11 @@ public void RaisePreFocusChanged(IMixedRealityPointer pointer, GameObject oldFoc } private static readonly ExecuteEvents.EventFunction OnPreFocusChangedHandler = - delegate (IMixedRealityFocusChangedHandler handler, BaseEventData eventData) - { - var casted = ExecuteEvents.ValidateEventData(eventData); - handler.OnBeforeFocusChange(casted); - }; + delegate (IMixedRealityFocusChangedHandler handler, BaseEventData eventData) + { + var casted = ExecuteEvents.ValidateEventData(eventData); + handler.OnBeforeFocusChange(casted); + }; /// public void RaiseFocusChanged(IMixedRealityPointer pointer, GameObject oldFocusedObject, GameObject newFocusedObject) @@ -739,19 +751,20 @@ public void RaiseFocusEnter(IMixedRealityPointer pointer, GameObject focusedObje focusEventData.Initialize(pointer); ExecuteEvents.ExecuteHierarchy(focusedObject, focusEventData, OnFocusEnterEventHandler); + ExecuteEvents.ExecuteHierarchy(focusedObject, focusEventData, ExecuteEvents.selectHandler); - if (FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out GraphicInputEventData graphicEventData)) + if (FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out var graphicEventData)) { ExecuteEvents.ExecuteHierarchy(focusedObject, graphicEventData, ExecuteEvents.pointerEnterHandler); } } private static readonly ExecuteEvents.EventFunction OnFocusEnterEventHandler = - delegate (IMixedRealityFocusHandler handler, BaseEventData eventData) - { - var casted = ExecuteEvents.ValidateEventData(eventData); - handler.OnFocusEnter(casted); - }; + delegate (IMixedRealityFocusHandler handler, BaseEventData eventData) + { + var casted = ExecuteEvents.ValidateEventData(eventData); + handler.OnFocusEnter(casted); + }; /// public void RaiseFocusExit(IMixedRealityPointer pointer, GameObject unfocusedObject) @@ -759,19 +772,20 @@ public void RaiseFocusExit(IMixedRealityPointer pointer, GameObject unfocusedObj focusEventData.Initialize(pointer); ExecuteEvents.ExecuteHierarchy(unfocusedObject, focusEventData, OnFocusExitEventHandler); + ExecuteEvents.ExecuteHierarchy(unfocusedObject, focusEventData, ExecuteEvents.deselectHandler); - if (FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out GraphicInputEventData graphicEventData)) + if (FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out var graphicEventData)) { ExecuteEvents.ExecuteHierarchy(unfocusedObject, graphicEventData, ExecuteEvents.pointerExitHandler); } } private static readonly ExecuteEvents.EventFunction OnFocusExitEventHandler = - delegate (IMixedRealityFocusHandler handler, BaseEventData eventData) - { - var casted = ExecuteEvents.ValidateEventData(eventData); - handler.OnFocusExit(casted); - }; + delegate (IMixedRealityFocusHandler handler, BaseEventData eventData) + { + var casted = ExecuteEvents.ValidateEventData(eventData); + handler.OnFocusExit(casted); + }; #endregion Focus Events @@ -794,11 +808,13 @@ public void RaisePointerDown(IMixedRealityPointer pointer, MixedRealityInputActi // Pass handler through HandleEvent to perform modal/fallback logic HandleEvent(pointerEventData, OnPointerDownEventHandler); - FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out GraphicInputEventData graphicInputEventData); - if (graphicInputEventData != null && graphicInputEventData.selectedObject != null) + var focusedObject = pointer.Result?.CurrentPointerTarget; + + if (focusedObject != null && + FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out var graphicInputEventData)) { - ExecuteEvents.ExecuteHierarchy(graphicInputEventData.selectedObject, graphicInputEventData, ExecuteEvents.pointerDownHandler); + ExecuteEvents.ExecuteHierarchy(focusedObject, graphicInputEventData, ExecuteEvents.pointerDownHandler); } } @@ -845,15 +861,13 @@ public void RaisePointerUp(IMixedRealityPointer pointer, MixedRealityInputAction // Pass handler through HandleEvent to perform modal/fallback logic HandleEvent(pointerEventData, OnPointerUpEventHandler); - FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out GraphicInputEventData graphicInputEventData); + var focusedObject = pointer.Result?.CurrentPointerTarget; - if (graphicInputEventData != null) + if (focusedObject != null && + FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out var graphicInputEventData)) { - if (graphicInputEventData.selectedObject != null) - { - ExecuteEvents.ExecuteHierarchy(graphicInputEventData.selectedObject, graphicInputEventData, ExecuteEvents.pointerUpHandler); - ExecuteEvents.ExecuteHierarchy(graphicInputEventData.selectedObject, graphicInputEventData, ExecuteEvents.pointerClickHandler); - } + ExecuteEvents.ExecuteHierarchy(focusedObject, graphicInputEventData, ExecuteEvents.pointerUpHandler); + ExecuteEvents.ExecuteHierarchy(focusedObject, graphicInputEventData, ExecuteEvents.pointerClickHandler); graphicInputEventData.Clear(); } @@ -861,6 +875,23 @@ public void RaisePointerUp(IMixedRealityPointer pointer, MixedRealityInputAction #endregion Pointer Up + /// + public void RaisePointerScroll(IMixedRealityPointer pointer, MixedRealityInputAction scrollAction, Vector2 scrollDelta, IMixedRealityInputSource inputSource = null) + { + vector2InputEventData.Initialize(inputSource ?? pointer.InputSourceParent, Handedness.None, scrollAction, scrollDelta); + + HandleEvent(vector2InputEventData, OnTwoDoFInputChanged); + + var focusedObject = pointer.Result?.CurrentPointerTarget; + + if (focusedObject != null && + FocusProvider.TryGetSpecificPointerGraphicEventData(pointer, out var graphicInputEventData)) + { + graphicInputEventData.scrollDelta = scrollDelta; + ExecuteEvents.ExecuteHierarchy(focusedObject, graphicInputEventData, ExecuteEvents.scrollHandler); + } + } + #endregion Pointers #region Generic Input Events diff --git a/Utilities/Async/Awaiters.cs b/Utilities/Async/Awaiters.cs index bb252e1a1..77118872c 100644 --- a/Utilities/Async/Awaiters.cs +++ b/Utilities/Async/Awaiters.cs @@ -81,14 +81,12 @@ void Exception() while (!cancellationTokenSource.IsCancellationRequested) { - #if UNITY_EDITOR if (editorCancelled) { tcs.TrySetCanceled(CancellationToken.None); } #endif - try { if (!predicate(element)) @@ -119,7 +117,6 @@ private static async Task WaitUntil_Indefinite(T element, Func predi var editorCancelled = false; UnityEditor.EditorApplication.playModeStateChanged += playModeStateChanged => editorCancelled = true; #endif - while (true) { #if UNITY_EDITOR @@ -128,7 +125,6 @@ private static async Task WaitUntil_Indefinite(T element, Func predi tcs.TrySetCanceled(CancellationToken.None); } #endif - try { if (!predicate(element)) diff --git a/Utilities/Physics/MixedRealityRaycaster.cs b/Utilities/Physics/MixedRealityRaycaster.cs index dbeeeacbd..be6c13a49 100644 --- a/Utilities/Physics/MixedRealityRaycaster.cs +++ b/Utilities/Physics/MixedRealityRaycaster.cs @@ -70,7 +70,6 @@ public static bool RaycastBoxPhysicsStep(RayStep step, Vector3 extents, Vector3 for (int y = -halfRaysPerEdge; y <= halfRaysPerEdge; y += 1) { Vector3 offset = matrix.MultiplyVector(new Vector3(x * extents.x, y * extents.y, 0)); - Vector3 origin = step.Origin; Vector3 direction = (targetPosition + offset) - step.Origin; @@ -80,7 +79,7 @@ public static bool RaycastBoxPhysicsStep(RayStep step, Vector3 extents, Vector3 direction = step.Direction; } - hits[index] = RaycastSimplePhysicsStep(new RayStep(origin, direction.normalized * maxDistance), prioritizedLayerMasks, out RaycastHit rayHit); + hits[index] = RaycastSimplePhysicsStep(new RayStep(origin, direction.normalized * maxDistance), prioritizedLayerMasks, out var rayHit); if (hits[index]) { @@ -163,7 +162,8 @@ public static bool TryGetPrioritizedPhysicsHit(RaycastHit[] hits, LayerMask[] pr for (int hitIdx = 0; hitIdx < hits.Length; hitIdx++) { - RaycastHit hit = hits[hitIdx]; + var hit = hits[hitIdx]; + if (hit.transform.gameObject.layer.IsInLayerMask(priorityLayers[layerMaskIdx]) && (minHit == null || hit.distance < minHit.Value.distance)) {