279 lines
13 KiB
C#
279 lines
13 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using Microsoft.MixedReality.Toolkit.Physics;
|
|
using Microsoft.MixedReality.Toolkit.Utilities;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Microsoft.MixedReality.Toolkit.Input
|
|
{
|
|
public static class PointerUtils
|
|
{
|
|
/// <summary>
|
|
/// Tries to get the end point of a hand ray.
|
|
/// If no hand ray of given handedness is found, returns false and sets result to zero.
|
|
/// </summary>
|
|
/// <param name="handedness">Handedness of ray</param>
|
|
/// <param name="endPoint">The output position</param>
|
|
/// <returns>True if pointer found, false otherwise. If not found, endPoint is set to zero</returns>
|
|
public static bool TryGetHandRayEndPoint(Handedness handedness, out Vector3 endPoint)
|
|
{
|
|
return TryGetPointerEndpoint<LinePointer>(handedness, InputSourceType.Hand, out endPoint);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to get the end point of a motion controller.
|
|
/// If no pointer of given handedness is found, returns false and sets result to zero.
|
|
/// </summary>
|
|
/// <param name="handedness">Handedness of ray</param>
|
|
/// <param name="endPoint">The output position</param>
|
|
/// <returns>True if pointer found, false otherwise. If not found, endPoint is set to zero</returns>
|
|
public static bool TryGetMotionControllerEndPoint(Handedness handedness, out Vector3 endPoint)
|
|
{
|
|
return TryGetPointerEndpoint<LinePointer>(handedness, InputSourceType.Controller, out endPoint);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to get the end point of a pointer by source type and handedness.
|
|
/// If no pointer of given handedness is found, returns false and sets result to zero.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of pointer to query</typeparam>
|
|
/// <param name="handedness">Handedness of pointer</param>
|
|
/// <param name="inputType">Input type of pointer</param>
|
|
/// <param name="endPoint">Output point position</param>
|
|
/// <returns>True if pointer found, false otherwise. If not found, endPoint is set to zero</returns>
|
|
public static bool TryGetPointerEndpoint<T>(Handedness handedness, InputSourceType inputType, out Vector3 endPoint) where T : IMixedRealityPointer
|
|
{
|
|
foreach (var pointer in GetPointers<IMixedRealityPointer>(handedness, inputType))
|
|
{
|
|
FocusDetails? details = pointer?.Result?.Details;
|
|
if (details.HasValue)
|
|
{
|
|
endPoint = details.Value.Point;
|
|
return true;
|
|
}
|
|
}
|
|
endPoint = Vector3.zero;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to get the end point of a pointer of a pointer type and handedness.
|
|
/// If no pointer of given handedness is found, returns false and sets result to zero.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of pointer to query</typeparam>
|
|
/// <param name="handedness">Handedness of pointer</param>
|
|
/// <param name="endPoint">The output point position</param>
|
|
/// <returns>True if pointer found, false otherwise. If not found, endPoint is set to zero</returns>
|
|
public static bool TryGetPointerEndpoint<T>(Handedness handedness, out Vector3 endPoint) where T : class, IMixedRealityPointer
|
|
{
|
|
T pointer = GetPointer<T>(handedness);
|
|
FocusDetails? details = pointer?.Result?.Details;
|
|
if (!details.HasValue)
|
|
{
|
|
endPoint = Vector3.zero;
|
|
return false;
|
|
}
|
|
endPoint = details.Value.Point;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find the first detected pointer of the given type with matching handedness.
|
|
/// </summary>
|
|
public static T GetPointer<T>(Handedness handedness) where T : class, IMixedRealityPointer
|
|
{
|
|
foreach (var pointer in CoreServices.InputSystem.FocusProvider.GetPointers<T>())
|
|
{
|
|
if (pointer.Controller?.ControllerHandedness.IsMatch(handedness) == true)
|
|
{
|
|
return pointer;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns iterator over all pointers of specific type, with specific handedness.
|
|
/// </summary>
|
|
/// <typeparam name="T">Return only pointers with this input type</typeparam>
|
|
/// <param name="handedness">Handedness of pointer</param>
|
|
/// <returns>Iterator over all pointers of specific type, with specific handedness</returns>
|
|
public static IEnumerable<T> GetPointers<T>(Handedness handedness = Handedness.Any) where T : IMixedRealityPointer
|
|
{
|
|
foreach (var pointer in GetPointers())
|
|
{
|
|
if (pointer is T pointerConcrete
|
|
&& pointer.Controller?.ControllerHandedness.IsMatch(handedness) == true)
|
|
{
|
|
yield return pointerConcrete;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns all pointers with given handedness and input type.
|
|
/// </summary>
|
|
/// <param name="handedness">Handedness of pointer</param>
|
|
/// <param name="sourceType">Only return pointers of this input source type</param>
|
|
/// <returns>Iterator over all pointers that match the source type, with specific handedness</returns>
|
|
public static IEnumerable<T> GetPointers<T>(Handedness handedness, InputSourceType sourceType) where T : IMixedRealityPointer
|
|
{
|
|
foreach (var pointer in GetPointers<T>(handedness))
|
|
{
|
|
if (pointer.Controller?.ControllerHandedness.IsMatch(handedness) == true
|
|
&& pointer.InputSourceParent.SourceType == sourceType)
|
|
{
|
|
yield return pointer;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Iterate over all pointers in the input system. May contain duplicates.
|
|
/// </summary>
|
|
public static IEnumerable<IMixedRealityPointer> GetPointers()
|
|
{
|
|
HashSet<IMixedRealityInputSource> inputSources = CoreServices.InputSystem?.DetectedInputSources;
|
|
|
|
if (inputSources == null)
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
foreach (IMixedRealityInputSource inputSource in inputSources)
|
|
{
|
|
foreach (IMixedRealityPointer pointer in inputSource.Pointers)
|
|
{
|
|
yield return pointer;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Queries input system for the behavior of a given pointer type. See <seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/>.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of pointer to query</typeparam>
|
|
/// <param name="handedness">Handedness to query</param>
|
|
/// <returns><seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/> for the given pointer type and handedness</returns>
|
|
public static PointerBehavior GetPointerBehavior<T>(Handedness handedness, InputSourceType inputSourceType) where T : class, IMixedRealityPointer
|
|
{
|
|
if (CoreServices.InputSystem?.FocusProvider is IPointerPreferences preferences)
|
|
{
|
|
if (typeof(T) == typeof(GGVPointer))
|
|
{
|
|
return preferences.GazePointerBehavior;
|
|
}
|
|
return preferences.GetPointerBehavior<T>(handedness, inputSourceType);
|
|
}
|
|
else
|
|
{
|
|
WarnAboutSettingCustomPointerBehaviors();
|
|
return PointerBehavior.Default;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the behavior for the hand ray with given handedness
|
|
/// </summary>
|
|
/// <param name="pointerBehavior">Desired <seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/>.</param>
|
|
/// <param name="handedness">Specify handedness to restrict to only right, left hands.</param>
|
|
public static void SetHandRayPointerBehavior(PointerBehavior pointerBehavior, Handedness handedness = Handedness.Any)
|
|
{
|
|
SetPointerBehavior<ShellHandRayPointer>(pointerBehavior, InputSourceType.Hand, handedness);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the behavior for the motion controller ray with given handedness
|
|
/// </summary>
|
|
/// <param name="pointerBehavior">Desired <seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/>.</param>
|
|
/// <param name="handedness">Specify handedness to restrict to only right, left.</param>
|
|
public static void SetMotionControllerRayPointerBehavior(PointerBehavior pointerBehavior, Handedness handedness = Handedness.Any)
|
|
{
|
|
SetPointerBehavior<ShellHandRayPointer>(pointerBehavior, InputSourceType.Controller, handedness);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the behavior for the grab pointer with given handedness.
|
|
/// </summary>
|
|
/// <param name="pointerBehavior">Desired <seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/>.</param>
|
|
/// <param name="handedness">Specify handedness to restrict to only right, left.</param>
|
|
public static void SetHandGrabPointerBehavior(PointerBehavior pointerBehavior, Handedness handedness = Handedness.Any)
|
|
{
|
|
SetPointerBehavior<SpherePointer>(pointerBehavior, InputSourceType.Hand, handedness);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the behavior for the poke pointer with given handedness.
|
|
/// </summary>
|
|
/// <param name="pointerBehavior">Desired <seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/>.</param>
|
|
/// <param name="handedness">Specify handedness to restrict to only right, left.</param>
|
|
public static void SetHandPokePointerBehavior(PointerBehavior pointerBehavior, Handedness handedness = Handedness.Any)
|
|
{
|
|
SetPointerBehavior<PokePointer>(pointerBehavior, InputSourceType.Hand, handedness);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the behavior for the gaze pointer.
|
|
/// </summary>
|
|
/// <param name="pointerBehavior">Desired <seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/>.</param>
|
|
public static void SetGazePointerBehavior(PointerBehavior pointerBehavior)
|
|
{
|
|
if (CoreServices.InputSystem.FocusProvider is IPointerPreferences pointerPreferences)
|
|
{
|
|
pointerPreferences.GazePointerBehavior = pointerBehavior;
|
|
foreach (InputSourceType sourceType in Enum.GetValues(typeof(InputSourceType)))
|
|
{
|
|
pointerPreferences.SetPointerBehavior<GGVPointer>(Handedness.Any, sourceType, pointerBehavior);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WarnAboutSettingCustomPointerBehaviors();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the pointer behavior for pointer of type T, for all input types.
|
|
/// </summary>
|
|
/// <typeparam name="T">All pointer types that equal or derive from this type will be set.</typeparam>
|
|
/// <param name="pointerBehavior">Desired <seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/>.</param>
|
|
/// <param name="handedness">Specify handedness to restrict to only right, left.</param>
|
|
public static void SetPointerBehavior<T>(PointerBehavior pointerBehavior, Handedness handedness = Handedness.Any) where T : class, IMixedRealityPointer
|
|
{
|
|
foreach (InputSourceType type in Enum.GetValues(typeof(InputSourceType)))
|
|
{
|
|
SetPointerBehavior<T>(pointerBehavior, type, handedness);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the behavior for the given pointer type and input type.
|
|
/// </summary>
|
|
/// <typeparam name="T">All pointer types that equal or derive from this type will be set.</typeparam>
|
|
/// <param name="pointerBehavior">Desired <seealso cref="Microsoft.MixedReality.Toolkit.Input.PointerBehavior"/>.</param>
|
|
/// <param name="sourceType">Allows setting different behaviors for different input types (hands, controllers, etc.)</param>
|
|
/// <param name="handedness">Specify handedness to restrict to only right, left.</param>
|
|
public static void SetPointerBehavior<T>(PointerBehavior pointerBehavior, InputSourceType sourceType, Handedness handedness = Handedness.Any) where T : class, IMixedRealityPointer
|
|
{
|
|
if (CoreServices.InputSystem.FocusProvider is IPointerPreferences preferences)
|
|
{
|
|
preferences.SetPointerBehavior<T>(handedness, sourceType, pointerBehavior);
|
|
}
|
|
else
|
|
{
|
|
WarnAboutSettingCustomPointerBehaviors();
|
|
}
|
|
}
|
|
|
|
private static void WarnAboutSettingCustomPointerBehaviors()
|
|
{
|
|
Debug.LogWarning("Setting custom pointer behaviors only works if the input system is using the default MRTK focus provider. " +
|
|
"Are you using a custom Focus Provider that doesn't implement IPointerPreferences?");
|
|
}
|
|
|
|
}
|
|
}
|