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);
        }
Example #2
0
        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);
            }
        }