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.

408 lines
15 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 System.Collections.ObjectModel;
  6. using UnityEngine;
  7. using UnityEngine.EventSystems;
  8. namespace HTC.UnityPlugin.Pointer3D
  9. {
  10. public enum RaycastMode
  11. {
  12. DefaultRaycast,
  13. Projection,
  14. Projectile,
  15. }
  16. // Contains and handles Pointer3DEventDatas, derived class should implement their own Pointer3DEventData
  17. // and add into buttonEventDataList, Pointer3DInputModule then will send eventData to the raycast target.
  18. public class Pointer3DRaycaster : BaseFallbackCamRaycaster
  19. {
  20. public const float MIN_SEGMENT_DISTANCE = 0.01f;
  21. private ReadOnlyCollection<Pointer3DEventData> buttonEventDataListReadOnly;
  22. private ReadOnlyCollection<RaycastResult> sortedRaycastResultsReadOnly;
  23. private ReadOnlyCollection<Vector3> breakPointsReadOnly;
  24. protected readonly List<Pointer3DEventData> buttonEventDataList = new List<Pointer3DEventData>();
  25. protected readonly List<RaycastResult> sortedRaycastResults = new List<RaycastResult>();
  26. protected readonly List<Vector3> breakPoints = new List<Vector3>();
  27. public float dragThreshold = 0.02f;
  28. public float clickInterval = 0.3f;
  29. public bool showDebugRay = true;
  30. public Pointer3DEventData HoverEventData { get { return buttonEventDataList.Count > 0 ? buttonEventDataList[0] : null; } }
  31. public ReadOnlyCollection<Pointer3DEventData> ButtonEventDataList
  32. {
  33. get { return buttonEventDataListReadOnly ?? (buttonEventDataListReadOnly = buttonEventDataList.AsReadOnly()); }
  34. }
  35. public ReadOnlyCollection<RaycastResult> SortedRaycastResults
  36. {
  37. get { return sortedRaycastResultsReadOnly ?? (sortedRaycastResultsReadOnly = sortedRaycastResults.AsReadOnly()); }
  38. }
  39. public ReadOnlyCollection<Vector3> BreakPoints
  40. {
  41. get { return breakPointsReadOnly ?? (breakPointsReadOnly = breakPoints.AsReadOnly()); }
  42. }
  43. public virtual Vector2 GetScrollDelta()
  44. {
  45. return Vector2.zero;
  46. }
  47. #if UNITY_EDITOR
  48. protected override void OnValidate()
  49. {
  50. base.OnValidate();
  51. // auto create RaySegmentGenerator if raycast mode is set when using previous version
  52. // and reset to DefaultRaycast since raycastMode is obsoleted
  53. if (m_raycastMode != RaycastMode.DefaultRaycast)
  54. {
  55. if (Application.isPlaying)
  56. {
  57. SetLagacyRaycastMode(m_raycastMode);
  58. m_raycastMode = RaycastMode.DefaultRaycast;
  59. }
  60. else
  61. {
  62. // force saving changes of raycastMode
  63. // use delayCall because sometimes scene is not loaded and can't be marked dirty at this time
  64. UnityEditor.EditorApplication.delayCall += new UnityEditor.EditorApplication.CallbackFunction(() =>
  65. {
  66. Debug.LogWarning("The RaycastMode." + m_raycastMode + " setting has been replaced by adding " + (m_raycastMode == RaycastMode.Projection ? "ProjectionGenerator" : "ProjectileGenerator")
  67. + " component. Please save the scene to preserve this changes.");
  68. SetLagacyRaycastMode(m_raycastMode);
  69. m_raycastMode = RaycastMode.DefaultRaycast;
  70. UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(gameObject.scene);
  71. UnityEditor.EditorUtility.SetDirty(this);
  72. });
  73. }
  74. }
  75. }
  76. #endif
  77. protected override void Start()
  78. {
  79. base.Start();
  80. if (m_raycastMode != RaycastMode.DefaultRaycast)
  81. {
  82. SetLagacyRaycastMode(m_raycastMode);
  83. m_raycastMode = RaycastMode.DefaultRaycast;
  84. }
  85. }
  86. // override OnEnable & OnDisable on purpose so that this BaseRaycaster won't be registered into RaycasterManager
  87. protected override void OnEnable()
  88. {
  89. //base.OnEnable();
  90. Pointer3DInputModule.AddRaycaster(this);
  91. }
  92. protected override void OnDisable()
  93. {
  94. //base.OnDisable();
  95. Pointer3DInputModule.RemoveRaycaster(this);
  96. }
  97. public virtual void CleanUpRaycast()
  98. {
  99. sortedRaycastResults.Clear();
  100. breakPoints.Clear();
  101. }
  102. // invoke by Pointer3DInputModule
  103. public virtual void Raycast()
  104. {
  105. sortedRaycastResults.Clear();
  106. breakPoints.Clear();
  107. var zScale = transform.lossyScale.z;
  108. var amountDistance = (FarDistance - NearDistance) * zScale;
  109. var origin = transform.TransformPoint(0f, 0f, NearDistance);
  110. breakPoints.Add(origin);
  111. bool hasNext = true;
  112. Vector3 direction;
  113. float distance;
  114. Ray ray;
  115. RaycastResult firstHit = default(RaycastResult);
  116. var generator = CurrentSegmentGenerator();
  117. if (ReferenceEquals(generator, null))
  118. {
  119. // process default raycast
  120. direction = transform.forward;
  121. distance = amountDistance;
  122. ray = new Ray(origin, direction);
  123. // move event camera in place
  124. eventCamera.farClipPlane = eventCamera.nearClipPlane + distance;
  125. eventCamera.transform.position = ray.origin - (ray.direction * eventCamera.nearClipPlane);
  126. eventCamera.transform.rotation = Quaternion.LookRotation(ray.direction, transform.up);
  127. ForeachRaycastMethods(ray, distance, sortedRaycastResults);
  128. firstHit = FirstRaycastResult();
  129. breakPoints.Add(firstHit.isValid ? firstHit.worldPosition : ray.GetPoint(distance));
  130. #if UNITY_EDITOR
  131. if (showDebugRay)
  132. {
  133. Debug.DrawLine(breakPoints[0], breakPoints[1], firstHit.isValid ? Color.green : Color.red);
  134. }
  135. #endif
  136. }
  137. else
  138. {
  139. generator.ResetSegments();
  140. do
  141. {
  142. hasNext = generator.NextSegment(out direction, out distance);
  143. if (distance < MIN_SEGMENT_DISTANCE)
  144. {
  145. Debug.LogWarning("RaySegment.distance cannot smaller than " + MIN_SEGMENT_DISTANCE + "! distance=" + distance.ToString("0.000"));
  146. break;
  147. }
  148. distance *= zScale;
  149. if (distance < amountDistance)
  150. {
  151. amountDistance -= distance;
  152. }
  153. else
  154. {
  155. distance = amountDistance;
  156. amountDistance = 0f;
  157. }
  158. ray = new Ray(origin, direction);
  159. // move event camera in place
  160. eventCamera.farClipPlane = eventCamera.nearClipPlane + distance;
  161. eventCamera.transform.position = ray.origin - (ray.direction * eventCamera.nearClipPlane);
  162. eventCamera.transform.rotation = Quaternion.LookRotation(ray.direction, transform.up);
  163. ForeachRaycastMethods(ray, distance, sortedRaycastResults);
  164. firstHit = FirstRaycastResult();
  165. // end loop if raycast hit
  166. if (firstHit.isValid)
  167. {
  168. breakPoints.Add(firstHit.worldPosition);
  169. #if UNITY_EDITOR
  170. if (showDebugRay)
  171. {
  172. Debug.DrawLine(breakPoints[breakPoints.Count - 2], breakPoints[breakPoints.Count - 1], Color.green);
  173. }
  174. #endif
  175. break;
  176. }
  177. // otherwise, shift to next iteration
  178. origin = ray.GetPoint(distance);
  179. breakPoints.Add(origin);
  180. #if UNITY_EDITOR
  181. if (showDebugRay)
  182. {
  183. Debug.DrawLine(breakPoints[breakPoints.Count - 2], breakPoints[breakPoints.Count - 1], Color.red);
  184. }
  185. #endif
  186. }
  187. while (hasNext && amountDistance > 0f);
  188. }
  189. }
  190. // called by StandaloneInputModule, not supported
  191. public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList) { }
  192. public RaycastResult FirstRaycastResult()
  193. {
  194. for (int i = 0, imax = sortedRaycastResults.Count; i < imax; ++i)
  195. {
  196. if (!sortedRaycastResults[i].isValid) { continue; }
  197. return sortedRaycastResults[i];
  198. }
  199. return default(RaycastResult);
  200. }
  201. #region managing segment generators
  202. private IndexedSet<IRaySegmentGenerator> generators = new IndexedSet<IRaySegmentGenerator>();
  203. public void AddGenerator(IRaySegmentGenerator generator)
  204. {
  205. generators.AddUnique(generator);
  206. }
  207. public void RemoveGenerator(IRaySegmentGenerator generator)
  208. {
  209. generators.Remove(generator);
  210. }
  211. // returns first enabled generator in generators, doesn't gaurantee any orders
  212. public IRaySegmentGenerator CurrentSegmentGenerator()
  213. {
  214. for (int i = 0, imax = generators.Count; i < imax; ++i)
  215. {
  216. if (generators[i].enabled) { return generators[i]; }
  217. }
  218. return null;
  219. }
  220. // enable or create TGenerator, disable others
  221. public TGenerator ForceEnableSegmentGenerator<TGenerator>() where TGenerator : MonoBehaviour, IRaySegmentGenerator
  222. {
  223. var gen = default(TGenerator);
  224. var genFound = false;
  225. var gens = ListPool<IRaySegmentGenerator>.Get();
  226. GetComponents(gens);
  227. for (int i = 0, imax = gens.Count; i < imax; ++i)
  228. {
  229. if (genFound || !(gens[i] is TGenerator))
  230. {
  231. gens[i].enabled = false;
  232. }
  233. else
  234. {
  235. gens[i].enabled = true;
  236. gen = gens[i] as TGenerator;
  237. genFound = true;
  238. }
  239. }
  240. ListPool<IRaySegmentGenerator>.Release(gens);
  241. if (!genFound)
  242. {
  243. gen = gameObject.AddComponent<TGenerator>();
  244. }
  245. return gen;
  246. }
  247. public void ForceDisableSegmentGenerators()
  248. {
  249. var gens = ListPool<IRaySegmentGenerator>.Get();
  250. GetComponents(gens);
  251. for (int i = 0, imax = gens.Count; i < imax; ++i)
  252. {
  253. gens[i].enabled = false;
  254. }
  255. ListPool<IRaySegmentGenerator>.Release(gens);
  256. }
  257. #endregion
  258. #region obsolete interfaces
  259. [HideInInspector]
  260. [SerializeField]
  261. private RaycastMode m_raycastMode = RaycastMode.DefaultRaycast;
  262. [HideInInspector]
  263. [SerializeField]
  264. private float m_velocity = 2f;
  265. [HideInInspector]
  266. [SerializeField]
  267. private Vector3 m_gravity = Vector3.down;
  268. [Obsolete("Please use component ProjectionGenerator / ProjectileGenerator")]
  269. public RaycastMode raycastMode
  270. {
  271. get { return m_raycastMode; }
  272. set
  273. {
  274. m_raycastMode = value;
  275. SetLagacyRaycastMode(value);
  276. }
  277. }
  278. [Obsolete("Please use ProjectionGenerator.velocity / ProjectileGenerator.velocity")]
  279. public float velocity
  280. {
  281. get { return m_velocity; }
  282. set
  283. {
  284. m_velocity = value;
  285. var gen = CurrentSegmentGenerator();
  286. if (gen != null)
  287. {
  288. if (gen is ProjectionGenerator) { ((ProjectionGenerator)gen).velocity = value; }
  289. else if (gen is ProjectileGenerator) { ((ProjectileGenerator)gen).velocity = value; }
  290. }
  291. }
  292. }
  293. [Obsolete("Please use ProjectionGenerator.gravity / ProjectileGenerator.gravity")]
  294. public Vector3 gravity
  295. {
  296. get { return m_gravity; }
  297. set
  298. {
  299. m_gravity = value;
  300. var gen = CurrentSegmentGenerator();
  301. if (gen != null)
  302. {
  303. if (gen is ProjectionGenerator) { ((ProjectionGenerator)gen).gravity = value; }
  304. else if (gen is ProjectileGenerator) { ((ProjectileGenerator)gen).gravity = value; }
  305. }
  306. }
  307. }
  308. [Obsolete("Please use component ProjectionGenerator / ProjectileGenerator")]
  309. protected virtual void InitSegmentGenerator() { }
  310. // for backward compatible
  311. private void SetLagacyRaycastMode(RaycastMode mode)
  312. {
  313. switch (mode)
  314. {
  315. case RaycastMode.Projection:
  316. {
  317. var gen = ForceEnableSegmentGenerator<ProjectionGenerator>();
  318. gen.velocity = m_velocity;
  319. gen.gravity = m_gravity;
  320. break;
  321. }
  322. case RaycastMode.Projectile:
  323. {
  324. var gen = ForceEnableSegmentGenerator<ProjectileGenerator>();
  325. gen.velocity = m_velocity;
  326. gen.gravity = m_gravity;
  327. break;
  328. }
  329. default:
  330. {
  331. ForceDisableSegmentGenerators();
  332. break;
  333. }
  334. }
  335. }
  336. #endregion
  337. public override string ToString()
  338. {
  339. var str = string.Empty;
  340. str += "Raycaster path: " + Pointer3DInputModule.PrintGOPath(gameObject) + "(" + GetType().Name + ")\n";
  341. str += "Raycaster transform: " + "pos" + transform.position.ToString("0.00") + " " + "rot" + transform.eulerAngles.ToString("0.0") + "\n";
  342. for (int i = 0, imax = buttonEventDataList.Count; i < imax; ++i)
  343. {
  344. var eventData = buttonEventDataList[i];
  345. if (eventData == null) { continue; }
  346. if (eventData.eligibleForClick || (i == 0 && eventData.pointerEnter != null)) // is hover event?
  347. {
  348. str += "<b>EventData: [" + i + "]</b>\n";
  349. str += eventData.ToString();
  350. }
  351. }
  352. return str;
  353. }
  354. }
  355. }