diff --git a/spine-c/include/spine/Bone.h b/spine-c/include/spine/Bone.h index 3aa022d4c..4ecf9d24c 100644 --- a/spine-c/include/spine/Bone.h +++ b/spine-c/include/spine/Bone.h @@ -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 diff --git a/spine-c/include/spine/BoneData.h b/spine-c/include/spine/BoneData.h index 36cab745c..244a50e0d 100644 --- a/spine-c/include/spine/BoneData.h +++ b/spine-c/include/spine/BoneData.h @@ -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 }; diff --git a/spine-c/include/spine/IkConstraint.h b/spine-c/include/spine/IkConstraint.h index 784f24efa..aef3c26a8 100644 --- a/spine-c/include/spine/IkConstraint.h +++ b/spine-c/include/spine/IkConstraint.h @@ -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; diff --git a/spine-c/include/spine/IkConstraintData.h b/spine-c/include/spine/IkConstraintData.h index f1dfe68ca..65c2f08b7 100644 --- a/spine-c/include/spine/IkConstraintData.h +++ b/spine-c/include/spine/IkConstraintData.h @@ -39,7 +39,7 @@ extern "C" { typedef struct spIkConstraintData { const char* const name; - + int order; int bonesCount; spBoneData** bones; diff --git a/spine-c/include/spine/PathConstraintData.h b/spine-c/include/spine/PathConstraintData.h index 983b1e087..31c9fad20 100644 --- a/spine-c/include/spine/PathConstraintData.h +++ b/spine-c/include/spine/PathConstraintData.h @@ -52,6 +52,7 @@ typedef enum { typedef struct spPathConstraintData { const char* const name; + int order; int bonesCount; spBoneData** const bones; spSlotData* target; diff --git a/spine-c/include/spine/Skeleton.h b/spine-c/include/spine/Skeleton.h index 58297f15e..c8c1c005c 100644 --- a/spine-c/include/spine/Skeleton.h +++ b/spine-c/include/spine/Skeleton.h @@ -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), diff --git a/spine-c/include/spine/TransformConstraintData.h b/spine-c/include/spine/TransformConstraintData.h index 4c4c4ce58..f7b8f211f 100644 --- a/spine-c/include/spine/TransformConstraintData.h +++ b/spine-c/include/spine/TransformConstraintData.h @@ -39,6 +39,7 @@ extern "C" { typedef struct spTransformConstraintData { const char* const name; + int order; int bonesCount; spBoneData** const bones; spBoneData* target; diff --git a/spine-c/src/spine/Bone.c b/spine-c/src/spine/Bone.c index d1539b2f5..aa5841894 100644 --- a/spine-c/src/spine/Bone.c +++ b/spine-c/src/spine/Bone.c @@ -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). *

- * 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; } } diff --git a/spine-c/src/spine/BoneData.c b/spine-c/src/spine/BoneData.c index 60ed86822..5933571ed 100644 --- a/spine-c/src/spine/BoneData.c +++ b/spine-c/src/spine/BoneData.c @@ -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; } diff --git a/spine-c/src/spine/IkConstraint.c b/spine-c/src/spine/IkConstraint.c index f0fc107e7..037070967 100644 --- a/spine-c/src/spine/IkConstraint.c +++ b/spine-c/src/spine/IkConstraint.c @@ -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); } } diff --git a/spine-c/src/spine/PathConstraint.c b/spine-c/src/spine/PathConstraint.c index 0eb5af40a..1a2f0eda6 100644 --- a/spine-c/src/spine/PathConstraint.c +++ b/spine-c/src/spine/PathConstraint.c @@ -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; } } diff --git a/spine-c/src/spine/RegionAttachment.c b/spine-c/src/spine/RegionAttachment.c index e9363266f..50b1fc833 100644 --- a/spine-c/src/spine/RegionAttachment.c +++ b/spine-c/src/spine/RegionAttachment.c @@ -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; diff --git a/spine-c/src/spine/Skeleton.c b/spine-c/src/spine/Skeleton.c index 4af6db685..f174ea15d 100644 --- a/spine-c/src/spine/Skeleton.c +++ b/spine-c/src/spine/Skeleton.c @@ -32,7 +32,6 @@ #include #include #include -#include 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; diff --git a/spine-c/src/spine/SkeletonBinary.c b/spine-c/src/spine/SkeletonBinary.c index 54f14c8bb..9e7a3cd16 100644 --- a/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/src/spine/SkeletonBinary.c @@ -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); diff --git a/spine-c/src/spine/SkeletonJson.c b/spine-c/src/spine/SkeletonJson.c index e42ed9e97..488b29052 100644 --- a/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/src/spine/SkeletonJson.c @@ -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; diff --git a/spine-c/src/spine/TransformConstraint.c b/spine-c/src/spine/TransformConstraint.c index 8b2e0e83d..d16d3b18e 100644 --- a/spine-c/src/spine/TransformConstraint.c +++ b/spine-c/src/spine/TransformConstraint.c @@ -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; } } diff --git a/spine-c/src/spine/VertexAttachment.c b/spine-c/src/spine/VertexAttachment.c index bc0cc0ccf..32357d3ca 100644 --- a/spine-c/src/spine/VertexAttachment.c +++ b/spine-c/src/spine/VertexAttachment.c @@ -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) { diff --git a/spine-sfml/example/main.cpp b/spine-sfml/example/main.cpp index a76c20244..306149b37 100644 --- a/spine-sfml/example/main.cpp +++ b/spine-sfml/example/main.cpp @@ -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; }