mixedreality/com.microsoft.mixedreality..../SDK/Features/UX/Scripts/Cursors/InteractiveMeshCursor.cs

182 lines
5.6 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Input
{
/// <summary>
/// A cursor that looks and acts more like the shell cursor.
/// A two part cursor with visual feedback for all cursor states
/// </summary>
[AddComponentMenu("Scripts/MRTK/SDK/InteractiveMeshCursor")]
public class InteractiveMeshCursor : BaseCursor
{
[SerializeField]
[Tooltip("The ring or outer element")]
private GameObject ring = null;
[SerializeField]
[Tooltip("Inner cursor element")]
private GameObject dot = null;
[SerializeField]
[Tooltip("The scale factor to soften the distance scaling, we want the cursor to scale in the distance, but not disappear.")]
private float distanceScaleFactor = 0.3f;
[SerializeField]
[Tooltip("The scale both elements will be at their default state")]
private float defaultScale = 0.75f;
[SerializeField]
[Tooltip("The scale both elements will when pressed")]
private float downScale = 0.5f;
[SerializeField]
[Tooltip("The scale both elements will a hand is visible")]
private float upScale = 1;
[SerializeField]
[Tooltip("Time to scale between states")]
private float scaleTime = 0.5f;
/// <summary>
/// internal state and element management
/// </summary>
private float timer = 0;
private bool isVisible = true;
private bool hasHover = false;
private bool hasHand = false;
private bool isDown = false;
private float ringDotTargetScale;
private Vector3 initialScale;
private void Awake()
{
initialScale = transform.localScale;
}
/// <summary>
/// Decide which element (ring or dot) should be visible and at what scale
/// </summary>
public override void OnCursorStateChange(CursorStateEnum state)
{
base.OnCursorStateChange(state);
// the cursor state has changed, reset the animation timer
if (hasHand != IsSourceDetected || isDown != IsPointerDown || hasHover != (TargetedObject != null))
{
timer = 0;
}
hasHand = IsSourceDetected;
isDown = IsPointerDown;
hasHover = TargetedObject != null;
ringDotTargetScale = defaultScale;
bool showRing = false;
switch (state)
{
case CursorStateEnum.None:
break;
case CursorStateEnum.Observe:
break;
case CursorStateEnum.ObserveHover:
showRing = true;
break;
case CursorStateEnum.Interact:
showRing = true;
ringDotTargetScale = downScale;
break;
case CursorStateEnum.InteractHover:
showRing = true;
ringDotTargetScale = upScale;
break;
case CursorStateEnum.Select:
ringDotTargetScale = upScale;
break;
case CursorStateEnum.Release:
break;
case CursorStateEnum.Contextual:
break;
}
if (!isVisible)
{
return;
}
ring.SetActive(showRing);
dot.SetActive(!showRing);
// added observation of CursorModifier
if (Pointer.CursorModifier != null && hasHover)
{
ElementVisibility(!Pointer.CursorModifier.GetCursorVisibility());
}
}
/// <summary>
/// scale the cursor elements
/// </summary>
protected override void UpdateCursorTransform()
{
base.UpdateCursorTransform();
// animate scale of ring and dot
if (timer < scaleTime)
{
timer += Time.deltaTime;
if (timer > scaleTime)
{
timer = scaleTime;
}
Vector3 useScale = Vector3.one * Mathf.Lerp(defaultScale, ringDotTargetScale, timer / scaleTime);
ring.transform.localScale = useScale;
dot.transform.localScale = useScale;
}
// handle scale of main cursor go
float distance = Vector3.Distance(CoreServices.InputSystem.GazeProvider.GazeOrigin, transform.position);
float smoothScaling = 1 - DefaultCursorDistance * distanceScaleFactor;
transform.localScale = initialScale * (distance * distanceScaleFactor + smoothScaling);
}
/// <summary>
/// override the base class for custom visibility
/// </summary>
public override void SetVisibility(bool visible)
{
base.SetVisibility(visible);
isVisible = visible;
ElementVisibility(visible);
if (visible)
{
OnCursorStateChange(CursorState);
}
}
/// <summary>
/// controls the visibility of cursor elements in one place
/// </summary>
private void ElementVisibility(bool visible)
{
if (ring != null)
{
ring.SetActive(visible);
}
if (dot != null)
{
dot.SetActive(visible);
}
}
}
}