RouteEditor.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using ICSharpCode.NRefactory.PrettyPrinter;
  6. using Roads;
  7. using Routes;
  8. using UnityEditor;
  9. using UnityEngine;
  10. using UnityEngine.Rendering;
  11. using UnityEngine.Rendering.UI;
  12. using Object = UnityEngine.Object;
  13. [CustomEditor(typeof(Route))]
  14. [CanEditMultipleObjects]
  15. // ReSharper disable once CheckNamespace
  16. public class RoutesEditor : UnityEditor.Editor
  17. {
  18. private bool showListContent;
  19. private bool inSelectionMode;
  20. private SceneView sceneView;
  21. private readonly List<Turn> selectedTurns = new List<Turn>();
  22. private Route route;
  23. private static float length = 0;
  24. private static readonly Dictionary<RoadDirection, int> roadDirectionIndexes = new Dictionary<RoadDirection, int>
  25. {
  26. {RoadDirection.West, 0},
  27. {RoadDirection.North, 1},
  28. {RoadDirection.East, 2},
  29. {RoadDirection.South, 3},
  30. {RoadDirection.None, 4}
  31. };
  32. public override void OnInspectorGUI()
  33. {
  34. serializedObject.Update();
  35. EditorGUILayout.PropertyField(serializedObject.FindProperty("start"));
  36. EditorGUILayout.PropertyField(serializedObject.FindProperty("finish"));
  37. EditorGUILayout.PropertyField(serializedObject.FindProperty("customStart"));
  38. RoutesList(serializedObject.FindProperty("items"));
  39. EditorGUILayout.LabelField($"Current length: {length}");
  40. //EditorGUILayout.PropertyField(routes.FindPropertyRelative("arraySize"), true);true);
  41. serializedObject.ApplyModifiedProperties();
  42. }
  43. private void OnEnable()
  44. {
  45. route = (Route) target;
  46. }
  47. private void OnSceneGUI()
  48. {
  49. if (inSelectionMode)
  50. {
  51. if (Event.current.type == EventType.Layout)
  52. {
  53. HandleUtility.AddDefaultControl(0);
  54. }
  55. sceneView = SceneView.currentDrawingSceneView;
  56. if (sceneView == null)
  57. {
  58. Debug.LogError("RouteEditor: No Scene View found");
  59. }
  60. if (sceneView != null && Event.current.type == EventType.MouseDown && Event.current.button == 0)
  61. {
  62. /*var coords = Event.current.mousePosition;
  63. var pos = sceneView.camera.ScreenToWorldPoint(new Vector3(coords.x, coords.y, sceneView.camera.nearClipPlane));
  64. Debug.Log("pos: "+pos);
  65. Debug.DrawRay(pos, Vector3.down * 1000, Color.magenta);*/
  66. Ray worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
  67. RaycastHit hitInfo;
  68. if (Physics.Raycast(worldRay, out hitInfo))
  69. {
  70. var intersection = GetIntersection(hitInfo.collider.gameObject);
  71. selectedTurns.Add(intersection);
  72. }
  73. }
  74. }
  75. if (GUI.changed)
  76. EditorUtility.SetDirty(target);
  77. }
  78. private Turn GetIntersection(GameObject gameObject)
  79. {
  80. Turn turn = null;
  81. for (var i = 0; i < 3; i++)
  82. {
  83. turn = gameObject.GetComponent<Turn>();
  84. if (turn != null || gameObject.transform.parent == null) break;
  85. gameObject = gameObject.transform.parent.gameObject;
  86. }
  87. Debug.Log($"Intersected Turn: {turn}");
  88. return turn;
  89. }
  90. private void RoutesList(SerializedProperty list)
  91. {
  92. showListContent =
  93. EditorGUILayout.BeginFoldoutHeaderGroup(showListContent, $"{list.displayName} (Length = {list.arraySize})");
  94. if (showListContent)
  95. {
  96. EditorGUI.indentLevel += 1;
  97. EditorGUILayout.BeginHorizontal();
  98. EditorGUILayout.PropertyField(list.FindPropertyRelative("Array.size"));
  99. if (GUILayout.Button("+", EditorStyles.miniButton, GUILayout.Width(32)))
  100. {
  101. list.InsertArrayElementAtIndex(list.arraySize);
  102. }
  103. if (GUILayout.Button(!inSelectionMode ? "Selection Mode" : "Quit Selection Mode", GUILayout.Width(128)))
  104. {
  105. SwitchSelectionMode();
  106. }
  107. if (GUILayout.Button("Clear", GUILayout.Width(56)))
  108. {
  109. Clear();
  110. }
  111. GUILayout.FlexibleSpace();
  112. EditorGUILayout.EndHorizontal();
  113. for (var i = 0; i < list.arraySize; i++)
  114. {
  115. EditorGUILayout.BeginHorizontal();
  116. EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i), true);
  117. if (GUILayout.Button("-", EditorStyles.miniButton, GUILayout.Width(32)))
  118. {
  119. list.DeleteArrayElementAtIndex(i);
  120. }
  121. EditorGUILayout.EndHorizontal();
  122. }
  123. EditorGUI.indentLevel -= 1;
  124. }
  125. EditorGUILayout.EndFoldoutHeaderGroup();
  126. }
  127. private void Clear()
  128. {
  129. var items = serializedObject.FindProperty("items");
  130. items.ClearArray();
  131. }
  132. private void SwitchSelectionMode()
  133. {
  134. inSelectionMode = !inSelectionMode;
  135. if (inSelectionMode)
  136. {
  137. selectedTurns.Clear();
  138. }
  139. else
  140. {
  141. ApplySelectedTurns();
  142. }
  143. }
  144. private void ApplySelectedTurns()
  145. {
  146. var items = serializedObject.FindProperty("items");
  147. var size = items.arraySize;
  148. SerializedProperty previousItem = null;
  149. for (var index = 0; index < selectedTurns.Count; index++)
  150. {
  151. var serializedIndex = size + index;
  152. var turn = selectedTurns[index];
  153. var previousTurn = index == 0 ? null : selectedTurns[index - 1];
  154. items.InsertArrayElementAtIndex(serializedIndex);
  155. var newItem = items.GetArrayElementAtIndex(serializedIndex);
  156. newItem.FindPropertyRelative("turn").objectReferenceValue = turn;
  157. Debug.Log($"---- Element {serializedIndex} ----");
  158. Debug.Log("Calculate From");
  159. newItem.FindPropertyRelative("from").enumValueIndex = CalculateDirection(turn.transform,
  160. previousTurn != null ? previousTurn.transform : null);
  161. newItem.FindPropertyRelative("to").enumValueIndex = roadDirectionIndexes[RoadDirection.None];
  162. if (previousItem != null)
  163. {
  164. Debug.Log("Calculate Previous To");
  165. previousItem.FindPropertyRelative("to").enumValueIndex =
  166. CalculateDirection(previousTurn != null ? previousTurn.transform : null, turn.transform);
  167. }
  168. previousItem = newItem;
  169. }
  170. selectedTurns.Clear();
  171. }
  172. private int CalculateDirection(Transform turnTransform, Transform reference)
  173. {
  174. if (reference == null) return roadDirectionIndexes[RoadDirection.None];
  175. var dif = reference.position - turnTransform.position;
  176. Debug.Log("Difference to reference = " + dif);
  177. RoadDirection direction;
  178. if (Mathf.Abs(dif.x) > Mathf.Abs(dif.z))
  179. {
  180. direction = dif.x < 0 ? RoadDirection.West : RoadDirection.East;
  181. }
  182. else
  183. {
  184. direction = dif.z < 0 ? RoadDirection.South : RoadDirection.North;
  185. }
  186. return roadDirectionIndexes[direction];
  187. }
  188. [DrawGizmo(GizmoType.Selected)]
  189. private static void DrawRoutePreview(Route route, GizmoType gizmoType)
  190. {
  191. length = 0f; // a bit hacky but who cares
  192. if (route.items == null) return;
  193. Gizmos.color = Color.red;
  194. Turn previousTurn = null;
  195. Vector3 from;
  196. Vector3 to;
  197. if (route.start != null && route.items.Count > 0)
  198. {
  199. from = route.start.transform.position;
  200. to = route.items[0].turn.transform.position;
  201. length += (to - from).magnitude;
  202. Helpers.DrawLine(from, to, 3);
  203. }
  204. foreach (var item in route.items)
  205. {
  206. var turn = item.turn;
  207. if (previousTurn != null)
  208. {
  209. from = previousTurn.transform.position;
  210. to = turn.transform.position;
  211. length += (to - from).magnitude;
  212. Helpers.DrawLine(from, to, 3);
  213. }
  214. previousTurn = turn;
  215. }
  216. if (route.finish != null && route.items.Count > 0)
  217. {
  218. from = route.items.Last().turn.transform.position;
  219. to = route.finish.transform.position;
  220. length += (to - from).magnitude;
  221. Helpers.DrawLine(from, to, 3);
  222. }
  223. }
  224. }