/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ namespace NRKernal { using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; /// Interface for canvas raycast target. public interface ICanvasRaycastTarget { /// Gets the canvas. /// The canvas. Canvas canvas { get; } /// Gets a value indicating whether this object is enabled. /// True if enabled, false if not. bool enabled { get; } /// Gets a value indicating whether the ignore reversed graphics. /// True if ignore reversed graphics, false if not. bool ignoreReversedGraphics { get; } void GraphicRaycast(bool ignoreReversedGraphics, Ray ray, float distance, Vector3 screenCenterPoint, NRPointerRaycaster raycaster, List raycastResults); } /// /// The class enables an UGUI Canvas and its children to be interactive with NRInput raycasters. [RequireComponent(typeof(Canvas))] [DisallowMultipleComponent] public class CanvasRaycastTarget : UIBehaviour, ICanvasRaycastTarget { /// The canvas. private Canvas m_canvas; /// True to ignore reversed graphics. [SerializeField] private bool m_IgnoreReversedGraphics = true; /// Gets the canvas. /// The canvas. public virtual Canvas canvas { get { return m_canvas ?? (m_canvas = GetComponent()); } } /// Gets or sets a value indicating whether the ignore reversed graphics. /// True if ignore reversed graphics, false if not. public bool ignoreReversedGraphics { get { return m_IgnoreReversedGraphics; } set { m_IgnoreReversedGraphics = value; } } /// See MonoBehaviour.OnEnable. protected override void OnEnable() { base.OnEnable(); CanvasTargetCollector.AddTarget(this); } /// See MonoBehaviour.OnDisable. protected override void OnDisable() { base.OnDisable(); CanvasTargetCollector.RemoveTarget(this); } public virtual void GraphicRaycast(bool ignoreReversedGraphics, Ray ray, float distance, Vector3 screenCenterPoint, NRPointerRaycaster raycaster, List raycastResults) { var eventCamera = raycaster.eventCamera; var graphics = GraphicRegistry.GetGraphicsForCanvas(canvas); for (int i = 0; i < graphics.Count; ++i) { var graphic = graphics[i]; // -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, screenCenterPoint, eventCamera)) { continue; } if (ignoreReversedGraphics && Vector3.Dot(ray.direction, graphic.transform.forward) <= 0f) { continue; } if (!graphic.Raycast(screenCenterPoint, eventCamera)) { continue; } float dist; new Plane(graphic.transform.forward, graphic.transform.position).Raycast(ray, out dist); if (dist > distance) { continue; } var racastResult = new RaycastResult { gameObject = graphic.gameObject, module = raycaster, distance = dist, worldPosition = ray.GetPoint(dist), worldNormal = -graphic.transform.forward, screenPosition = screenCenterPoint, index = raycastResults.Count, depth = graphic.depth, sortingLayer = canvas.sortingLayerID, sortingOrder = canvas.sortingOrder }; raycastResults.Add(racastResult); } } } }