Files
2026-02-21 16:45:37 +08:00

994 lines
35 KiB
C#

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<GameObject> objectsUnderPointer = new List<GameObject>();
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<GameObject> selectablesUnderGaze = new List<GameObject>();
private List<GameObject> selectablesUnderGazeLastFrame = new List<GameObject>();
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<Canvas>();
mySettings = GetComponent<CurvedUISettings>();
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<Selectable>() == null || !obj.GetComponent<Selectable>().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<RaycastResult> 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<RectTransform>().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<RectTransform>().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<RectTransform>().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<RectTransform>().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<Collider> list = new List<Collider>();
list.AddRange(GetComponents<Collider>());
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<Rigidbody>() != null || GetComponentInParent<Rigidbody>() != null)
{
if (colliderContainer != null)
{
UnityEngine.Object.Destroy(colliderContainer);
}
colliderContainer = CreateConvexCyllinderCollider();
}
else
{
SetupMeshColliderUsingMesh(CreateCyllinderColliderMesh());
}
break;
case CurvedUISettings.CurvedUIShape.CYLINDER_VERTICAL:
if (mySettings.ForceUseBoxCollider || GetComponent<Rigidbody>() != null || GetComponentInParent<Rigidbody>() != 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>();
boxCollider.size = new Vector3(mySettings.RingExternalDiameter, mySettings.RingExternalDiameter, 1f);
break;
}
case CurvedUISettings.CurvedUIShape.SPHERE:
if (GetComponent<Rigidbody>() != null || GetComponentInParent<Rigidbody>() != 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<MeshFilter>();
MeshCollider meshCollider = base.gameObject.AddComponent<MeshCollider>();
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<Vector3> list = new List<Vector3>();
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<RectTransform>().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<BoxCollider>();
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<Vector3> list = new List<Vector3>();
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<RectTransform>().rect;
float cyllinderRadiusInCanvasSpace = GetComponent<CurvedUISettings>().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<int> list2 = new List<int>();
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<Vector3> list = new List<Vector3>(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<int> list2 = new List<int>();
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<Graphic>();
if (!(item2.GetComponent<Selectable>() != 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<GameObject> GetObjectsUnderPointer()
{
if (objectsUnderPointer == null)
{
objectsUnderPointer = new List<GameObject>();
}
return objectsUnderPointer;
}
public List<GameObject> GetObjectsUnderScreenPos(Vector2 screenPos, Camera eventCamera = null)
{
if (eventCamera == null)
{
eventCamera = myCanvas.worldCamera;
}
return GetObjectsHitByRay(eventCamera.ScreenPointToRay(screenPos));
}
public List<GameObject> GetObjectsHitByRay(Ray ray)
{
List<GameObject> list = new List<GameObject>();
Vector2 o_positionOnCanvas;
if (!GetScreenSpacePointByRay(ray, out o_positionOnCanvas))
{
return list;
}
List<Graphic> list2 = new List<Graphic>();
IList<Graphic> 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>())
{
Slider component = GetObjectsUnderPointer()[i].GetComponent<Slider>();
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(component.handleRect.parent as RectTransform, lastFrameEventData.position, myCanvas.worldCamera, out localPoint);
localPoint -= component.handleRect.parent.GetComponent<RectTransform>().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<Slider>().fillRect.GetComponent<Graphic>().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<Vector3> verts, int vertexIndex, Vector2 requiredSize)
{
List<Vector3> list = new List<Vector3>();
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<Vector3> quad, float x, float y)
{
Vector3 zero = Vector3.zero;
List<float> list = new List<float>();
list.Add((1f - x) * (1f - y));
list.Add((1f - x) * y);
list.Add(x * y);
list.Add(x * (1f - y));
List<float> list2 = list;
for (int i = 0; i < 4; i++)
{
zero += quad[i] * list2[i];
}
return zero;
}
}
}