SW 중심대학 OSS GIT 서버 박건태, 이승준, 고기완, 이준호 새로운 배포
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.

229 lines
8.3 KiB

4 years ago
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Events;
  4. using Logger = ARLocation.Utils.Logger;
  5. namespace ARLocation {
  6. [AddComponentMenu("AR+GPS/Hotspot")]
  7. [HelpURL("https://http://docs.unity-ar-gps-location.com/guide/#hotspot")]
  8. [DisallowMultipleComponent]
  9. public class Hotspot : MonoBehaviour
  10. {
  11. [Serializable]
  12. public class OnHotspotActivatedUnityEvent : UnityEvent<GameObject> {}
  13. [Serializable]
  14. public class OnHotspotLeaveUnityEvent : UnityEvent<GameObject> {}
  15. [Serializable]
  16. public enum PositionModes {
  17. HotspotCenter,
  18. CameraPosition
  19. };
  20. [Serializable]
  21. public class HotspotSettingsData
  22. {
  23. [Tooltip("The prefab/GameObject that will be instantiated by the Hotspot.")]
  24. public GameObject Prefab;
  25. [Tooltip("The positioning mode. 'HotspotCenter' means the object will be instantiated at the Hotpot's center geo-location. 'CameraPosition' means it will be positioned at the front of the camera.")]
  26. public PositionModes PositionMode;
  27. [Tooltip("The distance from the center that the user must be located to activate the Hotspot.")]
  28. public float ActivationRadius = 4.0f;
  29. [Tooltip("If true, align the instantiated object to face the camera (horizontally).")]
  30. public bool AlignToCamera = true;
  31. [Tooltip("If 'PositionMode' is set to 'CameraPosition', how far from the camera the instantiated object should be placed.")]
  32. public float DistanceFromCamera = 3.0f;
  33. }
  34. [Serializable]
  35. public class StateData
  36. {
  37. public bool Activated;
  38. public GameObject Instance;
  39. public Location Location;
  40. public bool EmittedLeaveHotspotEvent;
  41. }
  42. public PlaceAtLocation.LocationSettingsData LocationSettings = new PlaceAtLocation.LocationSettingsData();
  43. public HotspotSettingsData HotspotSettings = new HotspotSettingsData();
  44. [Space(4.0f)]
  45. [Header("Debug")]
  46. [Tooltip("When debug mode is enabled, this component will print relevant messages to the console. Filter by 'Hotspot' in the log output to see the messages.")]
  47. public bool DebugMode;
  48. [Space(4.0f)]
  49. [Header("Events")]
  50. [Tooltip("If true, monitor distance to emit the 'OnLeaveHotspot' event. If you don't need it, keep this disabled for better performance.")]
  51. public bool UseOnLeaveHotspotEvent;
  52. [Tooltip("Event for the Hotspot is activated.")]
  53. public OnHotspotActivatedUnityEvent OnHotspotActivated = new OnHotspotActivatedUnityEvent();
  54. [Tooltip("This event will be emited only once, when the user leaves the hotspot area after it is activated.")]
  55. public OnHotspotLeaveUnityEvent OnHotspotLeave = new OnHotspotLeaveUnityEvent();
  56. private readonly StateData state = new StateData();
  57. private Transform root;
  58. private Camera arCamera;
  59. private double currentDistance;
  60. // ReSharper disable once UnusedMember.Global
  61. public GameObject Instance => state.Instance;
  62. // ReSharper disable once MemberCanBePrivate.Global
  63. public Location Location {
  64. // ReSharper disable once UnusedMember.Global
  65. get => state.Location;
  66. set => state.Location = value;
  67. }
  68. /// <summary>
  69. /// Returns the current user distance to the Hotspot center.
  70. /// </summary>
  71. public float CurrentDistance => (float) currentDistance;
  72. void Start()
  73. {
  74. var arLocationProvider = ARLocationProvider.Instance;
  75. arLocationProvider.Provider.LocationUpdatedRaw += Provider_LocationUpdatedRaw;
  76. root = ARLocationManager.Instance.gameObject.transform;
  77. if (state.Location == null)
  78. {
  79. state.Location = LocationSettings.GetLocation();
  80. }
  81. arCamera = ARLocationManager.Instance.MainCamera;
  82. if (arLocationProvider.IsEnabled)
  83. {
  84. Provider_LocationUpdatedRaw(arLocationProvider.CurrentLocation, arLocationProvider.LastLocation);
  85. }
  86. }
  87. public void Restart()
  88. {
  89. state.Activated = false;
  90. state.EmittedLeaveHotspotEvent = false;
  91. state.Instance = null;
  92. Destroy(state.Instance);
  93. }
  94. private void Provider_LocationUpdatedRaw(LocationReading currentLocation, LocationReading lastLocation)
  95. {
  96. if (state.Activated) return;
  97. Logger.LogFromMethod("Hotspot", "LocationUpdatedRaw", $"({gameObject.name}): New device location {currentLocation}", DebugMode);
  98. currentDistance = Location.HorizontalDistance(currentLocation.ToLocation(), state.Location);
  99. var delta = Location.HorizontalVectorFromTo(currentLocation.ToLocation(), state.Location);
  100. if (currentDistance <= HotspotSettings.ActivationRadius)
  101. {
  102. ActivateHotspot(new Vector3((float) delta.x, 0, (float) delta.y));
  103. }
  104. else
  105. {
  106. Logger.LogFromMethod("Hotspot", "LocationUpdatedRaw", $"({gameObject.name}): No activation - distance = {currentDistance}", DebugMode);
  107. }
  108. }
  109. private void ActivateHotspot(Vector3 delta)
  110. {
  111. Logger.LogFromMethod("Hotspot", "ActivateHotspot", $"({gameObject.name}): Activating hotspot...", DebugMode);
  112. if (HotspotSettings.Prefab == null) return;
  113. state.Instance = Instantiate(HotspotSettings.Prefab, HotspotSettings.AlignToCamera ? gameObject.transform : root);
  114. switch (HotspotSettings.PositionMode)
  115. {
  116. case PositionModes.HotspotCenter:
  117. state.Instance.transform.position = arCamera.transform.position + delta;
  118. break;
  119. case PositionModes.CameraPosition:
  120. var transform1 = arCamera.transform;
  121. var forward = transform1.forward;
  122. forward.y = 0;
  123. state.Instance.transform.position = transform1.position + forward * HotspotSettings.DistanceFromCamera;
  124. break;
  125. }
  126. if (HotspotSettings.AlignToCamera)
  127. {
  128. state.Instance.transform.LookAt(arCamera.transform);
  129. }
  130. state.Instance.AddComponent<GroundHeight>();
  131. state.Instance.name = name + " (Hotspot)";
  132. state.Activated = true;
  133. Logger.LogFromMethod("Hotspot", "ActivateHotspot", $"({name}): Hotspot activated", DebugMode);
  134. OnHotspotActivated?.Invoke(state.Instance);
  135. }
  136. // ReSharper disable once UnusedMethodReturnValue.Global
  137. // ReSharper disable once MemberCanBePrivate.Global
  138. public static Hotspot AddHotspotComponent(GameObject go, Location location, HotspotSettingsData settings)
  139. {
  140. var hotspot = go.AddComponent<Hotspot>();
  141. hotspot.Location = location.Clone();
  142. hotspot.HotspotSettings = settings;
  143. return hotspot;
  144. }
  145. // ReSharper disable once UnusedMember.Global
  146. public static GameObject CreateHotspotGameObject(Location location, HotspotSettingsData settings,
  147. string name = "GPS Hotspot")
  148. {
  149. var go = new GameObject(name);
  150. AddHotspotComponent(go, location, settings);
  151. return go;
  152. }
  153. void Update()
  154. {
  155. if (UseOnLeaveHotspotEvent && state.Activated && !state.EmittedLeaveHotspotEvent)
  156. {
  157. var distance = Vector3.Distance(arCamera.transform.position, state.Instance.transform.position);
  158. if (distance >= HotspotSettings.ActivationRadius)
  159. {
  160. OnHotspotLeave?.Invoke(state.Instance);
  161. state.EmittedLeaveHotspotEvent = true;
  162. }
  163. }
  164. }
  165. public void AtoB_Button()
  166. {
  167. LocationSettings.LocationInput.Location.Latitude = 35.967491;
  168. LocationSettings.LocationInput.Location.Longitude = 126.711558;
  169. gameObject.GetComponent<Hotspot>().enabled = true;
  170. }
  171. public void AtoC_Button()
  172. {
  173. gameObject.GetComponent<Hotspot>().enabled = true;
  174. }
  175. }
  176. }