mixedreality/com.microsoft.mixedreality..../SDK/Features/UX/Scripts/Tooltips/ToolTipConnector.cs

323 lines
12 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.UI
{
/// <summary>
/// Connects a ToolTip to a target
/// Maintains that connection even if the target moves
/// </summary>
[ExecuteAlways]
[AddComponentMenu("Scripts/MRTK/SDK/ToolTipConnector")]
public class ToolTipConnector : MonoBehaviour
{
[SerializeField]
[Tooltip("The GameObject to which the tooltip is connected")]
private GameObject target;
/// <summary>
/// The GameObject to which the tooltip is connected
/// </summary>
public GameObject Target
{
get { return target; }
set { target = value; }
}
[SerializeField]
private ToolTip toolTip;
[SerializeField]
[Tooltip("The follow style of the tooltip connector")]
private ConnectorFollowType connectorFollowType = ConnectorFollowType.AnchorOnly;
/// <summary>
/// The follow style of the tooltip connector
/// </summary>
public ConnectorFollowType ConnectorFollowingType
{
get { return connectorFollowType; }
set { connectorFollowType = value; }
}
[SerializeField]
[Tooltip("Is the connector pivot set manually or automatically?")]
private ConnectorPivotMode pivotMode = ConnectorPivotMode.Manual;
/// <summary>
/// Is the connector pivot set manually or automatically?
/// </summary>
public ConnectorPivotMode PivotMode
{
get { return pivotMode; }
set { pivotMode = value; }
}
[SerializeField]
[Tooltip("The direction of the connector")]
private ConnectorPivotDirection pivotDirection = ConnectorPivotDirection.North;
/// <summary>
/// The direction of the connector
/// </summary>
public ConnectorPivotDirection PivotDirection
{
get { return pivotDirection; }
set { pivotDirection = value; }
}
[SerializeField]
[Tooltip("orientation style for connector")]
private ConnectorOrientType pivotDirectionOrient = ConnectorOrientType.OrientToObject;
/// <summary>
/// Orientation style for connector
/// </summary>
public ConnectorOrientType PivotDirectionOrient
{
get { return pivotDirectionOrient; }
set { pivotDirectionOrient = value; }
}
[SerializeField]
[Tooltip("The direction of the manual pivot.")]
private Vector3 manualPivotDirection = Vector3.up;
/// <summary>
/// The direction of the manual pivot.
/// </summary>
public Vector3 ManualPivotDirection
{
get { return manualPivotDirection; }
set { manualPivotDirection = value; }
}
[SerializeField]
private Vector3 manualPivotLocalPosition = Vector3.up;
/// <summary>
/// getter/setter for local pivot position
/// </summary>
public Vector3 ManualPivotLocalPosition
{
get { return manualPivotLocalPosition; }
set { manualPivotLocalPosition = value; }
}
[SerializeField]
[Range(0f, 2f)]
[Tooltip("Set Distance from object that Tooltip pivots around.")]
private float pivotDistance = 0.25f;
/// <summary>
/// Set Distance from object that Tooltip pivots around.
/// </summary>
public float PivotDistance
{
get { return pivotDistance; }
set { pivotDistance = Mathf.Min(2.0f, Mathf.Max(0, value)); }
}
private void OnEnable()
{
toolTip = gameObject.GetComponent<ToolTip>();
if (toolTip == null)
{
Debug.LogWarning("This component only works with a ToolTip.");
enabled = false;
return;
}
UpdatePosition();
}
private void UpdatePosition()
{
if (target == null)
{
return;
}
switch (connectorFollowType)
{
case ConnectorFollowType.AnchorOnly:
default:
// Set the position of the anchor to the target's position
// And do nothing else
toolTip.Anchor.transform.position = target.transform.position;
break;
case ConnectorFollowType.Position:
// Move the entire tooltip transform while maintaining the anchor position offset
toolTip.transform.position = target.transform.position;
switch (PivotMode)
{
case ConnectorPivotMode.Automatic:
Transform relativeTo = null;
switch (PivotDirectionOrient)
{
case ConnectorOrientType.OrientToCamera:
relativeTo = CameraCache.Main.transform;
break;
case ConnectorOrientType.OrientToObject:
relativeTo = target.transform;
break;
}
toolTip.PivotPosition = target.transform.position + GetDirectionFromPivotDirection(
PivotDirection,
ManualPivotDirection,
relativeTo) * PivotDistance;
break;
case ConnectorPivotMode.LocalPosition:
toolTip.PivotPosition = target.transform.position + target.transform.TransformPoint(manualPivotLocalPosition);
break;
case ConnectorPivotMode.Manual:
// Do nothing
break;
}
break;
case ConnectorFollowType.PositionAndYRotation:
// Set the transform of the entire tool tip
// Set the pivot relative to target/camera
toolTip.transform.position = target.transform.position;
Vector3 eulerAngles = target.transform.eulerAngles;
eulerAngles.x = 0f;
eulerAngles.z = 0f;
toolTip.transform.eulerAngles = eulerAngles;
switch (PivotMode)
{
case ConnectorPivotMode.Automatic:
Transform relativeTo = null;
switch (PivotDirectionOrient)
{
case ConnectorOrientType.OrientToCamera:
relativeTo = CameraCache.Main.transform;
break;
case ConnectorOrientType.OrientToObject:
relativeTo = target.transform;
break;
}
Vector3 localPosition = GetDirectionFromPivotDirection(PivotDirection, ManualPivotDirection, relativeTo) * PivotDistance;
toolTip.PivotPosition = target.transform.position + localPosition;
break;
case ConnectorPivotMode.LocalPosition:
toolTip.PivotPosition = target.transform.position + target.transform.TransformPoint(manualPivotLocalPosition);
break;
case ConnectorPivotMode.Manual:
// Do nothing
break;
}
break;
case ConnectorFollowType.PositionAndXYRotation:
// Set the transform of the entire tool tip
// Set the pivot relative to target/camera
toolTip.transform.position = target.transform.position;
toolTip.transform.rotation = target.transform.rotation;
switch (PivotMode)
{
case ConnectorPivotMode.Automatic:
Transform relativeTo = null;
switch (PivotDirectionOrient)
{
case ConnectorOrientType.OrientToCamera:
relativeTo = CameraCache.Main.transform;
break;
case ConnectorOrientType.OrientToObject:
relativeTo = target.transform;
break;
}
toolTip.PivotPosition = target.transform.position + GetDirectionFromPivotDirection(
PivotDirection,
ManualPivotDirection,
relativeTo) * PivotDistance;
break;
case ConnectorPivotMode.LocalPosition:
toolTip.PivotPosition = target.transform.position + target.transform.TransformPoint(manualPivotLocalPosition);
break;
case ConnectorPivotMode.Manual:
// Do nothing
break;
}
break;
}
}
private void Update()
{
UpdatePosition();
}
/// <summary>
/// Computes the director of the connector
/// </summary>
/// <param name="pivotDirection">enum describing director of connector pivot</param>
/// <param name="manualPivotDirection">is the pivot set manually</param>
/// <param name="relativeTo">Transform that describes the frame of reference of the pivot</param>
/// <returns>a vector describing the pivot direction in world space</returns>
public static Vector3 GetDirectionFromPivotDirection(ConnectorPivotDirection pivotDirection, Vector3 manualPivotDirection, Transform relativeTo)
{
Vector3 dir = Vector3.zero;
switch (pivotDirection)
{
case ConnectorPivotDirection.North:
dir = Vector3.up;
break;
case ConnectorPivotDirection.Northeast:
dir = Vector3.Lerp(Vector3.up, Vector3.right, 0.5f).normalized;
break;
case ConnectorPivotDirection.East:
dir = Vector3.right;
break;
case ConnectorPivotDirection.Southeast:
dir = Vector3.Lerp(Vector3.down, Vector3.right, 0.5f).normalized;
break;
case ConnectorPivotDirection.South:
dir = Vector3.down;
break;
case ConnectorPivotDirection.Southwest:
dir = Vector3.Lerp(Vector3.down, Vector3.left, 0.5f).normalized;
break;
case ConnectorPivotDirection.West:
dir = Vector3.left;
break;
case ConnectorPivotDirection.Northwest:
dir = Vector3.Lerp(Vector3.up, Vector3.left, 0.5f).normalized;
break;
case ConnectorPivotDirection.InFront:
dir = Vector3.forward;
break;
case ConnectorPivotDirection.Manual:
dir = manualPivotDirection.normalized;
break;
}
return relativeTo.TransformDirection(dir);
}
}
}