123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658 |
- using EZXR.Glass.Inputs;
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Serialization;
- using UnityEngine.UI;
- namespace UnityEngine.EventSystems
- {
- [AddComponentMenu("Event/Hand Input Module")]
- /// <summary>
- /// A BaseInputModule designed for mouse / keyboard / controller input.
- /// </summary>
- /// <remarks>
- /// Input module for working with, mouse, keyboard, or controller.
- /// </remarks>
- public class HandInputModule : PointerInputModule
- {
- Button curPointerHover;
- Button lastPointerHover;
- public static Action<Button> OnPointerHover;
- public static Action<Button> OnPointerExit;
- public static Touch[] touches = new Touch[2];
- //public static Dictionary<int, HandInfoBase> handInfoPairs = new Dictionary<int, HandInfoBase>();
- private static Vector2[] inputMousePosition = new Vector2[1];
- private Vector2 m_MousePosition;
- private GameObject m_CurrentFocusedGameObject;
- private PointerEventData m_InputPointerEvent;
- public static PointerEventData eventData_Left;
- public static PointerEventData eventData_Right;
- protected HandInputModule()
- {
- }
- protected override void Awake()
- {
- base.Awake();
- touches[0].fingerId = (int)HandType.Left;
- touches[1].fingerId = (int)HandType.Right;
- /*
- if (controllerType == ControllerType.Gestures)
- {
- handInfoPairs.Add(finger_left, InputSystem.leftHand);
- handInfoPairs.Add(finger_right, InputSystem.rightHand);
- Debug.Log("HandInputModule, Init handInfoPairs with HandInfo (use Gestures)");
- }
- else
- {
- handInfoPairs.Add(finger_left, HandleControllerManager.leftHand);
- handInfoPairs.Add(finger_right, HandleControllerManager.rightHand);
- Debug.Log("HandInputModule, Init handInfoPairs with HandleControllerInfo (use Handles)");
- }
- */
- }
- private void Update()
- {
- GetPointerData(0, out eventData_Left, false);
- GetPointerData(1, out eventData_Right, false);
- Button newPointerHover = null;
- if (eventData_Left != null && eventData_Left.pointerEnter != null)
- {
- newPointerHover = eventData_Left.pointerEnter.GetComponent<Button>();
- }
- if (eventData_Right != null && eventData_Right.pointerEnter != null)
- {
- newPointerHover = eventData_Right.pointerEnter.GetComponent<Button>();
- }
- if (newPointerHover != null && newPointerHover != curPointerHover)
- {
- if (OnPointerHover != null)
- {
- OnPointerHover(newPointerHover);
- }
- if (OnPointerExit != null)
- {
- OnPointerExit(curPointerHover);
- }
- lastPointerHover = curPointerHover;
- curPointerHover = newPointerHover;
- }
- }
- [Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
- public enum InputMode
- {
- Mouse,
- Buttons
- }
- [Obsolete("Mode is no longer needed on input module as it handles both mouse and keyboard simultaneously.", false)]
- public InputMode inputMode
- {
- get { return InputMode.Mouse; }
- }
- [SerializeField]
- [FormerlySerializedAs("m_AllowActivationOnMobileDevice")]
- private bool m_ForceModuleActive;
- [Obsolete("allowActivationOnMobileDevice has been deprecated. Use forceModuleActive instead (UnityUpgradable) -> forceModuleActive")]
- public bool allowActivationOnMobileDevice
- {
- get { return m_ForceModuleActive; }
- set { m_ForceModuleActive = value; }
- }
- /// <summary>
- /// Force this module to be active.
- /// </summary>
- /// <remarks>
- /// If there is no module active with higher priority (ordered in the inspector) this module will be forced active even if valid enabling conditions are not met.
- /// </remarks>
- public bool forceModuleActive
- {
- get { return m_ForceModuleActive; }
- set { m_ForceModuleActive = value; }
- }
- private bool m_shouldActivate;
- public bool shouldActivate
- {
- get { return m_shouldActivate; }
- set { m_shouldActivate = value; }
- }
- private bool ShouldIgnoreEventsOnNoFocus()
- {
- switch (SystemInfo.operatingSystemFamily)
- {
- case OperatingSystemFamily.Windows:
- case OperatingSystemFamily.Linux:
- case OperatingSystemFamily.MacOSX:
- #if UNITY_EDITOR
- if (UnityEditor.EditorApplication.isRemoteConnected)
- return false;
- #endif
- return true;
- default:
- return false;
- }
- }
- public override void UpdateModule()
- {
- if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
- {
- if (m_InputPointerEvent != null && m_InputPointerEvent.pointerDrag != null && m_InputPointerEvent.dragging)
- {
- ReleaseMouse(m_InputPointerEvent, m_InputPointerEvent.pointerCurrentRaycast.gameObject);
- }
- m_InputPointerEvent = null;
- return;
- }
- m_MousePosition = inputMousePosition[0];
- }
- private void ReleaseMouse(PointerEventData pointerEvent, GameObject currentOverGo)
- {
- ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
- var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
- // PointerClick and Drop events
- if (pointerEvent.pointerPress == pointerUpHandler && pointerEvent.eligibleForClick)
- {
- ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerClickHandler);
- }
- else if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
- {
- ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
- }
- pointerEvent.eligibleForClick = false;
- pointerEvent.pointerPress = null;
- pointerEvent.rawPointerPress = null;
- if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
- ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
- pointerEvent.dragging = false;
- pointerEvent.pointerDrag = null;
- // redo pointer enter / exit to refresh state
- // so that if we moused over something that ignored it before
- // due to having pressed on something else
- // it now gets it.
- if (currentOverGo != pointerEvent.pointerEnter)
- {
- HandlePointerExitAndEnter(pointerEvent, null);
- HandlePointerExitAndEnter(pointerEvent, currentOverGo);
- }
- m_InputPointerEvent = pointerEvent;
- }
- public override bool IsModuleSupported()
- {
- return true /*|| input.mousePresent || input.touchSupported*/;
- }
- public override bool ShouldActivateModule()
- {
- if (!base.ShouldActivateModule())
- return false;
- var shouldActivate = m_ForceModuleActive;
- //shouldActivate |= input.GetButtonDown(m_SubmitButton);
- //shouldActivate |= input.GetButtonDown(m_CancelButton);
- //shouldActivate |= !Mathf.Approximately(input.GetAxisRaw(m_HorizontalAxis), 0.0f);
- //shouldActivate |= !Mathf.Approximately(input.GetAxisRaw(m_VerticalAxis), 0.0f);
- //shouldActivate |= (m_MousePosition - m_LastMousePosition).sqrMagnitude > 0.0f;
- //shouldActivate |= input.GetMouseButtonDown(0);
- //if (input.touchCount > 0)
- // shouldActivate = true;
- //return shouldActivate;
- return m_shouldActivate;
- }
- /// <summary>
- /// See BaseInputModule.
- /// </summary>
- public override void ActivateModule()
- {
- if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
- return;
- base.ActivateModule();
- m_MousePosition = inputMousePosition[0];
- var toSelect = eventSystem.currentSelectedGameObject;
- if (toSelect == null)
- toSelect = eventSystem.firstSelectedGameObject;
- eventSystem.SetSelectedGameObject(toSelect, GetBaseEventData());
- }
- /// <summary>
- /// See BaseInputModule.
- /// </summary>
- public override void DeactivateModule()
- {
- base.DeactivateModule();
- ClearSelection();
- }
- public override void Process()
- {
- if (!eventSystem.isFocused && ShouldIgnoreEventsOnNoFocus())
- return;
- //>>>>>>>>>>>!!!!!!!!! //if (!ProcessTouchEvents() && input.mousePresent)
- //ProcessMouseEvent(0);
- ProcessTouchEvents();
- }
- private bool ProcessTouchEvents()
- {
- for (int i = 0; i < touches.Length; ++i)
- {
- Touch touch = touches[i];
- if (touch.type == TouchType.Indirect)
- continue;
- bool released;
- bool pressed;
- var pointer = GetHandPointerTouchEventData(touch, out pressed, out released);
- ProcessTouchPress(pointer, pressed, released, touch.fingerId == 0 ? EZXR.Glass.Inputs.InputSystem.leftHand : EZXR.Glass.Inputs.InputSystem.rightHand);
- if (!released)
- {
- ProcessMove(pointer);
- ProcessDrag(pointer);
- }
- else
- RemovePointerData(pointer);
- }
- return touches.Length > 0;
- }
- PointerEventData GetHandPointerTouchEventData(Touch input, out bool pressed, out bool released)
- {
- PointerEventData pointerData;
- var created = GetPointerData(input.fingerId, out pointerData, true);
- pointerData.Reset();
- var handInfo = input.fingerId == (int)HandType.Left ? EZXR.Glass.Inputs.InputSystem.leftHand : EZXR.Glass.Inputs.InputSystem.rightHand;
- if (handInfo != null)
- {
- pressed = handInfo.startPinch;
- released = handInfo.endPinch;
- }
- else
- {
- pressed = false;
- released = false;
- }
- //pressed = (input.fingerId == (int)HandType.Left ? ControllerManager.leftHand : ControllerManager.rightHand).startPinch;
- //released = (input.fingerId == (int)HandType.Left ? ControllerManager.leftHand : ControllerManager.rightHand).endPinch;
- 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;
- //if (raycast.gameObject != null)
- // Debug.Log($"HandControllerSession, Raycast = {raycast.gameObject.name}, screenPosition = ({pointerData.position.x}, {pointerData.position.y})");
- m_RaycastResultCache.Clear();
- }
- return pointerData;
- }
- /// <summary>
- /// This method is called by Unity whenever a touch event is processed. Override this method with a custom implementation to process touch events yourself.
- /// </summary>
- /// <param name="pointerEvent">Event data relating to the touch event, such as position and ID to be passed to the touch event destination object.</param>
- /// <param name="pressed">This is true for the first frame of a touch event, and false thereafter. This can therefore be used to determine the instant a touch event occurred.</param>
- /// <param name="released">This is true only for the last frame of a touch event.</param>
- /// <remarks>
- /// This method can be overridden in derived classes to change how touch press events are handled.
- /// </remarks>
- protected void ProcessTouchPress(PointerEventData pointerEvent, bool pressed, bool released, InputInfoBase inputInfo)
- {
- var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
- // PointerDown notification
- if (pressed)
- {
- pointerEvent.eligibleForClick = true;
- pointerEvent.delta = Vector2.zero;
- pointerEvent.dragging = false;
- pointerEvent.useDragThreshold = true;
- pointerEvent.pressPosition = pointerEvent.position;
- pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
- DeselectIfSelectionChanged(currentOverGo, pointerEvent);
- if (pointerEvent.pointerEnter != currentOverGo)
- {
- // send a pointer enter to the touched element if it isn't the one to select...
- HandlePointerExitAndEnter(pointerEvent, currentOverGo);
- pointerEvent.pointerEnter = currentOverGo;
- }
- // search for the control that will receive the press
- // if we can't find a press handler set the press
- // handler to be what would receive a click.
- var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
- // didnt find a press handler... search for a click handler
- if (newPressed == null)
- newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
- // Debug.Log("Pressed: " + newPressed);
- float time = Time.unscaledTime;
- if (newPressed == pointerEvent.lastPress)
- {
- var diffTime = time - pointerEvent.clickTime;
- if (diffTime < 0.3f)
- ++pointerEvent.clickCount;
- else
- pointerEvent.clickCount = 1;
- pointerEvent.clickTime = time;
- }
- else
- {
- pointerEvent.clickCount = 1;
- }
- pointerEvent.pointerPress = newPressed;
- pointerEvent.rawPointerPress = currentOverGo;
- pointerEvent.clickTime = time;
- // Save the drag handler as well
- pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
- if (pointerEvent.pointerDrag != null)
- ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
- m_InputPointerEvent = pointerEvent;
- }
- // PointerUp notification
- if (released)
- {
- #if SYSTEMUI
- #region 在松开手指的时候向当前指向的物体发送press事件
- if (inputInfo.isPalmFacingHead())
- {
- // search for the control that will receive the press
- // if we can't find a press handler set the press
- // handler to be what would receive a click.
- var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
- // didnt find a press handler... search for a click handler
- if (newPressed == null)
- newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
- pointerEvent.pointerPress = newPressed;
- pointerEvent.rawPointerPress = currentOverGo;
- }
- #endregion
- #endif
- // Debug.Log("Executing pressup on: " + pointer.pointerPress);
- ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
- // Debug.Log("KeyCode: " + pointer.eventData.keyCode);
- // see if we mouse up on the same element that we clicked on...
- var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
- #if SYSTEMUI
- pointerEvent.pointerPress = pointerUpHandler;
- #endif
- // PointerClick and Drop events
- if (/*pointerEvent.pointerPress == pointerUpHandler &&*/ pointerEvent.eligibleForClick)
- {
- ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerClickHandler);
- }
- if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
- {
- ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
- }
- pointerEvent.eligibleForClick = false;
- pointerEvent.pointerPress = null;
- pointerEvent.rawPointerPress = null;
- if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
- ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
- pointerEvent.dragging = false;
- pointerEvent.pointerDrag = null;
- // send exit events as we need to simulate this on touch up on touch device
- ExecuteEvents.ExecuteHierarchy(pointerEvent.pointerEnter, pointerEvent, ExecuteEvents.pointerExitHandler);
- pointerEvent.pointerEnter = null;
- m_InputPointerEvent = pointerEvent;
- }
- }
- /// <summary>
- /// Process all mouse events.
- /// </summary>
- protected void ProcessMouseEvent(int id)
- {
- var mouseData = GetHandMousePointerEventData(id);
- var leftButtonData = mouseData.GetButtonState(PointerEventData.InputButton.Left).eventData;
- m_CurrentFocusedGameObject = leftButtonData.buttonData.pointerCurrentRaycast.gameObject;
- // Process the first mouse button fully
- ProcessMousePress(leftButtonData);
- ProcessMove(leftButtonData.buttonData);
- ProcessDrag(leftButtonData.buttonData);
- //// Now process right / middle clicks
- //ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData);
- //ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData.buttonData);
- //ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData);
- //ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData.buttonData);
- }
- protected override void ProcessMove(PointerEventData pointerEvent)
- {
- var targetGO = pointerEvent.pointerCurrentRaycast.gameObject;
- HandlePointerExitAndEnter(pointerEvent, targetGO);
- }
- /// <summary>
- /// Return the current MouseState.
- /// </summary>
- protected virtual MouseState GetHandMousePointerEventData(int id)
- {
- // Populate the left button...
- PointerEventData leftData;
- var created = GetPointerData(kMouseLeftId, out leftData, true);
- leftData.Reset();
- if (created)
- leftData.position = inputMousePosition[0];
- Vector2 pos = inputMousePosition[0];
- leftData.delta = pos - leftData.position;
- //Debug.Log(pos.ToString("#.####") + "�� " + leftData.position.ToString("#.####") + ", " + leftData.delta.y);
- leftData.position = pos;
- leftData.scrollDelta = Vector2.zero;// 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);
- //CopyFromTo(leftData, rightData);
- //rightData.button = PointerEventData.InputButton.Right;
- //PointerEventData middleData;
- //GetPointerData(kMouseMiddleId, out middleData, true);
- //CopyFromTo(leftData, middleData);
- //middleData.button = PointerEventData.InputButton.Middle;
- MouseState m_MouseState = new MouseState();
- m_MouseState.SetButtonState(PointerEventData.InputButton.Left, StateForHandMouseButton(0), leftData);
- //m_MouseState.SetButtonState(PointerEventData.InputButton.Right, StateForMouseButton(1), rightData);
- //m_MouseState.SetButtonState(PointerEventData.InputButton.Middle, StateForMouseButton(2), middleData);
- return m_MouseState;
- }
- /// <summary>
- /// Given a mouse button return the current state for the frame.
- /// </summary>
- /// <param name="buttonId">Mouse button ID</param>
- protected PointerEventData.FramePressState StateForHandMouseButton(int buttonId)
- {
- //#if UNITY_EDITOR
- // var pressed = input.GetMouseButtonDown(buttonId);
- // var released = input.GetMouseButtonUp(buttonId);
- //#else
- bool pressed = /*EZXR.Glass.Inputs.InputSystem.leftHand.startPinch || */EZXR.Glass.Inputs.InputSystem.leftHand.startPinch;
- bool released = /*EZXR.Glass.Inputs.InputSystem.leftHand.endPinch || */EZXR.Glass.Inputs.InputSystem.leftHand.endPinch;
- //#endif
- if (pressed && released)
- return PointerEventData.FramePressState.PressedAndReleased;
- if (pressed)
- return PointerEventData.FramePressState.Pressed;
- if (released)
- return PointerEventData.FramePressState.Released;
- return PointerEventData.FramePressState.NotChanged;
- }
- /// <summary>
- /// Calculate and process any mouse button state changes.
- /// </summary>
- protected void ProcessMousePress(MouseButtonEventData data)
- {
- var pointerEvent = data.buttonData;
- var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
- // PointerDown notification
- if (data.PressedThisFrame())
- {
- //Debug.Log("data.PressedThisFrame");
- pointerEvent.eligibleForClick = true;
- pointerEvent.delta = Vector2.zero;
- pointerEvent.dragging = false;
- pointerEvent.useDragThreshold = true;
- pointerEvent.pressPosition = pointerEvent.position;
- pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
- DeselectIfSelectionChanged(currentOverGo, pointerEvent);
- // search for the control that will receive the press
- // if we can't find a press handler set the press
- // handler to be what would receive a click.
- var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
- // didnt find a press handler... search for a click handler
- if (newPressed == null)
- newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
- // Debug.Log("Pressed: " + newPressed);
- float time = Time.unscaledTime;
- if (newPressed == pointerEvent.lastPress)
- {
- var diffTime = time - pointerEvent.clickTime;
- if (diffTime < 0.3f)
- ++pointerEvent.clickCount;
- else
- pointerEvent.clickCount = 1;
- pointerEvent.clickTime = time;
- }
- else
- {
- pointerEvent.clickCount = 1;
- }
- pointerEvent.pointerPress = newPressed;
- pointerEvent.rawPointerPress = currentOverGo;
- pointerEvent.clickTime = time;
- // Save the drag handler as well
- pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
- if (pointerEvent.pointerDrag != null)
- ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
- m_InputPointerEvent = pointerEvent;
- }
- // PointerUp notification
- if (data.ReleasedThisFrame())
- {
- ReleaseMouse(pointerEvent, currentOverGo);
- }
- }
- protected GameObject GetCurrentFocusedGameObject()
- {
- return m_CurrentFocusedGameObject;
- }
- }
- }
|