Ejemplo n.º 1
0
        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))
            {
                //find if we hit this canvas
                if (overrideEventData && hit.collider.gameObject != this.gameObject)
                {
                    o_canvasPos = Vector2.zero;
                    return(false);
                }

                Vector2 canvasSize = canvas.GetComponent <RectTransform>().rect.size;
                float   radius     = settings.GetCyllinderRadiusInCanvasSpace();

                //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             = canvas.transform.worldToLocalMatrix.MultiplyPoint3x4(hit.point);
                Vector3 SphereCenter              = new Vector3(0, 0, -radius);
                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), (settings.Angle > 0 ? Vector3.forward : Vector3.back), (settings.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(settings.Angle) * 0.5f;
                float vAngularSize = Mathf.Abs(hAngularSize * canvasSize.y / canvasSize.x);

                //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(canvas.transform.localToWorldMatrix.MultiplyPoint3x4(SphereCenter), canvas.transform.localToWorldMatrix.MultiplyVector(directionFromSphereCenter) * Mathf.Abs(radius), Color.red);
                    Debug.DrawRay(canvas.transform.localToWorldMatrix.MultiplyPoint3x4(SphereCenter), canvas.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 = canvas.worldCamera.WorldToScreenPoint(canvas.transform.localToWorldMatrix.MultiplyPoint3x4(pointOnCanvas));
                }

                return(true);
            }

            o_canvasPos = Vector2.zero;
            return(false);
        }
Ejemplo n.º 2
0
        private 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 = canvas.transform.localToWorldMatrix;
            canvasToLocal = canvas.transform.worldToLocalMatrix;
            toWorld       = transform.localToWorldMatrix;
            toLocal       = 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.
                rectSize = (transform as RectTransform).rect.size;

                tesselationRequired = false;
            }


            //lets get some values needed for curving from settings
            angle = settings.Angle;
            float   radius     = settings.GetCyllinderRadiusInCanvasSpace();
            Vector2 canvasSize = (canvas.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);
            }
        }