Last active
August 29, 2015 14:18
-
-
Save fum1h1ro/583df14ab71dd972fc57 to your computer and use it in GitHub Desktop.
GraphicRaycaster2: Addapt for RenderTexture
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
using UnityEngine.EventSystems; | |
namespace UnityEngine.UI | |
{ | |
[AddComponentMenu("Event/Graphic Raycaster 2")] | |
[RequireComponent(typeof(Canvas))] | |
public class GraphicRaycaster2 : BaseRaycaster | |
{ | |
protected const int kNoEventMaskSet = -1; | |
public enum BlockingObjects | |
{ | |
None = 0, | |
TwoD = 1, | |
ThreeD = 2, | |
All = 3, | |
} | |
public override int sortOrderPriority | |
{ | |
get | |
{ | |
// We need to return the sorting order here as distance will all be 0 for overlay. | |
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) | |
return canvas.sortingOrder; | |
return base.sortOrderPriority; | |
} | |
} | |
public override int renderOrderPriority | |
{ | |
get | |
{ | |
// We need to return the sorting order here as distance will all be 0 for overlay. | |
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) | |
return canvas.renderOrder; | |
return base.renderOrderPriority; | |
} | |
} | |
[SerializeField] | |
private bool m_IgnoreReversedGraphics = true; | |
[SerializeField] | |
private BlockingObjects m_BlockingObjects = BlockingObjects.None; | |
public bool ignoreReversedGraphics { get {return m_IgnoreReversedGraphics; } set{ m_IgnoreReversedGraphics = value; } } | |
public BlockingObjects blockingObjects { get {return m_BlockingObjects; } set{ m_BlockingObjects = value; } } | |
[SerializeField] | |
protected LayerMask m_BlockingMask = kNoEventMaskSet; | |
private Canvas m_Canvas; | |
protected GraphicRaycaster2() | |
{ } | |
private Canvas canvas | |
{ | |
get | |
{ | |
if (m_Canvas != null) | |
return m_Canvas; | |
m_Canvas = GetComponent<Canvas>(); | |
return m_Canvas; | |
} | |
} | |
[NonSerialized] private List<Graphic> m_RaycastResults = new List<Graphic>(); | |
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList) | |
{ | |
if (canvas == null) | |
return; | |
// Convert to view space | |
Vector2 pos; | |
if (eventCamera == null) | |
pos = new Vector2(eventData.position.x / Screen.width, eventData.position.y / Screen.height); | |
else | |
pos = eventCamera.ScreenToViewportPoint(eventData.position / canvas.scaleFactor); | |
//@Debug.Log(pos); | |
// 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 (eventCamera != null) | |
ray = eventCamera.ScreenPointToRay(eventData.position / canvas.scaleFactor); | |
if (canvas.renderMode != RenderMode.ScreenSpaceOverlay && blockingObjects != BlockingObjects.None) | |
{ | |
float dist = eventCamera.farClipPlane - eventCamera.nearClipPlane; | |
if (blockingObjects == BlockingObjects.ThreeD || blockingObjects == BlockingObjects.All) | |
{ | |
RaycastHit hit; | |
if (Physics.Raycast(ray, out hit, dist, m_BlockingMask)) | |
{ | |
hitDistance = hit.distance; | |
} | |
} | |
if (blockingObjects == BlockingObjects.TwoD || blockingObjects == BlockingObjects.All) | |
{ | |
RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction, dist, m_BlockingMask); | |
if (hit.collider != null) | |
{ | |
hitDistance = hit.fraction * dist; | |
} | |
} | |
} | |
m_RaycastResults.Clear(); | |
if (eventCamera != null) | |
Raycast(canvas, eventCamera, eventData.position / canvas.scaleFactor, m_RaycastResults); | |
else | |
Raycast(canvas, eventCamera, eventData.position, m_RaycastResults); | |
for (var index = 0; index < m_RaycastResults.Count; index++) | |
{ | |
var go = m_RaycastResults[index].gameObject; | |
bool appendGraphic = true; | |
if (ignoreReversedGraphics) | |
{ | |
if (eventCamera == 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 = eventCamera.transform.rotation * Vector3.forward; | |
var dir = go.transform.rotation * Vector3.forward; | |
appendGraphic = Vector3.Dot(cameraFoward, dir) > 0; | |
} | |
} | |
if (appendGraphic) | |
{ | |
float distance = 0; | |
if (eventCamera == null || canvas.renderMode == RenderMode.ScreenSpaceOverlay) | |
distance = 0; | |
else | |
{ | |
// http://geomalgorithms.com/a06-_intersect-2.html | |
distance = (Vector3.Dot(go.transform.forward, go.transform.position - ray.origin) / Vector3.Dot(go.transform.forward, 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, | |
index = resultAppendList.Count, | |
depth = m_RaycastResults[index].depth, | |
sortingLayer = canvas.sortingLayerID, | |
sortingOrder = canvas.sortingOrder | |
}; | |
resultAppendList.Add(castResult); | |
} | |
} | |
} | |
public override Camera eventCamera | |
{ | |
get | |
{ | |
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay | |
|| (canvas.renderMode == RenderMode.ScreenSpaceCamera && canvas.worldCamera == null)) | |
return null; | |
return canvas.worldCamera != null ? canvas.worldCamera : Camera.main; | |
} | |
} | |
/// <summary> | |
/// Perform a raycast into the screen and collect all graphics underneath it. | |
/// </summary> | |
[NonSerialized] static readonly List<Graphic> s_SortedGraphics = new List<Graphic>(); | |
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); | |
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.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()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment