将Spline移出Plugin,以调整SplineRenderer的OnWillCameraRender
This commit is contained in:
322
Assets/Dreamteck/Splines/Components/SplineMorph.cs
Normal file
322
Assets/Dreamteck/Splines/Components/SplineMorph.cs
Normal file
@@ -0,0 +1,322 @@
|
||||
namespace Dreamteck.Splines
|
||||
{
|
||||
using UnityEngine;
|
||||
[AddComponentMenu("Dreamteck/Splines/Morph")]
|
||||
public class SplineMorph : MonoBehaviour
|
||||
{
|
||||
[HideInInspector]
|
||||
public SplineComputer.Space space = SplineComputer.Space.Local;
|
||||
[HideInInspector]
|
||||
public bool cycle = false;
|
||||
public enum CycleMode {Default, Loop, PingPong}
|
||||
public enum UpdateMode {Update, FixedUpdate, LateUpdate}
|
||||
[HideInInspector]
|
||||
public CycleMode cycleMode = CycleMode.Default;
|
||||
[HideInInspector]
|
||||
public UpdateMode cycleUpdateMode = UpdateMode.Update;
|
||||
[HideInInspector]
|
||||
public float cycleDuration = 1f;
|
||||
public SplineComputer spline
|
||||
{
|
||||
get { return _spline; }
|
||||
set
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
if(channels.Length > 0 && value.pointCount != channels[0].points.Length)
|
||||
{
|
||||
value.SetPoints(channels[0].points, space);
|
||||
}
|
||||
}
|
||||
_spline = value;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private SplineComputer _spline;
|
||||
private SplinePoint[] points = new SplinePoint[0];
|
||||
private float cycleValue = 0f;
|
||||
private short cycleDirection = 1;
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class Channel
|
||||
{
|
||||
public enum Interpolation { Linear, Spherical }
|
||||
[SerializeField]
|
||||
internal SplinePoint[] points = new SplinePoint[0];
|
||||
[SerializeField]
|
||||
internal float percent = 1f;
|
||||
public string name = "";
|
||||
public AnimationCurve curve;
|
||||
public Interpolation interpolation = Interpolation.Linear;
|
||||
}
|
||||
[HideInInspector]
|
||||
[SerializeField]
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("morphStates")]
|
||||
private Channel[] channels = new Channel[0];
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
spline = GetComponent<SplineComputer>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (cycleUpdateMode == UpdateMode.Update) RunUpdate();
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (cycleUpdateMode == UpdateMode.FixedUpdate) RunUpdate();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (cycleUpdateMode == UpdateMode.LateUpdate) RunUpdate();
|
||||
}
|
||||
|
||||
void RunUpdate()
|
||||
{
|
||||
if (!cycle) return;
|
||||
if (cycleMode != CycleMode.PingPong) cycleDirection = 1;
|
||||
cycleValue += Time.deltaTime / cycleDuration * cycleDirection;
|
||||
switch (cycleMode)
|
||||
{
|
||||
case CycleMode.Default:
|
||||
if (cycleValue > 1f) cycleValue = 1f;
|
||||
break;
|
||||
case CycleMode.Loop:
|
||||
if (cycleValue > 1f) cycleValue -= Mathf.Floor(cycleValue);
|
||||
break;
|
||||
case CycleMode.PingPong:
|
||||
if (cycleValue > 1f)
|
||||
{
|
||||
cycleValue = 1f - (cycleValue - Mathf.Floor(cycleValue));
|
||||
cycleDirection = -1;
|
||||
} else if (cycleValue < 0f)
|
||||
{
|
||||
cycleValue = -cycleValue - Mathf.Floor(-cycleValue);
|
||||
cycleDirection = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
SetWeight(cycleValue, cycleMode == CycleMode.Loop);
|
||||
}
|
||||
|
||||
public void SetCycle(float value)
|
||||
{
|
||||
cycleValue = Mathf.Clamp01(value);
|
||||
}
|
||||
|
||||
public void SetWeight(int index, float weight)
|
||||
{
|
||||
channels[index].percent = Mathf.Clamp01(weight);
|
||||
UpdateMorph();
|
||||
}
|
||||
|
||||
public void SetWeight(string name, float weight)
|
||||
{
|
||||
int index = GetChannelIndex(name);
|
||||
channels[index].percent = Mathf.Clamp01(weight);
|
||||
UpdateMorph();
|
||||
}
|
||||
|
||||
public void SetWeight(float percent, bool loop = false)
|
||||
{
|
||||
float channelValue = percent * (loop ? channels.Length : channels.Length - 1);
|
||||
for (int i = 0; i < channels.Length; i++)
|
||||
{
|
||||
float delta = Mathf.Abs(i - channelValue);
|
||||
if (delta > 1f)
|
||||
{
|
||||
SetWeight(i, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (channelValue <= i)
|
||||
{
|
||||
SetWeight(i, 1f - (i - channelValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWeight(i, 1f - (channelValue - i));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loop && channelValue >= channels.Length - 1)
|
||||
{
|
||||
SetWeight(0, channelValue - (channels.Length - 1));
|
||||
}
|
||||
}
|
||||
|
||||
public void CaptureSnapshot(string name)
|
||||
{
|
||||
CaptureSnapshot(GetChannelIndex(name));
|
||||
}
|
||||
|
||||
public void CaptureSnapshot(int index)
|
||||
{
|
||||
if (_spline == null) return;
|
||||
if ((channels.Length > 0 && _spline.pointCount != channels[0].points.Length && index != 0))
|
||||
{
|
||||
Debug.LogError("Point count must be the same as " + _spline.pointCount);
|
||||
return;
|
||||
}
|
||||
channels[index].points = _spline.GetPoints(space);
|
||||
UpdateMorph();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
channels = new Channel[0];
|
||||
}
|
||||
|
||||
public SplinePoint[] GetSnapshot(int index)
|
||||
{
|
||||
return channels[index].points;
|
||||
}
|
||||
public void SetSnapshot(int index, SplinePoint[] points)
|
||||
{
|
||||
channels[index].points = points;
|
||||
}
|
||||
|
||||
|
||||
public SplinePoint[] GetSnapshot(string name)
|
||||
{
|
||||
int index = GetChannelIndex(name);
|
||||
return channels[index].points;
|
||||
}
|
||||
|
||||
public float GetWeight(int index)
|
||||
{
|
||||
return channels[index].percent;
|
||||
}
|
||||
|
||||
public float GetWeight(string name)
|
||||
{
|
||||
int index = GetChannelIndex(name);
|
||||
return channels[index].percent;
|
||||
}
|
||||
|
||||
public void AddChannel(string name)
|
||||
{
|
||||
if (_spline == null) return;
|
||||
if (channels.Length > 0 && _spline.pointCount != channels[0].points.Length)
|
||||
{
|
||||
Debug.LogError("Point count must be the same as " + channels[0].points.Length);
|
||||
return;
|
||||
}
|
||||
Channel newMorph = new Channel();
|
||||
newMorph.points = _spline.GetPoints(space);
|
||||
newMorph.name = name;
|
||||
newMorph.curve = new AnimationCurve();
|
||||
newMorph.curve.AddKey(new Keyframe(0, 0, 0, 1));
|
||||
newMorph.curve.AddKey(new Keyframe(1, 1, 1, 0));
|
||||
ArrayUtility.Add(ref channels, newMorph);
|
||||
UpdateMorph();
|
||||
}
|
||||
|
||||
public void RemoveChannel(string name)
|
||||
{
|
||||
int index = GetChannelIndex(name);
|
||||
RemoveChannel(index);
|
||||
}
|
||||
|
||||
public void RemoveChannel(int index)
|
||||
{
|
||||
if (index < 0 || index >= channels.Length) return;
|
||||
Channel[] newStates = new Channel[channels.Length - 1];
|
||||
for (int i = 0; i < channels.Length; i++)
|
||||
{
|
||||
if (i == index) continue;
|
||||
else if (i < index) newStates[i] = channels[i];
|
||||
else if (i >= index) newStates[i - 1] = channels[i];
|
||||
}
|
||||
channels = newStates;
|
||||
UpdateMorph();
|
||||
}
|
||||
|
||||
private int GetChannelIndex(string name)
|
||||
{
|
||||
for (int i = 0; i < channels.Length; i++)
|
||||
{
|
||||
if (channels[i].name == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
Debug.Log("Channel not found " + name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int GetChannelCount()
|
||||
{
|
||||
if (channels == null) return 0;
|
||||
return channels.Length;
|
||||
}
|
||||
|
||||
public Channel GetChannel(int index)
|
||||
{
|
||||
return channels[index];
|
||||
}
|
||||
|
||||
public Channel GetChannel(string name)
|
||||
{
|
||||
return channels[GetChannelIndex(name)];
|
||||
}
|
||||
|
||||
public void UpdateMorph()
|
||||
{
|
||||
if (_spline == null) return;
|
||||
if (channels.Length == 0) return;
|
||||
if(points.Length != channels[0].points.Length)
|
||||
{
|
||||
points = new SplinePoint[channels[0].points.Length];
|
||||
}
|
||||
|
||||
for (int i = 0; i < channels.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < points.Length; j++)
|
||||
{
|
||||
if(i == 0)
|
||||
{
|
||||
points[j] = channels[0].points[j];
|
||||
continue;
|
||||
}
|
||||
|
||||
float percent = channels[i].curve.Evaluate(channels[i].percent);
|
||||
if (channels[i].interpolation == Channel.Interpolation.Linear)
|
||||
{
|
||||
points[j].position += (channels[i].points[j].position - channels[0].points[j].position) * percent;
|
||||
points[j].tangent += (channels[i].points[j].tangent - channels[0].points[j].tangent) * percent;
|
||||
points[j].tangent2 += (channels[i].points[j].tangent2 - channels[0].points[j].tangent2) * percent;
|
||||
points[j].normal += (channels[i].points[j].normal - channels[0].points[j].normal) * percent;
|
||||
} else
|
||||
{
|
||||
points[j].position = Vector3.Slerp(points[j].position, points[j].position + (channels[i].points[j].position - channels[0].points[j].position), percent);
|
||||
points[j].tangent = Vector3.Slerp(points[j].tangent, points[j].tangent + (channels[i].points[j].tangent - channels[0].points[j].tangent), percent);
|
||||
points[j].tangent2 = Vector3.Slerp(points[j].tangent2, points[j].tangent2 + (channels[i].points[j].tangent2 - channels[0].points[j].tangent2), percent);
|
||||
points[j].normal = Vector3.Slerp(points[j].normal, points[j].normal + (channels[i].points[j].normal - channels[0].points[j].normal), percent);
|
||||
}
|
||||
|
||||
points[j].color += (channels[i].points[j].color - channels[0].points[j].color) * percent;
|
||||
points[j].size += (channels[i].points[j].size - channels[0].points[j].size) * percent;
|
||||
|
||||
if(points[j].type == SplinePoint.Type.SmoothMirrored) points[j].type = channels[i].points[j].type;
|
||||
else if(points[j].type == SplinePoint.Type.SmoothFree)
|
||||
{
|
||||
if (channels[i].points[j].type == SplinePoint.Type.Broken) points[j].type = SplinePoint.Type.Broken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
points[i].normal.Normalize();
|
||||
}
|
||||
_spline.SetPoints(points, space);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user