[cpp] Sequence and SequenceTimeline support in SkeletonBinary.

This commit is contained in:
Mario Zechner 2021-12-16 17:14:52 +01:00
parent 2c8f68bd29
commit 9fda6dcd3b
6 changed files with 186 additions and 108 deletions

View File

@ -43,14 +43,14 @@ namespace spine {
public: public:
LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent,
bool inheritDeform); bool inheritTimeline);
private: private:
MeshAttachment *_mesh; MeshAttachment *_mesh;
String _skin; String _skin;
size_t _slotIndex; size_t _slotIndex;
String _parent; String _parent;
bool _inheritDeform; bool _inheritTimeline;
}; };
} }

View File

@ -39,12 +39,16 @@ namespace spine {
class Attachment; 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: public:
explicit Sequence(); explicit Sequence();
Sequence(int id, const Vector<TextureRegion *> &regions, int start, int digits, int setupIndex); Sequence(int count);
~Sequence(); ~Sequence();

View File

@ -61,6 +61,8 @@ namespace spine {
class CurveTimeline2; class CurveTimeline2;
class Sequence;
class SP_API SkeletonBinary : public SpineObject { class SP_API SkeletonBinary : public SpineObject {
public: public:
static const int BONE_ROTATE = 0; static const int BONE_ROTATE = 0;
@ -81,6 +83,9 @@ namespace spine {
static const int SLOT_RGB2 = 4; static const int SLOT_RGB2 = 4;
static const int SLOT_ALPHA = 5; 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_POSITION = 0;
static const int PATH_SPACING = 1; static const int PATH_SPACING = 1;
static const int PATH_MIX = 2; static const int PATH_MIX = 2;
@ -137,10 +142,12 @@ namespace spine {
Skin *readSkin(DataInput *input, bool defaultSkin, SkeletonData *skeletonData, bool nonessential); 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, Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
SkeletonData *skeletonData, bool nonessential); SkeletonData *skeletonData, bool nonessential);
void readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount); void readVertices(DataInput *input, Vector<float> &vertices, Vector<size_t> &bones, int vertexCount);
void readFloatArray(DataInput *input, int n, float scale, Vector<float> &array); void readFloatArray(DataInput *input, int n, float scale, Vector<float> &array);

View File

@ -38,9 +38,9 @@
using namespace spine; using namespace spine;
LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent, LinkedMesh::LinkedMesh(MeshAttachment *mesh, const String &skin, size_t slotIndex, const String &parent,
bool inheritDeform) : _mesh(mesh), bool inheritTimeline) : _mesh(mesh),
_skin(skin), _skin(skin),
_slotIndex(slotIndex), _slotIndex(slotIndex),
_parent(parent), _parent(parent),
_inheritDeform(inheritDeform) { _inheritTimeline(inheritTimeline) {
} }

View File

@ -35,11 +35,12 @@
using namespace spine; using namespace spine;
Sequence::Sequence() : _id(Sequence::getNextID()), Sequence::Sequence(int count) : _id(Sequence::getNextID()),
_regions(), _regions(),
_start(0), _start(0),
_digits(0), _digits(0),
_setupIndex(0) { _setupIndex(0) {
_regions.setSize(count, NULL);
} }
Sequence::~Sequence() { Sequence::~Sequence() {

View File

@ -72,6 +72,7 @@
#include <spine/TransformConstraintData.h> #include <spine/TransformConstraintData.h>
#include <spine/TransformConstraintTimeline.h> #include <spine/TransformConstraintTimeline.h>
#include <spine/TranslateTimeline.h> #include <spine/TranslateTimeline.h>
#include "spine/SequenceTimeline.h"
using namespace spine; using namespace spine;
@ -298,10 +299,10 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
setError("Parent mesh not found: ", linkedMesh->_parent.buffer()); setError("Parent mesh not found: ", linkedMesh->_parent.buffer());
return NULL; return NULL;
} }
linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritDeform ? static_cast<VertexAttachment *>(parent) linkedMesh->_mesh->_timelineAttachment = linkedMesh->_inheritTimeline ? static_cast<VertexAttachment *>(parent)
: linkedMesh->_mesh; : linkedMesh->_mesh;
linkedMesh->_mesh->setParentMesh(static_cast<MeshAttachment *>(parent)); linkedMesh->_mesh->setParentMesh(static_cast<MeshAttachment *>(parent));
linkedMesh->_mesh->updateRegion(); if (linkedMesh->_mesh->_region) linkedMesh->_mesh->updateRegion();
_attachmentLoader->configureAttachment(linkedMesh->_mesh); _attachmentLoader->configureAttachment(linkedMesh->_mesh);
} }
ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes);
@ -478,6 +479,15 @@ Skin *SkeletonBinary::readSkin(DataInput *input, bool defaultSkin, SkeletonData
return skin; 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, Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
SkeletonData *skeletonData, bool nonessential) { SkeletonData *skeletonData, bool nonessential) {
String name(readStringRef(input, skeletonData)); String name(readStringRef(input, skeletonData));
@ -488,21 +498,32 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
case AttachmentType_Region: { case AttachmentType_Region: {
String path(readStringRef(input, skeletonData)); String path(readStringRef(input, skeletonData));
if (path.isEmpty()) path = name; 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) { if (!region) {
setError("Error reading attachment: ", name.buffer()); setError("Error reading attachment: ", name.buffer());
return nullptr; return nullptr;
} }
region->_path = path; region->_path = path;
region->_rotation = readFloat(input); region->_rotation = rotation;
region->_x = readFloat(input) * _scale; region->_x = x;
region->_y = readFloat(input) * _scale; region->_y = y;
region->_scaleX = readFloat(input); region->_scaleX = scaleX;
region->_scaleY = readFloat(input); region->_scaleY = scaleY;
region->_width = readFloat(input) * _scale; region->_width = width;
region->_height = readFloat(input) * _scale; region->_height = height;
readColor(input, region->getColor()); region->getColor().set(color);
region->updateRegion(); region->_sequence = sequence;
if (sequence == NULL) region->updateRegion();
_attachmentLoader->configureAttachment(region); _attachmentLoader->configureAttachment(region);
return region; return region;
} }
@ -513,7 +534,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
setError("Error reading attachment: ", name.buffer()); setError("Error reading attachment: ", name.buffer());
return nullptr; return nullptr;
} }
readVertices(input, static_cast<VertexAttachment *>(box), vertexCount); readVertices(input, box->getVertices(), box->getBones(), vertexCount);
box->setWorldVerticesLength(vertexCount << 1);
if (nonessential) { if (nonessential) {
readColor(input, box->getColor()); readColor(input, box->getColor());
} }
@ -521,31 +543,51 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
return box; return box;
} }
case AttachmentType_Mesh: { case AttachmentType_Mesh: {
Color color;
int vertexCount; int vertexCount;
MeshAttachment *mesh; Vector<float> uvs;
Vector<unsigned short> triangles;
Vector<float> vertices;
Vector<size_t> bones;
int hullLength;
Sequence *sequence;
float width = 0;
float height = 0;
Vector<unsigned short> edges;
String path(readStringRef(input, skeletonData)); String path(readStringRef(input, skeletonData));
if (path.isEmpty()) path = name; 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) { if (!mesh) {
setError("Error reading attachment: ", name.buffer()); setError("Error reading attachment: ", name.buffer());
return nullptr; return nullptr;
} }
mesh->_path = path; mesh->_path = path;
readColor(input, mesh->getColor()); mesh->_color.set(color);
vertexCount = readVarint(input, true); mesh->_vertices.addAll(vertices);
readFloatArray(input, vertexCount << 1, 1, mesh->getRegionUVs()); mesh->setWorldVerticesLength(vertexCount << 1);
readShortArray(input, mesh->getTriangles()); mesh->_triangles.addAll(triangles);
readVertices(input, static_cast<VertexAttachment *>(mesh), vertexCount); mesh->_regionUVs.addAll(uvs);
mesh->updateRegion(); if (sequence == NULL) mesh->updateRegion();
mesh->_hullLength = readVarint(input, true) << 1; mesh->_hullLength = hullLength;
mesh->_sequence = sequence;
if (nonessential) { if (nonessential) {
readShortArray(input, mesh->getEdges()); mesh->_edges.addAll(edges);
mesh->_width = readFloat(input) * _scale; mesh->_width = width;
mesh->_height = readFloat(input) * _scale; mesh->_height = height;
} else {
mesh->_width = 0;
mesh->_height = 0;
} }
_attachmentLoader->configureAttachment(mesh); _attachmentLoader->configureAttachment(mesh);
return mesh; return mesh;
@ -554,23 +596,33 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
String path(readStringRef(input, skeletonData)); String path(readStringRef(input, skeletonData));
if (path.isEmpty()) path = name; 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) { if (!mesh) {
setError("Error reading attachment: ", name.buffer()); setError("Error reading attachment: ", name.buffer());
return nullptr; return nullptr;
} }
mesh->_path = path; mesh->_path = path;
readColor(input, mesh->getColor()); mesh->_color.set(color);
String skinName(readStringRef(input, skeletonData)); mesh->_sequence = sequence;
String parent(readStringRef(input, skeletonData));
bool inheritDeform = readBoolean(input);
if (nonessential) { if (nonessential) {
mesh->_width = readFloat(input) * _scale; mesh->_width = width;
mesh->_height = readFloat(input) * _scale; mesh->_height = height;
} }
LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex, LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, String(skinName), slotIndex,
String(parent), inheritDeform); String(parent), inheritTimelines);
_linkedMeshes.add(linkedMesh); _linkedMeshes.add(linkedMesh);
return mesh; return mesh;
} }
@ -583,7 +635,8 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
path->_closed = readBoolean(input); path->_closed = readBoolean(input);
path->_constantSpeed = readBoolean(input); path->_constantSpeed = readBoolean(input);
int vertexCount = readVarint(input, true); int vertexCount = readVarint(input, true);
readVertices(input, static_cast<VertexAttachment *>(path), vertexCount); readVertices(input, path->getVertices(), path->getBones(), vertexCount);
path->setWorldVerticesLength(vertexCount << 1);
int lengthsLength = vertexCount / 3; int lengthsLength = vertexCount / 3;
path->_lengths.setSize(lengthsLength, 0); path->_lengths.setSize(lengthsLength, 0);
for (int i = 0; i < lengthsLength; ++i) { 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()); setError("Error reading attachment: ", name.buffer());
return nullptr; return nullptr;
} }
readVertices(input, static_cast<VertexAttachment *>(clip), vertexCount); readVertices(input, clip->getVertices(), clip->getBones(), vertexCount);
clip->setWorldVerticesLength(vertexCount << 1);
clip->_endSlot = skeletonData->_slots[endSlotIndex]; clip->_endSlot = skeletonData->_slots[endSlotIndex];
if (nonessential) { if (nonessential) {
readColor(input, clip->getColor()); readColor(input, clip->getColor());
@ -631,18 +685,15 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
return nullptr; return nullptr;
} }
void SkeletonBinary::readVertices(DataInput *input, VertexAttachment *attachment, int vertexCount) { void SkeletonBinary::readVertices(DataInput *input, Vector<float> &vertices, Vector<size_t> &bones, int vertexCount) {
float scale = _scale; float scale = _scale;
int verticesLength = vertexCount << 1; int verticesLength = vertexCount << 1;
attachment->setWorldVerticesLength(vertexCount << 1);
if (!readBoolean(input)) { if (!readBoolean(input)) {
readFloatArray(input, verticesLength, scale, attachment->getVertices()); readFloatArray(input, verticesLength, scale, vertices);
return; return;
} }
Vector<float> &vertices = attachment->getVertices();
Vector<size_t> &bones = attachment->getBones();
vertices.ensureCapacity(verticesLength * 3 * 3); vertices.ensureCapacity(verticesLength * 3 * 3);
bones.ensureCapacity(verticesLength * 3); bones.ensureCapacity(verticesLength * 3);
@ -1176,21 +1227,22 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) {
const char *attachmentName = readStringRef(input, skeletonData); const char *attachmentName = readStringRef(input, skeletonData);
Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName)); Attachment *baseAttachment = skin->getAttachment(slotIndex, String(attachmentName));
if (!baseAttachment) { if (!baseAttachment) {
ContainerUtil::cleanUpVectorOfPointers(timelines); ContainerUtil::cleanUpVectorOfPointers(timelines);
setError("Attachment not found: ", attachmentName); setError("Attachment not found: ", attachmentName);
return NULL; return NULL;
} }
VertexAttachment *attachment = static_cast<VertexAttachment *>(baseAttachment); VertexAttachment *attachment = static_cast<VertexAttachment *>(baseAttachment);
unsigned int timelineType = readByte(input);
int frameCount = readVarint(input, true);
int frameLast = frameCount - 1;
switch (timelineType) {
case ATTACHMENT_DEFORM: {
bool weighted = attachment->_bones.size() > 0; bool weighted = attachment->_bones.size() > 0;
Vector<float> &vertices = attachment->_vertices; Vector<float> &vertices = attachment->_vertices;
int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size(); int deformLength = weighted ? vertices.size() / 3 * 2 : vertices.size();
int frameCount = readVarint(input, true);
int frameLast = frameCount - 1;
int bezierCount = readVarint(input, true); int bezierCount = readVarint(input, true);
DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex, DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(frameCount, bezierCount, slotIndex,
attachment); attachment);
@ -1239,6 +1291,20 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
} }
timelines.add(timeline); timelines.add(timeline);
break;
}
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;
}
}
} }
} }
} }