mixedreality/com.microsoft.mixedreality..../SDK/Features/UX/Scripts/Pointers/SpherePointerVisual.cs

124 lines
4.2 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using Unity.Profiling;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Input
{
[AddComponentMenu("Scripts/MRTK/SDK/SpherePointerVisual")]
public class SpherePointerVisual : MonoBehaviour
{
public Transform TetherEndPoint => tetherEndPoint;
public bool TetherVisualsEnabled { get; private set; }
[Tooltip("The pointer these visuals decorate")]
private SpherePointer pointer;
[SerializeField]
[Tooltip("Tether will not be shown unless it is at least this long")]
private float minTetherLength = 0.03f;
[SerializeField]
private Transform visualsRoot = null;
[SerializeField]
private Transform tetherEndPoint = null;
/// Assumption: Tether line is a child of the visuals!
[SerializeField]
private BaseMixedRealityLineDataProvider tetherLine = null;
public void OnEnable()
{
CheckInitialization();
}
public void OnDestroy()
{
if (visualsRoot != null)
{
Destroy(visualsRoot.gameObject);
}
}
public void Start()
{
// put it at root of scene
MixedRealityPlayspace.AddChild(visualsRoot.transform);
visualsRoot.gameObject.name = $"{gameObject.name}_NearTetherVisualsRoot";
}
private void CheckInitialization()
{
if (pointer == null)
{
pointer = GetComponent<SpherePointer>();
}
if (pointer == null)
{
Debug.LogError($"No SpherePointer found on {gameObject.name}.");
}
CheckAsset(visualsRoot, "Visuals Root");
CheckAsset(tetherEndPoint, "Tether End Point");
CheckAsset(tetherLine, "Tether Line");
}
private void CheckAsset(object asset, string fieldname)
{
if (asset == null)
{
Debug.LogError($"No {fieldname} specified on {gameObject.name}.SpherePointerVisual. Did you forget to set the {fieldname}?");
}
}
private static readonly ProfilerMarker UpdatePerfMarker = new ProfilerMarker("[MRTK] SpherePointerVisual.Update");
public void Update()
{
using (UpdatePerfMarker.Auto())
{
TetherVisualsEnabled = false;
if (pointer.IsFocusLocked && pointer.IsTargetPositionLockedOnFocusLock && pointer.Result != null)
{
NearInteractionGrabbable grabbedObject = GetGrabbedObject();
if (grabbedObject != null && grabbedObject.ShowTetherWhenManipulating)
{
Vector3 graspPosition;
pointer.TryGetNearGraspPoint(out graspPosition);
tetherLine.FirstPoint = graspPosition;
Vector3 endPoint = pointer.Result.Details.Object.transform.TransformPoint(pointer.Result.Details.PointLocalSpace);
tetherLine.LastPoint = endPoint;
TetherVisualsEnabled = Vector3.Distance(tetherLine.FirstPoint, tetherLine.LastPoint) > minTetherLength;
tetherLine.enabled = TetherVisualsEnabled;
tetherEndPoint.gameObject.SetActive(TetherVisualsEnabled);
tetherEndPoint.position = endPoint;
}
}
visualsRoot.gameObject.SetActive(TetherVisualsEnabled);
}
}
private static readonly ProfilerMarker GetGrabbedObjectPerfMarker = new ProfilerMarker("[MRTK] SpherePointer.GetGrabbedObject");
private NearInteractionGrabbable GetGrabbedObject()
{
using (GetGrabbedObjectPerfMarker.Auto())
{
if (pointer.Result?.Details.Object != null)
{
return pointer.Result.Details.Object.GetComponent<NearInteractionGrabbable>();
}
else
{
return null;
}
}
}
}
}