public virtual bool RaycastToSphereCanvas(Ray ray3D, out Vector2 o_canvasPos, bool OutputInCanvasSpace = false, int myLayerMask = -1) { RaycastHit hit = new RaycastHit(); if (Physics.Raycast(ray3D, out hit, float.PositiveInfinity, myLayerMask)) { Vector2 canvasSize = myCanvas.GetComponent <RectTransform>().rect.size; float radius = (mySettings.PreserveAspect ? mySettings.GetCyllinderRadiusInCanvasSpace() : canvasSize.x / 2.0f); //local hit point on canvas, direction from its center and a vector perpendicular to direction, so we can use it to calculate its angle in both planes. Vector3 localHitPoint = myCanvas.transform.worldToLocalMatrix.MultiplyPoint3x4(hit.point); Vector3 SphereCenter = new Vector3(0, 0, mySettings.PreserveAspect ? -radius : 0); Vector3 directionFromSphereCenter = (localHitPoint - SphereCenter).normalized; Vector3 XZPlanePerpendicular = Vector3.Cross(directionFromSphereCenter, directionFromSphereCenter.ModifyY(0)).normalized *(directionFromSphereCenter.y < 0 ? 1 : -1); //horizontal and vertical angle between middle of the sphere and the hit point. //We do some fancy checks to determine vectors we compare them to, //to make sure they are negative on the left and bottom side of the canvas float hAngle = -AngleSigned(directionFromSphereCenter.ModifyY(0), (mySettings.Angle > 0 ? Vector3.forward : Vector3.back), (mySettings.Angle > 0 ? Vector3.up : Vector3.down)); float vAngle = -AngleSigned(directionFromSphereCenter, directionFromSphereCenter.ModifyY(0), XZPlanePerpendicular); //find the size of the canvas expressed as measure of the arc it occupies on the sphere float hAngularSize = Mathf.Abs(mySettings.Angle) * 0.5f; float vAngularSize = Mathf.Abs(mySettings.PreserveAspect ? hAngularSize * canvasSize.y / canvasSize.x : mySettings.VerticalAngle * 0.5f); //map the intersection point to 2d point in canvas space Vector2 pointOnCanvas = new Vector2(hAngle.Remap(-hAngularSize, hAngularSize, -canvasSize.x * 0.5f, canvasSize.x * 0.5f), vAngle.Remap(-vAngularSize, vAngularSize, -canvasSize.y * 0.5f, canvasSize.y * 0.5f)); if (showDebug) { Debug.Log("h: " + hAngle + " / v: " + vAngle + " poc: " + pointOnCanvas); Debug.DrawRay(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(SphereCenter), myCanvas.transform.localToWorldMatrix.MultiplyVector(directionFromSphereCenter) * Mathf.Abs(radius), Color.red); Debug.DrawRay(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(SphereCenter), myCanvas.transform.localToWorldMatrix.MultiplyVector(XZPlanePerpendicular) * 300, Color.magenta); } if (OutputInCanvasSpace) { o_canvasPos = pointOnCanvas; } else // convert the result to screen point in camera.This will be later used by raycaster and world camera to determine what we're pointing at { o_canvasPos = myCanvas.worldCamera.WorldToScreenPoint(myCanvas.transform.localToWorldMatrix.MultiplyPoint3x4(pointOnCanvas)); } return(true); } o_canvasPos = Vector2.zero; return(false); }
void ModifyVerts(List <UIVertex> verts) { if (verts == null || verts.Count == 0) { return; } //update transformation matrices we're going to use in curving the verts. CanvasToWorld = myCanvas.transform.localToWorldMatrix; CanvasToLocal = myCanvas.transform.worldToLocalMatrix; MyToWorld = transform.localToWorldMatrix; MyToLocal = transform.worldToLocalMatrix; //tesselate the vertices if needed and save them to a list, //so we don't have to retesselate if RectTransform's size has not changed. if (tesselationRequired || !Application.isPlaying) { TesselateGeometry(verts); // Save the tesselated vertices, so if the size does not change, // we can use them when redrawing vertices. tesselatedVerts = new List <UIVertex>(verts); //save the transform properties we last tesselated for. savedRectSize = (transform as RectTransform).rect.size; tesselationRequired = false; } //lets get some values needed for curving from settings angle = mySettings.Angle; float radius = mySettings.GetCyllinderRadiusInCanvasSpace(); Vector2 canvasSize = (myCanvas.transform as RectTransform).rect.size; int initialCount = verts.Count; if (tesselatedVerts != null) { // use saved verts if we have those UIVertex[] copiedVerts = new UIVertex[tesselatedVerts.Count]; for (int i = 0; i < tesselatedVerts.Count; i++) { copiedVerts[i] = CurveVertex(tesselatedVerts[i], angle, radius, canvasSize); } verts.AddRange(copiedVerts); verts.RemoveRange(0, initialCount); } else // or just the mesh's vertices if we do not { UIVertex[] copiedVerts = new UIVertex[verts.Count]; for (int i = 0; i < initialCount; i++) { copiedVerts[i] = CurveVertex(verts[i], angle, radius, canvasSize); } verts.AddRange(copiedVerts); verts.RemoveRange(0, initialCount); } }
protected override void Awake() { base.Awake(); myCanvas = GetComponent <Canvas>(); mySettings = GetComponent <CurvedUISettings>(); cyllinderMidPoint = new Vector3(0, 0, -mySettings.GetCyllinderRadiusInCanvasSpace()); //the canvas needs an event camera set up to process events correctly. Try to use main camera if no one is provided. if (myCanvas.worldCamera == null && Camera.main != null) { myCanvas.worldCamera = Camera.main; } }
protected override void Awake() { base.Awake(); myCanvas = GetComponent <Canvas>(); mySettings = GetComponent <CurvedUISettings>(); cyllinderMidPoint = new Vector3(0, 0, -mySettings.GetCyllinderRadiusInCanvasSpace()); //the canvas needs an event camera set up to process events correctly. Try to use main camera if no one is provided. if (myCanvas.worldCamera == null && Camera.main != null) { myCanvas.worldCamera = Camera.main; } handle = clientData.RootFind("[CameraRig]/Controller (right)"); //Add By Lcx }
//This is called by canvas after UI object's mesh is generated, but before it is rendered. //Best place to modify the vertices of the object. public override void ModifyMesh(VertexHelper vh) { if (!ShouldModify()) { return; } //check for changes in text font material that would mean a retesselation in required to get fresh UV's CheckTextFontMaterial(); //TESSELATING VERTICES--------------------------------------------------------// //tesselate (subdivide) the vertices of the UI object if we need more of them //to display nice curvature. Save them to a list, so we don't have to retesselate //if RectTransform's size has not changed. if (tesselationRequired || !Application.isPlaying) { //Prepare a list and get vertices from the vertex stream. These come as triangles. if (m_tesselatedVerts == null) { m_tesselatedVerts = new List <UIVertex>(); } else { m_tesselatedVerts.Clear(); } vh.GetUIVertexStream(m_tesselatedVerts); //subdivide them TesselateGeometry(m_tesselatedVerts); //save the transform properties we last tesselated for. savedRectSize = (transform as RectTransform).rect.size; //set flag tesselationRequired = false; curvingRequired = true; } //CURVING VERTICES ---------------------------------------------------------// if (curvingRequired) { //update transformation matrices we're going to use in curving the verts. CanvasToWorld = myCanvas.transform.localToWorldMatrix; CanvasToLocal = myCanvas.transform.worldToLocalMatrix; MyToWorld = transform.localToWorldMatrix; MyToLocal = transform.worldToLocalMatrix; //prepare list if (m_curvedVerts == null) { m_curvedVerts = new List <UIVertex>(); } //Debug.Log("verts:" + m_curvedVerts.Count + " tess'd:" + m_tesselatedVerts.Count); if (m_curvedVerts.Count == m_tesselatedVerts.Count) { //Debug.Log("count equal"); for (int i = 0; i < m_curvedVerts.Count; i++) { m_curvedVerts[i] = CurveVertex(m_tesselatedVerts[i], mySettings.Angle, mySettings.GetCyllinderRadiusInCanvasSpace(), (myCanvas.transform as RectTransform).rect.size); } } else { m_curvedVerts.Clear(); for (int i = 0; i < m_tesselatedVerts.Count; i++) { m_curvedVerts.Add(CurveVertex(m_tesselatedVerts[i], mySettings.Angle, mySettings.GetCyllinderRadiusInCanvasSpace(), (myCanvas.transform as RectTransform).rect.size)); } } //set flags curvingRequired = false; } //SAVE CURVED VERTICES TO THE VERTEX HELPER------------------------// //They can come as quads or as triangles. vh.Clear(); if (m_curvedVerts.Count % 4 == 0) { for (int i = 0; i < m_curvedVerts.Count; i += 4) { for (int v = 0; v < 4; v++)//create a quad { m_quad[v] = m_curvedVerts[i + v]; } vh.AddUIVertexQuad(m_quad); // add it to the list } } else { vh.AddUIVertexTriangleStream(m_curvedVerts); } }