private Attachment ReadAttachment(Stream input, Skin skin, int slotIndex, String attachmentName, bool nonessential) { float scale = Scale; String name = ReadString(input); if (name == null) { name = attachmentName; } AttachmentType type = (AttachmentType)input.ReadByte(); switch (type) { case AttachmentType.region: { String path = ReadString(input); float rotation = ReadFloat(input); float x = ReadFloat(input); float y = ReadFloat(input); float scaleX = ReadFloat(input); float scaleY = ReadFloat(input); float width = ReadFloat(input); float height = ReadFloat(input); int color = ReadInt(input); if (path == null) { path = name; } RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path); if (region == null) { return(null); } region.Path = path; region.x = x * scale; region.y = y * scale; region.scaleX = scaleX; region.scaleY = scaleY; region.rotation = rotation; region.width = width * scale; region.height = height * scale; region.r = ((color & 0xff000000) >> 24) / 255f; region.g = ((color & 0x00ff0000) >> 16) / 255f; region.b = ((color & 0x0000ff00) >> 8) / 255f; region.a = ((color & 0x000000ff)) / 255f; region.UpdateOffset(); return(region); } case AttachmentType.boundingbox: { float[] vertices = ReadFloatArray(input, ReadVarint(input, true) * 2, scale); BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name); if (box == null) { return(null); } box.vertices = vertices; return(box); } case AttachmentType.mesh: { String path = ReadString(input); int color = ReadInt(input); int hullLength = 0; int verticesLength = ReadVarint(input, true) * 2; float[] uvs = ReadFloatArray(input, verticesLength, 1); int[] triangles = ReadShortArray(input); float[] vertices = ReadFloatArray(input, verticesLength, scale); hullLength = ReadVarint(input, true); int[] edges = null; float width = 0, height = 0; if (nonessential) { edges = ReadShortArray(input); width = ReadFloat(input); height = ReadFloat(input); } if (path == null) { path = name; } MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; mesh.r = ((color & 0xff000000) >> 24) / 255f; mesh.g = ((color & 0x00ff0000) >> 16) / 255f; mesh.b = ((color & 0x0000ff00) >> 8) / 255f; mesh.a = ((color & 0x000000ff)) / 255f; mesh.vertices = vertices; mesh.triangles = triangles; mesh.regionUVs = uvs; mesh.UpdateUVs(); mesh.HullLength = hullLength; if (nonessential) { mesh.Edges = edges; mesh.Width = width * scale; mesh.Height = height * scale; } return(mesh); } case AttachmentType.linkedmesh: { String path = ReadString(input); int color = ReadInt(input); String skinName = ReadString(input); String parent = ReadString(input); bool inheritFFD = ReadBoolean(input); float width = 0, height = 0; if (nonessential) { width = ReadFloat(input); height = ReadFloat(input); } if (path == null) { path = name; } MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; mesh.r = ((color & 0xff000000) >> 24) / 255f; mesh.g = ((color & 0x00ff0000) >> 16) / 255f; mesh.b = ((color & 0x0000ff00) >> 8) / 255f; mesh.a = ((color & 0x000000ff)) / 255f; mesh.inheritFFD = inheritFFD; if (nonessential) { mesh.Width = width * scale; mesh.Height = height * scale; } linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent)); return(mesh); } case AttachmentType.weightedmesh: { String path = ReadString(input); int color = ReadInt(input); int vertexCount = ReadVarint(input, true); float[] uvs = ReadFloatArray(input, vertexCount * 2, 1); int[] triangles = ReadShortArray(input); var weights = new List <float>(uvs.Length * 3 * 3); var bones = new List <int>(uvs.Length * 3); for (int i = 0; i < vertexCount; i++) { int boneCount = (int)ReadFloat(input); bones.Add(boneCount); for (int ii = 0; ii < boneCount; ii++) { bones.Add((int)ReadFloat(input)); weights.Add(ReadFloat(input) * scale); weights.Add(ReadFloat(input) * scale); weights.Add(ReadFloat(input)); } } int hullLength = ReadVarint(input, true); int[] edges = null; float width = 0, height = 0; if (nonessential) { edges = ReadShortArray(input); width = ReadFloat(input); height = ReadFloat(input); } if (path == null) { path = name; } WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; mesh.r = ((color & 0xff000000) >> 24) / 255f; mesh.g = ((color & 0x00ff0000) >> 16) / 255f; mesh.b = ((color & 0x0000ff00) >> 8) / 255f; mesh.a = ((color & 0x000000ff)) / 255f; mesh.bones = bones.ToArray(); mesh.weights = weights.ToArray(); mesh.triangles = triangles; mesh.regionUVs = uvs; mesh.UpdateUVs(); mesh.HullLength = hullLength * 2; if (nonessential) { mesh.Edges = edges; mesh.Width = width * scale; mesh.Height = height * scale; } // return(mesh); } case AttachmentType.weightedlinkedmesh: { String path = ReadString(input); int color = ReadInt(input); String skinName = ReadString(input); String parent = ReadString(input); bool inheritFFD = ReadBoolean(input); float width = 0, height = 0; if (nonessential) { width = ReadFloat(input); height = ReadFloat(input); } if (path == null) { path = name; } WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; mesh.r = ((color & 0xff000000) >> 24) / 255f; mesh.g = ((color & 0x00ff0000) >> 16) / 255f; mesh.b = ((color & 0x0000ff00) >> 8) / 255f; mesh.a = ((color & 0x000000ff)) / 255f; mesh.inheritFFD = inheritFFD; if (nonessential) { mesh.Width = width * scale; mesh.Height = height * scale; } linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent)); return(mesh); } } return(null); }
public SkeletonData ReadSkeletonData(Stream input) { if (input == null) { throw new ArgumentNullException("input"); } float scale = Scale; var skeletonData = new SkeletonData(); skeletonData.hash = ReadString(input); if (skeletonData.hash.Length == 0) { skeletonData.hash = null; } skeletonData.version = ReadString(input); if (skeletonData.version.Length == 0) { skeletonData.version = null; } skeletonData.width = ReadFloat(input); skeletonData.height = ReadFloat(input); bool nonessential = ReadBoolean(input); if (nonessential) { skeletonData.imagesPath = ReadString(input); if (skeletonData.imagesPath.Length == 0) { skeletonData.imagesPath = null; } } // Bones. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { String name = ReadString(input); BoneData parent = i == 0 ? null : skeletonData.bones.Items[ReadVarint(input, true)]; BoneData boneData = new BoneData(name, parent); boneData.rotation = ReadFloat(input); boneData.x = ReadFloat(input) * scale; boneData.y = ReadFloat(input) * scale; boneData.scaleX = ReadFloat(input); boneData.scaleY = ReadFloat(input); boneData.shearX = ReadFloat(input); boneData.shearY = ReadFloat(input); boneData.length = ReadFloat(input) * scale; boneData.inheritRotation = ReadBoolean(input); boneData.inheritScale = ReadBoolean(input); if (nonessential) { ReadInt(input); // Skip bone color. } skeletonData.bones.Add(boneData); } // IK constraints. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { IkConstraintData ikConstraintData = new IkConstraintData(ReadString(input)); for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) { ikConstraintData.bones.Add(skeletonData.bones.Items[ReadVarint(input, true)]); } ikConstraintData.target = skeletonData.bones.Items[ReadVarint(input, true)]; ikConstraintData.mix = ReadFloat(input); ikConstraintData.bendDirection = ReadSByte(input); skeletonData.ikConstraints.Add(ikConstraintData); } // Transform constraints. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { TransformConstraintData transformConstraintData = new TransformConstraintData(ReadString(input)); transformConstraintData.bone = skeletonData.bones.Items[ReadVarint(input, true)]; transformConstraintData.target = skeletonData.bones.Items[ReadVarint(input, true)]; transformConstraintData.offsetRotation = ReadFloat(input); transformConstraintData.offsetX = ReadFloat(input) * scale; transformConstraintData.offsetY = ReadFloat(input) * scale; transformConstraintData.offsetScaleX = ReadFloat(input); transformConstraintData.offsetScaleY = ReadFloat(input); transformConstraintData.offsetShearY = ReadFloat(input); transformConstraintData.rotateMix = ReadFloat(input); transformConstraintData.translateMix = ReadFloat(input); transformConstraintData.scaleMix = ReadFloat(input); transformConstraintData.shearMix = ReadFloat(input); skeletonData.transformConstraints.Add(transformConstraintData); } // Slots. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { String slotName = ReadString(input); BoneData boneData = skeletonData.bones.Items[ReadVarint(input, true)]; SlotData slotData = new SlotData(slotName, boneData); int color = ReadInt(input); slotData.r = ((color & 0xff000000) >> 24) / 255f; slotData.g = ((color & 0x00ff0000) >> 16) / 255f; slotData.b = ((color & 0x0000ff00) >> 8) / 255f; slotData.a = ((color & 0x000000ff)) / 255f; slotData.attachmentName = ReadString(input); slotData.blendMode = (BlendMode)ReadVarint(input, true); skeletonData.slots.Add(slotData); } // Default skin. Skin defaultSkin = ReadSkin(input, "default", nonessential); if (defaultSkin != null) { skeletonData.defaultSkin = defaultSkin; skeletonData.skins.Add(defaultSkin); } // Skins. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { skeletonData.skins.Add(ReadSkin(input, ReadString(input), nonessential)); } // Linked meshes. for (int i = 0, n = linkedMeshes.Count; i < n; i++) { SkeletonJson.LinkedMesh linkedMesh = linkedMeshes[i]; Skin skin = linkedMesh.skin == null ? skeletonData.DefaultSkin : skeletonData.FindSkin(linkedMesh.skin); if (skin == null) { throw new Exception("Skin not found: " + linkedMesh.skin); } Attachment parent = skin.GetAttachment(linkedMesh.slotIndex, linkedMesh.parent); if (parent == null) { throw new Exception("Parent mesh not found: " + linkedMesh.parent); } if (linkedMesh.mesh is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)linkedMesh.mesh; mesh.ParentMesh = (MeshAttachment)parent; mesh.UpdateUVs(); } else { WeightedMeshAttachment mesh = (WeightedMeshAttachment)linkedMesh.mesh; mesh.ParentMesh = (WeightedMeshAttachment)parent; mesh.UpdateUVs(); } } linkedMeshes.Clear(); // Events. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { EventData eventData = new EventData(ReadString(input)); eventData.Int = ReadVarint(input, false); eventData.Float = ReadFloat(input); eventData.String = ReadString(input); skeletonData.events.Add(eventData); } // Animations. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { ReadAnimation(ReadString(input), input, skeletonData); } skeletonData.bones.TrimExcess(); skeletonData.slots.TrimExcess(); skeletonData.skins.TrimExcess(); skeletonData.events.TrimExcess(); skeletonData.animations.TrimExcess(); skeletonData.ikConstraints.TrimExcess(); return(skeletonData); }
public SkeletonData ReadSkeletonData(TextReader reader) { if (reader == null) { throw new ArgumentNullException("reader cannot be null."); } var scale = this.Scale; var skeletonData = new SkeletonData(); var root = Json.Deserialize(reader) as Dictionary <String, Object>; if (root == null) { throw new Exception("Invalid JSON."); } // Skeleton. if (root.ContainsKey("skeleton")) { var skeletonMap = (Dictionary <String, Object>)root["skeleton"]; skeletonData.hash = (String)skeletonMap["hash"]; skeletonData.version = (String)skeletonMap["spine"]; skeletonData.width = GetFloat(skeletonMap, "width", 0); skeletonData.height = GetFloat(skeletonMap, "height", 0); } // 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"]); } } var boneData = new BoneData((String)boneMap["name"], parent); boneData.length = GetFloat(boneMap, "length", 0) * scale; boneData.x = GetFloat(boneMap, "x", 0) * scale; boneData.y = GetFloat(boneMap, "y", 0) * scale; boneData.rotation = GetFloat(boneMap, "rotation", 0); boneData.scaleX = GetFloat(boneMap, "scaleX", 1); boneData.scaleY = GetFloat(boneMap, "scaleY", 1); boneData.shearX = GetFloat(boneMap, "shearX", 0); boneData.shearY = GetFloat(boneMap, "shearY", 0); boneData.inheritScale = GetBoolean(boneMap, "inheritScale", true); boneData.inheritRotation = GetBoolean(boneMap, "inheritRotation", true); skeletonData.bones.Add(boneData); } // IK constraints. if (root.ContainsKey("ik")) { foreach (Dictionary <String, Object> ikMap in (List <Object>)root["ik"]) { IkConstraintData ikConstraintData = new IkConstraintData((String)ikMap["name"]); foreach (String boneName in (List <Object>)ikMap["bones"]) { BoneData bone = skeletonData.FindBone(boneName); if (bone == null) { throw new Exception("IK bone not found: " + boneName); } ikConstraintData.bones.Add(bone); } String targetName = (String)ikMap["target"]; ikConstraintData.target = skeletonData.FindBone(targetName); if (ikConstraintData.target == null) { throw new Exception("Target bone not found: " + targetName); } ikConstraintData.bendDirection = GetBoolean(ikMap, "bendPositive", true) ? 1 : -1; ikConstraintData.mix = GetFloat(ikMap, "mix", 1); skeletonData.ikConstraints.Add(ikConstraintData); } } // Transform constraints. if (root.ContainsKey("transform")) { foreach (Dictionary <String, Object> transformMap in (List <Object>)root["transform"]) { TransformConstraintData transformConstraintData = new TransformConstraintData((String)transformMap["name"]); String boneName = (String)transformMap["bone"]; transformConstraintData.bone = skeletonData.FindBone(boneName); if (transformConstraintData.bone == null) { throw new Exception("Bone not found: " + boneName); } String targetName = (String)transformMap["target"]; transformConstraintData.target = skeletonData.FindBone(targetName); if (transformConstraintData.target == null) { throw new Exception("Target bone not found: " + targetName); } transformConstraintData.offsetRotation = GetFloat(transformMap, "rotation", 0); transformConstraintData.offsetX = GetFloat(transformMap, "x", 0) * scale; transformConstraintData.offsetY = GetFloat(transformMap, "y", 0) * scale; transformConstraintData.offsetScaleX = GetFloat(transformMap, "scaleX", 0); transformConstraintData.offsetScaleY = GetFloat(transformMap, "scaleY", 0); transformConstraintData.offsetShearY = GetFloat(transformMap, "shearY", 0); transformConstraintData.rotateMix = GetFloat(transformMap, "rotateMix", 1); transformConstraintData.translateMix = GetFloat(transformMap, "translateMix", 1); transformConstraintData.scaleMix = GetFloat(transformMap, "scaleMix", 1); transformConstraintData.shearMix = GetFloat(transformMap, "shearMix", 1); skeletonData.transformConstraints.Add(transformConstraintData); } } // Slots. if (root.ContainsKey("slots")) { foreach (Dictionary <String, Object> slotMap in (List <Object>)root["slots"]) { var slotName = (String)slotMap["name"]; var boneName = (String)slotMap["bone"]; BoneData boneData = skeletonData.FindBone(boneName); if (boneData == null) { throw new Exception("Slot bone not found: " + boneName); } var slotData = new SlotData(slotName, boneData); if (slotMap.ContainsKey("color")) { var 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"]; } if (slotMap.ContainsKey("blend")) { slotData.blendMode = (BlendMode)Enum.Parse(typeof(BlendMode), (String)slotMap["blend"], false); } else { slotData.blendMode = BlendMode.normal; } skeletonData.slots.Add(slotData); } } // Skins. if (root.ContainsKey("skins")) { foreach (KeyValuePair <String, Object> entry in (Dictionary <String, Object>)root["skins"]) { var 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 = ReadAttachment(skin, slotIndex, attachmentEntry.Key, (Dictionary <String, Object>)attachmentEntry.Value); if (attachment != null) { skin.AddAttachment(slotIndex, attachmentEntry.Key, attachment); } } } skeletonData.skins.Add(skin); if (skin.name == "default") { skeletonData.defaultSkin = skin; } } } // Linked meshes. for (int i = 0, n = linkedMeshes.Count; i < n; i++) { LinkedMesh linkedMesh = linkedMeshes[i]; Skin skin = linkedMesh.skin == null ? skeletonData.defaultSkin : skeletonData.FindSkin(linkedMesh.skin); if (skin == null) { throw new Exception("Slot not found: " + linkedMesh.skin); } Attachment parent = skin.GetAttachment(linkedMesh.slotIndex, linkedMesh.parent); if (parent == null) { throw new Exception("Parent mesh not found: " + linkedMesh.parent); } if (linkedMesh.mesh is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)linkedMesh.mesh; mesh.ParentMesh = (MeshAttachment)parent; mesh.UpdateUVs(); } else { WeightedMeshAttachment mesh = (WeightedMeshAttachment)linkedMesh.mesh; mesh.ParentMesh = (WeightedMeshAttachment)parent; mesh.UpdateUVs(); } } linkedMeshes.Clear(); // Events. if (root.ContainsKey("events")) { foreach (KeyValuePair <String, Object> entry in (Dictionary <String, Object>)root["events"]) { var entryMap = (Dictionary <String, Object>)entry.Value; var eventData = new EventData(entry.Key); eventData.Int = GetInt(entryMap, "int", 0); eventData.Float = GetFloat(entryMap, "float", 0); eventData.String = GetString(entryMap, "string", null); skeletonData.events.Add(eventData); } } // Animations. if (root.ContainsKey("animations")) { foreach (KeyValuePair <String, Object> entry in (Dictionary <String, Object>)root["animations"]) { ReadAnimation(entry.Key, (Dictionary <String, Object>)entry.Value, skeletonData); } } skeletonData.bones.TrimExcess(); skeletonData.slots.TrimExcess(); skeletonData.skins.TrimExcess(); skeletonData.events.TrimExcess(); skeletonData.animations.TrimExcess(); skeletonData.ikConstraints.TrimExcess(); return(skeletonData); }
private Attachment ReadAttachment(Skin skin, int slotIndex, String name, Dictionary <String, Object> map) { if (map.ContainsKey("name")) { name = (String)map["name"]; } var scale = this.Scale; var type = AttachmentType.region; if (map.ContainsKey("type")) { var typeName = (String)map["type"]; if (typeName == "skinnedmesh") { typeName = "weightedmesh"; } type = (AttachmentType)Enum.Parse(typeof(AttachmentType), typeName, false); } String path = name; if (map.ContainsKey("path")) { path = (String)map["path"]; } switch (type) { case AttachmentType.region: RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path); if (region == null) { return(null); } region.Path = path; region.x = GetFloat(map, "x", 0) * scale; region.y = GetFloat(map, "y", 0) * scale; region.scaleX = GetFloat(map, "scaleX", 1); region.scaleY = GetFloat(map, "scaleY", 1); region.rotation = GetFloat(map, "rotation", 0); region.width = GetFloat(map, "width", 32) * scale; region.height = GetFloat(map, "height", 32) * scale; region.UpdateOffset(); if (map.ContainsKey("color")) { var color = (String)map["color"]; region.r = ToColor(color, 0); region.g = ToColor(color, 1); region.b = ToColor(color, 2); region.a = ToColor(color, 3); } return(region); case AttachmentType.mesh: case AttachmentType.linkedmesh: { MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; if (map.ContainsKey("color")) { var color = (String)map["color"]; mesh.r = ToColor(color, 0); mesh.g = ToColor(color, 1); mesh.b = ToColor(color, 2); mesh.a = ToColor(color, 3); } mesh.Width = GetInt(map, "width", 0) * scale; mesh.Height = GetInt(map, "height", 0) * scale; String parent = GetString(map, "parent", null); if (parent == null) { mesh.vertices = GetFloatArray(map, "vertices", scale); mesh.triangles = GetIntArray(map, "triangles"); mesh.regionUVs = GetFloatArray(map, "uvs", 1); mesh.UpdateUVs(); mesh.HullLength = GetInt(map, "hull", 0) * 2; if (map.ContainsKey("edges")) { mesh.Edges = GetIntArray(map, "edges"); } } else { mesh.InheritFFD = GetBoolean(map, "ffd", true); linkedMeshes.Add(new LinkedMesh(mesh, GetString(map, "skin", null), slotIndex, parent)); } return(mesh); } case AttachmentType.weightedmesh: case AttachmentType.weightedlinkedmesh: { WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; if (map.ContainsKey("color")) { var color = (String)map["color"]; mesh.r = ToColor(color, 0); mesh.g = ToColor(color, 1); mesh.b = ToColor(color, 2); mesh.a = ToColor(color, 3); } mesh.Width = GetInt(map, "width", 0) * scale; mesh.Height = GetInt(map, "height", 0) * scale; String parent = GetString(map, "parent", null); if (parent == null) { float[] uvs = GetFloatArray(map, "uvs", 1); float[] vertices = GetFloatArray(map, "vertices", 1); var weights = new List <float>(uvs.Length * 3 * 3); var bones = new List <int>(uvs.Length * 3); for (int i = 0, n = vertices.Length; i < n;) { int boneCount = (int)vertices[i++]; bones.Add(boneCount); for (int nn = i + boneCount * 4; i < nn; i += 4) { bones.Add((int)vertices[i]); weights.Add(vertices[i + 1] * scale); weights.Add(vertices[i + 2] * scale); weights.Add(vertices[i + 3]); } } mesh.bones = bones.ToArray(); mesh.weights = weights.ToArray(); mesh.triangles = GetIntArray(map, "triangles"); mesh.regionUVs = uvs; mesh.UpdateUVs(); mesh.HullLength = GetInt(map, "hull", 0) * 2; if (map.ContainsKey("edges")) { mesh.Edges = GetIntArray(map, "edges"); } } else { mesh.InheritFFD = GetBoolean(map, "ffd", true); linkedMeshes.Add(new LinkedMesh(mesh, GetString(map, "skin", null), slotIndex, parent)); } return(mesh); } case AttachmentType.boundingbox: BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name); if (box == null) { return(null); } box.vertices = GetFloatArray(map, "vertices", scale); return(box); } return(null); }
private Attachment ReadAttachment(Stream input, Skin skin, String attachmentName, bool nonessential) { float scale = Scale; String name = ReadString(input); if (name == null) { name = attachmentName; } switch ((AttachmentType)input.ReadByte()) { case AttachmentType.region: { String path = ReadString(input); if (path == null) { path = name; } RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path); if (region == null) { return(null); } region.Path = path; region.x = ReadFloat(input) * scale; region.y = ReadFloat(input) * scale; region.scaleX = ReadFloat(input); region.scaleY = ReadFloat(input); region.rotation = ReadFloat(input); region.width = ReadFloat(input) * scale; region.height = ReadFloat(input) * scale; int color = ReadInt(input); region.r = ((color & 0xff000000) >> 24) / 255f; region.g = ((color & 0x00ff0000) >> 16) / 255f; region.b = ((color & 0x0000ff00) >> 8) / 255f; region.a = ((color & 0x000000ff)) / 255f; region.UpdateOffset(); return(region); } case AttachmentType.boundingbox: { BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name); if (box == null) { return(null); } box.vertices = ReadFloatArray(input, scale); return(box); } case AttachmentType.mesh: { String path = ReadString(input); if (path == null) { path = name; } MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; mesh.regionUVs = ReadFloatArray(input, 1); mesh.triangles = ReadShortArray(input); mesh.vertices = ReadFloatArray(input, scale); mesh.UpdateUVs(); int color = ReadInt(input); mesh.r = ((color & 0xff000000) >> 24) / 255f; mesh.g = ((color & 0x00ff0000) >> 16) / 255f; mesh.b = ((color & 0x0000ff00) >> 8) / 255f; mesh.a = ((color & 0x000000ff)) / 255f; mesh.HullLength = ReadInt(input, true) * 2; if (nonessential) { mesh.Edges = ReadIntArray(input); mesh.Width = ReadFloat(input) * scale; mesh.Height = ReadFloat(input) * scale; } return(mesh); } case AttachmentType.weightedmesh: { String path = ReadString(input); if (path == null) { path = name; } WeightedMeshAttachment mesh = attachmentLoader.NewWeightedMeshAttachment(skin, name, path); if (mesh == null) { return(null); } mesh.Path = path; float[] uvs = ReadFloatArray(input, 1); int[] triangles = ReadShortArray(input); int vertexCount = ReadInt(input, true); var weights = new List <float>(uvs.Length * 3 * 3); var bones = new List <int>(uvs.Length * 3); for (int i = 0; i < vertexCount; i++) { int boneCount = (int)ReadFloat(input); bones.Add(boneCount); for (int nn = i + boneCount * 4; i < nn; i += 4) { bones.Add((int)ReadFloat(input)); weights.Add(ReadFloat(input) * scale); weights.Add(ReadFloat(input) * scale); weights.Add(ReadFloat(input)); } } mesh.bones = bones.ToArray(); mesh.weights = weights.ToArray(); mesh.triangles = triangles; mesh.regionUVs = uvs; mesh.UpdateUVs(); int color = ReadInt(input); mesh.r = ((color & 0xff000000) >> 24) / 255f; mesh.g = ((color & 0x00ff0000) >> 16) / 255f; mesh.b = ((color & 0x0000ff00) >> 8) / 255f; mesh.a = ((color & 0x000000ff)) / 255f; mesh.HullLength = ReadInt(input, true) * 2; if (nonessential) { mesh.Edges = ReadIntArray(input); mesh.Width = ReadFloat(input) * scale; mesh.Height = ReadFloat(input) * scale; } return(mesh); } } return(null); }