From 1fa5545f1982e7ce3df06dd755e023c47e47d4eb Mon Sep 17 00:00:00 2001 From: badlogic Date: Thu, 18 Mar 2021 14:44:38 +0100 Subject: [PATCH] [c] 4.0 porting, constraints & skeleton --- spine-c/spine-c/include/spine/Bone.h | 17 -- spine-c/spine-c/include/spine/IkConstraint.h | 2 +- .../spine-c/include/spine/PathConstraint.h | 7 +- .../include/spine/PathConstraintData.h | 5 +- .../include/spine/TransformConstraint.h | 4 +- .../include/spine/TransformConstraintData.h | 2 +- spine-c/spine-c/src/spine/IkConstraint.c | 8 +- spine-c/spine-c/src/spine/PathConstraint.c | 183 +++++++++++------- spine-c/spine-c/src/spine/Skeleton.c | 142 +++++++------- .../spine-c/src/spine/TransformConstraint.c | 158 +++++++-------- 10 files changed, 268 insertions(+), 260 deletions(-) diff --git a/spine-c/spine-c/include/spine/Bone.h b/spine-c/spine-c/include/spine/Bone.h index 32251d309..fd7272de5 100644 --- a/spine-c/spine-c/include/spine/Bone.h +++ b/spine-c/spine-c/include/spine/Bone.h @@ -55,23 +55,6 @@ struct spBone { int/*bool*/ sorted; int/*bool*/ active; - -#ifdef __cplusplus - spBone() : - data(0), - skeleton(0), - parent(0), - childrenCount(0), children(0), - x(0), y(0), rotation(0), scaleX(0), scaleY(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), - - sorted(0), active(0) { - } -#endif }; SP_API void spBone_setYDown (int/*bool*/yDown); diff --git a/spine-c/spine-c/include/spine/IkConstraint.h b/spine-c/spine-c/include/spine/IkConstraint.h index 18b154b08..662e54489 100644 --- a/spine-c/spine-c/include/spine/IkConstraint.h +++ b/spine-c/spine-c/include/spine/IkConstraint.h @@ -59,7 +59,7 @@ typedef struct spIkConstraint { SP_API spIkConstraint* spIkConstraint_create (spIkConstraintData* data, const struct spSkeleton* skeleton); SP_API void spIkConstraint_dispose (spIkConstraint* self); -SP_API void spIkConstraint_apply (spIkConstraint* self); +SP_API void spIkConstraint_update (spIkConstraint* self); SP_API void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, int /*boolean*/ compress, int /*boolean*/ stretch, int /*boolean*/ uniform, float alpha); SP_API void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, int /*boolean*/ stretch, float softness, float alpha); diff --git a/spine-c/spine-c/include/spine/PathConstraint.h b/spine-c/spine-c/include/spine/PathConstraint.h index 06f975ee4..9075d317d 100644 --- a/spine-c/spine-c/include/spine/PathConstraint.h +++ b/spine-c/spine-c/include/spine/PathConstraint.h @@ -47,7 +47,8 @@ typedef struct spPathConstraint { int bonesCount; spBone** const bones; spSlot* target; - float position, spacing, rotateMix, translateMix; + float position, spacing; + float mixRotate, mixX, mixY; int spacesCount; float* spaces; @@ -74,8 +75,8 @@ typedef struct spPathConstraint { SP_API spPathConstraint* spPathConstraint_create (spPathConstraintData* data, const struct spSkeleton* skeleton); SP_API void spPathConstraint_dispose (spPathConstraint* self); -SP_API void spPathConstraint_apply (spPathConstraint* self); -SP_API float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAttachment* path, int spacesCount, int/*bool*/ tangents, int/*bool*/percentPosition, int/**/percentSpacing); +SP_API void spPathConstraint_update (spPathConstraint* self); +SP_API float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAttachment* path, int spacesCount, int/*bool*/ tangents); #ifdef __cplusplus } diff --git a/spine-c/spine-c/include/spine/PathConstraintData.h b/spine-c/spine-c/include/spine/PathConstraintData.h index bb0b0708e..4a694d077 100644 --- a/spine-c/spine-c/include/spine/PathConstraintData.h +++ b/spine-c/spine-c/include/spine/PathConstraintData.h @@ -43,7 +43,7 @@ typedef enum { } spPositionMode; typedef enum { - SP_SPACING_MODE_LENGTH, SP_SPACING_MODE_FIXED, SP_SPACING_MODE_PERCENT + SP_SPACING_MODE_LENGTH, SP_SPACING_MODE_FIXED, SP_SPACING_MODE_PERCENT, SP_SPACING_MODE_PROPORTIONAL } spSpacingMode; typedef enum { @@ -61,7 +61,8 @@ typedef struct spPathConstraintData { spSpacingMode spacingMode; spRotateMode rotateMode; float offsetRotation; - float position, spacing, rotateMix, translateMix; + float position, spacing; + float mixRotate, mixX, mixY; } spPathConstraintData; SP_API spPathConstraintData* spPathConstraintData_create (const char* name); diff --git a/spine-c/spine-c/include/spine/TransformConstraint.h b/spine-c/spine-c/include/spine/TransformConstraint.h index a1fc1df21..be30f9b90 100644 --- a/spine-c/spine-c/include/spine/TransformConstraint.h +++ b/spine-c/spine-c/include/spine/TransformConstraint.h @@ -45,14 +45,14 @@ typedef struct spTransformConstraint { int bonesCount; spBone** const bones; spBone* target; - float rotateMix, translateMix, scaleMix, shearMix; + float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY; int /*boolean*/ active; } spTransformConstraint; SP_API spTransformConstraint* spTransformConstraint_create (spTransformConstraintData* data, const struct spSkeleton* skeleton); SP_API void spTransformConstraint_dispose (spTransformConstraint* self); -SP_API void spTransformConstraint_apply (spTransformConstraint* self); +SP_API void spTransformConstraint_update (spTransformConstraint* self); #ifdef __cplusplus } diff --git a/spine-c/spine-c/include/spine/TransformConstraintData.h b/spine-c/spine-c/include/spine/TransformConstraintData.h index 8cf575beb..a36643b4e 100644 --- a/spine-c/spine-c/include/spine/TransformConstraintData.h +++ b/spine-c/spine-c/include/spine/TransformConstraintData.h @@ -44,7 +44,7 @@ typedef struct spTransformConstraintData { int bonesCount; spBoneData** const bones; spBoneData* target; - float rotateMix, translateMix, scaleMix, shearMix; + float mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY; float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY; int /*boolean*/ relative; int /*boolean*/ local; diff --git a/spine-c/spine-c/src/spine/IkConstraint.c b/spine-c/spine-c/src/spine/IkConstraint.c index 1c9d47ea9..5ee53aa7e 100644 --- a/spine-c/spine-c/src/spine/IkConstraint.c +++ b/spine-c/spine-c/src/spine/IkConstraint.c @@ -57,7 +57,8 @@ void spIkConstraint_dispose(spIkConstraint *self) { FREE(self); } -void spIkConstraint_apply(spIkConstraint *self) { +void spIkConstraint_update(spIkConstraint *self) { + if (self->mix == 0) return; switch (self->bonesCount) { case 1: spIkConstraint_apply1(self->bones[0], self->target->worldX, self->target->worldY, self->compress, self->stretch, self->data->uniform, self->mix); @@ -131,10 +132,7 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float float tx, ty, dd, dx, dy, l1, l2, a1, a2, r, td, sd, p; float id, x, y; float aa, bb, ll, ta, c0, c1, c2; - if (alpha == 0) { - 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; sx = psx; psy = parent->ascaleY; csx = child->ascaleX; diff --git a/spine-c/spine-c/src/spine/PathConstraint.c b/spine-c/spine-c/src/spine/PathConstraint.c index 9f19c998a..3439270b0 100644 --- a/spine-c/spine-c/src/spine/PathConstraint.c +++ b/spine-c/spine-c/src/spine/PathConstraint.c @@ -47,8 +47,9 @@ spPathConstraint* spPathConstraint_create (spPathConstraintData* data, const spS self->target = spSkeleton_findSlot(skeleton, self->data->target->name); self->position = data->position; self->spacing = data->spacing; - self->rotateMix = data->rotateMix; - self->translateMix = data->translateMix; + self->mixRotate = data->mixRotate; + self->mixX = data->mixX; + self->mixY = data->mixY; self->spacesCount = 0; self->spaces = 0; self->positionsCount = 0; @@ -72,26 +73,23 @@ void spPathConstraint_dispose (spPathConstraint* self) { FREE(self); } -void spPathConstraint_apply (spPathConstraint* self) { +void spPathConstraint_update (spPathConstraint* self) { int i, p, n; - float length, setupLength, x, y, dx, dy, s; + float length, setupLength, x, y, dx, dy, s, sum; float* spaces, *lengths, *positions; float spacing; float boneX, boneY, offsetRotation; int/*bool*/tip; - float rotateMix = self->rotateMix, translateMix = self->translateMix; - int/*bool*/ translate = translateMix > 0, rotate = rotateMix > 0; + float mixRotate = self->mixRotate, mixX = self->mixX, mixY = self->mixY; int lengthSpacing; spPathAttachment* attachment = (spPathAttachment*)self->target->attachment; spPathConstraintData* data = self->data; - int percentSpacing = data->spacingMode == SP_SPACING_MODE_PERCENT; - spRotateMode rotateMode = data->rotateMode; - int tangents = rotateMode == SP_ROTATE_MODE_TANGENT, scale = rotateMode == SP_ROTATE_MODE_CHAIN_SCALE; + int tangents = data->rotateMode == SP_ROTATE_MODE_TANGENT, scale = data->rotateMode == SP_ROTATE_MODE_CHAIN_SCALE; int boneCount = self->bonesCount, spacesCount = tangents ? boneCount : boneCount + 1; spBone** bones = self->bones; spBone* pa; - if (!translate && !rotate) return; + if (mixRotate == 0 && mixX == 0 && mixY == 0) return; if ((attachment == 0) || (attachment->super.super.type != SP_ATTACHMENT_PATH)) return; if (self->spacesCount != spacesCount) { @@ -103,48 +101,77 @@ void spPathConstraint_apply (spPathConstraint* self) { spaces[0] = 0; lengths = 0; spacing = self->spacing; - if (scale || !percentSpacing) { - if (scale) { - if (self->lengthsCount != boneCount) { - if (self->lengths) FREE(self->lengths); - self->lengths = MALLOC(float, boneCount); - self->lengthsCount = boneCount; - } - lengths = self->lengths; - } - lengthSpacing = data->spacingMode == SP_SPACING_MODE_LENGTH; - for (i = 0, n = spacesCount - 1; i < n;) { - spBone *bone = bones[i]; - setupLength = bone->data->length; - if (setupLength < EPSILON) { - if (scale) lengths[i] = 0; - spaces[++i] = 0; - } else if (percentSpacing) { - if (scale) { - x = setupLength * bone->a, y = setupLength * bone->c; - length = SQRT(x * x + y * y); - lengths[i] = length; - } - spaces[++i] = spacing; - } else { - x = setupLength * bone->a, y = setupLength * bone->c; - length = SQRT(x * x + y * y); - if (scale) lengths[i] = length; - spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; - } - } - } else { - for (i = 1; i < spacesCount; i++) { - spaces[i] = spacing; - } - } - positions = spPathConstraint_computeWorldPositions(self, attachment, spacesCount, tangents, - data->positionMode == SP_POSITION_MODE_PERCENT, percentSpacing); + if (scale) { + if (self->lengthsCount != boneCount) { + if (self->lengths) FREE(self->lengths); + self->lengths = MALLOC(float, boneCount); + self->lengthsCount = boneCount; + } + lengths = self->lengths; + } + + switch (data->spacingMode) { + case SP_SPACING_MODE_PERCENT: + if (scale) { + for (i = 0, n = spacesCount - 1; i < n; i++) { + spBone* bone = bones[i]; + setupLength = bone->data->length; + if (setupLength < EPSILON) + lengths[i] = 0; + else { + x = setupLength * bone->a; + y = setupLength * bone->c; + lengths[i] = SQRT(x * x + y * y); + } + } + } + for (i = 1, n = spacesCount; i < n; i++) spaces[i] = spacing; + break; + case SP_SPACING_MODE_PROPORTIONAL: + sum = 0; + for (i = 0; i < boneCount;) { + spBone* bone = bones[i]; + setupLength = bone->data->length; + if (setupLength < EPSILON) { + if (scale) lengths[i] = 0; + spaces[++i] = spacing; + } else { + x = setupLength * bone->a, y = setupLength * bone->c; + length = SQRT(x * x + y * y); + if (scale) lengths[i] = length; + spaces[++i] = length; + sum += length; + } + } + if (sum > 0) { + sum = spacesCount / sum * spacing; + for (i = 1; i < spacesCount; i++) + spaces[i] *= sum; + } + break; + default: + lengthSpacing = data->spacingMode == SP_SPACING_MODE_LENGTH; + for (i = 0, n = spacesCount - 1; i < n;) { + spBone* bone = bones[i]; + setupLength = bone->data->length; + if (setupLength < EPSILON) { + if (scale) lengths[i] = 0; + spaces[++i] = spacing; + } else { + x = setupLength * bone->a, y = setupLength * bone->c; + length = SQRT(x * x + y * y); + if (scale) lengths[i] = length; + spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + + positions = spPathConstraint_computeWorldPositions(self, attachment, spacesCount, tangents); boneX = positions[0], boneY = positions[1], offsetRotation = self->data->offsetRotation; tip = 0; if (offsetRotation == 0) - tip = rotateMode == SP_ROTATE_MODE_CHAIN; + tip = data->rotateMode == SP_ROTATE_MODE_CHAIN; else { tip = 0; pa = self->target->bone; @@ -152,20 +179,20 @@ void spPathConstraint_apply (spPathConstraint* self) { } for (i = 0, p = 3; i < boneCount; i++, p += 3) { spBone* bone = bones[i]; - CONST_CAST(float, bone->worldX) += (boneX - bone->worldX) * translateMix; - CONST_CAST(float, bone->worldY) += (boneY - bone->worldY) * translateMix; + CONST_CAST(float, bone->worldX) += (boneX - bone->worldX) * mixX; + CONST_CAST(float, bone->worldY) += (boneY - bone->worldY) * mixY; x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; if (scale) { length = lengths[i]; if (length != 0) { - s = (SQRT(dx * dx + dy * dy) / length - 1) * rotateMix + 1; + s = (SQRT(dx * dx + dy * dy) / length - 1) * mixRotate + 1; CONST_CAST(float, bone->a) *= s; CONST_CAST(float, bone->c) *= s; } } boneX = x; boneY = y; - if (rotate) { + if (mixRotate > 0) { float a = bone->a, b = bone->b, c = bone->c, d = bone->d, r, cosine, sine; if (tangents) r = positions[p - 1]; @@ -178,15 +205,15 @@ void spPathConstraint_apply (spPathConstraint* self) { cosine = COS(r); sine = SIN(r); length = bone->data->length; - boneX += (length * (cosine * a - sine * c) - dx) * rotateMix; - boneY += (length * (sine * a + cosine * c) - dy) * rotateMix; + boneX += (length * (cosine * a - sine * c) - dx) * mixRotate; + boneY += (length * (sine * a + cosine * c) - dy) * mixRotate; } else r += offsetRotation; if (r > PI) r -= PI2; else if (r < -PI) r += PI2; - r *= rotateMix; + r *= mixRotate; cosine = COS(r); sine = SIN(r); CONST_CAST(float, bone->a) = cosine * a - sine * c; @@ -236,11 +263,11 @@ static void _addCurvePosition (float p, float x1, float y1, float cx1, float cy1 } } -float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAttachment* path, int spacesCount, int/*bool*/ tangents, int/*bool*/percentPosition, int/**/percentSpacing) { +float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAttachment* path, int spacesCount, int/*bool*/ tangents) { int i, o, w, curve, segment, /*bool*/closed, verticesLength, curveCount, prevCurve; float* out, *curves, *segments; float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy, pathLength, curveLength, p; - float x1, y1, cx1, cy1, cx2, cy2, x2, y2; + float x1, y1, cx1, cy1, cx2, cy2, x2, y2, multiplier; spSlot* target = self->target; float position = self->position; float* spaces = self->spaces, *world = 0; @@ -257,11 +284,18 @@ float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAtta float* lengths = path->lengths; curveCount -= closed ? 1 : 2; pathLength = lengths[curveCount]; - if (percentPosition) position *= pathLength; - if (percentSpacing) { - for (i = 1; i < spacesCount; i++) - spaces[i] *= pathLength; - } + if (self->data->positionMode == SP_POSITION_MODE_PERCENT) position += pathLength; + switch (self->data->spacingMode) { + case SP_SPACING_MODE_PERCENT: + multiplier = pathLength; + break; + case SP_SPACING_MODE_PROPORTIONAL: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } + if (self->worldCount != 8) { if (self->world) FREE(self->world); self->world = MALLOC(float, 8); @@ -269,7 +303,7 @@ float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAtta } world = self->world; for (i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { - float space = spaces[i]; + float space = spaces[i] * multiplier; position += space; p = position; @@ -384,19 +418,24 @@ float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAtta x1 = x2; y1 = y2; } - if (percentPosition) - position *= pathLength; - else - position *= pathLength / path->lengths[curveCount - 1]; - if (percentSpacing) { - for (i = 1; i < spacesCount; i++) - spaces[i] *= pathLength; - } + + if (self->data->positionMode == SP_POSITION_MODE_PERCENT) position *= pathLength; + + switch (self->data->spacingMode) { + case SP_SPACING_MODE_PERCENT: + multiplier = pathLength; + break; + case SP_SPACING_MODE_PROPORTIONAL: + multiplier = pathLength / spacesCount; + break; + default: + multiplier = 1; + } segments = self->segments; curveLength = 0; for (i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { - float space = spaces[i]; + float space = spaces[i] * multiplier; position += space; p = position; diff --git a/spine-c/spine-c/src/spine/Skeleton.c b/spine-c/spine-c/src/spine/Skeleton.c index e074cc065..9ba2c6260 100644 --- a/spine-c/spine-c/src/spine/Skeleton.c +++ b/spine-c/spine-c/src/spine/Skeleton.c @@ -47,10 +47,6 @@ typedef struct { int updateCacheCount; int updateCacheCapacity; _spUpdate* updateCache; - - int updateCacheResetCount; - int updateCacheResetCapacity; - spBone** updateCacheReset; } _spSkeleton; spSkeleton* spSkeleton_create (spSkeletonData* data) { @@ -133,7 +129,6 @@ 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]); @@ -171,15 +166,6 @@ 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 = (spBone**)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); @@ -199,11 +185,13 @@ static void _sortPathConstraintAttachmentBones(_spSkeleton* const internal, spAt else { spBone** bones = internal->super.bones; int i = 0, n; - while (i < pathBonesCount) { - int boneCount = pathBones[i++]; - for (n = i + boneCount; i < n; i++) - _sortBone(internal, bones[pathBones[i]]); - } + + for (i = 0, n = pathBonesCount; i < n;) { + int nn = pathBones[i++]; + nn += i; + while (i < nn) + _sortBone(internal, bones[pathBones[i++]]); + } } } @@ -241,23 +229,18 @@ static void _sortIkConstraint (_spSkeleton* const internal, spIkConstraint* cons parent = constrained[0]; _sortBone(internal, parent); - if (constraint->bonesCount > 1) { + if (constraint->bonesCount == 1) { + _addToUpdateCache(internal, SP_UPDATE_IK_CONSTRAINT, constraint); + _sortReset(parent->children, parent->childrenCount); + } else { 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); + _sortBone(internal, child); + + _addToUpdateCache(internal, SP_UPDATE_IK_CONSTRAINT, constraint); + + _sortReset(parent->children, parent->childrenCount); + child->sorted = 1; } - - _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) { @@ -310,16 +293,8 @@ static void _sortTransformConstraint(_spSkeleton* const internal, spTransformCon if (constraint->data->local) { for (i = 0; i < boneCount; i++) { child = constrained[i]; + _sortBone(internal, child->parent); _sortBone(internal, child); - 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); } } else { for (i = 0; i < boneCount; i++) @@ -348,11 +323,6 @@ void spSkeleton_updateCache (spSkeleton* self) { 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) { spBone* bone = bones[i]; @@ -417,19 +387,6 @@ 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; switch (update->type) { @@ -437,18 +394,60 @@ void spSkeleton_updateWorldTransform (const spSkeleton* self) { spBone_updateWorldTransform((spBone*)update->object); break; case SP_UPDATE_IK_CONSTRAINT: - spIkConstraint_apply((spIkConstraint*)update->object); + spIkConstraint_update((spIkConstraint *) update->object); break; case SP_UPDATE_TRANSFORM_CONSTRAINT: - spTransformConstraint_apply((spTransformConstraint*)update->object); + spTransformConstraint_update((spTransformConstraint *) update->object); break; case SP_UPDATE_PATH_CONSTRAINT: - spPathConstraint_apply((spPathConstraint*)update->object); + spPathConstraint_update((spPathConstraint *) update->object); break; } } } +void spSkeleton_updateWorldTransformWith (const spSkeleton* self, const spBone *parent) { +/* Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection. */ + int i, n; + float rotationY, la, lb, lc, ld; + _spUpdate *updateCache; + _spSkeleton* internal = SUB_CAST(_spSkeleton, self); + spBone *rootBone = self->root; + float pa = parent->a, pb = parent->b, pc = parent->c, pd = parent->d; + CONST_CAST(float, rootBone->worldX) = pa * self->x + pb * self->y + parent->worldX; + CONST_CAST(float, rootBone->worldY) = pc * self->x + pd * self->y + parent->worldY; + + rotationY = rootBone->rotation + 90 + rootBone->shearY; + la = COS_DEG(rootBone->rotation + rootBone->shearX) * rootBone->scaleX; + lb = COS_DEG(rotationY) * rootBone->scaleY; + lc = SIN_DEG(rootBone->rotation + rootBone->shearX) * rootBone->scaleX; + ld = SIN_DEG(rotationY) * rootBone->scaleY; + CONST_CAST(float, rootBone->a) = (pa * la + pb * lc) * self->scaleX; + CONST_CAST(float, rootBone->b) = (pa * lb + pb * ld) * self->scaleX; + CONST_CAST(float, rootBone->c) = (pc * la + pd * lc) * self->scaleY; + CONST_CAST(float, rootBone->d) = (pc * lb + pd * ld) * self->scaleY; + + /* Update everything except root bone. */ + updateCache = internal->updateCache; + for (i = 0; i < internal->updateCacheCount; ++i) { + _spUpdate* update = internal->updateCache + i; + switch (update->type) { + case SP_UPDATE_BONE: + if ((spBone*)update->object != rootBone) spBone_updateWorldTransform((spBone*)update->object); + break; + case SP_UPDATE_IK_CONSTRAINT: + spIkConstraint_update((spIkConstraint *) update->object); + break; + case SP_UPDATE_TRANSFORM_CONSTRAINT: + spTransformConstraint_update((spTransformConstraint *) update->object); + break; + case SP_UPDATE_PATH_CONSTRAINT: + spPathConstraint_update((spPathConstraint *) update->object); + break; + } + } +} + void spSkeleton_setToSetupPose (const spSkeleton* self) { spSkeleton_setBonesToSetupPose(self); spSkeleton_setSlotsToSetupPose(self); @@ -471,10 +470,12 @@ void spSkeleton_setBonesToSetupPose (const spSkeleton* self) { for (i = 0; i < self->transformConstraintsCount; ++i) { spTransformConstraint* constraint = self->transformConstraints[i]; spTransformConstraintData* data = constraint->data; - constraint->rotateMix = data->rotateMix; - constraint->translateMix = data->translateMix; - constraint->scaleMix = data->scaleMix; - constraint->shearMix = data->shearMix; + constraint->mixRotate = data->mixRotate; + constraint->mixX = data->mixX; + constraint->mixY = data->mixY; + constraint->mixScaleX = data->mixScaleX; + constraint->mixScaleY = data->mixScaleY; + constraint->mixShearY = data->mixShearY; } for (i = 0; i < self->pathConstraintsCount; ++i) { @@ -482,8 +483,9 @@ void spSkeleton_setBonesToSetupPose (const spSkeleton* self) { spPathConstraintData* data = constraint->data; constraint->position = data->position; constraint->spacing = data->spacing; - constraint->rotateMix = data->rotateMix; - constraint->translateMix = data->translateMix; + constraint->mixRotate = data->mixRotate; + constraint->mixX = data->mixX; + constraint->mixY = data->mixY; } } diff --git a/spine-c/spine-c/src/spine/TransformConstraint.c b/spine-c/spine-c/src/spine/TransformConstraint.c index 4fede676b..39d5a424e 100644 --- a/spine-c/spine-c/src/spine/TransformConstraint.c +++ b/spine-c/spine-c/src/spine/TransformConstraint.c @@ -35,10 +35,12 @@ spTransformConstraint* spTransformConstraint_create (spTransformConstraintData* int i; spTransformConstraint* self = NEW(spTransformConstraint); CONST_CAST(spTransformConstraintData*, self->data) = data; - self->rotateMix = data->rotateMix; - self->translateMix = data->translateMix; - self->scaleMix = data->scaleMix; - self->shearMix = data->shearMix; + self->mixRotate = data->mixRotate; + self->mixX = data->mixX; + self->mixY = data->mixY; + self->mixScaleX = data->mixScaleX; + self->mixScaleY = data->mixScaleY; + self->mixShearY = data->mixShearY; self->bonesCount = data->bonesCount; CONST_CAST(spBone**, self->bones) = MALLOC(spBone*, self->bonesCount); for (i = 0; i < self->bonesCount; ++i) @@ -53,134 +55,128 @@ void spTransformConstraint_dispose (spTransformConstraint* self) { } void _spTransformConstraint_applyAbsoluteWorld (spTransformConstraint* self) { - float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix; + float mixRotate = self->mixRotate, mixX = self->mixX, mixY = self->mixY, mixScaleX = self->mixScaleX, + mixScaleY = self->mixScaleY, mixShearY = self->mixShearY; + int /*bool*/ translate = mixX != 0 || mixY != 0; spBone* target = self->target; float ta = target->a, tb = target->b, tc = target->c, td = target->d; float degRadReflect = ta * td - tb * tc > 0 ? DEG_RAD : -DEG_RAD; float offsetRotation = self->data->offsetRotation * degRadReflect, offsetShearY = self->data->offsetShearY * degRadReflect; - int /*bool*/ modified; int i; float a, b, c, d, r, cosine, sine, x, y, s, ts, by; for (i = 0; i < self->bonesCount; ++i) { spBone* bone = self->bones[i]; - modified = 0; - if (rotateMix != 0) { + if (mixRotate != 0) { a = bone->a, b = bone->b, c = bone->c, d = bone->d; r = ATAN2(tc, ta) - ATAN2(c, a) + offsetRotation; if (r > PI) r -= PI2; else if (r < -PI) r += PI2; - r *= rotateMix; + r *= mixRotate; cosine = COS(r); sine = SIN(r); CONST_CAST(float, bone->a) = cosine * a - sine * c; 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 (translate) { 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; + CONST_CAST(float, bone->worldX) += (x - bone->worldX) * mixX; + CONST_CAST(float, bone->worldY) += (y - bone->worldY) * mixY; } - if (scaleMix > 0) { - s = SQRT(bone->a * bone->a + bone->c * bone->c); - ts = SQRT(ta * ta + tc * tc); - 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; - s = SQRT(bone->b * bone->b + bone->d * bone->d); - ts = SQRT(tb * tb + td * td); - 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 (mixScaleX > 0) { + s = SQRT(bone->a * bone->a + bone->c * bone->c); + if (s != 0) s = (s + (SQRT(ta * ta + tc * tc) - s + self->data->offsetScaleX) * mixScaleX) / s; + CONST_CAST(float, bone->a) *= s; + CONST_CAST(float, bone->c) *= s; } + if (mixScaleY != 0) { + s = SQRT(bone->b * bone->b + bone->d * bone->d); + if (s != 0) s = (s + (SQRT(tb * tb + td * td) - s + self->data->offsetScaleY) * mixScaleY) / s; + CONST_CAST(float, bone->b) *= s; + CONST_CAST(float, bone->d) *= s; + } - if (shearMix > 0) { + if (mixShearY > 0) { b = bone->b, d = bone->d; by = ATAN2(d, b); r = ATAN2(td, tb) - ATAN2(tc, ta) - (by - ATAN2(bone->c, bone->a)); s = SQRT(b * b + d * d); if (r > PI) r -= PI2; else if (r < -PI) r += PI2; - r = by + (r + offsetShearY) * shearMix; + r = by + (r + offsetShearY) * mixShearY; 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; + CONST_CAST(int, bone->appliedValid) = 0; } } void _spTransformConstraint_applyRelativeWorld (spTransformConstraint* self) { - float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix; + float mixRotate = self->mixRotate, mixX = self->mixX, mixY = self->mixY, mixScaleX = self->mixScaleX, + mixScaleY = self->mixScaleY, mixShearY = self->mixShearY; + int /*bool*/ translate = mixX != 0 || mixY != 0; spBone* target = self->target; float ta = target->a, tb = target->b, tc = target->c, td = target->d; float degRadReflect = ta * td - tb * tc > 0 ? DEG_RAD : -DEG_RAD; float offsetRotation = self->data->offsetRotation * degRadReflect, offsetShearY = self->data->offsetShearY * degRadReflect; - int /*bool*/ modified; int i; float a, b, c, d, r, cosine, sine, x, y, s; for (i = 0; i < self->bonesCount; ++i) { spBone* bone = self->bones[i]; - modified = 0; - if (rotateMix != 0) { + if (mixRotate != 0) { a = bone->a, b = bone->b, c = bone->c, d = bone->d; r = ATAN2(tc, ta) + offsetRotation; if (r > PI) r -= PI2; else if (r < -PI) r += PI2; - r *= rotateMix; + r *= mixRotate; cosine = COS(r); sine = SIN(r); CONST_CAST(float, bone->a) = cosine * a - sine * c; 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 (translate != 0) { spBone_localToWorld(target, self->data->offsetX, self->data->offsetY, &x, &y); - CONST_CAST(float, bone->worldX) += (x * translateMix); - CONST_CAST(float, bone->worldY) += (y * translateMix); - modified = 1; + CONST_CAST(float, bone->worldX) += (x * mixX); + CONST_CAST(float, bone->worldY) += (y * mixY); } - if (scaleMix > 0) { - s = (SQRT(ta * ta + tc * tc) - 1 + self->data->offsetScaleX) * scaleMix + 1; - CONST_CAST(float, bone->a) *= s; - CONST_CAST(float, bone->c) *= s; - s = (SQRT(tb * tb + td * td) - 1 + self->data->offsetScaleY) * scaleMix + 1; + if (mixScaleX != 0) { + s = (SQRT(ta * ta + tc * tc) - 1 + self->data->offsetScaleX) * mixScaleX + 1; + CONST_CAST(float, bone->a) *= s; + CONST_CAST(float, bone->c) *= s; + } + if (mixScaleY > 0) { + s = (SQRT(tb * tb + td * td) - 1 + self->data->offsetScaleY) * mixScaleY + 1; CONST_CAST(float, bone->b) *= s; CONST_CAST(float, bone->d) *= s; - modified = 1; } - if (shearMix > 0) { + if (mixShearY > 0) { r = ATAN2(td, tb) - ATAN2(tc, ta); if (r > PI) r -= PI2; else if (r < -PI) r += PI2; b = bone->b, d = bone->d; - r = ATAN2(d, b) + (r - PI / 2 + offsetShearY) * shearMix; + r = ATAN2(d, b) + (r - PI / 2 + offsetShearY) * mixShearY; s = SQRT(b * b + d * d); 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; + CONST_CAST(int, bone->appliedValid) = 0; } } void _spTransformConstraint_applyAbsoluteLocal (spTransformConstraint* self) { - float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix; + float mixRotate = self->mixRotate, mixX = self->mixX, mixY = self->mixY, mixScaleX = self->mixScaleX, + mixScaleY = self->mixScaleY, mixShearY = self->mixShearY; spBone* target = self->target; int i; float rotation, r, x, y, scaleX, scaleY, shearY; @@ -191,29 +187,27 @@ void _spTransformConstraint_applyAbsoluteLocal (spTransformConstraint* self) { if (!bone->appliedValid) spBone_updateAppliedTransform(bone); rotation = bone->arotation; - if (rotateMix != 0) { + if (mixRotate != 0) { r = target->arotation - rotation + self->data->offsetRotation; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - rotation += r * rotateMix; + rotation += r * mixRotate; } x = bone->ax, y = bone->ay; - if (translateMix != 0) { - x += (target->ax - x + self->data->offsetX) * translateMix; - y += (target->ay - y + self->data->offsetY) * translateMix; - } + x += (target->ax - x + self->data->offsetX) * mixX; + y += (target->ay - y + self->data->offsetY) * mixY; scaleX = bone->ascaleX, scaleY = bone->ascaleY; - if (scaleMix != 0) { - if (scaleX > 0.00001) scaleX = (scaleX + (target->ascaleX - scaleX + self->data->offsetScaleX) * scaleMix) / scaleX; - if (scaleY > 0.00001) scaleY = (scaleY + (target->ascaleY - scaleY + self->data->offsetScaleY) * scaleMix) / scaleY; - } + if (mixScaleX != 0 && scaleX != 0) + scaleX = (scaleX + (target->ascaleX - scaleX + self->data->offsetScaleX) * mixScaleX) / scaleX; + if (mixScaleY != 0 && scaleY != 0) + scaleY = (scaleY + (target->ascaleY - scaleY + self->data->offsetScaleY) * mixScaleY) / scaleY; shearY = bone->ashearY; - if (shearMix != 0) { + if (mixShearY != 0) { r = target->ashearY - shearY + self->data->offsetShearY; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - bone->shearY += r * shearMix; + shearY += r * mixShearY; } spBone_updateWorldTransformWith(bone, x, y, rotation, scaleX, scaleY, bone->ashearX, shearY); @@ -221,7 +215,8 @@ void _spTransformConstraint_applyAbsoluteLocal (spTransformConstraint* self) { } void _spTransformConstraint_applyRelativeLocal (spTransformConstraint* self) { - float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix; + float mixRotate = self->mixRotate, mixX = self->mixX, mixY = self->mixY, mixScaleX = self->mixScaleX, + mixScaleY = self->mixScaleY, mixShearY = self->mixShearY; spBone* target = self->target; int i; float rotation, x, y, scaleX, scaleY, shearY; @@ -232,32 +227,21 @@ void _spTransformConstraint_applyRelativeLocal (spTransformConstraint* self) { spBone* bone = self->bones[i]; if (!bone->appliedValid) spBone_updateAppliedTransform(bone); - rotation = bone->arotation; - if (rotateMix != 0) rotation += (target->arotation + self->data->offsetRotation) * rotateMix; + rotation = bone->arotation + (target->arotation + self->data->offsetRotation) * mixRotate; + x = bone->ax + (target->ax + self->data->offsetX) * mixX; + y = bone->ay + (target->ay + self->data->offsetY) * mixY; + scaleX = (bone->ascaleX * ((target->ascaleX - 1 + self->data->offsetScaleX) * mixScaleX) + 1); + scaleY = (bone->ascaleY * ((target->ascaleY - 1 + self->data->offsetScaleY) * mixScaleY) + 1); + shearY = bone->ashearY + (target->ashearY + self->data-> offsetShearY) * mixShearY; - x = bone->ax; - y = bone->ay; - if (translateMix != 0) { - x += (target->ax + self->data->offsetX) * translateMix; - y += (target->ay + self->data->offsetY) * translateMix; - } - - scaleX = bone->ascaleX; - scaleY = bone->ascaleY; - if (scaleMix != 0) { - if (scaleX > 0.00001f) scaleX *= ((target->ascaleX - 1 + self->data->offsetScaleX) * scaleMix) + 1; - if (scaleY > 0.00001f) scaleY *= ((target->ascaleY - 1 + self->data->offsetScaleY) * scaleMix) + 1; - } - - shearY = bone->ashearY; - if (shearMix != 0) shearY += (target->ashearY + self->data->offsetShearY) * shearMix; - - spBone_updateWorldTransformWith(bone, x, y, rotation, scaleX, scaleY, bone->ashearX, shearY); + spBone_updateWorldTransformWith(bone, x, y, rotation, scaleX, scaleY, bone->ashearX, shearY); } } -void spTransformConstraint_apply (spTransformConstraint* self) { - if (self->data->local) { +void spTransformConstraint_update (spTransformConstraint* self) { + if (self->mixRotate == 0 && self->mixX == 0 && self->mixY == 0 && self->mixScaleX == 0 && self->mixScaleX == 0 && self->mixShearY == 0) return; + + if (self->data->local) { if (self->data->relative) _spTransformConstraint_applyRelativeLocal(self); else