rabidus-test/Assets/Dreamteck/Splines/Editor/Components/SplineUserEditor.cs

421 lines
16 KiB
C#

namespace Dreamteck.Splines.Editor
{
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
[CustomEditor(typeof(SplineUser), true)]
[CanEditMultipleObjects]
public class SplineUserEditor : Editor
{
protected bool showClip = true;
protected bool showAveraging = true;
protected bool showUpdateMethod = true;
protected bool showMultithreading = true;
private bool settingsFoldout = false;
protected RotationModifierEditor rotationModifierEditor;
protected OffsetModifierEditor offsetModifierEditor;
protected ColorModifierEditor colorModifierEditor;
protected SizeModifierEditor sizeModifierEditor;
protected SplineUser[] users = new SplineUser[0];
SerializedProperty multithreadedProperty, updateMethodProperty, buildOnAwakeProperty, buildOnEnableProperty, autoUpdateProperty, loopSamplesProperty, clipFromProperty, clipToProperty;
protected GUIStyle foldoutHeaderStyle;
bool doRebuild = false;
protected SerializedProperty spline;
public int editIndex
{
get { return _editIndex; }
set
{
if(value == 0)
{
Debug.LogError("Cannot set edit index to 0. 0 is reserved.");
return;
}
if (value < -1) value = -1;
_editIndex = value;
}
}
private int _editIndex = -1; //0 is reserved for editing clip values
protected GUIContent editButtonContent = new GUIContent("Edit", "Enable edit mode in scene view");
protected virtual void HeaderGUI()
{
SplineUser user = (SplineUser)target;
Undo.RecordObject(user, "Inspector Change");
SplineComputer lastSpline = (SplineComputer)spline.objectReferenceValue;
EditorGUILayout.PropertyField(spline);
SplineComputer newSpline = (SplineComputer)spline.objectReferenceValue;
if (lastSpline != (SplineComputer)spline.objectReferenceValue)
{
for (int i = 0; i < users.Length; i++)
{
if (lastSpline != null) lastSpline.Unsubscribe(users[i]);
if (newSpline != null) newSpline.Subscribe(users[i]);
}
user.Rebuild();
}
if (user.spline == null) EditorGUILayout.HelpBox("No SplineComputer is referenced. Link a SplineComputer to make this SplineUser work.", MessageType.Error);
settingsFoldout = EditorGUILayout.Foldout(settingsFoldout, "User Configuration", foldoutHeaderStyle);
if (settingsFoldout)
{
EditorGUI.indentLevel++;
if (showClip) InspectorClipEdit();
if (showUpdateMethod) EditorGUILayout.PropertyField(updateMethodProperty);
EditorGUILayout.PropertyField(autoUpdateProperty, new GUIContent("Auto Rebuild"));
if (showMultithreading) EditorGUILayout.PropertyField(multithreadedProperty);
EditorGUILayout.PropertyField(buildOnAwakeProperty);
EditorGUILayout.PropertyField(buildOnEnableProperty);
EditorGUI.indentLevel--;
}
}
private void InspectorClipEdit()
{
bool isClosed = true;
bool loopSamples = true;
for (int i = 0; i < users.Length; i++)
{
if (users[i].spline == null) isClosed = false;
else if (!users[i].spline.isClosed) isClosed = false;
else if (!users[i].loopSamples) loopSamples = false;
}
float clipFrom = clipFromProperty.floatValue;
float clipTo = clipToProperty.floatValue;
if (isClosed && loopSamples)
{
EditorGUILayout.BeginHorizontal();
if (EditButton(_editIndex == 0))
{
if (_editIndex == 0) _editIndex = -1;
else _editIndex = 0;
}
EditorGUILayout.BeginVertical();
clipFrom = EditorGUILayout.Slider("Clip From", clipFrom, 0f, 1f);
clipTo = EditorGUILayout.Slider("Clip To", clipTo, 0f, 1f);
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
}
else
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.BeginHorizontal();
if (EditButton(_editIndex == 0))
{
if (_editIndex == 0) _editIndex = -1;
else _editIndex = 0;
}
if (GUILayout.Button("Set Distance", GUILayout.Width(85)))
{
ClipRangeWindow w = EditorWindow.GetWindow<ClipRangeWindow>(true);
float length = 0f;
if(users.Length == 1)
{
length = users[0].spline.CalculateLength();
}
float fromDist = 0f;
float toDist = 0f;
int divide = 0;
for (int i = 0; i < users.Length; i++)
{
if(users[i].spline != null)
{
fromDist += users[i].spline.CalculateLength(0.0, users[i].clipFrom);
toDist += users[i].spline.CalculateLength(0.0, users[i].clipTo);
divide++;
}
}
if(divide > 0)
{
fromDist /= divide;
toDist /= divide;
}
w.Init(OnSetClipRangeDistance, fromDist, toDist, length);
}
EditorGUIUtility.labelWidth = 80f;
EditorGUILayout.MinMaxSlider(new GUIContent("Clip Range "), ref clipFrom, ref clipTo, 0f, 1f);
EditorGUIUtility.labelWidth = 0f;
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(30));
clipFrom = EditorGUILayout.FloatField(clipFrom);
clipTo = EditorGUILayout.FloatField(clipTo);
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndHorizontal();
}
clipFromProperty.floatValue = clipFrom;
clipToProperty.floatValue = clipTo;
SplineComputerEditor.hold = _editIndex >= 0;
if (isClosed) EditorGUILayout.PropertyField(loopSamplesProperty, new GUIContent("Loop Samples"));
if (!loopSamplesProperty.boolValue || !isClosed)
{
if (clipFromProperty.floatValue > clipToProperty.floatValue)
{
float temp = clipToProperty.floatValue;
clipToProperty.floatValue = clipFromProperty.floatValue;
clipFromProperty.floatValue = temp;
}
}
}
void OnSetClipRangeDistance(float from, float to)
{
int longest = 0;
float max = 0f;
for (int i = 0; i < users.Length; i++)
{
if (users[i].spline == null) continue;
float length = users[i].CalculateLength();
if(length > max)
{
max = length;
longest = i;
}
}
clipFromProperty = serializedObject.FindProperty("_clipFrom");
clipToProperty = serializedObject.FindProperty("_clipTo");
serializedObject.Update();
clipFromProperty.floatValue = (float)users[longest].spline.Travel(0.0, from);
clipToProperty.floatValue = (float)users[longest].spline.Travel(0.0, to);
serializedObject.ApplyModifiedProperties();
for (int i = 0; i < users.Length; i++)
{
if (users[i].spline == null) continue;
users[i].clipFrom = clipFromProperty.floatValue;
users[i].clipTo = clipToProperty.floatValue;
users[i].RebuildImmediate();
}
}
protected virtual void BodyGUI()
{
EditorGUILayout.Space();
}
protected virtual void FooterGUI()
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Sample Modifiers", EditorStyles.boldLabel);
if (users.Length == 1)
{
if (offsetModifierEditor != null) offsetModifierEditor.DrawInspector();
if (rotationModifierEditor != null) rotationModifierEditor.DrawInspector();
if (colorModifierEditor != null) colorModifierEditor.DrawInspector();
if (sizeModifierEditor != null) sizeModifierEditor.DrawInspector();
}
else EditorGUILayout.LabelField("Modifiers not available when multiple Spline Users are selected.", EditorStyles.centeredGreyMiniLabel);
EditorGUILayout.Space();
}
protected virtual void DuringSceneGUI(SceneView currentSceneView)
{
if (doRebuild)
{
DoRebuild();
}
SplineUser user = (SplineUser)target;
if (user == null) return;
if (user.spline != null)
{
SplineComputer rootComputer = user.GetComponent<SplineComputer>();
List<SplineComputer> allComputers = user.spline.GetConnectedComputers();
for (int i = 0; i < allComputers.Count; i++)
{
if (allComputers[i] == rootComputer && _editIndex == -1) continue;
if (allComputers[i].editorAlwaysDraw) continue;
DSSplineDrawer.DrawSplineComputer(allComputers[i], 0.0, 1.0, 0.4f);
}
DSSplineDrawer.DrawSplineComputer(user.spline);
}
if (_editIndex == 0) SceneClipEdit();
if (offsetModifierEditor != null) offsetModifierEditor.DrawScene();
if (rotationModifierEditor != null) rotationModifierEditor.DrawScene();
if (colorModifierEditor != null) colorModifierEditor.DrawScene();
if (sizeModifierEditor != null) sizeModifierEditor.DrawScene();
}
void SceneClipEdit()
{
if (users.Length > 1) return;
SplineUser user = (SplineUser)target;
if (user.spline == null) return;
Color col = user.spline.editorPathColor;
Undo.RecordObject(user, "Edit Clip Range");
double val = user.clipFrom;
SplineComputerEditorHandles.Slider(user.spline, ref val, col, "Clip From", SplineComputerEditorHandles.SplineSliderGizmo.ForwardTriangle);
if (val != user.clipFrom) user.clipFrom = val;
val = user.clipTo;
SplineComputerEditorHandles.Slider(user.spline, ref val, col, "Clip To", SplineComputerEditorHandles.SplineSliderGizmo.BackwardTriangle);
if (val != user.clipTo) user.clipTo = val;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (doRebuild) DoRebuild();
serializedObject.Update();
EditorGUI.BeginChangeCheck();
HeaderGUI();
if (EditorGUI.EndChangeCheck())
{
ApplyAndRebuild();
}
EditorGUI.BeginChangeCheck();
BodyGUI();
if (EditorGUI.EndChangeCheck())
{
ApplyAndRebuild();
}
EditorGUI.BeginChangeCheck();
FooterGUI();
if (EditorGUI.EndChangeCheck())
{
ApplyAndRebuild();
}
}
private void ApplyAndRebuild()
{
serializedObject.ApplyModifiedProperties();
DoRebuild();
}
private void DoRebuild()
{
for (int i = 0; i < users.Length; i++)
{
if (users[i] && users[i].isActiveAndEnabled)
{
try
{
users[i].Rebuild();
}
catch (System.Exception ex)
{
Debug.Log(ex.Message);
}
}
}
doRebuild = false;
}
protected virtual void OnDestroy()
{
if (Application.isEditor && !Application.isPlaying)
{
if (target == null)
{
OnDelete(); //The object or the component is being deleted
}
else
{
DoRebuild();
}
}
SplineComputerEditor.hold = false;
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui -= DuringSceneGUI;
#endif
}
protected virtual void OnDelete()
{
}
protected virtual void Awake()
{
foldoutHeaderStyle = EditorStyles.foldout;
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui += DuringSceneGUI;
#endif
SplineUser user = (SplineUser)target;
user.EditorAwake();
}
#if !UNITY_2019_1_OR_NEWER
protected void OnSceneGUI()
{
DuringSceneGUI(SceneView.currentDrawingSceneView);
}
#endif
protected virtual void OnEnable()
{
SplineUser user = (SplineUser)target;
settingsFoldout = EditorPrefs.GetBool("Dreamteck.Splines.Editor.SplineUserEditor.settingsFoldout", false);
rotationModifierEditor = new RotationModifierEditor(user, this);
offsetModifierEditor = new OffsetModifierEditor(user, this);
colorModifierEditor = new ColorModifierEditor(user, this);
sizeModifierEditor = new SizeModifierEditor(user, this);
updateMethodProperty = serializedObject.FindProperty("updateMethod");
buildOnAwakeProperty = serializedObject.FindProperty("buildOnAwake");
buildOnEnableProperty = serializedObject.FindProperty("buildOnEnable");
multithreadedProperty = serializedObject.FindProperty("multithreaded");
autoUpdateProperty = serializedObject.FindProperty("_autoUpdate");
loopSamplesProperty = serializedObject.FindProperty("_loopSamples");
clipFromProperty = serializedObject.FindProperty("_clipFrom");
clipToProperty = serializedObject.FindProperty("_clipTo");
spline = serializedObject.FindProperty("_spline");
users = new SplineUser[targets.Length];
for (int i = 0; i < users.Length; i++)
{
users[i] = (SplineUser)targets[i];
}
Undo.undoRedoPerformed += OnUndoRedo;
}
protected virtual void OnDisable()
{
EditorPrefs.SetBool("Dreamteck.Splines.Editor.SplineUserEditor.settingsFoldout", settingsFoldout);
Undo.undoRedoPerformed -= OnUndoRedo;
}
protected virtual void OnUndoRedo()
{
doRebuild = true;
}
public bool EditButton(bool selected)
{
float width = 40f;
editButtonContent.image = ResourceUtility.EditorLoadTexture("Splines/Editor/Icons", "edit_cursor");
if (editButtonContent.image != null)
{
editButtonContent.text = "";
width = 25f;
}
SplineEditorGUI.SetHighlightColors(SplinePrefs.highlightColor, SplinePrefs.highlightContentColor);
if (SplineEditorGUI.EditorLayoutSelectableButton(editButtonContent, true, selected, GUILayout.Width(width)))
{
SceneView.RepaintAll();
return true;
}
return false;
}
}
}