/// <summary>Fires events for frames > lastTime and <= time.</summary> public void Apply(Skeleton skeleton, float lastTime, float time, ExposedList <Event> firedEvents, float alpha) { if (firedEvents == null) { return; } float[] frames = this.frames; int frameCount = frames.Length; if (lastTime > time) // Fire events after last time for looped animations. { Apply(skeleton, lastTime, int.MaxValue, firedEvents, alpha); lastTime = -1f; } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame. { return; } if (time < frames[0]) { return; // Time is before first frame. } int frame; if (lastTime < frames[0]) { frame = 0; } else { frame = Animation.binarySearch(frames, lastTime); float frameTime = frames[frame]; while (frame > 0) // Fire multiple events with the same frame. { if (frames[frame - 1] != frameTime) { break; } frame--; } } for (; frame < frameCount && time >= frames[frame]; frame++) { firedEvents.Add(events[frame]); } }
public Skeleton(SkeletonData data) { if (data == null) { throw new ArgumentNullException("data cannot be null."); } this.data = data; bones = new ExposedList <Bone>(data.bones.Count); foreach (BoneData boneData in data.bones) { Bone parent = boneData.parent == null ? null : bones.Items[data.bones.IndexOf(boneData.parent)]; Bone bone = new Bone(boneData, this, parent); if (parent != null) { parent.children.Add(bone); } bones.Add(bone); } slots = new ExposedList <Slot>(data.slots.Count); drawOrder = new ExposedList <Slot>(data.slots.Count); foreach (SlotData slotData in data.slots) { Bone bone = bones.Items[data.bones.IndexOf(slotData.boneData)]; Slot slot = new Slot(slotData, bone); slots.Add(slot); drawOrder.Add(slot); } ikConstraints = new ExposedList <IkConstraint>(data.ikConstraints.Count); foreach (IkConstraintData ikConstraintData in data.ikConstraints) { ikConstraints.Add(new IkConstraint(ikConstraintData, this)); } transformConstraints = new ExposedList <TransformConstraint>(data.transformConstraints.Count); foreach (TransformConstraintData transformConstraintData in data.transformConstraints) { transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); } UpdateCache(); UpdateWorldTransform(); }
public IkConstraint(IkConstraintData data, Skeleton skeleton) { if (data == null) { throw new ArgumentNullException("data cannot be null."); } if (skeleton == null) { throw new ArgumentNullException("skeleton cannot be null."); } this.data = data; mix = data.mix; bendDirection = data.bendDirection; bones = new ExposedList <Bone>(data.bones.Count); foreach (BoneData boneData in data.bones) { bones.Add(skeleton.FindBone(boneData.name)); } target = skeleton.FindBone(data.target.name); }
public void Apply(Skeleton skeleton, float lastTime, float time, ExposedList <Event> firedEvents, float alpha) { float[] frames = this.frames; if (time < frames[0]) { return; // Time is before first frame. } int frame; if (time >= frames[frames.Length - 1]) // Time is after last frame. { frame = frames.Length - 1; } else { frame = Animation.binarySearch(frames, time) - 1; } ExposedList <Slot> drawOrder = skeleton.drawOrder; ExposedList <Slot> slots = skeleton.slots; int[] drawOrderToSetupIndex = drawOrders[frame]; if (drawOrderToSetupIndex == null) { drawOrder.Clear(); for (int i = 0, n = slots.Count; i < n; i++) { drawOrder.Add(slots.Items[i]); } } else { for (int i = 0, n = drawOrderToSetupIndex.Length; i < n; i++) { drawOrder.Items[i] = slots.Items[drawOrderToSetupIndex[i]]; } } }
private void ReadAnimation(String name, Dictionary <String, Object> map, SkeletonData skeletonData) { var timelines = new ExposedList <Timeline>(); float duration = 0; var scale = this.Scale; if (map.ContainsKey("slots")) { foreach (KeyValuePair <String, Object> entry in (Dictionary <String, Object>)map["slots"]) { String slotName = entry.Key; int slotIndex = skeletonData.FindSlotIndex(slotName); var timelineMap = (Dictionary <String, Object>)entry.Value; foreach (KeyValuePair <String, Object> timelineEntry in timelineMap) { var values = (List <Object>)timelineEntry.Value; var timelineName = (String)timelineEntry.Key; if (timelineName == "color") { var timeline = new ColorTimeline(values.Count); timeline.slotIndex = slotIndex; int frameIndex = 0; foreach (Dictionary <String, Object> valueMap in values) { float time = (float)valueMap["time"]; String c = (String)valueMap["color"]; timeline.SetFrame(frameIndex, time, ToColor(c, 0), ToColor(c, 1), ToColor(c, 2), ToColor(c, 3)); ReadCurve(timeline, frameIndex, valueMap); frameIndex++; } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 5 - 5]); } else if (timelineName == "attachment") { var timeline = new AttachmentTimeline(values.Count); timeline.slotIndex = slotIndex; int frameIndex = 0; foreach (Dictionary <String, Object> valueMap in values) { float time = (float)valueMap["time"]; timeline.SetFrame(frameIndex++, time, (String)valueMap["name"]); } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]); } else { throw new Exception("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")"); } } } } if (map.ContainsKey("bones")) { foreach (KeyValuePair <String, Object> entry in (Dictionary <String, Object>)map["bones"]) { String boneName = entry.Key; int boneIndex = skeletonData.FindBoneIndex(boneName); if (boneIndex == -1) { throw new Exception("Bone not found: " + boneName); } var timelineMap = (Dictionary <String, Object>)entry.Value; foreach (KeyValuePair <String, Object> timelineEntry in timelineMap) { var values = (List <Object>)timelineEntry.Value; var timelineName = (String)timelineEntry.Key; if (timelineName == "rotate") { var timeline = new RotateTimeline(values.Count); timeline.boneIndex = boneIndex; int frameIndex = 0; foreach (Dictionary <String, Object> valueMap in values) { float time = (float)valueMap["time"]; timeline.SetFrame(frameIndex, time, (float)valueMap["angle"]); ReadCurve(timeline, frameIndex, valueMap); frameIndex++; } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 2 - 2]); } else if (timelineName == "translate" || timelineName == "scale" || timelineName == "shear") { TranslateTimeline timeline; float timelineScale = 1; if (timelineName == "scale") { timeline = new ScaleTimeline(values.Count); } else if (timelineName == "shear") { timeline = new ShearTimeline(values.Count); } else { timeline = new TranslateTimeline(values.Count); timelineScale = scale; } timeline.boneIndex = boneIndex; int frameIndex = 0; foreach (Dictionary <String, Object> valueMap in values) { float time = (float)valueMap["time"]; float x = GetFloat(valueMap, "x", 0); float y = GetFloat(valueMap, "y", 0); timeline.SetFrame(frameIndex, time, (float)x * timelineScale, (float)y * timelineScale); ReadCurve(timeline, frameIndex, valueMap); frameIndex++; } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 3 - 3]); } else { throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")"); } } } } // IK timelines. if (map.ContainsKey("ik")) { foreach (KeyValuePair <String, Object> constraintMap in (Dictionary <String, Object>)map["ik"]) { IkConstraintData constraint = skeletonData.FindIkConstraint(constraintMap.Key); var values = (List <Object>)constraintMap.Value; var timeline = new IkConstraintTimeline(values.Count); timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(constraint); int frameIndex = 0; foreach (Dictionary <String, Object> valueMap in values) { float time = (float)valueMap["time"]; float mix = GetFloat(valueMap, "mix", 1); bool bendPositive = GetBoolean(valueMap, "bendPositive", true); timeline.SetFrame(frameIndex, time, mix, bendPositive ? 1 : -1); ReadCurve(timeline, frameIndex, valueMap); frameIndex++; } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 3 - 3]); } } // Transform constraint timelines. if (map.ContainsKey("transform")) { foreach (KeyValuePair <String, Object> constraintMap in (Dictionary <String, Object>)map["transform"]) { TransformConstraintData constraint = skeletonData.FindTransformConstraint(constraintMap.Key); var values = (List <Object>)constraintMap.Value; var timeline = new TransformConstraintTimeline(values.Count); timeline.transformConstraintIndex = skeletonData.transformConstraints.IndexOf(constraint); int frameIndex = 0; foreach (Dictionary <String, Object> valueMap in values) { float time = (float)valueMap["time"]; float rotateMix = GetFloat(valueMap, "rotateMix", 1); float translateMix = GetFloat(valueMap, "translateMix", 1); float scaleMix = GetFloat(valueMap, "scaleMix", 1); float shearMix = GetFloat(valueMap, "shearMix", 1); timeline.SetFrame(frameIndex, time, rotateMix, translateMix, scaleMix, shearMix); ReadCurve(timeline, frameIndex, valueMap); frameIndex++; } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 5 - 5]); } } // FFD timelines. if (map.ContainsKey("ffd")) { foreach (KeyValuePair <String, Object> ffdMap in (Dictionary <String, Object>)map["ffd"]) { Skin skin = skeletonData.FindSkin(ffdMap.Key); foreach (KeyValuePair <String, Object> slotMap in (Dictionary <String, Object>)ffdMap.Value) { int slotIndex = skeletonData.FindSlotIndex(slotMap.Key); foreach (KeyValuePair <String, Object> meshMap in (Dictionary <String, Object>)slotMap.Value) { var values = (List <Object>)meshMap.Value; var timeline = new FfdTimeline(values.Count); Attachment attachment = skin.GetAttachment(slotIndex, meshMap.Key); if (attachment == null) { throw new Exception("FFD attachment not found: " + meshMap.Key); } timeline.slotIndex = slotIndex; timeline.attachment = attachment; int vertexCount; if (attachment is MeshAttachment) { vertexCount = ((MeshAttachment)attachment).vertices.Length; } else { vertexCount = ((WeightedMeshAttachment)attachment).Weights.Length / 3 * 2; } int frameIndex = 0; foreach (Dictionary <String, Object> valueMap in values) { float[] vertices; if (!valueMap.ContainsKey("vertices")) { if (attachment is MeshAttachment) { vertices = ((MeshAttachment)attachment).vertices; } else { vertices = new float[vertexCount]; } } else { var verticesValue = (List <Object>)valueMap["vertices"]; vertices = new float[vertexCount]; int start = GetInt(valueMap, "offset", 0); if (scale == 1) { for (int i = 0, n = verticesValue.Count; i < n; i++) { vertices[i + start] = (float)verticesValue[i]; } } else { for (int i = 0, n = verticesValue.Count; i < n; i++) { vertices[i + start] = (float)verticesValue[i] * scale; } } if (attachment is MeshAttachment) { float[] meshVertices = ((MeshAttachment)attachment).vertices; for (int i = 0; i < vertexCount; i++) { vertices[i] += meshVertices[i]; } } } timeline.SetFrame(frameIndex, (float)valueMap["time"], vertices); ReadCurve(timeline, frameIndex, valueMap); frameIndex++; } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]); } } } } if (map.ContainsKey("drawOrder") || map.ContainsKey("draworder")) { var values = (List <Object>)map[map.ContainsKey("drawOrder") ? "drawOrder" : "draworder"]; var timeline = new DrawOrderTimeline(values.Count); int slotCount = skeletonData.slots.Count; int frameIndex = 0; foreach (Dictionary <String, Object> drawOrderMap in values) { int[] drawOrder = null; if (drawOrderMap.ContainsKey("offsets")) { drawOrder = new int[slotCount]; for (int i = slotCount - 1; i >= 0; i--) { drawOrder[i] = -1; } var offsets = (List <Object>)drawOrderMap["offsets"]; int[] unchanged = new int[slotCount - offsets.Count]; int originalIndex = 0, unchangedIndex = 0; foreach (Dictionary <String, Object> offsetMap in offsets) { int slotIndex = skeletonData.FindSlotIndex((String)offsetMap["slot"]); if (slotIndex == -1) { throw new Exception("Slot not found: " + offsetMap["slot"]); } // Collect unchanged items. while (originalIndex != slotIndex) { unchanged[unchangedIndex++] = originalIndex++; } // Set changed items. int index = originalIndex + (int)(float)offsetMap["offset"]; drawOrder[index] = originalIndex++; } // Collect remaining unchanged items. while (originalIndex < slotCount) { unchanged[unchangedIndex++] = originalIndex++; } // Fill in unchanged items. for (int i = slotCount - 1; i >= 0; i--) { if (drawOrder[i] == -1) { drawOrder[i] = unchanged[--unchangedIndex]; } } } timeline.SetFrame(frameIndex++, (float)drawOrderMap["time"], drawOrder); } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]); } if (map.ContainsKey("events")) { var eventsMap = (List <Object>)map["events"]; var timeline = new EventTimeline(eventsMap.Count); int frameIndex = 0; foreach (Dictionary <String, Object> eventMap in eventsMap) { EventData eventData = skeletonData.FindEvent((String)eventMap["name"]); if (eventData == null) { throw new Exception("Event not found: " + eventMap["name"]); } var e = new Event((float)eventMap["time"], eventData); e.Int = GetInt(eventMap, "int", eventData.Int); e.Float = GetFloat(eventMap, "float", eventData.Float); e.String = GetString(eventMap, "string", eventData.String); timeline.SetFrame(frameIndex++, e); } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]); } timelines.TrimExcess(); skeletonData.animations.Add(new Animation(name, timelines, duration)); }
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 TIMELINE_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[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(input), ReadString(input)); } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[frameCount - 1]); 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 TIMELINE_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 * 2 - 2]); break; } case TIMELINE_TRANSLATE: case TIMELINE_SCALE: case TIMELINE_SHEAR: { TranslateTimeline timeline; float timelineScale = 1; if (timelineType == TIMELINE_SCALE) { timeline = new ScaleTimeline(frameCount); } else if (timelineType == TIMELINE_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 * 3 - 3]); break; } } } } // IK timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { IkConstraintData constraint = skeletonData.ikConstraints.Items[ReadVarint(input, true)]; int frameCount = ReadVarint(input, true); IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount); timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(constraint); for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadSByte(input)); if (frameIndex < frameCount - 1) { ReadCurve(input, frameIndex, timeline); } } timelines.Add(timeline); duration = Math.Max(duration, timeline.frames[frameCount * 3 - 3]); } // Transform constraint timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { TransformConstraintData constraint = skeletonData.transformConstraints.Items[ReadVarint(input, true)]; int frameCount = ReadVarint(input, true); TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount); timeline.transformConstraintIndex = skeletonData.transformConstraints.IndexOf(constraint); 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 * 5 - 5]); } // FFD 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++) { Attachment attachment = skin.GetAttachment(slotIndex, ReadString(input)); int frameCount = ReadVarint(input, true); FfdTimeline timeline = new FfdTimeline(frameCount); timeline.slotIndex = slotIndex; timeline.attachment = attachment; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = ReadFloat(input); float[] vertices; int vertexCount; if (attachment is MeshAttachment) { vertexCount = ((MeshAttachment)attachment).vertices.Length; } else { vertexCount = ((WeightedMeshAttachment)attachment).weights.Length / 3 * 2; } int end = ReadVarint(input, true); if (end == 0) { if (attachment is MeshAttachment) { vertices = ((MeshAttachment)attachment).vertices; } else { vertices = new float[vertexCount]; } } else { vertices = new float[vertexCount]; int start = ReadVarint(input, true); end += start; if (scale == 1) { for (int v = start; v < end; v++) { vertices[v] = ReadFloat(input); } } else { for (int v = start; v < end; v++) { vertices[v] = ReadFloat(input) * scale; } } if (attachment is 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(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); e.Int = ReadVarint(input, false); e.Float = ReadFloat(input); e.String = ReadBoolean(input) ? ReadString(input) : eventData.String; 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)); }