namespace Dreamteck.Splines.Editor { using UnityEngine; using System.Collections; using UnityEditor; using System.Collections.Generic; public class PointModule : EditorModule { protected bool isClosed { get { return editor.GetSplineClosed(); } } protected int sampleRate { get { return editor.GetSplineSampleRate(); } } protected Spline.Type splineType { get { return editor.GetSplineType(); } } protected Color color { get { return editor.drawColor; } } protected SplineEditor editor; protected SerializedSplinePoint[] points { get { return editor.points; } set { editor.points = value; } } protected List selectedPoints { get { return editor.selectedPoints; } set { editor.selectedPoints = value; } } public Vector3 center { get { Vector3 avg = Vector3.zero; if (points.Length == 0) return avg; for (int i = 0; i < points.Length; i++) avg += points[i].position; return avg / points.Length; } } public Vector3 selectionCenter { get { Vector3 avg = Vector3.zero; if (selectedPoints.Count == 0) return avg; for (int i = 0; i < selectedPoints.Count; i++) avg += points[selectedPoints[i]].position; return avg / selectedPoints.Count; } } protected EditorGUIEvents eventModule; public delegate void UndoHandler(string title); public delegate void EmptyHandler(); public delegate void IntHandler(int value); public delegate void IntArrayHandler(int[] values); public Spline.Direction duplicationDirection = Spline.Direction.Forward; public Color highlightColor = Color.white; public bool showPointNumbers = false; public event EmptyHandler onBeforeDeleteSelectedPoints; public event EmptyHandler onSelectionChanged; public event IntArrayHandler onDuplicatePoint; private bool movePivot = false; private Vector3 idealPivot = Vector3.zero; public PointModule(SplineEditor editor) { this.editor = editor; eventModule = editor.eventModule; } protected override void RecordUndo(string title) { if (editor.undoHandler != null) editor.undoHandler(title); } protected override void Repaint() { if (editor.repaintHandler != null) editor.repaintHandler(); } public override void BeforeSceneDraw(SceneView current) { base.BeforeSceneDraw(current); Event e = Event.current; if (movePivot) { SceneView.lastActiveSceneView.pivot = Vector3.Lerp(SceneView.lastActiveSceneView.pivot, idealPivot, 0.02f); if (e.type == EventType.MouseDown || e.type == EventType.MouseUp) movePivot = false; if (Vector3.Distance(SceneView.lastActiveSceneView.pivot, idealPivot) <= 0.05f) { SceneView.lastActiveSceneView.pivot = idealPivot; movePivot = false; } } if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Delete && HasSelection()) { DeleteSelectedPoints(); e.Use(); } if(e.type == EventType.ExecuteCommand && Tools.current == Tool.None) { switch (e.commandName) { case "FrameSelected": if (points.Length > 0) { e.commandName = ""; FramePoints(); e.Use(); } break; case "SelectAll": e.commandName = ""; ClearSelection(); for (int i = 0; i < points.Length; i++) { AddPointSelection(i); } e.Use(); break; case "Duplicate": if (points.Length > 0 && selectedPoints.Count > 0) { e.commandName = ""; DuplicateSelected(); e.Use(); } break; } } } public virtual void DuplicateSelected() { if (selectedPoints.Count == 0) return; SplinePoint[] newPoints = new SplinePoint[points.Length + selectedPoints.Count]; SplinePoint[] duplicated = new SplinePoint[selectedPoints.Count]; editor.SetPointsCount(newPoints.Length); int index = 0; for (int i = 0; i < selectedPoints.Count; i++) duplicated[index++] = points[selectedPoints[i]].CreateSplinePoint(); int min = points.Length - 1, max = 0; for (int i = 0; i < selectedPoints.Count; i++) { if (selectedPoints[i] < min) min = selectedPoints[i]; if (selectedPoints[i] > max) max = selectedPoints[i]; } int[] selected = selectedPoints.ToArray(); selectedPoints.Clear(); if (duplicationDirection == Spline.Direction.Backward) { for (int i = 0; i < min; i++) newPoints[i] = points[i].CreateSplinePoint(); for (int i = 0; i < duplicated.Length; i++) { newPoints[i + min] = duplicated[i]; selectedPoints.Add(i + min); } for (int i = min; i < points.Length; i++) newPoints[i + duplicated.Length] = points[i].CreateSplinePoint(); } else { for (int i = 0; i <= max; i++) newPoints[i] = points[i].CreateSplinePoint(); for (int i = 0; i < duplicated.Length; i++) { newPoints[i + max + 1] = duplicated[i]; selectedPoints.Add(i + max + 1); } for (int i = max + 1; i < points.Length; i++) newPoints[i + duplicated.Length] = points[i].CreateSplinePoint(); } editor.SetPointsArray(newPoints); RegisterChange(); if (onDuplicatePoint != null) onDuplicatePoint(selected); } public virtual void Reset() { } public bool HasSelection() { return selectedPoints.Count > 0; } public void ClearSelection() { selectedPoints.Clear(); Repaint(); if (editor.selectionChangeHandler != null) editor.selectionChangeHandler(); if (onSelectionChanged != null) onSelectionChanged(); } protected void DeleteSelectedPoints() { if (onBeforeDeleteSelectedPoints != null) { onBeforeDeleteSelectedPoints(); } for (int i = 0; i < selectedPoints.Count; i++) { DeletePoint(selectedPoints[i]); for (int n = i; n < selectedPoints.Count; n++) { selectedPoints[n]--; } } ClearSelection(); RegisterChange(); editor.ApplyModifiedProperties(true); } protected void DeletePoint(int index) { editor.DeletePoint(index); RegisterChange(); } public void InverseSelection() { List inverse = new List(); for (int i = 0; i < (isClosed ? points.Length - 1 : points.Length); i++) { bool found = false; for (int j = 0; j < selectedPoints.Count; j++) { if (selectedPoints[j] == i) { found = true; break; } } if (!found) inverse.Add(i); } selectedPoints = new List(inverse); Repaint(); if (editor.selectionChangeHandler != null) editor.selectionChangeHandler(); if (onSelectionChanged != null) onSelectionChanged(); } protected void SelectPoint(int index) { if (selectedPoints.Count == 1 && selectedPoints[0] == index) return; selectedPoints.Clear(); selectedPoints.Add(index); Repaint(); if (editor.selectionChangeHandler != null) editor.selectionChangeHandler(); if (onSelectionChanged != null) onSelectionChanged(); } protected void DeselectPoint(int index) { if (selectedPoints.Contains(index)) { selectedPoints.Remove(index); Repaint(); if (editor.selectionChangeHandler != null) editor.selectionChangeHandler(); if (onSelectionChanged != null) onSelectionChanged(); } } protected void SelectPoints(List indices) { selectedPoints.Clear(); for (int i = 0; i < indices.Count; i++) { selectedPoints.Add(indices[i]); } Repaint(); if (editor.selectionChangeHandler != null) editor.selectionChangeHandler(); if (onSelectionChanged != null) onSelectionChanged(); } protected void AddPointSelection(int index) { if (selectedPoints.Contains(index)) return; selectedPoints.Add(index); Repaint(); if (editor.selectionChangeHandler != null) editor.selectionChangeHandler(); if (onSelectionChanged != null) onSelectionChanged(); } protected void FramePoints() { if (points.Length == 0) return; Vector3 center = Vector3.zero; Camera camera = SceneView.lastActiveSceneView.camera; Transform cam = camera.transform; Vector3 min = Vector3.zero, max = Vector3.zero; if (HasSelection()) { for (int i = 0; i < selectedPoints.Count; i++) { center += points[selectedPoints[i]].position; Vector3 local = cam.InverseTransformPoint(points[selectedPoints[i]].position); if (local.x < min.x) min.x = local.x; if (local.y < min.y) min.y = local.y; if (local.z < min.z) min.z = local.z; if (local.x > max.x) max.x = local.x; if (local.y > max.y) max.y = local.y; if (local.z > max.z) max.z = local.z; } center /= selectedPoints.Count; } else { for (int i = 0; i < points.Length; i++) { center += points[i].position; Vector3 local = cam.InverseTransformPoint(points[i].position); if (local.x < min.x) min.x = local.x; if (local.y < min.y) min.y = local.y; if (local.z < min.z) min.z = local.z; if (local.x > max.x) max.x = local.x; if (local.y > max.y) max.y = local.y; if (local.z > max.z) max.z = local.z; } center /= points.Length; } movePivot = true; idealPivot = center; } } }