using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using ICSharpCode.NRefactory.PrettyPrinter; using Roads; using Routes; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.UI; using Object = UnityEngine.Object; [CustomEditor(typeof(Route))] [CanEditMultipleObjects] // ReSharper disable once CheckNamespace public class RoutesEditor : UnityEditor.Editor { private bool showListContent; private bool inSelectionMode; private SceneView sceneView; private readonly List selectedTurns = new List(); private Route route; private static float length = 0; private static readonly Dictionary roadDirectionIndexes = new Dictionary { {RoadDirection.West, 0}, {RoadDirection.North, 1}, {RoadDirection.East, 2}, {RoadDirection.South, 3}, {RoadDirection.None, 4} }; public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(serializedObject.FindProperty("start")); EditorGUILayout.PropertyField(serializedObject.FindProperty("finish")); RoutesList(serializedObject.FindProperty("items")); EditorGUILayout.LabelField($"Current length: {length}"); //EditorGUILayout.PropertyField(routes.FindPropertyRelative("arraySize"), true);true); serializedObject.ApplyModifiedProperties(); } private void OnEnable() { route = (Route) target; } private void OnSceneGUI() { if (inSelectionMode) { if (Event.current.type == EventType.Layout) { HandleUtility.AddDefaultControl(0); } sceneView = SceneView.currentDrawingSceneView; if (sceneView == null) { Debug.LogError("RouteEditor: No Scene View found"); } if (sceneView != null && Event.current.type == EventType.MouseDown && Event.current.button == 0) { /*var coords = Event.current.mousePosition; var pos = sceneView.camera.ScreenToWorldPoint(new Vector3(coords.x, coords.y, sceneView.camera.nearClipPlane)); Debug.Log("pos: "+pos); Debug.DrawRay(pos, Vector3.down * 1000, Color.magenta);*/ Ray worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); RaycastHit hitInfo; if (Physics.Raycast(worldRay, out hitInfo)) { var intersection = GetIntersection(hitInfo.collider.gameObject); selectedTurns.Add(intersection); } } } if (GUI.changed) EditorUtility.SetDirty(target); } private Turn GetIntersection(GameObject gameObject) { Turn turn = null; for (var i = 0; i < 3; i++) { turn = gameObject.GetComponent(); if (turn != null || gameObject.transform.parent == null) break; gameObject = gameObject.transform.parent.gameObject; } Debug.Log($"Intersected Turn: {turn}"); return turn; } private void RoutesList(SerializedProperty list) { showListContent = EditorGUILayout.BeginFoldoutHeaderGroup(showListContent, $"{list.displayName} (Length = {list.arraySize})"); if (showListContent) { EditorGUI.indentLevel += 1; EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(list.FindPropertyRelative("Array.size")); if (GUILayout.Button("+", EditorStyles.miniButton, GUILayout.Width(32))) { list.InsertArrayElementAtIndex(list.arraySize); } if (GUILayout.Button(!inSelectionMode ? "Selection Mode" : "Quit Selection Mode", GUILayout.Width(128))) { SwitchSelectionMode(); } if (GUILayout.Button("Clear", GUILayout.Width(56))) { Clear(); } GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); for (var i = 0; i < list.arraySize; i++) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i), true); if (GUILayout.Button("-", EditorStyles.miniButton, GUILayout.Width(32))) { list.DeleteArrayElementAtIndex(i); } EditorGUILayout.EndHorizontal(); } EditorGUI.indentLevel -= 1; } EditorGUILayout.EndFoldoutHeaderGroup(); } private void Clear() { var items = serializedObject.FindProperty("items"); items.ClearArray(); } private void SwitchSelectionMode() { inSelectionMode = !inSelectionMode; if (inSelectionMode) { selectedTurns.Clear(); } else { ApplySelectedTurns(); } } private void ApplySelectedTurns() { var items = serializedObject.FindProperty("items"); var size = items.arraySize; SerializedProperty previousItem = null; for (var index = 0; index < selectedTurns.Count; index++) { var serializedIndex = size + index; var turn = selectedTurns[index]; var previousTurn = index == 0 ? null : selectedTurns[index - 1]; items.InsertArrayElementAtIndex(serializedIndex); var newItem = items.GetArrayElementAtIndex(serializedIndex); newItem.FindPropertyRelative("turn").objectReferenceValue = turn; Debug.Log($"---- Element {serializedIndex} ----"); Debug.Log("Calculate From"); newItem.FindPropertyRelative("from").enumValueIndex = CalculateDirection(turn.transform, previousTurn != null ? previousTurn.transform : null); newItem.FindPropertyRelative("to").enumValueIndex = roadDirectionIndexes[RoadDirection.None]; if (previousItem != null) { Debug.Log("Calculate Previous To"); previousItem.FindPropertyRelative("to").enumValueIndex = CalculateDirection(previousTurn != null ? previousTurn.transform : null, turn.transform); } previousItem = newItem; } selectedTurns.Clear(); } private int CalculateDirection(Transform turnTransform, Transform reference) { if (reference == null) return roadDirectionIndexes[RoadDirection.None]; var dif = reference.position - turnTransform.position; Debug.Log("Difference to reference = " + dif); RoadDirection direction; if (Mathf.Abs(dif.x) > Mathf.Abs(dif.z)) { direction = dif.x < 0 ? RoadDirection.West : RoadDirection.East; } else { direction = dif.z < 0 ? RoadDirection.South : RoadDirection.North; } return roadDirectionIndexes[direction]; } [DrawGizmo(GizmoType.Selected)] private static void DrawRoutePreview(Route route, GizmoType gizmoType) { length = 0f; // a bit hacky but who cares if (route.items == null) return; Gizmos.color = Color.red; Turn previousTurn = null; Vector3 from; Vector3 to; if (route.start != null && route.items.Count > 0) { from = route.start.transform.position; to = route.items[0].turn.transform.position; length += (to - from).magnitude; Helpers.DrawLine(from, to, 3); } foreach (var item in route.items) { var turn = item.turn; if (previousTurn != null) { from = previousTurn.transform.position; to = turn.transform.position; length += (to - from).magnitude; Helpers.DrawLine(from, to, 3); } previousTurn = turn; } if (route.finish != null && route.items.Count > 0) { from = route.items.Last().turn.transform.position; to = route.finish.transform.position; length += (to - from).magnitude; Helpers.DrawLine(from, to, 3); } } }