This commit is contained in:
SoulliesOfficial
2025-06-06 10:14:55 -04:00
parent d4e860fa16
commit db4d131192
1088 changed files with 45704 additions and 2260 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 671f4a431b4054141ac528dc52c4772e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,590 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class ComputerEditor : SplineEditorBase
{
public bool drawComputer = true;
public bool drawPivot = true;
public bool drawConnectedComputers = true;
private DreamteckSplinesEditor _pathEditor;
private int _operation = -1, _module = -1, _transformTool = 1;
private ComputerEditorModule[] _modules = new ComputerEditorModule[0];
private Dreamteck.Editor.Toolbar _utilityToolbar;
private Dreamteck.Editor.Toolbar _operationsToolbar;
private Dreamteck.Editor.Toolbar _transformToolbar;
private SplineComputer _spline = null;
private SplineComputer[] _splines = new SplineComputer[0];
private bool _pathToolsFoldout = false, _interpolationFoldout = false;
private SerializedProperty _splineProperty;
private SerializedProperty _sampleRate;
private SerializedProperty _type;
private SerializedProperty _knotParametrization;
private SerializedProperty _linearAverageDirection;
private SerializedProperty _space;
private SerializedProperty _sampleMode;
private SerializedProperty _optimizeAngleThreshold;
private SerializedProperty _updateMode;
private SerializedProperty _multithreaded;
private SerializedProperty _customNormalInterpolation;
private SerializedProperty _customValueInterpolation;
public ComputerEditor(SplineComputer[] splines, SerializedObject serializedObject, DreamteckSplinesEditor pathEditor) : base(serializedObject)
{
_spline = splines[0];
this._splines = splines;
this._pathEditor = pathEditor;
_splineProperty = serializedObject.FindProperty("_spline");
_sampleRate = serializedObject.FindProperty("_spline").FindPropertyRelative("sampleRate");
_type = serializedObject.FindProperty("_spline").FindPropertyRelative("type");
_linearAverageDirection = _splineProperty.FindPropertyRelative("linearAverageDirection");
_space = serializedObject.FindProperty("_space");
_sampleMode = serializedObject.FindProperty("_sampleMode");
_optimizeAngleThreshold = serializedObject.FindProperty("_optimizeAngleThreshold");
_updateMode = serializedObject.FindProperty("updateMode");
_multithreaded = serializedObject.FindProperty("multithreaded");
_customNormalInterpolation = _splineProperty.FindPropertyRelative("customNormalInterpolation");
_customValueInterpolation = _splineProperty.FindPropertyRelative("customValueInterpolation");
_knotParametrization = _splineProperty.FindPropertyRelative("_knotParametrization");
_modules = new ComputerEditorModule[2];
_modules[0] = new ComputerMergeModule(_spline);
_modules[1] = new ComputerSplitModule(_spline);
GUIContent[] utilityContents = new GUIContent[_modules.Length], utilityContentsSelected = new GUIContent[_modules.Length];
for (int i = 0; i < _modules.Length; i++)
{
utilityContents[i] = _modules[i].GetIconOff();
utilityContentsSelected[i] = _modules[i].GetIconOn();
_modules[i].undoHandler += OnRecordUndo;
_modules[i].repaintHandler += OnRepaint;
}
_utilityToolbar = new Dreamteck.Editor.Toolbar(utilityContents, utilityContentsSelected, 35f);
_utilityToolbar.newLine = false;
int index = 0;
GUIContent[] transformContents = new GUIContent[4], transformContentsSelected = new GUIContent[4];
transformContents[index] = new GUIContent("OFF");
transformContentsSelected[index++] = new GUIContent("OFF");
transformContents[index] = EditorGUIUtility.IconContent("MoveTool");
transformContentsSelected[index++] = EditorGUIUtility.IconContent("MoveTool On");
transformContents[index] = EditorGUIUtility.IconContent("RotateTool");
transformContentsSelected[index++] = EditorGUIUtility.IconContent("RotateTool On");
transformContents[index] = EditorGUIUtility.IconContent("ScaleTool");
transformContentsSelected[index] = EditorGUIUtility.IconContent("ScaleTool On");
_transformToolbar = new Dreamteck.Editor.Toolbar(transformContents, transformContentsSelected, 35f);
_transformToolbar.newLine = false;
index = 0;
GUIContent[] operationContents = new GUIContent[3], operationContentsSelected = new GUIContent[3];
for (int i = 0; i < operationContents.Length; i++)
{
operationContents[i] = new GUIContent("");
operationContentsSelected[i] = new GUIContent("");
}
_operationsToolbar = new Dreamteck.Editor.Toolbar(operationContents, operationContentsSelected, 64f);
_operationsToolbar.newLine = false;
}
void OnRecordUndo(string title)
{
if (undoHandler != null) undoHandler(title);
}
void OnRepaint()
{
if (repaintHandler != null) repaintHandler();
}
protected override void Load()
{
base.Load();
_pathToolsFoldout = LoadBool("DreamteckSplinesEditor.pathToolsFoldout", false);
_interpolationFoldout = LoadBool("DreamteckSplinesEditor.interpolationFoldout", false);
_transformTool = LoadInt("DreamteckSplinesEditor.transformTool", 0);
}
protected override void Save()
{
base.Save();
SaveBool("DreamteckSplinesEditor.pathToolsFoldout", _pathToolsFoldout);
SaveBool("DreamteckSplinesEditor.interpolationFoldout", _interpolationFoldout);
SaveInt("DreamteckSplinesEditor.transformTool", _transformTool);
}
public override void Destroy()
{
base.Destroy();
for (int i = 0; i < _modules.Length; i++) _modules[i].Deselect();
}
public override void DrawInspector()
{
base.DrawInspector();
if (_spline == null) return;
SplineEditorGUI.SetHighlightColors(SplinePrefs.highlightColor, SplinePrefs.highlightContentColor);
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
EditorGUI.BeginChangeCheck();
_operationsToolbar.SetContent(0, new GUIContent(_spline.isClosed ? "Break" : "Close"));
_operationsToolbar.SetContent(1, new GUIContent("Reverse"));
_operationsToolbar.SetContent(2, new GUIContent(_spline.is2D ? "3D Mode" : "2D Mode"));
_operationsToolbar.Draw(ref _operation);
if (EditorGUI.EndChangeCheck())
{
PerformOperation();
}
EditorGUI.BeginChangeCheck();
if (_splines.Length == 1)
{
int mod = _module;
_utilityToolbar.Draw(ref mod);
if (EditorGUI.EndChangeCheck())
{
ToggleModule(mod);
}
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
if (_module >= 0 && _module < _modules.Length)
{
_modules[_module].DrawInspector();
}
EditorGUILayout.Space();
DreamteckEditorGUI.DrawSeparator();
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
Spline.Type lastType = (Spline.Type)_type.intValue;
EditorGUILayout.PropertyField(_type);
if(lastType == Spline.Type.CatmullRom && _type.intValue == (int)Spline.Type.Bezier)
{
if(EditorUtility.DisplayDialog("Hermite to Bezier", "Would you like to retain the Catmull Rom shape in Bezier mode?", "Yes", "No"))
{
for (int i = 0; i < _splines.Length; i++)
{
Undo.RecordObject(_splines[i], "CatToBezierTangents");
_splines[i].CatToBezierTangents();
EditorUtility.SetDirty(_splines[i]);
}
_pathEditor.SetPointsArray(_spline.GetPoints());
_pathEditor.ApplyModifiedProperties();
}
}
if(_spline.type == Spline.Type.CatmullRom)
{
int type = Mathf.RoundToInt(_knotParametrization.floatValue * 2);
string catmullTypeText = "Parametrization: ";
switch (type)
{
case 0: catmullTypeText += "Uniform"; break;
case 1: catmullTypeText += "Centripetal"; break;
case 2: catmullTypeText += "Chordal"; break;
}
EditorGUILayout.PropertyField(_knotParametrization, new GUIContent(catmullTypeText));
}
if (_spline.type == Spline.Type.Linear)
{
EditorGUILayout.PropertyField(_linearAverageDirection);
}
int lastSpace = _space.intValue;
EditorGUILayout.Space();
EditorGUILayout.PropertyField(_space, new GUIContent("Space"));
if((SplineComputer.Space)_space.enumValueIndex == SplineComputer.Space.Local)
{
EditTransformToolbar();
if (_splines.Length == 1)
{
EditorGUILayout.Space();
}
}
EditorGUILayout.PropertyField(_sampleMode, new GUIContent("Sample Mode"));
if (_sampleMode.intValue == (int)SplineComputer.SampleMode.Optimized) EditorGUILayout.PropertyField(_optimizeAngleThreshold);
EditorGUILayout.PropertyField(_updateMode);
if (_updateMode.intValue == (int)SplineComputer.UpdateMode.None && Application.isPlaying)
{
if (GUILayout.Button("Rebuild"))
{
for (int i = 0; i < _splines.Length; i++) _splines[i].RebuildImmediate(true, true);
}
}
if (_spline.type != Spline.Type.Linear) EditorGUILayout.PropertyField(_sampleRate, new GUIContent("Sample Rate"));
EditorGUILayout.PropertyField(_multithreaded);
EditorGUI.indentLevel++;
bool curveUpdate = false;
_interpolationFoldout = EditorGUILayout.Foldout(_interpolationFoldout, "Point Value Interpolation");
if (_interpolationFoldout)
{
if (_customValueInterpolation.animationCurveValue == null || _customValueInterpolation.animationCurveValue.keys.Length == 0)
{
if (GUILayout.Button("Size & Color Interpolation"))
{
AnimationCurve curve = new AnimationCurve();
curve.AddKey(new Keyframe(0, 0, 0, 0));
curve.AddKey(new Keyframe(1, 1, 0, 0));
for (int i = 0; i < _splines.Length; i++) _splines[i].customValueInterpolation = curve;
_serializedObject.Update();
_pathEditor.GetPointsFromSpline();
curveUpdate = true;
}
}
else
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(_customValueInterpolation, new GUIContent("Size & Color Interpolation"));
if (GUILayout.Button("x", GUILayout.MaxWidth(25)))
{
_customValueInterpolation.animationCurveValue = null;
for (int i = 0; i < _splines.Length; i++) _splines[i].customValueInterpolation = null;
_serializedObject.Update();
_pathEditor.GetPointsFromSpline();
curveUpdate = true;
}
EditorGUILayout.EndHorizontal();
}
if (_customNormalInterpolation.animationCurveValue == null || _customNormalInterpolation.animationCurveValue.keys.Length == 0)
{
if (GUILayout.Button("Normal Interpolation"))
{
AnimationCurve curve = new AnimationCurve();
curve.AddKey(new Keyframe(0, 0));
curve.AddKey(new Keyframe(1, 1));
for (int i = 0; i < _splines.Length; i++) _splines[i].customNormalInterpolation = curve;
_serializedObject.Update();
_pathEditor.GetPointsFromSpline();
curveUpdate = true;
}
}
else
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(_customNormalInterpolation, new GUIContent("Normal Interpolation"));
if (GUILayout.Button("x", GUILayout.MaxWidth(25)))
{
_customNormalInterpolation.animationCurveValue = null;
for (int i = 0; i < _splines.Length; i++) _splines[i].customNormalInterpolation = null;
_serializedObject.Update();
_pathEditor.GetPointsFromSpline();
curveUpdate = true;
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUI.indentLevel--;
if (EditorGUI.EndChangeCheck() || curveUpdate)
{
if (_sampleRate.intValue < 2)
{
_sampleRate.intValue = 2;
}
bool forceUpdateAll = false;
if (lastSpace != _space.intValue)
{
forceUpdateAll = true;
}
_pathEditor.ApplyModifiedProperties(true);
for (int i = 1; i < _splines.Length; i++)
{
_splines[i].RebuildImmediate(true, forceUpdateAll);
}
}
if (_pathEditor.currentModule != null)
{
_transformTool = 0;
}
}
private void EditTransformToolbar()
{
if(_splines.Length > 1)
{
GUILayout.Label("Edit Transform unavailable with multiple splines");
return;
}
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Edit Transform - Only");
GUILayout.FlexibleSpace();
int lastTool = _transformTool;
_transformToolbar.Draw(ref _transformTool);
if (lastTool != _transformTool && _transformTool > 0)
{
_pathEditor.UntoggleCurrentModule();
Tools.current = Tool.None;
}
EditorGUILayout.EndHorizontal();
switch (_transformTool)
{
case 1:
Vector3 position = _spline.transform.position;
position = EditorGUILayout.Vector3Field("Position", position);
if (position != _spline.transform.position)
{
Undo.RecordObject(_spline.transform, "Move spline computer");
_spline.transform.position = position;
_pathEditor.ApplyModifiedProperties(true);
}
break;
case 2:
Quaternion rotation = _spline.transform.rotation;
rotation = Quaternion.Euler(EditorGUILayout.Vector3Field("Rotation", rotation.eulerAngles));
if (rotation != _spline.transform.rotation)
{
Undo.RecordObject(_spline.transform, "Rotate spline computer");
_spline.transform.rotation = rotation;
_pathEditor.ApplyModifiedProperties(true);
}
break;
case 3:
Vector3 scale = _spline.transform.localScale;
scale = EditorGUILayout.Vector3Field("Scale", scale);
if (scale != _spline.transform.localScale)
{
Undo.RecordObject(_spline.transform, "Scale spline computer");
_spline.transform.localScale = scale;
_pathEditor.ApplyModifiedProperties(true);
}
break;
}
}
void PerformOperation()
{
switch (_operation)
{
case 0:
if (_spline.isClosed)
{
BreakSpline();
}
else
{
CloseSpline();
}
_operation = -1;
break;
case 1:
ReversePointOrder();
_operation = -1;
break;
case 2:
{
_pathEditor.is2D = !_pathEditor.is2D;
if (_pathEditor.is2D)
{
for (int i = 0; i < _pathEditor.points.Length; i++)
{
FlattenPoint(ref _pathEditor.points[i], LinearAlgebraUtility.Axis.Z);
}
}
_pathEditor.ApplyModifiedProperties();
_operation = -1;
}
break;
}
}
private void FlattenPoint(ref SerializedSplinePoint point, LinearAlgebraUtility.Axis axis, float flatValue = 0f)
{
point.position = LinearAlgebraUtility.FlattenVector(point.position, axis, flatValue);
point.tangent = LinearAlgebraUtility.FlattenVector(point.tangent, axis, flatValue);
point.tangent2 = LinearAlgebraUtility.FlattenVector(point.tangent2, axis, flatValue);
switch (axis)
{
case LinearAlgebraUtility.Axis.X: point.normal = Vector3.right; break;
case LinearAlgebraUtility.Axis.Y: point.normal = Vector3.up; break;
case LinearAlgebraUtility.Axis.Z: point.normal = Vector3.forward; break;
}
}
void ToggleModule(int index)
{
if (_module >= 0 && _module < _modules.Length) _modules[_module].Deselect();
if (_module == index) index = -1;
_module = index;
if (_module >= 0 && _module < _modules.Length) _modules[_module].Select();
}
public void BreakSpline()
{
RecordUndo("Break path");
if (_splines.Length == 1 && _pathEditor.selectedPoints.Count == 1)
{
_spline.Break(_pathEditor.selectedPoints[0]);
EditorUtility.SetDirty(_spline);
_pathEditor.selectedPoints.Clear();
_pathEditor.selectedPoints.Add(0);
}
else
{
for (int i = 0; i < _splines.Length; i++)
{
_splines[i].Break();
EditorUtility.SetDirty(_splines[i]);
}
}
}
public void CloseSpline()
{
RecordUndo("Close path");
for (int i = 0; i < _splines.Length; i++)
{
_splines[i].Close();
}
}
void ReversePointOrder()
{
for (int i = 0; i < _splines.Length; i++)
{
ReversePointOrder(_splines[i]);
}
}
void ReversePointOrder(SplineComputer spline)
{
SplinePoint[] points = spline.GetPoints();
for (int i = 0; i < Mathf.FloorToInt(points.Length / 2); i++)
{
SplinePoint temp = points[i];
points[i] = points[(points.Length - 1) - i];
Vector3 tempTan = points[i].tangent;
points[i].tangent = points[i].tangent2;
points[i].tangent2 = tempTan;
int opposideIndex = (points.Length - 1) - i;
points[opposideIndex] = temp;
tempTan = points[opposideIndex].tangent;
points[opposideIndex].tangent = points[opposideIndex].tangent2;
points[opposideIndex].tangent2 = tempTan;
}
if (points.Length % 2 != 0)
{
Vector3 tempTan = points[Mathf.CeilToInt(points.Length / 2)].tangent;
points[Mathf.CeilToInt(points.Length / 2)].tangent = points[Mathf.CeilToInt(points.Length / 2)].tangent2;
points[Mathf.CeilToInt(points.Length / 2)].tangent2 = tempTan;
}
spline.SetPoints(points);
}
public override void DrawScene(SceneView current)
{
base.DrawScene(current);
if (_spline == null)
{
return;
}
for (int i = 0; i < _splines.Length; i++)
{
if (drawComputer)
{
DSSplineDrawer.DrawSplineComputer(_splines[i]);
}
if (drawPivot)
{
var trs = _splines[i].transform;
float size = HandleUtility.GetHandleSize(trs.position);
Handles.color = Color.red;
Handles.DrawLine(trs.position, trs.position + trs.right * size * 0.5f);
Handles.color = Color.green;
Handles.DrawLine(trs.position, trs.position + trs.up * size * 0.5f);
Handles.color = Color.blue;
Handles.DrawLine(trs.position, trs.position + trs.forward * size * 0.5f);
}
}
if (drawConnectedComputers)
{
for (int i = 0; i < _splines.Length; i++)
{
List<SplineComputer> computers = _splines[i].GetConnectedComputers();
for (int j = 1; j < computers.Count; j++)
{
DSSplineDrawer.DrawSplineComputer(computers[j], 0.0, 1.0, 0.5f);
}
}
}
if (_pathEditor.currentModule == null)
{
if(_splines.Length > 1 || Tools.current != Tool.None)
{
_transformTool = 0;
}
switch (_transformTool)
{
case 1:
Vector3 position = _spline.transform.position;
position = Handles.PositionHandle(position, _spline.transform.rotation);
if (position != _spline.transform.position)
{
Undo.RecordObject(_spline.transform, "Move spline computer");
_spline.transform.position = position;
_pathEditor.ApplyModifiedProperties(true);
}
break;
case 2:
Quaternion rotation = _spline.transform.rotation;
rotation = Handles.RotationHandle(rotation, _spline.transform.position);
if (rotation != _spline.transform.rotation)
{
Undo.RecordObject(_spline.transform, "Rotate spline computer");
_spline.transform.rotation = rotation;
_pathEditor.ApplyModifiedProperties(true);
}
break;
case 3:
Vector3 scale = _spline.transform.localScale;
scale = Handles.ScaleHandle(scale, _spline.transform.position, _spline.transform.rotation,
HandleUtility.GetHandleSize(_spline.transform.position));
if (scale != _spline.transform.localScale)
{
Undo.RecordObject(_spline.transform, "Scale spline computer");
_spline.transform.localScale = scale;
_pathEditor.ApplyModifiedProperties(true);
}
break;
}
if (_transformTool > 0)
{
Vector2 screenPosition = HandleUtility.WorldToGUIPoint(_spline.transform.position);
screenPosition.y += 20f;
Handles.BeginGUI();
DreamteckEditorGUI.Label(new Rect(screenPosition.x - 120 + _spline.name.Length * 4, screenPosition.y, 120, 25), _spline.name);
Handles.EndGUI();
}
}
if (_module >= 0 && _module < _modules.Length) _modules[_module].DrawScene();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e59af6b243fa55640b014783bedaaae3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class ComputerEditorModule : EditorModule
{
protected SplineComputer spline;
public SplineEditorBase.UndoHandler undoHandler;
public EmptySplineHandler repaintHandler;
public ComputerEditorModule(SplineComputer spline)
{
this.spline = spline;
}
protected override void RecordUndo(string title)
{
base.RecordUndo(title);
if (undoHandler != null) undoHandler(title);
}
protected override void Repaint()
{
base.Repaint();
if (repaintHandler != null) repaintHandler();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17f0469145b8d194f8e96c0e083d5b72
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,209 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
public class ComputerMergeModule : ComputerEditorModule
{
SplineComputer[] availableMergeComputers = new SplineComputer[0];
public enum MergeSide { Start, End }
public MergeSide mergeSide = MergeSide.End;
public bool mergeEndpoints = false;
public ComputerMergeModule(SplineComputer spline) : base(spline)
{
}
public override GUIContent GetIconOff()
{
return IconContent("Merge", "merge", "Merge Splines");
}
public override GUIContent GetIconOn()
{
return IconContent("Merge", "merge_on", "Merge Splines");
}
public override void LoadState()
{
mergeEndpoints = LoadBool("mergeEndpoints");
mergeSide = (MergeSide)LoadInt("mergeSide");
}
public override void SaveState()
{
SaveBool("mergeEndpoints", mergeEndpoints);
SaveInt("mergeSide", (int)mergeSide);
}
public override void Select()
{
base.Select();
FindAvailableComputers();
}
private void FindAvailableComputers()
{
SplineComputer[] found = Object.FindObjectsOfType<SplineComputer>();
List<SplineComputer> available = new List<SplineComputer>();
for (int i = 0; i < found.Length; i++)
{
if (found[i] != spline && !found[i].isClosed && spline.pointCount >= 2) available.Add(found[i]);
}
availableMergeComputers = available.ToArray();
}
protected override void OnDrawScene()
{
base.OnDrawScene();
if (spline.isClosed) return;
Camera editorCamera = SceneView.currentDrawingSceneView.camera;
for (int i = 0; i < availableMergeComputers.Length; i++)
{
DSSplineDrawer.DrawSplineComputer(availableMergeComputers[i]);
SplinePoint startPoint = availableMergeComputers[i].GetPoint(0);
SplinePoint endPoint = availableMergeComputers[i].GetPoint(availableMergeComputers[i].pointCount - 1);
Handles.color = availableMergeComputers[i].editorPathColor;
if (SplineEditorHandles.CircleButton(startPoint.position, Quaternion.LookRotation(editorCamera.transform.position - startPoint.position), HandleUtility.GetHandleSize(startPoint.position) * 0.15f, 1f, availableMergeComputers[i].editorPathColor))
{
Merge(i, MergeSide.Start);
break;
}
if (SplineEditorHandles.CircleButton(endPoint.position, Quaternion.LookRotation(editorCamera.transform.position - endPoint.position), HandleUtility.GetHandleSize(endPoint.position) * 0.15f, 1f, availableMergeComputers[i].editorPathColor))
{
Merge(i, MergeSide.End);
break;
}
}
Handles.color = Color.white;
}
protected override void OnDrawInspector()
{
base.OnDrawInspector();
if (spline.isClosed)
{
EditorGUILayout.LabelField("Closed splines cannot be merged with others.", EditorStyles.centeredGreyMiniLabel);
return;
}
mergeSide = (MergeSide)EditorGUILayout.EnumPopup("Merge:", mergeSide);
mergeEndpoints = EditorGUILayout.Toggle("Merge Endpoints", mergeEndpoints);
}
private void Merge(int index, MergeSide mergingSide)
{
RegisterChange();
SplineComputer mergedSpline = availableMergeComputers[index];
SplinePoint[] mergedPoints = mergedSpline.GetPoints();
SplinePoint[] original = spline.GetPoints();
List<SplinePoint> pointsList = new List<SplinePoint>();
SplinePoint[] points;
if (!mergeEndpoints) points = new SplinePoint[mergedPoints.Length + original.Length];
else points = new SplinePoint[mergedPoints.Length + original.Length - 1];
if(mergeSide == MergeSide.End)
{
if(mergingSide == MergeSide.Start)
{
for (int i = 0; i < original.Length; i++) pointsList.Add(original[i]);
for (int i = mergeEndpoints ? 1 : 0; i < mergedPoints.Length; i++) pointsList.Add(mergedPoints[i]);
} else
{
for (int i = 0; i < original.Length; i++) pointsList.Add(original[i]);
for (int i = 0; i < mergedPoints.Length - (mergeEndpoints ? 1 : 0); i++) pointsList.Add(mergedPoints[(mergedPoints.Length-1)-i]);
}
} else
{
if (mergingSide == MergeSide.Start)
{
for (int i = 0; i < mergedPoints.Length - (mergeEndpoints ? 1 : 0); i++) pointsList.Add(mergedPoints[(mergedPoints.Length - 1) - i]);
for (int i = 0; i < original.Length; i++) pointsList.Add(original[i]);
}
else
{
for (int i = mergeEndpoints ? 1 : 0; i < mergedPoints.Length; i++) pointsList.Add(mergedPoints[i]);
for (int i = 0; i < original.Length; i++) pointsList.Add(original[i]);
}
}
points = pointsList.ToArray();
double mergedPercent = (double)(mergedPoints.Length-1) / (points.Length-1);
double from = 0.0;
double to = 1.0;
if (mergeSide == MergeSide.End)
{
from = 1.0 - mergedPercent;
to = 1.0;
}
else
{
from = 0.0;
to = mergedPercent;
}
List<Node> mergedNodes = new List<Node>();
List<int> mergedIndices = new List<int>();
for (int i = 0; i < mergedSpline.pointCount; i++)
{
Node node = mergedSpline.GetNode(i);
if (node != null)
{
mergedNodes.Add(node);
mergedIndices.Add(i);
Undo.RecordObject(node, "Disconnect Node");
mergedSpline.DisconnectNode(i);
i--;
}
}
SplineUser[] subs = mergedSpline.GetSubscribers();
for (int i = 0; i < subs.Length; i++)
{
mergedSpline.Unsubscribe(subs[i]);
subs[i].spline = spline;
subs[i].clipFrom = DMath.Lerp(from, to, subs[i].clipFrom);
subs[i].clipTo = DMath.Lerp(from, to, subs[i].clipTo);
}
spline.SetPoints(points);
if (mergeSide == MergeSide.Start)
{
spline.ShiftNodes(0, spline.pointCount - 1, mergedSpline.pointCount);
for (int i = 0; i < mergedNodes.Count; i++)
{
spline.ConnectNode(mergedNodes[i], mergedIndices[i]);
}
} else
{
for (int i = 0; i < mergedNodes.Count; i++)
{
int connectIndex = mergedIndices[i] + original.Length;
if (mergeEndpoints) connectIndex--;
spline.ConnectNode(mergedNodes[i], connectIndex);
}
}
if (EditorUtility.DisplayDialog("Keep merged computer's GameObject?", "Do you want to keep the merged computer's game object?", "Yes", "No"))
{
Undo.DestroyObjectImmediate(mergedSpline);
}
else
{
for (int i = 0; i < mergedNodes.Count; i++)
{
if(TransformUtility.IsParent(mergedNodes[i].transform, mergedSpline.transform))
{
Undo.SetTransformParent(mergedNodes[i].transform, mergedSpline.transform.parent, "Reparent Node");
}
}
Undo.DestroyObjectImmediate(mergedSpline.gameObject);
}
FindAvailableComputers();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 50db3c9801774b24cbb81bdf47a3f852
timeCreated: 1476814299
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class DSCreatePointModule : CreatePointModule
{
DreamteckSplinesEditor dsEditor;
private bool createNode = false;
public DSCreatePointModule(SplineEditor editor) : base(editor)
{
dsEditor = (DreamteckSplinesEditor)editor;
}
public override void LoadState()
{
base.LoadState();
createNode = LoadBool("createNode");
}
public override void SaveState()
{
base.SaveState();
SaveBool("createNode", createNode);
}
protected override void OnDrawInspector()
{
base.OnDrawInspector();
createNode = EditorGUILayout.Toggle("Create Node", createNode);
}
protected override void CreateSplinePoint(Vector3 position, Vector3 normal)
{
GUIUtility.hotControl = GUIUtility.GetControlID(FocusType.Passive);
List<int> indices = new List<int>();
List<Node> nodes = new List<Node>();
SplineComputer spline = dsEditor.spline;
dsEditor.CacheTriggerPositions();
if (!isClosed && points.Length >= 3)
{
Vector2 first = HandleUtility.WorldToGUIPoint(points[0].position);
Vector2 last = HandleUtility.WorldToGUIPoint(position);
if (Vector2.Distance(first, last) <= 20f)
{
if (EditorUtility.DisplayDialog("Close spline?", "Do you want to make the spline path closed ?", "Yes", "No"))
{
editor.SetSplineClosed(true);
spline.EditorSetAllPointsDirty();
RegisterChange();
SceneView.currentDrawingSceneView.Focus();
SceneView.RepaintAll();
return;
}
}
}
AddPoint();
if (appendMode == AppendMode.End)
{
for (int i = 0; i < indices.Count; i++)
{
nodes[i].AddConnection(spline, indices[i] + 1);
}
}
dsEditor.ApplyModifiedProperties(true);
dsEditor.WriteTriggerPositions();
RegisterChange();
if (appendMode == AppendMode.Beginning)
{
spline.ShiftNodes(0, spline.pointCount - 1, 1);
}
if (createNode)
{
dsEditor.ApplyModifiedProperties();
if (appendMode == 0)
{
CreateNodeForPoint(0);
}
else
{
CreateNodeForPoint(points.Length - 1);
}
}
}
protected override void InsertMode(Vector3 screenCoordinates)
{
base.InsertMode(screenCoordinates);
double percent = ProjectScreenSpace(screenCoordinates);
editor.evaluate(percent, ref evalResult);
if (editor.eventModule.mouseRight)
{
SplineEditorHandles.DrawCircle(evalResult.position, Quaternion.LookRotation(editorCamera.transform.position - evalResult.position), HandleUtility.GetHandleSize(evalResult.position) * 0.2f);
return;
}
if (SplineEditorHandles.CircleButton(evalResult.position, Quaternion.LookRotation(editorCamera.transform.position - evalResult.position), HandleUtility.GetHandleSize(evalResult.position) * 0.2f, 1.5f, color))
{
dsEditor.CacheTriggerPositions();
SplinePoint newPoint = new SplinePoint(evalResult.position, evalResult.position);
newPoint.size = evalResult.size;
newPoint.color = evalResult.color;
newPoint.normal = evalResult.up;
int pointIndex = dsEditor.spline.PercentToPointIndex(percent);
editor.AddPointAt(pointIndex + 1);
points[pointIndex + 1].SetPoint(newPoint);
SplineComputer spline = dsEditor.spline;
lastCreated = points.Length - 1;
editor.ApplyModifiedProperties(true);
spline.ShiftNodes(pointIndex + 1, spline.pointCount - 1, 1);
if (createNode) CreateNodeForPoint(pointIndex + 1);
RegisterChange();
dsEditor.WriteTriggerPositions();
}
}
void CreateNodeForPoint(int index)
{
GameObject obj = new GameObject("Node_" + (points.Length - 1));
obj.transform.parent = dsEditor.spline.transform;
Node node = obj.AddComponent<Node>();
node.transform.localRotation = Quaternion.identity;
node.transform.position = points[index].position;
Undo.SetCurrentGroupName("Create Node For Point " + index);
Undo.RegisterCreatedObjectUndo(obj, "Create Node object");
Undo.RegisterCompleteObjectUndo(dsEditor.spline, "Link Node");
dsEditor.spline.ConnectNode(node, index);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 870db4c17be74374e93a8dbc31114a05
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,474 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class DreamteckSplinesEditor : SplineEditor
{
public SplineComputer spline = null;
public bool splineChanged
{
get { return _splineChanged; }
}
private Transform _transform;
private DSCreatePointModule _createPointModule = null;
private Dreamteck.Editor.Toolbar _nodesToolbar;
private bool _splineChanged = false;
private List<Vector3> _triggerWorldPositions = new List<Vector3>();
protected override string editorName { get { return "DreamteckSplines"; } }
public DreamteckSplinesEditor(SplineComputer splineComputer, SerializedObject splineHolder) : base (splineComputer.transform.localToWorldMatrix, splineHolder, "_spline")
{
spline = splineComputer;
_transform = spline.transform;
evaluate = spline.Evaluate;
evaluateAtPoint = spline.Evaluate;
evaluatePosition = spline.EvaluatePosition;
calculateLength = spline.CalculateLength;
travel = spline.Travel;
undoHandler = HandleUndo;
mainModule.onBeforeDeleteSelectedPoints += OnBeforeDeleteSelectedPoints;
mainModule.onDuplicatePoint += OnDuplicatePoint;
if (spline.isNewlyCreated)
{
if (SplinePrefs.startInCreationMode)
{
open = true;
editMode = true;
ToggleModule(0);
}
spline.isNewlyCreated = false;
}
GUIContent[] nodeToolbarContents = new GUIContent[3];
nodeToolbarContents[0] = new GUIContent("Select");
nodeToolbarContents[1] = new GUIContent("Delete");
nodeToolbarContents[2] = new GUIContent("Disconnect");
_nodesToolbar = new Dreamteck.Editor.Toolbar(nodeToolbarContents);
}
protected override void Load()
{
pointOperations.Add(new PointOperation { name = "Center To Transform", action = delegate { CenterSelection(); } });
pointOperations.Add(new PointOperation { name = "Move Transform To", action = delegate { MoveTransformToSelection(); } });
base.Load();
}
private void OnDuplicatePoint(int[] points)
{
for (int i = 0; i < points.Length; i++)
{
spline.ShiftNodes(points[i], spline.pointCount - 1, 1);
}
}
public override void DrawInspector()
{
drawColor = spline.editorPathColor;
is2D = spline.is2D;
base.DrawInspector();
}
public override void DrawScene(SceneView current)
{
if (spline == null) return;
drawColor = spline.editorPathColor;
is2D = spline.is2D;
base.DrawScene(current);
}
public void CacheTriggerPositions()
{
_triggerWorldPositions.Clear();
LoopTriggerProperties((trigger) =>
{
SerializedProperty positionProperty = trigger.FindPropertyRelative("position");
_triggerWorldPositions.Add(spline.EvaluatePosition(positionProperty.floatValue));
});
}
public void WriteTriggerPositions()
{
SplineSample projectSample = new SplineSample();
int index = 0;
LoopTriggerProperties((trigger) =>
{
spline.Project(_triggerWorldPositions[index], ref projectSample);
SerializedProperty positionProperty = trigger.FindPropertyRelative("position");
positionProperty.floatValue = (float)projectSample.percent;
index++;
});
_serializedObject.ApplyModifiedProperties();
}
private void OnBeforeDeleteSelectedPoints()
{
CacheTriggerPositions();
string nodeString = "";
List <Node> deleteNodes = new List<Node>();
for (int i = 0; i < selectedPoints.Count; i++)
{
Node node = spline.GetNode(selectedPoints[i]);
if (node)
{
spline.DisconnectNode(selectedPoints[i]);
if (node.GetConnections().Length == 0)
{
deleteNodes.Add(node);
if (nodeString != "") nodeString += ", ";
string trimmed = node.name.Trim();
if (nodeString.Length + trimmed.Length > 80) nodeString += "...";
else nodeString += node.name.Trim();
}
}
}
if (deleteNodes.Count > 0)
{
string message = "The following nodes:\r\n" + nodeString + "\r\n were only connected to the currently selected points. Would you like to remove them from the scene?";
if (EditorUtility.DisplayDialog("Remove nodes?", message, "Yes", "No"))
{
for (int i = 0; i < deleteNodes.Count; i++)
{
Undo.DestroyObjectImmediate(deleteNodes[i].gameObject);
}
}
}
int min = spline.pointCount - 1;
for (int i = 0; i < selectedPoints.Count; i++)
{
if (selectedPoints[i] < min)
{
min = selectedPoints[i];
}
}
}
protected override void PointMenu()
{
base.PointMenu();
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Nodes", GUILayout.MaxWidth(200f));
int nodesCount = 0;
for (int i = 0; i < selectedPoints.Count; i++)
{
if(spline.GetNode(selectedPoints[i]) != null)
{
nodesCount ++;
}
}
if (nodesCount > 0)
{
int option = -1;
_nodesToolbar.center = false;
_nodesToolbar.Draw(ref option);
if(option == 0)
{
List<Node> nodeList = new List<Node>();
for (int i = 0; i < selectedPoints.Count; i++)
{
Node node = spline.GetNode(selectedPoints[i]);
if(node != null)
{
nodeList.Add(node);
}
}
Selection.objects = nodeList.ToArray();
}
if(option == 1)
{
for (int i = 0; i < selectedPoints.Count; i++)
{
bool delete = true;
Node node = spline.GetNode(selectedPoints[i]);
if(node.GetConnections().Length > 1)
{
if(!EditorUtility.DisplayDialog("Delete Node",
"Node " + node.name + " has multiple connections. Are you sure you want to completely remove it?", "Yes", "No"))
{
delete = false;
}
}
if (delete)
{
Undo.RegisterCompleteObjectUndo(spline, "Delete Node");
Undo.DestroyObjectImmediate(node.gameObject);
spline.DisconnectNode(selectedPoints[i]);
EditorUtility.SetDirty(spline);
}
}
}
if (option == 2)
{
for (int i = 0; i < selectedPoints.Count; i++)
{
Undo.RegisterCompleteObjectUndo(spline, "Disconnect Node");
spline.DisconnectNode(selectedPoints[i]);
EditorUtility.SetDirty(spline);
}
}
} else
{
if(GUILayout.Button(selectedPoints.Count == 1 ? "Add Node to Point" : "Add Nodes to Points"))
{
for (int i = 0; i < selectedPoints.Count; i++)
{
SplineSample sample = spline.Evaluate(selectedPoints[i]);
GameObject go = new GameObject(spline.name + "_Node_" + (spline.GetNodes().Count+1));
go.transform.parent = spline.transform;
go.transform.position = sample.position;
if (spline.is2D)
{
go.transform.rotation = sample.rotation * Quaternion.Euler(90, -90, 0);
}
else
{
go.transform.rotation = sample.rotation;
}
Node node = go.AddComponent<Node>();
Undo.RegisterCreatedObjectUndo(go, "Create Node");
Undo.RegisterCompleteObjectUndo(spline, "Create Node");
spline.ConnectNode(node, selectedPoints[i]);
}
}
}
EditorGUILayout.Space();
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
}
protected override void OnModuleList(List<PointModule> list)
{
_createPointModule = new DSCreatePointModule(this);
list.Add(_createPointModule);
list.Add(new DeletePointModule(this));
list.Add(new PointMoveModule(this));
list.Add(new PointRotateModule(this));
list.Add(new PointScaleModule(this));
list.Add(new PointNormalModule(this));
list.Add(new PointMirrorModule(this));
list.Add(new PrimitivesModule(this));
}
public override void Destroy()
{
base.Destroy();
if(spline != null)
{
spline.RebuildImmediate();
}
}
public override void BeforeSceneGUI(SceneView current)
{
for (int i = 0; i < moduleCount; i++)
{
SetupModule(GetModule(i));
}
SetupModule(mainModule);
_createPointModule.createPointColor = SplinePrefs.createPointColor;
_createPointModule.createPointSize = SplinePrefs.createPointSize;
base.BeforeSceneGUI(current);
}
public override void DeletePoint(int index)
{
CacheTriggerPositions();
Dictionary<int, Node> nodes = new Dictionary<int, Node>();
foreach(var node in spline.GetNodes())
{
if(node.Key > index)
{
spline.DisconnectNode(node.Key);
nodes.Add(node.Key - 1, node.Value);
}
}
var nodesProperty = _serializedObject.FindProperty("_nodes");
for (int i = 0; i < nodesProperty.arraySize; i++)
{
var indexProperty = nodesProperty.GetArrayElementAtIndex(i).FindPropertyRelative("pointIndex");
if(indexProperty.intValue > index)
{
nodesProperty.DeleteArrayElementAtIndex(i);
i--;
}
}
InverseTransformPoints();
_pointsProperty.DeleteArrayElementAtIndex(index);
foreach (var node in nodes)
{
spline.ConnectNode(node.Value, node.Key);
nodesProperty.arraySize = nodesProperty.arraySize + 1;
var lastProperty = nodesProperty.GetArrayElementAtIndex(nodesProperty.arraySize - 1);
var lastnodeProperty = lastProperty.FindPropertyRelative("node");
var lastIndexProperty = lastProperty.FindPropertyRelative("pointIndex");
lastnodeProperty.objectReferenceValue = node.Value;
lastIndexProperty.intValue = node.Key;
}
_serializedObject.ApplyModifiedProperties();
GetPointsFromSpline();
spline.Rebuild(true);
WriteTriggerPositions();
}
public override void GetPointsFromSpline()
{
base.GetPointsFromSpline();
if (_serializedObject.FindProperty("_space").enumValueIndex == (int)SplineComputer.Space.Local)
{
TransformPoints();
}
}
public override void ApplyModifiedProperties(bool forceAllUpdate = false)
{
if (_serializedObject.FindProperty("_space").enumValueIndex == (int)SplineComputer.Space.Local)
{
InverseTransformPoints();
}
for (int i = 0; i < points.Length; i++)
{
if (points[i].changed || forceAllUpdate)
{
spline.EditorSetPointDirty(i);
}
}
_splineChanged = true;
if (spline.isClosed && points.Length < 3)
{
SetSplineClosed(false);
}
_serializedObject.FindProperty("_is2D").boolValue = is2D;
base.ApplyModifiedProperties(forceAllUpdate);
spline.EditorUpdateConnectedNodes();
if (_serializedObject.FindProperty("editorUpdateMode").enumValueIndex == (int)SplineComputer.EditorUpdateMode.Default)
{
spline.RebuildImmediate(true, forceAllUpdate);
}
GetPointsFromSpline();
}
public override void SetSplineClosed(bool closed)
{
base.SetSplineClosed(closed);
if (closed)
{
spline.Close();
}
else
{
if (selectedPoints.Count > 0)
{
spline.Break(selectedPoints[selectedPoints.Count - 1]);
}
else
{
spline.Break();
}
}
}
public override void UndoRedoPerformed()
{
base.UndoRedoPerformed();
spline.RebuildImmediate(true, true);
}
private void TransformPoints()
{
_matrix = spline.transform.localToWorldMatrix;
for (int i = 0; i < points.Length; i++)
{
bool changed = points[i].changed;
points[i].position = _matrix.MultiplyPoint3x4(points[i].position);
points[i].tangent = _matrix.MultiplyPoint3x4(points[i].tangent);
points[i].tangent2 = _matrix.MultiplyPoint3x4(points[i].tangent2);
points[i].normal = _matrix.MultiplyVector(points[i].normal);
points[i].changed = changed;
}
}
private void InverseTransformPoints()
{
_matrix = spline.transform.localToWorldMatrix;
Matrix4x4 invMatrix = _matrix.inverse;
for (int i = 0; i < points.Length; i++)
{
bool changed = points[i].changed;
points[i].position = invMatrix.MultiplyPoint3x4(points[i].position);
points[i].tangent = invMatrix.MultiplyPoint3x4(points[i].tangent);
points[i].tangent2 = invMatrix.MultiplyPoint3x4(points[i].tangent2);
points[i].normal = invMatrix.MultiplyVector(points[i].normal);
points[i].changed = changed;
}
}
public override void SetPreviewPoints(SplinePoint[] points)
{
spline.SetPoints(points);
}
private void HandleUndo(string title)
{
Undo.RecordObject(spline, title);
}
public void MoveTransformToSelection()
{
Undo.RecordObject(_transform, "Move Transform To");
Vector3 avg = Vector3.zero;
for (int i = 0; i < selectedPoints.Count; i++)
{
avg += points[selectedPoints[i]].position;
}
avg /= selectedPoints.Count;
_transform.position = avg;
ApplyModifiedProperties(true);
ResetCurrentModule();
}
public void CenterSelection()
{
RecordUndo("Center Selection");
Vector3 avg = Vector3.zero;
for (int i = 0; i < selectedPoints.Count; i++)
{
avg += points[selectedPoints[i]].position;
}
avg /= selectedPoints.Count;
Vector3 delta = _transform.position - avg;
for (int i = 0; i < selectedPoints.Count; i++)
{
points[selectedPoints[i]].SetPosition(points[selectedPoints[i]].position + delta);
}
ApplyModifiedProperties(true);
ResetCurrentModule();
}
private void SetupModule(PointModule module)
{
module.duplicationDirection = SplinePrefs.duplicationDirection;
module.highlightColor = SplinePrefs.highlightColor;
module.showPointNumbers = SplinePrefs.showPointNumbers;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 45538fa443017094faf75943a969938d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,251 @@
namespace Dreamteck.Splines.Editor
{
using System;
using UnityEngine;
using Dreamteck.Splines;
using Dreamteck.Splines.Primitives;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class PrimitivesModule : PointTransformModule
{
DreamteckSplinesEditor dsEditor = null;
private PrimitiveEditor[] primitiveEditors;
private string[] primitiveNames;
private SplinePreset[] presets;
private string[] presetNames;
int mode = 0, selectedPrimitive = 0, selectedPreset = 0;
bool createPresetMode = false;
GUIContent[] toolbarContents = new GUIContent[2];
Dreamteck.Editor.Toolbar toolbar;
private string savePresetName = "", savePresetDescription = "";
private bool lastClosed = false;
private Spline.Type lastType = Spline.Type.Bezier;
public PrimitivesModule(SplineEditor editor) : base(editor)
{
dsEditor = ((DreamteckSplinesEditor)editor);
toolbarContents[0] = new GUIContent("Primitives", "Procedural Primitives");
toolbarContents[1] = new GUIContent("Presets", "Saved spline presets");
toolbar = new Dreamteck.Editor.Toolbar(toolbarContents, toolbarContents);
}
public override GUIContent GetIconOff()
{
return IconContent("*", "primitives", "Spline Primitives");
}
public override GUIContent GetIconOn()
{
return IconContent("*", "primitives_on", "Spline Primitives");
}
public override void LoadState()
{
base.LoadState();
selectedPrimitive = LoadInt("selectedPrimitive");
mode = LoadInt("mode");
createPresetMode = LoadBool("createPresetMode");
}
public override void SaveState()
{
base.SaveState();
SaveInt("selectedPrimitive", selectedPrimitive);
SaveInt("mode", mode);
SaveBool("createPresetMode", createPresetMode);
}
public override void Select()
{
base.Select();
lastClosed = editor.GetSplineClosed();
lastType = editor.GetSplineType();
if(mode == 0) LoadPrimitives();
else if(!createPresetMode) LoadPresets();
}
public override void Deselect()
{
ApplyDialog();
base.Deselect();
}
void ApplyDialog()
{
if (!IsDirty()) return;
if (EditorUtility.DisplayDialog("Unapplied Primitives", "There is an unapplied primitive. Do you want to apply the changes?", "Apply", "Revert"))
{
Apply();
}
else
{
Revert();
}
}
public override void Revert()
{
editor.SetSplineType(lastType);
editor.SetSplineClosed(lastClosed);
base.Revert();
}
protected override void OnDrawInspector()
{
EditorGUI.BeginChangeCheck();
toolbar.Draw(ref mode);
if (EditorGUI.EndChangeCheck())
{
if (mode == 0) LoadPrimitives();
else if (!createPresetMode) LoadPresets();
}
if (selectedPoints.Count > 0) ClearSelection();
if (mode == 0) PrimitivesGUI();
else PresetsGUI();
if (IsDirty() && (!createPresetMode || mode == 0))
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Apply")) Apply();
if (GUILayout.Button("Revert")) Revert();
EditorGUILayout.EndHorizontal();
}
}
void PrimitivesGUI()
{
int last = selectedPrimitive;
selectedPrimitive = EditorGUILayout.Popup(selectedPrimitive, primitiveNames);
if (last != selectedPrimitive)
{
primitiveEditors[selectedPrimitive].Open(dsEditor);
primitiveEditors[selectedPrimitive].Update();
TransformPoints();
}
EditorGUI.BeginChangeCheck();
primitiveEditors[selectedPrimitive].Draw();
if (EditorGUI.EndChangeCheck())
{
TransformPoints();
}
}
void PresetsGUI()
{
if (createPresetMode)
{
savePresetName = EditorGUILayout.TextField("Preset name", savePresetName);
EditorGUILayout.LabelField("Description");
savePresetDescription = EditorGUILayout.TextArea(savePresetDescription);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Save"))
{
string lower = savePresetName.ToLower();
string noSlashes = lower.Replace('/', '_');
noSlashes = noSlashes.Replace('\\', '_');
string noSpaces = noSlashes.Replace(' ', '_');
SplinePreset preset = new SplinePreset(points, isClosed, splineType);
preset.name = savePresetName;
preset.description = savePresetDescription;
preset.Save(noSpaces);
createPresetMode = false;
LoadPresets();
savePresetName = savePresetDescription = "";
}
if (GUILayout.Button("Cancel")) createPresetMode = false;
EditorGUILayout.EndHorizontal();
return;
}
if (GUILayout.Button("Create New")) createPresetMode = true;
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
selectedPreset = EditorGUILayout.Popup(selectedPreset, presetNames, GUILayout.MaxWidth(Screen.width / 3f));
if (selectedPreset >= 0 && selectedPreset < presets.Length)
{
if (GUILayout.Button("Use"))
{
LoadPreset(selectedPreset);
}
if (GUILayout.Button("Delete", GUILayout.MaxWidth(80)))
{
if (EditorUtility.DisplayDialog("Delete Preset", "This will permanently delete the preset file. Continue?", "Yes", "No"))
{
SplinePreset.Delete(presets[selectedPreset].filename);
LoadPresets();
if (selectedPreset >= presets.Length) selectedPreset = presets.Length - 1;
}
}
}
EditorGUILayout.EndHorizontal();
}
void TransformPoints()
{
for (int i = 0; i < editor.points.Length; i++)
{
editor.points[i].position = dsEditor.spline.transform.TransformPoint(editor.points[i].position);
editor.points[i].tangent = dsEditor.spline.transform.TransformPoint(editor.points[i].tangent);
editor.points[i].tangent2 = dsEditor.spline.transform.TransformPoint(editor.points[i].tangent2);
editor.points[i].normal = dsEditor.spline.transform.TransformDirection(editor.points[i].normal);
}
RegisterChange();
SetDirty();
}
void LoadPrimitives()
{
List<Type> types = FindDerivedClasses.GetAllDerivedClasses(typeof(PrimitiveEditor));
primitiveEditors = new PrimitiveEditor[types.Count];
int count = 0;
primitiveNames = new string[types.Count];
foreach (Type t in types)
{
primitiveEditors[count] = (PrimitiveEditor)Activator.CreateInstance(t);
primitiveNames[count] = primitiveEditors[count].GetName();
count++;
}
if (selectedPrimitive >= 0 && selectedPrimitive < primitiveEditors.Length)
{
ClearSelection();
primitiveEditors[selectedPrimitive].Open(dsEditor);
primitiveEditors[selectedPrimitive].Update();
TransformPoints();
SetDirty();
}
}
void LoadPresets()
{
ApplyDialog();
presets = SplinePreset.LoadAll();
presetNames = new string[presets.Length];
for (int i = 0; i < presets.Length; i++)
{
presetNames[i] = presets[i].name;
}
ClearSelection();
}
void LoadPreset(int index)
{
if (index >= 0 && index < presets.Length)
{
editor.SetPointsArray(presets[index].points);
editor.SetSplineClosed(presets[index].isClosed);
editor.SetSplineType(presets[index].type);
TransformPoints();
FramePoints();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a63f089fd77344408647fe340cc2cf5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,123 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class SplineComputerDebugEditor : SplineEditorBase
{
public SplineComputer.EditorUpdateMode editorUpdateMode
{
get
{
return (SplineComputer.EditorUpdateMode)_editorUpdateMode.enumValueIndex;
}
}
private SerializedProperty _editorDrawPivot;
private SerializedProperty _editorPathColor;
private SerializedProperty _editorAlwaysDraw;
private SerializedProperty _editorDrawThickness;
private SerializedProperty _editorBillboardThickness;
private SerializedProperty _editorUpdateMode;
private SplineComputer _spline;
private DreamteckSplinesEditor _pathEditor;
private float _length = 0f;
public SplineComputerDebugEditor(SplineComputer spline, SerializedObject serializedObject, DreamteckSplinesEditor pathEditor) : base(serializedObject)
{
_spline = spline;
_pathEditor = pathEditor;
GetSplineLength();
_editorPathColor = serializedObject.FindProperty("editorPathColor");
_editorAlwaysDraw = serializedObject.FindProperty("editorAlwaysDraw");
_editorDrawThickness = serializedObject.FindProperty("editorDrawThickness");
_editorBillboardThickness = serializedObject.FindProperty("editorBillboardThickness");
_editorUpdateMode = serializedObject.FindProperty("editorUpdateMode");
_editorDrawPivot = serializedObject.FindProperty("editorDrawPivot");
}
void GetSplineLength()
{
_length = Mathf.RoundToInt(_spline.CalculateLength() * 100f) / 100f;
}
public override void DrawInspector()
{
base.DrawInspector();
if (Event.current.type == EventType.MouseUp) GetSplineLength();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(_editorUpdateMode, new GUIContent("Editor Update Mode"));
EditorGUILayout.PropertyField(_editorPathColor, new GUIContent("Color in Scene"));
bool lastAlwaysDraw = _editorAlwaysDraw.boolValue;
EditorGUILayout.PropertyField(_editorDrawPivot, new GUIContent("Draw Transform Pivot"));
EditorGUILayout.PropertyField(_editorAlwaysDraw, new GUIContent("Always Draw Spline"));
if (lastAlwaysDraw != _editorAlwaysDraw.boolValue)
{
if (_editorAlwaysDraw.boolValue)
{
for (int i = 0; i < _serializedObject.targetObjects.Length; i++)
{
if (_serializedObject.targetObjects[i] is SplineComputer)
{
DSSplineDrawer.RegisterComputer((SplineComputer)_serializedObject.targetObjects[i]);
}
}
}
else
{
for (int i = 0; i < _serializedObject.targetObjects.Length; i++)
{
if (_serializedObject.targetObjects[i] is SplineComputer)
{
DSSplineDrawer.UnregisterComputer((SplineComputer)_serializedObject.targetObjects[i]);
}
}
}
}
EditorGUILayout.PropertyField(_editorDrawThickness, new GUIContent("Draw thickness"));
if (_editorDrawThickness.boolValue)
{
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(_editorBillboardThickness, new GUIContent("Always face camera"));
EditorGUI.indentLevel--;
}
EditorGUILayout.Space();
if (_serializedObject.targetObjects.Length == 1)
{
EditorGUILayout.HelpBox("Samples: " + _spline.sampleCount + "\n\r" + "Length: " + _length, MessageType.Info);
} else
{
EditorGUILayout.HelpBox("Multiple spline objects selected" + _length, MessageType.Info);
}
if (EditorGUI.EndChangeCheck())
{
if (editorUpdateMode == SplineComputer.EditorUpdateMode.Default)
{
for (int i = 0; i < _serializedObject.targetObjects.Length; i++)
{
if(_serializedObject.targetObjects[i] is SplineComputer)
{
((SplineComputer)_serializedObject.targetObjects[i]).RebuildImmediate(true);
}
}
SceneView.RepaintAll();
}
_pathEditor.ApplyModifiedProperties();
}
}
public override void DrawScene(SceneView current)
{
base.DrawScene(current);
if (Event.current.type == EventType.MouseUp && open)
{
GetSplineLength();
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 79246ce5388cae549b7ae6bf61b912f3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,289 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class SplineTriggersEditor : SplineEditorBase
{
private int selected = -1, selectedGroup = -1;
private bool renameTrigger = false, renameGroup = false;
SplineComputer spline;
SplineTrigger.Type addTriggerType = SplineTrigger.Type.Double;
private int setDistanceGroup, setDistanceTrigger;
public SplineTriggersEditor(SplineComputer spline, SerializedObject serializedObject) : base(serializedObject)
{
this.spline = spline;
}
protected override void Load()
{
base.Load();
addTriggerType = (SplineTrigger.Type)LoadInt("addTriggerType");
}
protected override void Save()
{
base.Save();
SaveInt("addTriggerType", (int)addTriggerType);
}
public override void DrawInspector()
{
base.DrawInspector();
EditorGUI.BeginChangeCheck();
EditorGUILayout.BeginVertical();
for (int i = 0; i < spline.triggerGroups.Length; i++) DrawGroupGUI(i);
EditorGUILayout.Space();
if(GUILayout.Button("New Group"))
{
RecordUndo("Add Trigger Group");
TriggerGroup group = new TriggerGroup();
group.name = "Trigger Group " + (spline.triggerGroups.Length+1);
ArrayUtility.Add(ref spline.triggerGroups, group);
}
EditorGUILayout.EndVertical();
if (EditorGUI.EndChangeCheck()) SceneView.RepaintAll();
}
public override void DrawScene(SceneView current)
{
base.DrawScene(current);
if (spline == null) return;
for (int i = 0; i < spline.triggerGroups.Length; i++)
{
if (!spline.triggerGroups[i].open) continue;
DrawGroupScene(i);
}
}
void DrawGroupScene(int index)
{
TriggerGroup group = spline.triggerGroups[index];
for (int i = 0; i < group.triggers.Length; i++)
{
SplineComputerEditorHandles.SplineSliderGizmo gizmo = SplineComputerEditorHandles.SplineSliderGizmo.DualArrow;
switch (group.triggers[i].type)
{
case SplineTrigger.Type.Backward: gizmo = SplineComputerEditorHandles.SplineSliderGizmo.BackwardTriangle; break;
case SplineTrigger.Type.Forward: gizmo = SplineComputerEditorHandles.SplineSliderGizmo.ForwardTriangle; break;
case SplineTrigger.Type.Double: gizmo = SplineComputerEditorHandles.SplineSliderGizmo.DualArrow; break;
}
double last = group.triggers[i].position;
if (SplineComputerEditorHandles.Slider(spline, ref group.triggers[i].position, group.triggers[i].color, group.triggers[i].name, gizmo) || last != group.triggers[i].position)
{
Select(index, i);
Repaint();
}
}
}
void OnSetDistance(float distance)
{
SerializedObject serializedObject = new SerializedObject(spline);
SerializedProperty groups = serializedObject.FindProperty("triggerGroups");
SerializedProperty groupProperty = groups.GetArrayElementAtIndex(setDistanceGroup);
SerializedProperty triggersProperty = groupProperty.FindPropertyRelative("triggers");
SerializedProperty triggerProperty = triggersProperty.GetArrayElementAtIndex(setDistanceTrigger);
SerializedProperty position = triggerProperty.FindPropertyRelative("position");
double travel = spline.Travel(0.0, distance, Spline.Direction.Forward);
position.floatValue = (float)travel;
serializedObject.ApplyModifiedProperties();
}
void DrawGroupGUI(int index)
{
TriggerGroup group = spline.triggerGroups[index];
SerializedObject serializedObject = new SerializedObject(spline);
SerializedProperty groups = serializedObject.FindProperty("triggerGroups");
SerializedProperty groupProperty = groups.GetArrayElementAtIndex(index);
EditorGUI.indentLevel += 2;
if(selectedGroup == index && renameGroup)
{
if (Event.current.type == EventType.KeyDown && (Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter))
{
renameGroup = false;
Repaint();
}
group.name = EditorGUILayout.TextField(group.name);
} else group.open = EditorGUILayout.Foldout(group.open, index + " - " + group.name);
Rect lastRect = GUILayoutUtility.GetLastRect();
if(lastRect.Contains(Event.current.mousePosition) && Event.current.type == EventType.MouseDown && Event.current.button == 1)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Rename"), false, delegate { RecordUndo("Rename Trigger Group"); selectedGroup = index; renameGroup = true; renameTrigger = false; Repaint(); });
menu.AddItem(new GUIContent("Delete"), false, delegate {
RecordUndo("Delete Trigger Group");
ArrayUtility.RemoveAt(ref spline.triggerGroups, index);
Repaint();
});
menu.ShowAsContext();
}
EditorGUI.indentLevel -= 2;
if (!group.open) return;
for (int i = 0; i < group.triggers.Length; i++) DrawTriggerGUI(i, index, groupProperty);
if (GUI.changed) serializedObject.ApplyModifiedProperties();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Add Trigger"))
{
RecordUndo("Add Trigger");
SplineTrigger newTrigger = new SplineTrigger(addTriggerType);
newTrigger.name = "Trigger " + (group.triggers.Length + 1);
ArrayUtility.Add(ref group.triggers, newTrigger);
}
addTriggerType = (SplineTrigger.Type)EditorGUILayout.EnumPopup(addTriggerType);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.Space();
}
void Select(int group, int trigger)
{
selected = trigger;
selectedGroup = group;
renameTrigger = false;
renameGroup = false;
Repaint();
}
void DrawTriggerGUI(int index, int groupIndex, SerializedProperty groupProperty)
{
bool isSelected = selected == index && selectedGroup == groupIndex;
TriggerGroup group = spline.triggerGroups[groupIndex];
SplineTrigger trigger = group.triggers[index];
SerializedProperty triggersProperty = groupProperty.FindPropertyRelative("triggers");
SerializedProperty triggerProperty = triggersProperty.GetArrayElementAtIndex(index);
SerializedProperty eventProperty = triggerProperty.FindPropertyRelative("onCross");
SerializedProperty positionProperty = triggerProperty.FindPropertyRelative("position");
SerializedProperty colorProperty = triggerProperty.FindPropertyRelative("color");
SerializedProperty nameProperty = triggerProperty.FindPropertyRelative("name");
SerializedProperty enabledProperty = triggerProperty.FindPropertyRelative("enabled");
SerializedProperty workOnceProperty = triggerProperty.FindPropertyRelative("workOnce");
SerializedProperty typeProperty = triggerProperty.FindPropertyRelative("type");
Color col = colorProperty.colorValue;
if (isSelected) col.a = 1f;
else col.a = 0.6f;
GUI.backgroundColor = col;
EditorGUILayout.BeginVertical(GUI.skin.box);
GUI.backgroundColor = Color.white;
if (trigger == null)
{
EditorGUILayout.BeginHorizontal();
GUILayout.Label("NULL");
if (GUILayout.Button("x")) ArrayUtility.RemoveAt(ref group.triggers, index);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
return;
}
if (isSelected && renameTrigger)
{
if (Event.current.type == EventType.KeyDown && (Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter))
{
renameTrigger = false;
Repaint();
}
nameProperty.stringValue = EditorGUILayout.TextField(nameProperty.stringValue);
}
else
{
EditorGUILayout.LabelField(nameProperty.stringValue);
}
if (isSelected)
{
EditorGUILayout.Space();
EditorGUILayout.PropertyField(enabledProperty);
EditorGUILayout.PropertyField(colorProperty);
EditorGUILayout.BeginHorizontal();
positionProperty.floatValue = EditorGUILayout.Slider("Position", positionProperty.floatValue, 0f, 1f);
if (GUILayout.Button("Set Distance", GUILayout.Width(85)))
{
DistanceWindow w = EditorWindow.GetWindow<DistanceWindow>(true);
w.Init(OnSetDistance, spline.CalculateLength());
setDistanceGroup = groupIndex;
setDistanceTrigger = index;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(typeProperty);
EditorGUILayout.PropertyField(workOnceProperty);
EditorGUILayout.PropertyField(eventProperty);
}
EditorGUILayout.EndVertical();
Rect lastRect = GUILayoutUtility.GetLastRect();
if (lastRect.Contains(Event.current.mousePosition) && Event.current.type == EventType.MouseDown)
{
if (Event.current.button == 0) Select(groupIndex, index);
else if (Event.current.button == 1)
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Deselect"), false, delegate { Select(-1, -1); });
menu.AddItem(new GUIContent("Rename"), false, delegate { Select(groupIndex, index); renameTrigger = true; renameGroup = false; });
if (index > 0)
{
menu.AddItem(new GUIContent("Move Up"), false, delegate {
RecordUndo("Move Trigger Up");
SplineTrigger temp = group.triggers[index - 1];
group.triggers[index - 1] = trigger;
group.triggers[index] = temp;
selected--;
renameTrigger = false;
});
}
else
{
menu.AddDisabledItem(new GUIContent("Move Up"));
}
if (index < group.triggers.Length - 1)
{
menu.AddItem(new GUIContent("Move Down"), false, delegate {
RecordUndo("Move Trigger Down");
SplineTrigger temp = group.triggers[index + 1];
group.triggers[index + 1] = trigger;
group.triggers[index] = temp;
selected--;
renameTrigger = false;
});
}
else
{
menu.AddDisabledItem(new GUIContent("Move Down"));
}
menu.AddItem(new GUIContent("Duplicate"), false, delegate {
RecordUndo("Duplicate Trigger");
SplineTrigger newTrigger = new SplineTrigger(SplineTrigger.Type.Double);
newTrigger.color = colorProperty.colorValue;
newTrigger.enabled = enabledProperty.boolValue;
newTrigger.position = positionProperty.floatValue;
newTrigger.type = (SplineTrigger.Type) typeProperty.intValue;
newTrigger.name = "Trigger " + (group.triggers.Length + 1);
ArrayUtility.Add(ref group.triggers, newTrigger);
Select(groupIndex, group.triggers.Length - 1);
});
menu.AddItem(new GUIContent("Delete"), false, delegate {
RecordUndo("Delete Trigger");
ArrayUtility.RemoveAt(ref group.triggers, index);
Select(-1, -1);
});
menu.ShowAsContext();
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8e0ea2345d361b04b8778234920e3e24
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,151 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class EditorModule
{
protected string prefPrefix = "";
private bool _changed = false;
public bool hasChanged { get { return _changed; } }
protected SceneView _currentSceneView;
protected void RegisterChange()
{
_changed = true;
}
public virtual void Select()
{
LoadState();
}
public virtual void Deselect()
{
SaveState();
}
public virtual void BeforeSceneDraw(SceneView current)
{
_currentSceneView = current;
}
public void DrawScene()
{
_changed = false;
OnDrawScene();
}
protected virtual void OnDrawScene()
{
}
public void DrawInspector()
{
_changed = false;
OnDrawInspector();
}
protected virtual void OnDrawInspector()
{
}
public virtual GUIContent GetIconOff()
{
return new GUIContent("OFF", "Point Module Off");
}
public virtual GUIContent GetIconOn()
{
return new GUIContent("ON", "Point Module On");
}
protected virtual void RecordUndo(string title)
{
}
protected virtual void Repaint()
{
}
protected void SaveBool(string variableName, bool value)
{
if (prefPrefix == "") prefPrefix = GetType().ToString();
EditorPrefs.SetBool(prefPrefix + "." + variableName, value);
}
protected void SaveInt(string variableName, int value)
{
if (prefPrefix == "") prefPrefix = GetType().ToString();
EditorPrefs.SetInt(prefPrefix + "." + variableName, value);
}
protected void SaveFloat(string variableName, float value)
{
if (prefPrefix == "") prefPrefix = GetType().ToString();
EditorPrefs.SetFloat(prefPrefix + "." + variableName, value);
}
protected void SaveString(string variableName, string value)
{
if (prefPrefix == "") prefPrefix = GetType().ToString();
EditorPrefs.SetString(prefPrefix + "." + variableName, value);
}
protected bool LoadBool(string variableName)
{
if (prefPrefix == "") prefPrefix = GetType().ToString();
return EditorPrefs.GetBool(prefPrefix + "." + variableName, false);
}
protected int LoadInt(string variableName, int defaultValue = 0)
{
if (prefPrefix == "") prefPrefix = GetType().ToString();
return EditorPrefs.GetInt(prefPrefix + "." + variableName, defaultValue);
}
protected float LoadFloat(string variableName, float d = 0f)
{
if (prefPrefix == "") prefPrefix = GetType().ToString();
return EditorPrefs.GetFloat(prefPrefix + "." + variableName, d);
}
protected string LoadString(string variableName)
{
if (prefPrefix == "") prefPrefix = GetType().ToString();
return EditorPrefs.GetString(prefPrefix + "." + variableName, "");
}
public virtual void SaveState()
{
}
public virtual void LoadState()
{
}
internal static GUIContent IconContent(string title, string iconName, string description)
{
GUIContent content = new GUIContent(title, description);
if (EditorGUIUtility.isProSkin)
{
iconName += "_dark";
}
Texture2D tex = ResourceUtility.EditorLoadTexture("Splines/Editor/Icons", iconName);
if (tex != null)
{
content.image = tex;
content.text = "";
}
return content;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8686a0595fc0a4f439a1a64fb1a4d49a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fbe370f8b912d1341b528bc7a71f4ddf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,421 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class CreatePointModule : PointModule
{
public enum AppendMode { Beginning = 0, End = 1}
public enum PlacementMode { YPlane, XPlane, ZPlane, CameraPlane, Surface, Insert }
public enum NormalMode { Default, LookAtCamera, AlignWithCamera, Calculate, Left, Right, Up, Down, Forward, Back }
protected PlacementMode placementMode = PlacementMode.YPlane;
public AppendMode appendMode = AppendMode.End;
public float offset = 0f;
public NormalMode normalMode = NormalMode.Default;
public LayerMask surfaceLayerMask = new LayerMask();
public float createPointSize = 1f;
public Color createPointColor = Color.white;
protected Spline visualizer;
protected Camera editorCamera;
protected Vector3 createPoint = Vector3.zero, createNormal = Vector3.up;
protected SplineSample evalResult = new SplineSample();
protected int lastCreated = -1;
public CreatePointModule(SplineEditor editor) : base(editor)
{
}
public override GUIContent GetIconOff()
{
return IconContent("+", "add", "Add Points");
}
public override GUIContent GetIconOn()
{
return IconContent("+", "add_on", "Add Points");
}
public override void LoadState()
{
base.LoadState();
normalMode = (NormalMode)LoadInt("normalMode");
placementMode = (PlacementMode)LoadInt("placementMode");
appendMode = (AppendMode)LoadInt("appendMode", 1);
offset = LoadFloat("offset");
surfaceLayerMask = LoadInt("surfaceLayerMask", ~0);
}
public override void SaveState()
{
base.SaveState();
SaveInt("normalMode", (int)normalMode);
SaveInt("placementMode", (int)placementMode);
SaveInt("appendMode", (int)appendMode);
SaveFloat("offset", offset);
SaveInt("surfaceLayerMask", surfaceLayerMask);
}
public override void Deselect()
{
base.Deselect();
GUIUtility.hotControl = -1;
if (Event.current != null)
{
Event.current.Use();
}
}
protected override void OnDrawInspector()
{
placementMode = (PlacementMode)EditorGUILayout.EnumPopup("Placement Mode", placementMode);
if (placementMode != PlacementMode.Insert)
{
normalMode = (NormalMode)EditorGUILayout.EnumPopup("Normal Mode", normalMode);
appendMode = (AppendMode)EditorGUILayout.EnumPopup("Append To", appendMode);
}
string offsetLabel = "Grid Offset";
if (placementMode == PlacementMode.CameraPlane) offsetLabel = "Far Plane";
if (placementMode == PlacementMode.Surface) offsetLabel = "Surface Offset";
offset = EditorGUILayout.FloatField(offsetLabel, offset);
if (placementMode == PlacementMode.Surface)
{
surfaceLayerMask = DreamteckEditorGUI.LayermaskField("Surface Mask", surfaceLayerMask);
}
}
protected override void OnDrawScene()
{
editorCamera = SceneView.currentDrawingSceneView.camera;
bool canCreate = false;
if (placementMode == PlacementMode.CameraPlane)
{
GetCreatePointOnPlane(-editorCamera.transform.forward, editorCamera.transform.position + editorCamera.transform.forward * offset, out createPoint);
Handles.color = new Color(1f, 0.78f, 0.12f);
DrawGrid(createPoint, editorCamera.transform.forward, Vector2.one * 10, 2.5f);
Handles.color = Color.white;
canCreate = true;
createNormal = -editorCamera.transform.forward;
}
if (placementMode == PlacementMode.Surface)
{
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity, surfaceLayerMask))
{
canCreate = true;
createPoint = hit.point + hit.normal * offset;
Handles.color = Color.blue;
Handles.DrawLine(hit.point, createPoint);
SplineEditorHandles.DrawRectangle(createPoint, Quaternion.LookRotation(-editorCamera.transform.forward, editorCamera.transform.up), HandleUtility.GetHandleSize(createPoint) * 0.1f);
Handles.color = Color.white;
createNormal = hit.normal;
}
}
if (placementMode == PlacementMode.XPlane)
{
canCreate = AxisGrid(Vector3.right, new Color(0.85f, 0.24f, 0.11f, 0.92f), out createPoint);
createNormal = Vector3.right;
}
if (placementMode == PlacementMode.YPlane)
{
canCreate = AxisGrid(Vector3.up, new Color(0.6f, 0.95f, 0.28f, 0.92f), out createPoint);
createNormal = Vector3.up;
}
if (placementMode == PlacementMode.ZPlane)
{
canCreate = AxisGrid(Vector3.forward, new Color(0.22f, 0.47f, 0.97f, 0.92f), out createPoint);
createNormal = Vector3.back;
}
if (placementMode == PlacementMode.Insert)
{
canCreate = true;
if (points.Length < 2)
{
placementMode = PlacementMode.YPlane;
}
else
{
InsertMode(Event.current.mousePosition);
}
}
else if (eventModule.mouseLeftDown && canCreate && !eventModule.mouseRight && !eventModule.alt)
{
CreateSplinePoint(createPoint, createNormal);
}
if (lastCreated >= 0 && lastCreated < points.Length && editor.eventModule.mouseLeft)
{
Vector3 tangent = points[lastCreated].position - createPoint;
if (appendMode == AppendMode.End)
{
tangent = createPoint - points[lastCreated].position;
}
points[lastCreated].SetTangent2Position(points[lastCreated].position + tangent);
RegisterChange();
}
else if (!editor.eventModule.mouseLeft)
{
lastCreated = -1;
}
if (!canCreate) DrawMouseCross();
UpdateVisualizer();
SplineDrawer.DrawSpline(visualizer, color);
Repaint();
}
protected virtual void CreateSplinePoint(Vector3 position, Vector3 normal)
{
GUIUtility.hotControl = -1;
AddPoint();
}
protected void AddPoint()
{
SplinePoint newPoint = new SplinePoint(createPoint, createPoint);
newPoint.size = createPointSize;
newPoint.color = createPointColor;
SplinePoint[] newPoints = editor.GetPointsArray();
if (appendMode == AppendMode.End)
{
Dreamteck.ArrayUtility.Add(ref newPoints, newPoint);
lastCreated = newPoints.Length - 1;
}
else
{
Dreamteck.ArrayUtility.Insert(ref newPoints, 0, newPoint);
lastCreated = 0;
}
editor.SetPointsArray(newPoints);
SetPointNormal(lastCreated, createNormal);
SelectPoint(lastCreated);
RegisterChange();
}
protected void SetPointNormal(int index, Vector3 defaultNormal)
{
if (editor.is2D)
{
points[index].normal = Vector3.back;
return;
}
if (normalMode == NormalMode.Default) points[index].normal = defaultNormal;
else
{
Camera editorCamera = SceneView.lastActiveSceneView.camera;
switch (normalMode)
{
case NormalMode.AlignWithCamera: points[index].normal = editorCamera.transform.forward; break;
case NormalMode.LookAtCamera: points[index].normal = Vector3.Normalize(editorCamera.transform.position - points[index].position); break;
case NormalMode.Calculate: PointNormalModule.CalculatePointNormal(points, index, isClosed); break;
case NormalMode.Left: points[index].normal = Vector3.left; break;
case NormalMode.Right: points[index].normal = Vector3.right; break;
case NormalMode.Up: points[index].normal = Vector3.up; break;
case NormalMode.Down: points[index].normal = Vector3.down; break;
case NormalMode.Forward: points[index].normal = Vector3.forward; break;
case NormalMode.Back: points[index].normal = Vector3.back; break;
}
}
}
protected virtual void InsertMode(Vector3 screenCoordinates)
{
double percent = ProjectScreenSpace(screenCoordinates);
editor.evaluate(percent, ref evalResult);
if (editor.eventModule.mouseRight)
{
SplineEditorHandles.DrawCircle(evalResult.position, Quaternion.LookRotation(editorCamera.transform.position - evalResult.position), HandleUtility.GetHandleSize(evalResult.position) * 0.2f);
return;
}
if (SplineEditorHandles.CircleButton(evalResult.position, Quaternion.LookRotation(editorCamera.transform.position - evalResult.position), HandleUtility.GetHandleSize(evalResult.position) * 0.2f, 1.5f, color))
{
SplinePoint newPoint = new SplinePoint(evalResult.position, evalResult.position);
newPoint.size = evalResult.size;
newPoint.color = evalResult.color;
newPoint.normal = evalResult.up;
double floatIndex = (points.Length - 1) * percent;
int pointIndex = Mathf.Clamp(DMath.FloorInt(floatIndex), 0, points.Length - 2);
editor.AddPointAt(pointIndex + 1);
points[pointIndex + 1].SetPoint(newPoint);
SelectPoint(pointIndex);
RegisterChange();
}
}
protected double ProjectScreenSpace(Vector2 screenPoint)
{
float closestDistance = (screenPoint - HandleUtility.WorldToGUIPoint(points[0].position)).sqrMagnitude;
double closestPercent = 0.0;
double moveStep = 1.0 / ((editor.points.Length - 1) * sampleRate);
double add = moveStep;
if (splineType == Spline.Type.Linear) add /= 2.0;
int count = 0;
for (double i = add; i < 1.0; i += add)
{
editor.evaluate(i, ref evalResult);
Vector2 point = HandleUtility.WorldToGUIPoint(evalResult.position);
float dist = (point - screenPoint).sqrMagnitude;
if (dist < closestDistance)
{
closestDistance = dist;
closestPercent = i;
}
count++;
}
return closestPercent;
}
bool GetCreatePointOnPlane(Vector3 normal, Vector3 origin, out Vector3 result)
{
Plane plane = new Plane(normal, origin);
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
float rayDistance;
if (plane.Raycast(ray, out rayDistance))
{
result = ray.GetPoint(rayDistance);
return true;
}
else if (normal == Vector3.zero)
{
result = origin;
return true;
}
else
{
result = ray.GetPoint(0f);
return true;
}
}
bool AxisGrid(Vector3 axis, Color color, out Vector3 origin)
{
float dot = Vector3.Dot(editorCamera.transform.position.normalized, axis);
if (dot < 0f) axis = -axis;
Plane plane = new Plane(axis, Vector3.zero);
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
float rayDistance;
if (plane.Raycast(ray, out rayDistance))
{
origin = ray.GetPoint(rayDistance) + axis * offset;
Handles.color = color;
float distance = 1f;
ray = new Ray(editorCamera.transform.position, -axis);
if (!editorCamera.orthographic && plane.Raycast(ray, out rayDistance)) distance = Vector3.Distance(editorCamera.transform.position + axis * offset, origin);
else if (editorCamera.orthographic) distance = 2f * editorCamera.orthographicSize;
DrawGrid(origin, axis, Vector2.one * distance * 0.3f, distance * 2.5f * 0.03f);
Handles.DrawLine(origin, origin - axis * offset);
Handles.color = Color.white;
return true;
}
else
{
origin = Vector3.zero;
return false;
}
}
void DrawGrid(Vector3 center, Vector3 normal, Vector2 size, float scale)
{
Vector3 right = Vector3.Cross(Vector3.up, normal).normalized;
if (Mathf.Abs(Vector3.Dot(Vector3.up, normal)) >= 0.9999f) right = Vector3.Cross(Vector3.forward, normal).normalized;
Vector3 up = Vector3.Cross(normal, right).normalized;
Vector3 startPoint = center - right * size.x * 0.5f + up * size.y * 0.5f;
float i = 0f;
float add = scale;
while (i <= size.x)
{
Vector3 point = startPoint + right * i;
Handles.DrawLine(point, point - up * size.y);
i += add;
}
i = 0f;
add = scale;
while (i <= size.x)
{
Vector3 point = startPoint - up * i;
Handles.DrawLine(point, point + right * size.x);
i += add;
}
}
void DrawMouseCross()
{
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
Vector3 origin = ray.GetPoint(1f);
float size = 0.4f * HandleUtility.GetHandleSize(origin);
Vector3 a = origin + editorCamera.transform.up * size - editorCamera.transform.right * size;
Vector3 b = origin - editorCamera.transform.up * size + editorCamera.transform.right * size;
Handles.color = Color.red;
Handles.DrawLine(a, b);
a = origin - editorCamera.transform.up * size - editorCamera.transform.right * size;
b = origin + editorCamera.transform.up * size + editorCamera.transform.right * size;
Handles.DrawLine(a, b);
Handles.color = Color.white;
}
private void UpdateVisualizer()
{
if(visualizer == null) visualizer = new Spline(splineType);
visualizer.type = splineType;
visualizer.sampleRate = sampleRate;
if(placementMode == PlacementMode.Insert)
{
visualizer.points = editor.GetPointsArray();
if (isClosed) visualizer.Close();
else if (visualizer.isClosed) visualizer.Break();
return;
}
if (visualizer.points.Length != points.Length + 1)
{
visualizer.points = new SplinePoint[points.Length + 1];
}
SplinePoint newPoint = new SplinePoint(createPoint, createPoint, createNormal, 1f, Color.white);
if (appendMode == AppendMode.End)
{
for (int i = 0; i < points.Length; i++)
{
visualizer.points[i] = points[i].CreateSplinePoint();
}
visualizer.points[visualizer.points.Length - 1] = newPoint;
}
else
{
for (int i = 1; i < visualizer.points.Length; i++)
{
visualizer.points[i] = points[i - 1].CreateSplinePoint();
}
visualizer.points[0] = newPoint;
}
if (isClosed && !visualizer.isClosed)
{
if(visualizer.points.Length >= 3)
{
visualizer.Close();
} else
{
visualizer.Break();
}
}
else if (!isClosed && visualizer.isClosed)
{
visualizer.Break();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: dcb9fe180ed013a44a474b2a4ece59fc
timeCreated: 1476219856
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,87 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class DeletePointModule : PointModule
{
public float deleteRadius = 50f;
Vector2 lastMousePos = Vector2.zero;
public DeletePointModule(SplineEditor editor) : base(editor)
{
}
public override GUIContent GetIconOff()
{
return IconContent("-", "remove", "Delete Points");
}
public override GUIContent GetIconOn()
{
return IconContent("-", "remove_on", "Delete Points");
}
public override void LoadState()
{
base.LoadState();
deleteRadius = LoadFloat("deleteRadius", 50f);
}
public override void SaveState()
{
base.SaveState();
SaveFloat("deleteRadius", deleteRadius);
}
protected override void OnDrawInspector()
{
deleteRadius = EditorGUILayout.FloatField("Brush Radius", deleteRadius);
}
protected override void OnDrawScene()
{
if (selectedPoints.Count > 0) ClearSelection();
Handles.BeginGUI();
Handles.color = Color.red;
Handles.DrawWireDisc(Event.current.mousePosition, -Vector3.forward, deleteRadius);
Handles.color = Color.white;
Handles.EndGUI();
if (!eventModule.alt && SceneView.currentDrawingSceneView.camera.pixelRect.Contains(Event.current.mousePosition)) {
if (editor.eventModule.mouseLeftDown) GUIUtility.hotControl = GUIUtility.GetControlID(FocusType.Passive);
if (editor.eventModule.mouseLeft && lastMousePos != Event.current.mousePosition)
{
lastMousePos = Event.current.mousePosition;
RunDeleteMethod();
}
}
Repaint();
}
void RunDeleteMethod()
{
Camera cam = SceneView.currentDrawingSceneView.camera;
Vector3 mousPos = Event.current.mousePosition;
Rect mouseRect = new Rect(mousPos.x - deleteRadius, mousPos.y - deleteRadius, deleteRadius * 2f, deleteRadius * 2f);
for (int i = 0; i < points.Length; i++)
{
Vector3 localPos = cam.transform.InverseTransformPoint(points[i].position);
if (localPos.z < 0f) continue;
Vector2 screenPos = HandleUtility.WorldToGUIPoint(points[i].position);
if (mouseRect.Contains(screenPos))
{
if (Vector2.Distance(mousPos, screenPos) <= deleteRadius)
{
DeletePoint(i);
editor.ApplyModifiedProperties(true);
i--;
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 031571ebca44b8a47a9af1984caeeff9
timeCreated: 1476219856
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,350 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using UnityEditor;
public class MainPointModule : PointModule
{
public bool excludeSelected = false;
public int minimumRectSize = 5;
private Vector2 _rectStart = Vector2.zero;
private Vector2 _rectEnd = Vector2.zero;
private Rect _dragRect;
private bool _drag = false;
private bool _finalizeDrag = false;
private bool _pointsMoved = false;
private bool _tangentMode = false;
private Color _bgColor = Color.black;
public static bool isSelecting => __isDragging;
private static bool __holdInteraction = false;
private static bool __isDragging = false;
public bool isDragging
{
get
{
return _drag && _dragRect.width >= minimumRectSize && _dragRect.height >= minimumRectSize;
}
}
public bool tangentMode => _tangentMode;
public MainPointModule(SplineEditor editor) : base(editor)
{
_bgColor = Color.Lerp(color, Color.black, 0.75f);
_bgColor.a = 0.75f;
}
public static void HoldInteraction()
{
__holdInteraction = true;
}
protected override void OnDrawInspector()
{
string[] options = new string[points.Length + 4];
options[0] = "- - -";
if (selectedPoints.Count > 1) options[0] = "- Multiple -";
options[1] = "All";
options[2] = "None";
options[3] = "Inverse";
for (int i = 0; i < points.Length; i++)
{
options[i + 4] = "Point " + (i + 1);
if (splineType == Spline.Type.Bezier)
{
switch (points[i].type)
{
case SplinePoint.Type.Broken: options[i + 4] += " - Broken"; break;
case SplinePoint.Type.SmoothFree: options[i + 4] += " - Smooth Free"; break;
case SplinePoint.Type.SmoothMirrored: options[i + 4] += " - Smooth Mirrored"; break;
}
}
}
int option = 0;
if (selectedPoints.Count == 1) {
option = selectedPoints[0] + 4;
}
option = EditorGUILayout.Popup("Select", option, options);
switch (option)
{
case 1:
ClearSelection();
for (int i = 0; i < points.Length; i++) AddPointSelection(i);
break;
case 2:
ClearSelection();
break;
case 3:
InverseSelection();
break;
}
if(option >= 4)
{
SelectPoint(option - 4);
}
if (isDragging)
{
if (!eventModule.mouseLeft)
{
FinishDrag();
}
}
}
protected override void OnDrawScene()
{
if (eventModule.v) return;
Transform camTransform = SceneView.currentDrawingSceneView.camera.transform;
if (!_drag)
{
if (_finalizeDrag)
{
if (_dragRect.width > 0f && _dragRect.height > 0f)
{
if (!eventModule.control) ClearSelection();
for (int i = 0; i < points.Length; i++)
{
Vector2 guiPoint = HandleUtility.WorldToGUIPoint(points[i].position);
if (_dragRect.Contains(guiPoint))
{
Vector3 local = camTransform.InverseTransformPoint(points[i].position);
if (local.z >= 0f)
{
AddPointSelection(i);
}
}
}
}
_finalizeDrag = false;
}
}
else
{
if (__holdInteraction)
{
CancelDrag();
}
else
{
_rectEnd = Event.current.mousePosition;
_dragRect = new Rect(Mathf.Min(_rectStart.x, _rectEnd.x), Mathf.Min(_rectStart.y, _rectEnd.y), Mathf.Abs(_rectEnd.x - _rectStart.x), Mathf.Abs(_rectEnd.y - _rectStart.y));
if (_dragRect.width >= minimumRectSize && _dragRect.height >= minimumRectSize)
{
Color col = highlightColor;
col.a = 0.4f;
Handles.BeginGUI();
EditorGUI.DrawRect(_dragRect, col);
Handles.EndGUI();
SceneView.RepaintAll();
}
}
}
TextAnchor originalAlignment = GUI.skin.label.alignment;
Color originalColor = GUI.skin.label.normal.textColor;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUI.skin.label.normal.textColor = color;
if (selectedPoints.Count > 1)
{
_tangentMode = false;
}
for (int i = 0; i < points.Length; i++)
{
bool isSelected = selectedPoints.Contains(i);
Vector3 lastPos = points[i].position;
if (splineType == Spline.Type.Bezier && isSelected)
{
Handles.color = color;
if (Event.current.type == EventType.Repaint)
Handles.DrawDottedLine(points[i].position, points[i].tangent, 4f);
if (Event.current.type == EventType.Repaint)
Handles.DrawDottedLine(points[i].position, points[i].tangent2, 4f);
if (_tangentMode && selectedPoints.Count == 1)
{
Handles.color = highlightColor;
}
Vector3 lastTangentPos = points[i].tangent;
Vector3 newPos = SplineEditorHandles.FreeMoveCircle(points[i].tangent, HandleUtility.GetHandleSize(points[i].tangent) * 0.22f);
if (lastTangentPos != newPos)
{
points[i].SetTangentPosition(newPos);
RegisterChange();
}
lastTangentPos = points[i].tangent2;
newPos = SplineEditorHandles.FreeMoveCircle(points[i].tangent2, HandleUtility.GetHandleSize(points[i].tangent2) * 0.22f);
if (!__holdInteraction && lastTangentPos != newPos)
{
points[i].SetTangent2Position(newPos);
RegisterChange();
}
Handles.color = color;
}
Handles.color = Color.clear;
if (showPointNumbers && camTransform.InverseTransformPoint(points[i].position).z > 0f)
{
if(Event.current.type == EventType.Repaint)
{
Handles.Label(points[i].position + Camera.current.transform.up * HandleUtility.GetHandleSize(points[i].position) * 0.3f, (i + 1).ToString());
}
}
if (!eventModule.alt && !__holdInteraction)
{
if (excludeSelected && isSelected)
{
SplineEditorHandles.FreeMoveRectangle(points[i].position, HandleUtility.GetHandleSize(points[i].position) * 0.1f);
}
else
{
points[i].SetPosition(SplineEditorHandles.FreeMoveRectangle(points[i].position, HandleUtility.GetHandleSize(points[i].position) * 0.1f));
}
}
if (!__holdInteraction && lastPos != points[i].position)
{
_tangentMode = false;
_pointsMoved = true;
if (isSelected)
{
for (int n = 0; n < selectedPoints.Count; n++)
{
if (selectedPoints[n] == i) continue;
points[selectedPoints[n]].SetPosition(points[selectedPoints[n]].position + (points[i].position - lastPos));
}
}
else
{
SelectPoint(i);
}
RegisterChange();
}
if (!_pointsMoved && !eventModule.alt && editor.eventModule.mouseLeftUp)
{
if(SplineEditorHandles.HoverArea(points[i].position, 0.12f))
{
if (eventModule.control && selectedPoints.Contains(i))
{
DeselectPoint(i);
}
else
{
if (eventModule.shift) ShiftSelect(i, points.Length);
else if (eventModule.control) AddPointSelection(i);
else SelectPoint(i);
}
_tangentMode = false;
} else if(splineType == Spline.Type.Bezier)
{
if (SplineEditorHandles.HoverArea(points[i].tangent, 0.23f))
{
if (eventModule.shift) ShiftSelect(i, points.Length);
else if (eventModule.control) AddPointSelection(i);
else SelectPoint(i);
_tangentMode = true;
}
}
}
if (!excludeSelected || !isSelected)
{
if (Event.current.type == EventType.Repaint)
{
SplineEditorHandles.DrawPoint(points[i].position, isSelected && (!_tangentMode || selectedPoints.Count != 1));
}
}
}
GUI.skin.label.alignment = originalAlignment;
GUI.skin.label.normal.textColor = originalColor;
if (isDragging && Event.current.type == EventType.MouseDrag)
{
bool mouseIsOutside = false;
#if UNITY_2022_1_OR_NEWER
Vector2 mousePos = Event.current.mousePosition;
Vector2 viewportSize = new Vector2(_currentSceneView.position.width, _currentSceneView.position.height);
mouseIsOutside = mousePos.x <= 0 || mousePos.y <= 0f || mousePos.x >= viewportSize.x || mousePos.y >= viewportSize.y;
#else
mouseIsOutside = !SceneView.currentDrawingSceneView.camera.pixelRect.Contains(Event.current.mousePosition);
#endif
if (eventModule.alt || mouseIsOutside || !eventModule.mouseLeft)
{
FinishDrag();
}
}
if (eventModule.mouseLeftUp)
{
_pointsMoved = false;
}
__holdInteraction = false;
__isDragging = isDragging;
}
void ShiftSelect(int index, int pointCount)
{
if (selectedPoints.Count == 0)
{
AddPointSelection(index);
return;
}
int minSelected = pointCount-1, maxSelected = 0;
for (int i = 0; i < selectedPoints.Count; i++)
{
if (minSelected > selectedPoints[i]) minSelected = selectedPoints[i];
if (maxSelected < selectedPoints[i]) maxSelected = selectedPoints[i];
}
if(index > maxSelected)
{
for (int i = maxSelected + 1; i <= index; i++) AddPointSelection(i);
} else if(index < minSelected)
{
for (int i = minSelected-1; i >= index; i--) AddPointSelection(i);
} else
{
for (int i = minSelected + 1; i <= index; i++) AddPointSelection(i);
}
}
public void StartDrag(Vector2 position)
{
if (__holdInteraction) return;
_rectStart = position;
_drag = true;
_finalizeDrag = false;
}
public void FinishDrag()
{
if (!_drag) return;
_drag = false;
_finalizeDrag = true;
}
public void CancelDrag()
{
_drag = false;
_finalizeDrag = false;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 222164afd4e1e1845bca6b747eca74fb
timeCreated: 1476960765
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,371 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
public class PointMirrorModule : PointTransformModule
{
public enum Axis { X, Y, Z }
public Axis axis = Axis.X;
public bool flip = false;
public float weldDistance = 0f;
Vector3 mirrorCenter = Vector3.zero;
private SplinePoint[] mirrored = new SplinePoint[0];
public PointMirrorModule(SplineEditor editor) : base(editor)
{
LoadState();
}
public override GUIContent GetIconOff()
{
return IconContent("||", "mirror", "Mirror Path");
}
public override GUIContent GetIconOn()
{
return IconContent("||", "mirror_on", "Mirror Path");
}
public override void LoadState()
{
axis = (Axis)LoadInt("axis");
flip = LoadBool("flip");
weldDistance = LoadFloat("weldDistance");
}
public override void SaveState()
{
base.SaveState();
SaveInt("axis", (int)axis);
SaveBool("flip", flip);
SaveFloat("weldDistance", weldDistance);
}
public override void Select()
{
base.Select();
ClearSelection();
DoMirror();
SetDirty();
}
public override void Deselect()
{
if (IsDirty())
{
if (EditorUtility.DisplayDialog("Unapplied Mirror Operation", "There is an unapplied mirror operation. Do you want to apply the changes?", "Apply", "Revert"))
{
Apply();
}
else
{
Revert();
}
}
base.Deselect();
}
protected override void OnDrawInspector()
{
if (selectedPoints.Count > 0) ClearSelection();
EditorGUI.BeginChangeCheck();
axis = (Axis)EditorGUILayout.EnumPopup("Axis", axis);
flip = EditorGUILayout.Toggle("Flip", flip);
weldDistance = EditorGUILayout.FloatField("Weld Distance", weldDistance);
mirrorCenter = EditorGUILayout.Vector3Field("Center", mirrorCenter);
if (EditorGUI.EndChangeCheck()) DoMirror();
if (IsDirty())
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Apply")) Apply();
if (GUILayout.Button("Revert")) Revert();
EditorGUILayout.EndHorizontal();
}
}
protected override void OnDrawScene()
{
if (selectedPoints.Count > 0) ClearSelection();
Vector3 worldCenter = TransformPosition(mirrorCenter);
Vector3 lastCenter = worldCenter;
worldCenter = Handles.PositionHandle(worldCenter, rotation);
mirrorCenter = InverseTransformPosition(worldCenter);
DrawMirror();
if (lastCenter != worldCenter) DoMirror();
selectedPoints.Clear();
}
public void DoMirror()
{
List<int> half = GetHalf(ref originalPoints);
int welded = -1;
if (half.Count > 0)
{
if (flip)
{
if (IsWeldable(originalPoints[half[0]]))
{
welded = half[0];
half.RemoveAt(0);
}
}
else
{
if (IsWeldable(originalPoints[half[half.Count - 1]]))
{
welded = half[half.Count - 1];
half.RemoveAt(half.Count - 1);
}
}
int offset = welded >= 0 ? 1 : 0;
int mirroredLength = half.Count * 2 + offset;
if(mirrored.Length != mirroredLength) mirrored = new SplinePoint[mirroredLength];
for (int i = 0; i < half.Count; i++)
{
if (flip)
{
mirrored[i] = new SplinePoint(originalPoints[half[(half.Count - 1) - i]]);
mirrored[i + half.Count + offset] = GetMirrored(originalPoints[half[i]]);
SwapTangents(ref mirrored[i]);
SwapTangents(ref mirrored[i + half.Count + offset]);
}
else
{
mirrored[i] = new SplinePoint(originalPoints[half[i]]);
mirrored[i + half.Count + offset] = GetMirrored(originalPoints[half[(half.Count - 1) - i]]);
}
}
if (welded >= 0)
{
mirrored[half.Count] = new SplinePoint(originalPoints[welded]);
if (flip) SwapTangents(ref mirrored[half.Count]);
MakeMiddlePoint(ref mirrored[half.Count]);
}
if (isClosed && mirrored.Length > 0)
{
MakeMiddlePoint(ref mirrored[0]);
mirrored[mirrored.Length - 1] = new SplinePoint(mirrored[0]);
}
}
else mirrored = new SplinePoint[0];
editor.SetPointsArray(mirrored);
RegisterChange();
SetDirty();
}
void SwapTangents(ref SplinePoint point)
{
Vector3 temp = point.tangent;
point.tangent = point.tangent2;
point.tangent2 = temp;
}
void MakeMiddlePoint(ref SplinePoint point)
{
point.type = SplinePoint.Type.Broken;
InverseTransformPoint(ref point);
Vector3 newPos = point.position;
switch (axis)
{
case Axis.X:
newPos.x = mirrorCenter.x;
point.SetPosition(newPos);
if ((point.tangent.x >= mirrorCenter.x && flip) || (point.tangent.x <= mirrorCenter.x && !flip))
{
point.tangent2 = point.tangent;
point.SetTangent2X(point.position.x + (point.position.x - point.tangent.x));
}
else
{
point.tangent = point.tangent2;
point.SetTangentX(point.position.x + (point.position.x - point.tangent2.x));
}
break;
case Axis.Y:
newPos.y = mirrorCenter.y;
point.SetPosition(newPos);
if ((point.tangent.y >= mirrorCenter.y && flip) || (point.tangent.y <= mirrorCenter.y && !flip))
{
point.tangent2 = point.tangent;
point.SetTangent2Y(point.position.y + (point.position.y - point.tangent.y));
}
else
{
point.tangent = point.tangent2;
point.SetTangentY(point.position.y + (point.position.y - point.tangent2.y));
}
break;
case Axis.Z:
newPos.z = mirrorCenter.z;
point.SetPosition(newPos);
if ((point.tangent.z >= mirrorCenter.z && flip) || (point.tangent.z <= mirrorCenter.z && !flip))
{
point.tangent2 = point.tangent;
point.SetTangent2Z(point.position.z + (point.position.z - point.tangent.z));
}
else
{
point.tangent = point.tangent2;
point.SetTangentZ(point.position.z + (point.position.z - point.tangent2.z));
}
break;
}
TransformPoint(ref point);
}
bool IsWeldable(SplinePoint point)
{
switch (axis)
{
case Axis.X:
if (Mathf.Abs(point.position.x - mirrorCenter.x) <= weldDistance) return true;
break;
case Axis.Y:
if (Mathf.Abs(point.position.y - mirrorCenter.y) <= weldDistance) return true;
break;
case Axis.Z:
if (Mathf.Abs(point.position.z - mirrorCenter.z) <= weldDistance) return true;
break;
}
return false;
}
void DrawMirror()
{
Vector3[] points = new Vector3[4];
Color color = Color.white;
Vector3 worldCenter = TransformPosition(mirrorCenter);
float size = HandleUtility.GetHandleSize(worldCenter);
Vector3 forward = rotation * Vector3.forward * size;
Vector3 back = -forward;
Vector3 right = rotation * Vector3.right * size;
Vector3 left = -right;
Vector3 up = rotation * Vector3.up * size;
Vector3 down = -up;
switch (axis)
{
case Axis.X:
points[0] = back + up;
points[1] = forward + up;
points[2] = forward + down;
points[3] = back + down;
color = Color.red;
break;
case Axis.Y:
points[0] = back + left;
points[1] = forward + left;
points[2] = forward + right;
points[3] = back + right;
color = Color.green;
break;
case Axis.Z:
points[0] = left + up;
points[1] = right + up;
points[2] = right + down;
points[3] = left + down;
color = Color.blue;
break;
}
Handles.color = color;
Handles.DrawLine(worldCenter + points[0], worldCenter + points[1]);
Handles.DrawLine(worldCenter + points[1], worldCenter + points[2]);
Handles.DrawLine(worldCenter + points[2], worldCenter + points[3]);
Handles.DrawLine(worldCenter + points[3], worldCenter + points[0]);
Handles.color = Color.white;
}
SplinePoint GetMirrored(SplinePoint source)
{
SplinePoint newPoint = new SplinePoint(source);
InverseTransformPoint(ref newPoint);
switch (axis)
{
case Axis.X:
newPoint.SetPositionX(mirrorCenter.x - (newPoint.position.x - mirrorCenter.x));
newPoint.SetNormalX(-newPoint.normal.x);
newPoint.SetTangentX(mirrorCenter.x - (newPoint.tangent.x - mirrorCenter.x));
newPoint.SetTangent2X(mirrorCenter.x - (newPoint.tangent2.x - mirrorCenter.x));
break;
case Axis.Y:
newPoint.SetPositionY(mirrorCenter.y - (newPoint.position.y - mirrorCenter.y));
newPoint.SetNormalY(-newPoint.normal.y);
newPoint.SetTangentY(mirrorCenter.y - (newPoint.tangent.y - mirrorCenter.y));
newPoint.SetTangent2Y(mirrorCenter.y - (newPoint.tangent2.y - mirrorCenter.y));
break;
case Axis.Z:
newPoint.SetPositionZ(mirrorCenter.z - (newPoint.position.z - mirrorCenter.z));
newPoint.SetNormalZ(-newPoint.normal.z);
newPoint.SetTangentZ(mirrorCenter.z - (newPoint.tangent.z - mirrorCenter.z));
newPoint.SetTangent2Z(mirrorCenter.z - (newPoint.tangent2.z - mirrorCenter.z));
break;
}
SwapTangents(ref newPoint);
TransformPoint(ref newPoint);
return newPoint;
}
List<int> GetHalf(ref SplinePoint[] points)
{
List<int> found = new List<int>();
switch (axis)
{
case Axis.X:
for (int i = 0; i < points.Length; i++)
{
if (flip)
{
if (InverseTransformPosition(points[i].position).x >= mirrorCenter.x) found.Add(i);
}
else
{
if (InverseTransformPosition(points[i].position).x <= mirrorCenter.x) found.Add(i);
}
}
break;
case Axis.Y:
for (int i = 0; i < points.Length; i++)
{
if (flip)
{
if (InverseTransformPosition(points[i].position).y >= mirrorCenter.y) found.Add(i);
else
{
if (InverseTransformPosition(points[i].position).y <= mirrorCenter.y) found.Add(i);
}
}
}
break;
case Axis.Z:
for (int i = 0; i < points.Length; i++)
{
if (flip)
{
if (InverseTransformPosition(points[i].position).z >= mirrorCenter.z) found.Add(i);
}
else
{
if (InverseTransformPosition(points[i].position).z <= mirrorCenter.z) found.Add(i);
}
}
break;
}
return found;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0562a8339f410c04180d98ba21fdafb3
timeCreated: 1476814299
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,344 @@
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;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b030b7d8eb93a004185129c729549ba8
timeCreated: 1476220001
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,162 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class PointMoveModule : PointTransformModule
{
public bool snap = false;
public float snapGridSize = 1f;
public bool surfaceMode = false;
public float surfaceOffset = 0f;
public LayerMask surfaceLayerMask = ~0;
private bool useTangentHandles => editor.mainModule.tangentMode || editor.selectedPoints.Count != 1;
public PointMoveModule(SplineEditor editor) : base(editor)
{
}
public override GUIContent GetIconOff()
{
return EditorGUIUtility.IconContent("MoveTool");
}
public override GUIContent GetIconOn()
{
return EditorGUIUtility.IconContent("MoveTool On");
}
public override void LoadState()
{
base.LoadState();
snap = LoadBool("snap");
snapGridSize = LoadFloat("snapGridSize", 0.5f);
surfaceOffset = LoadFloat("surfaceOffset", 0f);
surfaceMode = LoadBool("surfaceMode");
surfaceLayerMask = LoadInt("surfaceLayerMask", ~0);
}
public override void SaveState()
{
base.SaveState();
SaveBool("snap", snap);
SaveFloat("snapGridSize", snapGridSize);
SaveFloat("surfaceOffset", surfaceOffset);
SaveBool("surfaceMode", surfaceMode);
SaveInt("surfaceLayerMask", surfaceLayerMask);
}
public override void BeforeSceneDraw(SceneView current)
{
base.BeforeSceneDraw(current);
if (Event.current.type == EventType.MouseUp) GetRotation();
}
protected override void OnDrawInspector()
{
editSpace = (EditSpace)EditorGUILayout.EnumPopup("Edit Space", editSpace);
surfaceMode = EditorGUILayout.Toggle("Move On Surface", surfaceMode);
if (surfaceMode)
{
surfaceLayerMask = DreamteckEditorGUI.LayermaskField("Surface Mask", surfaceLayerMask);
surfaceOffset = EditorGUILayout.FloatField("Surface Offset", surfaceOffset);
}
snap = EditorGUILayout.Toggle("Snap to Grid", snap);
if (snap)
{
snapGridSize = EditorGUILayout.FloatField("Grid Size", snapGridSize);
if (snapGridSize < 0.0001f) snapGridSize = 0.0001f;
}
}
private Vector3 SurfaceMoveHandle(Vector3 inputPosition, float size = 0.2f)
{
Vector3 lastPosition = inputPosition;
inputPosition = SplineEditorHandles.FreeMoveHandle(inputPosition, HandleUtility.GetHandleSize(inputPosition) * size, Vector3.zero, Handles.CircleHandleCap);
if (lastPosition != inputPosition)
{
Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity, surfaceLayerMask))
{
inputPosition = hit.point + hit.normal * surfaceOffset;
Handles.DrawLine(hit.point, hit.point + hit.normal * HandleUtility.GetHandleSize(hit.point) * 0.5f);
}
}
return inputPosition;
}
protected override void OnDrawScene()
{
if (selectedPoints.Count == 0) return;
Vector3 c = selectionCenter;
Vector3 lastPos = c;
if (surfaceMode)
{
c = SurfaceMoveHandle(c, 0.2f);
}
else
{
c = Handles.PositionHandle(c, rotation);
}
if (lastPos != c)
{
RegisterChange();
for (int i = 0; i < selectedPoints.Count; i++)
{
points[selectedPoints[i]].SetPosition(points[selectedPoints[i]].position + (c - lastPos));
if (snap) points[selectedPoints[i]].SetPosition(SnapPoint(points[selectedPoints[i]].position));
}
}
if (splineType == Spline.Type.Bezier && selectedPoints.Count == 1 && useTangentHandles)
{
int index = selectedPoints[0];
lastPos = points[index].tangent;
Vector3 newPos = Vector3.zero;
if (surfaceMode)
{
newPos = SurfaceMoveHandle(points[index].tangent, 0.15f);
} else
{
newPos = Handles.PositionHandle(points[index].tangent, rotation);
}
if (snap) newPos = SnapPoint(newPos);
if (newPos != lastPos)
{
RegisterChange();
}
points[index].SetTangentPosition(newPos);
lastPos = points[index].tangent2;
if (surfaceMode)
{
newPos = SurfaceMoveHandle(points[index].tangent2, 0.15f);
} else
{
newPos = Handles.PositionHandle(points[index].tangent2, rotation);
}
if (snap) newPos = SnapPoint(newPos);
if (newPos != lastPos)
{
RegisterChange();
}
points[index].SetTangent2Position(newPos);
}
}
public Vector3 SnapPoint(Vector3 point)
{
point.x = Mathf.RoundToInt(point.x / snapGridSize) * snapGridSize;
point.y = Mathf.RoundToInt(point.y / snapGridSize) * snapGridSize;
point.z = Mathf.RoundToInt(point.z / snapGridSize) * snapGridSize;
return point;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 37e5af750f2ba6a49bd760d3a39d1309
timeCreated: 1476219856
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,290 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using UnityEditor;
public class PointNormalModule : PointModule
{
public enum NormalMode { Auto, Free }
public NormalMode normalMode = NormalMode.Auto;
SplineSample evalResult = new SplineSample();
private string[] _normalOperations = new string[0];
private int _normalOperation = 0;
private NormalRotationWindow _rotationWindow;
public PointNormalModule(SplineEditor editor) : base(editor)
{
_normalOperations = new string[] { "Flip",
"Look At Camera",
"Align with Camera",
"Calculate",
"Look Left",
"Look Right",
"Look Up",
"Look Down",
"Look Forward",
"Look Back",
"Look At Avg. Center",
"Perpendicular to Spline",
"Rotate Degrees"
};
}
public override void LoadState()
{
base.LoadState();
normalMode = (NormalMode)LoadInt("normalMode");
_normalOperation = LoadInt("normalOperation");
}
public override void SaveState()
{
base.SaveState();
SaveInt("normalMode", (int)normalMode);
SaveInt("normalOperation", (int)_normalOperation);
if (_rotationWindow != null)
{
_rotationWindow.Close();
}
}
public override GUIContent GetIconOff()
{
return IconContent("N", "normal", "Set Point Normals");
}
public override GUIContent GetIconOn()
{
return IconContent("N", "normal_on", "Set Point Normals");
}
private void OnNormalRotationApplied()
{
editor.ApplyModifiedProperties(true);
RegisterChange();
SceneView.RepaintAll();
}
void SetNormals(int mode)
{
if (mode == 12)
{
_rotationWindow = EditorWindow.GetWindow<NormalRotationWindow>(true);
_rotationWindow.Init(this, OnNormalRotationApplied);
return;
}
Vector3 avg = Vector3.zero;
for (int i = 0; i < selectedPoints.Count; i++) avg += points[selectedPoints[i]].position;
if (selectedPoints.Count > 1) avg /= selectedPoints.Count;
Camera editorCamera = SceneView.lastActiveSceneView.camera;
for (int i = 0; i < selectedPoints.Count; i++)
{
switch (mode)
{
case 0: points[selectedPoints[i]].normal *= -1; break;
case 1: points[selectedPoints[i]].normal = Vector3.Normalize(editorCamera.transform.position - points[selectedPoints[i]].position); break;
case 2: points[selectedPoints[i]].normal = editorCamera.transform.forward; break;
case 3: points[selectedPoints[i]].normal = CalculatePointNormal(points, selectedPoints[i], isClosed); break;
case 4: points[selectedPoints[i]].normal = Vector3.left; break;
case 5: points[selectedPoints[i]].normal = Vector3.right; break;
case 6: points[selectedPoints[i]].normal = Vector3.up; break;
case 7: points[selectedPoints[i]].normal = Vector3.down; break;
case 8: points[selectedPoints[i]].normal = Vector3.forward; break;
case 9: points[selectedPoints[i]].normal = Vector3.back; break;
case 10: points[selectedPoints[i]].normal = Vector3.Normalize(avg - points[selectedPoints[i]].position); break;
case 11:
SplineSample result = new SplineSample();
editor.evaluateAtPoint(selectedPoints[i], ref result);
points[selectedPoints[i]].normal = Vector3.Cross(result.forward, result.right).normalized;
break;
}
}
RegisterChange();
SceneView.RepaintAll();
}
public static Vector3 CalculatePointNormal(SerializedSplinePoint[] points, int index, bool isClosed)
{
if (points.Length < 3)
{
Debug.Log("Spline needs to have at least 3 control points in order to calculate normals");
return Vector3.zero;
}
Vector3 side1 = Vector3.zero;
Vector3 side2 = Vector3.zero;
if (index == 0)
{
if (isClosed)
{
side1 = points[index].position - points[index + 1].position;
side2 = points[index].position - points[points.Length - 2].position;
}
else
{
side1 = points[0].position - points[1].position;
side2 = points[0].position - points[2].position;
}
}
else if (index == points.Length - 1)
{
side1 = points[points.Length - 1].position - points[points.Length - 3].position;
side2 = points[points.Length - 1].position - points[points.Length - 2].position;
}
else
{
side1 = points[index].position - points[index + 1].position;
side2 = points[index].position - points[index - 1].position;
}
return Vector3.Cross(side1.normalized, side2.normalized).normalized;
}
protected override void OnDrawInspector()
{
if (editor.is2D)
{
EditorGUILayout.LabelField("Normal editing unavailable in 2D Mode", EditorStyles.centeredGreyMiniLabel);
return;
}
normalMode = (NormalMode)EditorGUILayout.EnumPopup("Normal Mode", normalMode);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Normal Operations");
EditorGUILayout.BeginVertical();
_normalOperation = EditorGUILayout.Popup(_normalOperation, _normalOperations);
if (GUILayout.Button("Apply"))
{
SetNormals(_normalOperation);
}
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
}
protected override void OnDrawScene()
{
if (editor.is2D) return;
for (int i = 0; i < selectedPoints.Count; i++)
{
if (normalMode == NormalMode.Free) FreeNormal(selectedPoints[i]);
else AutoNormal(selectedPoints[i]);
}
}
void AutoNormal(int index)
{
editor.evaluateAtPoint(index, ref evalResult);
Handles.color = highlightColor;
Handles.DrawWireDisc(points[index].position, evalResult.forward, HandleUtility.GetHandleSize(points[index].position) * 0.5f);
Handles.color = color;
Matrix4x4 matrix = Matrix4x4.TRS(points[index].position, evalResult.rotation, Vector3.one);
Vector3 pos = points[index].position + points[index].normal * HandleUtility.GetHandleSize(points[index].position) * 0.5f;
Handles.DrawLine(points[index].position, pos);
Vector3 lastPos = pos;
Vector3 lastLocalPos = matrix.inverse.MultiplyPoint(pos);
pos = SplineEditorHandles.FreeMoveHandle(pos, HandleUtility.GetHandleSize(pos) * 0.1f, Vector3.zero, Handles.CircleHandleCap);
if (pos != lastPos)
{
pos = matrix.inverse.MultiplyPoint(pos);
Vector3 delta = pos - lastLocalPos;
for (int n = 0; n < selectedPoints.Count; n++)
{
if (selectedPoints[n] == index) continue;
editor.evaluateAtPoint(selectedPoints[n], ref evalResult);
Matrix4x4 localMatrix = Matrix4x4.TRS(points[selectedPoints[n]].position, evalResult.rotation, Vector3.one);
Vector3 localPos = localMatrix.inverse.MultiplyPoint(points[selectedPoints[n]].position + points[selectedPoints[n]].normal * HandleUtility.GetHandleSize(points[selectedPoints[n]].position) * 0.5f);
localPos += delta;
localPos.z = 0f;
points[selectedPoints[n]].normal = (localMatrix.MultiplyPoint(localPos) - points[selectedPoints[n]].position).normalized;
}
pos.z = 0f;
pos = matrix.MultiplyPoint(pos);
points[index].normal = (pos - points[index].position).normalized;
RegisterChange();
}
}
void FreeNormal(int index)
{
Handles.color = highlightColor;
Handles.DrawWireDisc(points[index].position, points[index].normal, HandleUtility.GetHandleSize(points[index].position) * 0.25f);
Handles.DrawWireDisc(points[index].position, points[index].normal, HandleUtility.GetHandleSize(points[index].position) * 0.5f);
Handles.color = color;
Handles.DrawLine(points[index].position, points[index].position + HandleUtility.GetHandleSize(points[index].position) * points[index].normal);
Vector3 normalPos = points[index].position + points[index].normal * HandleUtility.GetHandleSize(points[index].position);
Vector3 lastNormal = points[index].normal;
normalPos = SplineEditorHandles.FreeMoveCircle(normalPos, HandleUtility.GetHandleSize(normalPos) * 0.1f);
normalPos -= points[index].position;
normalPos.Normalize();
if (normalPos == Vector3.zero) normalPos = Vector3.up;
if (lastNormal != normalPos)
{
Debug.Log(Random.Range(0, 10000));
points[index].normal = normalPos;
Quaternion delta = Quaternion.FromToRotation(lastNormal, normalPos);
for (int n = 0; n < selectedPoints.Count; n++)
{
if (selectedPoints[n] == index) continue;
points[selectedPoints[n]].normal = delta * points[selectedPoints[n]].normal;
}
RegisterChange();
}
}
private class NormalRotationWindow : EditorWindow
{
private float _angle = 0f;
private PointNormalModule _normalModule;
private System.Action _onRotationApplied;
public void Init(PointNormalModule module, System.Action onRotationApplied)
{
_normalModule = module;
_onRotationApplied = onRotationApplied;
titleContent = new GUIContent("Rotate Normal");
minSize = maxSize = new Vector2(240, 90);
_angle = EditorPrefs.GetFloat("Dreamteck.Splines.Editor.PointNormalModule.NormalRotationWindow.angle", 0f);
}
private void OnGUI()
{
if (Event.current.type == EventType.KeyDown && (Event.current.keyCode == KeyCode.KeypadEnter || Event.current.keyCode == KeyCode.Return))
{
ApplyRotationAndClose();
}
_angle = EditorGUILayout.FloatField("Angle", _angle);
if (GUILayout.Button("Rotate"))
{
ApplyRotationAndClose();
}
}
private void ApplyRotationAndClose()
{
SplineSample sample = new SplineSample();
for (int i = 0; i < _normalModule.selectedPoints.Count; i++)
{
int pointIndex = _normalModule.selectedPoints[i];
_normalModule.editor.evaluateAtPoint(pointIndex, ref sample);
Quaternion rotation = Quaternion.AngleAxis(-_angle, sample.forward);
_normalModule.points[pointIndex].normal = rotation * _normalModule.points[pointIndex].normal;
_normalModule.points[pointIndex].changed = true;
}
if (_onRotationApplied != null)
{
_onRotationApplied();
}
EditorPrefs.SetFloat("Dreamteck.Splines.Editor.PointNormalModule.NormalRotationWindow.angle", _angle);
Close();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f9bb1bdae9d59a748a61453d1696598f
timeCreated: 1476219856
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class PointRotateModule : PointTransformModule
{
public bool rotateNormals = true;
public bool rotateTangents = true;
public PointRotateModule(SplineEditor editor) : base(editor)
{
}
public override GUIContent GetIconOff()
{
return EditorGUIUtility.IconContent("RotateTool");
}
public override GUIContent GetIconOn()
{
return EditorGUIUtility.IconContent("RotateTool On");
}
public override void LoadState()
{
base.LoadState();
rotateNormals = LoadBool("rotateNormals");
rotateTangents = LoadBool("rotateTangents");
}
public override void SaveState()
{
base.SaveState();
SaveBool("rotateNormals", rotateNormals);
SaveBool("rotateTangents", rotateTangents);
}
protected override void OnDrawInspector()
{
editSpace = (EditSpace)EditorGUILayout.EnumPopup("Edit Space", editSpace);
rotateNormals = EditorGUILayout.Toggle("Rotate Normals", rotateNormals);
rotateTangents = EditorGUILayout.Toggle("Rotate Tangents", rotateTangents);
}
protected override void OnDrawScene()
{
if (selectedPoints.Count == 0) return;
if (rotateNormals)
{
Handles.color = new Color(Color.yellow.r, Color.yellow.g, Color.yellow.b, 0.4f);
for (int i = 0; i < selectedPoints.Count; i++)
{
Vector3 normal = points[selectedPoints[i]].normal;
normal *= HandleUtility.GetHandleSize(points[selectedPoints[i]].position);
Handles.DrawLine(points[selectedPoints[i]].position, points[selectedPoints[i]].position + normal);
SplineEditorHandles.DrawArrowCap(points[selectedPoints[i]].position + normal, Quaternion.LookRotation(normal), HandleUtility.GetHandleSize(points[selectedPoints[i]].position));
}
}
Handles.color = Color.white;
Quaternion lastRotation = rotation;
rotation = Handles.RotationHandle(lastRotation, selectionCenter);
if (lastRotation != rotation)
{
PrepareTransform();
for (int i = 0; i < selectedPoints.Count; i++)
{
var point = localPoints[selectedPoints[i]];
TransformPoint(ref point, rotateNormals, rotateTangents);
points[selectedPoints[i]].SetPoint(point);
}
RegisterChange();
SetDirty();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 241d10a7b944cc44e9a68f8a66f3b04d
timeCreated: 1476219856
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class PointScaleModule : PointTransformModule
{
public bool scaleSize = true;
public bool scaleTangents = true;
public PointScaleModule(SplineEditor editor) : base(editor)
{
}
public override GUIContent GetIconOff()
{
return EditorGUIUtility.IconContent("ScaleTool");
}
public override GUIContent GetIconOn()
{
return EditorGUIUtility.IconContent("ScaleTool On");
}
public override void LoadState()
{
base.LoadState();
scaleSize = LoadBool("scaleSize");
scaleTangents = LoadBool("scaleTangents");
}
public override void SaveState()
{
base.SaveState();
SaveBool("scaleSize", scaleSize);
SaveBool("scaleTangents", scaleTangents);
}
protected override void OnDrawInspector()
{
editSpace = (EditSpace)EditorGUILayout.EnumPopup("Edit Space", editSpace);
scaleSize = EditorGUILayout.Toggle("Scale Sizes", scaleSize);
scaleTangents = EditorGUILayout.Toggle("Scale Tangents", scaleTangents);
}
protected override void OnDrawScene()
{
if (selectedPoints.Count == 0) return;
if (eventModule.mouseLeftUp)
{
Reset();
}
Vector3 lastScale = scale;
Vector3 c = selectionCenter;
scale = Handles.ScaleHandle(scale, c, rotation, HandleUtility.GetHandleSize(c));
if (lastScale != scale)
{
PrepareTransform();
for (int i = 0; i < selectedPoints.Count; i++)
{
var point = localPoints[selectedPoints[i]];
TransformPoint(ref point, false, scaleTangents, scaleSize);
points[selectedPoints[i]].SetPoint(point);
}
RegisterChange();
SetDirty();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2efaeffa226557a4183cdcf4cf6142a9
timeCreated: 1476219856
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,177 @@
namespace Dreamteck.Splines.Editor
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PointTransformModule : PointModule
{
public enum EditSpace { World, Transform, Spline }
public EditSpace editSpace = EditSpace.World;
public Vector3 scale = Vector3.one, offset = Vector3.zero;
protected Quaternion rotation = Quaternion.identity;
protected Vector3 origin = Vector3.zero;
protected SplinePoint[] originalPoints = new SplinePoint[0];
protected SplinePoint[] localPoints = new SplinePoint[0];
private Matrix4x4 matrix = new Matrix4x4();
private Matrix4x4 inverseMatrix = new Matrix4x4();
private bool _unapplied = true;
SplineSample evalResult = new SplineSample();
public PointTransformModule(SplineEditor editor) : base(editor)
{
}
public override void Reset()
{
base.Reset();
GetRotation();
origin = selectionCenter;
scale = Vector3.one;
matrix.SetTRS(origin, rotation, Vector3.one);
inverseMatrix = matrix.inverse;
localPoints = editor.GetPointsArray();
for (int i = 0; i < localPoints.Length; i++) InverseTransformPoint(ref localPoints[i]);
}
protected void GetRotation()
{
switch (editSpace)
{
case EditSpace.World: rotation = Quaternion.identity; break;
case EditSpace.Transform: rotation = TransformUtility.GetRotation(editor.matrix); break;
case EditSpace.Spline:
if (editor.evaluate == null)
{
Debug.LogError("Unassigned handler evaluate for Spline Editor.");
break;
}
if (selectedPoints.Count == 1)
{
editor.evaluate((double)selectedPoints[0] / (points.Length - 1), ref evalResult);
rotation = evalResult.rotation;
}
else rotation = Quaternion.identity;
break;
}
}
public override void LoadState()
{
base.LoadState();
editSpace = (EditSpace)LoadInt("editSpace");
}
public override void SaveState()
{
base.SaveState();
SaveInt("editSpace", (int)editSpace);
}
protected void SetDirty()
{
RegisterChange();
_unapplied = true;
}
protected bool IsDirty()
{
return _unapplied;
}
public virtual void Revert()
{
editor.SetPointsArray(originalPoints);
editor.ApplyModifiedProperties();
_unapplied = false;
}
public virtual void Apply()
{
RegisterChange();
CacheOriginalPoints();
_unapplied = false;
}
public override void Select()
{
base.Select();
CacheOriginalPoints();
}
public override void Deselect()
{
base.Deselect();
_unapplied = false;
}
private void CacheOriginalPoints()
{
originalPoints = editor.GetPointsArray();
}
protected void PrepareTransform()
{
matrix.SetTRS(origin + offset, rotation, scale);
}
protected Vector3 TransformPosition(Vector3 position)
{
return matrix.MultiplyPoint3x4(position);
}
protected Vector3 InverseTransformPosition(Vector3 position)
{
return inverseMatrix.MultiplyPoint3x4(position);
}
protected Vector3 TransformDirection(Vector3 direction)
{
return matrix.MultiplyVector(direction);
}
protected Vector3 InverseTransformDirection(Vector3 direction)
{
return inverseMatrix.MultiplyVector(direction);
}
protected void TransformPoint(ref SplinePoint point, bool normals = true, bool tangents = true, bool size = false)
{
if (tangents)
{
point.position = TransformPosition(point.position);
point.tangent = TransformPosition(point.tangent);
point.tangent2 = TransformPosition(point.tangent2);
}
else
{
point.SetPosition(TransformPosition(point.position));
}
if(normals) point.normal = TransformDirection(point.normal).normalized;
if (size)
{
float avg = (scale.x + scale.y + scale.z) / 3f;
point.size *= avg;
}
}
protected void InverseTransformPoint(ref SplinePoint point, bool normals = true, bool tangents = true, bool size = false)
{
if (tangents)
{
point.position = InverseTransformPosition(point.position);
point.tangent = InverseTransformPosition(point.tangent);
point.tangent2 = InverseTransformPosition(point.tangent2);
} else point.SetPosition(TransformPosition(point.position));
if (normals) point.normal = InverseTransformDirection(point.normal).normalized;
if (size)
{
float avg = (scale.x + scale.y + scale.z) / 3f;
point.size /= avg;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0d24553f5bce60b458dabe3b6bca0158
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb86255f2f032e04297cae0b6fde161f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,127 @@
namespace Dreamteck.Splines.Editor
{
using UnityEditor;
using UnityEngine;
public class SplineEditorBase
{
public bool open = false;
public EditorGUIEvents eventModule = null;
public delegate void UndoHandler(string title);
public delegate void EmptyHandler();
public UndoHandler undoHandler;
public EmptyHandler repaintHandler;
protected bool gizmosEnabled
{
get { return _gizmosEnabled; }
}
private bool _gizmosEnabled = true;
protected readonly SerializedObject _serializedObject;
public SplineEditorBase(SerializedObject serializedObject)
{
Load();
this._serializedObject = serializedObject;
eventModule = new EditorGUIEvents();
}
public virtual void Destroy()
{
Save();
}
protected virtual void Load()
{
open = LoadBool("open");
}
protected virtual void Save()
{
SaveBool("open", open);
}
public virtual void DrawInspector()
{
if(SceneView.lastActiveSceneView != null)
{
#if UNITY_2019_1_OR_NEWER
_gizmosEnabled = SceneView.lastActiveSceneView.drawGizmos;
#endif
}
eventModule.Update(Event.current);
}
public virtual void DrawScene(SceneView current)
{
eventModule.Update(Event.current);
}
protected virtual void RecordUndo(string title)
{
if (undoHandler != null) undoHandler(title);
}
protected virtual void Repaint()
{
if (repaintHandler != null)
{
repaintHandler();
}
}
public virtual void UndoRedoPerformed()
{
}
protected string GetSaveName(string valueName)
{
return GetType().FullName + "." + valueName;
}
protected void SaveBool(string variableName, bool value)
{
EditorPrefs.SetBool(GetType().ToString() + "." + variableName, value);
}
protected void SaveInt(string variableName, int value)
{
EditorPrefs.SetInt(GetType().ToString() + "." + variableName, value);
}
protected void SaveFloat(string variableName, float value)
{
EditorPrefs.SetFloat(GetType().ToString() + "." + variableName, value);
}
protected void SaveString(string variableName, string value)
{
EditorPrefs.SetString(GetType().ToString() + "." + variableName, value);
}
protected bool LoadBool(string variableName, bool defaultValue = false)
{
return EditorPrefs.GetBool(GetType().ToString() + "." + variableName, defaultValue);
}
protected int LoadInt(string variableName, int defaultValue = 0)
{
return EditorPrefs.GetInt(GetType().ToString() + "." + variableName, defaultValue);
}
protected float LoadFloat(string variableName, float d = 0f)
{
return EditorPrefs.GetFloat(GetType().ToString() + "." + variableName, d);
}
protected string LoadString(string variableName)
{
return EditorPrefs.GetString(GetType().ToString() + "." + variableName, "");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc43fa09ec92d7b4996069786c06b474
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: