CustomRouteInspector.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. using UnityEngine;
  2. using UnityEditor;
  3. using System;
  4. using System.Collections.Generic;
  5. namespace ARLocation.MapboxRoutes
  6. {
  7. [CustomEditor(typeof(CustomRoute))]
  8. public class CustomRouteInspector : Editor
  9. {
  10. private List<Vector3> pointsCache = null;
  11. private void OnEnable()
  12. {
  13. AddOnSceneGUIDelegate(OnSceneGuiDelegate);
  14. Tools.hidden = true;
  15. }
  16. void OnDisable()
  17. {
  18. RemoveOnSceneGUIDelegate(OnSceneGuiDelegate);
  19. Tools.hidden = false;
  20. }
  21. #if UNITY_2019_1_OR_NEWER
  22. private void AddOnSceneGUIDelegate(Action<SceneView> del)
  23. {
  24. SceneView.duringSceneGui += del; // sceneView => OnSceneGUI();
  25. }
  26. #else
  27. private void AddOnSceneGUIDelegate(SceneView.OnSceneFunc del)
  28. {
  29. SceneView.onSceneGUIDelegate += del;
  30. }
  31. #endif
  32. #if UNITY_2019_1_OR_NEWER
  33. private void RemoveOnSceneGUIDelegate(Action<SceneView> del)
  34. {
  35. SceneView.duringSceneGui -= del; // sceneView => OnSceneGUI();
  36. }
  37. #else
  38. private void RemoveOnSceneGUIDelegate(SceneView.OnSceneFunc del)
  39. {
  40. SceneView.onSceneGUIDelegate -= del;
  41. }
  42. #endif
  43. private void OnSceneGuiDelegate(SceneView sceneview)
  44. {
  45. OnSceneGUI();
  46. }
  47. void DrawHandles(CustomRoute customRoute)
  48. {
  49. var viewScale = customRoute.SceneViewScale;
  50. var effScale = (1.0f + Mathf.Cos(viewScale * Mathf.PI / 2 - Mathf.PI));
  51. var s = new Vector3(effScale, 1.0f, effScale);
  52. for (var i = 0; i < pointsCache.Count; i++)
  53. {
  54. var p = pointsCache[i];
  55. var isStep = customRoute.Points[i].IsStep;
  56. Handles.color = isStep ? Color.red : Color.blue;
  57. Handles.SphereHandleCap(0, Vector3.Scale(p, s), Quaternion.identity, 4.0f, EventType.Repaint);
  58. if (i > 0)
  59. {
  60. Handles.color = Color.green;
  61. Handles.DrawLine(Vector3.Scale(s, pointsCache[i - 1]), Vector3.Scale(s, pointsCache[i]));
  62. }
  63. }
  64. }
  65. void DrawOnSceneGui(CustomRoute customRoute)
  66. {
  67. Handles.BeginGUI();
  68. GUILayout.BeginArea(new Rect(20, 20, 200, 200));
  69. var rect = EditorGUILayout.BeginVertical();
  70. GUI.color = new Color(1, 1, 1, 0.4f);
  71. GUI.Box(rect, GUIContent.none);
  72. GUI.color = Color.white;
  73. GUILayout.BeginHorizontal();
  74. GUILayout.FlexibleSpace();
  75. GUILayout.Label("Custom Route");
  76. GUILayout.FlexibleSpace();
  77. GUILayout.EndHorizontal();
  78. var style = new GUIStyle
  79. {
  80. margin = new RectOffset(0, 0, 4, 200)
  81. };
  82. GUILayout.BeginHorizontal(style);
  83. GUI.backgroundColor = new Color(0.2f, 0.5f, 0.92f);
  84. GUILayout.Label("View Scale: ", GUILayout.Width(80.0f));
  85. var sceneViewScale = customRoute.SceneViewScale;
  86. var newViewScale = GUILayout.HorizontalSlider(sceneViewScale, 0.01f, 1.0f);
  87. if (Math.Abs(newViewScale - sceneViewScale) > 0.000001f)
  88. {
  89. sceneViewScale = newViewScale;
  90. serializedObject.ApplyModifiedProperties();
  91. }
  92. customRoute.SceneViewScale = sceneViewScale;
  93. GUILayout.Label(sceneViewScale.ToString("0.00"), GUILayout.Width(32.0f));
  94. GUILayout.EndHorizontal();
  95. EditorGUILayout.EndVertical();
  96. GUILayout.EndArea();
  97. Handles.EndGUI();
  98. }
  99. void OnSceneGUI()
  100. {
  101. var customRoute = (CustomRoute)target;
  102. if (customRoute == null || customRoute.Points.Count < 2)
  103. {
  104. return;
  105. }
  106. if (customRoute.IsDirty || pointsCache == null)
  107. {
  108. pointsCache = new List<Vector3>();
  109. for (var i = 0; i < customRoute.Points.Count; i++)
  110. {
  111. var position = Location.GetGameObjectPositionForLocation(
  112. null,
  113. new Vector3(),
  114. customRoute.Points[0].Location,
  115. customRoute.Points[i].Location,
  116. true
  117. );
  118. position.y = 0;
  119. pointsCache.Add(position);
  120. }
  121. customRoute.IsDirty = false;
  122. }
  123. DrawOnSceneGui(customRoute);
  124. DrawHandles(customRoute);
  125. }
  126. [MenuItem("Assets/AR+GPS/Custom Route From KML", false)]
  127. private static void KmlMenuClick()
  128. {
  129. var path = AssetDatabase.GetAssetPath(Selection.activeObject);
  130. var reader = new System.IO.StreamReader(path);
  131. var contents = reader.ReadToEnd();
  132. Debug.Log(contents);
  133. reader.Close();
  134. var xml = new System.Xml.XmlDocument();
  135. xml.LoadXml(contents);
  136. var kmlNode = xml["kml"];
  137. if (kmlNode == null)
  138. {
  139. Debug.LogError("Erorr parsing xml file!");
  140. }
  141. var documentNode = kmlNode["Document"];
  142. if (documentNode == null)
  143. {
  144. Debug.LogError("Erorr parsing xml file!");
  145. }
  146. var placemarkNodeList = documentNode.GetElementsByTagName("Placemark");
  147. for (var i = 0; i < placemarkNodeList.Count; i++)
  148. {
  149. var placemarkNode = placemarkNodeList[i];
  150. var name = placemarkNode["name"]?.Name;
  151. var lineStringNode = placemarkNode["LineString"];
  152. if (lineStringNode != null)
  153. {
  154. var coordinatesNode = lineStringNode["coordinates"];
  155. if (coordinatesNode != null)
  156. {
  157. // var txt = coordinatesNode.Value.TrimStart();
  158. var txt = coordinatesNode.InnerText.TrimStart().TrimEnd();
  159. var split = txt.Split(new char[] { ',', ' ' });
  160. foreach (var s in split)
  161. {
  162. Debug.Log($":{s}:");
  163. }
  164. var customRoute = ScriptableObject.CreateInstance<MapboxRoutes.CustomRoute>();
  165. customRoute.Points = new List<CustomRoute.Point>();
  166. for (var k = 0; k < split.Length; k += 3)
  167. {
  168. var lonString = split[k];
  169. var latString = split[k + 1];
  170. double lat, lon;
  171. if (!double.TryParse(lonString, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out lon))
  172. {
  173. Debug.LogError("Failed to parse float number");
  174. return;
  175. }
  176. if (!double.TryParse(latString, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out lat))
  177. {
  178. Debug.LogError("Failed to parse float number");
  179. return;
  180. }
  181. var location = new Location(lat, lon);
  182. var point = new MapboxRoutes.CustomRoute.Point();
  183. point.Location = location;
  184. customRoute.Points.Add(point);
  185. }
  186. customRoute.Points[0].IsStep = true;
  187. customRoute.Points[customRoute.Points.Count - 1].IsStep = true;
  188. var dirPath = System.IO.Path.GetDirectoryName(path);
  189. var baseName = System.IO.Path.GetFileNameWithoutExtension(path);
  190. var filename = System.IO.Path.Combine(dirPath, baseName + (placemarkNodeList.Count == 0 ? "": $"({i})") + ".asset");
  191. AssetDatabase.CreateAsset(customRoute, filename);
  192. }
  193. }
  194. }
  195. }
  196. [MenuItem("Assets/AR+GPS/Custom Route From KML", true)]
  197. private static bool KmlMenuClickValidator()
  198. {
  199. var path = AssetDatabase.GetAssetPath(Selection.activeObject);
  200. var ext = System.IO.Path.GetExtension(path);
  201. return ext.ToLower(System.Globalization.CultureInfo.InvariantCulture) == ".kml";
  202. }
  203. }
  204. }