ClickMeshBrowserUI.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
  2. #define ZF_OSX
  3. #endif
  4. using System;
  5. using UnityEngine;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using UnityEngine.EventSystems;
  9. using UnityEngine.UI;
  10. namespace ZenFulcrum.EmbeddedBrowser {
  11. /**
  12. * This class will handle input to a browser based on the mouse position and a mesh collider on the browser.
  13. * Mouse positions are looked up according to the UVs on the *collider* mesh. Generally, you will want to use
  14. * the same or a visually similar (including UVs) mesh for the renderer.
  15. */
  16. [Obsolete("Use PointerUIMesh instead.")]
  17. public class ClickMeshBrowserUI : MonoBehaviour, IBrowserUI {
  18. /**
  19. * Creates a new UI handler.
  20. * We will attach to {parent}, which must have the mesh we are interacting with.
  21. * In most cases, this will also be the same object that has the Browser we will be fed to. (a la browser.UIHandler)
  22. */
  23. public static ClickMeshBrowserUI Create(MeshCollider meshCollider) {
  24. var ui = meshCollider.gameObject.AddComponent<ClickMeshBrowserUI>();
  25. ui.meshCollider = meshCollider;
  26. return ui;
  27. }
  28. public void Awake() {
  29. BrowserCursor = new BrowserCursor();
  30. BrowserCursor.cursorChange += CursorUpdated;
  31. InputSettings = new BrowserInputSettings();
  32. }
  33. protected MeshCollider meshCollider;
  34. /**
  35. * How far can we reach to touch a browser?
  36. *
  37. * HideInInspector:
  38. * Showing it in the inspector would imply that changing the value would be used, but in most practical cases
  39. * with FPSBrowserUI, the value will be overridden by the FPSCursorRenderer.
  40. */
  41. [HideInInspector]
  42. public float maxDistance = float.PositiveInfinity;
  43. /** Fills up with key events as they happen. */
  44. protected List<Event> keyEvents = new List<Event>();
  45. /** Swaps with keyEvents on InputUpdate and is returned in the main getter. */
  46. protected List<Event> keyEventsLast = new List<Event>();
  47. /** Returns the user's interacting ray, usually the mouse pointer in some form. */
  48. protected virtual Ray LookRay {
  49. get { return Camera.main.ScreenPointToRay(Input.mousePosition); }
  50. }
  51. /** List of keys Unity won't give us events for. So we have to poll. */
  52. static readonly KeyCode[] keysToCheck = {
  53. #if ZF_OSX
  54. //On windows you get GUI events for ctrl, super, alt. On mac...you don't!
  55. KeyCode.LeftCommand,
  56. KeyCode.RightCommand,
  57. KeyCode.LeftControl,
  58. KeyCode.RightControl,
  59. KeyCode.LeftAlt,
  60. KeyCode.RightAlt,
  61. //KeyCode.CapsLock, unity refuses to inform us of this, so there's not much we can do
  62. #endif
  63. //Unity consistently doesn't send events for shift across all platforms.
  64. KeyCode.LeftShift,
  65. KeyCode.RightShift,
  66. };
  67. public virtual void InputUpdate() {
  68. //Note: keyEvents gets filled in OnGUI as things happen. InputUpdate get called just before it's read.
  69. //To get the right events to the right place at the right time, swap the "double buffer" of key events.
  70. var tmp = keyEvents;
  71. keyEvents = keyEventsLast;
  72. keyEventsLast = tmp;
  73. keyEvents.Clear();
  74. //Trace mouse from the main camera
  75. var mouseRay = LookRay;
  76. RaycastHit hit;
  77. Physics.Raycast(mouseRay, out hit, maxDistance);
  78. if (hit.transform != meshCollider.transform) {
  79. //not looking at it.
  80. MousePosition = new Vector3(0, 0);
  81. MouseButtons = 0;
  82. MouseScroll = new Vector2(0, 0);
  83. MouseHasFocus = false;
  84. KeyboardHasFocus = false;
  85. LookOff();
  86. return;
  87. }
  88. LookOn();
  89. MouseHasFocus = true;
  90. KeyboardHasFocus = true;
  91. //convert ray hit to useful mouse position on page
  92. var localPoint = hit.textureCoord;
  93. MousePosition = localPoint;
  94. var buttons = (MouseButton)0;
  95. if (Input.GetMouseButton(0)) buttons |= MouseButton.Left;
  96. if (Input.GetMouseButton(1)) buttons |= MouseButton.Right;
  97. if (Input.GetMouseButton(2)) buttons |= MouseButton.Middle;
  98. MouseButtons = buttons;
  99. MouseScroll = Input.mouseScrollDelta;
  100. //Unity doesn't include events for some keys, so fake it by checking each frame.
  101. for (int i = 0; i < keysToCheck.Length; i++) {
  102. if (Input.GetKeyDown(keysToCheck[i])) {
  103. //Prepend down, postpend up. We don't know which happened first, but pressing
  104. //modifiers usually precedes other key presses and releasing tends to follow.
  105. keyEventsLast.Insert(0, new Event() {type = EventType.KeyDown, keyCode = keysToCheck[i]});
  106. } else if (Input.GetKeyUp(keysToCheck[i])) {
  107. keyEventsLast.Add(new Event() {type = EventType.KeyUp, keyCode = keysToCheck[i]});
  108. }
  109. }
  110. }
  111. public void OnGUI() {
  112. var ev = Event.current;
  113. if (ev.type != EventType.KeyDown && ev.type != EventType.KeyUp) return;
  114. // if (ev.character != 0) Debug.Log("ev >>> " + ev.character);
  115. // else if (ev.type == EventType.KeyUp) Debug.Log("ev ^^^ " + ev.keyCode);
  116. // else if (ev.type == EventType.KeyDown) Debug.Log("ev vvv " + ev.keyCode);
  117. keyEvents.Add(new Event(ev));
  118. }
  119. protected bool mouseWasOver = false;
  120. protected void LookOn() {
  121. if (BrowserCursor != null) {
  122. CursorUpdated();
  123. }
  124. mouseWasOver = true;
  125. }
  126. protected void LookOff() {
  127. if (BrowserCursor != null && mouseWasOver) {
  128. SetCursor(null);
  129. }
  130. mouseWasOver = false;
  131. }
  132. protected void CursorUpdated() {
  133. SetCursor(BrowserCursor);
  134. }
  135. /**
  136. * Sets the current mouse cursor.
  137. * If the cursor is null we are not looking at this browser.
  138. *
  139. * This base implementation changes the mouse cursor, but you could change an in-game reticle, etc.
  140. */
  141. protected virtual void SetCursor(BrowserCursor newCursor) {
  142. //note that HandleKeyInputBrowserCursor can change while we don't have focus.
  143. //In such a case, don't do anything
  144. if (!MouseHasFocus && newCursor != null) return;
  145. if (newCursor == null) {
  146. Cursor.visible = true;
  147. Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto);
  148. } else {
  149. if (newCursor.Texture != null) {
  150. Cursor.visible = true;
  151. Cursor.SetCursor(newCursor.Texture, newCursor.Hotspot, CursorMode.Auto);
  152. } else {
  153. Cursor.visible = false;
  154. Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto);
  155. }
  156. }
  157. }
  158. public bool MouseHasFocus { get; protected set; }
  159. public Vector2 MousePosition { get; protected set; }
  160. public MouseButton MouseButtons { get; protected set; }
  161. public Vector2 MouseScroll { get; protected set; }
  162. public bool KeyboardHasFocus { get; protected set; }
  163. public List<Event> KeyEvents { get { return keyEventsLast; } }
  164. public BrowserCursor BrowserCursor { get; protected set; }
  165. public BrowserInputSettings InputSettings { get; protected set; }
  166. }
  167. }