Esempio n. 1
0
        // copy paste from EventSystem.cs original code since its private and i need it
        private static int RaycastComparer(MLURaycastResult lhs, MLURaycastResult rhs)
        {
            if (lhs.module != rhs.module && lhs.rootCanvas != rhs.rootCanvas)
            {
                if (lhs.distance < rhs.distance)
                {
                    return(-1);
                }
                if (lhs.distance > rhs.distance)
                {
                    return(1);
                }

                return(0);
            }

            if (lhs.sortingLayer != rhs.sortingLayer)
            {
                // Uses the layer value to properly compare the relative order of the layers.
                var rid = SortingLayer.GetLayerValueFromID(rhs.sortingLayer);
                var lid = SortingLayer.GetLayerValueFromID(lhs.sortingLayer);
                return(rid.CompareTo(lid));
            }

            if (lhs.sortingOrder != rhs.sortingOrder)
            {
                return(rhs.sortingOrder.CompareTo(lhs.sortingOrder));
            }

            if (lhs.depth != rhs.depth)
            {
                return(rhs.depth.CompareTo(lhs.depth));
            }

            if (lhs.distance != rhs.distance)
            {
                return(lhs.distance.CompareTo(rhs.distance));
            }

            return(lhs.index.CompareTo(rhs.index));
        }
        /// <summary>
        /// Performs the given GraphicRaycaster raycast taking the given ray as if it were a world pointer instead of screen mouse input. Event camera must be viewing the whole ray for this modification to work.
        /// </summary>
        /// <param name="rayPointer">ray represeting a physical pointer that may point into the raycaster's canvas</param>
        /// <param name="raycaster">the configuration of this raycaster will be used to perform the raycast</param>
        /// <param name="eventData">Current event data</param>
        /// <param name="resultAppendList">List of hit objects to append new results to.</param>
        public static void RaycastRayPointer(Ray rayPointer, GraphicRaycaster raycaster, Camera eventCamera, PointerEventData eventData, List <MLURaycastResult> resultAppendList)
        {
            Canvas canvas = raycaster.GetComponent <Canvas>();

            if (canvas == null || eventCamera == null)
            {
                return;
            }
            canvas.worldCamera = eventCamera;             // this kind of raycasting requires all canvases to use the same eventCamera

            if (canvas.renderMode != RenderMode.WorldSpace)
            {
                Debug.LogError("GraphicRaycaster's canvas must be in world space render mode when using pointer ray raycasting. Disabling GraphicRaycaster...");
                raycaster.enabled = false;
                return;
            }

            var canvasGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas);

            if (canvasGraphics == null || canvasGraphics.Count == 0)
            {
                return;
            }

            Plane canvasPlane = new Plane(-canvas.transform.forward, canvas.transform.position);
            float dist;

            if (!canvasPlane.Raycast(rayPointer, out dist))
            {
                return;
            }
            Vector2 screenPointerPos = eventCamera.WorldToScreenPoint(rayPointer.GetPoint(dist));

            Vector2 previousPosition = eventData.position;
            Vector2 previousDelta    = eventData.delta;

            eventData.delta    = screenPointerPos - eventData.position;
            eventData.position = screenPointerPos;

            float hitDistance = float.MaxValue;

            // obtain m_BlockingMask field from through reflection
            LayerMask m_BlockingMask = (LayerMask)BlockingMaskInfo.GetValue(raycaster);

            if (raycaster.blockingObjects != BlockingObjects.None)
            {
                float distanceToClipPlane;
                canvasPlane.Raycast(rayPointer, out distanceToClipPlane);

                if (raycaster.blockingObjects == BlockingObjects.ThreeD || raycaster.blockingObjects == BlockingObjects.All)
                {
                    var hits = Physics.RaycastAll(rayPointer, distanceToClipPlane, (int)m_BlockingMask);
                    if (hits.Length > 0)
                    {
                        hitDistance = hits[0].distance;
                    }
                }

                if (raycaster.blockingObjects == BlockingObjects.TwoD || raycaster.blockingObjects == BlockingObjects.All)
                {
                    var hits = Physics2D.GetRayIntersectionAll(rayPointer, distanceToClipPlane, (int)m_BlockingMask);
                    if (hits.Length > 0)
                    {
                        hitDistance = hits[0].distance;
                    }
                }
            }

            s_RaycastResults.Clear();
            Raycast(canvas, eventCamera, eventData.position, canvasGraphics, s_RaycastResults);

            int totalCount = s_RaycastResults.Count;

            for (var index = 0; index < totalCount; index++)
            {
                var  go            = s_RaycastResults[index].gameObject;
                bool appendGraphic = true;

                if (raycaster.ignoreReversedGraphics)
                {
                    var dir = go.transform.rotation * Vector3.forward;
                    appendGraphic = Vector3.Dot(rayPointer.direction, dir) > 0;
                }

                if (appendGraphic)
                {
                    float distance = 0;

                    Transform trans        = go.transform;
                    Vector3   transForward = trans.forward;
                    // http://geomalgorithms.com/a06-_intersect-2.html
                    distance = (Vector3.Dot(transForward, trans.position - rayPointer.origin) / Vector3.Dot(transForward, rayPointer.direction));

                    // Check to see if the go is behind the camera or its blocked by another object
                    if (distance < 0 || distance >= hitDistance)
                    {
                        continue;
                    }

                    var castResult = new MLURaycastResult
                    {
                        gameObject     = go,
                        module         = raycaster,
                        distance       = distance,
                        screenPosition = eventData.position,
                        screenDelta    = eventData.delta,
                        index          = resultAppendList.Count,
                        depth          = s_RaycastResults[index].depth,
                        sortingLayer   = canvas.sortingLayerID,
                        sortingOrder   = canvas.sortingOrder,
                        canvas         = canvas,
                        rootCanvas     = canvas.rootCanvas,
                        worldPosition  = rayPointer.GetPoint(distance),
                        worldNormal    = -trans.forward
                    };

                    resultAppendList.Add(castResult);
                }
            }

            // in this kind of raycast event position and delta are supposed to be assigned on the Input Module, the fact that they are changed at the start of this method its only
            // to prevent more code rewritting from original Unity code
            eventData.position = previousPosition;
            eventData.delta    = previousDelta;
        }