Merge branch 'spine-c-3.5' into spine-3.5

This commit is contained in:
badlogic 2016-10-20 13:13:19 +02:00
commit 7460418885
18 changed files with 375 additions and 264 deletions

View File

@ -47,11 +47,11 @@ struct spBone {
int childrenCount;
spBone** const children;
float x, y, rotation, scaleX, scaleY, shearX, shearY;
float appliedRotation;
float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY;
int /*bool*/ appliedValid;
float const a, b, worldX;
float const c, d, worldY;
float const worldSignX, worldSignY;
int/*bool*/ sorted;
@ -62,11 +62,11 @@ struct spBone {
parent(0),
childrenCount(0), children(0),
x(0), y(0), rotation(0), scaleX(0), scaleY(0),
appliedRotation(0),
ax(0), ay(0), arotation(0), ascaleX(0), ascaleY(0), ashearX(0), ashearY(0),
appliedValid(0),
a(0), b(0), worldX(0),
c(0), d(0), worldY(0),
worldSignX(0), worldSignY(0),
sorted(0) {
}
@ -93,7 +93,7 @@ float spBone_getWorldScaleY (spBone* self);
float spBone_worldToLocalRotationX (spBone* self);
float spBone_worldToLocalRotationY (spBone* self);
void spBone_rotateWorld (spBone* self, float degrees);
void spBone_updateLocalTransform (spBone* self);
void spBone_updateAppliedTransform (spBone* self);
void spBone_worldToLocal (spBone* self, float worldX, float worldY, float* localX, float* localY);
void spBone_localToWorld (spBone* self, float localX, float localY, float* worldX, float* worldY);
@ -114,7 +114,7 @@ typedef spBone Bone;
#define Bone_worldToLocalRotationX(...) spBone_worldToLocalRotationX(__VA_ARGS__)
#define Bone_worldToLocalRotationY(...) spBone_worldToLocalRotationY(__VA_ARGS__)
#define Bone_rotateWorld(...) spBone_rotateWorld(__VA_ARGS__)
#define Bone_updateLocalTransform(...) spBone_updateLocalTransform(__VA_ARGS__)
#define Bone_updateAppliedTransform(...) spBone_updateAppliedTransform(__VA_ARGS__)
#define Bone_worldToLocal(...) spBone_worldToLocal(__VA_ARGS__)
#define Bone_localToWorld(...) spBone_localToWorld(__VA_ARGS__)
#endif

View File

@ -35,6 +35,14 @@
extern "C" {
#endif
typedef enum {
SP_TRANSFORMMODE_NORMAL,
SP_TRANSFORMMODE_ONLYTRANSLATION,
SP_TRANSFORMMODE_NOROTATIONORREFLECTION,
SP_TRANSFORMMODE_NOSCALE,
SP_TRANSFORMMODE_NOSCALEORREFLECTION
} spTransformMode;
typedef struct spBoneData spBoneData;
struct spBoneData {
const int index;
@ -42,7 +50,7 @@ struct spBoneData {
spBoneData* const parent;
float length;
float x, y, rotation, scaleX, scaleY, shearX, shearY;
int/*bool*/inheritRotation, inheritScale;
spTransformMode transformMode;
#ifdef __cplusplus
spBoneData() :
@ -54,7 +62,7 @@ struct spBoneData {
rotation(0),
scaleX(0), scaleY(0),
shearX(0), shearY(0),
inheritRotation(0), inheritScale(0) {
transformMode(SP_TRANSFORMMODE_NORMAL) {
}
#endif
};

View File

@ -50,8 +50,6 @@ typedef struct spIkConstraint {
int bendDirection;
float mix;
int level;
#ifdef __cplusplus
spIkConstraint() :
data(0),
@ -59,8 +57,7 @@ typedef struct spIkConstraint {
bones(0),
target(0),
bendDirection(0),
mix(0),
level(0) {
mix(0) {
}
#endif
} spIkConstraint;

View File

@ -39,7 +39,7 @@ extern "C" {
typedef struct spIkConstraintData {
const char* const name;
int order;
int bonesCount;
spBoneData** bones;

View File

@ -52,6 +52,7 @@ typedef enum {
typedef struct spPathConstraintData {
const char* const name;
int order;
int bonesCount;
spBoneData** const bones;
spSlotData* target;

View File

@ -55,7 +55,6 @@ typedef struct spSkeleton {
int ikConstraintsCount;
spIkConstraint** ikConstraints;
spIkConstraint** ikConstraintsSorted;
int transformConstraintsCount;
spTransformConstraint** transformConstraints;
@ -81,7 +80,6 @@ typedef struct spSkeleton {
ikConstraintsCount(0),
ikConstraints(0),
ikConstraintsSorted(0),
transformConstraintsCount(0),
transformConstraints(0),

View File

@ -39,6 +39,7 @@ extern "C" {
typedef struct spTransformConstraintData {
const char* const name;
int order;
int bonesCount;
spBoneData** const bones;
spBoneData* target;

View File

@ -61,15 +61,24 @@ void spBone_updateWorldTransform (spBone* self) {
void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) {
float cosine, sine;
float rotationY = rotation + 90 + shearY;
float la = COS_DEG(rotation + shearX) * scaleX, lb = COS_DEG(rotationY) * scaleY;
float lc = SIN_DEG(rotation + shearX) * scaleX, ld = SIN_DEG(rotationY) * scaleY;
float pa, pb, pc, pd, temp;
float pa, pb, pc, pd;
spBone* parent = self->parent;
CONST_CAST(float, self->appliedRotation) = rotation;
self->ax = x;
self->ay = y;
self->arotation = rotation;
self->ascaleX = scaleX;
self->ascaleY = scaleY;
self->ashearX = shearX;
self->ashearY = shearY;
self->appliedValid = 1;
if (!parent) { /* Root bone. */
float rotationY = rotation + 90 + shearY;
float la = COS_DEG(rotation + shearX) * scaleX;
float lb = COS_DEG(rotationY) * scaleY;
float lc = SIN_DEG(rotation + shearX) * scaleX;
float ld = SIN_DEG(rotationY) * scaleY;
if (self->skeleton->flipX) {
x = -x;
la = -la;
@ -84,10 +93,8 @@ void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rota
CONST_CAST(float, self->b) = lb;
CONST_CAST(float, self->c) = lc;
CONST_CAST(float, self->d) = ld;
CONST_CAST(float, self->worldX) = x;
CONST_CAST(float, self->worldY) = y;
CONST_CAST(float, self->worldSignX) = scaleX > 0 ? 1.0f : -1.0f;
CONST_CAST(float, self->worldSignY) = scaleY > 0 ? 1.0f : -1.0f;
CONST_CAST(float, self->worldX) = x + self->skeleton->x;
CONST_CAST(float, self->worldY) = y + self->skeleton->y;
return;
}
@ -98,84 +105,91 @@ void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rota
CONST_CAST(float, self->worldX) = pa * x + pb * y + parent->worldX;
CONST_CAST(float, self->worldY) = pc * x + pd * y + parent->worldY;
CONST_CAST(float, self->worldSignX) = parent->worldSignX * (scaleX > 0 ? 1 : -1);
CONST_CAST(float, self->worldSignY) = parent->worldSignY * (scaleY > 0 ? 1 : -1);
if (self->data->inheritRotation && self->data->inheritScale) {
CONST_CAST(float, self->a) = pa * la + pb * lc;
CONST_CAST(float, self->b) = pa * lb + pb * ld;
CONST_CAST(float, self->c) = pc * la + pd * lc;
CONST_CAST(float, self->d) = pc * lb + pd * ld;
} else {
if (self->data->inheritRotation) { /* No scale inheritance. */
pa = 1;
pb = 0;
pc = 0;
pd = 1;
do {
cosine = COS_DEG(parent->appliedRotation); sine = SIN_DEG(parent->appliedRotation);
temp = pa * cosine + pb * sine;
pb = pb * cosine - pa * sine;
pa = temp;
temp = pc * cosine + pd * sine;
pd = pd * cosine - pc * sine;
pc = temp;
if (!parent->data->inheritRotation) break;
parent = parent->parent;
} while (parent);
switch (self->data->transformMode) {
case SP_TRANSFORMMODE_NORMAL: {
float rotationY = rotation + 90 + shearY;
float la = COS_DEG(rotation + shearX) * scaleX;
float lb = COS_DEG(rotationY) * scaleY;
float lc = SIN_DEG(rotation + shearX) * scaleX;
float ld = SIN_DEG(rotationY) * scaleY;
CONST_CAST(float, self->a) = pa * la + pb * lc;
CONST_CAST(float, self->b) = pa * lb + pb * ld;
CONST_CAST(float, self->c) = pc * la + pd * lc;
CONST_CAST(float, self->d) = pc * lb + pd * ld;
} else if (self->data->inheritScale) { /* No rotation inheritance. */
pa = 1;
pb = 0;
pc = 0;
pd = 1;
do {
float za, zb, zc, zd;
float psx = parent->scaleX, psy = parent->scaleY;
cosine = COS_DEG(parent->appliedRotation);
sine = SIN_DEG(parent->appliedRotation);
za = cosine * psx; zb = sine * psy; zc = sine * psx; zd = cosine * psy;
temp = pa * za + pb * zc;
pb = pb * zd - pa * zb;
pa = temp;
temp = pc * za + pd * zc;
pd = pd * zd - pc * zb;
pc = temp;
if (psx >= 0) sine = -sine;
temp = pa * cosine + pb * sine;
pb = pb * cosine - pa * sine;
pa = temp;
temp = pc * cosine + pd * sine;
pd = pd * cosine - pc * sine;
pc = temp;
if (!parent->data->inheritScale) break;
parent = parent->parent;
} while (parent);
CONST_CAST(float, self->a) = pa * la + pb * lc;
CONST_CAST(float, self->b) = pa * lb + pb * ld;
return;
}
case SP_TRANSFORMMODE_ONLYTRANSLATION: {
float rotationY = rotation + 90 + shearY;
CONST_CAST(float, self->a) = COS_DEG(rotation + shearX) * scaleX;
CONST_CAST(float, self->b) = COS_DEG(rotationY) * scaleY;
CONST_CAST(float, self->c) = SIN_DEG(rotation + shearX) * scaleX;
CONST_CAST(float, self->d) = SIN_DEG(rotationY) * scaleY;
break;
}
case SP_TRANSFORMMODE_NOROTATIONORREFLECTION: {
float s = pa * pa + pc * pc;
float prx, rx, ry, la, lb, lc, ld;
if (s > 0.0001f) {
s = ABS(pa * pd - pb * pc) / s;
pb = pc * s;
pd = pa * s;
prx = ATAN2(pc, pa) * RAD_DEG;
} else {
pa = 0;
pc = 0;
prx = 90 - ATAN2(pd, pb) * RAD_DEG;
}
rx = rotation + shearX - prx;
ry = rotation + shearY - prx + 90;
la = COS_DEG(rx) * scaleX;
lb = COS_DEG(ry) * scaleY;
lc = SIN_DEG(rx) * scaleX;
ld = SIN_DEG(ry) * scaleY;
CONST_CAST(float, self->a) = pa * la - pb * lc;
CONST_CAST(float, self->b) = pa * lb - pb * ld;
CONST_CAST(float, self->c) = pc * la + pd * lc;
CONST_CAST(float, self->d) = pc * lb + pd * ld;
} else {
CONST_CAST(float, self->a) = la;
CONST_CAST(float, self->b) = lb;
CONST_CAST(float, self->c) = lc;
CONST_CAST(float, self->d) = ld;
break;
}
if (self->skeleton->flipX) {
CONST_CAST(float, self->a) = -self->a;
CONST_CAST(float, self->b) = -self->b;
}
if (self->skeleton->flipY != yDown) {
CONST_CAST(float, self->c) = -self->c;
CONST_CAST(float, self->d) = -self->d;
case SP_TRANSFORMMODE_NOSCALE:
case SP_TRANSFORMMODE_NOSCALEORREFLECTION: {
float za, zc, s;
float r, zb, zd, la, lb, lc, ld;
cosine = COS_DEG(rotation); sine = SIN_DEG(rotation);
za = pa * cosine + pb * sine;
zc = pc * cosine + pd * sine;
s = SQRT(za * za + zc * zc);
if (s > 0.00001f) s = 1 / s;
za *= s;
zc *= s;
s = SQRT(za * za + zc * zc);
r = PI / 2 + atan2(zc, za);
zb = COS(r) * s;
zd = SIN(r) * s;
la = COS_DEG(shearX) * scaleX;
lb = COS_DEG(90 + shearY) * scaleY;
lc = SIN_DEG(shearX) * scaleX;
ld = SIN_DEG(90 + shearY) * scaleY;
CONST_CAST(float, self->a) = za * la + zb * lc;
CONST_CAST(float, self->b) = za * lb + zb * ld;
CONST_CAST(float, self->c) = zc * la + zd * lc;
CONST_CAST(float, self->d) = zc * lb + zd * ld;
if (self->data->transformMode != SP_TRANSFORMMODE_NOSCALEORREFLECTION ? pa * pd - pb * pc < 0 : self->skeleton->flipX != self->skeleton->flipY) {
CONST_CAST(float, self->b) = -self->b;
CONST_CAST(float, self->d) = -self->d;
}
return;
}
}
if (self->skeleton->flipX) {
CONST_CAST(float, self->a) = -self->a;
CONST_CAST(float, self->b) = -self->b;
}
if (self->skeleton->flipY != yDown) {
CONST_CAST(float, self->c) = -self->c;
CONST_CAST(float, self->d) = -self->d;
}
}
void spBone_setToSetupPose (spBone* self) {
@ -197,22 +211,22 @@ float spBone_getWorldRotationY (spBone* self) {
}
float spBone_getWorldScaleX (spBone* self) {
return SQRT(self->a * self->a + self->b * self->b) * self->worldSignX;
return SQRT(self->a * self->a + self->c * self->c);
}
float spBone_getWorldScaleY (spBone* self) {
return SQRT(self->c * self->c + self->d * self->d) * self->worldSignY;
return SQRT(self->b * self->b + self->d * self->d);
}
float spBone_worldToLocalRotationX (spBone* self) {
spBone* parent = self->parent;
if (!parent) return self->rotation;
if (!parent) return self->arotation;
return ATAN2(parent->a * self->c - parent->c * self->a, parent->d * self->a - parent->b * self->c) * RAD_DEG;
}
float spBone_worldToLocalRotationY (spBone* self) {
spBone* parent = self->parent;
if (!parent) return self->rotation;
if (!parent) return self->arotation;
return ATAN2(parent->a * self->d - parent->c * self->b, parent->d * self->b - parent->b * self->d) * RAD_DEG;
}
@ -223,24 +237,25 @@ void spBone_rotateWorld (spBone* self, float degrees) {
CONST_CAST(float, self->b) = cosine * b - sine * d;
CONST_CAST(float, self->c) = sine * a + cosine * c;
CONST_CAST(float, self->d) = sine * b + cosine * d;
CONST_CAST(int, self->appliedValid) = 1;
}
/** Computes the local transform from the world transform. This can be useful to perform processing on the local transform
* after the world transform has been modified directly (eg, by a constraint).
/** Computes the individual applied transform values from the world transform. This can be useful to perform processing using
* the applied transform after the world transform has been modified directly (eg, by a constraint).
* <p>
* Some redundant information is lost by the world transform, such as -1,-1 scale versus 180 rotation. The computed local
* transform values may differ from the original values but are functionally the same. */
void spBone_updateLocalTransform (spBone* self) {
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */
void spBone_updateAppliedTransform (spBone* self) {
spBone* parent = self->parent;
self->appliedValid = 1;
if (!parent) {
float det = self->a * self->d - self->b * self->c;
self->x = self->worldX;
self->y = self->worldY;
self->rotation = ATAN2(self->c, self->a) * RAD_DEG;
self->scaleX = SQRT(self->a * self->a + self->c * self->c);
self->scaleY = SQRT(self->b * self->b + self->d * self->d);
self->shearX = 0;
self->shearY = ATAN2(self->a * self->b + self->c * self->d, det) * RAD_DEG;
self->ax = self->worldX;
self->ay = self->worldY;
self->arotation = ATAN2(self->c, self->a) * RAD_DEG;
self->ascaleX = SQRT(self->a * self->a + self->c * self->c);
self->ascaleY = SQRT(self->b * self->b + self->d * self->d);
self->ashearX = 0;
self->ashearY = ATAN2(self->a * self->b + self->c * self->d, self->a * self->d - self->b * self->c) * RAD_DEG;
} else {
float pa = parent->a, pb = parent->b, pc = parent->c, pd = parent->d;
float pid = 1 / (pa * pd - pb * pc);
@ -253,22 +268,21 @@ void spBone_updateLocalTransform (spBone* self) {
float rb = ia * self->b - ib * self->d;
float rc = id * self->c - ic * self->a;
float rd = id * self->d - ic * self->b;
self->x = (dx * pd * pid - dy * pb * pid);
self->y = (dy * pa * pid - dx * pc * pid);
self->shearX = 0;
self->scaleX = SQRT(ra * ra + rc * rc);
if (self->scaleX > 0.0001f) {
self->ax = (dx * pd * pid - dy * pb * pid);
self->ay = (dy * pa * pid - dx * pc * pid);
self->ashearX = 0;
self->ascaleX = SQRT(ra * ra + rc * rc);
if (self->ascaleX > 0.0001f) {
float det = ra * rd - rb * rc;
self->scaleY = det / self->scaleX;
self->shearY = ATAN2(ra * rb + rc * rd, det) * RAD_DEG;
self->rotation = ATAN2(rc, ra) * RAD_DEG;
self->ascaleY = det / self->ascaleX;
self->ashearY = ATAN2(ra * rb + rc * rd, det) * RAD_DEG;
self->arotation = ATAN2(rc, ra) * RAD_DEG;
} else {
self->scaleX = 0;
self->scaleY = SQRT(rb * rb + rd * rd);
self->shearY = 0;
self->rotation = 90 - ATAN2(rd, rb) * RAD_DEG;
self->ascaleX = 0;
self->ascaleY = SQRT(rb * rb + rd * rd);
self->ashearY = 0;
self->arotation = 90 - ATAN2(rd, rb) * RAD_DEG;
}
self->appliedRotation = self->rotation;
}
}

View File

@ -38,8 +38,7 @@ spBoneData* spBoneData_create (int index, const char* name, spBoneData* parent)
CONST_CAST(spBoneData*, self->parent) = parent;
self->scaleX = 1;
self->scaleY = 1;
self->inheritRotation = 1;
self->inheritScale = 1;
self->transformMode = SP_TRANSFORMMODE_NORMAL;
return self;
}

View File

@ -67,21 +67,23 @@ void spIkConstraint_apply(spIkConstraint *self) {
}
void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float alpha) {
spBone* pp = bone->parent;
float id = 1 / (pp->a * pp->d - pp->b * pp->c);
float x = targetX - pp->worldX, y = targetY - pp->worldY;
float tx = (x * pp->d - y * pp->b) * id - bone->x, ty = (y * pp->a - x * pp->c) * id - bone->y;
float rotationIK = ATAN2(ty, tx) * RAD_DEG - bone->shearX - bone->rotation;
if (bone->scaleX < 0) rotationIK += 180;
spBone* p = bone->parent;
float id, x, y, tx, ty, rotationIK;
if (!bone->appliedValid) spBone_updateAppliedTransform(bone);
id = 1 / (p->a * p->d - p->b * p->c);
x = targetX - p->worldX, y = targetY - p->worldY;
tx = (x * p->d - y * p->b) * id - bone->ax; ty = (y * p->a - x * p->c) * id - bone->ay;
rotationIK = ATAN2(ty, tx) * RAD_DEG - bone->ashearX - bone->arotation;
if (bone->ascaleX < 0) rotationIK += 180;
if (rotationIK > 180) rotationIK -= 360;
else if (rotationIK < -180) rotationIK += 360;
spBone_updateWorldTransformWith(bone, bone->x, bone->y, bone->rotation + rotationIK * alpha, bone->scaleX,
bone->scaleY, bone->shearX, bone->shearY);
spBone_updateWorldTransformWith(bone, bone->ax, bone->ay, bone->arotation + rotationIK * alpha, bone->ascaleX,
bone->ascaleY, bone->ashearX, bone->ashearY);
}
void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDir, float alpha) {
float px = parent->x, py = parent->y, psx = parent->scaleX, psy = parent->scaleY;
float cx = child->x, cy, csx = child->scaleX, cwx, cwy;
float px, py, psx, psy;
float cx, cy, csx, cwx, cwy;
int o1, o2, s2, u;
spBone* pp = parent->parent;
float tx, ty, dx, dy, l1, l2, a1, a2, r;
@ -90,6 +92,9 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float
spBone_updateWorldTransform(child);
return;
}
if (!parent->appliedValid) spBone_updateAppliedTransform(parent);
if (!child->appliedValid) spBone_updateAppliedTransform(child);
px = parent->ax; py = parent->ay; psx = parent->ascaleX; psy = parent->ascaleY; csx = child->ascaleX;
if (psx < 0) {
psx = -psx;
o1 = 180;
@ -108,13 +113,14 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float
} else
o2 = 0;
r = psx - psy;
cx = child->ax;
u = (r < 0 ? -r : r) <= 0.0001f;
if (!u) {
cy = 0;
cwx = parent->a * cx + parent->worldX;
cwy = parent->c * cx + parent->worldY;
} else {
cy = child->y;
cy = child->ay;
cwx = parent->a * cx + parent->b * cy + parent->worldX;
cwy = parent->c * cx + parent->d * cy + parent->worldY;
}
@ -198,13 +204,13 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float
}
outer: {
float os = ATAN2(cy, cx) * s2;
a1 = (a1 - os) * RAD_DEG + o1 - parent->rotation;
a1 = (a1 - os) * RAD_DEG + o1 - parent->arotation;
if (a1 > 180) a1 -= 360;
else if (a1 < -180) a1 += 360;
spBone_updateWorldTransformWith(parent, px, py, parent->rotation + a1 * alpha, parent->scaleX, parent->scaleY, 0, 0);
a2 = ((a2 + os) * RAD_DEG - child->shearX) * s2 + o2 - child->rotation;
spBone_updateWorldTransformWith(parent, px, py, parent->rotation + a1 * alpha, parent->ascaleX, parent->ascaleY, 0, 0);
a2 = ((a2 + os) * RAD_DEG - child->ashearX) * s2 + o2 - child->arotation;
if (a2 > 180) a2 -= 360;
else if (a2 < -180) a2 += 360;
spBone_updateWorldTransformWith(child, cx, cy, child->rotation + a2 * alpha, child->scaleX, child->scaleY, child->shearX, child->shearY);
spBone_updateWorldTransformWith(child, cx, cy, child->arotation + a2 * alpha, child->ascaleX, child->ascaleY, child->ashearX, child->ashearY);
}
}

View File

@ -77,8 +77,7 @@ void spPathConstraint_apply (spPathConstraint* self) {
float length, x, y, dx, dy, s;
float* spaces, *lengths, *positions;
float spacing;
spSkeleton* skeleton;
float skeletonX, skeletonY, boneX, boneY, offsetRotation;
float boneX, boneY, offsetRotation;
int/*bool*/tip;
float rotateMix = self->rotateMix, translateMix = self->translateMix;
int/*bool*/ translate = translateMix > 0, rotate = rotateMix > 0;
@ -127,14 +126,12 @@ void spPathConstraint_apply (spPathConstraint* self) {
positions = spPathConstraint_computeWorldPositions(self, attachment, spacesCount, tangents,
data->positionMode == SP_POSITION_MODE_PERCENT, spacingMode == SP_SPACING_MODE_PERCENT);
skeleton = self->target->bone->skeleton;
skeletonX = skeleton->x, skeletonY = skeleton->y;
boneX = positions[0], boneY = positions[1], offsetRotation = self->data->offsetRotation;
tip = rotateMode == SP_ROTATE_MODE_CHAIN_SCALE && offsetRotation == 0;
for (i = 0, p = 3; i < boneCount; i++, p += 3) {
spBone* bone = bones[i];
CONST_CAST(float, bone->worldX) += (boneX - skeletonX - bone->worldX) * translateMix;
CONST_CAST(float, bone->worldY) += (boneY - skeletonY - bone->worldY) * translateMix;
CONST_CAST(float, bone->worldX) += (boneX - bone->worldX) * translateMix;
CONST_CAST(float, bone->worldY) += (boneY - bone->worldY) * translateMix;
x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
if (scale) {
length = lengths[i];
@ -174,6 +171,7 @@ void spPathConstraint_apply (spPathConstraint* self) {
CONST_CAST(float, bone->c) = sine * a + cosine * c;
CONST_CAST(float, bone->d) = sine * b + cosine * d;
}
CONST_CAST(int, bone->appliedValid) = -1;
}
}

View File

@ -101,7 +101,7 @@ void spRegionAttachment_updateOffset (spRegionAttachment* self) {
void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, spBone* bone, float* vertices) {
const float* offset = self->offset;
float x = bone->skeleton->x + bone->worldX, y = bone->skeleton->y + bone->worldY;
float x = bone->worldX, y = bone->worldY;
vertices[SP_VERTEX_X1] = offset[SP_VERTEX_X1] * bone->a + offset[SP_VERTEX_Y1] * bone->b + x;
vertices[SP_VERTEX_Y1] = offset[SP_VERTEX_X1] * bone->c + offset[SP_VERTEX_Y1] * bone->d + y;
vertices[SP_VERTEX_X2] = offset[SP_VERTEX_X2] * bone->a + offset[SP_VERTEX_Y2] * bone->b + x;

View File

@ -32,7 +32,6 @@
#include <stdlib.h>
#include <string.h>
#include <spine/extension.h>
#include <spine/Skin.h>
typedef enum {
SP_UPDATE_BONE, SP_UPDATE_IK_CONSTRAINT, SP_UPDATE_PATH_CONSTRAINT, SP_UPDATE_TRANSFORM_CONSTRAINT
@ -49,6 +48,10 @@ typedef struct {
int updateCacheCount;
int updateCacheCapacity;
_spUpdate* updateCache;
int updateCacheResetCount;
int updateCacheResetCapacity;
spBone** updateCacheReset;
} _spSkeleton;
spSkeleton* spSkeleton_create (spSkeletonData* data) {
@ -65,15 +68,15 @@ spSkeleton* spSkeleton_create (spSkeletonData* data) {
for (i = 0; i < self->bonesCount; ++i) {
spBoneData* boneData = self->data->bones[i];
spBone* bone;
spBone* newBone;
if (!boneData->parent)
bone = spBone_create(boneData, self, 0);
newBone = spBone_create(boneData, self, 0);
else {
spBone* parent = self->bones[boneData->parent->index];
bone = spBone_create(boneData, self, parent);
newBone = spBone_create(boneData, self, parent);
++childrenCounts[boneData->parent->index];
}
self->bones[i] = bone;
self->bones[i] = newBone;
}
for (i = 0; i < self->bonesCount; ++i) {
spBoneData* boneData = self->data->bones[i];
@ -101,7 +104,6 @@ spSkeleton* spSkeleton_create (spSkeletonData* data) {
self->ikConstraintsCount = data->ikConstraintsCount;
self->ikConstraints = MALLOC(spIkConstraint*, self->ikConstraintsCount);
self->ikConstraintsSorted = MALLOC(spIkConstraint*, self->ikConstraintsCount);
for (i = 0; i < self->data->ikConstraintsCount; ++i)
self->ikConstraints[i] = spIkConstraint_create(self->data->ikConstraints[i], self);
@ -129,6 +131,7 @@ void spSkeleton_dispose (spSkeleton* self) {
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
FREE(internal->updateCache);
FREE(internal->updateCacheReset);
for (i = 0; i < self->bonesCount; ++i)
spBone_dispose(self->bones[i]);
@ -141,7 +144,6 @@ void spSkeleton_dispose (spSkeleton* self) {
for (i = 0; i < self->ikConstraintsCount; ++i)
spIkConstraint_dispose(self->ikConstraints[i]);
FREE(self->ikConstraints);
FREE(self->ikConstraintsSorted);
for (i = 0; i < self->transformConstraintsCount; ++i)
spTransformConstraint_dispose(self->transformConstraints[i]);
@ -167,6 +169,15 @@ static void _addToUpdateCache(_spSkeleton* const internal, _spUpdateType type, v
++internal->updateCacheCount;
}
static void _addToUpdateCacheReset(_spSkeleton* const internal, spBone* bone) {
if (internal->updateCacheResetCount == internal->updateCacheResetCapacity) {
internal->updateCacheResetCapacity *= 2;
internal->updateCacheReset = realloc(internal->updateCacheReset, sizeof(spBone*) * internal->updateCacheResetCapacity);
}
internal->updateCacheReset[internal->updateCacheResetCount] = bone;
++internal->updateCacheResetCount;
}
static void _sortBone(_spSkeleton* const internal, spBone* bone) {
if (bone->sorted) return;
if (bone->parent) _sortBone(internal, bone->parent);
@ -185,7 +196,7 @@ static void _sortPathConstraintAttachmentBones(_spSkeleton* const internal, spAt
_sortBone(internal, slotBone);
else {
spBone** bones = internal->super.bones;
int i = 0;
int i = 0, n;
while (i < pathBonesCount) {
int boneCount = pathBones[i++];
int n;
@ -212,113 +223,145 @@ static void _sortReset(spBone** bones, int bonesCount) {
}
}
static void _sortIkConstraint (_spSkeleton* const internal, spIkConstraint* constraint) {
int /*bool*/ contains = 0;
int i;
spBone* target = constraint->target;
spBone** constrained;
spBone* parent;
_sortBone(internal, target);
constrained = constraint->bones;
parent = constrained[0];
_sortBone(internal, parent);
if (constraint->bonesCount > 1) {
spBone* child = constrained[constraint->bonesCount - 1];
contains = 0;
for (i = 0; i < internal->updateCacheCount; i++) {
_spUpdate update = internal->updateCache[i];
if (update.object == child) {
contains = -1;
break;
}
}
if (!contains)
_addToUpdateCacheReset(internal, child);
}
_addToUpdateCache(internal, SP_UPDATE_IK_CONSTRAINT, constraint);
_sortReset(parent->children, parent->childrenCount);
constrained[constraint->bonesCount-1]->sorted = 1;
}
static void _sortPathConstraint(_spSkeleton* const internal, spPathConstraint* constraint) {
spSlot* slot = constraint->target;
int slotIndex = slot->data->index;
spBone* slotBone = slot->bone;
int ii, nn, boneCount;
spAttachment* attachment;
spBone** constrained;
spSkeleton* skeleton = SUPER_CAST(spSkeleton, internal);
if (skeleton->skin) _sortPathConstraintAttachment(internal, skeleton->skin, slotIndex, slotBone);
if (skeleton->data->defaultSkin && skeleton->data->defaultSkin != skeleton->skin)
_sortPathConstraintAttachment(internal, skeleton->data->defaultSkin, slotIndex, slotBone);
for (ii = 0, nn = skeleton->data->skinsCount; ii < nn; ii++)
_sortPathConstraintAttachment(internal, skeleton->data->skins[ii], slotIndex, slotBone);
attachment = slot->attachment;
if (attachment->type == SP_ATTACHMENT_PATH) _sortPathConstraintAttachmentBones(internal, attachment, slotBone);
constrained = constraint->bones;
boneCount = constraint->bonesCount;
for (ii = 0; ii < boneCount; ii++)
_sortBone(internal, constrained[ii]);
_addToUpdateCache(internal, SP_UPDATE_PATH_CONSTRAINT, constraint);
for (ii = 0; ii < boneCount; ii++)
_sortReset(constrained[ii]->children, constrained[ii]->childrenCount);
for (ii = 0; ii < boneCount; ii++)
constrained[ii]->sorted = 1;
}
static void _sortTransformConstraint(_spSkeleton* const internal, spTransformConstraint* constraint) {
int ii, boneCount;
spBone** constrained;
_sortBone(internal, constraint->target);
constrained = constraint->bones;
boneCount = constraint->bonesCount;
for (ii = 0; ii < boneCount; ii++)
_sortBone(internal, constrained[ii]);
_addToUpdateCache(internal, SP_UPDATE_TRANSFORM_CONSTRAINT, constraint);
for (ii = 0; ii < boneCount; ii++)
_sortReset(constrained[ii]->children, constrained[ii]->childrenCount);
for (ii = 0; ii < boneCount; ii++)
constrained[ii]->sorted = 1;
}
void spSkeleton_updateCache (spSkeleton* self) {
int i, ii, n, nn, level;
int i, ii;
spBone** bones;
spIkConstraint** ikConstraints;
spPathConstraint** pathConstraints;
spTransformConstraint** transformConstraints;
int ikCount, transformCount, pathCount, constraintCount;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
internal->updateCacheCapacity = self->bonesCount + self->ikConstraintsCount + self->transformConstraintsCount + self->pathConstraintsCount;
internal->updateCacheCapacity = self->bonesCount + self->ikConstraintsCount + self->transformConstraintsCount + self->pathConstraintsCount;
FREE(internal->updateCache);
internal->updateCache = MALLOC(_spUpdate, internal->updateCacheCapacity);
internal->updateCacheCount = 0;
internal->updateCacheResetCapacity = self->bonesCount;
FREE(internal->updateCacheReset);
internal->updateCacheReset = MALLOC(spBone*, internal->updateCacheResetCapacity);
internal->updateCacheResetCount = 0;
bones = self->bones;
for (i = 0; i < self->bonesCount; ++i)
bones[i]->sorted = 0;
/* IK first, lowest hierarchy depth first. */
if (self->ikConstraintsSorted) FREE(self->ikConstraintsSorted);
self->ikConstraintsSorted = MALLOC(spIkConstraint*, self->ikConstraintsCount);
ikConstraints = self->ikConstraintsSorted;
for (i = 0; i < self->ikConstraintsCount; ++i)
ikConstraints[i] = self->ikConstraints[i];
for (i = 0; i < self->ikConstraintsCount; ++i) {
spIkConstraint* ik = ikConstraints[i];
spBone* bone = ik->bones[0]->parent;
for (level = 0; bone; ++level)
bone = bone->parent;
ik->level = level;
}
for (i = 1; i < self->ikConstraintsCount; ++i) {
spIkConstraint* ik = ikConstraints[i];
level = ik->level;
for (ii = i - 1; ii >= 0; --ii) {
spIkConstraint* other = ikConstraints[ii];
if (other->level < level) break;
ikConstraints[ii + 1] = other;
}
ikConstraints[ii + 1] = ik;
}
for (i = 0; i < self->ikConstraintsCount; ++i) {
spBone** constrained;
spBone* parent;
spIkConstraint* constraint = ikConstraints[i];
spBone* target = constraint->target;
_sortBone(internal, target);
constrained = constraint->bones;
parent = constrained[0];
_sortBone(internal, parent);
_addToUpdateCache(internal, SP_UPDATE_IK_CONSTRAINT, constraint);
_sortReset(parent->children, parent->childrenCount);
constrained[constraint->bonesCount - 1]->sorted = 1;
}
pathConstraints = self->pathConstraints;
for (i = 0, n = self->pathConstraintsCount; i < n; i++) {
spAttachment* attachment;
spBone** constrained;
int boneCount;
spPathConstraint* constraint = pathConstraints[i];
spSlot* slot = constraint->target;
int slotIndex = slot->data->index;
spBone* slotBone = slot->bone;
if (self->skin) _sortPathConstraintAttachment(internal, self->skin, slotIndex, slotBone);
if (self->data->defaultSkin && self->data->defaultSkin != self->skin)
_sortPathConstraintAttachment(internal, self->data->defaultSkin, slotIndex, slotBone);
for (ii = 0, nn = self->data->skinsCount; ii < nn; ii++)
_sortPathConstraintAttachment(internal, self->data->skins[ii], slotIndex, slotBone);
attachment = slot->attachment;
if (attachment->type == SP_ATTACHMENT_PATH) _sortPathConstraintAttachmentBones(internal, attachment, slotBone);
constrained = constraint->bones;
boneCount = constraint->bonesCount;
for (ii = 0; ii < boneCount; ii++)
_sortBone(internal, constrained[ii]);
_addToUpdateCache(internal, SP_UPDATE_PATH_CONSTRAINT, constraint);
for (ii = 0; ii < boneCount; ii++)
_sortReset(constrained[ii]->children, constrained[ii]->childrenCount);
for (ii = 0; ii < boneCount; ii++)
constrained[ii]->sorted = 1;
}
ikConstraints = self->ikConstraints;
transformConstraints = self->transformConstraints;
for (i = 0, n = self->transformConstraintsCount; i < n; ++i) {
spTransformConstraint* constraint = transformConstraints[i];
spBone** constrained = constraint->bones;
pathConstraints = self->pathConstraints;
ikCount = self->ikConstraintsCount; transformCount = self->transformConstraintsCount; pathCount = self->pathConstraintsCount;
constraintCount = ikCount + transformCount + pathCount;
_sortBone(internal, constraint->target);
for (ii = 0; ii < constraint->bonesCount; ++ii)
_sortBone(internal, constrained[ii]);
_addToUpdateCache(internal, SP_UPDATE_TRANSFORM_CONSTRAINT, constraint);
for (ii = 0; ii < constraint->bonesCount; ++ii) {
spBone* bone = constrained[ii];
_sortReset(bone->children, bone->childrenCount);
i = 0;
outer:
for (; i < constraintCount; i++) {
for (ii = 0; ii < ikCount; ii++) {
spIkConstraint* ikConstraint = ikConstraints[ii];
if (ikConstraint->data->order == i) {
_sortIkConstraint(internal, ikConstraint);
i++;
goto outer;
}
}
for (ii = 0; ii < transformCount; ii++) {
spTransformConstraint* transformConstraint = transformConstraints[ii];
if (transformConstraint->data->order == i) {
_sortTransformConstraint(internal, transformConstraint);
i++;
goto outer;
}
}
for (ii = 0; ii < pathCount; ii++) {
spPathConstraint* pathConstraint = pathConstraints[ii];
if (pathConstraint->data->order == i) {
_sortPathConstraint(internal, pathConstraint);
i++;
goto outer;
}
}
for (ii = 0; ii < constraint->bonesCount; ++ii)
constrained[ii]->sorted = 1;
}
for (i = 0; i < self->bonesCount; ++i)
@ -328,6 +371,18 @@ void spSkeleton_updateCache (spSkeleton* self) {
void spSkeleton_updateWorldTransform (const spSkeleton* self) {
int i;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
spBone** updateCacheReset = internal->updateCacheReset;
for (i = 0; i < internal->updateCacheResetCount; i++) {
spBone* bone = updateCacheReset[i];
CONST_CAST(float, bone->ax) = bone->x;
CONST_CAST(float, bone->ay) = bone->y;
CONST_CAST(float, bone->arotation) = bone->rotation;
CONST_CAST(float, bone->ascaleX) = bone->scaleX;
CONST_CAST(float, bone->ascaleY) = bone->scaleY;
CONST_CAST(float, bone->ashearX) = bone->shearX;
CONST_CAST(float, bone->ashearY) = bone->shearY;
CONST_CAST(int, bone->appliedValid) = 1;
}
for (i = 0; i < internal->updateCacheCount; ++i) {
_spUpdate* update = internal->updateCache + i;

View File

@ -788,8 +788,8 @@ spSkin* spSkeletonBinary_readSkin(spSkeletonBinary* self, _dataInput* input,
int slotIndex = readVarint(input, 1);
for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) {
const char* name = readString(input);
spSkin_addAttachment(skin, slotIndex, name,
spSkeletonBinary_readAttachment(self, input, skin, slotIndex, name, nonessential));
spAttachment* attachment = spSkeletonBinary_readAttachment(self, input, skin, slotIndex, name, nonessential);
if (attachment) spSkin_addAttachment(skin, slotIndex, name, attachment);
FREE(name);
}
}
@ -842,13 +842,18 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const
nonessential = readBoolean(input);
if (nonessential) FREE(readString(input)); /* Skip images path. */
if (nonessential) {
/* Skip images path & fps */
readFloat(input);
FREE(readString(input));
}
/* Bones. */
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 */
@ -862,8 +867,14 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const
data->shearX = readFloat(input);
data->shearY = readFloat(input);
data->length = readFloat(input) * self->scale;
data->inheritRotation = readBoolean(input);
data->inheritScale = readBoolean(input);
mode = readVarint(input, 1);
switch (mode) {
case 0: data->transformMode = SP_TRANSFORMMODE_NORMAL; break;
case 1: data->transformMode = SP_TRANSFORMMODE_ONLYTRANSLATION; break;
case 2: data->transformMode = SP_TRANSFORMMODE_NOROTATIONORREFLECTION; break;
case 3: data->transformMode = SP_TRANSFORMMODE_NOSCALE; break;
case 4: data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; break;
}
if (nonessential) readInt(input); /* Skip bone color. */
skeletonData->bones[i] = data;
}
@ -890,6 +901,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const
const char* name = readString(input);
/* TODO Avoid copying of name */
spIkConstraintData* data = spIkConstraintData_create(name);
data->order = readVarint(input, 1);
FREE(name);
data->bonesCount = readVarint(input, 1);
data->bones = MALLOC(spBoneData*, data->bonesCount);
@ -909,6 +921,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const
const char* name = readString(input);
/* TODO Avoid copying of name */
spTransformConstraintData* data = spTransformConstraintData_create(name);
data->order = readVarint(input, 1);
FREE(name);
data->bonesCount = readVarint(input, 1);
CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount);
@ -935,6 +948,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const
const char* name = readString(input);
/* TODO Avoid copying of name */
spPathConstraintData* data = spPathConstraintData_create(name);
data->order = readVarint(input, 1);
FREE(name);
data->bonesCount = readVarint(input, 1);
CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount);

View File

@ -604,6 +604,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
skeletonData->bones = MALLOC(spBoneData*, bones->size);
for (boneMap = bones->child, i = 0; boneMap; boneMap = boneMap->next, ++i) {
spBoneData* data;
const char* transformMode;
spBoneData* parent = 0;
const char* parentName = Json_getString(boneMap, "parent", 0);
@ -625,8 +626,18 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
data->scaleY = Json_getFloat(boneMap, "scaleY", 1);
data->shearX = Json_getFloat(boneMap, "shearX", 0);
data->shearY = Json_getFloat(boneMap, "shearY", 0);
data->inheritRotation = Json_getInt(boneMap, "inheritRotation", 1);
data->inheritScale = Json_getInt(boneMap, "inheritScale", 1);
transformMode = Json_getString(boneMap, "transform", "normal");
data->transformMode = SP_TRANSFORMMODE_NORMAL;
if (strcmp(transformMode, "normal") == 0)
data->transformMode = SP_TRANSFORMMODE_NORMAL;
if (strcmp(transformMode, "onlyTranslation") == 0)
data->transformMode = SP_TRANSFORMMODE_ONLYTRANSLATION;
if (strcmp(transformMode, "noRotationOrReflection") == 0)
data->transformMode = SP_TRANSFORMMODE_NOROTATIONORREFLECTION;
if (strcmp(transformMode, "noScale") == 0)
data->transformMode = SP_TRANSFORMMODE_NOSCALE;
if (strcmp(transformMode, "noScaleOrReflection") == 0)
data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION;
skeletonData->bones[i] = data;
skeletonData->bonesCount++;
@ -688,6 +699,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
const char* targetName;
spIkConstraintData* data = spIkConstraintData_create(Json_getString(constraintMap, "name", 0));
data->order = Json_getInt(constraintMap, "order", 0);
boneMap = Json_getItem(constraintMap, "bones");
data->bonesCount = boneMap->size;
@ -726,6 +738,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
const char* name;
spTransformConstraintData* data = spTransformConstraintData_create(Json_getString(constraintMap, "name", 0));
data->order = Json_getInt(constraintMap, "order", 0);
boneMap = Json_getItem(constraintMap, "bones");
data->bonesCount = boneMap->size;
@ -774,6 +787,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
const char* item;
spPathConstraintData* data = spPathConstraintData_create(Json_getString(constraintMap, "name", 0));
data->order = Json_getInt(constraintMap, "order", 0);
boneMap = Json_getItem(constraintMap, "bones");
data->bonesCount = boneMap->size;

View File

@ -57,11 +57,13 @@ void spTransformConstraint_apply (spTransformConstraint* self) {
float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix;
spBone* target = self->target;
float ta = target->a, tb = target->b, tc = target->c, td = target->d;
int /*bool*/ modified;
int i;
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = self->bones[i];
modified = 0;
if (rotateMix > 0) {
if (rotateMix != 0) {
float a = bone->a, b = bone->b, c = bone->c, d = bone->d;
float r = ATAN2(tc, ta) - ATAN2(c, a) + self->data->offsetRotation * DEG_RAD;
float cosine, sine;
@ -74,26 +76,29 @@ void spTransformConstraint_apply (spTransformConstraint* self) {
CONST_CAST(float, bone->b) = cosine * b - sine * d;
CONST_CAST(float, bone->c) = sine * a + cosine * c;
CONST_CAST(float, bone->d) = sine * b + cosine * d;
modified = 1;
}
if (translateMix > 0) {
if (translateMix != 0) {
float x, y;
spBone_localToWorld(target, self->data->offsetX, self->data->offsetY, &x, &y);
CONST_CAST(float, bone->worldX) += (x - bone->worldX) * translateMix;
CONST_CAST(float, bone->worldY) += (y - bone->worldY) * translateMix;
modified = 1;
}
if (scaleMix > 0) {
float bs = SQRT(bone->a * bone->a + bone->c * bone->c);
float s = SQRT(bone->a * bone->a + bone->c * bone->c);
float ts = SQRT(ta * ta + tc * tc);
float s = bs > 0.00001f ? (bs + (ts - bs + self->data->offsetScaleX) * scaleMix) / bs : 0;
if (s > 0.00001f) s = (s + (ts - s + self->data->offsetScaleX) * scaleMix) / s;
CONST_CAST(float, bone->a) *= s;
CONST_CAST(float, bone->c) *= s;
bs = SQRT(bone->b * bone->b + bone->d * bone->d);
s = SQRT(bone->b * bone->b + bone->d * bone->d);
ts = SQRT(tb * tb + td * td);
s = bs > 0.00001f ? (bs + (ts - bs + self->data->offsetScaleY) * scaleMix) / bs : 0;
if (s > 0.00001f) s = (s + (ts - s + self->data->offsetScaleY) * scaleMix) / s;
CONST_CAST(float, bone->b) *= s;
CONST_CAST(float, bone->d) *= s;
modified = 1;
}
if (shearMix > 0) {
@ -106,6 +111,9 @@ void spTransformConstraint_apply (spTransformConstraint* self) {
r = by + (r + self->data->offsetShearY * DEG_RAD) * shearMix;
CONST_CAST(float, bone->b) = COS(r) * s;
CONST_CAST(float, bone->d) = SIN(r) * s;
modified = 1;
}
if (modified) CONST_CAST(int, bone->appliedValid) = 0;
}
}

View File

@ -43,7 +43,6 @@ void spVertexAttachment_computeWorldVertices (spVertexAttachment* self, spSlot*
void spVertexAttachment_computeWorldVertices1 (spVertexAttachment* self, int start, int count, spSlot* slot, float* worldVertices, int offset) {
spSkeleton* skeleton;
float x, y;
int deformLength;
float* deform;
float* vertices;
@ -51,8 +50,6 @@ void spVertexAttachment_computeWorldVertices1 (spVertexAttachment* self, int sta
count += offset;
skeleton = slot->bone->skeleton;
x = skeleton->x;
y = skeleton->y;
deformLength = slot->attachmentVerticesCount;
deform = slot->attachmentVertices;
vertices = self->vertices;
@ -60,10 +57,11 @@ void spVertexAttachment_computeWorldVertices1 (spVertexAttachment* self, int sta
if (!bones) {
spBone* bone;
int v, w;
float x, y;
if (deformLength > 0) vertices = deform;
bone = slot->bone;
x += bone->worldX;
y += bone->worldY;
x = bone->worldX;
y = bone->worldY;
for (v = start, w = offset; w < count; v += 2, w += 2) {
float vx = vertices[v], vy = vertices[v + 1];
worldVertices[w] = vx * bone->a + vy * bone->b + x;
@ -81,7 +79,7 @@ void spVertexAttachment_computeWorldVertices1 (spVertexAttachment* self, int sta
if (deformLength == 0) {
int w, b;
for (w = offset, b = skip * 3; w < count; w += 2) {
float wx = x, wy = y;
float wx = 0, wy = 0;
int n = bones[v++];
n += v;
for (; v < n; v++, b += 3) {
@ -96,7 +94,7 @@ void spVertexAttachment_computeWorldVertices1 (spVertexAttachment* self, int sta
} else {
int w, b, f;
for (w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) {
float wx = x, wy = y;
float wx = 0, wy = 0;
int n = bones[v++];
n += v;
for (; v < n; v++, b += 3, f += 2) {

View File

@ -294,7 +294,7 @@ void stretchyman (SkeletonData* skeletonData, Atlas* atlas) {
skeleton->flipX = false;
skeleton->flipY = false;
skeleton->x = 320;
skeleton->x = 100;
skeleton->y = 590;
Skeleton_updateWorldTransform(skeleton);
@ -353,6 +353,6 @@ int main () {
testcase(raptor, "data/raptor.json", "data/raptor.skel", "data/raptor.atlas", 0.5f);
testcase(spineboy, "data/spineboy.json", "data/spineboy.skel", "data/spineboy.atlas", 0.6f);
testcase(goblins, "data/goblins-mesh.json", "data/goblins-mesh.skel", "data/goblins.atlas", 1.4f);
testcase(stretchyman, "data/stretchyman.json", "data/stretchyman.skel", "data/stretchyman.atlas", 1.4f);
testcase(stretchyman, "data/stretchyman.json", "data/stretchyman.skel", "data/stretchyman.atlas", 0.6f);
return 0;
}