2021년 4학년 1학기 기업연계프로젝트2 컴퓨터소프트웨어공학과 <원광투어팀> 팀장 : 송유진 팀원 : 김나영, 이경희, 한유진
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

645 lines
24 KiB

5 years ago
  1. //========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
  2. using HTC.UnityPlugin.Utility;
  3. using System;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEngine.EventSystems;
  7. namespace HTC.UnityPlugin.Pointer3D
  8. {
  9. public class Pointer3DInputModule : BaseInputModule
  10. {
  11. private static Pointer3DInputModule instance;
  12. private static bool isApplicationQuitting = false;
  13. private static readonly IndexedSet<Pointer3DRaycaster> raycasters = new IndexedSet<Pointer3DRaycaster>();
  14. private static IndexedSet<Pointer3DRaycaster> processingRaycasters = new IndexedSet<Pointer3DRaycaster>();
  15. private static int validEventDataId = PointerInputModule.kFakeTouchesId - 1;
  16. #if UNITY_5_5_OR_NEWER
  17. private bool m_hasFocus;
  18. #endif
  19. private int m_processedFrame;
  20. // Pointer3DInputModule has it's own RaycasterManager and Pointer3DRaycaster doesn't share with other input modules.
  21. // So coexist with other input modules is by default and reasonable?
  22. public bool coexist = true;
  23. [NonSerialized]
  24. [Obsolete("Use Pointer3DRaycaster.dragThreshold instead")]
  25. public float dragThreshold = 0.02f;
  26. [NonSerialized]
  27. [Obsolete("Use Pointer3DRaycaster.clickInterval instead")]
  28. public float clickInterval = 0.3f;
  29. public static Vector2 ScreenCenterPoint { get { return new Vector2(Screen.width * 0.5f, Screen.height * 0.5f); } }
  30. public static bool Active { get { return instance != null; } }
  31. public static Pointer3DInputModule Instance
  32. {
  33. get
  34. {
  35. Initialize();
  36. return instance;
  37. }
  38. }
  39. protected virtual void OnApplicationQuit()
  40. {
  41. isApplicationQuitting = true;
  42. }
  43. public override bool ShouldActivateModule()
  44. {
  45. if (!base.ShouldActivateModule()) { return false; }
  46. // if coexist with other inputmodule is enabled, tell EventSystem not to active and let other module active first
  47. return !coexist;
  48. }
  49. #if UNITY_5_5_OR_NEWER
  50. protected virtual void OnApplicationFocus(bool hasFocus)
  51. {
  52. m_hasFocus = hasFocus;
  53. }
  54. protected virtual void Update()
  55. {
  56. // EventSystem is paused when application lost focus, so force ProcessRaycast here
  57. if (isActiveAndEnabled && !m_hasFocus)
  58. {
  59. if (EventSystem.current.currentInputModule == this || coexist)
  60. {
  61. ProcessRaycast();
  62. }
  63. }
  64. }
  65. #endif
  66. public override void UpdateModule()
  67. {
  68. Initialize();
  69. if (isActiveAndEnabled && EventSystem.current.currentInputModule != this && coexist)
  70. {
  71. ProcessRaycast();
  72. }
  73. }
  74. public static void Initialize()
  75. {
  76. if (Active || isApplicationQuitting) { return; }
  77. var instances = FindObjectsOfType<Pointer3DInputModule>();
  78. if (instances.Length > 0)
  79. {
  80. instance = instances[0];
  81. if (instances.Length > 1) { Debug.LogWarning("Multiple Pointer3DInputModule not supported!"); }
  82. }
  83. if (!Active)
  84. {
  85. EventSystem eventSystem = EventSystem.current;
  86. if (eventSystem == null)
  87. {
  88. eventSystem = FindObjectOfType<EventSystem>();
  89. }
  90. if (eventSystem == null)
  91. {
  92. eventSystem = new GameObject("[EventSystem]").AddComponent<EventSystem>();
  93. }
  94. if (eventSystem == null)
  95. {
  96. Debug.LogWarning("EventSystem not found or create fail!");
  97. return;
  98. }
  99. instance = eventSystem.gameObject.AddComponent<Pointer3DInputModule>();
  100. }
  101. }
  102. public static void AssignPointerId(Pointer3DEventData eventData)
  103. {
  104. eventData.pointerId = validEventDataId--;
  105. }
  106. public override void Process()
  107. {
  108. Initialize();
  109. if (isActiveAndEnabled)
  110. {
  111. ProcessRaycast();
  112. }
  113. }
  114. protected override void OnDisable()
  115. {
  116. base.OnDisable();
  117. if (Active && processingRaycasters.Count == 0)
  118. {
  119. for (var i = raycasters.Count - 1; i >= 0; --i)
  120. {
  121. instance.CleanUpRaycaster(raycasters[i]);
  122. }
  123. }
  124. }
  125. public static readonly Comparison<RaycastResult> defaultRaycastComparer = RaycastComparer;
  126. private static int RaycastComparer(RaycastResult lhs, RaycastResult rhs)
  127. {
  128. if (lhs.module != rhs.module)
  129. {
  130. if (lhs.module.eventCamera != null && rhs.module.eventCamera != null && lhs.module.eventCamera.depth != rhs.module.eventCamera.depth)
  131. {
  132. // need to reverse the standard compareTo
  133. if (lhs.module.eventCamera.depth < rhs.module.eventCamera.depth) { return 1; }
  134. if (lhs.module.eventCamera.depth == rhs.module.eventCamera.depth) { return 0; }
  135. return -1;
  136. }
  137. if (lhs.module.sortOrderPriority != rhs.module.sortOrderPriority)
  138. {
  139. return rhs.module.sortOrderPriority.CompareTo(lhs.module.sortOrderPriority);
  140. }
  141. if (lhs.module.renderOrderPriority != rhs.module.renderOrderPriority)
  142. {
  143. return rhs.module.renderOrderPriority.CompareTo(lhs.module.renderOrderPriority);
  144. }
  145. }
  146. if (lhs.sortingLayer != rhs.sortingLayer)
  147. {
  148. // Uses the layer value to properly compare the relative order of the layers.
  149. var rid = SortingLayer.GetLayerValueFromID(rhs.sortingLayer);
  150. var lid = SortingLayer.GetLayerValueFromID(lhs.sortingLayer);
  151. return rid.CompareTo(lid);
  152. }
  153. if (lhs.sortingOrder != rhs.sortingOrder)
  154. {
  155. return rhs.sortingOrder.CompareTo(lhs.sortingOrder);
  156. }
  157. if (!Mathf.Approximately(lhs.distance, rhs.distance))
  158. {
  159. return lhs.distance.CompareTo(rhs.distance);
  160. }
  161. if (lhs.depth != rhs.depth)
  162. {
  163. return rhs.depth.CompareTo(lhs.depth);
  164. }
  165. return lhs.index.CompareTo(rhs.index);
  166. }
  167. public static void AddRaycaster(Pointer3DRaycaster raycaster)
  168. {
  169. if (raycaster == null) { return; }
  170. Initialize();
  171. raycasters.AddUnique(raycaster);
  172. }
  173. public static void RemoveRaycaster(Pointer3DRaycaster raycaster)
  174. {
  175. if (!raycasters.Remove(raycaster)) { return; }
  176. if (!processingRaycasters.Contains(raycaster) && Active)
  177. {
  178. Instance.CleanUpRaycaster(raycaster);
  179. }
  180. }
  181. [Obsolete("Use RemoveRaycaster instead")]
  182. public static void RemoveRaycasters(Pointer3DRaycaster raycaster) { RemoveRaycaster(raycaster); }
  183. protected void CleanUpRaycaster(Pointer3DRaycaster raycaster)
  184. {
  185. if (raycaster == null) { return; }
  186. var hoverEventData = raycaster.HoverEventData;
  187. // buttons event
  188. for (int i = 0, imax = raycaster.ButtonEventDataList.Count; i < imax; ++i)
  189. {
  190. var buttonEventData = raycaster.ButtonEventDataList[i];
  191. if (buttonEventData == null) { continue; }
  192. buttonEventData.Reset();
  193. if (buttonEventData.pressPrecessed)
  194. {
  195. ProcessPressUp(buttonEventData);
  196. HandlePressExitAndEnter(buttonEventData, null);
  197. }
  198. if (buttonEventData.pointerEnter != null)
  199. {
  200. if (buttonEventData == hoverEventData)
  201. {
  202. // perform exit event only for hover event data
  203. HandlePointerExitAndEnter(buttonEventData, null);
  204. }
  205. else
  206. {
  207. buttonEventData.pointerEnter = null;
  208. }
  209. }
  210. }
  211. raycaster.CleanUpRaycast();
  212. for (int i = 0, imax = raycaster.ButtonEventDataList.Count; i < imax; ++i)
  213. {
  214. raycaster.ButtonEventDataList[i].pointerPressRaycast = default(RaycastResult);
  215. raycaster.ButtonEventDataList[i].pointerCurrentRaycast = default(RaycastResult);
  216. }
  217. }
  218. protected virtual void ProcessRaycast()
  219. {
  220. if (m_processedFrame == Time.frameCount) { return; }
  221. m_processedFrame = Time.frameCount;
  222. // use another list to iterate raycasters
  223. // incase that raycasters may changed during this process cycle
  224. for (int i = 0, imax = raycasters.Count; i < imax; ++i)
  225. {
  226. var r = raycasters[i];
  227. if (r != null)
  228. {
  229. processingRaycasters.Add(r);
  230. }
  231. }
  232. for (var i = processingRaycasters.Count - 1; i >= 0; --i)
  233. {
  234. var raycaster = processingRaycasters[i];
  235. if (raycaster == null) { continue; }
  236. raycaster.Raycast();
  237. var result = raycaster.FirstRaycastResult();
  238. // prepare raycaster value
  239. var scrollDelta = raycaster.GetScrollDelta();
  240. var raycasterPos = raycaster.transform.position;
  241. var raycasterRot = raycaster.transform.rotation;
  242. var hoverEventData = raycaster.HoverEventData;
  243. if (hoverEventData == null) { continue; }
  244. // gen shared data and put in hover event
  245. hoverEventData.Reset();
  246. hoverEventData.delta = Vector2.zero;
  247. hoverEventData.scrollDelta = scrollDelta;
  248. hoverEventData.position = ScreenCenterPoint;
  249. hoverEventData.pointerCurrentRaycast = result;
  250. hoverEventData.position3DDelta = raycasterPos - hoverEventData.position3D;
  251. hoverEventData.position3D = raycasterPos;
  252. hoverEventData.rotationDelta = Quaternion.Inverse(hoverEventData.rotation) * raycasterRot;
  253. hoverEventData.rotation = raycasterRot;
  254. // copy data to other button event
  255. for (int j = 0, jmax = raycaster.ButtonEventDataList.Count; j < jmax; ++j)
  256. {
  257. var buttonEventData = raycaster.ButtonEventDataList[j];
  258. if (buttonEventData == null || buttonEventData == hoverEventData) { continue; }
  259. buttonEventData.Reset();
  260. buttonEventData.delta = Vector2.zero;
  261. buttonEventData.scrollDelta = scrollDelta;
  262. buttonEventData.position = ScreenCenterPoint;
  263. buttonEventData.pointerCurrentRaycast = result;
  264. buttonEventData.position3DDelta = hoverEventData.position3DDelta;
  265. buttonEventData.position3D = hoverEventData.position3D;
  266. buttonEventData.rotationDelta = hoverEventData.rotationDelta;
  267. buttonEventData.rotation = hoverEventData.rotation;
  268. }
  269. ProcessPress(hoverEventData);
  270. ProcessMove(hoverEventData);
  271. ProcessDrag(hoverEventData);
  272. // other buttons event
  273. for (int j = 1, jmax = raycaster.ButtonEventDataList.Count; j < jmax; ++j)
  274. {
  275. var buttonEventData = raycaster.ButtonEventDataList[j];
  276. if (buttonEventData == null || buttonEventData == hoverEventData) { continue; }
  277. buttonEventData.pointerEnter = hoverEventData.pointerEnter;
  278. ProcessPress(buttonEventData);
  279. ProcessDrag(buttonEventData);
  280. }
  281. // scroll event
  282. if (result.isValid && !Mathf.Approximately(scrollDelta.sqrMagnitude, 0.0f))
  283. {
  284. var scrollHandler = ExecuteEvents.GetEventHandler<IScrollHandler>(result.gameObject);
  285. ExecuteEvents.ExecuteHierarchy(scrollHandler, hoverEventData, ExecuteEvents.scrollHandler);
  286. }
  287. }
  288. if (isActiveAndEnabled)
  289. {
  290. for (var i = processingRaycasters.Count - 1; i >= 0; --i)
  291. {
  292. var r = processingRaycasters[i];
  293. if (!raycasters.Contains(r))
  294. {
  295. CleanUpRaycaster(r);
  296. }
  297. }
  298. }
  299. else
  300. {
  301. for (var i = processingRaycasters.Count - 1; i >= 0; --i)
  302. {
  303. CleanUpRaycaster(processingRaycasters[i]);
  304. }
  305. }
  306. processingRaycasters.Clear();
  307. }
  308. protected virtual void ProcessMove(PointerEventData eventData)
  309. {
  310. var hoverGO = eventData.pointerCurrentRaycast.gameObject;
  311. if (eventData.pointerEnter != hoverGO)
  312. {
  313. HandlePointerExitAndEnter(eventData, hoverGO);
  314. }
  315. }
  316. protected virtual void ProcessPress(Pointer3DEventData eventData)
  317. {
  318. if (eventData.GetPress())
  319. {
  320. if (!eventData.pressPrecessed)
  321. {
  322. ProcessPressDown(eventData);
  323. }
  324. HandlePressExitAndEnter(eventData, eventData.pointerCurrentRaycast.gameObject);
  325. }
  326. else if (eventData.pressPrecessed)
  327. {
  328. ProcessPressUp(eventData);
  329. HandlePressExitAndEnter(eventData, null);
  330. }
  331. }
  332. protected void ProcessPressDown(Pointer3DEventData eventData)
  333. {
  334. var currentOverGo = eventData.pointerCurrentRaycast.gameObject;
  335. eventData.pressPrecessed = true;
  336. eventData.eligibleForClick = true;
  337. eventData.delta = Vector2.zero;
  338. eventData.dragging = false;
  339. eventData.useDragThreshold = true;
  340. eventData.pressPosition = eventData.position;
  341. eventData.pressPosition3D = eventData.position3D;
  342. eventData.pressRotation = eventData.rotation;
  343. eventData.pressDistance = eventData.pointerCurrentRaycast.distance;
  344. eventData.pointerPressRaycast = eventData.pointerCurrentRaycast;
  345. DeselectIfSelectionChanged(currentOverGo, eventData);
  346. // search for the control that will receive the press
  347. // if we can't find a press handler set the press
  348. // handler to be what would receive a click.
  349. var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, eventData, ExecuteEvents.pointerDownHandler);
  350. // didnt find a press handler... search for a click handler
  351. if (newPressed == null)
  352. {
  353. newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
  354. }
  355. var time = Time.unscaledTime;
  356. if (newPressed == eventData.lastPress)
  357. {
  358. if (eventData.raycaster != null && time < (eventData.clickTime + eventData.raycaster.clickInterval))
  359. {
  360. ++eventData.clickCount;
  361. }
  362. else
  363. {
  364. eventData.clickCount = 1;
  365. }
  366. eventData.clickTime = time;
  367. }
  368. else
  369. {
  370. eventData.clickCount = 1;
  371. }
  372. eventData.pointerPress = newPressed;
  373. eventData.rawPointerPress = currentOverGo;
  374. eventData.clickTime = time;
  375. // Save the drag handler as well
  376. eventData.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
  377. if (eventData.pointerDrag != null)
  378. {
  379. ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.initializePotentialDrag);
  380. }
  381. }
  382. protected void ProcessPressUp(Pointer3DEventData eventData)
  383. {
  384. var currentOverGo = eventData.pointerCurrentRaycast.gameObject;
  385. ExecuteEvents.Execute(eventData.pointerPress, eventData, ExecuteEvents.pointerUpHandler);
  386. // see if we mouse up on the same element that we clicked on...
  387. var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
  388. // PointerClick and Drop events
  389. if (eventData.pointerPress == pointerUpHandler && eventData.eligibleForClick)
  390. {
  391. ExecuteEvents.Execute(eventData.pointerPress, eventData, ExecuteEvents.pointerClickHandler);
  392. }
  393. else if (eventData.pointerDrag != null && eventData.dragging)
  394. {
  395. ExecuteEvents.ExecuteHierarchy(currentOverGo, eventData, ExecuteEvents.dropHandler);
  396. }
  397. eventData.pressPrecessed = false;
  398. eventData.eligibleForClick = false;
  399. eventData.pointerPress = null;
  400. eventData.rawPointerPress = null;
  401. if (eventData.pointerDrag != null && eventData.dragging)
  402. {
  403. ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.endDragHandler);
  404. }
  405. eventData.dragging = false;
  406. eventData.pointerDrag = null;
  407. // redo pointer enter / exit to refresh state
  408. // so that if we moused over something that ignored it before
  409. // due to having pressed on something else
  410. // it now gets it.
  411. if (currentOverGo != eventData.pointerEnter)
  412. {
  413. HandlePointerExitAndEnter(eventData, null);
  414. HandlePointerExitAndEnter(eventData, currentOverGo);
  415. }
  416. }
  417. protected bool ShouldStartDrag(Pointer3DEventData eventData)
  418. {
  419. if (!eventData.useDragThreshold || eventData.raycaster == null) { return true; }
  420. var currentPos = eventData.position3D + (eventData.rotation * Vector3.forward) * eventData.pressDistance;
  421. var pressPos = eventData.pressPosition3D + (eventData.pressRotation * Vector3.forward) * eventData.pressDistance;
  422. var threshold = eventData.raycaster.dragThreshold;
  423. return (currentPos - pressPos).sqrMagnitude >= threshold * threshold;
  424. }
  425. protected void ProcessDrag(Pointer3DEventData eventData)
  426. {
  427. var moving = !Mathf.Approximately(eventData.position3DDelta.sqrMagnitude, 0f) || !Mathf.Approximately(Quaternion.Angle(Quaternion.identity, eventData.rotationDelta), 0f);
  428. if (moving && eventData.pointerDrag != null && !eventData.dragging && ShouldStartDrag(eventData))
  429. {
  430. ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.beginDragHandler);
  431. eventData.dragging = true;
  432. }
  433. // Drag notification
  434. if (eventData.dragging && moving && eventData.pointerDrag != null)
  435. {
  436. // Before doing drag we should cancel any pointer down state
  437. // And clear selection!
  438. if (eventData.pointerPress != eventData.pointerDrag)
  439. {
  440. ExecuteEvents.Execute(eventData.pointerPress, eventData, ExecuteEvents.pointerUpHandler);
  441. eventData.eligibleForClick = false;
  442. eventData.pointerPress = null;
  443. eventData.rawPointerPress = null;
  444. }
  445. ExecuteEvents.Execute(eventData.pointerDrag, eventData, ExecuteEvents.dragHandler);
  446. }
  447. }
  448. protected static void HandlePressExitAndEnter(Pointer3DEventData eventData, GameObject newEnterTarget)
  449. {
  450. if (eventData.pressEnter == newEnterTarget) { return; }
  451. var oldTarget = eventData.pressEnter == null ? null : eventData.pressEnter.transform;
  452. var newTarget = newEnterTarget == null ? null : newEnterTarget.transform;
  453. var commonRoot = default(Transform);
  454. for (var t = oldTarget; t != null; t = t.parent)
  455. {
  456. if (newTarget != null && newTarget.IsChildOf(t))
  457. {
  458. commonRoot = t;
  459. break;
  460. }
  461. else
  462. {
  463. ExecuteEvents.Execute(t.gameObject, eventData, ExecutePointer3DEvents.PressExitHandler);
  464. }
  465. }
  466. eventData.pressEnter = newEnterTarget;
  467. for (var t = newTarget; t != commonRoot; t = t.parent)
  468. {
  469. ExecuteEvents.Execute(t.gameObject, eventData, ExecutePointer3DEvents.PressEnterHandler);
  470. }
  471. }
  472. protected void DeselectIfSelectionChanged(GameObject currentOverGo, BaseEventData pointerEvent)
  473. {
  474. // Selection tracking
  475. var selectHandlerGO = ExecuteEvents.GetEventHandler<ISelectHandler>(currentOverGo);
  476. // if we have clicked something new, deselect the old thing
  477. // leave 'selection handling' up to the press event though.
  478. if (eventSystem != null && selectHandlerGO != eventSystem.currentSelectedGameObject)
  479. {
  480. eventSystem.SetSelectedGameObject(null, pointerEvent);
  481. }
  482. }
  483. public bool SendUpdateEventToSelectedObject()
  484. {
  485. var selected = EventSystem.current.currentSelectedGameObject;
  486. if (selected == null) { return false; }
  487. var data = GetBaseEventData();
  488. ExecuteEvents.Execute(selected, data, ExecuteEvents.updateSelectedHandler);
  489. return data.used;
  490. }
  491. public bool SendSubmitEventToSelectedObject(bool submit, bool cencel)
  492. {
  493. var selected = EventSystem.current.currentSelectedGameObject;
  494. if (selected == null) { return false; }
  495. var data = GetBaseEventData();
  496. if (submit) { ExecuteEvents.Execute(selected, data, ExecuteEvents.submitHandler); }
  497. if (cencel) { ExecuteEvents.Execute(selected, data, ExecuteEvents.cancelHandler); }
  498. return data.used;
  499. }
  500. public bool SendMoveEventToSelectedObject(float x, float y, float moveDeadZone)
  501. {
  502. var selected = EventSystem.current.currentSelectedGameObject;
  503. if (selected == null) { return false; }
  504. var data = GetAxisEventData(x, y, moveDeadZone);
  505. ExecuteEvents.Execute(selected, data, ExecuteEvents.moveHandler);
  506. return data.used;
  507. }
  508. public static string PrintGOPath(GameObject go)
  509. {
  510. var str = string.Empty;
  511. if (go != null)
  512. {
  513. for (var t = go.transform; t != null; t = t.parent)
  514. {
  515. if (!string.IsNullOrEmpty(str)) { str = "." + str; }
  516. str = t.name + str;
  517. }
  518. }
  519. return str;
  520. }
  521. public override string ToString()
  522. {
  523. var str = string.Empty;
  524. if (raycasters.Count == 0)
  525. {
  526. str += "No raycaster registered";
  527. }
  528. else
  529. {
  530. for (int i = 0, imax = raycasters.Count; i < imax; ++i)
  531. {
  532. var raycaster = raycasters[i];
  533. if (raycaster == null) { continue; }
  534. str += "<b>Raycaster: [" + i + "]</b>\n";
  535. str += raycaster.ToString() + "\n";
  536. }
  537. }
  538. return str;
  539. }
  540. }
  541. }