using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace CurvedUI { public class CurvedUIRaycaster : GraphicRaycaster { [SerializeField] private bool showDebug; private bool overrideEventData = true; private Canvas myCanvas; private CurvedUISettings mySettings; private Vector3 cyllinderMidPoint; private List objectsUnderPointer = new List(); private Vector2 lastCanvasPos = Vector2.zero; private GameObject colliderContainer; private PointerEventData lastFrameEventData; private PointerEventData curEventData; private PointerEventData eventDataToUse; private Camera cachedWorldCamera; private Ray cachedRay; private Graphic gph; private List selectablesUnderGaze = new List(); private List selectablesUnderGazeLastFrame = new List(); private float objectsUnderGazeLastChangeTime; private bool gazeClickExecuted; private bool pointingAtCanvas; private bool pointingAtCanvasLastFrame; private Image GazeProgressImage { get { return CurvedUIInputModule.Instance.GazeTimedClickProgressImage; } } public bool PointingAtCanvas { get { return pointingAtCanvas; } } protected override void Awake() { base.Awake(); myCanvas = GetComponent(); mySettings = GetComponent(); cyllinderMidPoint = new Vector3(0f, 0f, 0f - mySettings.GetCyllinderRadiusInCanvasSpace()); if (myCanvas.worldCamera == null && Camera.main != null) { myCanvas.worldCamera = Camera.main; } base.ignoreReversedGraphics = false; } protected override void Start() { CreateCollider(); } protected virtual void Update() { if (CurvedUIInputModule.ControlMethod == CurvedUIInputModule.CUIControlMethod.GAZE && CurvedUIInputModule.Instance.GazeUseTimedClick) { if (pointingAtCanvas) { if (!pointingAtCanvasLastFrame) { ResetGazeTimedClick(); } ProcessGazeTimedClick(); selectablesUnderGazeLastFrame.Clear(); selectablesUnderGazeLastFrame.AddRange(selectablesUnderGaze); selectablesUnderGaze.Clear(); selectablesUnderGaze.AddRange(objectsUnderPointer); selectablesUnderGaze.RemoveAll((GameObject obj) => obj.GetComponent() == null || !obj.GetComponent().interactable); if ((bool)GazeProgressImage) { if (GazeProgressImage.type != Image.Type.Filled) { GazeProgressImage.type = Image.Type.Filled; } GazeProgressImage.fillAmount = (Time.time - objectsUnderGazeLastChangeTime).RemapAndClamp(CurvedUIInputModule.Instance.GazeClickTimerDelay, CurvedUIInputModule.Instance.GazeClickTimer + CurvedUIInputModule.Instance.GazeClickTimerDelay, 0f, 1f); } } else if (!pointingAtCanvas && pointingAtCanvasLastFrame) { ResetGazeTimedClick(); if ((bool)GazeProgressImage) { GazeProgressImage.fillAmount = 0f; } } } pointingAtCanvasLastFrame = pointingAtCanvas; pointingAtCanvas = false; } private void ProcessGazeTimedClick() { if (selectablesUnderGazeLastFrame.Count == 0 || selectablesUnderGazeLastFrame.Count != selectablesUnderGaze.Count) { ResetGazeTimedClick(); return; } for (int i = 0; i < selectablesUnderGazeLastFrame.Count && i < selectablesUnderGaze.Count; i++) { if (selectablesUnderGazeLastFrame[i].GetInstanceID() != selectablesUnderGaze[i].GetInstanceID()) { ResetGazeTimedClick(); return; } } if (!gazeClickExecuted && Time.time > objectsUnderGazeLastChangeTime + CurvedUIInputModule.Instance.GazeClickTimer + CurvedUIInputModule.Instance.GazeClickTimerDelay) { Click(); gazeClickExecuted = true; } } private void ResetGazeTimedClick() { objectsUnderGazeLastChangeTime = Time.time; gazeClickExecuted = false; } public override void Raycast(PointerEventData eventData, List resultAppendList) { if (!mySettings.Interactable) { return; } if (myCanvas.worldCamera == null) { if ((bool)Camera.main) { myCanvas.worldCamera = Camera.main; } if (myCanvas.worldCamera == null) { Debug.LogWarning("CurvedUI: No WORLD CAMERA assigned to Canvas " + base.gameObject.name + " to use for event processing!", myCanvas.gameObject); return; } } cachedWorldCamera = myCanvas.worldCamera; switch (CurvedUIInputModule.ControlMethod) { case CurvedUIInputModule.CUIControlMethod.MOUSE: cachedRay = cachedWorldCamera.ScreenPointToRay(eventData.position); break; case CurvedUIInputModule.CUIControlMethod.GAZE: cachedRay = new Ray(cachedWorldCamera.transform.position, cachedWorldCamera.transform.forward); UpdateSelectedObjects(eventData); break; case CurvedUIInputModule.CUIControlMethod.WORLD_MOUSE: cachedRay = new Ray(cachedWorldCamera.transform.position, mySettings.CanvasToCurvedCanvas(CurvedUIInputModule.Instance.WorldSpaceMouseInCanvasSpace) - myCanvas.worldCamera.transform.position); break; case CurvedUIInputModule.CUIControlMethod.STEAMVR_LEGACY: cachedRay = new Ray(CurvedUIInputModule.Instance.ControllerPointingOrigin, CurvedUIInputModule.Instance.ControllerPointingDirection); break; case CurvedUIInputModule.CUIControlMethod.GOOGLEVR: cachedRay = new Ray(CurvedUIInputModule.Instance.ControllerPointingOrigin, CurvedUIInputModule.Instance.ControllerPointingDirection); break; case CurvedUIInputModule.CUIControlMethod.CUSTOM_RAY: case CurvedUIInputModule.CUIControlMethod.OCULUSVR: case CurvedUIInputModule.CUIControlMethod.STEAMVR_2: cachedRay = CurvedUIInputModule.CustomControllerRay; UpdateSelectedObjects(eventData); break; default: cachedRay = default(Ray); break; } if (curEventData == null) { curEventData = new PointerEventData(EventSystem.current); } if (!overrideEventData) { curEventData.pointerEnter = eventData.pointerEnter; curEventData.rawPointerPress = eventData.rawPointerPress; curEventData.pointerDrag = eventData.pointerDrag; curEventData.pointerCurrentRaycast = eventData.pointerCurrentRaycast; curEventData.pointerPressRaycast = eventData.pointerPressRaycast; curEventData.hovered.Clear(); curEventData.hovered.AddRange(eventData.hovered); curEventData.eligibleForClick = eventData.eligibleForClick; curEventData.pointerId = eventData.pointerId; curEventData.position = eventData.position; curEventData.delta = eventData.delta; curEventData.pressPosition = eventData.pressPosition; curEventData.clickTime = eventData.clickTime; curEventData.clickCount = eventData.clickCount; curEventData.scrollDelta = eventData.scrollDelta; curEventData.useDragThreshold = eventData.useDragThreshold; curEventData.dragging = eventData.dragging; curEventData.button = eventData.button; } if (mySettings.Angle != 0 && mySettings.enabled) { Vector2 o_canvasPos = eventData.position; switch (mySettings.Shape) { case CurvedUISettings.CurvedUIShape.CYLINDER: if (!RaycastToCyllinderCanvas(cachedRay, out o_canvasPos)) { return; } break; case CurvedUISettings.CurvedUIShape.CYLINDER_VERTICAL: if (!RaycastToCyllinderVerticalCanvas(cachedRay, out o_canvasPos)) { return; } break; case CurvedUISettings.CurvedUIShape.RING: if (!RaycastToRingCanvas(cachedRay, out o_canvasPos)) { return; } break; case CurvedUISettings.CurvedUIShape.SPHERE: if (!RaycastToSphereCanvas(cachedRay, out o_canvasPos)) { return; } break; } pointingAtCanvas = true; eventDataToUse = ((!overrideEventData) ? curEventData : eventData); if (eventDataToUse.pressPosition == eventDataToUse.position) { eventDataToUse.pressPosition = o_canvasPos; } eventDataToUse.position = o_canvasPos; if (CurvedUIInputModule.ControlMethod == CurvedUIInputModule.CUIControlMethod.STEAMVR_LEGACY) { eventDataToUse.delta = o_canvasPos - lastCanvasPos; lastCanvasPos = o_canvasPos; } } objectsUnderPointer = eventData.hovered; lastFrameEventData = eventData; base.Raycast((!overrideEventData) ? curEventData : eventData, resultAppendList); } public virtual bool RaycastToCyllinderCanvas(Ray ray3D, out Vector2 o_canvasPos, bool OutputInCanvasSpace = false) { if (showDebug) { Debug.DrawLine(ray3D.origin, ray3D.GetPoint(1000f), Color.red); } LayerMask layerMaskForMyLayer = GetLayerMaskForMyLayer(); RaycastHit hitInfo = default(RaycastHit); if (Physics.Raycast(ray3D, out hitInfo, float.PositiveInfinity, layerMaskForMyLayer)) { if (overrideEventData && hitInfo.collider.gameObject != base.gameObject && (colliderContainer == null || hitInfo.collider.transform.parent != colliderContainer.transform)) { o_canvasPos = Vector2.zero; return false; } Vector3 vector = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(hitInfo.point); Vector3 normalized = (vector - cyllinderMidPoint).normalized; float value = 0f - AngleSigned(normalized.ModifyY(0f), (mySettings.Angle >= 0) ? Vector3.forward : Vector3.back, Vector3.up); Vector2 size = myCanvas.GetComponent().rect.size; Vector2 vector2 = new Vector3(0f, 0f, 0f); vector2.x = value.Remap((float)(-mySettings.Angle) / 2f, (float)mySettings.Angle / 2f, (0f - size.x) / 2f, size.x / 2f); vector2.y = vector.y; if (OutputInCanvasSpace) { o_canvasPos = vector2; } else { o_canvasPos = myCanvas.worldCamera.WorldToScreenPoint(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(vector2)); } if (showDebug) { Debug.DrawLine(hitInfo.point, hitInfo.point.ModifyY(hitInfo.point.y + 10f), Color.green); Debug.DrawLine(hitInfo.point, myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(cyllinderMidPoint), Color.yellow); } return true; } o_canvasPos = Vector2.zero; return false; } public virtual bool RaycastToCyllinderVerticalCanvas(Ray ray3D, out Vector2 o_canvasPos, bool OutputInCanvasSpace = false) { if (showDebug) { Debug.DrawLine(ray3D.origin, ray3D.GetPoint(1000f), Color.red); } LayerMask layerMaskForMyLayer = GetLayerMaskForMyLayer(); RaycastHit hitInfo = default(RaycastHit); if (Physics.Raycast(ray3D, out hitInfo, float.PositiveInfinity, layerMaskForMyLayer)) { if (overrideEventData && hitInfo.collider.gameObject != base.gameObject && (colliderContainer == null || hitInfo.collider.transform.parent != colliderContainer.transform)) { o_canvasPos = Vector2.zero; return false; } Vector3 vector = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(hitInfo.point); Vector3 normalized = (vector - cyllinderMidPoint).normalized; float value = 0f - AngleSigned(normalized.ModifyX(0f), (mySettings.Angle >= 0) ? Vector3.forward : Vector3.back, Vector3.left); Vector2 size = myCanvas.GetComponent().rect.size; Vector2 vector2 = new Vector3(0f, 0f, 0f); vector2.y = value.Remap((float)(-mySettings.Angle) / 2f, (float)mySettings.Angle / 2f, (0f - size.y) / 2f, size.y / 2f); vector2.x = vector.x; if (OutputInCanvasSpace) { o_canvasPos = vector2; } else { o_canvasPos = myCanvas.worldCamera.WorldToScreenPoint(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(vector2)); } if (showDebug) { Debug.DrawLine(hitInfo.point, hitInfo.point.ModifyY(hitInfo.point.y + 10f), Color.green); Debug.DrawLine(hitInfo.point, myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(cyllinderMidPoint), Color.yellow); } return true; } o_canvasPos = Vector2.zero; return false; } public virtual bool RaycastToRingCanvas(Ray ray3D, out Vector2 o_canvasPos, bool OutputInCanvasSpace = false) { LayerMask layerMaskForMyLayer = GetLayerMaskForMyLayer(); RaycastHit hitInfo = default(RaycastHit); if (Physics.Raycast(ray3D, out hitInfo, float.PositiveInfinity, layerMaskForMyLayer)) { if (overrideEventData && hitInfo.collider.gameObject != base.gameObject && (colliderContainer == null || hitInfo.collider.transform.parent != colliderContainer.transform)) { o_canvasPos = Vector2.zero; return false; } Vector3 trans = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(hitInfo.point); Vector3 normalized = trans.ModifyZ(0f).normalized; Vector2 size = myCanvas.GetComponent().rect.size; float num = 0f - AngleSigned(normalized.ModifyZ(0f), Vector3.up, Vector3.back); Vector2 vector = new Vector2(0f, 0f); if (showDebug) { Debug.Log("angle: " + num); } if (num < 0f) { vector.x = num.Remap(0f, -mySettings.Angle, (0f - size.x) / 2f, size.x / 2f); } else { vector.x = num.Remap(360f, 360 - mySettings.Angle, (0f - size.x) / 2f, size.x / 2f); } vector.y = trans.magnitude.Remap((float)mySettings.RingExternalDiameter * 0.5f * (1f - mySettings.RingFill), (float)mySettings.RingExternalDiameter * 0.5f, (0f - size.y) * 0.5f * (float)((!mySettings.RingFlipVertical) ? 1 : (-1)), size.y * 0.5f * (float)((!mySettings.RingFlipVertical) ? 1 : (-1))); if (OutputInCanvasSpace) { o_canvasPos = vector; } else { o_canvasPos = myCanvas.worldCamera.WorldToScreenPoint(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(vector)); } return true; } o_canvasPos = Vector2.zero; return false; } public virtual bool RaycastToSphereCanvas(Ray ray3D, out Vector2 o_canvasPos, bool OutputInCanvasSpace = false) { LayerMask layerMaskForMyLayer = GetLayerMaskForMyLayer(); RaycastHit hitInfo = default(RaycastHit); if (Physics.Raycast(ray3D, out hitInfo, float.PositiveInfinity, layerMaskForMyLayer)) { if (overrideEventData && hitInfo.collider.gameObject != base.gameObject && (colliderContainer == null || hitInfo.collider.transform.parent != colliderContainer.transform)) { o_canvasPos = Vector2.zero; return false; } Vector2 size = myCanvas.GetComponent().rect.size; float num = ((!mySettings.PreserveAspect) ? (size.x / 2f) : mySettings.GetCyllinderRadiusInCanvasSpace()); Vector3 vector = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(hitInfo.point); Vector3 vector2 = new Vector3(0f, 0f, (!mySettings.PreserveAspect) ? 0f : (0f - num)); Vector3 normalized = (vector - vector2).normalized; Vector3 vector3 = Vector3.Cross(normalized, normalized.ModifyY(0f)).normalized * ((normalized.y < 0f) ? 1 : (-1)); float num2 = 0f - AngleSigned(normalized.ModifyY(0f), (mySettings.Angle <= 0) ? Vector3.back : Vector3.forward, (mySettings.Angle <= 0) ? Vector3.down : Vector3.up); float num3 = 0f - AngleSigned(normalized, normalized.ModifyY(0f), vector3); float num4 = (float)Mathf.Abs(mySettings.Angle) * 0.5f; float num5 = Mathf.Abs((!mySettings.PreserveAspect) ? ((float)mySettings.VerticalAngle * 0.5f) : (num4 * size.y / size.x)); Vector2 vector4 = new Vector2(num2.Remap(0f - num4, num4, (0f - size.x) * 0.5f, size.x * 0.5f), num3.Remap(0f - num5, num5, (0f - size.y) * 0.5f, size.y * 0.5f)); if (showDebug) { Debug.Log("h: " + num2 + " / v: " + num3 + " poc: " + vector4); Debug.DrawRay(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(vector2), myCanvas.transform.localToWorldMatrix.MultiplyVector(normalized) * Mathf.Abs(num), Color.red); Debug.DrawRay(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(vector2), myCanvas.transform.localToWorldMatrix.MultiplyVector(vector3) * 300f, Color.magenta); } if (OutputInCanvasSpace) { o_canvasPos = vector4; } else { o_canvasPos = myCanvas.worldCamera.WorldToScreenPoint(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(vector4)); } return true; } o_canvasPos = Vector2.zero; return false; } protected void CreateCollider() { List list = new List(); list.AddRange(GetComponents()); for (int i = 0; i < list.Count; i++) { UnityEngine.Object.Destroy(list[i]); } if (!mySettings.BlocksRaycasts || (mySettings.Shape == CurvedUISettings.CurvedUIShape.SPHERE && !mySettings.PreserveAspect && mySettings.VerticalAngle == 0)) { return; } switch (mySettings.Shape) { case CurvedUISettings.CurvedUIShape.CYLINDER: if (mySettings.ForceUseBoxCollider || GetComponent() != null || GetComponentInParent() != null) { if (colliderContainer != null) { UnityEngine.Object.Destroy(colliderContainer); } colliderContainer = CreateConvexCyllinderCollider(); } else { SetupMeshColliderUsingMesh(CreateCyllinderColliderMesh()); } break; case CurvedUISettings.CurvedUIShape.CYLINDER_VERTICAL: if (mySettings.ForceUseBoxCollider || GetComponent() != null || GetComponentInParent() != null) { if (colliderContainer != null) { UnityEngine.Object.Destroy(colliderContainer); } colliderContainer = CreateConvexCyllinderCollider(true); } else { SetupMeshColliderUsingMesh(CreateCyllinderColliderMesh(true)); } break; case CurvedUISettings.CurvedUIShape.RING: { BoxCollider boxCollider = base.gameObject.AddComponent(); boxCollider.size = new Vector3(mySettings.RingExternalDiameter, mySettings.RingExternalDiameter, 1f); break; } case CurvedUISettings.CurvedUIShape.SPHERE: if (GetComponent() != null || GetComponentInParent() != null) { Debug.LogWarning("CurvedUI: Sphere shape canvases as children of rigidbodies do not support user input. Switch to Cyllinder shape or remove the rigidbody from parent.", base.gameObject); } SetupMeshColliderUsingMesh(CreateSphereColliderMesh()); break; } } private void SetupMeshColliderUsingMesh(Mesh meshie) { MeshFilter meshFilter = this.AddComponentIfMissing(); MeshCollider meshCollider = base.gameObject.AddComponent(); meshFilter.mesh = meshie; meshCollider.sharedMesh = meshie; } private GameObject CreateConvexCyllinderCollider(bool vertical = false) { GameObject gameObject = new GameObject("_CurvedUIColliders"); gameObject.layer = base.gameObject.layer; gameObject.transform.SetParent(base.transform); gameObject.transform.ResetTransform(); Mesh mesh = new Mesh(); Vector3[] array = new Vector3[4]; (myCanvas.transform as RectTransform).GetWorldCorners(array); mesh.vertices = array; if (vertical) { array[0] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[1]); array[1] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[2]); array[2] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[0]); array[3] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[3]); } else { array[0] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[1]); array[1] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[0]); array[2] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[2]); array[3] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[3]); } mesh.vertices = array; List list = new List(); int num = Mathf.Max(8, Mathf.RoundToInt((float)(mySettings.BaseCircleSegments * Mathf.Abs(mySettings.Angle)) / 360f)); for (int i = 0; i < num; i++) { list.Add(Vector3.Lerp(mesh.vertices[0], mesh.vertices[2], (float)i * 1f / (float)(num - 1))); } if (mySettings.Angle != 0) { Rect rect = myCanvas.GetComponent().rect; float cyllinderRadiusInCanvasSpace = mySettings.GetCyllinderRadiusInCanvasSpace(); for (int j = 0; j < list.Count; j++) { Vector3 value = list[j]; if (vertical) { float f = list[j].y / rect.size.y * (float)mySettings.Angle * ((float)Math.PI / 180f); value.y = Mathf.Sin(f) * cyllinderRadiusInCanvasSpace; value.z += Mathf.Cos(f) * cyllinderRadiusInCanvasSpace - cyllinderRadiusInCanvasSpace; list[j] = value; } else { float f2 = list[j].x / rect.size.x * (float)mySettings.Angle * ((float)Math.PI / 180f); value.x = Mathf.Sin(f2) * cyllinderRadiusInCanvasSpace; value.z += Mathf.Cos(f2) * cyllinderRadiusInCanvasSpace - cyllinderRadiusInCanvasSpace; list[j] = value; } } } float x = mySettings.GetTesslationSize(false).x / 10f; for (int k = 0; k < list.Count - 1; k++) { GameObject gameObject2 = new GameObject("Box collider"); gameObject2.layer = base.gameObject.layer; gameObject2.transform.SetParent(gameObject.transform); gameObject2.transform.ResetTransform(); gameObject2.AddComponent(); if (vertical) { gameObject2.transform.localPosition = new Vector3(0f, (list[k + 1].y + list[k].y) * 0.5f, (list[k + 1].z + list[k].z) * 0.5f); gameObject2.transform.localScale = new Vector3(x, Vector3.Distance(array[0], array[1]), Vector3.Distance(list[k + 1], list[k])); gameObject2.transform.localRotation = Quaternion.LookRotation(list[k + 1] - list[k], array[0] - array[1]); } else { gameObject2.transform.localPosition = new Vector3((list[k + 1].x + list[k].x) * 0.5f, 0f, (list[k + 1].z + list[k].z) * 0.5f); gameObject2.transform.localScale = new Vector3(x, Vector3.Distance(array[0], array[1]), Vector3.Distance(list[k + 1], list[k])); gameObject2.transform.localRotation = Quaternion.LookRotation(list[k + 1] - list[k], array[0] - array[1]); } } return gameObject; } private Mesh CreateCyllinderColliderMesh(bool vertical = false) { Mesh mesh = new Mesh(); Vector3[] array = new Vector3[4]; (myCanvas.transform as RectTransform).GetWorldCorners(array); mesh.vertices = array; if (vertical) { array[0] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[1]); array[1] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[2]); array[2] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[0]); array[3] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[3]); } else { array[0] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[1]); array[1] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[0]); array[2] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[2]); array[3] = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(mesh.vertices[3]); } mesh.vertices = array; List list = new List(); int num = Mathf.Max(8, Mathf.RoundToInt((float)(mySettings.BaseCircleSegments * Mathf.Abs(mySettings.Angle)) / 360f)); for (int i = 0; i < num; i++) { list.Add(Vector3.Lerp(mesh.vertices[0], mesh.vertices[2], (float)i * 1f / (float)(num - 1))); list.Add(Vector3.Lerp(mesh.vertices[1], mesh.vertices[3], (float)i * 1f / (float)(num - 1))); } if (mySettings.Angle != 0) { Rect rect = myCanvas.GetComponent().rect; float cyllinderRadiusInCanvasSpace = GetComponent().GetCyllinderRadiusInCanvasSpace(); for (int j = 0; j < list.Count; j++) { Vector3 value = list[j]; if (vertical) { float f = list[j].y / rect.size.y * (float)mySettings.Angle * ((float)Math.PI / 180f); value.y = Mathf.Sin(f) * cyllinderRadiusInCanvasSpace; value.z += Mathf.Cos(f) * cyllinderRadiusInCanvasSpace - cyllinderRadiusInCanvasSpace; list[j] = value; } else { float f2 = list[j].x / rect.size.x * (float)mySettings.Angle * ((float)Math.PI / 180f); value.x = Mathf.Sin(f2) * cyllinderRadiusInCanvasSpace; value.z += Mathf.Cos(f2) * cyllinderRadiusInCanvasSpace - cyllinderRadiusInCanvasSpace; list[j] = value; } } } mesh.vertices = list.ToArray(); List list2 = new List(); for (int k = 0; k < list.Count / 2 - 1; k++) { if (vertical) { list2.Add(k * 2); list2.Add(k * 2 + 1); list2.Add(k * 2 + 2); list2.Add(k * 2 + 1); list2.Add(k * 2 + 3); list2.Add(k * 2 + 2); } else { list2.Add(k * 2 + 2); list2.Add(k * 2 + 1); list2.Add(k * 2); list2.Add(k * 2 + 2); list2.Add(k * 2 + 3); list2.Add(k * 2 + 1); } } mesh.triangles = list2.ToArray(); return mesh; } private Mesh CreateSphereColliderMesh() { Mesh mesh = new Mesh(); Vector3[] array = new Vector3[4]; (myCanvas.transform as RectTransform).GetWorldCorners(array); List list = new List(array); for (int i = 0; i < list.Count; i++) { list[i] = mySettings.transform.worldToLocalMatrix.MultiplyPoint3x4(list[i]); } if (mySettings.Angle != 0) { int count = list.Count; for (int j = 0; j < count; j += 4) { ModifyQuad(list, j, mySettings.GetTesslationSize(false)); } list.RemoveRange(0, count); float num = mySettings.VerticalAngle; float num2 = mySettings.Angle; Vector2 size = (myCanvas.transform as RectTransform).rect.size; float num3 = mySettings.GetCyllinderRadiusInCanvasSpace(); if (mySettings.PreserveAspect) { num = (float)mySettings.Angle * (size.y / size.x); } else { num3 = size.x / 2f; } for (int k = 0; k < list.Count; k++) { float num4 = (list[k].x / size.x).Remap(-0.5f, 0.5f, (180f - num2) / 2f - 90f, 180f - (180f - num2) / 2f - 90f); num4 *= (float)Math.PI / 180f; float num5 = (list[k].y / size.y).Remap(-0.5f, 0.5f, (180f - num) / 2f, 180f - (180f - num) / 2f); num5 *= (float)Math.PI / 180f; list[k] = new Vector3(Mathf.Sin(num5) * Mathf.Sin(num4) * num3, (0f - num3) * Mathf.Cos(num5), Mathf.Sin(num5) * Mathf.Cos(num4) * num3 + ((!mySettings.PreserveAspect) ? 0f : (0f - num3))); } } mesh.vertices = list.ToArray(); List list2 = new List(); for (int l = 0; l < list.Count; l += 4) { list2.Add(l); list2.Add(l + 1); list2.Add(l + 2); list2.Add(l + 3); list2.Add(l); list2.Add(l + 2); } mesh.triangles = list2.ToArray(); return mesh; } private LayerMask GetLayerMaskForMyLayer() { int num = -1; if (mySettings.RaycastMyLayerOnly) { num = 1 << base.gameObject.layer; } return num; } private float AngleSigned(Vector3 v1, Vector3 v2, Vector3 n) { return Mathf.Atan2(Vector3.Dot(n, Vector3.Cross(v1, v2)), Vector3.Dot(v1, v2)) * 57.29578f; } private bool ShouldStartDrag(Vector2 pressPos, Vector2 currentPos, float threshold, bool useDragThreshold) { if (!useDragThreshold) { return true; } return (pressPos - currentPos).sqrMagnitude >= threshold * threshold; } protected virtual void ProcessMove(PointerEventData pointerEvent) { GameObject newEnterTarget = pointerEvent.pointerCurrentRaycast.gameObject; HandlePointerExitAndEnter(pointerEvent, newEnterTarget); } protected void UpdateSelectedObjects(PointerEventData eventData) { bool flag = false; foreach (GameObject item in eventData.hovered) { if (item == eventData.selectedObject) { flag = true; break; } } if (!flag) { eventData.selectedObject = null; } foreach (GameObject item2 in eventData.hovered) { if (item2 == null) { continue; } gph = item2.GetComponent(); if (!(item2.GetComponent() != null) || !(gph != null) || gph.depth == -1 || !gph.raycastTarget) { continue; } if (eventData.selectedObject != item2) { eventData.selectedObject = item2; } break; } if (mySettings.ControlMethod == CurvedUIInputModule.CUIControlMethod.GAZE && eventData.IsPointerMoving() && eventData.pointerDrag != null && !eventData.dragging && ShouldStartDrag(eventData.pressPosition, eventData.position, EventSystem.current.pixelDragThreshold, eventData.useDragThreshold)) { ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.beginDragHandler); eventData.dragging = true; } } protected void HandlePointerExitAndEnter(PointerEventData currentPointerData, GameObject newEnterTarget) { if (newEnterTarget == null || currentPointerData.pointerEnter == null) { for (int i = 0; i < currentPointerData.hovered.Count; i++) { ExecuteEvents.Execute(currentPointerData.hovered[i], currentPointerData, ExecuteEvents.pointerExitHandler); } currentPointerData.hovered.Clear(); if (newEnterTarget == null) { currentPointerData.pointerEnter = newEnterTarget; return; } } if (currentPointerData.pointerEnter == newEnterTarget && (bool)newEnterTarget) { return; } GameObject gameObject = FindCommonRoot(currentPointerData.pointerEnter, newEnterTarget); if (currentPointerData.pointerEnter != null) { Transform parent = currentPointerData.pointerEnter.transform; while (parent != null && (!(gameObject != null) || !(gameObject.transform == parent))) { ExecuteEvents.Execute(parent.gameObject, currentPointerData, ExecuteEvents.pointerExitHandler); currentPointerData.hovered.Remove(parent.gameObject); parent = parent.parent; } } currentPointerData.pointerEnter = newEnterTarget; if (newEnterTarget != null) { Transform parent2 = newEnterTarget.transform; while (parent2 != null && parent2.gameObject != gameObject) { ExecuteEvents.Execute(parent2.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler); currentPointerData.hovered.Add(parent2.gameObject); parent2 = parent2.parent; } } } protected static GameObject FindCommonRoot(GameObject g1, GameObject g2) { if (g1 == null || g2 == null) { return null; } Transform parent = g1.transform; while (parent != null) { Transform parent2 = g2.transform; while (parent2 != null) { if (parent == parent2) { return parent.gameObject; } parent2 = parent2.parent; } parent = parent.parent; } return null; } private bool GetScreenSpacePointByRay(Ray ray, out Vector2 o_positionOnCanvas) { switch (mySettings.Shape) { case CurvedUISettings.CurvedUIShape.CYLINDER: return RaycastToCyllinderCanvas(ray, out o_positionOnCanvas); case CurvedUISettings.CurvedUIShape.CYLINDER_VERTICAL: return RaycastToCyllinderVerticalCanvas(ray, out o_positionOnCanvas); case CurvedUISettings.CurvedUIShape.RING: return RaycastToRingCanvas(ray, out o_positionOnCanvas); case CurvedUISettings.CurvedUIShape.SPHERE: return RaycastToSphereCanvas(ray, out o_positionOnCanvas); default: o_positionOnCanvas = Vector2.zero; return false; } } public void RebuildCollider() { cyllinderMidPoint = new Vector3(0f, 0f, 0f - mySettings.GetCyllinderRadiusInCanvasSpace()); CreateCollider(); } public List GetObjectsUnderPointer() { if (objectsUnderPointer == null) { objectsUnderPointer = new List(); } return objectsUnderPointer; } public List GetObjectsUnderScreenPos(Vector2 screenPos, Camera eventCamera = null) { if (eventCamera == null) { eventCamera = myCanvas.worldCamera; } return GetObjectsHitByRay(eventCamera.ScreenPointToRay(screenPos)); } public List GetObjectsHitByRay(Ray ray) { List list = new List(); Vector2 o_positionOnCanvas; if (!GetScreenSpacePointByRay(ray, out o_positionOnCanvas)) { return list; } List list2 = new List(); IList graphicsForCanvas = GraphicRegistry.GetGraphicsForCanvas(myCanvas); for (int i = 0; i < graphicsForCanvas.Count; i++) { Graphic graphic = graphicsForCanvas[i]; if (graphic.depth != -1 && graphic.raycastTarget && RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, o_positionOnCanvas, eventCamera) && graphic.Raycast(o_positionOnCanvas, eventCamera)) { list2.Add(graphic); } } list2.Sort((Graphic g1, Graphic g2) => g2.depth.CompareTo(g1.depth)); for (int num = 0; num < list2.Count; num++) { list.Add(list2[num].gameObject); } list2.Clear(); return list; } public void Click() { for (int i = 0; i < GetObjectsUnderPointer().Count; i++) { if ((bool)GetObjectsUnderPointer()[i].GetComponent()) { Slider component = GetObjectsUnderPointer()[i].GetComponent(); Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(component.handleRect.parent as RectTransform, lastFrameEventData.position, myCanvas.worldCamera, out localPoint); localPoint -= component.handleRect.parent.GetComponent().rect.position; if (component.direction == Slider.Direction.LeftToRight || component.direction == Slider.Direction.RightToLeft) { component.normalizedValue = localPoint.x / (component.handleRect.parent as RectTransform).rect.width; } else { component.normalizedValue = localPoint.y / (component.handleRect.parent as RectTransform).rect.height; } GetObjectsUnderPointer()[i].GetComponent().fillRect.GetComponent().SetAllDirty(); } else { ExecuteEvents.Execute(GetObjectsUnderPointer()[i], lastFrameEventData, ExecuteEvents.pointerDownHandler); ExecuteEvents.Execute(GetObjectsUnderPointer()[i], lastFrameEventData, ExecuteEvents.pointerClickHandler); ExecuteEvents.Execute(GetObjectsUnderPointer()[i], lastFrameEventData, ExecuteEvents.pointerUpHandler); } } } private void ModifyQuad(List verts, int vertexIndex, Vector2 requiredSize) { List list = new List(); for (int i = 0; i < 4; i++) { list.Add(verts[vertexIndex + i]); } Vector3 vector = list[2] - list[1]; Vector3 vector2 = list[1] - list[0]; int num = Mathf.CeilToInt(vector.magnitude * (1f / Mathf.Max(1f, requiredSize.x))); int num2 = Mathf.CeilToInt(vector2.magnitude * (1f / Mathf.Max(1f, requiredSize.y))); float y = 0f; for (int j = 0; j < num2; j++) { float num3 = ((float)j + 1f) / (float)num2; float x = 0f; for (int k = 0; k < num; k++) { float num4 = ((float)k + 1f) / (float)num; verts.Add(TesselateQuad(list, x, y)); verts.Add(TesselateQuad(list, x, num3)); verts.Add(TesselateQuad(list, num4, num3)); verts.Add(TesselateQuad(list, num4, y)); x = num4; } y = num3; } } private Vector3 TesselateQuad(List quad, float x, float y) { Vector3 zero = Vector3.zero; List list = new List(); list.Add((1f - x) * (1f - y)); list.Add((1f - x) * y); list.Add(x * y); list.Add(x * (1f - y)); List list2 = list; for (int i = 0; i < 4; i++) { zero += quad[i] * list2[i]; } return zero; } } }