SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, const int length) { bool nonessential; SkeletonData *skeletonData; DataInput *input = new(__FILE__, __LINE__) DataInput(); input->cursor = binary; input->end = binary + length; _linkedMeshes.clear(); skeletonData = new(__FILE__, __LINE__) SkeletonData(); char *skeletonData_hash = readString(input); skeletonData->_hash.own(skeletonData_hash); char *skeletonData_version = readString(input); skeletonData->_version.own(skeletonData_version); skeletonData->_width = readFloat(input); skeletonData->_height = readFloat(input); nonessential = readBoolean(input); if (nonessential) { /* Skip images path, audio path & fps */ skeletonData->_fps = readFloat(input); skeletonData->_imagesPath.own(readString(input)); skeletonData->_audioPath.own(readString(input)); } /* Bones. */ int numBones = readVarint(input, true); skeletonData->_bones.setSize(numBones, 0); for (int i = 0; i < numBones; ++i) { const char *name = readString(input); BoneData *parent = i == 0 ? 0 : skeletonData->_bones[readVarint(input, true)]; BoneData *data = new(__FILE__, __LINE__) BoneData(i, String(name, true), parent); data->_rotation = readFloat(input); data->_x = readFloat(input) * _scale; data->_y = readFloat(input) * _scale; data->_scaleX = readFloat(input); data->_scaleY = readFloat(input); data->_shearX = readFloat(input); data->_shearY = readFloat(input); data->_length = readFloat(input) * _scale; data->_transformMode = static_cast<TransformMode>(readVarint(input, true)); if (nonessential) { /* Skip bone color. */ readInt(input); } skeletonData->_bones[i] = data; } /* Slots. */ int slotsCount = readVarint(input, true); skeletonData->_slots.setSize(slotsCount, 0); for (int i = 0; i < slotsCount; ++i) { const char *slotName = readString(input); BoneData *boneData = skeletonData->_bones[readVarint(input, true)]; SlotData *slotData = new(__FILE__, __LINE__) SlotData(i, String(slotName, true), *boneData); readColor(input, slotData->getColor()); unsigned char r = readByte(input); unsigned char g = readByte(input); unsigned char b = readByte(input); unsigned char a = readByte(input); if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { slotData->getDarkColor().set(r / 255.0f, g / 255.0f, b / 255.0f, 1); slotData->setHasDarkColor(true); } slotData->_attachmentName.own(readString(input)); slotData->_blendMode = static_cast<BlendMode>(readVarint(input, true)); skeletonData->_slots[i] = slotData; } /* IK constraints. */ int ikConstraintsCount = readVarint(input, true); skeletonData->_ikConstraints.setSize(ikConstraintsCount, 0); for (int i = 0; i < ikConstraintsCount; ++i) { const char *name = readString(input); IkConstraintData *data = new(__FILE__, __LINE__) IkConstraintData(String(name, true)); data->_order = readVarint(input, true); int bonesCount = readVarint(input, true); data->_bones.setSize(bonesCount, 0); for (int ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; } data->_target = skeletonData->_bones[readVarint(input, true)]; data->_mix = readFloat(input); data->_bendDirection = readSByte(input); data->_compress = readBoolean(input); data->_stretch = readBoolean(input); data->_uniform = readBoolean(input); skeletonData->_ikConstraints[i] = data; } /* Transform constraints. */ int transformConstraintsCount = readVarint(input, true); skeletonData->_transformConstraints.setSize(transformConstraintsCount, 0); for (int i = 0; i < transformConstraintsCount; ++i) { const char *name = readString(input); TransformConstraintData *data = new(__FILE__, __LINE__) TransformConstraintData(String(name, true)); data->_order = readVarint(input, true); int bonesCount = readVarint(input, true); data->_bones.setSize(bonesCount, 0); for (int ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; } data->_target = skeletonData->_bones[readVarint(input, true)]; data->_local = readBoolean(input); data->_relative = readBoolean(input); data->_offsetRotation = readFloat(input); data->_offsetX = readFloat(input) * _scale; data->_offsetY = readFloat(input) * _scale; data->_offsetScaleX = readFloat(input); data->_offsetScaleY = readFloat(input); data->_offsetShearY = readFloat(input); data->_rotateMix = readFloat(input); data->_translateMix = readFloat(input); data->_scaleMix = readFloat(input); data->_shearMix = readFloat(input); skeletonData->_transformConstraints[i] = data; } /* Path constraints */ int pathConstraintsCount = readVarint(input, true); skeletonData->_pathConstraints.setSize(pathConstraintsCount, 0); for (int i = 0; i < pathConstraintsCount; ++i) { const char *name = readString(input); PathConstraintData *data = new(__FILE__, __LINE__) PathConstraintData(String(name, true)); data->_order = readVarint(input, true); int bonesCount = readVarint(input, true); data->_bones.setSize(bonesCount, 0); for (int ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, true)]; } data->_target = skeletonData->_slots[readVarint(input, true)]; data->_positionMode = static_cast<PositionMode>(readVarint(input, true)); data->_spacingMode = static_cast<SpacingMode>(readVarint(input, true)); data->_rotateMode = static_cast<RotateMode>(readVarint(input, true)); data->_offsetRotation = readFloat(input); data->_position = readFloat(input); if (data->_positionMode == PositionMode_Fixed) data->_position *= _scale; data->_spacing = readFloat(input); if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) data->_spacing *= _scale; data->_rotateMix = readFloat(input); data->_translateMix = readFloat(input); skeletonData->_pathConstraints[i] = data; } /* Default skin. */ skeletonData->_defaultSkin = readSkin(input, "default", skeletonData, nonessential); int skinsCount = readVarint(input, true); if (skeletonData->_defaultSkin) { ++skinsCount; } skeletonData->_skins.setSize(skinsCount, 0); if (skeletonData->_defaultSkin) { skeletonData->_skins[0] = skeletonData->_defaultSkin; } /* Skins. */ for (size_t i = skeletonData->_defaultSkin ? 1 : 0; i < skeletonData->_skins.size(); ++i) { String skinName(readString(input), true); skeletonData->_skins[i] = readSkin(input, skinName, skeletonData, nonessential); } /* Linked meshes. */ for (int i = 0, n = _linkedMeshes.size(); i < n; ++i) { LinkedMesh *linkedMesh = _linkedMeshes[i]; Skin *skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin( linkedMesh->_skin); if (skin == NULL) { delete input; delete skeletonData; setError("Skin not found: ", linkedMesh->_skin.buffer()); return NULL; } Attachment *parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); if (parent == NULL) { delete input; delete skeletonData; setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); return NULL; } linkedMesh->_mesh->setParentMesh(static_cast<MeshAttachment *>(parent)); linkedMesh->_mesh->updateUVs(); _attachmentLoader->configureAttachment(linkedMesh->_mesh); } ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); _linkedMeshes.clear(); /* Events. */ int eventsCount = readVarint(input, true); skeletonData->_events.setSize(eventsCount, 0); for (int i = 0; i < eventsCount; ++i) { const char *name = readString(input); EventData *eventData = new(__FILE__, __LINE__) EventData(String(name, true)); eventData->_intValue = readVarint(input, false); eventData->_floatValue = readFloat(input); eventData->_stringValue.own(readString(input)); eventData->_audioPath.own(readString(input)); // skip audio path if (!eventData->_audioPath.isEmpty()) { eventData->_volume = readFloat(input); eventData->_balance = readFloat(input); } skeletonData->_events[i] = eventData; } /* Animations. */ int animationsCount = readVarint(input, true); skeletonData->_animations.setSize(animationsCount, 0); for (int i = 0; i < animationsCount; ++i) { String name(readString(input), true); Animation *animation = readAnimation(name, input, skeletonData); if (!animation) { delete input; delete skeletonData; return NULL; } skeletonData->_animations[i] = animation; } delete input; return skeletonData; }