From 9fda6dcd3b4448ce0163d7690c067b9fdf30a1b5 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 16 Dec 2021 17:14:52 +0100 Subject: [PATCH] [cpp] Sequence and SequenceTimeline support in SkeletonBinary. --- .../spine-cpp/include/spine/LinkedMesh.h | 4 +- spine-cpp/spine-cpp/include/spine/Sequence.h | 8 +- .../spine-cpp/include/spine/SkeletonBinary.h | 9 +- spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp | 10 +- spine-cpp/spine-cpp/src/spine/Sequence.cpp | 11 +- .../spine-cpp/src/spine/SkeletonBinary.cpp | 252 +++++++++++------- 6 files changed, 186 insertions(+), 108 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h index 8b6271d07..3af86be72 100644 --- a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h +++ b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -43,14 +43,14 @@ namespace spine { public: LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, - bool inheritDeform); + bool inheritTimeline); private: MeshAttachment *_mesh; String _skin; size_t _slotIndex; String _parent; - bool _inheritDeform; + bool _inheritTimeline; }; } diff --git a/spine-cpp/spine-cpp/include/spine/Sequence.h b/spine-cpp/spine-cpp/include/spine/Sequence.h index e697eb891..19d3a5a3b 100644 --- a/spine-cpp/spine-cpp/include/spine/Sequence.h +++ b/spine-cpp/spine-cpp/include/spine/Sequence.h @@ -39,12 +39,16 @@ namespace spine { class Attachment; - class SP_API Sequence : public SpineObject { + class SkeletonBinary; + class SkeletonJson; + class SP_API Sequence : public SpineObject { + friend class SkeletonBinary; + friend class SkeletonJson; public: explicit Sequence(); - Sequence(int id, const Vector ®ions, int start, int digits, int setupIndex); + Sequence(int count); ~Sequence(); diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index 3ffe1d21b..e5078f1be 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -61,6 +61,8 @@ namespace spine { class CurveTimeline2; + class Sequence; + class SP_API SkeletonBinary : public SpineObject { public: static const int BONE_ROTATE = 0; @@ -81,6 +83,9 @@ namespace spine { static const int SLOT_RGB2 = 4; static const int SLOT_ALPHA = 5; + static const int ATTACHMENT_DEFORM = 0; + static const int ATTACHMENT_SEQUENCE = 1; + static const int PATH_POSITION = 0; static const int PATH_SPACING = 1; static const int PATH_MIX = 2; @@ -137,10 +142,12 @@ namespace spine { Skin *readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential); + Sequence *readSequence(DataInput *input); + Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, SkeletonData *skeletonData, bool nonessential); - void readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount); + void readVertices(DataInput *input, Vector &vertices, Vector &bones, int vertexCount); void readFloatArray(DataInput *input, int n, float scale, Vector &array); diff --git a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp index d240f79a3..ed70ec900 100644 --- a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp +++ b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -38,9 +38,9 @@ using namespace spine; LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, - bool inheritDeform) : _mesh(mesh), - _skin(skin), - _slotIndex(slotIndex), - _parent(parent), - _inheritDeform(inheritDeform) { + bool inheritTimeline) : _mesh(mesh), + _skin(skin), + _slotIndex(slotIndex), + _parent(parent), + _inheritTimeline(inheritTimeline) { } diff --git a/spine-cpp/spine-cpp/src/spine/Sequence.cpp b/spine-cpp/spine-cpp/src/spine/Sequence.cpp index ec5b79c50..14dee55cc 100644 --- a/spine-cpp/spine-cpp/src/spine/Sequence.cpp +++ b/spine-cpp/spine-cpp/src/spine/Sequence.cpp @@ -35,11 +35,12 @@ using namespace spine; -Sequence::Sequence() : _id(Sequence::getNextID()), - _regions(), - _start(0), - _digits(0), - _setupIndex(0) { +Sequence::Sequence(int count) : _id(Sequence::getNextID()), + _regions(), + _start(0), + _digits(0), + _setupIndex(0) { + _regions.setSize(count, NULL); } Sequence::~Sequence() { diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index 47d70fd4a..4349fc782 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -72,6 +72,7 @@ #include #include #include +#include "spine/SequenceTimeline.h" using namespace spine; @@ -298,10 +299,10 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); return NULL; } - linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritDeform ? static_cast(parent) - : linkedMesh->_mesh; + linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast(parent) + : linkedMesh->_mesh; linkedMesh->_mesh->setParentMesh(static_cast(parent)); - linkedMesh->_mesh->updateRegion(); + if (linkedMesh->_mesh->_region) linkedMesh->_mesh->updateRegion(); _attachmentLoader->configureAttachment(linkedMesh->_mesh); } ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); @@ -478,6 +479,15 @@ Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData return skin; } +Sequence *SkeletonBinary::readSequence(DataInput *input) { + if (!readBoolean(input)) return NULL; + Sequence *sequence = new (__FILE__, __LINE__) Sequence(readVarint(input, true)); + sequence->_start = readVarint(input, true); + sequence->_digits = readVarint(input, true); + sequence->_setupIndex = readVarint(input, true); + return sequence; +} + Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName, SkeletonData *skeletonData, bool nonessential) { String name(readStringRef(input, skeletonData)); @@ -488,21 +498,32 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo case AttachmentType_Region: { String path(readStringRef(input, skeletonData)); if (path.isEmpty()) path = name; - RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path)); + float rotation = readFloat(input); + float x = readFloat(input) * _scale; + float y = readFloat(input) * _scale; + float scaleX = readFloat(input); + float scaleY = readFloat(input); + float width = readFloat(input) * _scale; + float height = readFloat(input) * _scale; + Color color; + readColor(input, color); + Sequence *sequence = readSequence(input); + RegionAttachment *region = _attachmentLoader->newRegionAttachment(*skin, String(name), String(path), sequence); if (!region) { setError("Error reading attachment: ", name.buffer()); return nullptr; } region->_path = path; - region->_rotation = readFloat(input); - region->_x = readFloat(input) * _scale; - region->_y = readFloat(input) * _scale; - region->_scaleX = readFloat(input); - region->_scaleY = readFloat(input); - region->_width = readFloat(input) * _scale; - region->_height = readFloat(input) * _scale; - readColor(input, region->getColor()); - region->updateRegion(); + region->_rotation = rotation; + region->_x = x; + region->_y = y; + region->_scaleX = scaleX; + region->_scaleY = scaleY; + region->_width = width; + region->_height = height; + region->getColor().set(color); + region->_sequence = sequence; + if (sequence == NULL) region->updateRegion(); _attachmentLoader->configureAttachment(region); return region; } @@ -513,7 +534,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo setError("Error reading attachment: ", name.buffer()); return nullptr; } - readVertices(input, static_cast(box), vertexCount); + readVertices(input, box->getVertices(), box->getBones(), vertexCount); + box->setWorldVerticesLength(vertexCount << 1); if (nonessential) { readColor(input, box->getColor()); } @@ -521,31 +543,51 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo return box; } case AttachmentType_Mesh: { + Color color; int vertexCount; - MeshAttachment *mesh; + Vector uvs; + Vector triangles; + Vector vertices; + Vector bones; + int hullLength; + Sequence *sequence; + float width = 0; + float height = 0; + Vector edges; + String path(readStringRef(input, skeletonData)); if (path.isEmpty()) path = name; + readColor(input, color); + vertexCount = readVarint(input, true); + readFloatArray(input, vertexCount << 1, 1, uvs); + readShortArray(input, triangles); + readVertices(input, vertices, bones, vertexCount); + hullLength = readVarint(input, true) << 1; + sequence = readSequence(input); + if (nonessential) { + readShortArray(input, edges); + width = readFloat(input) * _scale; + height = readFloat(input) * _scale; + } - mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence); if (!mesh) { setError("Error reading attachment: ", name.buffer()); return nullptr; } mesh->_path = path; - readColor(input, mesh->getColor()); - vertexCount = readVarint(input, true); - readFloatArray(input, vertexCount << 1, 1, mesh->getRegionUVs()); - readShortArray(input, mesh->getTriangles()); - readVertices(input, static_cast(mesh), vertexCount); - mesh->updateRegion(); - mesh->_hullLength = readVarint(input, true) << 1; + mesh->_color.set(color); + mesh->_vertices.addAll(vertices); + mesh->setWorldVerticesLength(vertexCount << 1); + mesh->_triangles.addAll(triangles); + mesh->_regionUVs.addAll(uvs); + if (sequence == NULL) mesh->updateRegion(); + mesh->_hullLength = hullLength; + mesh->_sequence = sequence; if (nonessential) { - readShortArray(input, mesh->getEdges()); - mesh->_width = readFloat(input) * _scale; - mesh->_height = readFloat(input) * _scale; - } else { - mesh->_width = 0; - mesh->_height = 0; + mesh->_edges.addAll(edges); + mesh->_width = width; + mesh->_height = height; } _attachmentLoader->configureAttachment(mesh); return mesh; @@ -554,23 +596,33 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo String path(readStringRef(input, skeletonData)); if (path.isEmpty()) path = name; - MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path)); + Color color; + float width, height; + readColor(input, color); + String skinName(readStringRef(input, skeletonData)); + String parent(readStringRef(input, skeletonData)); + bool inheritTimelines = readBoolean(input); + Sequence *sequence = readSequence(input); + if (nonessential) { + width = readFloat(input) * _scale; + height = readFloat(input) * _scale; + } + + MeshAttachment *mesh = _attachmentLoader->newMeshAttachment(*skin, String(name), String(path), sequence); if (!mesh) { setError("Error reading attachment: ", name.buffer()); return nullptr; } mesh->_path = path; - readColor(input, mesh->getColor()); - String skinName(readStringRef(input, skeletonData)); - String parent(readStringRef(input, skeletonData)); - bool inheritDeform = readBoolean(input); + mesh->_color.set(color); + mesh->_sequence = sequence; if (nonessential) { - mesh->_width = readFloat(input) * _scale; - mesh->_height = readFloat(input) * _scale; + mesh->_width = width; + mesh->_height = height; } LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex, - String(parent), inheritDeform); + String(parent), inheritTimelines); _linkedMeshes.add(linkedMesh); return mesh; } @@ -583,7 +635,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo path->_closed = readBoolean(input); path->_constantSpeed = readBoolean(input); int vertexCount = readVarint(input, true); - readVertices(input, static_cast(path), vertexCount); + readVertices(input, path->getVertices(), path->getBones(), vertexCount); + path->setWorldVerticesLength(vertexCount << 1); int lengthsLength = vertexCount / 3; path->_lengths.setSize(lengthsLength, 0); for (int i = 0; i < lengthsLength; ++i) { @@ -619,7 +672,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo setError("Error reading attachment: ", name.buffer()); return nullptr; } - readVertices(input, static_cast(clip), vertexCount); + readVertices(input, clip->getVertices(), clip->getBones(), vertexCount); + clip->setWorldVerticesLength(vertexCount << 1); clip->_endSlot = skeletonData->_slots[endSlotIndex]; if (nonessential) { readColor(input, clip->getColor()); @@ -631,18 +685,15 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo return nullptr; } -void SkeletonBinary::readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount) { +void SkeletonBinary::readVertices(DataInput *input, Vector &vertices, Vector &bones, int vertexCount) { float scale = _scale; int verticesLength = vertexCount << 1; - attachment->setWorldVerticesLength(vertexCount << 1); if (!readBoolean(input)) { - readFloatArray(input, verticesLength, scale, attachment->getVertices()); + readFloatArray(input, verticesLength, scale, vertices); return; } - Vector &vertices = attachment->getVertices(); - Vector &bones = attachment->getBones(); vertices.ensureCapacity(verticesLength * 3 * 3); bones.ensureCapacity(verticesLength * 3); @@ -1176,69 +1227,84 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { const char *attachmentName = readStringRef(input, skeletonData); Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName)); - if (!baseAttachment) { ContainerUtil::cleanUpVectorOfPointers(timelines); setError("Attachment not found: ", attachmentName); return NULL; } - VertexAttachment *attachment = static_cast(baseAttachment); - - bool weighted = attachment->_bones.size() > 0; - Vector &vertices = attachment->_vertices; - int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size(); - + unsigned int timelineType = readByte(input); int frameCount = readVarint(input, true); int frameLast = frameCount - 1; - int bezierCount = readVarint(input, true); - DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex, - attachment); - float time = readFloat(input); - for (int frame = 0, bezier = 0;; ++frame) { - Vector deform; - size_t end = (size_t) readVarint(input, true); - if (end == 0) { - if (weighted) { - deform.setSize(deformLength, 0); - for (int iiii = 0; iiii < deformLength; ++iiii) - deform[iiii] = 0; - } else { - deform.clearAndAddAll(vertices); - } - } else { - deform.setSize(deformLength, 0); - size_t start = (size_t) readVarint(input, true); - end += start; - if (scale == 1) { - for (size_t v = start; v < end; ++v) - deform[v] = readFloat(input); - } else { - for (size_t v = start; v < end; ++v) - deform[v] = readFloat(input) * scale; + switch (timelineType) { + case ATTACHMENT_DEFORM: { + bool weighted = attachment->_bones.size() > 0; + Vector &vertices = attachment->_vertices; + int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size(); + + int bezierCount = readVarint(input, true); + DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex, + attachment); + + float time = readFloat(input); + for (int frame = 0, bezier = 0;; ++frame) { + Vector deform; + size_t end = (size_t) readVarint(input, true); + if (end == 0) { + if (weighted) { + deform.setSize(deformLength, 0); + for (int iiii = 0; iiii < deformLength; ++iiii) + deform[iiii] = 0; + } else { + deform.clearAndAddAll(vertices); + } + } else { + deform.setSize(deformLength, 0); + size_t start = (size_t) readVarint(input, true); + end += start; + if (scale == 1) { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input); + } else { + for (size_t v = start; v < end; ++v) + deform[v] = readFloat(input) * scale; + } + + if (!weighted) { + for (size_t v = 0, vn = deform.size(); v < vn; ++v) + deform[v] += vertices[v]; + } + } + + timeline->setFrame(frame, time, deform); + if (frame == frameLast) break; + float time2 = readFloat(input); + switch (readSByte(input)) { + case CURVE_STEPPED: + timeline->setStepped(frame); + break; + case CURVE_BEZIER: + setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + } + time = time2; } - if (!weighted) { - for (size_t v = 0, vn = deform.size(); v < vn; ++v) - deform[v] += vertices[v]; - } + timelines.add(timeline); + break; } - - timeline->setFrame(frame, time, deform); - if (frame == frameLast) break; - float time2 = readFloat(input); - switch (readSByte(input)) { - case CURVE_STEPPED: - timeline->setStepped(frame); - break; - case CURVE_BEZIER: - setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1); + case ATTACHMENT_SEQUENCE: { + SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frameCount, slotIndex, attachment); + for (int frame = 0; frame < frameCount; frame++) { + float time = readFloat(input); + int modeAndIndex = readInt(input); + float delay = readFloat(input); + timeline->setFrame(frame, time, (spine::SequenceMode)(modeAndIndex & 0xf), modeAndIndex >> 4, delay); + } + timelines.add(timeline); + break; } - time = time2; } - - timelines.add(timeline); } } }