345 lines
12 KiB
C#
345 lines
12 KiB
C#
|
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<int> 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<int> inverse = new List<int>();
|
||
|
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<int>(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<int> 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|