[unity] Fixed prefab baking ignoring separated timelines. Closes #2035.

This commit is contained in:
Harald Csaszar 2022-02-16 21:18:42 +01:00
parent c523576895
commit a4e7654bc5

View File

@ -782,8 +782,16 @@ namespace Spine.Unity.Editor {
if (t is ScaleTimeline) {
ParseScaleTimeline(skeleton, (ScaleTimeline)t, clip);
} else if (t is ScaleXTimeline) {
ParseSingleSplitScaleTimeline(skeleton, (ScaleXTimeline)t, null, clip);
} else if (t is ScaleYTimeline) {
ParseSingleSplitScaleTimeline(skeleton, null, (ScaleYTimeline)t, clip);
} else if (t is TranslateTimeline) {
ParseTranslateTimeline(skeleton, (TranslateTimeline)t, clip);
} else if (t is TranslateXTimeline) {
ParseSingleSplitTranslateTimeline(skeleton, (TranslateXTimeline)t, null, clip);
} else if (t is TranslateYTimeline) {
ParseSingleSplitTranslateTimeline(skeleton, null, (TranslateYTimeline)t, clip);
} else if (t is RotateTimeline) {
//bypass any rotation keys if they're going to get baked anyway to prevent localEulerAngles vs Baked collision
if (ignoreRotateTimelineIndexes.Contains(((RotateTimeline)t).BoneIndex) == false)
@ -895,7 +903,7 @@ namespace Spine.Unity.Editor {
AnimationCurve yCurve = new AnimationCurve();
AnimationCurve zCurve = new AnimationCurve();
float endTime = timeline.Frames[(timeline.FrameCount * 3) - 3];
float endTime = timeline.Frames[(timeline.FrameCount * TranslateTimeline.ENTRIES) - TranslateTimeline.ENTRIES];
float currentTime = timeline.Frames[0];
@ -907,7 +915,7 @@ namespace Spine.Unity.Editor {
int listIndex = 1;
int frameIndex = 1;
int f = 3;
int f = TranslateTimeline.ENTRIES;
float[] frames = timeline.Frames;
skeleton.SetToSetupPose();
float lastTime = 0;
@ -1006,7 +1014,7 @@ namespace Spine.Unity.Editor {
}
frameIndex++;
f += 3;
f += TranslateTimeline.ENTRIES;
}
xCurve = EnsureCurveKeyCount(new AnimationCurve(xKeys.ToArray()));
@ -1022,6 +1030,107 @@ namespace Spine.Unity.Editor {
clip.SetCurve(path, typeof(Transform), propertyName + ".z", zCurve);
}
/// <summary>Parses a single TranslateXTimeline or TranslateYTimeline.
/// Only one of <c>timelineX</c> or <c>timelineY</c> shall be filled out, the other must be null.</summary>
static void ParseSingleSplitTranslateTimeline (Skeleton skeleton,
TranslateXTimeline timelineX, TranslateYTimeline timelineY, AnimationClip clip) {
bool isXTimeline = timelineX != null;
CurveTimeline1 timeline = isXTimeline ? timelineX : timelineY as CurveTimeline1;
IBoneTimeline boneTimeline = isXTimeline ? timelineX : timelineY as IBoneTimeline;
var boneData = skeleton.Data.Bones.Items[boneTimeline.BoneIndex];
var bone = skeleton.Bones.Items[boneTimeline.BoneIndex];
float boneDataOffset = isXTimeline ? boneData.X : boneData.Y;
AnimationCurve curve = new AnimationCurve();
float endTime = timeline.Frames[(timeline.FrameCount * TranslateXTimeline.ENTRIES) - TranslateXTimeline.ENTRIES];
float currentTime = timeline.Frames[0];
List<Keyframe> keys = new List<Keyframe>();
keys.Add(new Keyframe(timeline.Frames[0], timeline.Frames[1] + boneDataOffset, 0, 0));
int listIndex = 1;
int frameIndex = 1;
int f = TranslateXTimeline.ENTRIES;
float[] frames = timeline.Frames;
skeleton.SetToSetupPose();
float lastTime = 0;
while (currentTime < endTime) {
int pIndex = listIndex - 1;
float curveType = timeline.GetCurveType(frameIndex - 1);
if (curveType == 0) {
//linear
Keyframe p = keys[pIndex];
float time = frames[f];
float value = frames[f + 1] + boneDataOffset;
float valueOut = (value - p.value) / (time - p.time);
p.outTangent = valueOut;
keys.Add(new Keyframe(time, value, valueOut, 0));
keys[pIndex] = p;
currentTime = time;
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
lastTime = time;
listIndex++;
} else if (curveType == 1) {
//stepped
Keyframe p = keys[pIndex];
float time = frames[f];
float value = frames[f + 1] + boneDataOffset;
float valueOut = float.PositiveInfinity;
p.outTangent = valueOut;
keys.Add(new Keyframe(time, value, valueOut, 0));
keys[pIndex] = p;
currentTime = time;
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
lastTime = time;
listIndex++;
} else {
//bezier
Keyframe p = keys[pIndex];
float time = frames[f];
int steps = Mathf.FloorToInt((time - p.time) / BakeIncrement);
for (int i = 1; i <= steps; i++) {
currentTime += BakeIncrement;
if (i == steps)
currentTime = time;
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
p = keys[listIndex - 1];
float boneOffset = isXTimeline ? bone.X : bone.Y;
float valueOut = (boneOffset - p.value) / (currentTime - p.time);
p.outTangent = valueOut;
keys.Add(new Keyframe(currentTime, boneOffset, valueOut, 0));
keys[listIndex - 1] = p;
listIndex++;
lastTime = currentTime;
}
}
frameIndex++;
f += TranslateXTimeline.ENTRIES;
}
curve = EnsureCurveKeyCount(new AnimationCurve(keys.ToArray()));
string path = GetPath(boneData);
const string propertyName = "localPosition";
clip.SetCurve(path, typeof(Transform), propertyName + (isXTimeline ? ".x" : ".y"), curve);
}
static void ParseScaleTimeline (Skeleton skeleton, ScaleTimeline timeline, AnimationClip clip) {
var boneData = skeleton.Data.Bones.Items[timeline.BoneIndex];
var bone = skeleton.Bones.Items[timeline.BoneIndex];
@ -1030,7 +1139,7 @@ namespace Spine.Unity.Editor {
AnimationCurve yCurve = new AnimationCurve();
AnimationCurve zCurve = new AnimationCurve();
float endTime = timeline.Frames[(timeline.FrameCount * 3) - 3];
float endTime = timeline.Frames[(timeline.FrameCount * ScaleTimeline.ENTRIES) - ScaleTimeline.ENTRIES];
float currentTime = timeline.Frames[0];
@ -1042,7 +1151,7 @@ namespace Spine.Unity.Editor {
int listIndex = 1;
int frameIndex = 1;
int f = 3;
int f = ScaleTimeline.ENTRIES;
float[] frames = timeline.Frames;
skeleton.SetToSetupPose();
float lastTime = 0;
@ -1140,7 +1249,7 @@ namespace Spine.Unity.Editor {
}
frameIndex++;
f += 3;
f += ScaleTimeline.ENTRIES;
}
xCurve = EnsureCurveKeyCount(new AnimationCurve(xKeys.ToArray()));
@ -1154,6 +1263,103 @@ namespace Spine.Unity.Editor {
clip.SetCurve(path, typeof(Transform), propertyName + ".z", zCurve);
}
static void ParseSingleSplitScaleTimeline (Skeleton skeleton,
ScaleXTimeline timelineX, ScaleYTimeline timelineY, AnimationClip clip) {
bool isXTimeline = timelineX != null;
CurveTimeline1 timeline = isXTimeline ? timelineX : timelineY as CurveTimeline1;
IBoneTimeline boneTimeline = isXTimeline ? timelineX : timelineY as IBoneTimeline;
var boneData = skeleton.Data.Bones.Items[boneTimeline.BoneIndex];
var bone = skeleton.Bones.Items[boneTimeline.BoneIndex];
float boneDataOffset = isXTimeline ? boneData.ScaleX : boneData.ScaleY;
AnimationCurve curve = new AnimationCurve();
float endTime = timeline.Frames[(timeline.FrameCount * ScaleXTimeline.ENTRIES) - ScaleXTimeline.ENTRIES];
float currentTime = timeline.Frames[0];
List<Keyframe> keys = new List<Keyframe>();
keys.Add(new Keyframe(timeline.Frames[0], timeline.Frames[1] * boneDataOffset, 0, 0));
int listIndex = 1;
int frameIndex = 1;
int f = ScaleXTimeline.ENTRIES;
float[] frames = timeline.Frames;
skeleton.SetToSetupPose();
float lastTime = 0;
while (currentTime < endTime) {
int pIndex = listIndex - 1;
float curveType = timeline.GetCurveType(frameIndex - 1);
if (curveType == 0) {
//linear
Keyframe p = keys[pIndex];
float time = frames[f];
float value = frames[f + 1] * boneDataOffset;
float valueOut = (value - p.value) / (time - p.time);
p.outTangent = valueOut;
keys.Add(new Keyframe(time, value, valueOut, 0));
keys[pIndex] = p;
currentTime = time;
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
lastTime = time;
listIndex++;
} else if (curveType == 1) {
//stepped
Keyframe p = keys[pIndex];
float time = frames[f];
float value = frames[f + 1] * boneDataOffset;
float valueOut = float.PositiveInfinity;
p.outTangent = valueOut;
keys.Add(new Keyframe(time, value, valueOut, 0));
keys[pIndex] = p;
currentTime = time;
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
lastTime = time;
listIndex++;
} else {
//bezier
Keyframe p = keys[pIndex];
float time = frames[f];
int steps = Mathf.FloorToInt((time - p.time) / BakeIncrement);
for (int i = 1; i <= steps; i++) {
currentTime += BakeIncrement;
if (i == steps)
currentTime = time;
timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In);
p = keys[listIndex - 1];
float boneScale = isXTimeline ? bone.ScaleX : bone.ScaleY;
float valueOut = (boneScale - p.value) / (currentTime - p.time);
p.outTangent = valueOut;
keys.Add(new Keyframe(currentTime, boneScale, valueOut, 0));
keys[listIndex - 1] = p;
listIndex++;
lastTime = currentTime;
}
}
frameIndex++;
f += ScaleXTimeline.ENTRIES;
}
curve = EnsureCurveKeyCount(new AnimationCurve(keys.ToArray()));
string path = GetPath(boneData);
string propertyName = "localScale";
clip.SetCurve(path, typeof(Transform), propertyName + (isXTimeline ? ".x" : ".y"), curve);
}
static void ParseRotateTimeline (Skeleton skeleton, RotateTimeline timeline, AnimationClip clip) {
var boneData = skeleton.Data.Bones.Items[timeline.BoneIndex];
var bone = skeleton.Bones.Items[timeline.BoneIndex];