[cpp] Support sequence (timelines) in SkeletonJson

This commit is contained in:
Mario Zechner 2021-12-17 16:41:40 +01:00
parent 9fda6dcd3b
commit 9ac6f3dcc7
6 changed files with 132 additions and 80 deletions

View File

@ -46,8 +46,6 @@ namespace spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
public: public:
explicit Sequence();
Sequence(int count); Sequence(int count);
~Sequence(); ~Sequence();

View File

@ -59,6 +59,8 @@ namespace spine {
class String; class String;
class Sequence;
class SP_API SkeletonJson : public SpineObject { class SP_API SkeletonJson : public SpineObject {
public: public:
explicit SkeletonJson(Atlas *atlas); explicit SkeletonJson(Atlas *atlas);
@ -82,6 +84,8 @@ namespace spine {
const bool _ownsLoader; const bool _ownsLoader;
String _error; String _error;
static Sequence *readSequence(Json *sequence);
static void static void
setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1,
float cy1, float cy1,

View File

@ -144,6 +144,22 @@ void MeshAttachment::setPath(const String &inValue) {
_path = inValue; _path = inValue;
} }
TextureRegion *MeshAttachment::getRegion() {
return _region;
}
void MeshAttachment::setRegion(TextureRegion *region) {
_region = region;
}
Sequence *MeshAttachment::getSequence() {
return _sequence;
}
void MeshAttachment::setSequence(Sequence *sequence) {
_sequence = sequence;
}
MeshAttachment *MeshAttachment::getParentMesh() { MeshAttachment *MeshAttachment::getParentMesh() {
return _parentMesh; return _parentMesh;
} }

View File

@ -47,9 +47,9 @@ Sequence::~Sequence() {
} }
Sequence *Sequence::copy() { Sequence *Sequence::copy() {
Sequence *copy = new (__FILE__, __LINE__) Sequence(); Sequence *copy = new (__FILE__, __LINE__) Sequence(_regions.size());
for (size_t i = 0; i < _regions.size(); i++) { for (size_t i = 0; i < _regions.size(); i++) {
copy->_regions.add(_regions[i]); copy->_regions[i] = _regions[i];
} }
copy->_start = _start; copy->_start = _start;
copy->_digits = _digits; copy->_digits = _digits;

View File

@ -72,6 +72,7 @@
#include <spine/TransformConstraintTimeline.h> #include <spine/TransformConstraintTimeline.h>
#include <spine/TranslateTimeline.h> #include <spine/TranslateTimeline.h>
#include <spine/Vertices.h> #include <spine/Vertices.h>
#include "spine/SequenceTimeline.h"
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#define strdup _strdup #define strdup _strdup
@ -548,7 +549,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
switch (type) { switch (type) {
case AttachmentType_Region: { case AttachmentType_Region: {
attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath); Sequence *sequence = readSequence(Json::getItem(attachmentMap, "sequence"));
attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath, sequence);
if (!attachment) { if (!attachment) {
delete skeletonData; delete skeletonData;
setError(root, "Error reading attachment: ", skinAttachmentName); setError(root, "Error reading attachment: ", skinAttachmentName);
@ -565,17 +567,19 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
region->_rotation = Json::getFloat(attachmentMap, "rotation", 0); region->_rotation = Json::getFloat(attachmentMap, "rotation", 0);
region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale;
region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale;
region->_sequence = sequence;
color = Json::getString(attachmentMap, "color", 0); color = Json::getString(attachmentMap, "color", 0);
if (color) toColor(region->getColor(), color, true); if (color) toColor(region->getColor(), color, true);
region->updateRegion(); if (region->_region != NULL) region->updateRegion();
_attachmentLoader->configureAttachment(region); _attachmentLoader->configureAttachment(region);
break; break;
} }
case AttachmentType_Mesh: case AttachmentType_Mesh:
case AttachmentType_Linkedmesh: { case AttachmentType_Linkedmesh: {
attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath); Sequence *sequence = readSequence(Json::getItem(attachmentMap, "sequence"));
attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath, sequence);
if (!attachment) { if (!attachment) {
delete skeletonData; delete skeletonData;
@ -591,6 +595,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
mesh->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; mesh->_width = Json::getFloat(attachmentMap, "width", 32) * _scale;
mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale;
mesh->_sequence = sequence;
entry = Json::getItem(attachmentMap, "parent"); entry = Json::getItem(attachmentMap, "parent");
if (!entry) { if (!entry) {
@ -610,7 +615,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
readVertices(attachmentMap, mesh, verticesLength); readVertices(attachmentMap, mesh, verticesLength);
mesh->updateRegion(); if (mesh->_region != NULL) mesh->updateRegion();
mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0); mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0);
@ -623,14 +628,14 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
} }
_attachmentLoader->configureAttachment(mesh); _attachmentLoader->configureAttachment(mesh);
} else { } else {
bool inheritDeform = Json::getInt(attachmentMap, "deform", 1) ? true : false; bool inheritTimelines = Json::getInt(attachmentMap, "timelines", 1) ? true : false;
LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh, LinkedMesh *linkedMesh = new (__FILE__, __LINE__) LinkedMesh(mesh,
String(Json::getString( String(Json::getString(
attachmentMap, attachmentMap,
"skin", 0)), "skin", 0)),
slot->getIndex(), slot->getIndex(),
String(entry->_valueString), String(entry->_valueString),
inheritDeform); inheritTimelines);
_linkedMeshes.add(linkedMesh); _linkedMeshes.add(linkedMesh);
} }
break; break;
@ -722,10 +727,10 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
setError(root, "Parent mesh not found: ", linkedMesh->_parent.buffer()); setError(root, "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 != NULL) linkedMesh->_mesh->updateRegion();
_attachmentLoader->configureAttachment(linkedMesh->_mesh); _attachmentLoader->configureAttachment(linkedMesh->_mesh);
} }
ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes);
@ -777,6 +782,15 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
return skeletonData; return skeletonData;
} }
Sequence *SkeletonJson::readSequence(Json *item) {
if (item == NULL) return NULL;
Sequence *sequence = new Sequence(Json::getInt(item, "count", 0));
sequence->_start = Json::getInt(item, "start", 1);
sequence->_digits = Json::getInt(item, "digits", 0);
sequence->_setupIndex = Json::getInt(item, "setupIndex", 0);
return sequence;
}
void SkeletonJson::setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, void SkeletonJson::setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1,
float cy1, float cy1,
float cx2, float cy2, float time2, float value2) { float cx2, float cy2, float time2, float value2) {
@ -865,10 +879,10 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
Json *ik = Json::getItem(root, "ik"); Json *ik = Json::getItem(root, "ik");
Json *transform = Json::getItem(root, "transform"); Json *transform = Json::getItem(root, "transform");
Json *paths = Json::getItem(root, "path"); Json *paths = Json::getItem(root, "path");
Json *deform = Json::getItem(root, "deform"); Json *attachments = Json::getItem(root, "attachments");
Json *drawOrder = Json::getItem(root, "drawOrder"); Json *drawOrder = Json::getItem(root, "drawOrder");
Json *events = Json::getItem(root, "events"); Json *events = Json::getItem(root, "events");
Json *boneMap, *slotMap, *constraintMap, *keyMap, *nextMap, *curve; Json *boneMap, *slotMap, *keyMap, *nextMap, *curve;
int frame, bezier; int frame, bezier;
Color color, color2, newColor, newColor2; Color color, color2, newColor, newColor2;
@ -883,7 +897,7 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frames, slotIndex); AttachmentTimeline *timeline = new (__FILE__, __LINE__) AttachmentTimeline(frames, slotIndex);
for (keyMap = timelineMap->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) { for (keyMap = timelineMap->_child, frame = 0; keyMap; keyMap = keyMap->_next, ++frame) {
timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0), timeline->setFrame(frame, Json::getFloat(keyMap, "time", 0),
Json::getItem(keyMap, "name")->_valueString); Json::getItem(keyMap, "name") ? Json::getItem(keyMap, "name")->_valueString : NULL);
} }
timelines.add(timeline); timelines.add(timeline);
@ -1079,7 +1093,7 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
} }
/** IK constraint timelines. */ /** IK constraint timelines. */
for (constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) { for (Json *constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
keyMap = constraintMap->_child; keyMap = constraintMap->_child;
if (keyMap == NULL) continue; if (keyMap == NULL) continue;
@ -1122,7 +1136,7 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
} }
/** Transform constraint timelines. */ /** Transform constraint timelines. */
for (constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) { for (Json *constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
keyMap = constraintMap->_child; keyMap = constraintMap->_child;
if (keyMap == NULL) continue; if (keyMap == NULL) continue;
@ -1178,7 +1192,7 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
} }
/** Path constraint timelines. */ /** Path constraint timelines. */
for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) { for (Json *constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) {
PathConstraintData *constraint = skeletonData->findPathConstraint(constraintMap->_name); PathConstraintData *constraint = skeletonData->findPathConstraint(constraintMap->_name);
if (!constraint) { if (!constraint) {
ContainerUtil::cleanUpVectorOfPointers(timelines); ContainerUtil::cleanUpVectorOfPointers(timelines);
@ -1239,77 +1253,98 @@ Animation *SkeletonJson::readAnimation(Json *root, SkeletonData *skeletonData) {
} }
} }
/** Deform timelines. */ /** Attachment timelines. */
for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { for (Json *attachmenstMap = attachments ? attachments->_child : NULL; attachmenstMap; attachmenstMap = attachmenstMap->_next) {
Skin *skin = skeletonData->findSkin(constraintMap->_name); Skin *skin = skeletonData->findSkin(attachmenstMap->_name);
for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) { for (slotMap = attachmenstMap->_child; slotMap; slotMap = slotMap->_next) {
int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines); int slotIndex = findSlotIndex(skeletonData, slotMap->_name, timelines);
if (slotIndex == -1) return NULL; if (slotIndex == -1) return NULL;
for (Json *timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { for (Json *attachmentMap = slotMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) {
keyMap = timelineMap->_child; Attachment *attachment = skin->getAttachment(slotIndex, attachmentMap->_name);
if (keyMap == NULL) continue; if (!attachment) {
Attachment *baseAttachment = skin->getAttachment(slotIndex, timelineMap->_name);
if (!baseAttachment) {
ContainerUtil::cleanUpVectorOfPointers(timelines); ContainerUtil::cleanUpVectorOfPointers(timelines);
setError(NULL, "Attachment not found: ", timelineMap->_name); setError(NULL, "Attachment not found: ", attachmentMap->_name);
return NULL; return NULL;
} }
VertexAttachment *attachment = static_cast<VertexAttachment *>(baseAttachment);
bool weighted = attachment->_bones.size() != 0; for (Json *timelineMap = attachmentMap->_child; timelineMap; timelineMap = timelineMap->_next) {
Vector<float> &verts = attachment->_vertices; keyMap = timelineMap->_child;
int deformLength = weighted ? verts.size() / 3 * 2 : verts.size(); if (keyMap == NULL) continue;
int frames = timelineMap->_size;
String timelineName = timelineMap->_name;
if (timelineName == "deform") {
VertexAttachment *vertexAttachment = static_cast<VertexAttachment *>(attachment);
bool weighted = vertexAttachment->_bones.size() != 0;
Vector<float> &verts = vertexAttachment->_vertices;
int deformLength = weighted ? verts.size() / 3 * 2 : verts.size();
DeformTimeline *timeline = new (__FILE__, __LINE__) DeformTimeline(timelineMap->_size, DeformTimeline *timeline = new(__FILE__, __LINE__) DeformTimeline(frames,
timelineMap->_size, slotIndex, frames, slotIndex,vertexAttachment);
attachment); float time = Json::getFloat(keyMap, "time", 0);
float time = Json::getFloat(keyMap, "time", 0); for (frame = 0, bezier = 0;; frame++) {
for (frame = 0, bezier = 0;; frame++) { Json *vertices = Json::getItem(keyMap, "vertices");
Json *vertices = Json::getItem(keyMap, "vertices"); Vector<float> deformed;
Vector<float> deformed; if (!vertices) {
if (!vertices) { if (weighted) {
if (weighted) { deformed.setSize(deformLength, 0);
deformed.setSize(deformLength, 0); } else {
} else { deformed.clearAndAddAll(vertexAttachment->_vertices);
deformed.clearAndAddAll(attachment->_vertices); }
} else {
deformed.setSize(deformLength, 0);
int v, start = Json::getInt(keyMap, "offset", 0);
Json *vertex;
if (_scale == 1) {
for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) {
deformed[v] = vertex->_valueFloat;
}
} else {
for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) {
deformed[v] = vertex->_valueFloat * _scale;
}
}
if (!weighted) {
Vector<float> &verticesAttachment = vertexAttachment->_vertices;
for (v = 0; v < deformLength; ++v) {
deformed[v] += verticesAttachment[v];
}
}
}
timeline->setFrame(frame, time, deformed);
nextMap = keyMap->_next;
if (!nextMap) {
// timeline.shrink(); // BOZO
break;
}
float time2 = Json::getFloat(nextMap, "time", 0);
curve = Json::getItem(keyMap, "curve");
if (curve) {
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
}
time = time2;
keyMap = nextMap;
} }
} else { timelines.add(timeline);
int v, start = Json::getInt(keyMap, "offset", 0); } else if (timelineName == "sequence") {
Json *vertex; SequenceTimeline *timeline = new SequenceTimeline(frames, slotIndex, attachment);
deformed.setSize(deformLength, 0); float lastDelay = 0;
if (_scale == 1) { for (frame = 0; keyMap != NULL; keyMap = keyMap->_next, frame++) {
for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { float delay = Json::getFloat(keyMap, "delay", lastDelay);
deformed[v] = vertex->_valueFloat; float time = Json::getFloat(keyMap, "time", 0);
} String modeString = Json::getString(keyMap, "mode", "hold");
} else { int index = Json::getInt(keyMap, "index", 0);
for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { SequenceMode mode = SequenceMode::hold;
deformed[v] = vertex->_valueFloat * _scale; if (modeString == "once") mode = SequenceMode::once;
} if (modeString == "loop") mode = SequenceMode::loop;
} if (modeString == "pingpong") mode = SequenceMode::pingpong;
if (!weighted) { if (modeString == "onceReverse") mode = SequenceMode::onceReverse;
Vector<float> &verticesAttachment = attachment->_vertices; if (modeString == "loopReverse") mode = SequenceMode::loopReverse;
for (v = 0; v < deformLength; ++v) { if (modeString == "pingpongReverse") mode = SequenceMode::pingpongReverse;
deformed[v] += verticesAttachment[v]; timeline->setFrame(frame, time, mode, index, delay);
}
} }
} }
timeline->setFrame(frame, time, deformed);
nextMap = keyMap->_next;
if (!nextMap) {
// timeline.shrink(); // BOZO
break;
}
float time2 = Json::getFloat(nextMap, "time", 0);
curve = Json::getItem(keyMap, "curve");
if (curve) {
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
}
time = time2;
keyMap = nextMap;
} }
timelines.add(timeline);
} }
} }
} }

View File

@ -77,7 +77,6 @@ namespace spine {
} }
void SkeletonDrawable::update(float deltaTime) { void SkeletonDrawable::update(float deltaTime) {
skeleton->update(deltaTime);
state->update(deltaTime * timeScale); state->update(deltaTime * timeScale);
state->apply(*skeleton); state->apply(*skeleton);
skeleton->updateWorldTransform(); skeleton->updateWorldTransform();
@ -123,7 +122,7 @@ namespace spine {
} }
worldVertices.setSize(8, 0); worldVertices.setSize(8, 0);
regionAttachment->computeWorldVertices(slot.getBone(), worldVertices, 0, 2); regionAttachment->computeWorldVertices(slot, worldVertices, 0, 2);
verticesCount = 4; verticesCount = 4;
uvs = &regionAttachment->getUVs(); uvs = &regionAttachment->getUVs();
indices = &quadIndices; indices = &quadIndices;
@ -142,7 +141,7 @@ namespace spine {
worldVertices.setSize(mesh->getWorldVerticesLength(), 0); worldVertices.setSize(mesh->getWorldVerticesLength(), 0);
texture = (Texture *) ((AtlasRegion *) mesh->getRendererObject())->page->getRendererObject(); texture = (Texture *) ((AtlasRegion *) mesh->getRendererObject())->page->getRendererObject();
mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), worldVertices, 0, 2); mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), worldVertices.buffer(), 0, 2);
verticesCount = mesh->getWorldVerticesLength() >> 1; verticesCount = mesh->getWorldVerticesLength() >> 1;
uvs = &mesh->getUVs(); uvs = &mesh->getUVs();
indices = &mesh->getTriangles(); indices = &mesh->getTriangles();