/// <summary> /// Reads the animation. /// </summary> /// <param name="name">The name.</param> /// <param name="map">The map.</param> /// <param name="skeletonData">The skeleton data.</param> /// <exception cref="System.Exception">Bone not found: + boneName</exception> private void ReadAnimation(string name, Dictionary<string, object> map, SkeletonData skeletonData) { var timelines = new List<ITimeline>(); float duration = 0; if (map.ContainsKey("bones")) { var bonesMap = (Dictionary<string, object>)map["bones"]; foreach (KeyValuePair<string, object> entry in bonesMap) { 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; string timelineName = (string)timelineEntry.Key; if (timelineName.Equals(TimelineRotate)) { RotateTimeline 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"]); this.ReadCurve(timeline, frameIndex, valueMap); frameIndex++; } timelines.Add(timeline); duration = Math.Max(duration, timeline.Frames[(timeline.FrameCount * 2) - 2]); } else if (timelineName.Equals(TimelineTranslate) || timelineName.Equals(TimelineScale)) { TranslateTimeline timeline; float timelineScale = 1; if (timelineName.Equals(TimelineScale)) { timeline = new ScaleTimeline(values.Count); } else { timeline = new TranslateTimeline(values.Count); timelineScale = this.Scale; } timeline.BoneIndex = boneIndex; int frameIndex = 0; foreach (Dictionary<string, object> valueMap in values) { float time = (float)valueMap["time"]; float x = valueMap.ContainsKey("x") ? (float)valueMap["x"] : 0; float y = valueMap.ContainsKey("y") ? (float)valueMap["y"] : 0; timeline.SetFrame(frameIndex, time, (float)x * timelineScale, (float)y * timelineScale); this.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 + ")"); } } } } if (map.ContainsKey("slots")) { var slotsMap = (Dictionary<string, object>)map["slots"]; foreach (KeyValuePair<string, object> entry in slotsMap) { 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; string timelineName = (string)timelineEntry.Key; if (timelineName.Equals(TimelineColor)) { ColorTimeline 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)); this.ReadCurve(timeline, frameIndex, valueMap); frameIndex++; } timelines.Add(timeline); duration = Math.Max(duration, timeline.Frames[(timeline.FrameCount * 5) - 5]); } else if (timelineName.Equals(TimelineAttachment)) { AttachmentTimeline 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 + ")"); } } } } timelines.TrimExcess(); skeletonData.AddAnimation(new Animation(name, timelines, duration)); }
/// <summary> /// Reads the skeleton data. /// </summary> /// <param name="reader">The reader.</param> /// <returns>Return SkeletonData.</returns> /// <exception cref="System.ArgumentNullException">reader cannot be null.</exception> /// <exception cref="System.Exception">Invalid JSON.</exception> public SkeletonData ReadSkeletonData(TextReader reader) { if (reader == null) { throw new ArgumentNullException("reader cannot be null."); } SkeletonData skeletonData = new SkeletonData(); var root = Json.Deserialize(reader) as Dictionary<string, object>; if (root == null) { throw new Exception("Invalid JSON."); } // Bones. foreach (Dictionary<string, object> boneMap in (List<object>)root["bones"]) { BoneData parent = null; if (boneMap.ContainsKey("parent")) { parent = skeletonData.FindBone((string)boneMap["parent"]); if (parent == null) { throw new Exception("Parent bone not found: " + boneMap["parent"]); } } BoneData boneData = new BoneData((string)boneMap["name"], parent); boneData.Length = this.GetFloat(boneMap, "length", 0) * this.Scale; boneData.X = this.GetFloat(boneMap, "x", 0) * this.Scale; boneData.Y = this.GetFloat(boneMap, "y", 0) * this.Scale; boneData.Rotation = this.GetFloat(boneMap, "rotation", 0); boneData.ScaleX = this.GetFloat(boneMap, "scaleX", 1); boneData.ScaleY = this.GetFloat(boneMap, "scaleY", 1); skeletonData.AddBone(boneData); } // Slots. if (root.ContainsKey("slots")) { var slots = (List<object>)root["slots"]; foreach (Dictionary<string, object> slotMap in (List<object>)slots) { string slotName = (string)slotMap["name"]; string boneName = (string)slotMap["bone"]; BoneData boneData = skeletonData.FindBone(boneName); if (boneData == null) { throw new Exception("Slot bone not found: " + boneName); } SlotData slotData = new SlotData(slotName, boneData); if (slotMap.ContainsKey("color")) { string color = (string)slotMap["color"]; slotData.R = ToColor(color, 0); slotData.G = ToColor(color, 1); slotData.B = ToColor(color, 2); slotData.A = ToColor(color, 3); } if (slotMap.ContainsKey("attachment")) { slotData.AttachmentName = (string)slotMap["attachment"]; } skeletonData.AddSlot(slotData); } } // Skins. if (root.ContainsKey("skins")) { var skinMap = (Dictionary<string, object>)root["skins"]; foreach (KeyValuePair<string, object> entry in skinMap) { Skin skin = new Skin(entry.Key); foreach (KeyValuePair<string, object> slotEntry in (Dictionary<string, object>)entry.Value) { int slotIndex = skeletonData.FindSlotIndex(slotEntry.Key); foreach (KeyValuePair<string, object> attachmentEntry in (Dictionary<string, object>)slotEntry.Value) { Attachment attachment = this.ReadAttachment(skin, attachmentEntry.Key, (Dictionary<string, object>)attachmentEntry.Value); skin.AddAttachment(slotIndex, attachmentEntry.Key, attachment); } } skeletonData.AddSkin(skin); if (skin.Name == "default") { skeletonData.DefaultSkin = skin; } } } // Animations. if (root.ContainsKey("animations")) { var animationMap = (Dictionary<string, object>)root["animations"]; foreach (KeyValuePair<string, object> entry in animationMap) { this.ReadAnimation(entry.Key, (Dictionary<string, object>)entry.Value, skeletonData); } } skeletonData.Bones.TrimExcess(); skeletonData.Slots.TrimExcess(); skeletonData.Skins.TrimExcess(); skeletonData.Animations.TrimExcess(); return skeletonData; }