From 7c2fb931d8f09d44742e0f58cf19cc127fb717ec Mon Sep 17 00:00:00 2001 From: John Date: Sun, 8 Apr 2018 23:32:04 +0800 Subject: [PATCH] [unity] Minor cleanup for SkeletonBaker.cs --- .../spine-unity/Editor/SkeletonBaker.cs | 330 +++++++++--------- 1 file changed, 163 insertions(+), 167 deletions(-) diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs index b9e04b5a0..84cfc1fc8 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonBaker.cs @@ -56,19 +56,16 @@ namespace Spine.Unity.Editor { /// Attachment Timeline /// /// RegionAttachment - /// MeshAttachment - /// SkinnedMeshAttachment + /// MeshAttachment (optionally Skinned) /// /// [LIMITATIONS] - /// *Inverse Kinematics & Bezier Curves are baked into the animation at 60fps and are not realtime. Use bakeIncrement constant to adjust key density if desired. - /// **Non-uniform Scale Keys (ie: if ScaleX and ScaleY are not equal to eachother, it will not be accurate to Spine source) + /// *Bezier Curves are baked into the animation at 60fps and are not realtime. Use bakeIncrement constant to adjust key density if desired. + /// *Inverse Kinematics is baked into the animation at 60fps and are not realtime. Use bakeIncrement constant to adjust key density if desired. /// ***Events may only fire 1 type of data per event in Unity safely so priority to String data if present in Spine key, otherwise a Float is sent whether the Spine key was Int or Float with priority given to Int. /// /// [DOES NOT SUPPORT] - /// FlipX or FlipY (Maybe one day) /// FFD (Unity does not provide access to BlendShapes with code) /// Color Keys (Maybe one day when Unity supports full FBX standard and provides access with code) - /// InheritScale (Never. Unity and Spine do scaling very differently) /// Draw Order Keyframes /// public static class SkeletonBaker { @@ -174,11 +171,11 @@ namespace Spine.Unity.Editor { #endif #endregion - #region Baking + #region Prefab and AnimationClip Baking /// /// Interval between key sampling for Bezier curves, IK controlled bones, and Inherit Rotation effected bones. /// - const float bakeIncrement = 1 / 60f; + const float BakeIncrement = 1 / 60f; public static void BakeToPrefab (SkeletonDataAsset skeletonDataAsset, ExposedList skins, string outputPath = "", bool bakeAnimations = true, bool bakeIK = true, SendMessageOptions eventOptions = SendMessageOptions.DontRequireReceiver) { if (skeletonDataAsset == null || skeletonDataAsset.GetSkeletonData(true) == null) { @@ -351,8 +348,8 @@ namespace Spine.Unity.Editor { for (int a = 0; a < attachments.Count; a++) { var attachment = attachments[a]; - var attachmentName = attachmentNames[a]; - var attachmentMeshName = "[" + slotData.Name + "] " + attachmentName; + string attachmentName = attachmentNames[a]; + string attachmentMeshName = "[" + slotData.Name + "] " + attachmentName; Vector3 offset = Vector3.zero; float rotation = 0; Mesh mesh = null; @@ -454,18 +451,20 @@ namespace Spine.Unity.Editor { } - static Bone extractionBone; - static Slot extractionSlot; + #region Attachment Baking + static Bone DummyBone; + static Slot DummySlot; - internal static Bone GetExtractionBone () { - if (extractionBone != null) - return extractionBone; + internal static Bone GetDummyBone () { + if (DummyBone != null) + return DummyBone; SkeletonData skelData = new SkeletonData(); - BoneData data = new BoneData(0, "temp", null); - data.ScaleX = 1; - data.ScaleY = 1; - data.Length = 100; + BoneData data = new BoneData(0, "temp", null) { + ScaleX = 1, + ScaleY = 1, + Length = 100 + }; skelData.Bones.Add(data); @@ -474,25 +473,25 @@ namespace Spine.Unity.Editor { Bone bone = new Bone(data, skeleton, null); bone.UpdateWorldTransform(); - extractionBone = bone; + DummyBone = bone; - return extractionBone; + return DummyBone; } - internal static Slot GetExtractionSlot () { - if (extractionSlot != null) - return extractionSlot; + internal static Slot GetDummySlot () { + if (DummySlot != null) + return DummySlot; - Bone bone = GetExtractionBone(); + Bone bone = GetDummyBone(); SlotData data = new SlotData(0, "temp", bone.Data); Slot slot = new Slot(data, bone); - extractionSlot = slot; - return extractionSlot; + DummySlot = slot; + return DummySlot; } internal static Mesh ExtractRegionAttachment (string name, RegionAttachment attachment, Mesh mesh = null, bool centered = true) { - var bone = GetExtractionBone(); + var bone = GetDummyBone(); if (centered) { bone.X = -attachment.X; @@ -532,7 +531,7 @@ namespace Spine.Unity.Editor { } internal static Mesh ExtractMeshAttachment (string name, MeshAttachment attachment, Mesh mesh = null) { - var slot = GetExtractionSlot(); + var slot = GetDummySlot(); slot.Bone.X = 0; slot.Bone.Y = 0; @@ -731,7 +730,9 @@ namespace Spine.Unity.Editor { return arr; } + #endregion + #region Animation Baking static AnimationClip ExtractAnimation (string name, SkeletonData skeletonData, Dictionary> slotLookup, bool bakeIK, SendMessageOptions eventOptions, AnimationClip clip = null) { var animation = skeletonData.FindAnimation(name); @@ -755,7 +756,7 @@ namespace Spine.Unity.Editor { foreach (Bone b in i.Bones) { int index = skeleton.FindBoneIndex(b.Data.Name); ignoreRotateTimelineIndexes.Add(index); - BakeBone(b, animation, clip); + BakeBoneConstraints(b, animation, clip); } } } @@ -766,7 +767,7 @@ namespace Spine.Unity.Editor { if (ignoreRotateTimelineIndexes.Contains(index) == false) { ignoreRotateTimelineIndexes.Add(index); - BakeBone(b, animation, clip); + BakeBoneConstraints(b, animation, clip); } } } @@ -813,122 +814,13 @@ namespace Spine.Unity.Editor { low = current + 1; else high = current; + if (low == high) return (low + 1); current = (int)((uint)(low + high) >> 1); } } - static void ParseEventTimeline (EventTimeline timeline, AnimationClip clip, SendMessageOptions eventOptions) { - - float[] frames = timeline.Frames; - var events = timeline.Events; - - List animEvents = new List(); - for (int i = 0; i < frames.Length; i++) { - var ev = events[i]; - - AnimationEvent ae = new AnimationEvent(); - //MITCH: left todo: Deal with Mecanim's zero-time missed event - ae.time = frames[i]; - ae.functionName = ev.Data.Name; - ae.messageOptions = eventOptions; - - if (!string.IsNullOrEmpty(ev.String)) { - ae.stringParameter = ev.String; - } else { - if (ev.Int == 0 && ev.Float == 0) { - //do nothing, raw function - } else { - if (ev.Int != 0) - ae.floatParameter = (float)ev.Int; - else - ae.floatParameter = ev.Float; - } - - } - - animEvents.Add(ae); - } - - AnimationUtility.SetAnimationEvents(clip, animEvents.ToArray()); - } - - static void ParseAttachmentTimeline (Skeleton skeleton, AttachmentTimeline timeline, Dictionary> slotLookup, AnimationClip clip) { - var attachmentNames = slotLookup[timeline.SlotIndex]; - - string bonePath = GetPath(skeleton.Slots.Items[timeline.SlotIndex].Bone.Data); - string slotPath = bonePath + "/" + skeleton.Slots.Items[timeline.SlotIndex].Data.Name; - - Dictionary curveTable = new Dictionary(); - - foreach (string str in attachmentNames) { - curveTable.Add(str, new AnimationCurve()); - } - - float[] frames = timeline.Frames; - - if (frames[0] != 0) { - string startingName = skeleton.Slots.Items[timeline.SlotIndex].Data.AttachmentName; - foreach (var pair in curveTable) { - if (startingName == "" || startingName == null) { - pair.Value.AddKey(new Keyframe(0, 0, float.PositiveInfinity, float.PositiveInfinity)); - } else { - if (pair.Key == startingName) { - pair.Value.AddKey(new Keyframe(0, 1, float.PositiveInfinity, float.PositiveInfinity)); - } else { - pair.Value.AddKey(new Keyframe(0, 0, float.PositiveInfinity, float.PositiveInfinity)); - } - } - } - } - - float currentTime = timeline.Frames[0]; - float endTime = frames[frames.Length - 1]; - int f = 0; - while (currentTime < endTime) { - float time = frames[f]; - - int frameIndex = (time >= frames[frames.Length - 1] ? frames.Length : BinarySearch(frames, time)) - 1; - - string name = timeline.AttachmentNames[frameIndex]; - foreach (var pair in curveTable) { - if (name == "") { - pair.Value.AddKey(new Keyframe(time, 0, float.PositiveInfinity, float.PositiveInfinity)); - } else { - if (pair.Key == name) { - pair.Value.AddKey(new Keyframe(time, 1, float.PositiveInfinity, float.PositiveInfinity)); - } else { - pair.Value.AddKey(new Keyframe(time, 0, float.PositiveInfinity, float.PositiveInfinity)); - } - } - } - - currentTime = time; - f += 1; - } - - foreach (var pair in curveTable) { - string path = slotPath + "/" + pair.Key; - string prop = "m_IsActive"; - - clip.SetCurve(path, typeof(GameObject), prop, pair.Value); - } - } - - static float GetUninheritedRotation (Bone b) { - - Bone parent = b.Parent; - float angle = b.AppliedRotation; - - while (parent != null) { - angle -= parent.AppliedRotation; - parent = parent.Parent; - } - - return angle; - } - - static void BakeBone (Bone bone, Spine.Animation animation, AnimationClip clip) { + static void BakeBoneConstraints (Bone bone, Spine.Animation animation, AnimationClip clip) { Skeleton skeleton = bone.Skeleton; bool inheritRotation = bone.Data.TransformMode.InheritsRotation(); @@ -942,7 +834,7 @@ namespace Spine.Unity.Editor { float rotation = bone.AppliedRotation; if (!inheritRotation) - rotation = GetUninheritedRotation(bone); + rotation = GetUninheritedAppliedRotation(bone); keys.Add(new Keyframe(0, rotation, 0, 0)); @@ -950,13 +842,13 @@ namespace Spine.Unity.Editor { float r = rotation; - int steps = Mathf.CeilToInt(duration / bakeIncrement); + int steps = Mathf.CeilToInt(duration / BakeIncrement); float currentTime = 0; float angle = rotation; for (int i = 1; i <= steps; i++) { - currentTime += bakeIncrement; + currentTime += BakeIncrement; if (i == steps) currentTime = duration; @@ -969,7 +861,7 @@ namespace Spine.Unity.Editor { pk = keys[pIndex]; - rotation = inheritRotation ? bone.AppliedRotation : GetUninheritedRotation(bone); + rotation = inheritRotation ? bone.AppliedRotation : GetUninheritedAppliedRotation(bone); angle += Mathf.DeltaAngle(angle, rotation); @@ -1026,10 +918,7 @@ namespace Spine.Unity.Editor { while (currentTime < endTime) { int pIndex = listIndex - 1; - - float curveType = timeline.GetCurveType(frameIndex - 1); - if (curveType == 0) { //linear Keyframe px = xKeys[pIndex]; @@ -1092,10 +981,10 @@ namespace Spine.Unity.Editor { float time = frames[f]; - int steps = Mathf.FloorToInt((time - px.time) / bakeIncrement); + int steps = Mathf.FloorToInt((time - px.time) / BakeIncrement); for (int i = 1; i <= steps; i++) { - currentTime += bakeIncrement; + currentTime += BakeIncrement; if (i == steps) currentTime = time; @@ -1138,13 +1027,6 @@ namespace Spine.Unity.Editor { clip.SetCurve(path, typeof(Transform), propertyName + ".z", zCurve); } - static AnimationCurve EnsureCurveKeyCount (AnimationCurve curve) { - if (curve.length == 1) - curve.AddKey(curve.keys[0].time + 0.25f, curve.keys[0].value); - - return 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]; @@ -1234,10 +1116,10 @@ namespace Spine.Unity.Editor { float time = frames[f]; - int steps = Mathf.FloorToInt((time - px.time) / bakeIncrement); + int steps = Mathf.FloorToInt((time - px.time) / BakeIncrement); for (int i = 1; i <= steps; i++) { - currentTime += bakeIncrement; + currentTime += BakeIncrement; if (i == steps) currentTime = time; @@ -1367,10 +1249,10 @@ namespace Spine.Unity.Editor { angle += Mathf.DeltaAngle(angle, rotation); float r = angle; - int steps = Mathf.FloorToInt((time - pk.time) / bakeIncrement); + int steps = Mathf.FloorToInt((time - pk.time) / BakeIncrement); for (int i = 1; i <= steps; i++) { - currentTime += bakeIncrement; + currentTime += BakeIncrement; if (i == steps) currentTime = time; @@ -1412,18 +1294,132 @@ namespace Spine.Unity.Editor { AnimationUtility.SetEditorCurve(clip, zBind, curve); } + static void ParseEventTimeline (EventTimeline timeline, AnimationClip clip, SendMessageOptions eventOptions) { + + float[] frames = timeline.Frames; + var events = timeline.Events; + + List animEvents = new List(); + for (int i = 0; i < frames.Length; i++) { + var ev = events[i]; + + AnimationEvent ae = new AnimationEvent(); + //MITCH: left todo: Deal with Mecanim's zero-time missed event + ae.time = frames[i]; + ae.functionName = ev.Data.Name; + ae.messageOptions = eventOptions; + + if (!string.IsNullOrEmpty(ev.String)) { + ae.stringParameter = ev.String; + } else { + if (ev.Int == 0 && ev.Float == 0) { + //do nothing, raw function + } else { + if (ev.Int != 0) + ae.floatParameter = (float)ev.Int; + else + ae.floatParameter = ev.Float; + } + + } + + animEvents.Add(ae); + } + + AnimationUtility.SetAnimationEvents(clip, animEvents.ToArray()); + } + + static void ParseAttachmentTimeline (Skeleton skeleton, AttachmentTimeline timeline, Dictionary> slotLookup, AnimationClip clip) { + var attachmentNames = slotLookup[timeline.SlotIndex]; + + string bonePath = GetPath(skeleton.Slots.Items[timeline.SlotIndex].Bone.Data); + string slotPath = bonePath + "/" + skeleton.Slots.Items[timeline.SlotIndex].Data.Name; + + Dictionary curveTable = new Dictionary(); + + foreach (string str in attachmentNames) { + curveTable.Add(str, new AnimationCurve()); + } + + float[] frames = timeline.Frames; + + if (frames[0] != 0) { + string startingName = skeleton.Slots.Items[timeline.SlotIndex].Data.AttachmentName; + foreach (var pair in curveTable) { + if (startingName == "" || startingName == null) { + pair.Value.AddKey(new Keyframe(0, 0, float.PositiveInfinity, float.PositiveInfinity)); + } else { + if (pair.Key == startingName) { + pair.Value.AddKey(new Keyframe(0, 1, float.PositiveInfinity, float.PositiveInfinity)); + } else { + pair.Value.AddKey(new Keyframe(0, 0, float.PositiveInfinity, float.PositiveInfinity)); + } + } + } + } + + float currentTime = timeline.Frames[0]; + float endTime = frames[frames.Length - 1]; + int f = 0; + while (currentTime < endTime) { + float time = frames[f]; + + int frameIndex = (time >= frames[frames.Length - 1] ? frames.Length : BinarySearch(frames, time)) - 1; + + string name = timeline.AttachmentNames[frameIndex]; + foreach (var pair in curveTable) { + if (name == "") { + pair.Value.AddKey(new Keyframe(time, 0, float.PositiveInfinity, float.PositiveInfinity)); + } else { + if (pair.Key == name) { + pair.Value.AddKey(new Keyframe(time, 1, float.PositiveInfinity, float.PositiveInfinity)); + } else { + pair.Value.AddKey(new Keyframe(time, 0, float.PositiveInfinity, float.PositiveInfinity)); + } + } + } + + currentTime = time; + f += 1; + } + + foreach (var pair in curveTable) { + string path = slotPath + "/" + pair.Key; + string prop = "m_IsActive"; + + clip.SetCurve(path, typeof(GameObject), prop, pair.Value); + } + } + + static AnimationCurve EnsureCurveKeyCount (AnimationCurve curve) { + if (curve.length == 1) + curve.AddKey(curve.keys[0].time + 0.25f, curve.keys[0].value); + + return curve; + } + + static float GetUninheritedAppliedRotation (Bone b) { + Bone parent = b.Parent; + float angle = b.AppliedRotation; + + while (parent != null) { + angle -= parent.AppliedRotation; + parent = parent.Parent; + } + + return angle; + } + #endregion + #endregion + static string GetPath (BoneData b) { return GetPathRecurse(b).Substring(1); } static string GetPathRecurse (BoneData b) { - if (b == null) { - return ""; - } - + if (b == null) return ""; return GetPathRecurse(b.Parent) + "/" + b.Name; } - #endregion static void SetAnimationSettings (AnimationClip clip, AnimationClipSettings settings) { AnimationUtility.SetAnimationClipSettings(clip, settings);