[c] More 4.2 porting, SkeletonBinary, untested, probably broken

This commit is contained in:
Mario Zechner 2024-04-16 13:48:19 +02:00
parent dca79e4731
commit cbf150b653
4 changed files with 406 additions and 350 deletions

View File

@ -65,7 +65,7 @@ struct spMeshAttachment {
/* Nonessential. */
int edgesCount;
int *edges;
unsigned short *edges;
float width, height;
};

View File

@ -32,8 +32,8 @@
#include <spine/AtlasAttachmentLoader.h>
#include <spine/SkeletonBinary.h>
#include <spine/extension.h>
#include <stdio.h>
#include <spine/Version.h>
#include <stdio.h>
typedef struct {
const unsigned char *cursor;
@ -42,7 +42,7 @@ typedef struct {
typedef struct {
const char *parent;
const char *skin;
int skinIndex;
int slotIndex;
spMeshAttachment *mesh;
int inheritTimeline;
@ -57,6 +57,34 @@ typedef struct {
_spLinkedMesh *linkedMeshes;
} _spSkeletonBinary;
static int string_lastIndexOf(const char *str, char needle) {
if (!str) return -1;
int lastIndex = -1;
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == needle) {
lastIndex = i;
}
}
return lastIndex;
}
static char *string_substring(const char *str, int start, int end) {
if (str == NULL || start > end || start < 0) {
return NULL;
}
int len = end - start;
char *substr = MALLOC(char, len + 1);
if (substr == NULL) {
return NULL;
}
strncpy(substr, str + start, len);
substr[len] = '\0';
return substr;
}
spSkeletonBinary *spSkeletonBinary_createWithLoader(spAttachmentLoader *attachmentLoader) {
spSkeletonBinary *self = SUPER(NEW(_spSkeletonBinary));
self->scale = 1;
@ -185,6 +213,7 @@ static void readColor(_dataInput *input, float *r, float *g, float *b, float *a)
#define BONE_SHEAR 7
#define BONE_SHEARX 8
#define BONE_SHEARY 9
#define BONE_INHERIT 10
#define SLOT_ATTACHMENT 0
#define SLOT_RGBA 1
@ -215,6 +244,15 @@ static void readColor(_dataInput *input, float *r, float *g, float *b, float *a)
#define PATH_ROTATE_CHAIN 1
#define PATH_ROTATE_CHAIN_SCALE 2
#define PHYSICS_INERTIA 0
#define PHYSICS_STRENGTH 1
#define PHYSICS_DAMPING 2
#define PHYSICS_MASS 4
#define PHYSICS_WIND 5
#define PHYSICS_GRAVITY 6
#define PHYSICS_MIX 7
#define PHYSICS_RESET 8
static spSequence *readSequence(_dataInput *input) {
spSequence *sequence = NULL;
if (!readBoolean(input)) return NULL;
@ -236,7 +274,7 @@ setBezier(_dataInput *input, spTimeline *timeline, int bezier, int frame, int va
value2);
}
static spTimeline *readTimeline(_dataInput *input, spCurveTimeline1 *timeline, float scale) {
static void readTimeline(_dataInput *input, spTimelineArray *timelines, spCurveTimeline1 *timeline, float scale) {
int frame, bezier, frameLast;
float time2, value2;
float time = readFloat(input);
@ -256,10 +294,10 @@ static spTimeline *readTimeline(_dataInput *input, spCurveTimeline1 *timeline, f
time = time2;
value = value2;
}
return SUPER(timeline);
spTimelineArray_add(timelines, SUPER(timeline));
}
static spTimeline *readTimeline2(_dataInput *input, spCurveTimeline2 *timeline, float scale) {
static void readTimeline2(_dataInput *input, spTimelineArray *timelines, spCurveTimeline2 *timeline, float scale) {
int frame, bezier, frameLast;
float time2, nvalue1, nvalue2;
float time = readFloat(input);
@ -283,11 +321,11 @@ static spTimeline *readTimeline2(_dataInput *input, spCurveTimeline2 *timeline,
value1 = nvalue1;
value2 = nvalue2;
}
return SUPER(timeline);
spTimelineArray_add(timelines, SUPER(timeline));
}
static void _spSkeletonBinary_addLinkedMesh(spSkeletonBinary *self, spMeshAttachment *mesh,
const char *skin, int slotIndex, const char *parent, int inheritDeform) {
int skinIndex, int slotIndex, const char *parent, int inheritDeform) {
_spLinkedMesh *linkedMesh;
_spSkeletonBinary *internal = SUB_CAST(_spSkeletonBinary, self);
@ -304,7 +342,7 @@ static void _spSkeletonBinary_addLinkedMesh(spSkeletonBinary *self, spMeshAttach
linkedMesh = internal->linkedMeshes + internal->linkedMeshCount++;
linkedMesh->mesh = mesh;
linkedMesh->skin = skin;
linkedMesh->skinIndex = skinIndex;
linkedMesh->slotIndex = slotIndex;
linkedMesh->parent = parent;
linkedMesh->inheritTimeline = inheritDeform;
@ -552,50 +590,59 @@ static spAnimation *_spSkeletonBinary_readAnimation(spSkeletonBinary *self, cons
for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) {
unsigned char timelineType = readByte(input);
int frameCount = readVarint(input, 1);
if (timelineType == BONE_INHERIT) {
spInheritTimeline *timeline = spInheritTimeline_create(frameCount, boneIndex);
for (frame = 0; frame < frameCount; frame++) {
float time = readFloat(input);
spInherit inherit = readByte(input);
spInheritTimeline_setFrame(timeline, frame, time, inherit);
}
spTimelineArray_add(timelines, SUPER(timeline));
continue;
}
int bezierCount = readVarint(input, 1);
spTimeline *timeline = NULL;
switch (timelineType) {
case BONE_ROTATE:
timeline = readTimeline(input, SUPER(spRotateTimeline_create(frameCount, bezierCount, boneIndex)),
readTimeline(input, timelines, SUPER(spRotateTimeline_create(frameCount, bezierCount, boneIndex)),
1);
break;
case BONE_TRANSLATE:
timeline = readTimeline2(input,
readTimeline2(input,timelines,
SUPER(spTranslateTimeline_create(frameCount, bezierCount, boneIndex)),
scale);
break;
case BONE_TRANSLATEX:
timeline = readTimeline(input,
readTimeline(input, timelines,
SUPER(spTranslateXTimeline_create(frameCount, bezierCount, boneIndex)),
scale);
break;
case BONE_TRANSLATEY:
timeline = readTimeline(input,
readTimeline(input, timelines,
SUPER(spTranslateYTimeline_create(frameCount, bezierCount, boneIndex)),
scale);
break;
case BONE_SCALE:
timeline = readTimeline2(input, SUPER(spScaleTimeline_create(frameCount, bezierCount, boneIndex)),
readTimeline2(input, timelines, SUPER(spScaleTimeline_create(frameCount, bezierCount, boneIndex)),
1);
break;
case BONE_SCALEX:
timeline = readTimeline(input, SUPER(spScaleXTimeline_create(frameCount, bezierCount, boneIndex)),
readTimeline(input, timelines, SUPER(spScaleXTimeline_create(frameCount, bezierCount, boneIndex)),
1);
break;
case BONE_SCALEY:
timeline = readTimeline(input, SUPER(spScaleYTimeline_create(frameCount, bezierCount, boneIndex)),
readTimeline(input, timelines, SUPER(spScaleYTimeline_create(frameCount, bezierCount, boneIndex)),
1);
break;
case BONE_SHEAR:
timeline = readTimeline2(input, SUPER(spShearTimeline_create(frameCount, bezierCount, boneIndex)),
readTimeline2(input, timelines, SUPER(spShearTimeline_create(frameCount, bezierCount, boneIndex)),
1);
break;
case BONE_SHEARX:
timeline = readTimeline(input, SUPER(spShearXTimeline_create(frameCount, bezierCount, boneIndex)),
readTimeline(input, timelines, SUPER(spShearXTimeline_create(frameCount, bezierCount, boneIndex)),
1);
break;
case BONE_SHEARY:
timeline = readTimeline(input, SUPER(spShearYTimeline_create(frameCount, bezierCount, boneIndex)),
readTimeline(input, timelines, SUPER(spShearYTimeline_create(frameCount, bezierCount, boneIndex)),
1);
break;
default: {
@ -607,7 +654,6 @@ static spAnimation *_spSkeletonBinary_readAnimation(spSkeletonBinary *self, cons
return NULL;
}
}
spTimelineArray_add(timelines, timeline);
}
}
@ -618,27 +664,20 @@ static spAnimation *_spSkeletonBinary_readAnimation(spSkeletonBinary *self, cons
int frameLast = frameCount - 1;
int bezierCount = readVarint(input, 1);
spIkConstraintTimeline *timeline = spIkConstraintTimeline_create(frameCount, bezierCount, index);
float time = readFloat(input);
float mix = readFloat(input);
float softness = readFloat(input) * scale;
int flags = readByte(input);
float time = readFloat(input), mix = (flags & 1) != 0 ? ((flags & 2) != 0 ? readFloat(input) : 1) : 0;
float softness = (flags & 4) != 0 ? readFloat(input) * scale : 0;
for (frame = 0, bezier = 0;; frame++) {
float time2, mix2, softness2;
int bendDirection = readSByte(input);
int compress = readBoolean(input);
int stretch = readBoolean(input);
spIkConstraintTimeline_setFrame(timeline, frame, time, mix, softness, bendDirection, compress, stretch);
spIkConstraintTimeline_setFrame(timeline, frame, time, mix, softness, (flags & 8) != 0 ? 1 : -1, (flags & 16) != 0, (flags & 32) != 0);
if (frame == frameLast) break;
time2 = readFloat(input);
mix2 = readFloat(input);
softness2 = readFloat(input) * scale;
switch (readSByte(input)) {
case CURVE_STEPPED:
flags = readByte(input);
float time2 = readFloat(input), mix2 = (flags & 1) != 0 ? ((flags & 2) != 0 ? readFloat(input) : 1) : 0;
float softness2 = (flags & 4) != 0 ? readFloat(input) * scale : 0;
if ((flags & 64) != 0)
spCurveTimeline_setStepped(SUPER(timeline), frame);
break;
case CURVE_BEZIER:
else if ((flags & 128) != 0) {
setBezier(input, SUPER(SUPER(timeline)), bezier++, frame, 0, time, time2, mix, mix2, 1);
setBezier(input, SUPER(SUPER(timeline)), bezier++, frame, 1, time, time2, softness, softness2,
scale);
setBezier(input, SUPER(SUPER(timeline)), bezier++, frame, 1, time, time2, softness, softness2, scale);
}
time = time2;
mix = mix2;
@ -701,25 +740,25 @@ static spAnimation *_spSkeletonBinary_readAnimation(spSkeletonBinary *self, cons
int index = readVarint(input, 1);
spPathConstraintData *data = skeletonData->pathConstraints[index];
for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) {
int type = readSByte(input);
int type = readByte(input);
int frameCount = readVarint(input, 1);
int bezierCount = readVarint(input, 1);
switch (type) {
case PATH_POSITION: {
spTimelineArray_add(timelines, readTimeline(input, SUPER(spPathConstraintPositionTimeline_create(frameCount, bezierCount, index)),
readTimeline(input, timelines, SUPER(spPathConstraintPositionTimeline_create(frameCount, bezierCount, index)),
data->positionMode == SP_POSITION_MODE_FIXED ? scale
: 1));
: 1);
break;
}
case PATH_SPACING: {
spTimelineArray_add(timelines, readTimeline(input,
readTimeline(input, timelines,
SUPER(spPathConstraintSpacingTimeline_create(frameCount,
bezierCount,
index)),
data->spacingMode == SP_SPACING_MODE_LENGTH ||
data->spacingMode == SP_SPACING_MODE_FIXED
? scale
: 1));
: 1);
break;
}
case PATH_MIX: {
@ -762,6 +801,44 @@ static spAnimation *_spSkeletonBinary_readAnimation(spSkeletonBinary *self, cons
}
}
for (i = 0, n = readVarint(input, 1); i < n; i++) {
int index = readVarint(input, 1) - 1;
for (ii = 0, nn = readVarint(input, 1); ii < nn; ii++) {
int type = readByte(input);
int frameCount = readVarint(input, 1);
if (type == PHYSICS_RESET) {
spPhysicsConstraintResetTimeline *timeline = spPhysicsConstraintResetTimeline_create(frameCount, index);
for (frame = 0; frame < frameCount; frame++)
spPhysicsConstraintResetTimeline_setFrame(timeline, frame, readFloat(input));
spTimelineArray_add(timelines, SUPER(timeline));
continue;
}
int bezierCount = readVarint(input, 1);
switch (type) {
case PHYSICS_INERTIA:
readTimeline(input, timelines, SUPER(spPhysicsConstraintTimeline_create(frameCount, bezierCount, index, SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA)), 1);
break;
case PHYSICS_STRENGTH:
readTimeline(input, timelines, SUPER(spPhysicsConstraintTimeline_create(frameCount, bezierCount, index, SP_TIMELINE_PHYSICSCONSTRAINT_STRENGTH)), 1);
break;
case PHYSICS_DAMPING:
readTimeline(input, timelines, SUPER(spPhysicsConstraintTimeline_create(frameCount, bezierCount, index, SP_TIMELINE_PHYSICSCONSTRAINT_DAMPING)), 1);
break;
case PHYSICS_MASS:
readTimeline(input, timelines, SUPER(spPhysicsConstraintTimeline_create(frameCount, bezierCount, index, SP_TIMELINE_PHYSICSCONSTRAINT_MASS)), 1);
break;
case PHYSICS_WIND:
readTimeline(input, timelines, SUPER(spPhysicsConstraintTimeline_create(frameCount, bezierCount, index, SP_TIMELINE_PHYSICSCONSTRAINT_WIND)), 1);
break;
case PHYSICS_GRAVITY:
readTimeline(input, timelines, SUPER(spPhysicsConstraintTimeline_create(frameCount, bezierCount, index, SP_TIMELINE_PHYSICSCONSTRAINT_GRAVITY)), 1);
break;
case PHYSICS_MIX:
readTimeline(input, timelines, SUPER(spPhysicsConstraintTimeline_create(frameCount, bezierCount, index, SP_TIMELINE_PHYSICSCONSTRAINT_MIX)), 1);
}
}
}
/* Attachment timelines. */
for (i = 0, n = readVarint(input, 1); i < n; ++i) {
spSkin *skin = skeletonData->skins[readVarint(input, 1)];
@ -908,10 +985,14 @@ static spAnimation *_spSkeletonBinary_readAnimation(spSkeletonBinary *self, cons
spEvent *event = spEvent_create(time, eventData);
event->intValue = readVarint(input, 0);
event->floatValue = readFloat(input);
if (readBoolean(input))
event->stringValue = readString(input);
else
MALLOC_STR(event->stringValue, eventData->stringValue);
const char *event_stringValue = readString(input);
if (event_stringValue == NULL) {
event->stringValue = eventData->stringValue;
} else {
event->stringValue = MALLOC_STR(event->stringValue, event_stringValue);
FREE(event_stringValue);
}
if (eventData->audioPath) {
event->volume = readFloat(input);
event->balance = readFloat(input);
@ -941,97 +1022,66 @@ static float *_readFloatArray(_dataInput *input, int n, float scale) {
return array;
}
static short *_readShortArray(_dataInput *input, int *length) {
int n = readVarint(input, 1);
short *array = MALLOC(short, n);
static unsigned short *_readShortArray(_dataInput *input, int n) {
unsigned short *array = MALLOC(unsigned short, n);
int i;
*length = n;
for (i = 0; i < n; ++i) {
array[i] = readByte(input) << 8;
array[i] |= readByte(input);
array[i] = (unsigned short) readVarint(input, 1);
}
return array;
}
static void _readVertices(spSkeletonBinary *self, _dataInput *input, int *bonesCount, int **bones2, int *verticesCount,
float **vertices, int *worldVerticesLength, int vertexCount) {
int i, ii;
int verticesLength = vertexCount << 1;
spFloatArray *weights = NULL;
spIntArray *bones = NULL;
*worldVerticesLength = verticesLength;
if (!readBoolean(input)) {
*verticesCount = verticesLength;
*vertices = _readFloatArray(input, verticesLength, self->scale);
static int _readVertices(_dataInput *input, float **vertices, int *verticesLength, int **bones, int *bonesCount, int/*bool*/ weighted, float scale) {
int vertexCount = readVarint(input, 1);
*verticesLength = vertexCount << 1;
if (!weighted) {
*vertices = _readFloatArray(input, *verticesLength, scale);
*bones = NULL;
*bonesCount = 0;
*bones2 = NULL;
return;
return *verticesLength;
}
weights = spFloatArray_create(verticesLength * 3 * 3);
bones = spIntArray_create(verticesLength * 3);
for (i = 0; i < vertexCount; ++i) {
*vertices = MALLOC(float, *verticesLength * 3 * 3);
*bones = MALLOC(int, *verticesLength * 3);
int boneIdx = 0;
int vertexIdx = 0;
for (int i = 0; i < vertexCount; ++i) {
int boneCount = readVarint(input, 1);
spIntArray_add(bones, boneCount);
for (ii = 0; ii < boneCount; ++ii) {
spIntArray_add(bones, readVarint(input, 1));
spFloatArray_add(weights, readFloat(input) * self->scale);
spFloatArray_add(weights, readFloat(input) * self->scale);
spFloatArray_add(weights, readFloat(input));
*bones[boneIdx++] = boneCount;
for (int ii = 0; ii < boneCount; ++ii) {
*bones[boneIdx++] = readVarint(input, 1);
*vertices[vertexIdx++] = readFloat(input) * scale;
*vertices[vertexIdx++] = readFloat(input) * scale;
*vertices[vertexIdx++] = readFloat(input);
}
}
*verticesCount = weights->size;
*vertices = weights->items;
FREE(weights);
*bonesCount = bones->size;
*bones2 = bones->items;
FREE(bones);
*bonesCount = boneIdx;
return *verticesLength;
}
spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput *input,
spSkin *skin, int slotIndex, const char *attachmentName,
spSkeletonData *skeletonData, int /*bool*/ nonessential) {
int i;
spAttachmentType type;
const char *name = readStringRef(input, skeletonData);
if (!name) name = attachmentName;
type = (spAttachmentType) readByte(input);
int flags = readByte(input);
const char *name = (flags & 8) != 0 ? readStringRef(input, skeletonData) : attachmentName;
spAttachmentType type = (flags & 0x7);
switch (type) {
case SP_ATTACHMENT_REGION: {
char *path = readStringRef(input, skeletonData);
float rotation, x, y, scaleX, scaleY, width, height;
char *path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : (char*)name;
spColor color;
spSequence *sequence;
if (!path) MALLOC_STR(path, name);
else {
char *tmp = 0;
MALLOC_STR(tmp, path);
path = tmp;
}
rotation = readFloat(input);
x = readFloat(input) * self->scale;
y = readFloat(input) * self->scale;
scaleX = readFloat(input);
scaleY = readFloat(input);
width = readFloat(input) * self->scale;
height = readFloat(input) * self->scale;
readColor(input, &color.r, &color.g, &color.b, &color.a);
sequence = readSequence(input);
{
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name,
path, sequence);
spRegionAttachment *region = NULL;
if (!attachment)
return NULL;
region = SUB_CAST(spRegionAttachment, attachment);
spColor_setFromFloats(&color, 1, 1, 1, 1);
if ((flags & 32) != 0) readColor(input, &color.r, &color.g, &color.b, &color.a);
spSequence *sequence = (flags & 64) != 0 ? readSequence(input) : NULL;
float rotation = (flags & 128) != 0 ? readFloat(input) : 0;
float x = readFloat(input) * self->scale;
float y = readFloat(input) * self->scale;
float scaleX = readFloat(input);
float scaleY = readFloat(input);
float width = readFloat(input) * self->scale;
float height = readFloat(input) * self->scale;
spRegionAttachment *region = SUB_CAST(spRegionAttachment, spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name,
path, sequence));
region->path = path;
region->rotation = rotation;
region->x = x;
@ -1043,82 +1093,69 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput
spColor_setFromColor(&region->color, &color);
region->sequence = sequence;
if (sequence == NULL) spRegionAttachment_updateRegion(region);
spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
return attachment;
}
spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(region));
return SUPER(region);
}
case SP_ATTACHMENT_BOUNDING_BOX: {
int vertexCount = readVarint(input, 1);
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0,
NULL);
spVertexAttachment *vertexAttachment = NULL;
if (!attachment)
return NULL;
vertexAttachment = SUB_CAST(spVertexAttachment, attachment);
_readVertices(self, input, &vertexAttachment->bonesCount, &vertexAttachment->bones,
&vertexAttachment->verticesCount, &vertexAttachment->vertices,
&vertexAttachment->worldVerticesLength, vertexCount);
spBoundingBoxAttachment *box = SUB_CAST(spBoundingBoxAttachment, spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0,
NULL));
if (!box) return NULL;
_readVertices(input, &box->super.vertices, &box->super.verticesCount, &box->super.bones, &box->super.bonesCount, (flags & 16) != 0, self->scale);
box->super.worldVerticesLength = box->super.verticesCount;
if (nonessential) {
spBoundingBoxAttachment *bbox = SUB_CAST(spBoundingBoxAttachment, attachment);
readColor(input, &bbox->color.r, &bbox->color.g, &bbox->color.b, &bbox->color.a);
readColor(input, &box->color.r, &box->color.g, &box->color.b, &box->color.a);
}
spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
return attachment;
spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(box)));
return SUPER(SUPER(box));
}
case SP_ATTACHMENT_MESH: {
int vertexCount;
char *path = readStringRef(input, skeletonData);
spColor color;
float *regionUVs;
unsigned short *triangles;
int trianglesCount;
int *bones;
int bonesCount;
float *vertices;
int verticesCount;
int worldVerticesLength;
int hullLength;
spSequence *sequence;
int *edges = NULL;
int edgesCount = 0;
float *uvs = NULL;
int uvsCount = 0;
unsigned short *triangles = NULL;
int trianglesCount = 0;
float *vertices = NULL;
int verticesCount = 0;
int *bones = NULL;
int bonesCount = 0;
int hullLength = 0;
float width = 0;
float height = 0;
if (!path) MALLOC_STR(path, name);
else {
char *tmp = 0;
MALLOC_STR(tmp, path);
path = tmp;
}
unsigned short *edges = NULL;
int edgesCount = 0;
char* path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : (char*)name;
spColor color;
spColor_setFromFloats(&color, 1, 1, 1, 1);
if ((flags & 32) != 0) readColor(input, &color.r, &color.g, &color.b, &color.a);
spSequence *sequence = (flags & 64) != 0 ? readSequence(input) : NULL;
hullLength = readVarint(input, 1);
int verticesLength = _readVertices(input, &vertices, &verticesCount, &bones, &bonesCount, (flags & 128) != 0, self->scale);
uvsCount = verticesLength;
uvs = _readFloatArray(input, uvsCount, 1);
trianglesCount = (verticesLength - hullLength - 2) * 3;
triangles = _readShortArray(input, trianglesCount);
readColor(input, &color.r, &color.g, &color.b, &color.a);
vertexCount = readVarint(input, 1);
regionUVs = _readFloatArray(input, vertexCount << 1, 1);
triangles = (unsigned short *) _readShortArray(input, &trianglesCount);
_readVertices(self, input, &bonesCount, &bones, &verticesCount, &vertices, &worldVerticesLength, vertexCount);
hullLength = readVarint(input, 1) << 1;
sequence = readSequence(input);
if (nonessential) {
edges = (int *) _readShortArray(input, &edgesCount);
width = readFloat(input) * self->scale;
height = readFloat(input) * self->scale;
edgesCount = readVarint(input, 1);
edges = _readShortArray(input, edgesCount);
width = readFloat(input);
height = readFloat(input);
}
{
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path, sequence);
spMeshAttachment *mesh = NULL;
if (!attachment)
return NULL;
mesh = SUB_CAST(spMeshAttachment, attachment);
if (!attachment) return NULL;
spMeshAttachment *mesh = SUB_CAST(spMeshAttachment, attachment);
mesh->path = path;
spColor_setFromColor(&mesh->color, &color);
mesh->regionUVs = regionUVs;
mesh->regionUVs = uvs;
mesh->triangles = triangles;
mesh->trianglesCount = trianglesCount;
mesh->super.vertices = vertices;
mesh->super.verticesCount = verticesCount;
mesh->super.bones = bones;
mesh->super.bonesCount = bonesCount;
mesh->super.worldVerticesLength = worldVerticesLength;
mesh->super.worldVerticesLength = verticesLength;
mesh->hullLength = hullLength;
mesh->edges = edges;
mesh->edgesCount = edgesCount;
@ -1129,66 +1166,52 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput
spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
return attachment;
}
}
case SP_ATTACHMENT_LINKED_MESH: {
const char *path = (flags & 16) != 0 ? readStringRef(input, skeletonData) : name;
spColor color;
spColor_setFromFloats(&color, 1, 1, 1, 1);
if ((flags & 32) != 0) readColor(input, &color.r, &color.g, &color.b, &color.a);
spSequence *sequence = (flags & 64) != 0 ? readSequence(input) : NULL;
int/*bool*/ inheritTimelines = (flags & 128) != 0;
int skinIndex = readVarint(input, 1);
char *parent = readStringRef(input, skeletonData);
float width = 0, height = 0;
const char *skinName;
const char *parent;
int inheritTimeline;
spSequence *sequence;
char *path = readStringRef(input, skeletonData);
if (!path) MALLOC_STR(path, name);
else {
char *tmp = 0;
MALLOC_STR(tmp, path);
path = tmp;
}
readColor(input, &color.r, &color.g, &color.b, &color.a);
skinName = readStringRef(input, skeletonData);
parent = readStringRef(input, skeletonData);
inheritTimeline = readBoolean(input);
sequence = readSequence(input);
if (nonessential) {
width = readFloat(input) * self->scale;
height = readFloat(input) * self->scale;
}
{
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path, sequence);
spMeshAttachment *mesh = NULL;
if (!attachment)
return NULL;
mesh = SUB_CAST(spMeshAttachment, attachment);
mesh->path = path;
mesh->path = (char*)path;
if (mesh->path) {
char *tmp = NULL;
MALLOC_STR(tmp, mesh->path);
mesh->path = tmp;
}
spColor_setFromColor(&mesh->color, &color);
mesh->sequence = sequence;
mesh->width = width;
mesh->height = height;
_spSkeletonBinary_addLinkedMesh(self, mesh, skinName, slotIndex, parent, inheritTimeline);
_spSkeletonBinary_addLinkedMesh(self, mesh, skinIndex, slotIndex, parent, inheritTimelines);
return attachment;
}
}
case SP_ATTACHMENT_PATH: {
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0,
NULL);
spPathAttachment *path = NULL;
spVertexAttachment *vertexAttachment = NULL;
int vertexCount = 0;
if (!attachment)
return NULL;
path = SUB_CAST(spPathAttachment, attachment);
vertexAttachment = SUPER(path);
path->closed = readBoolean(input);
path->constantSpeed = readBoolean(input);
vertexCount = readVarint(input, 1);
_readVertices(self, input, &vertexAttachment->bonesCount, &vertexAttachment->bones,
&vertexAttachment->verticesCount, &vertexAttachment->vertices,
&vertexAttachment->worldVerticesLength, vertexCount);
path->lengthsLength = vertexCount / 3;
path->closed = (flags & 16) != 0;
path->constantSpeed = (flags & 32) != 0;
int verticesLength = _readVertices(input, &path->super.vertices, &path->super.verticesCount, &path->super.bones, &path->super.bonesCount, (flags & 64) != 0, self->scale);
path->super.worldVerticesLength = verticesLength;
path->lengthsLength = verticesLength / 6;
path->lengths = MALLOC(float, path->lengthsLength);
for (i = 0; i < path->lengthsLength; ++i) {
for (int i = 0; i < path->lengthsLength; ++i) {
path->lengths[i] = readFloat(input) * self->scale;
}
if (nonessential) {
@ -1216,18 +1239,14 @@ spAttachment *spSkeletonBinary_readAttachment(spSkeletonBinary *self, _dataInput
}
case SP_ATTACHMENT_CLIPPING: {
int endSlotIndex = readVarint(input, 1);
int vertexCount = readVarint(input, 1);
spAttachment *attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0,
NULL);
spClippingAttachment *clip = NULL;
spVertexAttachment *vertexAttachment = NULL;
if (!attachment)
return NULL;
clip = SUB_CAST(spClippingAttachment, attachment);
vertexAttachment = SUPER(clip);
_readVertices(self, input, &vertexAttachment->bonesCount, &vertexAttachment->bones,
&vertexAttachment->verticesCount, &vertexAttachment->vertices,
&vertexAttachment->worldVerticesLength, vertexCount);
int verticesLength = _readVertices(input, &clip->super.vertices, &clip->super.verticesCount, &clip->super.bones, &clip->super.bonesCount, (flags & 16) != 0, self->scale);
clip->super.worldVerticesLength = verticesLength;
if (nonessential) {
readColor(input, &clip->color.r, &clip->color.g, &clip->color.b, &clip->color.a);
}
@ -1250,7 +1269,10 @@ spSkin *spSkeletonBinary_readSkin(spSkeletonBinary *self, _dataInput *input, int
if (slotCount == 0) return NULL;
skin = spSkin_create("default");
} else {
skin = spSkin_create(readStringRef(input, skeletonData));
char *name = readString(input);
skin = spSkin_create(name);
FREE(name);
if (nonessential) readColor(input, &skin->color.r, &skin->color.g, &skin->color.b, &skin->color.a);
for (i = 0, n = readVarint(input, 1); i < n; i++)
spBoneDataArray_add(skin->bones, skeletonData->bones[readVarint(input, 1)]);
@ -1264,6 +1286,9 @@ spSkin *spSkeletonBinary_readSkin(spSkeletonBinary *self, _dataInput *input, int
for (i = 0, n = readVarint(input, 1); i < n; i++)
spPathConstraintDataArray_add(skin->pathConstraints, skeletonData->pathConstraints[readVarint(input, 1)]);
for (i = 0, n = readVarint(input, 1); i < n; i++)
spPhysicsConstraintDataArray_add(skin->physicsConstraints, skeletonData->physicsConstraints[readVarint(input, 1)]);
slotCount = readVarint(input, 1);
}
@ -1346,6 +1371,7 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
skeletonData->y = readFloat(input);
skeletonData->width = readFloat(input);
skeletonData->height = readFloat(input);
skeletonData->referenceScale = readFloat(input);
nonessential = readBoolean(input);
@ -1373,12 +1399,9 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
skeletonData->bonesCount = readVarint(input, 1);
skeletonData->bones = MALLOC(spBoneData *, skeletonData->bonesCount);
for (i = 0; i < skeletonData->bonesCount; ++i) {
spBoneData *data;
int mode;
const char *name = readString(input);
spBoneData *parent = i == 0 ? 0 : skeletonData->bones[readVarint(input, 1)];
/* TODO Avoid copying of name */
data = spBoneData_create(i, name, parent);
spBoneData *data = spBoneData_create(i, name, parent);
FREE(name);
data->rotation = readFloat(input);
data->x = readFloat(input) * self->scale;
@ -1388,27 +1411,12 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
data->shearX = readFloat(input);
data->shearY = readFloat(input);
data->length = readFloat(input) * self->scale;
mode = readVarint(input, 1);
switch (mode) {
case 0:
data->inherit = SP_INHERIT_NORMAL;
break;
case 1:
data->inherit = SP_INHERIT_ONLYTRANSLATION;
break;
case 2:
data->inherit = SP_INHERIT_NOROTATIONORREFLECTION;
break;
case 3:
data->inherit = SP_INHERIT_NOSCALE;
break;
case 4:
data->inherit = SP_INHERIT_NOSCALEORREFLECTION;
break;
}
data->inherit = readVarint(input, 1);
data->skinRequired = readBoolean(input);
if (nonessential) {
readColor(input, &data->color.r, &data->color.g, &data->color.b, &data->color.a);
data->icon = readString(input);
data->visible = readBoolean(input);
}
skeletonData->bones[i] = data;
}
@ -1417,27 +1425,36 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
skeletonData->slotsCount = readVarint(input, 1);
skeletonData->slots = MALLOC(spSlotData *, skeletonData->slotsCount);
for (i = 0; i < skeletonData->slotsCount; ++i) {
int r, g, b, a;
const char *attachmentName;
const char *slotName = readString(input);
char *slotName = readString(input);
char *pathName = NULL;
if (nonessential) {
int slash = string_lastIndexOf(slotName, '/');
if (slash != -1) {
pathName = string_substring(slotName, 0, slash);
slotName = string_substring(slotName, slash + 1, strlen(slotName));
}
}
spBoneData *boneData = skeletonData->bones[readVarint(input, 1)];
/* TODO Avoid copying of slotName */
spSlotData *slotData = spSlotData_create(i, slotName, boneData);
FREE(slotName);
readColor(input, &slotData->color.r, &slotData->color.g, &slotData->color.b, &slotData->color.a);
a = readByte(input);
r = readByte(input);
g = readByte(input);
b = readByte(input);
int a = readByte(input);
int r = readByte(input);
int g = readByte(input);
int b = readByte(input);
if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) {
slotData->darkColor = spColor_create();
spColor_setFromFloats(slotData->darkColor, r / 255.0f, g / 255.0f, b / 255.0f, 1);
}
attachmentName = readStringRef(input, skeletonData);
char *attachmentName = readStringRef(input, skeletonData);
if (attachmentName) MALLOC_STR(slotData->attachmentName, attachmentName);
else
slotData->attachmentName = 0;
slotData->blendMode = (spBlendMode) readVarint(input, 1);
if (nonessential) {
slotData->visible = readBoolean(input);
slotData->path = pathName;
}
skeletonData->slots[i] = slotData;
}
@ -1446,22 +1463,23 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
skeletonData->ikConstraints = MALLOC(spIkConstraintData *, skeletonData->ikConstraintsCount);
for (i = 0; i < skeletonData->ikConstraintsCount; ++i) {
const char *name = readString(input);
/* TODO Avoid copying of name */
spIkConstraintData *data = spIkConstraintData_create(name);
data->order = readVarint(input, 1);
data->skinRequired = readBoolean(input);
FREE(name);
data->order = readVarint(input, 1);
data->bonesCount = readVarint(input, 1);
data->bones = MALLOC(spBoneData *, data->bonesCount);
for (ii = 0; ii < data->bonesCount; ++ii)
data->bones[ii] = skeletonData->bones[readVarint(input, 1)];
data->target = skeletonData->bones[readVarint(input, 1)];
data->mix = readFloat(input);
data->softness = readFloat(input);
data->bendDirection = readSByte(input);
data->compress = readBoolean(input);
data->stretch = readBoolean(input);
data->uniform = readBoolean(input);
int flags = readByte(input);
data->skinRequired = (flags & 1) != 0;
data->bendDirection = (flags & 2) != 0 ? 1 : -1;
data->compress = (flags & 4) != 0;
data->stretch = (flags & 8) != 0;
data->uniform = (flags & 16) != 0;
if ((flags & 32) != 0) data->mix = (flags & 64) != 0 ? readFloat(input) : 1;
if ((flags & 128) != 0) data->softness = readFloat(input) * self->scale;
skeletonData->ikConstraints[i] = data;
}
@ -1471,30 +1489,32 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
spTransformConstraintData *, skeletonData->transformConstraintsCount);
for (i = 0; i < skeletonData->transformConstraintsCount; ++i) {
const char *name = readString(input);
/* TODO Avoid copying of name */
spTransformConstraintData *data = spTransformConstraintData_create(name);
data->order = readVarint(input, 1);
data->skinRequired = readBoolean(input);
FREE(name);
data->order = readVarint(input, 1);
data->bonesCount = readVarint(input, 1);
data->bones = MALLOC(spBoneData *, data->bonesCount);
for (ii = 0; ii < data->bonesCount; ++ii)
data->bones[ii] = skeletonData->bones[readVarint(input, 1)];
data->target = skeletonData->bones[readVarint(input, 1)];
data->local = readBoolean(input);
data->relative = readBoolean(input);
data->offsetRotation = readFloat(input);
data->offsetX = readFloat(input) * self->scale;
data->offsetY = readFloat(input) * self->scale;
data->offsetScaleX = readFloat(input);
data->offsetScaleY = readFloat(input);
data->offsetShearY = readFloat(input);
data->mixRotate = readFloat(input);
data->mixX = readFloat(input);
data->mixY = readFloat(input);
data->mixScaleX = readFloat(input);
data->mixScaleY = readFloat(input);
data->mixShearY = readFloat(input);
int flags = readByte(input);
data->skinRequired = (flags & 1) != 0;
data->local = (flags & 2) != 0;
data->relative = (flags & 4) != 0;
if ((flags & 8) != 0) data->offsetRotation = readFloat(input);
if ((flags & 16) != 0) data->offsetX = readFloat(input) * self->scale;
if ((flags & 32) != 0) data->offsetY = readFloat(input) * self->scale;
if ((flags & 64) != 0) data->offsetScaleX = readFloat(input);
if ((flags & 128) != 0) data->offsetScaleY = readFloat(input);
flags = readByte(input);
if ((flags & 1) != 0) data->offsetShearY = readFloat(input);
if ((flags & 2) != 0) data->mixRotate = readFloat(input);
if ((flags & 4) != 0) data->mixX = readFloat(input);
if ((flags & 8) != 0) data->mixY = readFloat(input);
if ((flags & 16) != 0) data->mixScaleX = readFloat(input);
if ((flags & 32) != 0) data->mixScaleY = readFloat(input);
if ((flags & 64) != 0) data->mixShearY = readFloat(input);
skeletonData->transformConstraints[i] = data;
}
@ -1503,20 +1523,20 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
skeletonData->pathConstraints = MALLOC(spPathConstraintData *, skeletonData->pathConstraintsCount);
for (i = 0; i < skeletonData->pathConstraintsCount; ++i) {
const char *name = readString(input);
/* TODO Avoid copying of name */
spPathConstraintData *data = spPathConstraintData_create(name);
FREE(name);
data->order = readVarint(input, 1);
data->skinRequired = readBoolean(input);
FREE(name);
data->bonesCount = readVarint(input, 1);
data->bones = MALLOC(spBoneData *, data->bonesCount);
for (ii = 0; ii < data->bonesCount; ++ii)
data->bones[ii] = skeletonData->bones[readVarint(input, 1)];
data->target = skeletonData->slots[readVarint(input, 1)];
data->positionMode = (spPositionMode) readVarint(input, 1);
data->spacingMode = (spSpacingMode) readVarint(input, 1);
data->rotateMode = (spRotateMode) readVarint(input, 1);
data->offsetRotation = readFloat(input);
int flags = readByte(input);
data->positionMode = (flags & 1);
data->spacingMode = ((flags >> 1) & 3);
data->rotateMode = ((flags >> 3) & 3);
if ((flags & 128) != 0) data->offsetRotation = readFloat(input);
data->position = readFloat(input);
if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale;
data->spacing = readFloat(input);
@ -1528,6 +1548,42 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
skeletonData->pathConstraints[i] = data;
}
// Physics constraints.
skeletonData->physicsConstraintsCount = readVarint(input, 1);
skeletonData->physicsConstraints = MALLOC(spPhysicsConstraintData *, skeletonData->physicsConstraintsCount);
for (i = 0; i < skeletonData->physicsConstraintsCount; i++) {
const char *name = readString(input);
spPhysicsConstraintData *data = spPhysicsConstraintData_create(name);
FREE(name);
data->order = readVarint(input, 1);
data->bone = skeletonData->bones[readVarint(input, 1)];
int flags = readByte(input);
data->skinRequired = (flags & 1) != 0;
if ((flags & 2) != 0) data->x = readFloat(input);
if ((flags & 4) != 0) data->y = readFloat(input);
if ((flags & 8) != 0) data->rotate = readFloat(input);
if ((flags & 16) != 0) data->scaleX = readFloat(input);
if ((flags & 32) != 0) data->shearX = readFloat(input);
data->limit = ((flags & 64) != 0 ? readFloat(input) : 5000) * self->scale;
data->step = 1.f / readByte(input);
data->inertia = readFloat(input);
data->strength = readFloat(input);
data->damping = readFloat(input);
data->massInverse = (flags & 128) != 0 ? readFloat(input) : 1;
data->wind = readFloat(input);
data->gravity = readFloat(input);
flags = readByte(input);
if ((flags & 1) != 0) data->inertiaGlobal = -1;
if ((flags & 2) != 0) data->strengthGlobal = -1;
if ((flags & 4) != 0) data->dampingGlobal = -1;
if ((flags & 8) != 0) data->massGlobal = -1;
if ((flags & 16) != 0) data->windGlobal = -1;
if ((flags & 32) != 0) data->gravityGlobal = -1;
if ((flags & 64) != 0) data->mixGlobal = -1;
data->mix = (flags & 128) != 0 ? readFloat(input) : 1;
skeletonData->physicsConstraints[i] = data;
}
/* Default skin. */
skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, -1, skeletonData, nonessential);
if (self->attachmentLoader->error1) {
@ -1559,15 +1615,14 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
/* Linked meshes. */
for (i = 0; i < internal->linkedMeshCount; ++i) {
_spLinkedMesh *linkedMesh = internal->linkedMeshes + i;
spSkin *skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin);
spAttachment *parent;
spSkin *skin = skeletonData->skins[linkedMesh->skinIndex];
if (!skin) {
FREE(input);
spSkeletonData_dispose(skeletonData);
_spSkeletonBinary_setError(self, "Skin not found: ", linkedMesh->skin);
_spSkeletonBinary_setError(self, "Skin not found", "");
return NULL;
}
parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent);
spAttachment *parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent);
if (!parent) {
FREE(input);
spSkeletonData_dispose(skeletonData);
@ -1585,8 +1640,9 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
skeletonData->eventsCount = readVarint(input, 1);
skeletonData->events = MALLOC(spEventData *, skeletonData->eventsCount);
for (i = 0; i < skeletonData->eventsCount; ++i) {
const char *name = readStringRef(input, skeletonData);
const char *name = readString(input);
spEventData *eventData = spEventData_create(name);
FREE(name);
eventData->intValue = readVarint(input, 0);
eventData->floatValue = readFloat(input);
eventData->stringValue = readString(input);

View File

@ -756,7 +756,7 @@ static spAnimation *_spSkeletonJson_readAnimation(spSkeletonJson *self, Json *ro
continue;
}
spCurveTimeline1 *timeline = NULL;
spPhysicsConstraintTimeline *timeline = NULL;
if (strcmp(timelineName, "inertia") == 0) {
timeline = spPhysicsConstraintTimeline_create(frames, frames, index, SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA);
} else if (strcmp(timelineName, "strength") == 0) {
@ -774,7 +774,7 @@ static spAnimation *_spSkeletonJson_readAnimation(spSkeletonJson *self, Json *ro
} else {
continue;
}
spTimelineArray_add(timelines, readTimeline(keyMap, timeline, 0, 1));
spTimelineArray_add(timelines, readTimeline(keyMap, SUPER(timeline), 0, 1));
}
}
@ -1659,9 +1659,9 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
entry = Json_getItem(attachmentMap, "edges");
if (entry) {
mesh->edgesCount = entry->size;
mesh->edges = MALLOC(int, entry->size);
mesh->edges = MALLOC(unsigned short, entry->size);
for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii)
mesh->edges[ii] = entry->valueInt;
mesh->edges[ii] = (unsigned short)entry->valueInt;
}
spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);

View File

@ -99,9 +99,9 @@ void testcase(void func(spSkeletonData *skeletonData, spAtlas *atlas),
func(skeletonData, atlas);
spSkeletonData_dispose(skeletonData);
// skeletonData = readSkeletonBinaryData(binaryName, atlas, scale);
// func(skeletonData, atlas);
// spSkeletonData_dispose(skeletonData);
skeletonData = readSkeletonBinaryData(binaryName, atlas, scale);
func(skeletonData, atlas);
spSkeletonData_dispose(skeletonData);
spAtlas_dispose(atlas);