308 lines
12 KiB
C#
308 lines
12 KiB
C#
using Convention;
|
|
using Demo.Editor.UI;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using Unity.Collections;
|
|
using UnityEngine;
|
|
|
|
namespace Demo.Game
|
|
{
|
|
namespace ConfigType
|
|
{
|
|
public abstract class UpdatementConfig<DataType>: ScriptLoadableConfig where DataType : struct
|
|
{
|
|
public NativeArray<float> TimePoints;
|
|
public NativeArray<DataType> Positions;
|
|
public NativeArray<MathExtension.EaseCurveType> EaseCurveTypes;
|
|
|
|
protected abstract void DeserializePositions(BinaryReader reader, ref NativeArray<DataType> positions);
|
|
protected abstract void SerializePositions(BinaryWriter writer, in NativeArray<DataType> positions);
|
|
|
|
public override void Deserialize(BinaryReader reader)
|
|
{
|
|
BinarySerializeUtility.DeserializeNativeArray(reader, ref TimePoints);
|
|
DeserializePositions(reader, ref Positions);
|
|
{
|
|
NativeArray<int> temp = new(EaseCurveTypes.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
|
|
BinarySerializeUtility.DeserializeNativeArray(reader, ref temp);
|
|
for (int i = 0, e = EaseCurveTypes.Length; i < e; i++)
|
|
{
|
|
EaseCurveTypes[i] = (MathExtension.EaseCurveType)temp[i];
|
|
}
|
|
temp.Dispose();
|
|
}
|
|
base.Deserialize(reader);
|
|
}
|
|
|
|
public override void Serialize(BinaryWriter writer)
|
|
{
|
|
BinarySerializeUtility.SerializeNativeArray(writer, TimePoints);
|
|
SerializePositions(writer, Positions);
|
|
{
|
|
NativeArray<int> temp = new(EaseCurveTypes.Length, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
|
|
for (int i = 0, e = EaseCurveTypes.Length; i < e; i++)
|
|
{
|
|
temp[i] = (int)EaseCurveTypes[i];
|
|
}
|
|
BinarySerializeUtility.SerializeNativeArray(writer, temp);
|
|
temp.Dispose();
|
|
}
|
|
base.Serialize(writer);
|
|
}
|
|
}
|
|
|
|
public class UpdatementIntConfig : UpdatementConfig<int>
|
|
{
|
|
protected override void DeserializePositions(BinaryReader reader, ref NativeArray<int> positions)
|
|
{
|
|
BinarySerializeUtility.DeserializeNativeArray(reader, ref positions);
|
|
}
|
|
|
|
protected override void SerializePositions(BinaryWriter writer, in NativeArray<int> positions)
|
|
{
|
|
BinarySerializeUtility.SerializeNativeArray(writer, positions);
|
|
}
|
|
}
|
|
|
|
public class UpdatementFloatConfig : UpdatementConfig<float>
|
|
{
|
|
protected override void DeserializePositions(BinaryReader reader, ref NativeArray<float> positions)
|
|
{
|
|
BinarySerializeUtility.DeserializeNativeArray(reader, ref positions);
|
|
}
|
|
|
|
protected override void SerializePositions(BinaryWriter writer, in NativeArray<float> positions)
|
|
{
|
|
BinarySerializeUtility.SerializeNativeArray(writer, positions);
|
|
}
|
|
}
|
|
|
|
public class UpdatementVec2Config : UpdatementConfig<Vector2>
|
|
{
|
|
protected override void DeserializePositions(BinaryReader reader, ref NativeArray<Vector2> positions)
|
|
{
|
|
BinarySerializeUtility.DeserializeNativeArray(reader, ref positions);
|
|
}
|
|
|
|
protected override void SerializePositions(BinaryWriter writer, in NativeArray<Vector2> positions)
|
|
{
|
|
BinarySerializeUtility.SerializeNativeArray(writer, positions);
|
|
}
|
|
}
|
|
|
|
public class UpdatementVec3Config : UpdatementConfig<Vector3>
|
|
{
|
|
protected override void DeserializePositions(BinaryReader reader, ref NativeArray<Vector3> positions)
|
|
{
|
|
BinarySerializeUtility.DeserializeNativeArray(reader, ref positions);
|
|
}
|
|
|
|
protected override void SerializePositions(BinaryWriter writer, in NativeArray<Vector3> positions)
|
|
{
|
|
BinarySerializeUtility.SerializeNativeArray(writer, positions);
|
|
}
|
|
}
|
|
}
|
|
|
|
public abstract class Updatement<DataType> : TimelineScriptObject where DataType : struct
|
|
{
|
|
[Serializable]
|
|
public class UpdatementEntry
|
|
{
|
|
public float TimePoint = 0;
|
|
public DataType Position = default;
|
|
public MathExtension.EaseCurveType easeCurveType = MathExtension.EaseCurveType.Linear;
|
|
}
|
|
[Serializable]
|
|
public struct UpdatementCompiledEntries: IDisposable
|
|
{
|
|
public NativeArray<float> TimePoints;
|
|
public NativeArray<DataType> Positions;
|
|
public NativeArray<MathExtension.EaseCurveType> EaseCurveTypes;
|
|
public readonly int Count;
|
|
|
|
public UpdatementCompiledEntries(NativeArray<float> timePoints,
|
|
NativeArray<DataType> positions,
|
|
NativeArray<MathExtension.EaseCurveType> easeCurveTypes,
|
|
int count)
|
|
{
|
|
TimePoints = timePoints;
|
|
Positions = positions;
|
|
EaseCurveTypes = easeCurveTypes;
|
|
Count = count;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (TimePoints.IsCreated)
|
|
TimePoints.Dispose();
|
|
if (Positions.IsCreated)
|
|
Positions.Dispose();
|
|
if (EaseCurveTypes.IsCreated)
|
|
EaseCurveTypes.Dispose();
|
|
}
|
|
}
|
|
|
|
public int Content = 0;
|
|
private readonly List<UpdatementEntry> Entries = new();
|
|
public UpdatementCompiledEntries CompiledEntries;
|
|
protected abstract void UpdateData(DataType data);
|
|
protected abstract DataType Lerp(DataType begin, DataType end, float t);
|
|
|
|
/// <summary>
|
|
/// 添加数据
|
|
/// </summary>
|
|
/// <param name="time"></param>
|
|
/// <param name="position"></param>
|
|
/// <param name="curveType"></param>
|
|
public void ManualAddEntry(float time, DataType position, MathExtension.EaseCurveType curveType)
|
|
{
|
|
Entries.Add(new()
|
|
{
|
|
TimePoint = time,
|
|
Position = position,
|
|
easeCurveType = curveType
|
|
});
|
|
}
|
|
|
|
private void BuildupCompiledEntriesAndReleaseEntries()
|
|
{
|
|
Entries.Sort((x, y) => x.TimePoint.CompareTo(y.TimePoint));
|
|
CompiledEntries = new(
|
|
new NativeArray<float>(Entries.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory),
|
|
new NativeArray<DataType>(Entries.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory),
|
|
new NativeArray<MathExtension.EaseCurveType>(Entries.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory),
|
|
Entries.Count
|
|
);
|
|
int index = 0;
|
|
foreach (var item in Entries)
|
|
{
|
|
CompiledEntries.TimePoints[index] = item.TimePoint;
|
|
CompiledEntries.Positions[index] = item.Position;
|
|
CompiledEntries.EaseCurveTypes[index] = item.easeCurveType;
|
|
index++;
|
|
}
|
|
Entries.Clear();
|
|
}
|
|
|
|
private void UpdateEntry(int start, float percent)
|
|
{
|
|
int head = start;
|
|
int tail = Mathf.Min(start + 1, CompiledEntries.Count - 1);
|
|
UpdateData(Lerp(CompiledEntries.Positions[start],
|
|
CompiledEntries.Positions[tail],
|
|
MathExtension.Evaluate(Mathf.Clamp01(percent), CompiledEntries.EaseCurveTypes[head])));
|
|
}
|
|
|
|
protected override IEnumerator DoSomethingDuringApplyScript()
|
|
{
|
|
yield return base.DoSomethingDuringApplyScript();
|
|
BuildupCompiledEntriesAndReleaseEntries();
|
|
if (UpdateTarget == null)
|
|
{
|
|
UpdateTarget = Parent.gameObject;
|
|
}
|
|
}
|
|
|
|
public override void ResetEnterGameStatus()
|
|
{
|
|
base.ResetEnterGameStatus();
|
|
if (CompiledEntries.Count <= 1)
|
|
return;
|
|
UpdateEntry(0, 0);
|
|
}
|
|
|
|
public override IEnumerator UnloadScript()
|
|
{
|
|
Content = 0;
|
|
CompiledEntries = default;
|
|
yield return base.UnloadScript();
|
|
}
|
|
|
|
protected override void UpdateTicks(float currentTime, float deltaTime, TickType tickType)
|
|
{
|
|
base.UpdateTicks(currentTime, deltaTime, tickType);
|
|
|
|
float GetPercentValue()
|
|
{
|
|
if (Content + 1 == CompiledEntries.Count)
|
|
return 1;
|
|
return (currentTime - CompiledEntries.TimePoints[Content]) / (CompiledEntries.TimePoints[Content + 1] - CompiledEntries.TimePoints[Content]);
|
|
}
|
|
|
|
if (CompiledEntries.Count <= 1)
|
|
return;
|
|
switch (tickType)
|
|
{
|
|
case TickType.Reset:
|
|
case TickType.Start:
|
|
{
|
|
Content = 0;
|
|
while (Content + 1 < CompiledEntries.Count && CompiledEntries.TimePoints[Content + 1] < currentTime)
|
|
Content++;
|
|
UpdateEntry(Content, GetPercentValue());
|
|
}
|
|
break;
|
|
default:
|
|
if (CompiledEntries.TimePoints[0] > currentTime)
|
|
return;
|
|
if (Content + 1 < CompiledEntries.Count && CompiledEntries.TimePoints[Content + 1] < currentTime)
|
|
Content++;
|
|
if (Content + 1 > CompiledEntries.Count)
|
|
return;
|
|
UpdateEntry(Content, GetPercentValue());
|
|
break;
|
|
}
|
|
}
|
|
|
|
public DataType Evaluate(float time)
|
|
{
|
|
if (CompiledEntries.Count == 0)
|
|
return default;
|
|
if (CompiledEntries.Count == 1)
|
|
return CompiledEntries.Positions[0];
|
|
if (time < CompiledEntries.TimePoints[0])
|
|
return CompiledEntries.Positions[0];
|
|
for (int i = 1; i < CompiledEntries.Count; i++)
|
|
{
|
|
if (CompiledEntries.TimePoints[i - 1] <= time && CompiledEntries.TimePoints[i] > time)
|
|
{
|
|
return Lerp(CompiledEntries.Positions[i - 1], CompiledEntries.Positions[i],
|
|
(time - CompiledEntries.TimePoints[i - 1]) / (CompiledEntries.TimePoints[i] - CompiledEntries.TimePoints[i - 1]));
|
|
}
|
|
}
|
|
return CompiledEntries.Positions[^1];
|
|
}
|
|
|
|
[Content] public GameObject UpdateTarget;
|
|
|
|
/// <summary>
|
|
/// 设置更新对象
|
|
/// </summary>
|
|
[Convention.RScript.Variable.Attr.Method]
|
|
public void SetUpdateTarget(ScriptableObject target)
|
|
{
|
|
UpdateTarget = target.gameObject;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="item">实例在父类中控制</param>
|
|
protected override void SetupTimelineItem(TimelineItem item)
|
|
{
|
|
if (CompiledEntries.Count == 0)
|
|
return;
|
|
|
|
item.SetupDuration(new(CompiledEntries.TimePoints[0], CompiledEntries.TimePoints[^1]), GetTimelineItemColor());
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
CompiledEntries.Dispose();
|
|
}
|
|
}
|
|
}
|