123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- /****************************************************************************
- * Copyright 2019 Nreal Techonology Limited. All rights reserved.
- *
- * This file is part of NRSDK.
- *
- * https://www.nreal.ai/
- *
- *****************************************************************************/
- namespace NRKernal
- {
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.EventSystems;
-
- /// <summary> A nr input module. </summary>
- public class NRInputModule : BaseInputModule
- {
- /// <summary> The processed frame. </summary>
- private int m_processedFrame;
- /// <summary> The raycasters. </summary>
- private static readonly List<NRPointerRaycaster> raycasters = new List<NRPointerRaycaster>();
- /// <summary> Gets a value indicating whether the active. </summary>
- /// <value> True if active, false if not. </value>
- public static bool Active { get { return m_Instance != null; } }
- /// <summary> Gets the screen center point. </summary>
- /// <value> The screen center point. </value>
- public static Vector2 ScreenCenterPoint { get { return new Vector2(Screen.width * 0.5f, Screen.height * 0.5f); } }
- /// <summary> True if is application quitting, false if not. </summary>
- private static bool isApplicationQuitting = false;
- /// <summary> The instance. </summary>
- private static NRInputModule m_Instance;
- /// <summary> Gets the instance. </summary>
- /// <value> The instance. </value>
- public static NRInputModule Instance
- {
- get
- {
- Initialize();
- return m_Instance;
- }
- }
- /// <summary> <para>Update the internal state of the Module.</para> </summary>
- public override void UpdateModule()
- {
- Initialize();
- if (isActiveAndEnabled && EventSystem.current.currentInputModule != this)
- {
- ProcessRaycast();
- }
- }
- /// <summary> Process the raycast. </summary>
- protected virtual void ProcessRaycast()
- {
- if (m_processedFrame == Time.frameCount)
- return;
- m_processedFrame = Time.frameCount;
- RaycastAll();
- }
- /// <summary> Raycast all. </summary>
- private void RaycastAll()
- {
- for (int i = 0; i < raycasters.Count; i++)
- {
- var raycaster = raycasters[i];
- if (raycaster == null)
- continue;
- raycaster.Raycast();
- var result = raycaster.FirstRaycastResult();
- var scrollDelta = raycaster.GetScrollDelta();
- var raycasterPos = raycaster.BreakPoints[0];
- var raycasterRot = raycaster.transform.rotation;
- var hoverEventData = raycaster.HoverEventData;
- if (hoverEventData == null)
- continue;
- hoverEventData.Reset();
- hoverEventData.delta = Vector2.zero;
- hoverEventData.scrollDelta = scrollDelta;
- hoverEventData.position = ScreenCenterPoint;
- hoverEventData.pointerCurrentRaycast = result;
- hoverEventData.position3DDelta = raycasterPos - hoverEventData.position3D;
- hoverEventData.position3D = raycasterPos;
- hoverEventData.rotationDelta = Quaternion.Inverse(hoverEventData.rotation) * raycasterRot;
- hoverEventData.rotation = raycasterRot;
- for (int j = 0, jmax = raycaster.ButtonEventDataList.Count; j < jmax; ++j)
- {
- var buttonEventData = raycaster.ButtonEventDataList[j];
- if (buttonEventData == null || buttonEventData == hoverEventData)
- continue;
- buttonEventData.Reset();
- buttonEventData.delta = Vector2.zero;
- buttonEventData.scrollDelta = scrollDelta;
- buttonEventData.position = ScreenCenterPoint;
- buttonEventData.pointerCurrentRaycast = result;
- buttonEventData.position3DDelta = hoverEventData.position3DDelta;
- buttonEventData.position3D = hoverEventData.position3D;
- buttonEventData.rotationDelta = hoverEventData.rotationDelta;
- buttonEventData.rotation = hoverEventData.rotation;
- }
- ProcessPress(hoverEventData);
- ProcessMove(hoverEventData);
- ProcessDrag(hoverEventData);
- for (int j = 1, jmax = raycaster.ButtonEventDataList.Count; j < jmax; ++j)
- {
- var buttonEventData = raycaster.ButtonEventDataList[j];
- if (buttonEventData == null || buttonEventData == hoverEventData)
- continue;
- buttonEventData.pointerEnter = hoverEventData.pointerEnter;
- ProcessPress(buttonEventData);
- ProcessDrag(buttonEventData);
- }
- }
- }
- /// <summary> Initializes this object. </summary>
- public static void Initialize()
- {
- if (Active || isApplicationQuitting)
- return;
- var instances = FindObjectsOfType<NRInputModule>();
- if (instances.Length > 0)
- {
- m_Instance = instances[0];
- if (instances.Length > 1)
- {
- NRDebugger.Warning("Multiple NRInputModule not supported!");
- }
- }
- if (!Active)
- {
- EventSystem eventSystem = EventSystem.current;
- if (eventSystem == null)
- {
- eventSystem = FindObjectOfType<EventSystem>();
- }
- if (eventSystem == null)
- {
- eventSystem = new GameObject("[EventSystem]").AddComponent<EventSystem>();
- }
- if (eventSystem == null)
- {
- NRDebugger.Warning("EventSystem not found or create fail!");
- return;
- }
- m_Instance = eventSystem.gameObject.AddComponent<NRInputModule>();
- DontDestroyOnLoad(eventSystem.gameObject);
- }
- }
- /// <summary> <para>Process the current tick for the module.</para> </summary>
- public override void Process()
- {
- Initialize();
- if (isActiveAndEnabled)
- {
- ProcessRaycast();
- }
- }
- /// <summary> Executes the 'application quit' action. </summary>
- private void OnApplicationQuit()
- {
- isApplicationQuitting = true;
- }
- /// <summary> Adds a raycaster. </summary>
- /// <param name="raycaster"> The raycaster.</param>
- public static void AddRaycaster(NRPointerRaycaster raycaster)
- {
- if (raycaster == null)
- return;
- Initialize();
- raycasters.Add(raycaster);
- }
- /// <summary> Removes the raycaster described by raycaster. </summary>
- /// <param name="raycaster"> The raycaster.</param>
- public static void RemoveRaycaster(NRPointerRaycaster raycaster)
- {
- if (m_Instance)
- {
- m_Instance.ProcessRaycast();
- }
- raycasters.Remove(raycaster);
- }
- /// <summary> The default raycast comparer. </summary>
- public static readonly Comparison<RaycastResult> defaultRaycastComparer = RaycastComparer;
- /// <summary> Raycast comparer. </summary>
- /// <param name="lhs"> The left hand side.</param>
- /// <param name="rhs"> The right hand side.</param>
- /// <returns> An int. </returns>
- private static int RaycastComparer(RaycastResult lhs, RaycastResult rhs)
- {
- if (lhs.module != rhs.module)
- {
- if (lhs.module.eventCamera != null && rhs.module.eventCamera != null && lhs.module.eventCamera.depth != rhs.module.eventCamera.depth)
- {
- if (lhs.module.eventCamera.depth < rhs.module.eventCamera.depth) { return 1; }
- if (lhs.module.eventCamera.depth == rhs.module.eventCamera.depth) { return 0; }
- return -1;
- }
- if (lhs.module.sortOrderPriority != rhs.module.sortOrderPriority)
- {
- return rhs.module.sortOrderPriority.CompareTo(lhs.module.sortOrderPriority);
- }
- if (lhs.module.renderOrderPriority != rhs.module.renderOrderPriority)
- {
- return rhs.module.renderOrderPriority.CompareTo(lhs.module.renderOrderPriority);
- }
- }
- if (lhs.sortingLayer != rhs.sortingLayer)
- {
- var rid = SortingLayer.GetLayerValueFromID(rhs.sortingLayer);
- var lid = SortingLayer.GetLayerValueFromID(lhs.sortingLayer);
- return rid.CompareTo(lid);
- }
- if (lhs.sortingOrder != rhs.sortingOrder)
- {
- return rhs.sortingOrder.CompareTo(lhs.sortingOrder);
- }
- if (!Mathf.Approximately(lhs.distance, rhs.distance))
- {
- return lhs.distance.CompareTo(rhs.distance);
- }
- if (lhs.depth != rhs.depth)
- {
- return rhs.depth.CompareTo(lhs.depth);
- }
- return lhs.index.CompareTo(rhs.index);
- }
- /// <summary> Process the move described by eventData. </summary>
- /// <param name="eventData"> Information describing the event.</param>
- protected virtual void ProcessMove(PointerEventData eventData)
- {
- var hoverGO = eventData.pointerCurrentRaycast.gameObject;
- if (eventData.pointerEnter != hoverGO)
- {
- HandlePointerExitAndEnter(eventData, hoverGO);
- }
- }
- /// <summary> Process the press described by eventData. </summary>
- /// <param name="eventData"> Information describing the event.</param>
- protected virtual void ProcessPress(NRPointerEventData eventData)
- {
- if (eventData.GetPress())
- {
- if (!eventData.pressPrecessed)
- {
- ProcessPressDown(eventData);
- }
- HandlePressExitAndEnter(eventData, eventData.pointerCurrentRaycast.gameObject);
- }
- else if (eventData.pressPrecessed)
- {
- ProcessPressUp(eventData);
- HandlePressExitAndEnter(eventData, null);
- }
- }
- /// <summary> Process the press down described by eventData. </summary>
- /// <param name="eventData"> Information describing the event.</param>
- protected void ProcessPressDown(NRPointerEventData eventData)
- {
- var currentOverGo = eventData.pointerCurrentRaycast.gameObject;
- eventData.pressPrecessed = true;
- eventData.eligibleForClick = true;
- eventData.delta = Vector2.zero;
- eventData.dragging = false;
- eventData.useDragThreshold = true;
- eventData.pressPosition = eventData.position;
- eventData.pressPosition3D = eventData.position3D;
- eventData.pressRotation = eventData.rotation;
- eventData.pressDistance = eventData.pointerCurrentRaycast.distance;
- eventData.pointerPressRaycast = eventData.pointerCurrentRaycast;
- DeselectIfSelectionChanged(currentOverGo, eventData);
- var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, eventData, ExecuteEvents.pointerDownHandler);
- if (newPressed == null)
- {
- newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
- }
- var time = Time.unscaledTime;
- if (newPressed == eventData.lastPress)
- {
- if (eventData.raycaster != null && time < (eventData.clickTime + NRInput.ClickInterval))
- {
- ++eventData.clickCount;
- }
- else
- {
- eventData.clickCount = 1;
- }
- eventData.clickTime = time;
- }
- else
- {
- eventData.clickCount = 1;
- }
- eventData.pointerPress = newPressed;
- eventData.rawPointerPress = currentOverGo;
- eventData.clickTime = time;
- eventData.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
- if (eventData.pointerDrag != null)
- {
- ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.initializePotentialDrag);
- }
- }
- /// <summary> Process the press up described by eventData. </summary>
- /// <param name="eventData"> Information describing the event.</param>
- protected void ProcessPressUp(NRPointerEventData eventData)
- {
- var currentOverGo = eventData.pointerCurrentRaycast.gameObject;
- ExecuteEvents.Execute(eventData.pointerPress, eventData, ExecuteEvents.pointerUpHandler);
- var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
- if (eventData.pointerPress == pointerUpHandler && eventData.eligibleForClick)
- {
- ExecuteEvents.Execute(eventData.pointerPress, eventData, ExecuteEvents.pointerClickHandler);
- }
- else if (eventData.pointerDrag != null && eventData.dragging)
- {
- ExecuteEvents.ExecuteHierarchy(currentOverGo, eventData, ExecuteEvents.dropHandler);
- }
- eventData.pressPrecessed = false;
- eventData.eligibleForClick = false;
- eventData.pointerPress = null;
- eventData.rawPointerPress = null;
- if (eventData.pointerDrag != null && eventData.dragging)
- {
- ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.endDragHandler);
- }
- eventData.dragging = false;
- eventData.pointerDrag = null;
- if (currentOverGo != eventData.pointerEnter)
- {
- HandlePointerExitAndEnter(eventData, null);
- HandlePointerExitAndEnter(eventData, currentOverGo);
- }
- }
- /// <summary> Determine if we should start drag. </summary>
- /// <param name="eventData"> Information describing the event.</param>
- /// <returns> True if it succeeds, false if it fails. </returns>
- protected bool ShouldStartDrag(NRPointerEventData eventData)
- {
- if (!eventData.useDragThreshold || eventData.raycaster == null)
- {
- return true;
- }
- var currentPos = eventData.position3D + (eventData.rotation * Vector3.forward) * eventData.pressDistance;
- var pressPos = eventData.pressPosition3D + (eventData.pressRotation * Vector3.forward) * eventData.pressDistance;
- var threshold = NRInput.DragThreshold;
- return (currentPos - pressPos).sqrMagnitude >= threshold * threshold;
- }
- /// <summary> Process the drag described by eventData. </summary>
- /// <param name="eventData"> Information describing the event.</param>
- protected void ProcessDrag(NRPointerEventData eventData)
- {
- var moving = !Mathf.Approximately(eventData.position3DDelta.sqrMagnitude, 0f) || !Mathf.Approximately(Quaternion.Angle(Quaternion.identity, eventData.rotationDelta), 0f);
- if (moving && eventData.pointerDrag != null && !eventData.dragging && ShouldStartDrag(eventData))
- {
- ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.beginDragHandler);
- eventData.dragging = true;
- }
- if (eventData.dragging && moving && eventData.pointerDrag != null)
- {
- if (eventData.pointerPress != eventData.pointerDrag)
- {
- ExecuteEvents.Execute(eventData.pointerPress, eventData, ExecuteEvents.pointerUpHandler);
- eventData.eligibleForClick = false;
- eventData.pointerPress = null;
- eventData.rawPointerPress = null;
- }
- ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.dragHandler);
- }
- }
- /// <summary> Handles the press exit and enter. </summary>
- /// <param name="eventData"> Information describing the event.</param>
- /// <param name="newEnterTarget"> The new enter target.</param>
- protected static void HandlePressExitAndEnter(NRPointerEventData eventData, GameObject newEnterTarget)
- {
- if (eventData.pressEnter == newEnterTarget)
- return;
- var oldTarget = eventData.pressEnter == null ? null : eventData.pressEnter.transform;
- var newTarget = newEnterTarget == null ? null : newEnterTarget.transform;
- var commonRoot = default(Transform);
- for (var t = oldTarget; t != null; t = t.parent)
- {
- if (newTarget != null && newTarget.IsChildOf(t))
- {
- commonRoot = t;
- break;
- }
- else
- {
- ExecuteEvents.Execute(t.gameObject, eventData, NRExecutePointerEvents.PressExitHandler);
- }
- }
- eventData.pressEnter = newEnterTarget;
- for (var t = newTarget; t != commonRoot; t = t.parent)
- {
- ExecuteEvents.Execute(t.gameObject, eventData, NRExecutePointerEvents.PressEnterHandler);
- }
- }
- /// <summary> Deselect if selection changed. </summary>
- /// <param name="currentOverGo"> The current over go.</param>
- /// <param name="pointerEvent"> The pointer event.</param>
- protected void DeselectIfSelectionChanged(GameObject currentOverGo, BaseEventData pointerEvent)
- {
- var selectHandlerGO = ExecuteEvents.GetEventHandler<ISelectHandler>(currentOverGo);
- if (eventSystem != null && selectHandlerGO != eventSystem.currentSelectedGameObject)
- {
- eventSystem.SetSelectedGameObject(null, pointerEvent);
- }
- }
- }
-
- }
|