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.

438 lines
16 KiB

5 years ago
  1. //========= Copyright 2016-2020, HTC Corporation. All rights reserved. ===========
  2. using HTC.UnityPlugin.Utility;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.EventSystems;
  6. namespace HTC.UnityPlugin.ColliderEvent
  7. {
  8. public interface IColliderEventCaster
  9. {
  10. GameObject gameObject { get; }
  11. Transform transform { get; }
  12. MonoBehaviour monoBehaviour { get; }
  13. IIndexedSetReadOnly<Collider> enteredColliders { get; }
  14. Rigidbody rigid { get; }
  15. }
  16. [RequireComponent(typeof(Rigidbody))]
  17. public class ColliderEventCaster : MonoBehaviour, IColliderEventCaster
  18. {
  19. private static HashSet<int> s_gos = new HashSet<int>();
  20. private bool isUpdating;
  21. private bool isDisabled;
  22. private IndexedSet<Collider> stayingColliders = new IndexedSet<Collider>();
  23. private IndexedSet<GameObject> hoveredObjects = new IndexedSet<GameObject>();
  24. private Rigidbody m_rigid;
  25. private ColliderHoverEventData hoverEventData;
  26. protected readonly List<ColliderButtonEventData> buttonEventDataList = new List<ColliderButtonEventData>();
  27. protected readonly List<ColliderAxisEventData> axisEventDataList = new List<ColliderAxisEventData>();
  28. private List<GameObject> hoverEnterHandlers = new List<GameObject>();
  29. private List<GameObject> hoverExitHandlers = new List<GameObject>();
  30. protected class ButtonHandlers
  31. {
  32. public List<GameObject> pressEnterHandlers = new List<GameObject>();
  33. public List<GameObject> pressExitHandlers = new List<GameObject>();
  34. public List<GameObject> pressDownHandlers = new List<GameObject>();
  35. public List<GameObject> pressUpHandlers = new List<GameObject>();
  36. public List<GameObject> clickHandlers = new List<GameObject>();
  37. public List<GameObject> dragStartHandlers = new List<GameObject>();
  38. public List<GameObject> dragFixedUpdateHandlers = new List<GameObject>();
  39. public List<GameObject> dragUpdateHandlers = new List<GameObject>();
  40. public List<GameObject> dragEndHandlers = new List<GameObject>();
  41. public List<GameObject> dropHandlers = new List<GameObject>();
  42. }
  43. protected class AxisHandlers
  44. {
  45. public List<GameObject> axisChangedHandlers = new List<GameObject>();
  46. }
  47. private List<ButtonHandlers> buttonEventHandlerList = new List<ButtonHandlers>();
  48. private List<AxisHandlers> axisEventHanderList = new List<AxisHandlers>();
  49. public MonoBehaviour monoBehaviour
  50. {
  51. get { return this; }
  52. }
  53. public Rigidbody rigid
  54. {
  55. get { return m_rigid ?? (m_rigid = GetComponent<Rigidbody>()); }
  56. }
  57. public IIndexedSetReadOnly<Collider> enteredColliders
  58. {
  59. get { return stayingColliders.ReadOnly; }
  60. }
  61. public ColliderHoverEventData HoverEventData
  62. {
  63. get { return hoverEventData ?? (hoverEventData = new ColliderHoverEventData(this)); }
  64. protected set { hoverEventData = value; }
  65. }
  66. private bool CannotHandlDragAnymore(GameObject handler)
  67. {
  68. return !ExecuteEvents.CanHandleEvent<IColliderEventDragStartHandler>(handler);
  69. }
  70. protected virtual void OnEnable()
  71. {
  72. isDisabled = false;
  73. }
  74. protected virtual void FixedUpdate()
  75. {
  76. isUpdating = true;
  77. // fixed dragging
  78. for (int i = 0, imax = buttonEventDataList.Count; i < imax; ++i)
  79. {
  80. var eventData = buttonEventDataList[i];
  81. var handlers = GetButtonHandlers(i);
  82. eventData.draggingHandlers.RemoveAll(CannotHandlDragAnymore);
  83. if (!eventData.isPressed) { continue; }
  84. for (int j = eventData.draggingHandlers.Count - 1; j >= 0; --j)
  85. {
  86. handlers.dragFixedUpdateHandlers.Add(eventData.draggingHandlers[j]);
  87. }
  88. }
  89. ExecuteAllEvents();
  90. if (isDisabled)
  91. {
  92. CleanUp();
  93. }
  94. stayingColliders.Clear();
  95. isUpdating = false;
  96. }
  97. protected virtual void OnTriggerStay(Collider other)
  98. {
  99. stayingColliders.AddUnique(other);
  100. }
  101. protected virtual void Update()
  102. {
  103. isUpdating = true;
  104. // process enter
  105. var hoveredObjectsPrev = hoveredObjects;
  106. hoveredObjects = IndexedSetPool<GameObject>.Get();
  107. for (int i = stayingColliders.Count - 1; i >= 0; --i)
  108. {
  109. var collider = stayingColliders[i];
  110. if (collider == null) { continue; }
  111. // travel from collider's gameObject to its root
  112. for (var tr = collider.transform; !ReferenceEquals(tr, null); tr = tr.parent)
  113. {
  114. var go = tr.gameObject;
  115. if (!hoveredObjects.AddUnique(go)) { break; } // hit traveled gameObject, break and travel from the next collider
  116. if (hoveredObjectsPrev.Remove(go)) { continue; } // gameObject already existed in last frame, no need to execute enter event
  117. hoverEnterHandlers.Add(go);
  118. }
  119. }
  120. // process leave
  121. for (int i = hoveredObjectsPrev.Count - 1; i >= 0; --i)
  122. {
  123. hoverExitHandlers.Add(hoveredObjectsPrev[i]);
  124. }
  125. IndexedSetPool<GameObject>.Release(hoveredObjectsPrev);
  126. // process button events
  127. for (int i = 0, imax = buttonEventDataList.Count; i < imax; ++i)
  128. {
  129. var eventData = buttonEventDataList[i];
  130. var handlers = GetButtonHandlers(i);
  131. eventData.draggingHandlers.RemoveAll(CannotHandlDragAnymore);
  132. // process button press
  133. if (!eventData.isPressed)
  134. {
  135. if (eventData.GetPress())
  136. {
  137. ProcessPressDown(eventData, handlers);
  138. ProcessPressing(eventData, handlers);
  139. }
  140. }
  141. else
  142. {
  143. if (eventData.GetPress())
  144. {
  145. ProcessPressing(eventData, handlers);
  146. }
  147. else
  148. {
  149. ProcessPressUp(eventData, handlers);
  150. }
  151. }
  152. // process pressed button enter/exit
  153. if (eventData.isPressed)
  154. {
  155. var pressEnteredObjectsPrev = eventData.pressEnteredObjects;
  156. eventData.pressEnteredObjects = IndexedSetPool<GameObject>.Get();
  157. for (int j = hoveredObjects.Count - 1; j >= 0; --j)
  158. {
  159. eventData.pressEnteredObjects.Add(hoveredObjects[j]);
  160. if (pressEnteredObjectsPrev.Remove(hoveredObjects[j])) { continue; } // gameObject already existed in last frame, no need to execute enter event
  161. handlers.pressEnterHandlers.Add(hoveredObjects[j]);
  162. }
  163. for (int j = pressEnteredObjectsPrev.Count - 1; j >= 0; --j)
  164. {
  165. eventData.clickingHandlers.Remove(pressEnteredObjectsPrev[j]); // remove the obj from clicking obj if it leaved
  166. handlers.pressExitHandlers.Add(pressEnteredObjectsPrev[j]);
  167. }
  168. IndexedSetPool<GameObject>.Release(pressEnteredObjectsPrev);
  169. }
  170. else
  171. {
  172. for (int j = eventData.pressEnteredObjects.Count - 1; j >= 0; --j)
  173. {
  174. handlers.pressExitHandlers.Add(eventData.pressEnteredObjects[j]);
  175. }
  176. eventData.pressEnteredObjects.Clear();
  177. }
  178. }
  179. // process axis events
  180. for (int i = 0, imax = axisEventDataList.Count; i < imax; ++i)
  181. {
  182. var eventData = axisEventDataList[i];
  183. if ((eventData.v4 = eventData.GetDelta()) == Vector4.zero) { continue; }
  184. var handlers = GetAxisHandlers(i);
  185. GetEventHandlersFromHoveredColliders<IColliderEventAxisChangedHandler>(handlers.axisChangedHandlers);
  186. }
  187. ExecuteAllEvents();
  188. if (isDisabled)
  189. {
  190. CleanUp();
  191. }
  192. isUpdating = false;
  193. }
  194. protected void ProcessPressDown(ColliderButtonEventData eventData, ButtonHandlers handlers)
  195. {
  196. eventData.isPressed = true;
  197. eventData.pressPosition = transform.position;
  198. eventData.pressRotation = transform.rotation;
  199. for (int i = stayingColliders.Count - 1; i >= 0; --i)
  200. {
  201. if (stayingColliders[i] != null) { eventData.pressedRawObjects.AddUnique(stayingColliders[i].gameObject); }
  202. }
  203. // press down
  204. GetEventHandlersFromHoveredColliders<IColliderEventPressDownHandler>(eventData.pressedHandlers, handlers.pressDownHandlers);
  205. // click start
  206. GetEventHandlersFromHoveredColliders<IColliderEventClickHandler>(eventData.clickingHandlers);
  207. // drag start
  208. GetEventHandlersFromHoveredColliders<IColliderEventDragStartHandler>(eventData.draggingHandlers, handlers.dragStartHandlers);
  209. }
  210. protected void ProcessPressing(ColliderButtonEventData eventData, ButtonHandlers handlers)
  211. {
  212. // dragging
  213. handlers.dragUpdateHandlers.AddRange(eventData.draggingHandlers);
  214. }
  215. protected void ProcessPressUp(ColliderButtonEventData eventData, ButtonHandlers handlers)
  216. {
  217. IndexedSet<GameObject> tmp;
  218. eventData.isPressed = false;
  219. tmp = eventData.lastPressedRawObjects;
  220. eventData.lastPressedRawObjects = eventData.pressedRawObjects;
  221. eventData.pressedRawObjects = tmp;
  222. // press up
  223. handlers.pressUpHandlers.AddRange(eventData.pressedHandlers);
  224. tmp = eventData.lastPressedHandlers;
  225. eventData.lastPressedHandlers = eventData.pressedHandlers;
  226. eventData.pressedHandlers = tmp;
  227. // drag end
  228. handlers.dragEndHandlers.AddRange(eventData.draggingHandlers);
  229. // drop
  230. if (eventData.isDragging)
  231. {
  232. GetEventHandlersFromHoveredColliders<IColliderEventDropHandler>(handlers.dropHandlers);
  233. }
  234. // click end (execute only if pressDown handler and pressUp handler are the same)
  235. GetMatchedEventHandlersFromHoveredColliders<IColliderEventClickHandler>(h => eventData.clickingHandlers.Remove(h), handlers.clickHandlers);
  236. eventData.pressedRawObjects.Clear();
  237. eventData.pressedHandlers.Clear();
  238. eventData.clickingHandlers.Clear();
  239. eventData.draggingHandlers.Clear();
  240. }
  241. protected virtual void OnDisable()
  242. {
  243. isDisabled = true;
  244. if (!isUpdating)
  245. {
  246. CleanUp();
  247. }
  248. }
  249. private void CleanUp()
  250. {
  251. // release all
  252. for (int i = 0, imax = buttonEventDataList.Count; i < imax; ++i)
  253. {
  254. var eventData = buttonEventDataList[i];
  255. var handlers = GetButtonHandlers(i);
  256. eventData.draggingHandlers.RemoveAll(CannotHandlDragAnymore);
  257. if (eventData.isPressed)
  258. {
  259. ProcessPressUp(eventData, handlers);
  260. }
  261. for (int j = eventData.pressEnteredObjects.Count - 1; j >= 0; --j)
  262. {
  263. handlers.pressExitHandlers.Add(eventData.pressEnteredObjects[j]);
  264. }
  265. }
  266. // exit all
  267. for (int i = hoveredObjects.Count - 1; i >= 0; --i)
  268. {
  269. hoverExitHandlers.Add(hoveredObjects[i]);
  270. }
  271. hoveredObjects.Clear();
  272. stayingColliders.Clear();
  273. ExecuteAllEvents();
  274. }
  275. private ButtonHandlers GetButtonHandlers(int i)
  276. {
  277. while (i >= buttonEventHandlerList.Count) { buttonEventHandlerList.Add(null); }
  278. return buttonEventHandlerList[i] ?? (buttonEventHandlerList[i] = new ButtonHandlers());
  279. }
  280. private AxisHandlers GetAxisHandlers(int i)
  281. {
  282. while (i >= axisEventHanderList.Count) { axisEventHanderList.Add(null); }
  283. return axisEventHanderList[i] ?? (axisEventHanderList[i] = new AxisHandlers());
  284. }
  285. private void GetEventHandlersFromHoveredColliders<T>(IList<GameObject> appendHandler, IList<GameObject> appendHandler2 = null) where T : IEventSystemHandler
  286. {
  287. GetMatchedEventHandlersFromHoveredColliders<T>(null, appendHandler, appendHandler2);
  288. }
  289. private void GetMatchedEventHandlersFromHoveredColliders<T>(System.Predicate<GameObject> match, IList<GameObject> appendHandler, IList<GameObject> appendHandler2 = null) where T : IEventSystemHandler
  290. {
  291. for (int i = stayingColliders.Count - 1; i >= 0; --i)
  292. {
  293. var collider = stayingColliders[i];
  294. if (collider == null) { continue; }
  295. var handler = ExecuteEvents.GetEventHandler<T>(collider.gameObject);
  296. if (ReferenceEquals(handler, null)) { continue; }
  297. if (!s_gos.Add(handler.GetInstanceID())) { continue; }
  298. if (match != null && !match(handler)) { continue; }
  299. if (appendHandler != null) { appendHandler.Add(handler); }
  300. if (appendHandler2 != null) { appendHandler2.Add(handler); }
  301. }
  302. s_gos.Clear();
  303. }
  304. private void ExecuteAllEvents()
  305. {
  306. ExcuteHandlersEvents(hoverEnterHandlers, HoverEventData, ExecuteColliderEvents.HoverEnterHandler);
  307. for (int i = buttonEventHandlerList.Count - 1; i >= 0; --i)
  308. {
  309. if (buttonEventHandlerList[i] == null) { continue; }
  310. ExcuteHandlersEvents(buttonEventHandlerList[i].pressEnterHandlers, buttonEventDataList[i], ExecuteColliderEvents.PressEnterHandler);
  311. ExcuteHandlersEvents(buttonEventHandlerList[i].pressDownHandlers, buttonEventDataList[i], ExecuteColliderEvents.PressDownHandler);
  312. ExcuteHandlersEvents(buttonEventHandlerList[i].pressUpHandlers, buttonEventDataList[i], ExecuteColliderEvents.PressUpHandler);
  313. ExcuteHandlersEvents(buttonEventHandlerList[i].dragStartHandlers, buttonEventDataList[i], ExecuteColliderEvents.DragStartHandler);
  314. ExcuteHandlersEvents(buttonEventHandlerList[i].dragFixedUpdateHandlers, buttonEventDataList[i], ExecuteColliderEvents.DragFixedUpdateHandler);
  315. ExcuteHandlersEvents(buttonEventHandlerList[i].dragUpdateHandlers, buttonEventDataList[i], ExecuteColliderEvents.DragUpdateHandler);
  316. ExcuteHandlersEvents(buttonEventHandlerList[i].dragEndHandlers, buttonEventDataList[i], ExecuteColliderEvents.DragEndHandler);
  317. ExcuteHandlersEvents(buttonEventHandlerList[i].dropHandlers, buttonEventDataList[i], ExecuteColliderEvents.DropHandler);
  318. ExcuteHandlersEvents(buttonEventHandlerList[i].clickHandlers, buttonEventDataList[i], ExecuteColliderEvents.ClickHandler);
  319. ExcuteHandlersEvents(buttonEventHandlerList[i].pressExitHandlers, buttonEventDataList[i], ExecuteColliderEvents.PressExitHandler);
  320. }
  321. for (int i = axisEventHanderList.Count - 1; i >= 0; --i)
  322. {
  323. if (axisEventHanderList[i] == null) { continue; }
  324. ExcuteHandlersEvents(axisEventHanderList[i].axisChangedHandlers, axisEventDataList[i], ExecuteColliderEvents.AxisChangedHandler);
  325. }
  326. ExcuteHandlersEvents(hoverExitHandlers, HoverEventData, ExecuteColliderEvents.HoverExitHandler);
  327. }
  328. private void ExcuteHandlersEvents<T>(List<GameObject> handlers, BaseEventData eventData, ExecuteEvents.EventFunction<T> functor) where T : IEventSystemHandler
  329. {
  330. if (handlers.Count == 0) { return; }
  331. for (int i = handlers.Count - 1; i >= 0; --i)
  332. {
  333. ExecuteEvents.Execute(handlers[i], eventData, functor);
  334. }
  335. handlers.Clear();
  336. }
  337. }
  338. }