200 lines
6.6 KiB
C#
200 lines
6.6 KiB
C#
|
|
#if UNITY_EDITOR
|
||
|
|
using System;
|
||
|
|
using UnityEditor;
|
||
|
|
using UnityEditorInternal;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.UIElements;
|
||
|
|
|
||
|
|
namespace TweenAnimation
|
||
|
|
{
|
||
|
|
[CustomEditor(typeof(TweenPath))]
|
||
|
|
public class TweenPathEditor : Editor
|
||
|
|
{
|
||
|
|
TweenPath tweenPath;
|
||
|
|
ReorderableList targetsList;
|
||
|
|
int selectIndex = -1;
|
||
|
|
private AnimationCurve inverseSpeedCurve;
|
||
|
|
float startPos = 0f;
|
||
|
|
|
||
|
|
SerializedProperty targetsProp;
|
||
|
|
|
||
|
|
public override VisualElement CreateInspectorGUI()
|
||
|
|
{
|
||
|
|
tweenPath = (target as TweenPath);
|
||
|
|
targetsProp = serializedObject.FindProperty("targets");
|
||
|
|
targetsList = new ReorderableList(serializedObject, targetsProp, true, true, true, true);
|
||
|
|
targetsList.onSelectCallback += (_) =>
|
||
|
|
{
|
||
|
|
if (selectIndex == targetsList.index)
|
||
|
|
{
|
||
|
|
targetsList.ClearSelection();
|
||
|
|
selectIndex = -1;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
selectIndex = targetsList.index;
|
||
|
|
var target = tweenPath.targets[selectIndex];
|
||
|
|
startPos = Time2StartPos(target.startPos);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
targetsList.drawHeaderCallback = DrawHeader;
|
||
|
|
|
||
|
|
targetsList.drawElementCallback = DrawListItems;
|
||
|
|
targetsList.displayAdd = false;
|
||
|
|
|
||
|
|
inverseSpeedCurve = new AnimationCurve();
|
||
|
|
for (int i = 0; i < tweenPath.speedCurve.length; i++)
|
||
|
|
{
|
||
|
|
|
||
|
|
float inWeight = (tweenPath.speedCurve.keys[i].inTangent * tweenPath.speedCurve.keys[i].inWeight);
|
||
|
|
float outWeight = (tweenPath.speedCurve.keys[i].outTangent * tweenPath.speedCurve.keys[i].outWeight);
|
||
|
|
|
||
|
|
Keyframe inverseKey = new Keyframe(tweenPath.speedCurve.keys[i].value, tweenPath.speedCurve.keys[i].time, 1 / tweenPath.speedCurve.keys[i].inTangent, 1 / tweenPath.speedCurve.keys[i].outTangent, inWeight, outWeight);
|
||
|
|
|
||
|
|
inverseSpeedCurve.AddKey(inverseKey);
|
||
|
|
}
|
||
|
|
|
||
|
|
return base.CreateInspectorGUI();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void DrawListItems(Rect rect, int index, bool isActive, bool isFocused)
|
||
|
|
{
|
||
|
|
if (index < 0)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
EditorGUI.PropertyField(rect, targetsProp.GetArrayElementAtIndex(index).FindPropertyRelative("transform"));
|
||
|
|
}
|
||
|
|
|
||
|
|
private void DrawHeader(Rect rect)
|
||
|
|
{
|
||
|
|
string name = "目标物体";
|
||
|
|
EditorGUI.LabelField(rect, name);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void UpdateTargets()
|
||
|
|
{
|
||
|
|
if (targetsProp.arraySize != tweenPath.transform.childCount)
|
||
|
|
{
|
||
|
|
var tr = tweenPath.transform;
|
||
|
|
if (tweenPath.transform.childCount > targetsProp.arraySize)
|
||
|
|
{
|
||
|
|
var cnt = tweenPath.transform.childCount - targetsProp.arraySize;
|
||
|
|
for (int i = 0; i < cnt; i++)
|
||
|
|
{
|
||
|
|
targetsProp.InsertArrayElementAtIndex(targetsProp.arraySize);
|
||
|
|
targetsProp.GetArrayElementAtIndex(targetsProp.arraySize - 1).managedReferenceValue = new TweenPath.TweenTarget();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
serializedObject.ApplyModifiedProperties();
|
||
|
|
|
||
|
|
for (int i = 0; i < targetsProp.arraySize; i++)
|
||
|
|
{
|
||
|
|
var target = targetsProp.GetArrayElementAtIndex(i).managedReferenceValue as TweenPath.TweenTarget;
|
||
|
|
if (target == null)
|
||
|
|
{
|
||
|
|
targetsProp.GetArrayElementAtIndex(i).managedReferenceValue = new TweenPath.TweenTarget()
|
||
|
|
{
|
||
|
|
transform = tr.GetChild(i),
|
||
|
|
startPos = 0
|
||
|
|
};
|
||
|
|
}
|
||
|
|
else if (target.transform && target.transform.parent != tweenPath.transform)
|
||
|
|
{
|
||
|
|
targetsProp.DeleteArrayElementAtIndex(i);
|
||
|
|
}
|
||
|
|
else if (target.transform != tr.GetChild(i))
|
||
|
|
{
|
||
|
|
target.transform = tr.GetChild(i);
|
||
|
|
target.startPos = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (tweenPath.targets == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
Array.Sort(tweenPath.targets, (a, b) =>
|
||
|
|
{
|
||
|
|
var ai = 0;
|
||
|
|
var bi = 0;
|
||
|
|
for (int i = 0; i < tweenPath.transform.childCount; i++)
|
||
|
|
{
|
||
|
|
if (tweenPath.transform.GetChild(i) == a.transform)
|
||
|
|
{
|
||
|
|
ai = i;
|
||
|
|
}
|
||
|
|
if (tweenPath.transform.GetChild(i) == b.transform)
|
||
|
|
{
|
||
|
|
bi = i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return ai.CompareTo(bi);
|
||
|
|
});
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
serializedObject.ApplyModifiedProperties();
|
||
|
|
}
|
||
|
|
|
||
|
|
public override void OnInspectorGUI()
|
||
|
|
{
|
||
|
|
serializedObject.Update();
|
||
|
|
UpdateTargets();
|
||
|
|
|
||
|
|
base.OnInspectorGUI();
|
||
|
|
targetsList.DoLayoutList();
|
||
|
|
serializedObject.ApplyModifiedProperties();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void OnSceneGUI()
|
||
|
|
{
|
||
|
|
if (selectIndex == -1)
|
||
|
|
{
|
||
|
|
tweenPath.isEditing = false;
|
||
|
|
Tools.hidden = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
Tools.hidden = true;
|
||
|
|
tweenPath.isEditing = true;
|
||
|
|
DrawSelectHandle();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
private void DrawSelectHandle()
|
||
|
|
{
|
||
|
|
var target = tweenPath.targets[selectIndex];
|
||
|
|
|
||
|
|
target.transform.localPosition = tweenPath.path.EvaluateLocalPosition(startPos);
|
||
|
|
var newPos = Handles.PositionHandle(target.transform.position, Quaternion.identity);
|
||
|
|
startPos = tweenPath.path.FindClosestPoint(newPos, 0, 1, 1000);
|
||
|
|
|
||
|
|
target.startPos = StartPos2Time(startPos);
|
||
|
|
}
|
||
|
|
|
||
|
|
private float Time2StartPos(float t)
|
||
|
|
{
|
||
|
|
var p = tweenPath.speedCurve.Evaluate(t);
|
||
|
|
p = p * (tweenPath.path.MaxPos - tweenPath.path.MinPos);
|
||
|
|
return p;
|
||
|
|
}
|
||
|
|
|
||
|
|
private float StartPos2Time(float pos)
|
||
|
|
{
|
||
|
|
var t = pos / (tweenPath.path.MaxPos - tweenPath.path.MinPos);
|
||
|
|
t = inverseSpeedCurve.Evaluate(t);
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnDestroy()
|
||
|
|
{
|
||
|
|
Tools.hidden = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|