GetGraphicsForCanvas() public static method

Return a list of Graphics that are registered on the Canvas.

public static GetGraphicsForCanvas ( Canvas canvas ) : IList
canvas Canvas Input canvas.
return IList
Esempio n. 1
0
        private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, List <GameObject> results)
        {
            // Necessary for the event system
            var foundGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas);

            s_SortedGraphics.Clear();

            for (int i = 0; i < foundGraphics.Count; ++i)
            {
                Graphic graphic = foundGraphics[i];

                // -1 means it hasn't been processed by the canvas, which means it isn't actually drawn
                if (graphic.depth == -1)
                {
                    continue;
                }
                if (!RectTransformUtility.PointInRectangle(pointerPosition, graphic.rectTransform, eventCamera))
                {
                    continue;
                }

                if (graphic.Raycast(pointerPosition, eventCamera))
                {
                    s_SortedGraphics.Add(graphic);
                }
            }

            s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));
            for (int i = 0; i < s_SortedGraphics.Count; ++i)
            {
                results.Add(s_SortedGraphics[i].gameObject);
            }
        }
Esempio n. 2
0
        private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, List <Graphic> results)
        {
            IList <Graphic> graphicsForCanvas = GraphicRegistry.GetGraphicsForCanvas(canvas);

            for (int i = 0; i < graphicsForCanvas.Count; i++)
            {
                Graphic graphic = graphicsForCanvas[i];
                if (!graphic.canvasRenderer.cull)
                {
                    if (graphic.depth != -1 && graphic.raycastTarget)
                    {
                        if (RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera))
                        {
                            if (graphic.Raycast(pointerPosition, eventCamera))
                            {
                                GraphicRaycaster.s_SortedGraphics.Add(graphic);
                            }
                        }
                    }
                }
            }
            GraphicRaycaster.s_SortedGraphics.Sort((Graphic g1, Graphic g2) => g2.depth.CompareTo(g1.depth));
            for (int j = 0; j < GraphicRaycaster.s_SortedGraphics.Count; j++)
            {
                results.Add(GraphicRaycaster.s_SortedGraphics[j]);
            }
            GraphicRaycaster.s_SortedGraphics.Clear();
        }
Esempio n. 3
0
        private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, List <Graphic> results)
        {
            IList <Graphic> graphicsForCanvas = GraphicRegistry.GetGraphicsForCanvas(canvas);

            for (int i = 0; i < graphicsForCanvas.Count; i++)
            {
                Graphic item = graphicsForCanvas[i];
                if ((!item.canvasRenderer.cull && (item.depth != -1)) && ((item.raycastTarget && RectTransformUtility.RectangleContainsScreenPoint(item.rectTransform, pointerPosition, eventCamera)) && item.Raycast(pointerPosition, eventCamera)))
                {
                    s_SortedGraphics.Add(item);
                }
            }
            if (< > f__am$cache0 == null)
            {
        private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, List <Graphic> results)
        {
            IList <Graphic> graphicsForCanvas = GraphicRegistry.GetGraphicsForCanvas(canvas);

            for (int index = 0; index < graphicsForCanvas.Count; ++index)
            {
                Graphic graphic = graphicsForCanvas[index];
                if (graphic.depth != -1 && graphic.raycastTarget && (RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera) && graphic.Raycast(pointerPosition, eventCamera)))
                {
                    GraphicRaycaster.s_SortedGraphics.Add(graphic);
                }
            }
            GraphicRaycaster.s_SortedGraphics.Sort((Comparison <Graphic>)((g1, g2) => g2.depth.CompareTo(g1.depth)));
            for (int index = 0; index < GraphicRaycaster.s_SortedGraphics.Count; ++index)
            {
                results.Add(GraphicRaycaster.s_SortedGraphics[index]);
            }
            GraphicRaycaster.s_SortedGraphics.Clear();
        }
Esempio n. 5
0
        private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, List <Graphic> results)
        {
            // Debug.Log("ttt" + pointerPoision + ":::" + camera);
            // Necessary for the event system
            var foundGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas);

            for (int i = 0; i < foundGraphics.Count; ++i)
            {
                Graphic graphic = foundGraphics[i];

                if (graphic.canvasRenderer.cull)
                {
                    continue;
                }

                // -1 means it hasn't been processed by the canvas, which means it isn't actually drawn
                if (graphic.depth == -1 || !graphic.raycastTarget)
                {
                    continue;
                }

                if (!RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera))
                {
                    continue;
                }

                if (graphic.Raycast(pointerPosition, eventCamera))
                {
                    s_SortedGraphics.Add(graphic);
                }
            }

            s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));
            //      StringBuilder cast = new StringBuilder();
            for (int i = 0; i < s_SortedGraphics.Count; ++i)
            {
                results.Add(s_SortedGraphics[i]);
            }
            //      Debug.Log (cast.ToString());

            s_SortedGraphics.Clear();
        }
Esempio n. 6
0
        public override void Raycast(PointerEventData eventData, List <RaycastResult> resultAppendList)
        {
            if (canvas == null)
            {
                return;
            }

            var canvasGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas);

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

            //是否支持 MultiDisplay
            int displayIndex;
            var currentEventCamera = eventCamera; // Propery can call Camera.main, so cache the reference

            if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || currentEventCamera == null)
            {
                displayIndex = canvas.targetDisplay;
            }
            else
            {
                displayIndex = currentEventCamera.targetDisplay;
            }

            var eventPosition = Display.RelativeMouseAt(eventData.position);

            if (eventPosition != Vector3.zero)
            {
                // We support multiple display and display identification based on event position.

                int eventDisplayIndex = (int)eventPosition.z;

                // Discard events that are not part of this display so the user does not interact with multiple displays at once.
                if (eventDisplayIndex != displayIndex)
                {
                    return;
                }
            }
            else
            {
                // The multiple display system is not supported on all platforms, when it is not supported the returned position
                // will be all zeros so when the returned index is 0 we will default to the event data to be safe.
                eventPosition = eventData.position;
                // We dont really know in which display the event occured. We will process the event assuming it occured in our display.
            }

            // Convert to view space
            Vector2 pos;

            if (currentEventCamera == null)
            {
                // Multiple display support only when not the main display. For display 0 the reported
                // resolution is always the desktops resolution since its part of the display API,
                // so we use the standard none multiple display method. (case 741751)
                float w = Screen.width;
                float h = Screen.height;
                if (displayIndex > 0 && displayIndex < Display.displays.Length)
                {
                    w = Display.displays[displayIndex].systemWidth;
                    h = Display.displays[displayIndex].systemHeight;
                }
                pos = new Vector2(eventPosition.x / w, eventPosition.y / h);
            }
            else
            {
                pos = currentEventCamera.ScreenToViewportPoint(eventPosition);
            }

            // If it's outside the camera's viewport, do nothing
            if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f)
            {
                return;
            }

            float hitDistance = float.MaxValue;

            Ray ray = new Ray();

            if (currentEventCamera != null)
            {
                ray = currentEventCamera.ScreenPointToRay(eventPosition);
            }

            //通过两个属性来阻断射线检测部分;
            if (canvas.renderMode != RenderMode.ScreenSpaceOverlay && blockingObjects != BlockingObjects.None)
            {
                float distanceToClipPlane = 100.0f;

                if (currentEventCamera != null)
                {
                    float projectionDirection = ray.direction.z;
                    distanceToClipPlane = Mathf.Approximately(0.0f, projectionDirection)
                        ? Mathf.Infinity
                        : Mathf.Abs((currentEventCamera.farClipPlane - currentEventCamera.nearClipPlane) / projectionDirection);
                }

                if (blockingObjects == BlockingObjects.ThreeD || blockingObjects == BlockingObjects.All)
                {
                    if (ReflectionMethodsCache.Singleton.raycast3D != null)
                    {
                        var hits = ReflectionMethodsCache.Singleton.raycast3DAll(ray, distanceToClipPlane, (int)m_BlockingMask);
                        if (hits.Length > 0)
                        {
                            hitDistance = hits[0].distance;
                        }
                    }
                }

                if (blockingObjects == BlockingObjects.TwoD || blockingObjects == BlockingObjects.All)
                {
                    if (ReflectionMethodsCache.Singleton.raycast2D != null)
                    {
                        var hits = ReflectionMethodsCache.Singleton.getRayIntersectionAll(ray, distanceToClipPlane, (int)m_BlockingMask);
                        if (hits.Length > 0)
                        {
                            hitDistance = hits[0].distance;
                        }
                    }
                }
            }

            m_RaycastResults.Clear();
            Raycast(canvas, currentEventCamera, eventPosition, canvasGraphics, m_RaycastResults);

            int totalCount = m_RaycastResults.Count;

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

                //将背向 Camera 的对象过滤掉
                if (ignoreReversedGraphics)
                {
                    //判断当前 Graphic 方向与正方向 Vector3.forward 是否相交
                    if (currentEventCamera == null)
                    {
                        // If we dont have a camera we know that we should always be facing forward
                        var dir = go.transform.rotation * Vector3.forward;
                        appendGraphic = Vector3.Dot(Vector3.forward, dir) > 0;
                    }
                    else
                    {
                        // If we have a camera compare the direction against the cameras forward.
                        var cameraFoward = currentEventCamera.transform.rotation * Vector3.forward;
                        var dir          = go.transform.rotation * Vector3.forward;
                        appendGraphic = Vector3.Dot(cameraFoward, dir) > 0;
                    }
                }


                //检测 Distance
                if (appendGraphic)
                {
                    float distance = 0;

                    if (currentEventCamera == null || canvas.renderMode == RenderMode.ScreenSpaceOverlay)
                    {
                        distance = 0;
                    }
                    else
                    {
                        Transform trans        = go.transform;
                        Vector3   transForward = trans.forward;
                        // http://geomalgorithms.com/a06-_intersect-2.html
                        distance = (Vector3.Dot(transForward, trans.position - ray.origin) / Vector3.Dot(transForward, ray.direction));

                        // Check to see if the go is behind the camera.
                        if (distance < 0)
                        {
                            continue;
                        }
                    }

                    if (distance >= hitDistance)
                    {
                        continue;
                    }

                    var castResult = new RaycastResult
                    {
                        gameObject     = go,
                        module         = this,
                        distance       = distance,
                        screenPosition = eventPosition,
                        index          = resultAppendList.Count,
                        depth          = m_RaycastResults[index].depth,
                        sortingLayer   = canvas.sortingLayerID,
                        sortingOrder   = canvas.sortingOrder
                    };
                    resultAppendList.Add(castResult);
                }
            }
        }
Esempio n. 7
0
        public override void Raycast(PointerEventData eventData, List <RaycastResult> resultAppendList)
        {
            if (!(this.canvas == null))
            {
                IList <Graphic> graphicsForCanvas = GraphicRegistry.GetGraphicsForCanvas(this.canvas);
                if (graphicsForCanvas != null && graphicsForCanvas.Count != 0)
                {
                    Camera eventCamera = this.eventCamera;
                    int    targetDisplay;
                    if (this.canvas.renderMode == RenderMode.ScreenSpaceOverlay || eventCamera == null)
                    {
                        targetDisplay = this.canvas.targetDisplay;
                    }
                    else
                    {
                        targetDisplay = eventCamera.targetDisplay;
                    }
                    Vector3 vector = Display.RelativeMouseAt(eventData.position);
                    if (vector != Vector3.zero)
                    {
                        int num = (int)vector.z;
                        if (num != targetDisplay)
                        {
                            return;
                        }
                    }
                    else
                    {
                        vector = eventData.position;
                    }
                    Vector2 vector2;
                    if (eventCamera == null)
                    {
                        float num2 = (float)Screen.width;
                        float num3 = (float)Screen.height;
                        if (targetDisplay > 0 && targetDisplay < Display.displays.Length)
                        {
                            num2 = (float)Display.displays[targetDisplay].systemWidth;
                            num3 = (float)Display.displays[targetDisplay].systemHeight;
                        }
                        vector2 = new Vector2(vector.x / num2, vector.y / num3);
                    }
                    else
                    {
                        vector2 = eventCamera.ScreenToViewportPoint(vector);
                    }
                    if (vector2.x >= 0f && vector2.x <= 1f && vector2.y >= 0f && vector2.y <= 1f)
                    {
                        float num4 = 3.40282347E+38f;
                        Ray   r    = default(Ray);
                        if (eventCamera != null)
                        {
                            r = eventCamera.ScreenPointToRay(vector);
                        }
                        if (this.canvas.renderMode != RenderMode.ScreenSpaceOverlay && this.blockingObjects != GraphicRaycaster.BlockingObjects.None)
                        {
                            float f = 100f;
                            if (eventCamera != null)
                            {
                                float z = r.direction.z;
                                f = ((!Mathf.Approximately(0f, z)) ? Mathf.Abs((eventCamera.farClipPlane - eventCamera.nearClipPlane) / z) : float.PositiveInfinity);
                            }
                            if (this.blockingObjects == GraphicRaycaster.BlockingObjects.ThreeD || this.blockingObjects == GraphicRaycaster.BlockingObjects.All)
                            {
                                if (ReflectionMethodsCache.Singleton.raycast3D != null)
                                {
                                    RaycastHit[] array = ReflectionMethodsCache.Singleton.raycast3DAll(r, f, this.m_BlockingMask);
                                    if (array.Length > 0)
                                    {
                                        num4 = array[0].distance;
                                    }
                                }
                            }
                            if (this.blockingObjects == GraphicRaycaster.BlockingObjects.TwoD || this.blockingObjects == GraphicRaycaster.BlockingObjects.All)
                            {
                                if (ReflectionMethodsCache.Singleton.raycast2D != null)
                                {
                                    RaycastHit2D[] array2 = ReflectionMethodsCache.Singleton.getRayIntersectionAll(r, f, this.m_BlockingMask);
                                    if (array2.Length > 0)
                                    {
                                        num4 = array2[0].distance;
                                    }
                                }
                            }
                        }
                        this.m_RaycastResults.Clear();
                        GraphicRaycaster.Raycast(this.canvas, eventCamera, vector, graphicsForCanvas, this.m_RaycastResults);
                        int count = this.m_RaycastResults.Count;
                        int i     = 0;
                        while (i < count)
                        {
                            GameObject gameObject = this.m_RaycastResults[i].gameObject;
                            bool       flag       = true;
                            if (this.ignoreReversedGraphics)
                            {
                                if (eventCamera == null)
                                {
                                    Vector3 rhs = gameObject.transform.rotation * Vector3.forward;
                                    flag = (Vector3.Dot(Vector3.forward, rhs) > 0f);
                                }
                                else
                                {
                                    Vector3 lhs  = eventCamera.transform.rotation * Vector3.forward;
                                    Vector3 rhs2 = gameObject.transform.rotation * Vector3.forward;
                                    flag = (Vector3.Dot(lhs, rhs2) > 0f);
                                }
                            }
                            if (flag)
                            {
                                float num5;
                                if (eventCamera == null || this.canvas.renderMode == RenderMode.ScreenSpaceOverlay)
                                {
                                    num5 = 0f;
                                }
                                else
                                {
                                    Transform transform = gameObject.transform;
                                    Vector3   forward   = transform.forward;
                                    num5 = Vector3.Dot(forward, transform.position - eventCamera.transform.position) / Vector3.Dot(forward, r.direction);
                                    if (num5 < 0f)
                                    {
                                        goto IL_4EE;
                                    }
                                }
                                if (num5 < num4)
                                {
                                    RaycastResult item = new RaycastResult
                                    {
                                        gameObject     = gameObject,
                                        module         = this,
                                        distance       = num5,
                                        screenPosition = vector,
                                        index          = (float)resultAppendList.Count,
                                        depth          = this.m_RaycastResults[i].depth,
                                        sortingLayer   = this.canvas.sortingLayerID,
                                        sortingOrder   = this.canvas.sortingOrder
                                    };
                                    resultAppendList.Add(item);
                                }
                            }
IL_4EE:
                            i++;
                            continue;
                            goto IL_4EE;
                        }
                    }
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Perform the raycast against the list of graphics associated with the Canvas.
        /// GraphicRaycaster内围绕复写的基类的Raycast方法来展开(注意在GraphicRaycaster内部有另一个名为Raycast的私有静态方法,不要搞混)。
        ///
        /// 整个函数代码很多,但是做的事情很简单,对于给定的PointerEventData,射线投射得出一些投射结果RaycastResult,
        /// 追加到传入的参数List<RaycastResult>之后。
        /// </summary>
        /// <param name="eventData">Current event data</param>
        /// <param name="resultAppendList">List of hit objects to append new results to.</param>
        public override void Raycast(PointerEventData eventData, List <RaycastResult> resultAppendList)
        {
            if (canvas == null)
            {
                return;
            }

            // 获取当前 Canvas 下所有的 Graphic(canvasGraphics,这些 Graphics 在进行射线检测的时候会用到)。
            var canvasGraphics = GraphicRegistry.GetGraphicsForCanvas(canvas);

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

            int displayIndex;
            var currentEventCamera = eventCamera; // Property can call Camera.main, so cache the reference

            if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || currentEventCamera == null)
            {
                //Canvas.targetDisplay => For Overlay mode, display index on which the UI canvas will appear.
                displayIndex = canvas.targetDisplay;
            }
            else
            {
                displayIndex = currentEventCamera.targetDisplay;
            }

            // Display.RelativeMouseAt => Query relative mouse coordinates.
            // RelativeMouseAt can be used to query relative mouse input coordinates and the screen in which Mouse Input is recorded.
            // This is only valid on the Windows Desktop platforms with Multiple Displays.
            // x, y returns the coordinates in relative space and z returns the screen in which Mouse Input is handled.

            // Display.RelativeMouseAt(...)方法用于获取鼠标的相对位置,在PC平台下可能会有多个Display窗口,返回的z表示的是Display的id。
            // 如果不支持多个Display则返回值的z为0,此时获取到的就是eventData.position;
            var eventPosition = Display.RelativeMouseAt(eventData.position);

            if (eventPosition != Vector3.zero)
            {
                // We support multiple display and display identification based on event position.

                int eventDisplayIndex = (int)eventPosition.z;

                // Discard events that are not part of this display so the user does not interact with multiple displays at once.
                // 当平台支持 MultiDisplay 时,如果用户操作的不是当前的 Display,那么所有的其他 Display 上产生的事件都会被舍弃。
                if (eventDisplayIndex != displayIndex)
                {
                    return;
                }
            }
            else
            {
                // The multiple display system is not supported on all platforms, when it is not supported the returned position
                // will be all zeros so when the returned index is 0 we will default to the event data to be safe.
                eventPosition = eventData.position;

                // We dont really know in which display the event occured. We will process the event assuming it occured in our display.
            }

            // Convert to view space
            // 获取正确的pos:将上一步的屏幕坐标eventPosition转换成ViewPort坐标pos,这里同样也处理了多Display的情况。
            // 获取eventCamera不为null则直接调用相机的坐标转换方法ScreenToViewportPoint
            Vector2 pos;

            if (currentEventCamera == null)
            {
                // Multiple display support only when not the main display. For display 0 the reported
                // resolution is always the desktops resolution since its part of the display API,
                // so we use the standard none multiple display method. (case 741751)
                float w = Screen.width;
                float h = Screen.height;
                if (displayIndex > 0 && displayIndex < Display.displays.Length)
                {
                    w = Display.displays[displayIndex].systemWidth;
                    h = Display.displays[displayIndex].systemHeight;
                }
                pos = new Vector2(eventPosition.x / w, eventPosition.y / h);
            }
            else
            {
                pos = currentEventCamera.ScreenToViewportPoint(eventPosition);
            }

            // If it's outside the camera's viewport, do nothing
            if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f)
            {
                return;
            }

            // Distance from camera to target point.
            // 获取正确的hitDistance:这里分别处理blockingObjects 为不同的枚举值时的情况(默认值为None)。
            // hitDistance表示相机到投射目标点的距离。后边会根据这个距离值筛选掉一部分Graphic;
            // m_BlockingMask是LayerMask用于按层筛选投射目标;
            // 这里的ReflectionMethodsCache.Singleton.raycast3D这样的方法实际上调用的就是Physics.Raycast(...)方法
            float hitDistance = float.MaxValue;

            Ray ray = new Ray();

            if (currentEventCamera != null)
            {
                // Camera.ScreenPointToRay => Returns a ray going from camera through a screen point.
                // Resulting ray is in world space, starting on the near plane of the camera
                // and going through position's (x,y) pixel coordinates on the screen (position.z is ignored).
                // Screen space is defined in pixels. The bottom-left of the screen is (0,0); the right-top is (pixelWidth -1,pixelHeight -1).
                ray = currentEventCamera.ScreenPointToRay(eventPosition);
            }

            // Canvas renderMode 不为 RenderMode.ScreenSpaceOverlay 并且设置了 blockingObjects,
            // 此时就会 Blocked Objects 和 Blocked Mask 就会生效。
            if (canvas.renderMode != RenderMode.ScreenSpaceOverlay && blockingObjects != BlockingObjects.None)
            {
                float distanceToClipPlane = 100.0f;

                if (currentEventCamera != null)
                {
                    float projectionDirection = ray.direction.z;
                    distanceToClipPlane = Mathf.Approximately(0.0f, projectionDirection)
                        ? Mathf.Infinity
                        : Mathf.Abs((currentEventCamera.farClipPlane - currentEventCamera.nearClipPlane) / projectionDirection);
                }

                if (blockingObjects == BlockingObjects.ThreeD || blockingObjects == BlockingObjects.All)
                {
                    if (ReflectionMethodsCache.Singleton.raycast3D != null)
                    {
                        // ReflectionMethodsCache.Singleton.raycast3D这样的方法实际上调用的就是Physics.Raycast(...)
                        // raycast3DAll 时指定了射线检测层 m_BlockingMask,这个参数就是自定义设定的 Blocking Mask,
                        // 属于 block mask 的对象在这里就会就行射线检测,并得到最小的一个 hitDistance;
                        // 后面对所有的 Graphics 进行射线检测时,如果检测结果 distance 大于 hitDistance,那么那个结果会被舍弃。
                        // 如此一来,Blocking Mask 就起到了阻挡的作用,属于这个 layer 的所有对象的一旦被射线检测成功并得到 hitDistance,
                        // PhysicsRaycaster 最后的射线检测结果都只会包含这个 hitDistance 距离以内的对象。
                        var hits = ReflectionMethodsCache.Singleton.raycast3DAll(ray, distanceToClipPlane, (int)m_BlockingMask);
                        if (hits.Length > 0)
                        {
                            hitDistance = hits[0].distance;
                        }
                    }
                }

                if (blockingObjects == BlockingObjects.TwoD || blockingObjects == BlockingObjects.All)
                {
                    if (ReflectionMethodsCache.Singleton.raycast2D != null)
                    {
                        var hits = ReflectionMethodsCache.Singleton.getRayIntersectionAll(ray, distanceToClipPlane, (int)m_BlockingMask);
                        if (hits.Length > 0)
                        {
                            hitDistance = hits[0].distance;
                        }
                    }
                }
            }

            m_RaycastResults.Clear();

            Raycast(canvas, currentEventCamera, eventPosition, canvasGraphics, m_RaycastResults);

            // 判断对应的GameObject是否有效appendGraphic,即是否继续处理追加该Graphic到射线投射结果的列表
            int totalCount = m_RaycastResults.Count;

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

                // 如果ignoreReversedGraphics ,则只是追加朝向为正的Graphic
                if (ignoreReversedGraphics)
                {
                    if (currentEventCamera == null)
                    {
                        // If we dont have a camera we know that we should always be facing forward
                        var dir = go.transform.rotation * Vector3.forward;
                        appendGraphic = Vector3.Dot(Vector3.forward, dir) > 0;
                    }
                    else
                    {
                        // If we have a camera compare the direction against the cameras forward.
                        var cameraFoward = currentEventCamera.transform.rotation * Vector3.forward;
                        var dir          = go.transform.rotation * Vector3.forward;
                        appendGraphic = Vector3.Dot(cameraFoward, dir) > 0;
                    }
                }

                if (appendGraphic)
                {
                    float     distance     = 0;
                    Transform trans        = go.transform;
                    Vector3   transForward = trans.forward;

                    if (currentEventCamera == null || canvas.renderMode == RenderMode.ScreenSpaceOverlay)
                    {
                        distance = 0;
                    }
                    else
                    {
                        // http://geomalgorithms.com/a06-_intersect-2.html
                        // 计算 Graphic 和 Camera 之间的向量在 Graphic 正方向上的投影以及计算射线方向在 Graphic 正方向上的投影,
                        // 两者相除就得到最终的 distance。
                        distance = (Vector3.Dot(transForward, trans.position - ray.origin) / Vector3.Dot(transForward, ray.direction));

                        // Check to see if the go is behind the camera.
                        if (distance < 0)
                        {
                            continue;
                        }
                    }

                    if (distance >= hitDistance)
                    {
                        continue;
                    }

                    var castResult = new RaycastResult
                    {
                        gameObject     = go,
                        module         = this,
                        distance       = distance,
                        screenPosition = eventPosition,
                        index          = resultAppendList.Count,
                        depth          = m_RaycastResults[index].depth,
                        sortingLayer   = canvas.sortingLayerID,
                        sortingOrder   = canvas.sortingOrder,
                        worldPosition  = ray.origin + ray.direction * distance,
                        worldNormal    = -transForward
                    };
                    resultAppendList.Add(castResult);
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Perform a raycast into the screen and collect all graphics underneath it.
        /// </summary>
        private void Raycast(List <Canvas> canvases, Camera eventCamera, Vector2 pointerPosition, List <Graphic> results)
        {
            var workspaceTest = new Predicate <Graphic>( // Unity's original test, with modifications from voidALPHA to perform less intensive tests first
                g => !g.raycastTarget ||
                !RectTransformUtility.RectangleContainsScreenPoint(g.rectTransform, pointerPosition, eventCamera) ||
                g.depth == -1 ||
                !g.Raycast(pointerPosition, eventCamera)
                );
            var choreoTest = new Predicate <Graphic>( // Unity's original test, with modifications from voidALPHA to perform less intensive tests first
                g => !g.raycastTarget ||
                !RectTransformUtility.RectangleContainsScreenPoint(g.rectTransform, pointerPosition, null) ||
                g.depth == -1 ||
                !g.Raycast(pointerPosition, null)
                );

            foreach (var canvas in canvases)
            {
                AllWorkspaceGraphics.AddRange(GraphicRegistry.GetGraphicsForCanvas(canvas)); // Stick all graphics for canvas into list
            }
            if (ChoreoCanvas)
            {
                AllChoreoGraphics.AddRange(GraphicRegistry.GetGraphicsForCanvas(ChoreoCanvas));
            }

            if (AllWorkspaceGraphics.Count + AllChoreoGraphics.Count != LastKnownGraphicCount) // Graphics count changed
            {
                HierarchyCacheDictionary.Clear();                                              // Clear out cached dictionary and root graphic lists
                RootWorkspaceGraphics.Clear();
                RootChoreoGraphics.Clear();
                if (SatelliteUpdateLord.Instance.NodesProcessing) // We're still processing nodes; perform slower non-cached tests while nodes come up.
                                                                  // This provides raycast functionality while generating and is still faster than caching information every frame.
                {
                    if (Choreography.Views.TimelineViewBehaviour.StepPicker.gameObject.activeInHierarchy ||
                        pointerPosition.y < Choreography.Views.TimelineViewBehaviour.Instance.CurrentHeight)
                    {
                        AllChoreoGraphics.RemoveAll(choreoTest);
                        foreach (var graphic in AllChoreoGraphics)
                        {
                            SortedGraphics.Add(graphic);
                        }
                    }
                    else if (ChainView.Instance.Visible)
                    {
                        AllWorkspaceGraphics.RemoveAll(workspaceTest);
                        foreach (var graphic in AllWorkspaceGraphics)
                        {
                            SortedGraphics.Add(graphic);
                        }
                    }
                    LastKnownGraphicCount = 0;  // Zero out known Graphic count to force the Raycaster to attempt caching again on next raycast.
                }
                else
                {
                    transformTester.Refresh(AllWorkspaceGraphics, transform);
                    foreach (var g in AllWorkspaceGraphics)                               // Not processing nodes, do a lot of work up front to improve later speed of calculations
                    {
                        HierarchyCacheDictionary[g] = new List <Graphic>();               // Initialize the list of Children for this Graphic
                        g.transform.GetComponentsInChildren(HierarchyCacheDictionary[g]); // Ask Unity for the list of Graphics under this Graphic, store it in the cache
                        var p = g.transform.parent;
                        if (transformTester.TestTransform(p))                             // If no ancestor is a Graphic
                        {
                            RootWorkspaceGraphics.Add(g);                                 // This Graphic will need to be among the first to be tested
                        }
                    }

                    transformTester.Refresh(AllChoreoGraphics, ChoreoCanvas.transform);
                    foreach (var g in AllChoreoGraphics) // Do the same for the Choreography Canvas
                    {
                        HierarchyCacheDictionary[g] = new List <Graphic>();
                        g.transform.GetComponentsInChildren(HierarchyCacheDictionary[g]);
                        var p = g.transform.parent;
                        if (transformTester.TestTransform(p))
                        {
                            RootChoreoGraphics.Add(g);
                        }
                    }

                    LastKnownGraphicCount = AllWorkspaceGraphics.Count + AllChoreoGraphics.Count;
                }
            }

            // If we're working against cached graphic lists (ie nodes aren't currently being populated) prepare for the hierarchy-based test
            var test = workspaceTest;

            if (Choreography.Views.TimelineViewBehaviour.StepPicker.gameObject.activeInHierarchy || pointerPosition.y < Choreography.Views.TimelineViewBehaviour.Instance.CurrentHeight)
            { // Mouse is in the Choreography area, perform Choreography tests.
                test = choreoTest;
                foreach (var g in RootChoreoGraphics)
                {
                    GraphicsToTest.Enqueue(g);
                }
            }
            else if (ChainView.Instance.Visible)
            {
                foreach (var g in RootWorkspaceGraphics)
                {
                    GraphicsToTest.Enqueue(g);
                }
            }

            while (GraphicsToTest.Count > 0)
            {
                var g = GraphicsToTest.Dequeue();
                if (SortedGraphics.Contains(g))
                {
                    continue;
                }
                if (!test(g))
                {
                    foreach (var gr in HierarchyCacheDictionary[g])
                    {
                        if (gr == g)
                        {
                            continue;
                        }
                        GraphicsToTest.Enqueue(gr);
                    }
                    SortedGraphics.Add(g);
                }
            }

            var sgraphics = new List <Graphic>(SortedGraphics);

            sgraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));
            for (int i = 0; i < sgraphics.Count; ++i)
            {
                results.Add(sgraphics[i]);
            }

            // Ready the lists for the next run.
            AllWorkspaceGraphics.Clear();
            AllChoreoGraphics.Clear();
            SortedGraphics.Clear();
        }