private float[] readFloatArray(DataInput input, float scale) throws IOException { int n = input.readInt(true); float[] array = new float[n]; if (scale == 1) { for (int i = 0; i < n; i++) array[i] = input.readFloat(); } else { for (int i = 0; i < n; i++) array[i] = input.readFloat() * scale; } return array; }
private Skin readSkin(DataInput input, String skinName, boolean nonessential) throws IOException { int slotCount = input.readInt(true); if (slotCount == 0) return null; Skin skin = new Skin(skinName); for (int i = 0; i < slotCount; i++) { int slotIndex = input.readInt(true); for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { String name = input.readString(); skin.addAttachment(slotIndex, name, readAttachment(input, skin, name, nonessential)); } } return skin; }
private void readCurve(DataInput input, int frameIndex, CurveTimeline timeline) throws IOException { switch (input.readByte()) { case CURVE_STEPPED: timeline.setStepped(frameIndex); break; case CURVE_BEZIER: setCurve( timeline, frameIndex, input.readFloat(), input.readFloat(), input.readFloat(), input.readFloat()); break; } }
public SkeletonData readSkeletonData(FileHandle file) { if (file == null) throw new IllegalArgumentException("file cannot be null."); float scale = this.scale; SkeletonData skeletonData = new SkeletonData(); skeletonData.name = file.nameWithoutExtension(); DataInput input = new DataInput(file.read(512)); try { boolean nonessential = input.readBoolean(); // Bones. for (int i = 0, n = input.readInt(true); i < n; i++) { String name = input.readString(); BoneData parent = null; int parentIndex = input.readInt(true) - 1; if (parentIndex != -1) parent = skeletonData.bones.get(parentIndex); BoneData boneData = new BoneData(name, parent); boneData.x = input.readFloat() * scale; boneData.y = input.readFloat() * scale; boneData.scaleX = input.readFloat(); boneData.scaleY = input.readFloat(); boneData.rotation = input.readFloat(); boneData.length = input.readFloat() * scale; boneData.inheritScale = input.readBoolean(); boneData.inheritRotation = input.readBoolean(); if (nonessential) Color.rgba8888ToColor(boneData.getColor(), input.readInt()); skeletonData.addBone(boneData); } // Slots. for (int i = 0, n = input.readInt(true); i < n; i++) { String slotName = input.readString(); BoneData boneData = skeletonData.bones.get(input.readInt(true)); SlotData slotData = new SlotData(slotName, boneData); Color.rgba8888ToColor(slotData.getColor(), input.readInt()); slotData.attachmentName = input.readString(); slotData.additiveBlending = input.readBoolean(); skeletonData.addSlot(slotData); } // Default skin. Skin defaultSkin = readSkin(input, "default", nonessential); if (defaultSkin != null) { skeletonData.defaultSkin = defaultSkin; skeletonData.addSkin(defaultSkin); } // Skins. for (int i = 0, n = input.readInt(true); i < n; i++) skeletonData.addSkin(readSkin(input, input.readString(), nonessential)); // Events. for (int i = 0, n = input.readInt(true); i < n; i++) { EventData eventData = new EventData(input.readString()); eventData.intValue = input.readInt(false); eventData.floatValue = input.readFloat(); eventData.stringValue = input.readString(); skeletonData.addEvent(eventData); } // Animations. for (int i = 0, n = input.readInt(true); i < n; i++) readAnimation(input.readString(), input, skeletonData); } catch (IOException ex) { throw new SerializationException("Error reading skeleton file.", ex); } finally { try { input.close(); } catch (IOException ignored) { } } skeletonData.bones.shrink(); skeletonData.slots.shrink(); skeletonData.skins.shrink(); return skeletonData; }
private void readAnimation(String name, DataInput input, SkeletonData skeletonData) { Array<Timeline> timelines = new Array(); float scale = this.scale; float duration = 0; try { // Slot timelines. for (int i = 0, n = input.readInt(true); i < n; i++) { int slotIndex = input.readInt(true); for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { int timelineType = input.readByte(); int frameCount = input.readInt(true); switch (timelineType) { case TIMELINE_COLOR: { ColorTimeline timeline = new ColorTimeline(frameCount); timeline.slotIndex = slotIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = input.readFloat(); Color.rgba8888ToColor(tempColor, input.readInt()); timeline.setFrame( frameIndex, time, tempColor.r, tempColor.g, tempColor.b, tempColor.a); if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); } timelines.add(timeline); duration = Math.max(duration, timeline.getFrames()[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, input.readFloat(), input.readString()); timelines.add(timeline); duration = Math.max(duration, timeline.getFrames()[frameCount - 1]); break; } } } // Bone timelines. for (int i = 0, n = input.readInt(true); i < n; i++) { int boneIndex = input.readInt(true); for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { int timelineType = input.readByte(); int frameCount = input.readInt(true); switch (timelineType) { case TIMELINE_ROTATE: { RotateTimeline timeline = new RotateTimeline(frameCount); timeline.boneIndex = boneIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.setFrame(frameIndex, input.readFloat(), input.readFloat()); if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); } timelines.add(timeline); duration = Math.max(duration, timeline.getFrames()[frameCount * 2 - 2]); break; } case TIMELINE_TRANSLATE: case TIMELINE_SCALE: TranslateTimeline timeline; float timelineScale = 1; if (timelineType == TIMELINE_SCALE) timeline = new ScaleTimeline(frameCount); else { timeline = new TranslateTimeline(frameCount); timelineScale = scale; } timeline.boneIndex = boneIndex; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { timeline.setFrame( frameIndex, input.readFloat(), input.readFloat() * timelineScale, input.readFloat() * timelineScale); if (frameIndex < frameCount - 1) readCurve(input, frameIndex, timeline); } timelines.add(timeline); duration = Math.max(duration, timeline.getFrames()[frameCount * 3 - 3]); break; } } } // FFD timelines. for (int i = 0, n = input.readInt(true); i < n; i++) { Skin skin = skeletonData.getSkins().get(input.readInt(true) + 1); for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { int slotIndex = input.readInt(true); for (int iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { Attachment attachment = skin.getAttachment(slotIndex, input.readString()); int frameCount = input.readInt(true); FfdTimeline timeline = new FfdTimeline(frameCount); timeline.slotIndex = slotIndex; timeline.attachment = attachment; for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { float time = input.readFloat(); float[] vertices; int vertexCount; if (attachment instanceof MeshAttachment) vertexCount = ((MeshAttachment) attachment).getVertices().length; else vertexCount = ((SkinnedMeshAttachment) attachment).getWeights().length / 3 * 2; int end = input.readInt(true); if (end == 0) { if (attachment instanceof MeshAttachment) vertices = ((MeshAttachment) attachment).getVertices(); else vertices = new float[vertexCount]; } else { vertices = new float[vertexCount]; int start = input.readInt(true); end += start; if (scale == 1) { for (int v = start; v < end; v++) vertices[v] = input.readFloat(); } else { for (int v = start; v < end; v++) vertices[v] = input.readFloat() * scale; } if (attachment instanceof MeshAttachment) { float[] meshVertices = ((MeshAttachment) attachment).getVertices(); 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.getFrames()[frameCount - 1]); } } } // Draw order timeline. int drawOrderCount = input.readInt(true); if (drawOrderCount > 0) { DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount); int slotCount = skeletonData.slots.size; for (int i = 0; i < drawOrderCount; i++) { int offsetCount = input.readInt(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 = input.readInt(true); // Collect unchanged items. while (originalIndex != slotIndex) unchanged[unchangedIndex++] = originalIndex++; // Set changed items. drawOrder[originalIndex + input.readInt(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, input.readFloat(), drawOrder); } timelines.add(timeline); duration = Math.max(duration, timeline.getFrames()[drawOrderCount - 1]); } // Event timeline. int eventCount = input.readInt(true); if (eventCount > 0) { EventTimeline timeline = new EventTimeline(eventCount); for (int i = 0; i < eventCount; i++) { float time = input.readFloat(); EventData eventData = skeletonData.events.get(input.readInt(true)); Event event = new Event(eventData); event.intValue = input.readInt(false); event.floatValue = input.readFloat(); event.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue; timeline.setFrame(i, time, event); } timelines.add(timeline); duration = Math.max(duration, timeline.getFrames()[eventCount - 1]); } } catch (IOException ex) { throw new SerializationException("Error reading skeleton file.", ex); } timelines.shrink(); skeletonData.addAnimation(new Animation(name, timelines, duration)); }
private int[] readIntArray(DataInput input) throws IOException { int n = input.readInt(true); int[] array = new int[n]; for (int i = 0; i < n; i++) array[i] = input.readInt(true); return array; }
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; }