344 lines
14 KiB
C#
344 lines
14 KiB
C#
namespace Dreamteck.Splines.Editor
|
|
{
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
|
|
public class SplineSampleModifierEditor : SplineUserSubEditor
|
|
{
|
|
protected int selected = -1;
|
|
protected bool drawAllKeys = false;
|
|
protected virtual SerializedProperty _keysProperty => _keys;
|
|
protected SerializedProperty _keys;
|
|
protected SerializedProperty _blend;
|
|
protected SerializedProperty _useClipped;
|
|
protected SerializedProperty _modifier;
|
|
protected virtual string _keysPropertyName => "keys";
|
|
private int _deleteElement = -1;
|
|
|
|
protected SerializedObject _serializedObject;
|
|
|
|
public SplineSampleModifierEditor(SplineUser user, SplineUserEditor editor, string modifierPropertyPath = "") : base(user, editor)
|
|
{
|
|
title = "Sample Modifier";
|
|
_serializedObject = new SerializedObject(user);
|
|
string[] propertyPath = modifierPropertyPath.Split('/');
|
|
var property = _serializedObject.FindProperty(propertyPath[0]);
|
|
for (int i = 1; i < propertyPath.Length; i++)
|
|
{
|
|
if(propertyPath[i].StartsWith("[") && propertyPath[i].EndsWith("]"))
|
|
{
|
|
var num = propertyPath[i].Substring(1, propertyPath[i].Length - 2);
|
|
property = property.GetArrayElementAtIndex(int.Parse(num));
|
|
continue;
|
|
}
|
|
property = property.FindPropertyRelative(propertyPath[i]);
|
|
}
|
|
_modifier = property;
|
|
_keys = _modifier.FindPropertyRelative(_keysPropertyName);
|
|
_blend = _modifier.FindPropertyRelative("blend");
|
|
_useClipped = _modifier.FindPropertyRelative("useClippedPercent");
|
|
}
|
|
|
|
public override void DrawInspector()
|
|
{
|
|
base.DrawInspector();
|
|
if (!isOpen) return;
|
|
if (_keysProperty.arraySize > 0)
|
|
{
|
|
drawAllKeys = EditorGUILayout.Toggle("Draw all Modules", drawAllKeys);
|
|
}
|
|
_serializedObject.Update();
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
for (int i = 0; i < _keysProperty.arraySize; i++)
|
|
{
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
SerializedProperty keyProperty = _keysProperty.GetArrayElementAtIndex(i);
|
|
if (selected == i)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
KeyGUI(keyProperty);
|
|
if (EditorGUI.EndChangeCheck()) user.Rebuild();
|
|
}
|
|
else
|
|
{
|
|
SerializedProperty start = keyProperty.FindPropertyRelative("_featherStart");
|
|
SerializedProperty end = keyProperty.FindPropertyRelative("_featherEnd");
|
|
EditorGUILayout.LabelField(i + " [" + (Mathf.Round(start.floatValue * 10) / 10f) + " - " + (Mathf.Round(end.floatValue * 10) / 10f) + "]");
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
Rect lastRect = GUILayoutUtility.GetLastRect();
|
|
if (lastRect.Contains(Event.current.mousePosition))
|
|
{
|
|
if(Event.current.type == EventType.MouseDown)
|
|
{
|
|
if(Event.current.button == 0)
|
|
{
|
|
selected = i;
|
|
editor.Repaint();
|
|
} else if (Event.current.button == 1)
|
|
{
|
|
int index = i;
|
|
GenericMenu menu = new GenericMenu();
|
|
menu.AddItem(new GUIContent("Delete"), false, delegate
|
|
{
|
|
_deleteElement = index;
|
|
});
|
|
menu.ShowAsContext();
|
|
UpdateValues();
|
|
_serializedObject.Update();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
if (_keysProperty.arraySize > 0)
|
|
{
|
|
EditorGUILayout.PropertyField(_blend);
|
|
EditorGUILayout.PropertyField(_useClipped, new GUIContent("Use Clipped Percents", "Whether the percentages relate to the clip range of the user or not."));
|
|
}
|
|
|
|
if(_deleteElement >= 0)
|
|
{
|
|
_keysProperty.DeleteArrayElementAtIndex(_deleteElement);
|
|
_deleteElement = -1;
|
|
UpdateValues();
|
|
} else
|
|
{
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
UpdateValues();
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void DrawScene()
|
|
{
|
|
base.DrawScene();
|
|
_serializedObject.Update();
|
|
bool changed = false;
|
|
for (int i = 0; i < _keysProperty.arraySize; i++)
|
|
{
|
|
if (selected == i || drawAllKeys)
|
|
{
|
|
if(KeyHandles(_keysProperty.GetArrayElementAtIndex(i), selected == i))
|
|
{
|
|
changed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (changed)
|
|
{
|
|
UpdateValues();
|
|
}
|
|
}
|
|
|
|
protected void UpdateValues()
|
|
{
|
|
if (_serializedObject != null)
|
|
{
|
|
_serializedObject.ApplyModifiedProperties();
|
|
}
|
|
user.Rebuild();
|
|
editor.Repaint();
|
|
}
|
|
|
|
protected virtual SerializedProperty AddKey(float f, float t)
|
|
{
|
|
_keys.InsertArrayElementAtIndex(_keys.arraySize);
|
|
var key = _keys.GetArrayElementAtIndex(_keys.arraySize - 1);
|
|
SerializedProperty start = key.FindPropertyRelative("_featherStart");
|
|
SerializedProperty end = key.FindPropertyRelative("_featherEnd");
|
|
SerializedProperty centerStart = key.FindPropertyRelative("_centerStart");
|
|
SerializedProperty centerEnd = key.FindPropertyRelative("_centerEnd");
|
|
SerializedProperty blend = key.FindPropertyRelative("blend");
|
|
SerializedProperty interpolation = key.FindPropertyRelative("interpolation");
|
|
|
|
start.floatValue = Mathf.Clamp01(f);
|
|
end.floatValue = Mathf.Clamp01(t);
|
|
blend.floatValue = 1f;
|
|
interpolation.animationCurveValue = AnimationCurve.Linear(0f, 0f, 1f, 1f);
|
|
centerStart.floatValue = 0.1f;
|
|
centerEnd.floatValue = 0.9f;
|
|
return key;
|
|
}
|
|
|
|
protected virtual void KeyGUI(SerializedProperty keyProperty)
|
|
{
|
|
SerializedProperty start = keyProperty.FindPropertyRelative("_featherStart");
|
|
SerializedProperty end = keyProperty.FindPropertyRelative("_featherEnd");
|
|
SerializedProperty centerStart = keyProperty.FindPropertyRelative("_centerStart");
|
|
SerializedProperty centerEnd = keyProperty.FindPropertyRelative("_centerEnd");
|
|
SerializedProperty interpolation = keyProperty.FindPropertyRelative("interpolation");
|
|
SerializedProperty blend = keyProperty.FindPropertyRelative("blend");
|
|
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUIUtility.labelWidth = 50f;
|
|
start.floatValue = EditorGUILayout.Slider("Start", start.floatValue, 0f, 1f);
|
|
end.floatValue = EditorGUILayout.Slider("End", end.floatValue, 0f, 1f);
|
|
EditorGUILayout.EndHorizontal();
|
|
EditorGUIUtility.labelWidth = 0f;
|
|
float cs = centerStart.floatValue;
|
|
float ce = centerEnd.floatValue;
|
|
EditorGUILayout.MinMaxSlider("Center", ref cs, ref ce, 0f, 1f);
|
|
centerStart.floatValue = cs;
|
|
centerEnd.floatValue = ce;
|
|
EditorGUILayout.PropertyField(interpolation);
|
|
EditorGUILayout.PropertyField(blend);
|
|
}
|
|
|
|
protected static float GlobalToLocalPercent(float start, float end, float t)
|
|
{
|
|
if (start > end)
|
|
{
|
|
if (t > start) return Mathf.InverseLerp(start, start + (1f - start) + end, t);
|
|
else if (t < end) return Mathf.InverseLerp(-(1f - start), end, t);
|
|
else return 0f;
|
|
}
|
|
return Mathf.InverseLerp(start, end, t);
|
|
}
|
|
|
|
protected static float LocalToGlobalPercent(float start, float end, float t)
|
|
{
|
|
if (start > end)
|
|
{
|
|
t = Mathf.Lerp(start, start + (1f - start) + end, t);
|
|
if (t > 1f)
|
|
{
|
|
t -= Mathf.Floor(t);
|
|
}
|
|
return t;
|
|
}
|
|
return Mathf.Lerp(start, end, t);
|
|
}
|
|
|
|
protected static float GetPosition(float start, float end, float centerStart, float centerEnd)
|
|
{
|
|
float center = Mathf.Lerp(centerStart, centerEnd, 0.5f);
|
|
if (start > end)
|
|
{
|
|
float fromToEndDistance = 1f - start;
|
|
float centerDistance = center * (fromToEndDistance + end);
|
|
float pos = start + centerDistance;
|
|
if (pos > 1f)
|
|
{
|
|
pos -= Mathf.Floor(pos);
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
return Mathf.Lerp(start, end, center);
|
|
}
|
|
|
|
protected virtual bool KeyHandles(SerializedProperty key, bool edit)
|
|
{
|
|
if (!isOpen) return false;
|
|
bool useClip = _useClipped.boolValue;
|
|
|
|
SerializedProperty start = key.FindPropertyRelative("_featherStart");
|
|
SerializedProperty end = key.FindPropertyRelative("_featherEnd");
|
|
SerializedProperty centerStart = key.FindPropertyRelative("_centerStart");
|
|
SerializedProperty centerEnd = key.FindPropertyRelative("_centerEnd");
|
|
|
|
bool changed = false;
|
|
double value = start.floatValue;
|
|
if (useClip)
|
|
{
|
|
user.UnclipPercent(ref value);
|
|
}
|
|
SplineComputerEditorHandles.Slider(user.spline, ref value, user.spline.editorPathColor, "Start", SplineComputerEditorHandles.SplineSliderGizmo.ForwardTriangle, 0.8f);
|
|
if (useClip)
|
|
{
|
|
user.ClipPercent(ref value);
|
|
}
|
|
|
|
if (start.floatValue != value)
|
|
{
|
|
start.floatValue = (float)value;
|
|
changed = true;
|
|
}
|
|
|
|
value = LocalToGlobalPercent(start.floatValue, end.floatValue, centerStart.floatValue);
|
|
if (useClip)
|
|
{
|
|
user.UnclipPercent(ref value);
|
|
}
|
|
SplineComputerEditorHandles.Slider(user.spline, ref value, user.spline.editorPathColor, "", SplineComputerEditorHandles.SplineSliderGizmo.Rectangle, 0.6f);
|
|
if (useClip)
|
|
{
|
|
user.ClipPercent(ref value);
|
|
}
|
|
if (LocalToGlobalPercent(start.floatValue, end.floatValue, centerStart.floatValue) != value)
|
|
{
|
|
centerStart.floatValue = GlobalToLocalPercent(start.floatValue, end.floatValue, (float)value);
|
|
changed = true;
|
|
}
|
|
|
|
value = LocalToGlobalPercent(start.floatValue, end.floatValue, centerEnd.floatValue);
|
|
if (useClip)
|
|
{
|
|
user.UnclipPercent(ref value);
|
|
}
|
|
SplineComputerEditorHandles.Slider(user.spline, ref value, user.spline.editorPathColor, "", SplineComputerEditorHandles.SplineSliderGizmo.Rectangle, 0.6f);
|
|
if (useClip)
|
|
{
|
|
user.ClipPercent(ref value);
|
|
}
|
|
if (LocalToGlobalPercent(start.floatValue, end.floatValue, centerEnd.floatValue) != value)
|
|
{
|
|
centerEnd.floatValue = GlobalToLocalPercent(start.floatValue, end.floatValue, (float)value);
|
|
changed = true;
|
|
}
|
|
|
|
|
|
value = end.floatValue;
|
|
if (useClip)
|
|
{
|
|
user.UnclipPercent(ref value);
|
|
}
|
|
SplineComputerEditorHandles.Slider(user.spline, ref value, user.spline.editorPathColor, "End", SplineComputerEditorHandles.SplineSliderGizmo.BackwardTriangle, 0.8f);
|
|
if (useClip)
|
|
{
|
|
user.ClipPercent(ref value);
|
|
}
|
|
if (end.floatValue != value)
|
|
{
|
|
|
|
end.floatValue = (float)value;
|
|
changed = true;
|
|
}
|
|
|
|
|
|
if (Event.current.control)
|
|
{
|
|
value = GetPosition(start.floatValue, end.floatValue, centerStart.floatValue, centerEnd.floatValue);
|
|
double lastValue = value;
|
|
if (useClip)
|
|
{
|
|
user.UnclipPercent(ref value);
|
|
}
|
|
SplineComputerEditorHandles.Slider(user.spline, ref value, user.spline.editorPathColor, "", SplineComputerEditorHandles.SplineSliderGizmo.Circle, 0.4f);
|
|
if (useClip)
|
|
{
|
|
user.ClipPercent(ref value);
|
|
}
|
|
|
|
if (value != lastValue)
|
|
{
|
|
|
|
double delta = value - lastValue;
|
|
start.floatValue += (float)delta;
|
|
end.floatValue += (float)delta;
|
|
start.floatValue = Mathf.Clamp01(start.floatValue);
|
|
end.floatValue = Mathf.Clamp(end.floatValue, start.floatValue, 1f);
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
}
|
|
} |