static void ParseScaleTimeline (Skeleton skeleton, ScaleTimeline timeline, AnimationClip clip) { var boneData = skeleton.Data.Bones.Items[timeline.BoneIndex]; var bone = skeleton.Bones.Items[timeline.BoneIndex]; AnimationCurve xCurve = new AnimationCurve(); AnimationCurve yCurve = new AnimationCurve(); AnimationCurve zCurve = new AnimationCurve(); float endTime = timeline.Frames[(timeline.FrameCount * 3) - 3]; float currentTime = timeline.Frames[0]; List<Keyframe> xKeys = new List<Keyframe>(); List<Keyframe> yKeys = new List<Keyframe>(); xKeys.Add(new Keyframe(timeline.Frames[0], timeline.Frames[1] * boneData.ScaleX, 0, 0)); yKeys.Add(new Keyframe(timeline.Frames[0], timeline.Frames[2] * boneData.ScaleY, 0, 0)); int listIndex = 1; int frameIndex = 1; int f = 3; 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 px = xKeys[pIndex]; Keyframe py = yKeys[pIndex]; float time = frames[f]; float x = frames[f + 1] * boneData.ScaleX; float y = frames[f + 2] * boneData.ScaleY; float xOut = (x - px.value) / (time - px.time); float yOut = (y - py.value) / (time - py.time); px.outTangent = xOut; py.outTangent = yOut; xKeys.Add(new Keyframe(time, x, xOut, 0)); yKeys.Add(new Keyframe(time, y, yOut, 0)); xKeys[pIndex] = px; yKeys[pIndex] = py; currentTime = time; timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In); lastTime = time; listIndex++; } else if (curveType == 1) { //stepped Keyframe px = xKeys[pIndex]; Keyframe py = yKeys[pIndex]; float time = frames[f]; float x = frames[f + 1] * boneData.ScaleX; float y = frames[f + 2] * boneData.ScaleY; float xOut = float.PositiveInfinity; float yOut = float.PositiveInfinity; px.outTangent = xOut; py.outTangent = yOut; xKeys.Add(new Keyframe(time, x, xOut, 0)); yKeys.Add(new Keyframe(time, y, yOut, 0)); xKeys[pIndex] = px; yKeys[pIndex] = py; currentTime = time; timeline.Apply(skeleton, lastTime, currentTime, null, 1, MixBlend.Setup, MixDirection.In); lastTime = time; listIndex++; } else if (curveType == 2) { //bezier Keyframe px = xKeys[pIndex]; Keyframe py = yKeys[pIndex]; float time = frames[f]; int steps = Mathf.FloorToInt((time - px.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); px = xKeys[listIndex - 1]; py = yKeys[listIndex - 1]; float xOut = (bone.ScaleX - px.value) / (currentTime - px.time); float yOut = (bone.ScaleY - py.value) / (currentTime - py.time); px.outTangent = xOut; py.outTangent = yOut; xKeys.Add(new Keyframe(currentTime, bone.ScaleX, xOut, 0)); yKeys.Add(new Keyframe(currentTime, bone.ScaleY, yOut, 0)); xKeys[listIndex - 1] = px; yKeys[listIndex - 1] = py; listIndex++; lastTime = currentTime; } } frameIndex++; f += 3; } xCurve = EnsureCurveKeyCount(new AnimationCurve(xKeys.ToArray())); yCurve = EnsureCurveKeyCount(new AnimationCurve(yKeys.ToArray())); string path = GetPath(boneData); string propertyName = "localScale"; clip.SetCurve(path, typeof(Transform), propertyName + ".x", xCurve); clip.SetCurve(path, typeof(Transform), propertyName + ".y", yCurve); clip.SetCurve(path, typeof(Transform), propertyName + ".z", zCurve); }
private void ReadAnimation(String name, Stream input, SkeletonData skeletonData) { var timelines = new ExposedList <Timeline>(); float scale = Scale; float duration = 0; // Slot timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { int slotIndex = ReadVarint(input, true); for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) { int timelineType = input.ReadByte(); int frameCount = ReadVarint(input, true); switch (timelineType) { case SLOT_ATTACHMENT: { AttachmentTimeline timeline = new AttachmentTimeline(frameCount); timeline.slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(input), ReadString(input)); } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[frameCount - 1]); break; } case SLOT_COLOR: { ColorTimeline timeline = new ColorTimeline(frameCount); timeline.slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = ReadFloat(input); int color = ReadInt(input); float r = ((color & 0xff000000) >> 24) / 255f; float g = ((color & 0x00ff0000) >> 16) / 255f; float b = ((color & 0x0000ff00) >> 8) / 255f; float a = ((color & 0x000000ff)) / 255f; timeline.SetFrame(frameIndex, time, r, g, b, a); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * ColorTimeline.ENTRIES]); break; } case SLOT_TWO_COLOR: { TwoColorTimeline timeline = new TwoColorTimeline(frameCount); timeline.slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = ReadFloat(input); int color = ReadInt(input); float r = ((color & 0xff000000) >> 24) / 255f; float g = ((color & 0x00ff0000) >> 16) / 255f; float b = ((color & 0x0000ff00) >> 8) / 255f; float a = ((color & 0x000000ff)) / 255f; int color2 = ReadInt(input); // 0x00rrggbb float r2 = ((color2 & 0x00ff0000) >> 16) / 255f; float g2 = ((color2 & 0x0000ff00) >> 8) / 255f; float b2 = ((color2 & 0x000000ff)) / 255f; timeline.SetFrame(frameIndex, time, r, g, b, a, r2, g2, b2); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * TwoColorTimeline.ENTRIES]); break; } } } } // Bone timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { int boneIndex = ReadVarint(input, true); for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) { int timelineType = input.ReadByte(); int frameCount = ReadVarint(input, true); switch (timelineType) { case BONE_ROTATE: { RotateTimeline timeline = new RotateTimeline(frameCount); timeline.boneIndex = boneIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input)); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[(frameCount - 1) * RotateTimeline.ENTRIES]); break; } case BONE_TRANSLATE: case BONE_SCALE: case BONE_SHEAR: { TranslateTimeline timeline; float timelineScale = 1; if (timelineType == BONE_SCALE) { timeline = new ScaleTimeline(frameCount); } else if (timelineType == BONE_SHEAR) { timeline = new ShearTimeline(frameCount); } else { timeline = new TranslateTimeline(frameCount); timelineScale = scale; } timeline.boneIndex = boneIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale, ReadFloat(input) * timelineScale); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TranslateTimeline.ENTRIES]); break; } } } } // IK timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { int index = ReadVarint(input, true); int frameCount = ReadVarint(input, true); IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount) { ikConstraintIndex = index }; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadSByte(input), ReadBoolean(input), ReadBoolean(input)); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[(frameCount - 1) * IkConstraintTimeline.ENTRIES]); } // Transform constraint timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { int index = ReadVarint(input, true); int frameCount = ReadVarint(input, true); TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount); timeline.transformConstraintIndex = index; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input)); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TransformConstraintTimeline.ENTRIES]); } // Path constraint timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { int index = ReadVarint(input, true); PathConstraintData data = skeletonData.pathConstraints.Items[index]; for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) { int timelineType = ReadSByte(input); int frameCount = ReadVarint(input, true); switch (timelineType) { case PATH_POSITION: case PATH_SPACING: { PathConstraintPositionTimeline timeline; float timelineScale = 1; if (timelineType == PATH_SPACING) { timeline = new PathConstraintSpacingTimeline(frameCount); if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) { timelineScale = scale; } } else { timeline = new PathConstraintPositionTimeline(frameCount); if (data.positionMode == PositionMode.Fixed) { timelineScale = scale; } } timeline.pathConstraintIndex = index; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintPositionTimeline.ENTRIES]); break; } case PATH_MIX: { PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(frameCount); timeline.pathConstraintIndex = index; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input)); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintMixTimeline.ENTRIES]); break; } } } } // Deform timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { Skin skin = skeletonData.skins.Items[ReadVarint(input, true)]; for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) { int slotIndex = ReadVarint(input, true); for (int iii = 0, nnn = ReadVarint(input, true); iii < nnn; iii++) { VertexAttachment attachment = (VertexAttachment)skin.GetAttachment(slotIndex, ReadString(input)); bool weighted = attachment.bones != null; float[] vertices = attachment.vertices; int deformLength = weighted ? vertices.Length / 3 * 2 : vertices.Length; int frameCount = ReadVarint(input, true); DeformTimeline timeline = new DeformTimeline(frameCount); timeline.slotIndex = slotIndex; timeline.attachment = attachment; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = ReadFloat(input); float[] deform; int end = ReadVarint(input, true); if (end == 0) { deform = weighted ? new float[deformLength] : vertices; } else { deform = new float[deformLength]; int start = ReadVarint(input, true); end += start; if (scale == 1) { for (int v = start; v < end; v++) { deform[v] = ReadFloat(input); } } else { for (int v = start; v < end; v++) { deform[v] = ReadFloat(input) * scale; } } if (!weighted) { for (int v = 0, vn = deform.Length; v < vn; v++) { deform[v] += vertices[v]; } } } timeline.SetFrame(frameIndex, time, deform); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[frameCount - 1]); } } } // Draw order timeline. int drawOrderCount = ReadVarint(input, true); if (drawOrderCount > 0) { DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount); int slotCount = skeletonData.slots.Count; for (int i = 0; i < drawOrderCount; i++) { float time = ReadFloat(input); int offsetCount = ReadVarint(input, true); int[] drawOrder = new int[slotCount]; for (int ii = slotCount - 1; ii >= 0; ii--) { drawOrder[ii] = -1; } int[] unchanged = new int[slotCount - offsetCount]; int originalIndex = 0, unchangedIndex = 0; for (int ii = 0; ii < offsetCount; ii++) { int slotIndex = ReadVarint(input, true); // Collect unchanged items. while (originalIndex != slotIndex) { unchanged[unchangedIndex++] = originalIndex++; } // Set changed items. drawOrder[originalIndex + ReadVarint(input, true)] = originalIndex++; } // Collect remaining unchanged items. while (originalIndex < slotCount) { unchanged[unchangedIndex++] = originalIndex++; } // Fill in unchanged items. for (int ii = slotCount - 1; ii >= 0; ii--) { if (drawOrder[ii] == -1) { drawOrder[ii] = unchanged[--unchangedIndex]; } } timeline.SetFrame(i, time, drawOrder); } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[drawOrderCount - 1]); } // Event timeline. int eventCount = ReadVarint(input, true); if (eventCount > 0) { EventTimeline timeline = new EventTimeline(eventCount); for (int i = 0; i < eventCount; i++) { float time = ReadFloat(input); EventData eventData = skeletonData.events.Items[ReadVarint(input, true)]; Event e = new Event(time, eventData) { Int = ReadVarint(input, false), Float = ReadFloat(input), String = ReadBoolean(input) ? ReadString(input) : eventData.String }; if (e.data.AudioPath != null) { e.volume = ReadFloat(input); e.balance = ReadFloat(input); } timeline.SetFrame(i, e); } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[eventCount - 1]); } timelines.TrimExcess(); skeletonData.animations.Add(new Animation(name, timelines, duration)); }
void readAnimation(string name, SkeletonData skeletonData) { List <Timeline> timelines = new List <Timeline>(); float scale = 1; float duration = 0; //Slot timelines for (int i = 0, n = ReadInt(); i < n; i++) { int slotIndex = ReadInt(); for (int ii = 0, nn = ReadInt(); ii < nn; ii++) { int timelineType = Read(); int frameCount = ReadInt(); switch (timelineType) { case TIMELINE_COLOR: { ColorTimeline timeline = new ColorTimeline(frameCount); timeline.slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = ReadFloat(); m_tempColor = ReadColor(); //Color timeline.setFrame(frameIndex, time, m_tempColor.r, m_tempColor.g, m_tempColor.b, m_tempColor.a); if (frameIndex < frameCount - 1) { readCurve(frameIndex, timeline); } } timelines.Add(timeline); duration = Mathf.Max(duration, timeline.Frames[frameCount * 5 - 5]); break; } case TIMELINE_ATTACHMENT: { AttachmentTimeline timeline = new AttachmentTimeline(frameCount); timeline.slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.setFrame(frameIndex, ReadFloat(), ReadString()); } timelines.Add(timeline); duration = Mathf.Max(duration, timeline.Frames[frameCount - 1]); break; } } } } //Bone timelines for (int i = 0, n = ReadInt(); i < n; i++) { int boneIndex = ReadInt(); for (int ii = 0, nn = ReadInt(); ii < nn; ii++) { int timelineType = Read(); int frameCount = ReadInt(); switch (timelineType) { case TIMELINE_ROTATE: { RotateTimeline timeline = new RotateTimeline(frameCount); timeline.boneIndex = boneIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(), ReadFloat()); if (frameIndex < frameCount - 1) { readCurve(frameIndex, timeline); } } timelines.Add(timeline); duration = Mathf.Max(duration, timeline.Frames[frameCount * 2 - 2]); break; } case TIMELINE_TRANSLATE: case TIMELINE_SCALE: { TranslateTimeline timeline; float timelineScale = 1; if (timelineType == TIMELINE_SCALE) { timeline = new ScaleTimeline(frameCount); } else { timeline = new TranslateTimeline(frameCount); timelineScale = scale; } timeline.boneIndex = boneIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(), ReadFloat() * timelineScale, ReadFloat() * timelineScale); if (frameIndex < frameCount - 1) { readCurve(frameIndex, timeline); } } timelines.Add(timeline); duration = Mathf.Max(duration, timeline.Frames[frameCount * 3 - 3]); break; } } } } //FFD timelines for (int i = 0, n = ReadInt(); i < n; i++) { Skin skin = skeletonData.skins[ReadInt() + 1]; for (int ii = 0, nn = ReadInt(); ii < nn; ii++) { int slotIndex = ReadInt(); for (int iii = 0, nnn = ReadInt(); iii < nnn; iii++) { Attachment attachment = skin.GetAttachment(slotIndex, ReadString()); int frameCount = ReadInt(); FFDTimeline timeline = new FFDTimeline(frameCount); timeline.slotIndex = slotIndex; timeline.attachment = attachment; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = ReadFloat(); float[] vertices; int vertexCount; if (attachment.GetType() == typeof(MeshAttachment)) { vertexCount = ((MeshAttachment)attachment).vertices.Length; } else { vertexCount = ((SkinnedMeshAttachment)attachment).weights.Length / 3 * 2; } int end = ReadInt(); if (end == 0) { if (attachment.GetType() == typeof(MeshAttachment)) { vertices = ((MeshAttachment)attachment).vertices; } else { vertices = new float[vertexCount]; } } else { vertices = new float[vertexCount]; int start = ReadInt(); end += start; if (scale == 1) { for (int v = start; v < end; v++) { vertices[v] = ReadFloat(); } } else { for (int v = start; v < end; v++) { vertices[v] = ReadFloat() * scale; } } if (attachment.GetType() == typeof(MeshAttachment)) { float[] meshVertices = ((MeshAttachment)attachment).vertices; for (int v = 0, vn = vertices.Length; v < vn; v++) { vertices[v] += meshVertices[v]; } } } timeline.setFrame(frameIndex, time, vertices); if (frameIndex < frameCount - 1) { readCurve(frameIndex, timeline); } } timelines.Add(timeline); duration = Mathf.Max(duration, timeline.Frames[frameCount - 1]); } } } //Draw order timeline int drawOrderCount = ReadInt(); if (drawOrderCount > 0) { DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount); int slotCount = skeletonData.slots.Count; for (int i = 0; i < drawOrderCount; i++) { int offsetCount = ReadInt(); int[] drawOrder = new int[slotCount]; for (int ii = slotCount - 1; ii >= 0; ii--) { drawOrder[ii] = -1; } int[] unchanged = new int[slotCount - offsetCount]; int originalIndex = 0, unchangedIndex = 0; for (int ii = 0; ii < offsetCount; ii++) { int slotIndex = ReadInt(); // Collect unchanged items. while (originalIndex != slotIndex) { unchanged[unchangedIndex++] = originalIndex++; } // Set changed items. drawOrder[originalIndex + ReadInt()] = originalIndex++; } // Collect remaining unchanged items. while (originalIndex < slotCount) { unchanged[unchangedIndex++] = originalIndex++; } // Fill in unchanged items. for (int ii = slotCount - 1; ii >= 0; ii--) { if (drawOrder[ii] == -1) { drawOrder[ii] = unchanged[--unchangedIndex]; } } timeline.setFrame(i, ReadFloat(), drawOrder); } timelines.Add(timeline); duration = Mathf.Max(duration, timeline.Frames[drawOrderCount - 1]); } //Event timeline int eventCount = ReadInt(); if (eventCount > 0) { EventTimeline timeline = new EventTimeline(eventCount); for (int i = 0; i < eventCount; i++) { float time = ReadFloat(); EventData eventData = skeletonData.events[ReadInt()]; Spine.Event event1 = new Spine.Event(eventData); event1.Int = ReadInt(false); event1.Float = ReadFloat(); event1.String = ReadBoolean() ? ReadString() : eventData.String; timeline.setFrame(i, time, event1); } timelines.Add(timeline); duration = Mathf.Max(duration, timeline.Frames[eventCount - 1]); } timelines.TrimExcess(); skeletonData.AddAnimation(new Spine.Animation(name, timelines, duration)); }
private ITimeline ReadAnimationScaleTimeline(JArray jsonTimelineList, int boneIndex) { var scaleTimeline = new ScaleTimeline(jsonTimelineList.Count); PopulateAnimationTranslationScaleTimeline(scaleTimeline, jsonTimelineList, boneIndex, 1); return scaleTimeline; }