using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; namespace SC.XR.Unity.Module_InputSystem { /// /// Use a Unity UI RectTransform as touchable surface. /// [RequireComponent(typeof(RectTransform))] public class NearInteractionTouchableUnityUI : BaseNearInteractionTouchable { private Lazy rectTransform; public static IReadOnlyList Instances => instances; private static readonly List instances = new List(); public NearInteractionTouchableUnityUI() { rectTransform = new Lazy(GetComponent); } public override float DistanceToTouchable(Vector3 samplePoint, out Vector3 normal) { normal = Normal; Vector3 localPoint = transform.InverseTransformPoint(samplePoint); // touchables currently can only be touched within the bounds of the rectangle. // We return infinity to ensure that any point outside the bounds does not get touched. if(!rectTransform.Value.rect.Contains(localPoint)) { return float.PositiveInfinity; } // Scale back to 3D space localPoint = TransformSize(transform,localPoint); return Math.Abs(localPoint.z); } /// /// Transforms the size from local to world. /// /// The transform. /// The local size. /// World size. public Vector3 TransformSize(Transform transform, Vector3 localSize) { Vector3 transformedSize = new Vector3(localSize.x, localSize.y, localSize.z); Transform t = transform; do { transformedSize.x *= t.localScale.x; transformedSize.y *= t.localScale.y; transformedSize.z *= t.localScale.z; t = t.parent; } while(t != null); return transformedSize; } protected void OnEnable() { instances.Add(this); } protected void OnDisable() { instances.Remove(this); } } }