mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Merge branch 'spine-c-3.5' into spine-3.5
This commit is contained in:
commit
7460418885
@ -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
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -39,7 +39,7 @@ extern "C" {
|
||||
|
||||
typedef struct spIkConstraintData {
|
||||
const char* const name;
|
||||
|
||||
int order;
|
||||
int bonesCount;
|
||||
spBoneData** bones;
|
||||
|
||||
|
||||
@ -52,6 +52,7 @@ typedef enum {
|
||||
|
||||
typedef struct spPathConstraintData {
|
||||
const char* const name;
|
||||
int order;
|
||||
int bonesCount;
|
||||
spBoneData** const bones;
|
||||
spSlotData* target;
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -39,6 +39,7 @@ extern "C" {
|
||||
|
||||
typedef struct spTransformConstraintData {
|
||||
const char* const name;
|
||||
int order;
|
||||
int bonesCount;
|
||||
spBoneData** const bones;
|
||||
spBoneData* target;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user