|
@@ -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;
|
|
|
-
|
|
|
- _sortBone(internal, constraint->target);
|
|
|
-
|
|
|
- for (ii = 0; ii < constraint->bonesCount; ++ii)
|
|
|
- _sortBone(internal, constrained[ii]);
|
|
|
+ pathConstraints = self->pathConstraints;
|
|
|
+ ikCount = self->ikConstraintsCount; transformCount = self->transformConstraintsCount; pathCount = self->pathConstraintsCount;
|
|
|
+ constraintCount = ikCount + transformCount + pathCount;
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- _addToUpdateCache(internal, SP_UPDATE_TRANSFORM_CONSTRAINT, constraint);
|
|
|
+ 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 < constraint->bonesCount; ++ii) {
|
|
|
- spBone* bone = constrained[ii];
|
|
|
- _sortReset(bone->children, bone->childrenCount);
|
|
|
+ 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;
|