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;
  }