RouteEditor.cs 8.3 KB

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