123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- using System.Collections.Generic;
- using System.Text;
- using UnityEngine.UI;
-
- namespace UnityEngine.EventSystems
- {
- /// <summary>
- /// A BaseInputModule for pointer input.
- /// </summary>
- public abstract class PointerInputModule : BaseInputModule
- {
- /// <summary>
- /// Id of the cached left mouse pointer event.
- /// </summary>
- public const int kMouseLeftId = -1;
-
- /// <summary>
- /// Id of the cached right mouse pointer event.
- /// </summary>
- public const int kMouseRightId = -2;
-
- /// <summary>
- /// Id of the cached middle mouse pointer event.
- /// </summary>
- public const int kMouseMiddleId = -3;
-
- /// <summary>
- /// Touch id for when simulating touches on a non touch device.
- /// </summary>
- public const int kFakeTouchesId = -4;
-
- protected Dictionary<int, PointerEventData> m_PointerData = new Dictionary<int, PointerEventData>();
-
- /// <summary>
- /// Search the cache for currently active pointers, return true if found.
- /// </summary>
- /// <param name="id">Touch ID</param>
- /// <param name="data">Found data</param>
- /// <param name="create">If not found should it be created</param>
- /// <returns>True if pointer is found.</returns>
- protected bool GetPointerData(int id, out PointerEventData data, bool create)
- {
- if (!m_PointerData.TryGetValue(id, out data) && create)
- {
- data = new PointerEventData(eventSystem)
- {
- pointerId = id,
- };
- m_PointerData.Add(id, data);
- return true;
- }
- return false;
- }
-
- /// <summary>
- /// Remove the PointerEventData from the cache.
- /// </summary>
- protected void RemovePointerData(PointerEventData data)
- {
- m_PointerData.Remove(data.pointerId);
- }
-
- /// <summary>
- /// Given a touch populate the PointerEventData and return if we are pressed or released.
- /// </summary>
- /// <param name="input">Touch being processed</param>
- /// <param name="pressed">Are we pressed this frame</param>
- /// <param name="released">Are we released this frame</param>
- /// <returns></returns>
- protected PointerEventData GetTouchPointerEventData(Touch input, out bool pressed, out bool released)
- {
- PointerEventData pointerData;
- var created = GetPointerData(input.fingerId, out pointerData, true);
-
- pointerData.Reset();
-
- pressed = created || (input.phase == TouchPhase.Began);
- released = (input.phase == TouchPhase.Canceled) || (input.phase == TouchPhase.Ended);
-
- if (created)
- pointerData.position = input.position;
-
- if (pressed)
- pointerData.delta = Vector2.zero;
- else
- pointerData.delta = input.position - pointerData.position;
-
- pointerData.position = input.position;
-
- pointerData.button = PointerEventData.InputButton.Left;
-
- if (input.phase == TouchPhase.Canceled)
- {
- pointerData.pointerCurrentRaycast = new RaycastResult();
- }
- else
- {
- eventSystem.RaycastAll(pointerData, m_RaycastResultCache);
-
- var raycast = FindFirstRaycast(m_RaycastResultCache);
- pointerData.pointerCurrentRaycast = raycast;
- m_RaycastResultCache.Clear();
- }
-
- pointerData.pressure = input.pressure;
- pointerData.altitudeAngle = input.altitudeAngle;
- pointerData.azimuthAngle = input.azimuthAngle;
- pointerData.radius = Vector2.one * input.radius;
- pointerData.radiusVariance = Vector2.one * input.radiusVariance;
-
- return pointerData;
- }
-
- /// <summary>
- /// Copy one PointerEventData to another.
- /// </summary>
- protected void CopyFromTo(PointerEventData @from, PointerEventData @to)
- {
- @to.position = @from.position;
- @to.delta = @from.delta;
- @to.scrollDelta = @from.scrollDelta;
- @to.pointerCurrentRaycast = @from.pointerCurrentRaycast;
- @to.pointerEnter = @from.pointerEnter;
-
- @to.pressure = @from.pressure;
- @to.tangentialPressure = @from.tangentialPressure;
- @to.altitudeAngle = @from.altitudeAngle;
- @to.azimuthAngle = @from.azimuthAngle;
- @to.twist = @from.twist;
- @to.radius = @from.radius;
- @to.radiusVariance = @from.radiusVariance;
- }
-
- /// <summary>
- /// Given a mouse button return the current state for the frame.
- /// </summary>
- /// <param name="buttonId">Mouse button ID</param>
- protected PointerEventData.FramePressState StateForMouseButton(int buttonId)
- {
- var pressed = input.GetMouseButtonDown(buttonId);
- var released = input.GetMouseButtonUp(buttonId);
- if (pressed && released)
- return PointerEventData.FramePressState.PressedAndReleased;
- if (pressed)
- return PointerEventData.FramePressState.Pressed;
- if (released)
- return PointerEventData.FramePressState.Released;
- return PointerEventData.FramePressState.NotChanged;
- }
-
- protected class ButtonState
- {
- private PointerEventData.InputButton m_Button = PointerEventData.InputButton.Left;
-
- public MouseButtonEventData eventData
- {
- get { return m_EventData; }
- set { m_EventData = value; }
- }
-
- public PointerEventData.InputButton button
- {
- get { return m_Button; }
- set { m_Button = value; }
- }
-
- private MouseButtonEventData m_EventData;
- }
-
- protected class MouseState
- {
- private List<ButtonState> m_TrackedButtons = new List<ButtonState>();
-
- public bool AnyPressesThisFrame()
- {
- var trackedButtonsCount = m_TrackedButtons.Count;
- for (int i = 0; i < trackedButtonsCount; i++)
- {
- if (m_TrackedButtons[i].eventData.PressedThisFrame())
- return true;
- }
- return false;
- }
-
- public bool AnyReleasesThisFrame()
- {
- var trackedButtonsCount = m_TrackedButtons.Count;
- for (int i = 0; i < trackedButtonsCount; i++)
- {
- if (m_TrackedButtons[i].eventData.ReleasedThisFrame())
- return true;
- }
- return false;
- }
-
- public ButtonState GetButtonState(PointerEventData.InputButton button)
- {
- ButtonState tracked = null;
- var trackedButtonsCount = m_TrackedButtons.Count;
- for (int i = 0; i < trackedButtonsCount; i++)
- {
- if (m_TrackedButtons[i].button == button)
- {
- tracked = m_TrackedButtons[i];
- break;
- }
- }
-
- if (tracked == null)
- {
- tracked = new ButtonState { button = button, eventData = new MouseButtonEventData() };
- m_TrackedButtons.Add(tracked);
- }
- return tracked;
- }
-
- public void SetButtonState(PointerEventData.InputButton button, PointerEventData.FramePressState stateForMouseButton, PointerEventData data)
- {
- var toModify = GetButtonState(button);
- toModify.eventData.buttonState = stateForMouseButton;
- toModify.eventData.buttonData = data;
- }
- }
-
- /// <summary>
- /// Information about a mouse button event.
- /// </summary>
- public class MouseButtonEventData
- {
- /// <summary>
- /// The state of the button this frame.
- /// </summary>
- public PointerEventData.FramePressState buttonState;
-
- /// <summary>
- /// Pointer data associated with the mouse event.
- /// </summary>
- public PointerEventData buttonData;
-
- /// <summary>
- /// Was the button pressed this frame?
- /// </summary>
- public bool PressedThisFrame()
- {
- return buttonState == PointerEventData.FramePressState.Pressed || buttonState == PointerEventData.FramePressState.PressedAndReleased;
- }
-
- /// <summary>
- /// Was the button released this frame?
- /// </summary>
- public bool ReleasedThisFrame()
- {
- return buttonState == PointerEventData.FramePressState.Released || buttonState == PointerEventData.FramePressState.PressedAndReleased;
- }
- }
-
- private readonly MouseState m_MouseState = new MouseState();
-
- /// <summary>
- /// Return the current MouseState. Using the default pointer.
- /// </summary>
- protected virtual MouseState GetMousePointerEventData()
- {
- return GetMousePointerEventData(0);
- }
-
- /// <summary>
- /// Return the current MouseState.
- /// </summary>
- protected virtual MouseState GetMousePointerEventData(int id)
- {
- // Populate the left button...
- PointerEventData leftData;
- var created = GetPointerData(kMouseLeftId, out leftData, true);
-
- leftData.Reset();
-
- if (created)
- leftData.position = input.mousePosition;
-
- Vector2 pos = input.mousePosition;
- if (Cursor.lockState == CursorLockMode.Locked)
- {
- // We don't want to do ANY cursor-based interaction when the mouse is locked
- leftData.position = new Vector2(-1.0f, -1.0f);
- leftData.delta = Vector2.zero;
- }
- else
- {
- leftData.delta = pos - leftData.position;
- leftData.position = pos;
- }
- leftData.scrollDelta = input.mouseScrollDelta;
- leftData.button = PointerEventData.InputButton.Left;
- eventSystem.RaycastAll(leftData, m_RaycastResultCache);
- var raycast = FindFirstRaycast(m_RaycastResultCache);
- leftData.pointerCurrentRaycast = raycast;
- m_RaycastResultCache.Clear();
-
- // copy the apropriate data into right and middle slots
- PointerEventData rightData;
- GetPointerData(kMouseRightId, out rightData, true);
- rightData.Reset();
-
- CopyFromTo(leftData, rightData);
- rightData.button = PointerEventData.InputButton.Right;
-
- PointerEventData middleData;
- GetPointerData(kMouseMiddleId, out middleData, true);
- middleData.Reset();
-
- CopyFromTo(leftData, middleData);
- middleData.button = PointerEventData.InputButton.Middle;
-
- m_MouseState.SetButtonState(PointerEventData.InputButton.Left, StateForMouseButton(0), leftData);
- m_MouseState.SetButtonState(PointerEventData.InputButton.Right, StateForMouseButton(1), rightData);
- m_MouseState.SetButtonState(PointerEventData.InputButton.Middle, StateForMouseButton(2), middleData);
-
- return m_MouseState;
- }
-
- /// <summary>
- /// Return the last PointerEventData for the given touch / mouse id.
- /// </summary>
- protected PointerEventData GetLastPointerEventData(int id)
- {
- PointerEventData data;
- GetPointerData(id, out data, false);
- return data;
- }
-
- private static bool ShouldStartDrag(Vector2 pressPos, Vector2 currentPos, float threshold, bool useDragThreshold)
- {
- if (!useDragThreshold)
- return true;
-
- return (pressPos - currentPos).sqrMagnitude >= threshold * threshold;
- }
-
- /// <summary>
- /// Process movement for the current frame with the given pointer event.
- /// </summary>
- protected virtual void ProcessMove(PointerEventData pointerEvent)
- {
- var targetGO = (Cursor.lockState == CursorLockMode.Locked ? null : pointerEvent.pointerCurrentRaycast.gameObject);
- HandlePointerExitAndEnter(pointerEvent, targetGO);
- }
-
- /// <summary>
- /// Process the drag for the current frame with the given pointer event.
- /// </summary>
- protected virtual void ProcessDrag(PointerEventData pointerEvent)
- {
- if (!pointerEvent.IsPointerMoving() ||
- Cursor.lockState == CursorLockMode.Locked ||
- pointerEvent.pointerDrag == null)
- return;
-
- if (!pointerEvent.dragging
- && ShouldStartDrag(pointerEvent.pressPosition, pointerEvent.position, eventSystem.pixelDragThreshold, pointerEvent.useDragThreshold))
- {
- ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.beginDragHandler);
- pointerEvent.dragging = true;
- }
-
- // Drag notification
- if (pointerEvent.dragging)
- {
- // Before doing drag we should cancel any pointer down state
- // And clear selection!
- if (pointerEvent.pointerPress != pointerEvent.pointerDrag)
- {
- ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
-
- pointerEvent.eligibleForClick = false;
- pointerEvent.pointerPress = null;
- pointerEvent.rawPointerPress = null;
- }
- ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.dragHandler);
- }
- }
-
- public override bool IsPointerOverGameObject(int pointerId)
- {
- var lastPointer = GetLastPointerEventData(pointerId);
- if (lastPointer != null)
- return lastPointer.pointerEnter != null;
- return false;
- }
-
- /// <summary>
- /// Clear all pointers and deselect any selected objects in the EventSystem.
- /// </summary>
- protected void ClearSelection()
- {
- var baseEventData = GetBaseEventData();
-
- foreach (var pointer in m_PointerData.Values)
- {
- // clear all selection
- HandlePointerExitAndEnter(pointer, null);
- }
-
- m_PointerData.Clear();
- eventSystem.SetSelectedGameObject(null, baseEventData);
- }
-
- public override string ToString()
- {
- var sb = new StringBuilder("<b>Pointer Input Module of type: </b>" + GetType());
- sb.AppendLine();
- foreach (var pointer in m_PointerData)
- {
- if (pointer.Value == null)
- continue;
- sb.AppendLine("<B>Pointer:</b> " + pointer.Key);
- sb.AppendLine(pointer.Value.ToString());
- }
- return sb.ToString();
- }
-
- /// <summary>
- /// Deselect the current selected GameObject if the currently pointed-at GameObject is different.
- /// </summary>
- /// <param name="currentOverGo">The GameObject the pointer is currently over.</param>
- /// <param name="pointerEvent">Current event data.</param>
- protected void DeselectIfSelectionChanged(GameObject currentOverGo, BaseEventData pointerEvent)
- {
- // Selection tracking
- var selectHandlerGO = ExecuteEvents.GetEventHandler<ISelectHandler>(currentOverGo);
- // if we have clicked something new, deselect the old thing
- // leave 'selection handling' up to the press event though.
- if (selectHandlerGO != eventSystem.currentSelectedGameObject)
- eventSystem.SetSelectedGameObject(null, pointerEvent);
- }
- }
- }
|