private Attachment readAttachment(Skin skin, String name, JsonValue map) {
    name = map.getString("name", name);

    AttachmentType type =
        AttachmentType.valueOf(map.getString("type", AttachmentType.region.name()));
    Attachment attachment = attachmentLoader.newAttachment(skin, type, name);

    if (attachment instanceof RegionSequenceAttachment) {
      RegionSequenceAttachment regionSequenceAttachment = (RegionSequenceAttachment) attachment;

      float fps = map.getFloat("fps");
      regionSequenceAttachment.setFrameTime(fps);

      String modeString = map.getString("mode");
      regionSequenceAttachment.setMode(
          modeString == null ? Mode.forward : Mode.valueOf(modeString));
    }

    if (attachment instanceof RegionAttachment) {
      RegionAttachment regionAttachment = (RegionAttachment) attachment;
      regionAttachment.setX(map.getFloat("x", 0) * scale);
      regionAttachment.setY(map.getFloat("y", 0) * scale);
      regionAttachment.setScaleX(map.getFloat("scaleX", 1));
      regionAttachment.setScaleY(map.getFloat("scaleY", 1));
      regionAttachment.setRotation(map.getFloat("rotation", 0));
      regionAttachment.setWidth(map.getFloat("width", 32) * scale);
      regionAttachment.setHeight(map.getFloat("height", 32) * scale);
      regionAttachment.updateOffset();
    }

    return attachment;
  }
  private Attachment readAttachment(
      DataInput input, Skin skin, String attachmentName, boolean nonessential) throws IOException {
    float scale = this.scale;

    String name = input.readString();
    if (name == null) name = attachmentName;

    switch (AttachmentType.values()[input.readByte()]) {
      case region:
        {
          String path = input.readString();
          if (path == null) path = name;
          RegionAttachment region = attachmentLoader.newRegionAttachment(skin, name, path);
          if (region == null) return null;
          region.setPath(path);
          region.setX(input.readFloat() * scale);
          region.setY(input.readFloat() * scale);
          region.setScaleX(input.readFloat());
          region.setScaleY(input.readFloat());
          region.setRotation(input.readFloat());
          region.setWidth(input.readFloat() * scale);
          region.setHeight(input.readFloat() * scale);
          Color.rgba8888ToColor(region.getColor(), input.readInt());
          region.updateOffset();
          return region;
        }
      case boundingbox:
        {
          BoundingBoxAttachment box = attachmentLoader.newBoundingBoxAttachment(skin, name);
          if (box == null) return null;
          box.setVertices(readFloatArray(input, scale));
          return box;
        }
      case mesh:
        {
          String path = input.readString();
          if (path == null) path = name;
          MeshAttachment mesh = attachmentLoader.newMeshAttachment(skin, name, path);
          if (mesh == null) return null;
          mesh.setPath(path);
          float[] uvs = readFloatArray(input, 1);
          short[] triangles = readShortArray(input);
          float[] vertices = readFloatArray(input, scale);
          mesh.setVertices(vertices);
          mesh.setTriangles(triangles);
          mesh.setRegionUVs(uvs);
          mesh.updateUVs();
          Color.rgba8888ToColor(mesh.getColor(), input.readInt());
          mesh.setHullLength(input.readInt(true) * 2);
          if (nonessential) {
            mesh.setEdges(readIntArray(input));
            mesh.setWidth(input.readFloat() * scale);
            mesh.setHeight(input.readFloat() * scale);
          }
          return mesh;
        }
      case skinnedmesh:
        {
          String path = input.readString();
          if (path == null) path = name;
          SkinnedMeshAttachment mesh = attachmentLoader.newSkinnedMeshAttachment(skin, name, path);
          if (mesh == null) return null;
          mesh.setPath(path);
          float[] uvs = readFloatArray(input, 1);
          short[] triangles = readShortArray(input);

          int vertexCount = input.readInt(true);
          FloatArray weights = new FloatArray(uvs.length * 3 * 3);
          IntArray bones = new IntArray(uvs.length * 3);
          for (int i = 0; i < vertexCount; i++) {
            int boneCount = (int) input.readFloat();
            bones.add(boneCount);
            for (int nn = i + boneCount * 4; i < nn; i += 4) {
              bones.add((int) input.readFloat());
              weights.add(input.readFloat() * scale);
              weights.add(input.readFloat() * scale);
              weights.add(input.readFloat());
            }
          }
          mesh.setBones(bones.toArray());
          mesh.setWeights(weights.toArray());
          mesh.setTriangles(triangles);
          mesh.setRegionUVs(uvs);
          mesh.updateUVs();
          Color.rgba8888ToColor(mesh.getColor(), input.readInt());
          mesh.setHullLength(input.readInt(true) * 2);
          if (nonessential) {
            mesh.setEdges(readIntArray(input));
            mesh.setWidth(input.readFloat() * scale);
            mesh.setHeight(input.readFloat() * scale);
          }
          return mesh;
        }
    }
    return null;
  }