mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[c] More 4.2 porting, SkeletonJson, SFML physics examples
This commit is contained in:
parent
f7f4d5cbe7
commit
2d940b4156
@ -472,7 +472,7 @@ typedef struct spInheritTimeline {
|
|||||||
|
|
||||||
SP_API spInheritTimeline *spInheritTimeline_create(int framesCount, int boneIndex);
|
SP_API spInheritTimeline *spInheritTimeline_create(int framesCount, int boneIndex);
|
||||||
|
|
||||||
SP_API void spInheritTimeline_setFrame(spDrawOrderTimeline *self, int frameIndex, float time, spInherit inherit);
|
SP_API void spInheritTimeline_setFrame(spInheritTimeline *self, int frameIndex, float time, spInherit inherit);
|
||||||
|
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
@ -51,6 +51,7 @@ typedef struct spSlotData {
|
|||||||
spColor *darkColor;
|
spColor *darkColor;
|
||||||
spBlendMode blendMode;
|
spBlendMode blendMode;
|
||||||
int/*bool*/ visible;
|
int/*bool*/ visible;
|
||||||
|
char *path;
|
||||||
} spSlotData;
|
} spSlotData;
|
||||||
|
|
||||||
SP_API spSlotData *spSlotData_create(const int index, const char *name, spBoneData *boneData);
|
SP_API spSlotData *spSlotData_create(const int index, const char *name, spBoneData *boneData);
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
#define SPINE_VERTEXEFFECT_H_
|
#define SPINE_VERTEXEFFECT_H_
|
||||||
|
|
||||||
#define SPINE_MAJOR_VERSION 4
|
#define SPINE_MAJOR_VERSION 4
|
||||||
#define SPINE_MINOR_VERSION 1
|
#define SPINE_MINOR_VERSION 2
|
||||||
#define SPINE_VERSION_STRING "4.1"
|
#define SPINE_VERSION_STRING "4.2"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -2194,7 +2194,7 @@ spInheritTimeline *spInheritTimeline_create(int framesCount, int boneIndex) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spInheritTimeline_setFrame(spDrawOrderTimeline *self, int frame, float time, spInherit inherit) {
|
void spInheritTimeline_setFrame(spInheritTimeline *self, int frame, float time, spInherit inherit) {
|
||||||
frame *= 2;
|
frame *= 2;
|
||||||
self->super.frames->items[frame] = time;
|
self->super.frames->items[frame] = time;
|
||||||
self->super.frames->items[frame + 1] = inherit;
|
self->super.frames->items[frame + 1] = inherit;
|
||||||
@ -2857,6 +2857,6 @@ spPhysicsConstraintResetTimeline *spPhysicsConstraintResetTimeline_create(int fr
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spPhysicsResetTimeline_setFrame(spPhysicsConstraintResetTimeline *self, int frame, float time) {
|
void spPhysicsConstraintResetTimeline_setFrame(spPhysicsConstraintResetTimeline *self, int frame, float time) {
|
||||||
self->super.frames->items[frame] = time;
|
self->super.frames->items[frame] = time;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,7 +71,9 @@ void spBone_updateWorldTransform(spBone *self) {
|
|||||||
void spBone_updateWorldTransformWith(spBone *self, float x, float y, float rotation, float scaleX, float scaleY,
|
void spBone_updateWorldTransformWith(spBone *self, float x, float y, float rotation, float scaleX, float scaleY,
|
||||||
float shearX, float shearY) {
|
float shearX, float shearY) {
|
||||||
float pa, pb, pc, pd;
|
float pa, pb, pc, pd;
|
||||||
spBone *parent = self->parent;
|
float sx = self->skeleton->scaleX;
|
||||||
|
float sy = self->skeleton->scaleY * (spBone_isYDown() ? -1 : 1);
|
||||||
|
spBone *parent = self->parent;
|
||||||
|
|
||||||
self->ax = x;
|
self->ax = x;
|
||||||
self->ay = y;
|
self->ay = y;
|
||||||
@ -82,14 +84,14 @@ void spBone_updateWorldTransformWith(spBone *self, float x, float y, float rotat
|
|||||||
self->ashearY = shearY;
|
self->ashearY = shearY;
|
||||||
|
|
||||||
if (!parent) { /* Root bone. */
|
if (!parent) { /* Root bone. */
|
||||||
float sx = self->skeleton->scaleX;
|
|
||||||
float sy = self->skeleton->scaleY;
|
|
||||||
float rx = (rotation + shearX) * DEG_RAD;
|
float rx = (rotation + shearX) * DEG_RAD;
|
||||||
float ry = (rotation + 90 + shearY) * DEG_RAD;
|
float ry = (rotation + 90 + shearY) * DEG_RAD;
|
||||||
self->a = COS(rx) * scaleX * sx;
|
self->a = COS(rx) * scaleX * sx;
|
||||||
self->b = COS(ry) * scaleY * sx;
|
self->b = COS(ry) * scaleY * sx;
|
||||||
self->c = SIN(rx) * scaleX * sy;
|
self->c = SIN(rx) * scaleX * sy;
|
||||||
self->d = SIN(ry) * scaleY * sy;
|
self->d = SIN(ry) * scaleY * sy;
|
||||||
|
self->worldX = x * sx + self->skeleton->x;
|
||||||
|
self->worldY = y * sy + self->skeleton->y;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,8 +131,8 @@ void spBone_updateWorldTransformWith(spBone *self, float x, float y, float rotat
|
|||||||
float prx;
|
float prx;
|
||||||
if (s > 0.0001f) {
|
if (s > 0.0001f) {
|
||||||
s = ABS(pa * pd - pb * pc) / s;
|
s = ABS(pa * pd - pb * pc) / s;
|
||||||
pa /= self->skeleton->scaleX;
|
pa /= sx;
|
||||||
pc /= self->skeleton->scaleY;
|
pc /= sy;
|
||||||
pb = pc * s;
|
pb = pc * s;
|
||||||
pd = pa * s;
|
pd = pa * s;
|
||||||
prx = ATAN2DEG(pc, pa);
|
prx = ATAN2DEG(pc, pa);
|
||||||
@ -156,10 +158,10 @@ void spBone_updateWorldTransformWith(spBone *self, float x, float y, float rotat
|
|||||||
rotation *= DEG_RAD;
|
rotation *= DEG_RAD;
|
||||||
float cosine = COS(rotation);
|
float cosine = COS(rotation);
|
||||||
float sine = SIN(rotation);
|
float sine = SIN(rotation);
|
||||||
float za = (pa * cosine + pb * sine) / self->skeleton->scaleX;
|
float za = (pa * cosine + pb * sine) / sx;
|
||||||
float zc = (pc * cosine + pd * sine) / self->skeleton->scaleY;
|
float zc = (pc * cosine + pd * sine) / sy;
|
||||||
float s = SQRT(za * za + zc * zc);
|
float s = SQRT(za * za + zc * zc);
|
||||||
if (self->data->inherit == SP_INHERIT_NOSCALE && (pa * pd - pb * pc < 0) != (self->skeleton->scaleX < 0 != self->skeleton->scaleY < 0))
|
if (self->data->inherit == SP_INHERIT_NOSCALE && (pa * pd - pb * pc < 0) != (sx < 0 != sy < 0))
|
||||||
s = -s;
|
s = -s;
|
||||||
rotation = PI / 2 + ATAN2(zc, za);
|
rotation = PI / 2 + ATAN2(zc, za);
|
||||||
float zb = COS(rotation) * s;
|
float zb = COS(rotation) * s;
|
||||||
@ -177,10 +179,10 @@ void spBone_updateWorldTransformWith(spBone *self, float x, float y, float rotat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self->a *= self->skeleton->scaleX;
|
self->a *= sx;
|
||||||
self->b *= self->skeleton->scaleX;
|
self->b *= sx;
|
||||||
self->c *= self->skeleton->scaleY;
|
self->c *= sy;
|
||||||
self->d *= self->skeleton->scaleY;
|
self->d *= sy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spBone_setToSetupPose(spBone *self) {
|
void spBone_setToSetupPose(spBone *self) {
|
||||||
@ -223,6 +225,8 @@ void spBone_updateAppliedTransform(spBone *self) {
|
|||||||
float s, sa, sc;
|
float s, sa, sc;
|
||||||
float cosine, sine;
|
float cosine, sine;
|
||||||
|
|
||||||
|
float yDownScale = spBone_isYDown() ? -1 : 1;
|
||||||
|
|
||||||
spBone *parent = self->parent;
|
spBone *parent = self->parent;
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
self->ax = self->worldX - self->skeleton->x;
|
self->ax = self->worldX - self->skeleton->x;
|
||||||
@ -252,9 +256,9 @@ void spBone_updateAppliedTransform(spBone *self) {
|
|||||||
case SP_INHERIT_NOROTATIONORREFLECTION: {
|
case SP_INHERIT_NOROTATIONORREFLECTION: {
|
||||||
s = ABS(pa * pd - pb * pc) / (pa * pa + pc * pc);
|
s = ABS(pa * pd - pb * pc) / (pa * pa + pc * pc);
|
||||||
sa = pa / self->skeleton->scaleX;
|
sa = pa / self->skeleton->scaleX;
|
||||||
sc = pc / self->skeleton->scaleY;
|
sc = pc / self->skeleton->scaleY * yDownScale;
|
||||||
pb = -sc * s * self->skeleton->scaleX;
|
pb = -sc * s * self->skeleton->scaleX;
|
||||||
pd = sa * s * self->skeleton->scaleY;
|
pd = sa * s * self->skeleton->scaleY * yDownScale;
|
||||||
pid = 1 / (pa * pd - pb * pc);
|
pid = 1 / (pa * pd - pb * pc);
|
||||||
ia = pd * pid;
|
ia = pd * pid;
|
||||||
ib = pb * pid;
|
ib = pb * pid;
|
||||||
@ -265,14 +269,14 @@ void spBone_updateAppliedTransform(spBone *self) {
|
|||||||
float r = self->rotation * DEG_RAD;
|
float r = self->rotation * DEG_RAD;
|
||||||
cosine = COS(r), sine = SIN(r);
|
cosine = COS(r), sine = SIN(r);
|
||||||
pa = (pa * cosine + pb * sine) / self->skeleton->scaleX;
|
pa = (pa * cosine + pb * sine) / self->skeleton->scaleX;
|
||||||
pc = (pc * cosine + pd * sine) / self->skeleton->scaleY;
|
pc = (pc * cosine + pd * sine) / self->skeleton->scaleY * yDownScale;
|
||||||
s = SQRT(pa * pa + pc * pc);
|
s = SQRT(pa * pa + pc * pc);
|
||||||
if (s > 0.00001) s = 1 / s;
|
if (s > 0.00001) s = 1 / s;
|
||||||
pa *= s;
|
pa *= s;
|
||||||
pc *= s;
|
pc *= s;
|
||||||
s = SQRT(pa * pa + pc * pc);
|
s = SQRT(pa * pa + pc * pc);
|
||||||
if (self->inherit == SP_INHERIT_NOSCALE &&
|
if (self->inherit == SP_INHERIT_NOSCALE &&
|
||||||
pid < 0 != (self->skeleton->scaleX < 0 != self->skeleton->scaleY < 0))
|
pid < 0 != (self->skeleton->scaleX < 0 != (self->skeleton->scaleY * yDownScale) < 0))
|
||||||
s = -s;
|
s = -s;
|
||||||
r = PI / 2 + ATAN2(pc, pa);
|
r = PI / 2 + ATAN2(pc, pa);
|
||||||
pb = COS(r) * s;
|
pb = COS(r) * s;
|
||||||
|
|||||||
@ -268,6 +268,17 @@ int findPathConstraintIndex(spSkeletonJson *json, const spSkeletonData *skeleton
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int findPhysicsConstraintIndex(spSkeletonJson *json, const spSkeletonData *skeletonData, const spPhysicsConstraintData *constraint, spTimelineArray *timelines) {
|
||||||
|
if (constraint) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < skeletonData->physicsConstraintsCount; ++i)
|
||||||
|
if (skeletonData->physicsConstraints[i] == constraint) return i;
|
||||||
|
}
|
||||||
|
cleanUpTimelines(timelines);
|
||||||
|
_spSkeletonJson_setError(json, NULL, "Physics constraint not found: ", constraint->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static spAnimation *_spSkeletonJson_readAnimation(spSkeletonJson *self, Json *root, spSkeletonData *skeletonData) {
|
static spAnimation *_spSkeletonJson_readAnimation(spSkeletonJson *self, Json *root, spSkeletonData *skeletonData) {
|
||||||
spTimelineArray *timelines = spTimelineArray_create(8);
|
spTimelineArray *timelines = spTimelineArray_create(8);
|
||||||
|
|
||||||
@ -277,6 +288,7 @@ static spAnimation *_spSkeletonJson_readAnimation(spSkeletonJson *self, Json *ro
|
|||||||
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 *physics = Json_getItem(root, "physics");
|
||||||
Json *attachmentsJson = Json_getItem(root, "attachments");
|
Json *attachmentsJson = Json_getItem(root, "attachments");
|
||||||
Json *drawOrderJson = Json_getItem(root, "drawOrder");
|
Json *drawOrderJson = Json_getItem(root, "drawOrder");
|
||||||
Json *events = Json_getItem(root, "events");
|
Json *events = Json_getItem(root, "events");
|
||||||
@ -516,8 +528,29 @@ static spAnimation *_spSkeletonJson_readAnimation(spSkeletonJson *self, Json *ro
|
|||||||
spShearXTimeline *timeline = spShearXTimeline_create(frames, frames, boneIndex);
|
spShearXTimeline *timeline = spShearXTimeline_create(frames, frames, boneIndex);
|
||||||
spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, 1));
|
spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, 1));
|
||||||
} else if (strcmp(timelineMap->name, "sheary") == 0) {
|
} else if (strcmp(timelineMap->name, "sheary") == 0) {
|
||||||
spShearYTimeline *timeline = spShearYTimeline_create(frames, frames, boneIndex);
|
spShearYTimeline *timeline = spShearYTimeline_create(frames, frames, boneIndex);
|
||||||
spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, 1));
|
spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, 1));
|
||||||
|
} else if (strcmp(timelineMap->name, "inherit") == 0) {
|
||||||
|
spInheritTimeline *timeline = spInheritTimeline_create(frames, boneIndex);
|
||||||
|
keyMap = timelineMap->child;
|
||||||
|
for (frame = 0;; frame++) {
|
||||||
|
float time = Json_getFloat(keyMap, "time", 0);
|
||||||
|
const char *value = Json_getString(keyMap, "value", "normal");
|
||||||
|
spInherit inherit = SP_INHERIT_NORMAL;
|
||||||
|
if (strcmp(value, "normal") == 0) inherit = SP_INHERIT_NORMAL;
|
||||||
|
else if (strcmp(value, "onlyTranslation") == 0)
|
||||||
|
inherit = SP_INHERIT_ONLYTRANSLATION;
|
||||||
|
else if (strcmp(value, "noRotationOrReflection") == 0)
|
||||||
|
inherit = SP_INHERIT_NOROTATIONORREFLECTION;
|
||||||
|
else if (strcmp(value, "noScale") == 0)
|
||||||
|
inherit = SP_INHERIT_NOSCALE;
|
||||||
|
else if (strcmp(value, "noScaleOrReflection") == 0)
|
||||||
|
inherit = SP_INHERIT_NOSCALEORREFLECTION;
|
||||||
|
spInheritTimeline_setFrame(timeline, frame, time, inherit);
|
||||||
|
nextMap = keyMap->next;
|
||||||
|
if (!nextMap) break;
|
||||||
|
}
|
||||||
|
spTimelineArray_add(timelines, SUPER(timeline));
|
||||||
} else {
|
} else {
|
||||||
cleanUpTimelines(timelines);
|
cleanUpTimelines(timelines);
|
||||||
_spSkeletonJson_setError(self, NULL, "Invalid timeline type for a bone: ", timelineMap->name);
|
_spSkeletonJson_setError(self, NULL, "Invalid timeline type for a bone: ", timelineMap->name);
|
||||||
@ -701,6 +734,50 @@ static spAnimation *_spSkeletonJson_readAnimation(spSkeletonJson *self, Json *ro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Physics constraint timelines. */
|
||||||
|
for (constraintMap = physics ? physics->child : 0; constraintMap; constraintMap = constraintMap->next) {
|
||||||
|
int index = -1;
|
||||||
|
if (constraintMap->name && strlen(constraintMap->name) > 0) {
|
||||||
|
spPhysicsConstraintData *constraint = spSkeletonData_findPhysicsConstraint(skeletonData, constraintMap->name);
|
||||||
|
index = findPhysicsConstraintIndex(self, skeletonData, constraint, timelines);
|
||||||
|
if (index == -1) return NULL;
|
||||||
|
}
|
||||||
|
for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) {
|
||||||
|
keyMap = timelineMap->child;
|
||||||
|
if (keyMap == NULL) continue;
|
||||||
|
const char *timelineName = timelineMap->name;
|
||||||
|
int frames = timelineMap->size;
|
||||||
|
if (strcmp(timelineName, "reset") == 0) {
|
||||||
|
spPhysicsConstraintResetTimeline *timeline = spPhysicsConstraintResetTimeline_create(frames, index);
|
||||||
|
for (frame = 0; keyMap != NULL; keyMap = keyMap->next, frame++) {
|
||||||
|
spPhysicsConstraintResetTimeline_setFrame(timeline, frame, Json_getFloat(keyMap, "time", 0));
|
||||||
|
}
|
||||||
|
spTimelineArray_add(timelines, SUPER(timeline));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
spCurveTimeline1 *timeline = NULL;
|
||||||
|
if (strcmp(timelineName, "inertia") == 0) {
|
||||||
|
timeline = spPhysicsConstraintTimeline_create(frames, frames, index, SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA);
|
||||||
|
} else if (strcmp(timelineName, "strength") == 0) {
|
||||||
|
timeline = spPhysicsConstraintTimeline_create(frames, frames, index, SP_TIMELINE_PHYSICSCONSTRAINT_STRENGTH);
|
||||||
|
} else if (strcmp(timelineName, "damping") == 0) {
|
||||||
|
timeline = spPhysicsConstraintTimeline_create(frames, frames, index, SP_TIMELINE_PHYSICSCONSTRAINT_DAMPING);
|
||||||
|
} else if (strcmp(timelineName, "mass") == 0) {
|
||||||
|
timeline = spPhysicsConstraintTimeline_create(frames, frames, index, SP_TIMELINE_PHYSICSCONSTRAINT_MASS);
|
||||||
|
} else if (strcmp(timelineName, "wind") == 0) {
|
||||||
|
timeline = spPhysicsConstraintTimeline_create(frames, frames, index, SP_TIMELINE_PHYSICSCONSTRAINT_WIND);
|
||||||
|
} else if (strcmp(timelineName, "gravity") == 0) {
|
||||||
|
timeline = spPhysicsConstraintTimeline_create(frames, frames, index, SP_TIMELINE_PHYSICSCONSTRAINT_GRAVITY);
|
||||||
|
} else if (strcmp(timelineName, "mix") == 0) {
|
||||||
|
timeline = spPhysicsConstraintTimeline_create(frames, frames, index, SP_TIMELINE_PHYSICSCONSTRAINT_MIX);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
spTimelineArray_add(timelines, readTimeline(keyMap, timeline, 0, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Attachment timelines. */
|
/* Attachment timelines. */
|
||||||
for (attachmentsMap = attachmentsJson ? attachmentsJson->child : 0; attachmentsMap; attachmentsMap = attachmentsMap->next) {
|
for (attachmentsMap = attachmentsJson ? attachmentsJson->child : 0; attachmentsMap; attachmentsMap = attachmentsMap->next) {
|
||||||
spSkin *skin = spSkeletonData_findSkin(skeletonData, attachmentsMap->name);
|
spSkin *skin = spSkeletonData_findSkin(skeletonData, attachmentsMap->name);
|
||||||
@ -964,10 +1041,38 @@ static int string_starts_with(const char *str, const char *needle) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char *json) {
|
spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char *json) {
|
||||||
int i, ii;
|
int i, ii;
|
||||||
spSkeletonData *skeletonData;
|
spSkeletonData *skeletonData;
|
||||||
Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *pathJson, *slots, *skins, *animations, *events;
|
Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *pathJson, *physics, *slots, *skins, *animations, *events;
|
||||||
_spSkeletonJson *internal = SUB_CAST(_spSkeletonJson, self);
|
_spSkeletonJson *internal = SUB_CAST(_spSkeletonJson, self);
|
||||||
|
|
||||||
FREE(self->error);
|
FREE(self->error);
|
||||||
@ -996,6 +1101,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
|||||||
skeletonData->y = Json_getFloat(skeleton, "y", 0);
|
skeletonData->y = Json_getFloat(skeleton, "y", 0);
|
||||||
skeletonData->width = Json_getFloat(skeleton, "width", 0);
|
skeletonData->width = Json_getFloat(skeleton, "width", 0);
|
||||||
skeletonData->height = Json_getFloat(skeleton, "height", 0);
|
skeletonData->height = Json_getFloat(skeleton, "height", 0);
|
||||||
|
skeletonData->referenceScale = Json_getFloat(skeleton, "referenceScale", 100) * self->scale;
|
||||||
skeletonData->fps = Json_getFloat(skeleton, "fps", 30);
|
skeletonData->fps = Json_getFloat(skeleton, "fps", 30);
|
||||||
skeletonData->imagesPath = Json_getString(skeleton, "images", 0);
|
skeletonData->imagesPath = Json_getString(skeleton, "images", 0);
|
||||||
if (skeletonData->imagesPath) {
|
if (skeletonData->imagesPath) {
|
||||||
@ -1016,7 +1122,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
|||||||
skeletonData->bones = MALLOC(spBoneData *, bones->size);
|
skeletonData->bones = MALLOC(spBoneData *, bones->size);
|
||||||
for (boneMap = bones->child, i = 0; boneMap; boneMap = boneMap->next, ++i) {
|
for (boneMap = bones->child, i = 0; boneMap; boneMap = boneMap->next, ++i) {
|
||||||
spBoneData *data;
|
spBoneData *data;
|
||||||
const char *transformMode;
|
const char *inherit;
|
||||||
const char *color;
|
const char *color;
|
||||||
|
|
||||||
spBoneData *parent = 0;
|
spBoneData *parent = 0;
|
||||||
@ -1039,22 +1145,30 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
|||||||
data->scaleY = Json_getFloat(boneMap, "scaleY", 1);
|
data->scaleY = Json_getFloat(boneMap, "scaleY", 1);
|
||||||
data->shearX = Json_getFloat(boneMap, "shearX", 0);
|
data->shearX = Json_getFloat(boneMap, "shearX", 0);
|
||||||
data->shearY = Json_getFloat(boneMap, "shearY", 0);
|
data->shearY = Json_getFloat(boneMap, "shearY", 0);
|
||||||
transformMode = Json_getString(boneMap, "transform", "normal");
|
inherit = Json_getString(boneMap, "inherit", "normal");
|
||||||
data->inherit = SP_INHERIT_NORMAL;
|
data->inherit = SP_INHERIT_NORMAL;
|
||||||
if (strcmp(transformMode, "normal") == 0) data->inherit = SP_INHERIT_NORMAL;
|
if (strcmp(inherit, "normal") == 0) data->inherit = SP_INHERIT_NORMAL;
|
||||||
else if (strcmp(transformMode, "onlyTranslation") == 0)
|
else if (strcmp(inherit, "onlyTranslation") == 0)
|
||||||
data->inherit = SP_INHERIT_ONLYTRANSLATION;
|
data->inherit = SP_INHERIT_ONLYTRANSLATION;
|
||||||
else if (strcmp(transformMode, "noRotationOrReflection") == 0)
|
else if (strcmp(inherit, "noRotationOrReflection") == 0)
|
||||||
data->inherit = SP_INHERIT_NOROTATIONORREFLECTION;
|
data->inherit = SP_INHERIT_NOROTATIONORREFLECTION;
|
||||||
else if (strcmp(transformMode, "noScale") == 0)
|
else if (strcmp(inherit, "noScale") == 0)
|
||||||
data->inherit = SP_INHERIT_NOSCALE;
|
data->inherit = SP_INHERIT_NOSCALE;
|
||||||
else if (strcmp(transformMode, "noScaleOrReflection") == 0)
|
else if (strcmp(inherit, "noScaleOrReflection") == 0)
|
||||||
data->inherit = SP_INHERIT_NOSCALEORREFLECTION;
|
data->inherit = SP_INHERIT_NOSCALEORREFLECTION;
|
||||||
data->skinRequired = Json_getInt(boneMap, "skin", 0) ? 1 : 0;
|
data->skinRequired = Json_getInt(boneMap, "skin", 0) ? 1 : 0;
|
||||||
|
|
||||||
color = Json_getString(boneMap, "color", 0);
|
color = Json_getString(boneMap, "color", 0);
|
||||||
if (color) toColor2(&data->color, color, -1);
|
if (color) toColor2(&data->color, color, -1);
|
||||||
|
|
||||||
|
data->icon = Json_getString(boneMap, "icon", "");
|
||||||
|
if (data->icon) {
|
||||||
|
char *tmp = NULL;
|
||||||
|
MALLOC_STR(tmp, data->icon);
|
||||||
|
data->icon = tmp;
|
||||||
|
}
|
||||||
|
data->visible = Json_getInt(boneMap, "visible", -1) ? -1 : 0;
|
||||||
|
|
||||||
skeletonData->bones[i] = data;
|
skeletonData->bones[i] = data;
|
||||||
skeletonData->bonesCount++;
|
skeletonData->bonesCount++;
|
||||||
}
|
}
|
||||||
@ -1079,7 +1193,14 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = spSlotData_create(i, Json_getString(slotMap, "name", 0), boneData);
|
char *pathName = NULL;
|
||||||
|
char *slotName = (char*)Json_getString(slotMap, "name", NULL);
|
||||||
|
int slash = string_lastIndexOf(slotName, '/');
|
||||||
|
if (slash != -1) {
|
||||||
|
pathName = string_substring(slotName, 0, slash);
|
||||||
|
slotName = string_substring(slotName, slash + 1, strlen(slotName));
|
||||||
|
}
|
||||||
|
data = spSlotData_create(i, slotName, boneData);
|
||||||
|
|
||||||
color = Json_getString(slotMap, "color", 0);
|
color = Json_getString(slotMap, "color", 0);
|
||||||
if (color) {
|
if (color) {
|
||||||
@ -1113,6 +1234,8 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
|||||||
data->blendMode = SP_BLEND_MODE_SCREEN;
|
data->blendMode = SP_BLEND_MODE_SCREEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->visible = Json_getInt(slotMap, "visible", -1);
|
||||||
|
data->path = pathName;
|
||||||
skeletonData->slots[i] = data;
|
skeletonData->slots[i] = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1284,6 +1407,54 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Physics constraints */
|
||||||
|
physics = Json_getItem(root, "physics");
|
||||||
|
if (physics) {
|
||||||
|
Json *constraintMap;
|
||||||
|
skeletonData->physicsConstraintsCount = physics->size;
|
||||||
|
skeletonData->physicsConstraints = MALLOC(spPhysicsConstraintData *, physics->size);
|
||||||
|
for (constraintMap = physics->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) {
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
spPhysicsConstraintData *data = spPhysicsConstraintData_create(
|
||||||
|
Json_getString(constraintMap, "name", 0));
|
||||||
|
data->order = Json_getInt(constraintMap, "order", 0);
|
||||||
|
data->skinRequired = Json_getInt(constraintMap, "skin", 0);
|
||||||
|
|
||||||
|
name = Json_getString(constraintMap, "bone", 0);
|
||||||
|
data->bone = spSkeletonData_findBone(skeletonData, name);
|
||||||
|
if (!data->bone) {
|
||||||
|
spSkeletonData_dispose(skeletonData);
|
||||||
|
_spSkeletonJson_setError(self, root, "Physics bone not found: ", name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->x = Json_getFloat(constraintMap, "x", 0);
|
||||||
|
data->y = Json_getFloat(constraintMap, "y", 0);
|
||||||
|
data->rotate = Json_getFloat(constraintMap, "rotate", 0);
|
||||||
|
data->scaleX = Json_getFloat(constraintMap, "scaleX", 0);
|
||||||
|
data->shearX = Json_getFloat(constraintMap, "shearX", 0);
|
||||||
|
data->limit = Json_getFloat(constraintMap, "limit", 5000) * self->scale;
|
||||||
|
data->step = 1.0f / Json_getInt(constraintMap, "fps", 60);
|
||||||
|
data->inertia = Json_getFloat(constraintMap, "inertia", 1);
|
||||||
|
data->strength = Json_getFloat(constraintMap, "strength", 100);
|
||||||
|
data->damping = Json_getFloat(constraintMap, "damping", 1);
|
||||||
|
data->massInverse = 1.0f / Json_getFloat(constraintMap, "mass", 1);
|
||||||
|
data->wind = Json_getFloat(constraintMap, "wind", 0);
|
||||||
|
data->gravity = Json_getFloat(constraintMap, "gravity", 0);
|
||||||
|
data->mix = Json_getFloat(constraintMap, "mix", 1);
|
||||||
|
data->inertiaGlobal = Json_getInt(constraintMap, "inertiaGlobal", 0);
|
||||||
|
data->strengthGlobal = Json_getInt(constraintMap, "strengthGlobal", 0);
|
||||||
|
data->dampingGlobal = Json_getInt(constraintMap, "dampingGlobal", 0);
|
||||||
|
data->massGlobal = Json_getInt(constraintMap, "massGlobal", 0);
|
||||||
|
data->windGlobal = Json_getInt(constraintMap, "windGlobal", 0);
|
||||||
|
data->gravityGlobal = Json_getInt(constraintMap, "gravityGlobal", 0);
|
||||||
|
data->mixGlobal = Json_getInt(constraintMap, "mixGlobal", 0);
|
||||||
|
|
||||||
|
skeletonData->physicsConstraints[i] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Skins. */
|
/* Skins. */
|
||||||
skins = Json_getItem(root, "skins");
|
skins = Json_getItem(root, "skins");
|
||||||
if (skins) {
|
if (skins) {
|
||||||
@ -1351,6 +1522,20 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skinPart = Json_getItem(skinMap, "physics");
|
||||||
|
if (skinPart) {
|
||||||
|
for (skinPart = skinPart->child; skinPart; skinPart = skinPart->next) {
|
||||||
|
spPhysicsConstraintData *constraint = spSkeletonData_findPhysicsConstraint(skeletonData,
|
||||||
|
skinPart->valueString);
|
||||||
|
if (!constraint) {
|
||||||
|
spSkeletonData_dispose(skeletonData);
|
||||||
|
_spSkeletonJson_setError(self, root, "Skin physics constraint not found: ", skinPart->valueString);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
spPhysicsConstraintDataArray_add(skin->physicsConstraints, constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
skeletonData->skins[skeletonData->skinsCount++] = skin;
|
skeletonData->skins[skeletonData->skinsCount++] = skin;
|
||||||
if (strcmp(skin->name, "default") == 0) skeletonData->defaultSkin = skin;
|
if (strcmp(skin->name, "default") == 0) skeletonData->defaultSkin = skin;
|
||||||
|
|
||||||
|
|||||||
@ -95,13 +95,13 @@ void testcase(void func(spSkeletonData *skeletonData, spAtlas *atlas),
|
|||||||
float scale) {
|
float scale) {
|
||||||
spAtlas *atlas = spAtlas_createFromFile(atlasName, 0);
|
spAtlas *atlas = spAtlas_createFromFile(atlasName, 0);
|
||||||
|
|
||||||
spSkeletonData *skeletonData = readSkeletonBinaryData(binaryName, atlas, scale);
|
spSkeletonData *skeletonData = readSkeletonJsonData(jsonName, atlas, scale);
|
||||||
func(skeletonData, atlas);
|
func(skeletonData, atlas);
|
||||||
spSkeletonData_dispose(skeletonData);
|
spSkeletonData_dispose(skeletonData);
|
||||||
|
|
||||||
skeletonData = readSkeletonJsonData(jsonName, atlas, scale);
|
// skeletonData = readSkeletonBinaryData(binaryName, atlas, scale);
|
||||||
func(skeletonData, atlas);
|
// func(skeletonData, atlas);
|
||||||
spSkeletonData_dispose(skeletonData);
|
// spSkeletonData_dispose(skeletonData);
|
||||||
|
|
||||||
spAtlas_dispose(atlas);
|
spAtlas_dispose(atlas);
|
||||||
|
|
||||||
@ -648,7 +648,148 @@ void testMixAndMatch(spSkeletonData *skeletonData, spAtlas *atlas) {
|
|||||||
spSkin_dispose(skin);
|
spSkin_dispose(skin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cloudpot(spSkeletonData *skeletonData, spAtlas *atlas) {
|
||||||
|
UNUSED(atlas);
|
||||||
|
|
||||||
|
|
||||||
|
SkeletonDrawable *drawable = new SkeletonDrawable(skeletonData);
|
||||||
|
drawable->timeScale = 1;
|
||||||
|
drawable->setUsePremultipliedAlpha(true);
|
||||||
|
|
||||||
|
spSkeleton *skeleton = drawable->skeleton;
|
||||||
|
skeleton->x = 320;
|
||||||
|
skeleton->y = 480;
|
||||||
|
spSkeleton_updateWorldTransform(skeleton, SP_PHYSICS_UPDATE);
|
||||||
|
spAnimationState_setAnimationByName(drawable->state, 0, "playing-in-the-rain", true);
|
||||||
|
|
||||||
|
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - cloudpot");
|
||||||
|
window.setFramerateLimit(60);
|
||||||
|
sf::Event event;
|
||||||
|
sf::Clock deltaClock;
|
||||||
|
|
||||||
|
while (window.isOpen()) {
|
||||||
|
while (window.pollEvent(event))
|
||||||
|
if (event.type == sf::Event::Closed) window.close();
|
||||||
|
|
||||||
|
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||||
|
deltaClock.restart();
|
||||||
|
|
||||||
|
drawable->update(delta, SP_PHYSICS_UPDATE);
|
||||||
|
|
||||||
|
window.clear();
|
||||||
|
window.draw(*drawable);
|
||||||
|
window.display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sack(spSkeletonData *skeletonData, spAtlas *atlas) {
|
||||||
|
UNUSED(atlas);
|
||||||
|
|
||||||
|
|
||||||
|
SkeletonDrawable *drawable = new SkeletonDrawable(skeletonData);
|
||||||
|
drawable->timeScale = 1;
|
||||||
|
drawable->setUsePremultipliedAlpha(true);
|
||||||
|
|
||||||
|
spSkeleton *skeleton = drawable->skeleton;
|
||||||
|
skeleton->x = 320;
|
||||||
|
skeleton->y = 480;
|
||||||
|
spSkeleton_updateWorldTransform(skeleton, SP_PHYSICS_UPDATE);
|
||||||
|
spAnimationState_setAnimationByName(drawable->state, 0, "walk", true);
|
||||||
|
|
||||||
|
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - sack");
|
||||||
|
window.setFramerateLimit(60);
|
||||||
|
sf::Event event;
|
||||||
|
sf::Clock deltaClock;
|
||||||
|
|
||||||
|
while (window.isOpen()) {
|
||||||
|
while (window.pollEvent(event))
|
||||||
|
if (event.type == sf::Event::Closed) window.close();
|
||||||
|
|
||||||
|
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||||
|
deltaClock.restart();
|
||||||
|
|
||||||
|
drawable->update(delta, SP_PHYSICS_UPDATE);
|
||||||
|
|
||||||
|
window.clear();
|
||||||
|
window.draw(*drawable);
|
||||||
|
window.display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void snowglobe(spSkeletonData *skeletonData, spAtlas *atlas) {
|
||||||
|
UNUSED(atlas);
|
||||||
|
|
||||||
|
|
||||||
|
SkeletonDrawable *drawable = new SkeletonDrawable(skeletonData);
|
||||||
|
drawable->timeScale = 1;
|
||||||
|
drawable->setUsePremultipliedAlpha(true);
|
||||||
|
|
||||||
|
spSkeleton *skeleton = drawable->skeleton;
|
||||||
|
skeleton->x = 320;
|
||||||
|
skeleton->y = 480;
|
||||||
|
spSkeleton_updateWorldTransform(skeleton, SP_PHYSICS_UPDATE);
|
||||||
|
spAnimationState_setAnimationByName(drawable->state, 0, "shake", true);
|
||||||
|
|
||||||
|
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - snowglobe");
|
||||||
|
window.setFramerateLimit(60);
|
||||||
|
sf::Event event;
|
||||||
|
sf::Clock deltaClock;
|
||||||
|
|
||||||
|
while (window.isOpen()) {
|
||||||
|
while (window.pollEvent(event))
|
||||||
|
if (event.type == sf::Event::Closed) window.close();
|
||||||
|
|
||||||
|
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||||
|
deltaClock.restart();
|
||||||
|
|
||||||
|
drawable->update(delta, SP_PHYSICS_UPDATE);
|
||||||
|
|
||||||
|
window.clear();
|
||||||
|
window.draw(*drawable);
|
||||||
|
window.display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void celestialCircus(spSkeletonData *skeletonData, spAtlas *atlas) {
|
||||||
|
UNUSED(atlas);
|
||||||
|
|
||||||
|
|
||||||
|
SkeletonDrawable *drawable = new SkeletonDrawable(skeletonData);
|
||||||
|
drawable->timeScale = 1;
|
||||||
|
drawable->setUsePremultipliedAlpha(true);
|
||||||
|
|
||||||
|
spSkeleton *skeleton = drawable->skeleton;
|
||||||
|
skeleton->x = 320;
|
||||||
|
skeleton->y = 480;
|
||||||
|
spSkeleton_updateWorldTransform(skeleton, SP_PHYSICS_UPDATE);
|
||||||
|
spAnimationState_setAnimationByName(drawable->state, 0, "swing", true);
|
||||||
|
|
||||||
|
sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - celestrial circus");
|
||||||
|
window.setFramerateLimit(60);
|
||||||
|
sf::Event event;
|
||||||
|
sf::Clock deltaClock;
|
||||||
|
|
||||||
|
while (window.isOpen()) {
|
||||||
|
while (window.pollEvent(event))
|
||||||
|
if (event.type == sf::Event::Closed) window.close();
|
||||||
|
|
||||||
|
float delta = deltaClock.getElapsedTime().asSeconds();
|
||||||
|
deltaClock.restart();
|
||||||
|
|
||||||
|
drawable->update(delta, SP_PHYSICS_UPDATE);
|
||||||
|
|
||||||
|
window.clear();
|
||||||
|
window.draw(*drawable);
|
||||||
|
window.display();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
testcase(cloudpot, "data/cloud-pot.json", "data/cloud-pot.skel", "data/cloud-pot-pma.atlas", 0.2);
|
||||||
|
testcase(sack, "data/sack-pro.json", "data/sack-pro.skel", "data/sack-pma.atlas", 0.2f);
|
||||||
|
testcase(celestialCircus, "data/celestial-circus-pro.json", "data/celestial-circus-pro.skel", "data/celestial-circus-pma.atlas", 0.2f);
|
||||||
|
testcase(snowglobe, "data/snowglobe-pro.json", "data/snowglobe-pro.skel", "data/snowglobe-pma.atlas", 0.2f);
|
||||||
|
testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
|
||||||
testcase(dragon, "data/dragon-ess.json", "data/dragon-ess.skel", "data/dragon-pma.atlas", 0.6f);
|
testcase(dragon, "data/dragon-ess.json", "data/dragon-ess.skel", "data/dragon-pma.atlas", 0.6f);
|
||||||
testcase(ikDemo, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
|
testcase(ikDemo, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
|
||||||
testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
|
testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
|
||||||
@ -658,7 +799,6 @@ int main() {
|
|||||||
testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f);
|
testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f);
|
||||||
testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f);
|
testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f);
|
||||||
testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 0.2f);
|
testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 0.2f);
|
||||||
testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
|
|
||||||
testcase(goblins, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f);
|
testcase(goblins, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f);
|
||||||
testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f);
|
testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f);
|
||||||
testcase(testSkinsApi, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f);
|
testcase(testSkinsApi, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user