diff options
Diffstat (limited to 'Runtime/Export/MouseEvents.cs')
-rw-r--r-- | Runtime/Export/MouseEvents.cs | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/Runtime/Export/MouseEvents.cs b/Runtime/Export/MouseEvents.cs new file mode 100644 index 0000000..bd87008 --- /dev/null +++ b/Runtime/Export/MouseEvents.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections; +using System.Reflection; + +namespace UnityEngine +{ + +internal class SendMouseEvents +{ + struct HitInfo + { + public GameObject target; + public Camera camera; + + public void SendMessage (string name) + { + target.SendMessage (name, null, SendMessageOptions.DontRequireReceiver); + } + + public static implicit operator bool (HitInfo exists) + { + return exists.target != null && exists.camera != null; + } + + public static bool Compare (HitInfo lhs, HitInfo rhs) + { + return lhs.target == rhs.target && lhs.camera == rhs.camera; + } + } + + static HitInfo[] m_LastHit = { new HitInfo (), new HitInfo () }; + static HitInfo[] m_MouseDownHit = { new HitInfo (), new HitInfo () }; + static RaycastHit2D[] m_MouseRayHits2D = {new RaycastHit2D()}; + + [NotRenamed] + static void DoSendMouseEvents (int mouseUsed, int skipRTCameras) + { + HitInfo[] currentHit = { new HitInfo (), new HitInfo () }; + Vector3 mousePosition = Input.mousePosition; + Camera[] cameras = Camera.allCameras; + + // If UnityGUI has the mouse over, we simply don't do any mouse hit detection. + // That way, it will appear as if the mouse has missed everything. + if (mouseUsed == 0) + { + foreach (Camera camera in cameras) + { + // we do not want to check cameras that are rendering to textures, starting with 4.0 + if (skipRTCameras != 0 && camera.targetTexture != null) + continue; + + // Is the mouse inside the cameras viewport? + Rect rect = camera.pixelRect; + if (!rect.Contains (mousePosition)) + continue; + + // Did we hit any gui elements? + GUILayer layer = (GUILayer)camera.GetComponent (typeof (GUILayer)); + if (layer) + { + GUIElement element = layer.HitTest (mousePosition); + if (element) + { + currentHit[0].target = element.gameObject; + currentHit[0].camera = camera; + } + } +#if ENABLE_PHYSICS || ENABLE_2D_PHYSICS + // There is no need to continue if the camera shouldn't be sending out events + if ((int)camera.eventMask == 0) + continue; + +#if ENABLE_PHYSICS + // Did we hit any colliders? + RaycastHit hit; + if (camera.farClipPlane > 0.0f && Physics.Raycast (camera.ScreenPointToRay (mousePosition), + out hit, camera.farClipPlane, camera.cullingMask & camera.eventMask & Physics.DefaultRaycastLayers + )) + { + if (hit.rigidbody) + { + currentHit[1].target = hit.rigidbody.gameObject; + currentHit[1].camera = camera; + } + else + { + currentHit[1].target = hit.collider.gameObject; + currentHit[1].camera = camera; + } + } +#endif +#if ENABLE_2D_PHYSICS + // Did we hit any 2D colliders? + else if (camera.farClipPlane > 0.0f) + { + // Did we hit any 2D colliders? + if (Physics2D.GetRayIntersectionNonAlloc (camera.ScreenPointToRay (mousePosition), + m_MouseRayHits2D, camera.farClipPlane, camera.cullingMask & camera.eventMask & Physics2D.DefaultRaycastLayers) == 1) + { + currentHit[1].camera = camera; + if (m_MouseRayHits2D[0].rigidbody) + currentHit[1].target = m_MouseRayHits2D[0].rigidbody.gameObject; + else + currentHit[1].target = m_MouseRayHits2D[0].collider.gameObject; + } + } +#endif + else + { + // We did not hit anything with a raycast from this camera. But our camera + // clears the screen and renders on top of whatever was below, thus making things + // rendered before invisible. So clear any previous hit we have found. + if (camera.clearFlags == CameraClearFlags.Skybox || camera.clearFlags == CameraClearFlags.Color) + { + currentHit[1].target = null; + currentHit[1].camera = null; + } + } +#endif + } + } + + // i=0: CameraGUILayer, i=1: 3D Objects + for (int i=0;i<2;i++) + SendEvents(i, currentHit[i]); + } + + /// <summary> + /// Old-style mouse events used prior to the new event system of 4.2. + /// </summary> + + static void SendEvents (int i, HitInfo hit) + { + // Handle MouseDown, MouseDrag, MouseUp + bool mouseDownThisFrame = Input.GetMouseButtonDown(0); + bool mousePressed = Input.GetMouseButton(0); + + if (mouseDownThisFrame) + { + if (hit) + { + m_MouseDownHit[i] = hit; + m_MouseDownHit[i].SendMessage("OnMouseDown"); + } + } + else if (!mousePressed) + { + if (m_MouseDownHit[i]) + { + // For button like behavior only fire this event if same as on MouseDown + if (HitInfo.Compare(hit, m_MouseDownHit[i])) + m_MouseDownHit[i].SendMessage("OnMouseUpAsButton"); + + // For backwards compatibility we keep the event name OnMouseUp + m_MouseDownHit[i].SendMessage("OnMouseUp"); + m_MouseDownHit[i] = new HitInfo(); + } + } + else if (m_MouseDownHit[i]) + { + m_MouseDownHit[i].SendMessage("OnMouseDrag"); + } + + + // Handle MouseOver, MouseEnter, MouseExit + if (HitInfo.Compare(hit, m_LastHit[i])) + { + if (hit) + hit.SendMessage("OnMouseOver"); + } + else + { + if (m_LastHit[i]) + { + m_LastHit[i].SendMessage("OnMouseExit"); + } + + if (hit) + { + hit.SendMessage("OnMouseEnter"); + hit.SendMessage("OnMouseOver"); + } + } + m_LastHit[i] = hit; + } +} +} |