// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using UnityEngine; namespace Microsoft.MixedReality.Toolkit.UI { /// /// Static class providing useful functions for /// finding ToolTip Attach point information. /// public static class ToolTipUtility { private const int NumPivotLocations = 8; /// /// Avoid running this query in Update function because calculating Vector3.Distance requires sqr root calculation (expensive) /// Instead, find strategic moments to update nearest pivot (i.e. only once when ToolTip becomes active) /// /// Transform of object serving as anchor for tooltip /// Transform for the tooltip content /// list of positions to find the closest /// pivot type needed for calculation of closest /// Vector3 the point in localPivotPositions which is closest to the anchor position public static Vector3 FindClosestAttachPointToAnchor(Transform anchor, Transform contentParent, Vector3[] localPivotPositions, ToolTipAttachPoint pivotType) { Vector3 currentPivot; Vector3 nearPivot = Vector3.zero; Vector3 anchorPosition = anchor.position; float nearDist = Mathf.Infinity; if (localPivotPositions == null || localPivotPositions.Length < NumPivotLocations) { return nearPivot; } switch (pivotType) { case ToolTipAttachPoint.Center: return nearPivot; // Search all pivots case ToolTipAttachPoint.Closest: for (int i = 0; i < localPivotPositions.Length; i++) { currentPivot = localPivotPositions[i]; float sqrDist = (anchorPosition - contentParent.TransformPoint(currentPivot)).sqrMagnitude; if (sqrDist < nearDist) { nearDist = sqrDist; nearPivot = currentPivot; } } break; // Search corner pivots case ToolTipAttachPoint.ClosestCorner: for (int i = (int)ToolTipAttachPoint.BottomRightCorner; i < (int)ToolTipAttachPoint.TopLeftCorner; i++) { currentPivot = localPivotPositions[i]; float sqrDist = (anchorPosition - contentParent.TransformPoint(currentPivot)).sqrMagnitude; if (sqrDist < nearDist) { nearDist = sqrDist; nearPivot = currentPivot; } } break; // Search middle pivots case ToolTipAttachPoint.ClosestMiddle: for (int i = (int)ToolTipAttachPoint.BottomMiddle; i < (int)ToolTipAttachPoint.LeftMiddle; i++) { currentPivot = localPivotPositions[i]; float sqrDist = (anchorPosition - contentParent.TransformPoint(currentPivot)).sqrMagnitude; if (sqrDist < nearDist) { nearDist = sqrDist; nearPivot = currentPivot; } } break; default: // For all other types, just use the array position or contentParent // position if there is no array provided. nearPivot = localPivotPositions.Length == 0 ? contentParent.position : localPivotPositions[(int)pivotType]; break; } return nearPivot; } /// /// gets an array of pivot positions /// /// ref array that gets filled with positions /// the xy scale of the tooltip public static void GetAttachPointPositions(ref Vector3[] pivotPositions, Vector2 localContentSize) { if (pivotPositions == null || pivotPositions.Length < NumPivotLocations) { pivotPositions = new Vector3[NumPivotLocations]; } // Get the extents of our content size localContentSize *= 0.5f; pivotPositions[(int)ToolTipAttachPoint.BottomMiddle] = new Vector3(0f, -localContentSize.y, 0f); pivotPositions[(int)ToolTipAttachPoint.TopMiddle] = new Vector3(0f, localContentSize.y, 0f); pivotPositions[(int)ToolTipAttachPoint.LeftMiddle] = new Vector3(-localContentSize.x, 0f, 0f); // was right pivotPositions[(int)ToolTipAttachPoint.RightMiddle] = new Vector3(localContentSize.x, 0f, 0f); // was left pivotPositions[(int)ToolTipAttachPoint.BottomLeftCorner] = new Vector3(-localContentSize.x, -localContentSize.y, 0f); // was right pivotPositions[(int)ToolTipAttachPoint.BottomRightCorner] = new Vector3(localContentSize.x, -localContentSize.y, 0f); // was left pivotPositions[(int)ToolTipAttachPoint.TopLeftCorner] = new Vector3(-localContentSize.x, localContentSize.y, 0f); // was right pivotPositions[(int)ToolTipAttachPoint.TopRightCorner] = new Vector3(localContentSize.x, localContentSize.y, 0f); // was left } } }