using System.Collections.Generic; using WSMGameStudio.Splines; using UnityEngine; using UnityEditor; using UnityEngine.SceneManagement; using UnityEditor.SceneManagement; namespace WSMGameStudio.RailroadSystem { public class RouteEditingWindow : EditorWindow { private GUIStyle _menuBoxStyle; private GUIStyle _dragDropBoxStyle; private Color _lightYellow = new Color(1f, 0.95f, 0.7f); private static int _index; private static string _name; private static List _splines; private static RouteManager _routeManager; /// /// Show route editing window /// /// public static void ShowWindow(int routeIndex) { RouteEditingWindow currentWindow = GetWindow("Route Editing"); currentWindow.minSize = new Vector2(400, 160); currentWindow.maxSize = new Vector2(400, currentWindow.maxSize.y); _routeManager = FindObjectOfType(); _index = routeIndex; _name = _routeManager.Routes[_index].Name; _splines = new List(); foreach (var item in _routeManager.Routes[_index].Splines) { _splines.Add(item); } } void OnFocus() { // Remove delegate listener if it has previously been assigned. SceneView.duringSceneGui -= this.OnSceneViewGUI; // Add (or re-add) the delegate. SceneView.duringSceneGui += this.OnSceneViewGUI; } void OnDestroy() { // When the window is destroyed, remove the delegate so that it will no longer do any drawing. SceneView.duringSceneGui -= this.OnSceneViewGUI; } /// /// OnGUI /// private void OnGUI() { if (_routeManager == null) this.Close(); //Set up the box style if null if (_menuBoxStyle == null) { _menuBoxStyle = new GUIStyle(GUI.skin.box); _menuBoxStyle.normal.textColor = GUI.skin.label.normal.textColor; _menuBoxStyle.fontStyle = FontStyle.Bold; _menuBoxStyle.alignment = TextAnchor.UpperLeft; } GUILayout.BeginVertical(_menuBoxStyle); EditorGUILayout.LabelField("Route Index: " + _index, EditorStyles.boldLabel); _name = EditorGUILayout.TextField("Route Name", _name); _splines = _splines == null ? new List() : _splines; DropAreaGUI(); for (int i = 0; i < _splines.Count; i++) { GUILayout.BeginHorizontal(); _splines[i] = (Spline)EditorGUILayout.ObjectField(_splines[i], typeof(Spline), true); if (GUILayout.Button("▲", GUILayout.MaxWidth(30))) { if (i <= 0) return; Spline aux = _splines[i]; _splines[i] = _splines[i - 1]; _splines[i - 1] = aux; } if (GUILayout.Button("▼", GUILayout.MaxWidth(30))) { if (i >= _splines.Count - 1) return; Spline aux = _splines[i]; _splines[i] = _splines[i + 1]; _splines[i + 1] = aux; } if (GUILayout.Button("x", GUILayout.MaxWidth(30))) { _splines.RemoveAt(i); MarkSceneAlteration(); } GUILayout.EndHorizontal(); } GUILayout.BeginHorizontal(); if (GUILayout.Button("Save")) { _routeManager.Routes[_index].Name = _name; _routeManager.Routes[_index].Splines = _splines; MarkSceneAlteration(); this.Close(); } if (GUILayout.Button("Cancel")) { this.Close(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); } /// /// Drag & Drop objects on window /// public void DropAreaGUI() { if (_dragDropBoxStyle == null) { _dragDropBoxStyle = new GUIStyle(GUI.skin.box); _dragDropBoxStyle.normal.textColor = GUI.skin.label.normal.textColor; _dragDropBoxStyle.fontStyle = FontStyle.Bold; _dragDropBoxStyle.alignment = TextAnchor.MiddleCenter; } Event evt = Event.current; Rect drop_area = GUILayoutUtility.GetRect(0.0f, 30.0f, GUILayout.ExpandWidth(true)); Color originalBackgroundColor = GUI.backgroundColor; GUI.backgroundColor = _lightYellow; //Color.yellow; GUI.Box(drop_area, "Drag & Drop Splines Here", _dragDropBoxStyle); GUI.backgroundColor = originalBackgroundColor; switch (evt.type) { case EventType.DragUpdated: case EventType.DragPerform: if (!drop_area.Contains(evt.mousePosition)) return; DragAndDrop.visualMode = DragAndDropVisualMode.Copy; if (evt.type == EventType.DragPerform) { DragAndDrop.AcceptDrag(); foreach (Object dragged_object in DragAndDrop.objectReferences) { GameObject draggedGameObject = (GameObject)dragged_object; // Do On Drag Stuff here if (draggedGameObject == null) continue; Spline spline = draggedGameObject.GetComponent(); if (spline != null) _splines.Add(spline); } MarkSceneAlteration(); } GUIUtility.ExitGUI(); //Avoid GUI related errors break; } } private void OnSceneViewGUI(SceneView sceneView) { DrawSplinesOnSceneView(sceneView); } /// /// Draw Splines On Scene View /// /// private void DrawSplinesOnSceneView(SceneView sceneView) { if (_splines == null) return; if (_splines.Count == 0) return; Transform splineTransform; Vector3 startPoint, endPoint, tangent1, tangent2, splineStart = Vector3.zero, splineEnd = Vector3.zero; Vector3 startDirection, endDirection; Quaternion startRotation, endRotation; for (int splineIndex = 0; splineIndex < _splines.Count; splineIndex++) { if (_splines[splineIndex] == null) { Debug.LogWarning("Rote spline cannot be null. Please remove null references from route"); continue; } splineTransform = _splines[splineIndex].GetComponent(); for (int i = 0; i < _splines[splineIndex].ControlPointCount - 1; i += 3) { startPoint = splineTransform.TransformPoint(_splines[splineIndex].GetControlPointPosition(i)); tangent1 = splineTransform.TransformPoint(_splines[splineIndex].GetControlPointPosition(i + 1)); tangent2 = splineTransform.TransformPoint(_splines[splineIndex].GetControlPointPosition(i + 2)); endPoint = splineTransform.TransformPoint(_splines[splineIndex].GetControlPointPosition(i + 3)); Handles.DrawBezier(startPoint, endPoint, tangent1, tangent2, Color.magenta, null, 5f); splineStart = i == 0 ? startPoint : splineStart; splineEnd = endPoint; if (i != 0) { startDirection = splineTransform.InverseTransformDirection(_splines[splineIndex].GetDirection(startPoint, tangent1, tangent2, endPoint, 0f)); startRotation = Quaternion.FromToRotation(Vector3.forward, startDirection); DrawDirectionCone(startPoint, startRotation, Color.white, 3.5f); } } startDirection = _splines[splineIndex].GetDirection(0); endDirection = _splines[splineIndex].GetDirection(_splines[splineIndex].ControlPointCount - 1); startRotation = Quaternion.FromToRotation(Vector3.forward, startDirection); endRotation = Quaternion.FromToRotation(Vector3.forward, endDirection); DrawDirectionCone(splineStart, startRotation, Color.yellow, 5f); DrawDirectionCone(splineEnd, endRotation, Color.yellow, 5f); sceneView.Repaint(); } } /// /// Draw route direction cone /// /// /// /// /// private void DrawDirectionCone(Vector3 conePosition, Quaternion coneRotation, Color color, float coneSize) { float size = HandleUtility.GetHandleSize(conePosition) * coneSize; Color originalHandleColor = Handles.color; Handles.color = color; Handles.Button(conePosition, coneRotation, size * 0.04f, size * 0.06f, Handles.ConeHandleCap); Handles.color = originalHandleColor; } /// /// Mark Scene Alteration to save performed operations /// private void MarkSceneAlteration() { #if UNITY_EDITOR EditorUtility.SetDirty(_routeManager); EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene()); #endif } } }