diff --git a/spine-c/.cproject b/spine-c/.cproject
index b2b0c13c2..66072cca1 100644
--- a/spine-c/.cproject
+++ b/spine-c/.cproject
@@ -5,13 +5,13 @@
+
-
-
+
@@ -69,14 +69,14 @@
+
-
-
+
@@ -117,10 +117,10 @@
-
+
-
+
diff --git a/spine-c/include/spine/Animation.h b/spine-c/include/spine/Animation.h
index c826b262f..41485583a 100644
--- a/spine-c/include/spine/Animation.h
+++ b/spine-c/include/spine/Animation.h
@@ -94,9 +94,7 @@ typedef enum {
SP_TIMELINE_EVENT,
SP_TIMELINE_DRAWORDER,
SP_TIMELINE_FFD,
- SP_TIMELINE_IKCONSTRAINT,
- SP_TIMELINE_FLIPX,
- SP_TIMELINE_FLIPY
+ SP_TIMELINE_IKCONSTRAINT
} spTimelineType;
struct spTimeline {
@@ -400,36 +398,6 @@ typedef spIkConstraintTimeline IkConstraintTimeline;
/**/
-typedef struct spFlipTimeline {
- spTimeline super;
- int const x;
- int const framesCount;
- float* const frames; /* time, flip, ... */
- int boneIndex;
-
-#ifdef __cplusplus
- spFlipTimeline() :
- super(),
- x(0),
- framesCount(0),
- frames(0),
- boneIndex(0) {
- }
-#endif
-} spFlipTimeline;
-
-spFlipTimeline* spFlipTimeline_create (int framesCount, int/*bool*/x);
-
-void spFlipTimeline_setFrame (spFlipTimeline* self, int frameIndex, float time, int/*bool*/flip);
-
-#ifdef SPINE_SHORT_NAMES
-typedef spFlipTimeline FlipTimeline;
-#define FlipTimeline_create(...) spFlipTimeline_create(__VA_ARGS__)
-#define FlipTimeline_setFrame(...) spFlipTimeline_setFrame(__VA_ARGS__)
-#endif
-
-/**/
-
#ifdef __cplusplus
}
#endif
diff --git a/spine-c/include/spine/Attachment.h b/spine-c/include/spine/Attachment.h
index cab8a3938..71eccd3cb 100644
--- a/spine-c/include/spine/Attachment.h
+++ b/spine-c/include/spine/Attachment.h
@@ -37,7 +37,7 @@ extern "C" {
#endif
typedef enum {
- SP_ATTACHMENT_REGION, SP_ATTACHMENT_BOUNDING_BOX, SP_ATTACHMENT_MESH, SP_ATTACHMENT_SKINNED_MESH
+ SP_ATTACHMENT_REGION, SP_ATTACHMENT_BOUNDING_BOX, SP_ATTACHMENT_MESH, SP_ATTACHMENT_WEIGHTED_MESH
} spAttachmentType;
typedef struct spAttachment {
@@ -61,7 +61,7 @@ typedef spAttachmentType AttachmentType;
#define ATTACHMENT_REGION SP_ATTACHMENT_REGION
#define ATTACHMENT_BOUNDING_BOX SP_ATTACHMENT_BOUNDING_BOX
#define ATTACHMENT_MESH SP_ATTACHMENT_MESH
-#define ATTACHMENT_SKINNED_MESH SP_ATTACHMENT_SKINNED_MESH
+#define ATTACHMENT_WEIGHTED_MESH SP_ATTACHMENT_WEIGHTED_MESH
typedef spAttachment Attachment;
#define Attachment_dispose(...) spAttachment_dispose(__VA_ARGS__)
#endif
diff --git a/spine-c/include/spine/Bone.h b/spine-c/include/spine/Bone.h
index 88d482be4..160d9a642 100644
--- a/spine-c/include/spine/Bone.h
+++ b/spine-c/include/spine/Bone.h
@@ -45,32 +45,24 @@ struct spBone {
spBoneData* const data;
struct spSkeleton* const skeleton;
spBone* const parent;
- float x, y;
- float rotation, rotationIK;
- float scaleX, scaleY;
- int/*bool*/flipX, flipY;
+ float x, y, rotation, scaleX, scaleY;
+ float appliedRotation, appliedScaleX, appliedScaleY;
- float const m00, m01, worldX; /* a b x */
- float const m10, m11, worldY; /* c d y */
- float const worldRotation;
- float const worldScaleX, worldScaleY;
- int/*bool*/const worldFlipX, worldFlipY;
+ float const a, b, worldX;
+ float const c, d, worldY;
+ float const worldSignX, worldSignY;
#ifdef __cplusplus
spBone() :
data(0),
skeleton(0),
parent(0),
- x(0), y(0),
- rotation(0), rotationIK(0),
- scaleX(0), scaleY(0),
- flipX(0), flipY(0),
+ x(0), y(0), rotation(0), scaleX(0), scaleY(0),
+ appliedRotation(0), appliedScaleX(0), appliedScaleY(0),
- m00(0), m01(0), worldX(0),
- m10(0), m11(0), worldY(0),
- worldRotation(0),
- worldScaleX(0), worldScaleY(0),
- worldFlipX(0), worldFlipY(0) {
+ a(0), b(0), worldX(0),
+ c(0), d(0), worldY(0),
+ worldSignX(0), worldSignY(0) {
}
#endif
};
@@ -85,6 +77,12 @@ void spBone_dispose (spBone* self);
void spBone_setToSetupPose (spBone* self);
void spBone_updateWorldTransform (spBone* self);
+void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rotation, float scaleX, float scaleY);
+
+float spBone_getWorldRotationX (spBone* self);
+float spBone_getWorldRotationY (spBone* self);
+float spBone_getWorldScaleX (spBone* self);
+float spBone_getWorldScaleY (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);
@@ -97,6 +95,11 @@ typedef spBone Bone;
#define Bone_dispose(...) spBone_dispose(__VA_ARGS__)
#define Bone_setToSetupPose(...) spBone_setToSetupPose(__VA_ARGS__)
#define Bone_updateWorldTransform(...) spBone_updateWorldTransform(__VA_ARGS__)
+#define Bone_updateWorldTransformWith(...) spBone_updateWorldTransformWith(__VA_ARGS__)
+#define Bone_getWorldRotationX(...) spBone_getWorldRotationX(__VA_ARGS__)
+#define Bone_getWorldRotationY(...) spBone_getWorldRotationY(__VA_ARGS__)
+#define Bone_getWorldScaleX(...) spBone_getWorldScaleX(__VA_ARGS__)
+#define Bone_getWorldScaleY(...) spBone_getWorldScaleY(__VA_ARGS__)
#define Bone_worldToLocal(...) spBone_worldToLocal(__VA_ARGS__)
#define Bone_localToWorld(...) spBone_localToWorld(__VA_ARGS__)
#endif
diff --git a/spine-c/include/spine/BoneData.h b/spine-c/include/spine/BoneData.h
index 644f1bce0..e0591380c 100644
--- a/spine-c/include/spine/BoneData.h
+++ b/spine-c/include/spine/BoneData.h
@@ -44,7 +44,6 @@ struct spBoneData {
float x, y;
float rotation;
float scaleX, scaleY;
- int/*bool*/flipX, flipY;
int/*bool*/inheritScale, inheritRotation;
#ifdef __cplusplus
@@ -55,7 +54,6 @@ struct spBoneData {
x(0), y(0),
rotation(0),
scaleX(0), scaleY(0),
- flipX(0), flipY(0),
inheritScale(0), inheritRotation(0) {
}
#endif
diff --git a/spine-c/include/spine/Event.h b/spine-c/include/spine/Event.h
index 4df161a8a..31aebadca 100644
--- a/spine-c/include/spine/Event.h
+++ b/spine-c/include/spine/Event.h
@@ -40,6 +40,7 @@ extern "C" {
typedef struct spEvent {
spEventData* const data;
+ float const time;
int intValue;
float floatValue;
const char* stringValue;
@@ -47,6 +48,7 @@ typedef struct spEvent {
#ifdef __cplusplus
spEvent() :
data(0),
+ time(0),
intValue(0),
floatValue(0),
stringValue(0) {
@@ -54,7 +56,7 @@ typedef struct spEvent {
#endif
} spEvent;
-spEvent* spEvent_create (spEventData* data);
+spEvent* spEvent_create (float time, spEventData* data);
void spEvent_dispose (spEvent* self);
#ifdef SPINE_SHORT_NAMES
diff --git a/spine-c/include/spine/IkConstraint.h b/spine-c/include/spine/IkConstraint.h
index 0b100edae..f30cad388 100644
--- a/spine-c/include/spine/IkConstraint.h
+++ b/spine-c/include/spine/IkConstraint.h
@@ -75,6 +75,9 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float
typedef spIkConstraint IkConstraint;
#define IkConstraint_create(...) spIkConstraint_create(__VA_ARGS__)
#define IkConstraint_dispose(...) spIkConstraint_dispose(__VA_ARGS__)
+#define IkConstraint_apply(...) spIkConstraint_apply(__VA_ARGS__)
+#define IkConstraint_apply1(...) spIkConstraint_apply1(__VA_ARGS__)
+#define IkConstraint_apply2(...) spIkConstraint_apply2(__VA_ARGS__)
#endif
#ifdef __cplusplus
diff --git a/spine-c/include/spine/Skeleton.h b/spine-c/include/spine/Skeleton.h
index 8b6e07afe..43a63dc9d 100644
--- a/spine-c/include/spine/Skeleton.h
+++ b/spine-c/include/spine/Skeleton.h
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
#ifdef __cplusplus
extern "C" {
@@ -55,6 +56,9 @@ typedef struct spSkeleton {
int ikConstraintsCount;
spIkConstraint** ikConstraints;
+ int transformConstraintsCount;
+ spTransformConstraint** transformConstraints;
+
spSkin* const skin;
float r, g, b, a;
float time;
@@ -74,6 +78,9 @@ typedef struct spSkeleton {
ikConstraintsCount(0),
ikConstraints(0),
+ transformConstraintsCount(0),
+ transformConstraints(0),
+
skin(0),
r(0), g(0), b(0), a(0),
time(0),
@@ -87,11 +94,13 @@ typedef struct spSkeleton {
spSkeleton* spSkeleton_create (spSkeletonData* data);
void spSkeleton_dispose (spSkeleton* self);
-/* Caches information about bones and IK constraints. Must be called if bones or IK constraints are added or removed. */
+/* Caches information about bones and constraints. Must be called if bones or constraints are added or removed. */
void spSkeleton_updateCache (const spSkeleton* self);
void spSkeleton_updateWorldTransform (const spSkeleton* self);
+/* Sets the bones, constraints, and slots to their setup pose values. */
void spSkeleton_setToSetupPose (const spSkeleton* self);
+/* Sets the bones and constraints to their setup pose values. */
void spSkeleton_setBonesToSetupPose (const spSkeleton* self);
void spSkeleton_setSlotsToSetupPose (const spSkeleton* self);
@@ -123,7 +132,10 @@ spAttachment* spSkeleton_getAttachmentForSlotIndex (const spSkeleton* self, int
int spSkeleton_setAttachment (spSkeleton* self, const char* slotName, const char* attachmentName);
/* Returns 0 if the IK constraint was not found. */
-spIkConstraint* spSkeleton_findIkConstraint (const spSkeleton* self, const char* ikConstraintName);
+spIkConstraint* spSkeleton_findIkConstraint (const spSkeleton* self, const char* constraintName);
+
+/* Returns 0 if the transform constraint was not found. */
+spTransformConstraint* spSkeleton_findTransformConstraint (const spSkeleton* self, const char* constraintName);
void spSkeleton_update (spSkeleton* self, float deltaTime);
diff --git a/spine-c/include/spine/SkeletonData.h b/spine-c/include/spine/SkeletonData.h
index 1041c5a07..e73b75fe0 100644
--- a/spine-c/include/spine/SkeletonData.h
+++ b/spine-c/include/spine/SkeletonData.h
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#ifdef __cplusplus
extern "C" {
@@ -66,6 +67,9 @@ typedef struct spSkeletonData {
int ikConstraintsCount;
spIkConstraintData** ikConstraints;
+
+ int transformConstraintsCount;
+ spTransformConstraintData** transformConstraints;
} spSkeletonData;
spSkeletonData* spSkeletonData_create ();
@@ -83,7 +87,9 @@ spEventData* spSkeletonData_findEvent (const spSkeletonData* self, const char* e
spAnimation* spSkeletonData_findAnimation (const spSkeletonData* self, const char* animationName);
-spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* ikConstraintName);
+spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* constraintName);
+
+spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkeletonData* self, const char* constraintName);
#ifdef SPINE_SHORT_NAMES
typedef spSkeletonData SkeletonData;
diff --git a/spine-c/include/spine/TransformConstraint.h b/spine-c/include/spine/TransformConstraint.h
new file mode 100644
index 000000000..c670a7823
--- /dev/null
+++ b/spine-c/include/spine/TransformConstraint.h
@@ -0,0 +1,79 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ *
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef SPINE_TRANSFORMCONSTRAINT_H_
+#define SPINE_TRANSFORMCONSTRAINT_H_
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct spSkeleton;
+
+typedef struct spTransformConstraint {
+ spTransformConstraintData* const data;
+ spBone* bone;
+ spBone* target;
+ float translateMix;
+ float x, y;
+
+#ifdef __cplusplus
+ spTransformConstraint() :
+ data(0),
+ bone(0),
+ target(0),
+ translateMix(0),
+ x(0),
+ y(0) {
+ }
+#endif
+} spTransformConstraint;
+
+spTransformConstraint* spTransformConstraint_create (spTransformConstraintData* data, const struct spSkeleton* skeleton);
+void spTransformConstraint_dispose (spTransformConstraint* self);
+
+void spTransformConstraint_apply (spTransformConstraint* self);
+
+#ifdef SPINE_SHORT_NAMES
+typedef spTransformConstraint TransformConstraint;
+#define TransformConstraint_create(...) spTransformConstraint_create(__VA_ARGS__)
+#define TransformConstraint_dispose(...) spTransformConstraint_dispose(__VA_ARGS__)
+#define TransformConstraint_apply(...) spTransformConstraint_apply(__VA_ARGS__)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SPINE_TRANSFORMCONSTRAINT_H_ */
diff --git a/spine-c/include/spine/TransformConstraintData.h b/spine-c/include/spine/TransformConstraintData.h
new file mode 100644
index 000000000..3fc02a045
--- /dev/null
+++ b/spine-c/include/spine/TransformConstraintData.h
@@ -0,0 +1,74 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ *
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef SPINE_TRANSFORMCONSTRAINTDATA_H_
+#define SPINE_TRANSFORMCONSTRAINTDATA_H_
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct spTransformConstraintData {
+ const char* const name;
+
+ spBoneData* bone;
+ spBoneData* target;
+ float translateMix;
+ float x, y;
+
+#ifdef __cplusplus
+ spTransformConstraintData() :
+ name(0),
+ bone(0),
+ target(0),
+ translateMix(0),
+ x(0),
+ y(0) {
+ }
+#endif
+} spTransformConstraintData;
+
+spTransformConstraintData* spTransformConstraintData_create (const char* name);
+void spTransformConstraintData_dispose (spTransformConstraintData* self);
+
+#ifdef SPINE_SHORT_NAMES
+typedef spTransformConstraintData TransformConstraintData;
+#define TransformConstraintData_create(...) spTransformConstraintData_create(__VA_ARGS__)
+#define TransformConstraintData_dispose(...) spTransformConstraintData_dispose(__VA_ARGS__)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SPINE_TRANSFORMCONSTRAINTDATA_H_ */
diff --git a/spine-c/include/spine/SkinnedMeshAttachment.h b/spine-c/include/spine/WeightedMeshAttachment.h
similarity index 76%
rename from spine-c/include/spine/SkinnedMeshAttachment.h
rename to spine-c/include/spine/WeightedMeshAttachment.h
index a9c56152c..b133a95b9 100644
--- a/spine-c/include/spine/SkinnedMeshAttachment.h
+++ b/spine-c/include/spine/WeightedMeshAttachment.h
@@ -29,8 +29,8 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-#ifndef SPINE_SKINNEDMESHATTACHMENT_H_
-#define SPINE_SKINNEDMESHATTACHMENT_H_
+#ifndef SPINE_WEIGHTEDMESHATTACHMENT_H_
+#define SPINE_WEIGHTEDMESHATTACHMENT_H_
#include
#include
@@ -39,7 +39,7 @@
extern "C" {
#endif
-typedef struct spSkinnedMeshAttachment {
+typedef struct spWeightedMeshAttachment {
spAttachment super;
const char* path;
@@ -70,21 +70,21 @@ typedef struct spSkinnedMeshAttachment {
int edgesCount;
int* edges;
float width, height;
-} spSkinnedMeshAttachment;
+} spWeightedMeshAttachment;
-spSkinnedMeshAttachment* spSkinnedMeshAttachment_create (const char* name);
-void spSkinnedMeshAttachment_updateUVs (spSkinnedMeshAttachment* self);
-void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self, spSlot* slot, float* worldVertices);
+spWeightedMeshAttachment* spWeightedMeshAttachment_create (const char* name);
+void spWeightedMeshAttachment_updateUVs (spWeightedMeshAttachment* self);
+void spWeightedMeshAttachment_computeWorldVertices (spWeightedMeshAttachment* self, spSlot* slot, float* worldVertices);
#ifdef SPINE_SHORT_NAMES
-typedef spSkinnedMeshAttachment SkinnedMeshAttachment;
-#define SkinnedMeshAttachment_create(...) spSkinnedMeshAttachment_create(__VA_ARGS__)
-#define SkinnedMeshAttachment_updateUVs(...) spSkinnedMeshAttachment_updateUVs(__VA_ARGS__)
-#define SkinnedMeshAttachment_computeWorldVertices(...) spSkinnedMeshAttachment_computeWorldVertices(__VA_ARGS__)
+typedef spWeightedMeshAttachment WeightedMeshAttachment;
+#define WeightedMeshAttachment_create(...) spWeightedMeshAttachment_create(__VA_ARGS__)
+#define WeightedMeshAttachment_updateUVs(...) spWeightedMeshAttachment_updateUVs(__VA_ARGS__)
+#define WeightedMeshAttachment_computeWorldVertices(...) spWeightedMeshAttachment_computeWorldVertices(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
-#endif /* SPINE_SKINNEDMESHATTACHMENT_H_ */
+#endif /* SPINE_WEIGHTEDMESHATTACHMENT_H_ */
diff --git a/spine-c/include/spine/extension.h b/spine-c/include/spine/extension.h
index e42394c4c..c141fb119 100644
--- a/spine-c/include/spine/extension.h
+++ b/spine-c/include/spine/extension.h
@@ -68,6 +68,7 @@
#define COS(A) cosf(A)
#define SQRT(A) sqrtf(A)
#define ACOS(A) acosf(A)
+#define ABS(A) fabsf(A)
#else
#define FMOD(A,B) (float)fmod(A, B)
#define ATAN2(A,B) (float)atan2(A, B)
@@ -75,6 +76,7 @@
#define SIN(A) (float)sin(A)
#define SQRT(A) (float)sqrt(A)
#define ACOS(A) (float)acos(A)
+#define ABS(A) ((A) < 0 ? -(A) : (A))
#endif
#include
@@ -86,7 +88,7 @@
#include
#include
#include
-#include
+#include
#include
#include
diff --git a/spine-c/include/spine/spine.h b/spine-c/include/spine/spine.h
index bbd6acfec..0a1063a0a 100644
--- a/spine-c/include/spine/spine.h
+++ b/spine-c/include/spine/spine.h
@@ -43,7 +43,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/spine-c/src/spine/Animation.c b/spine-c/src/spine/Animation.c
index e233a4243..b12ff6542 100644
--- a/spine-c/src/spine/Animation.c
+++ b/spine-c/src/spine/Animation.c
@@ -789,48 +789,3 @@ void spIkConstraintTimeline_setFrame (spIkConstraintTimeline* self, int frameInd
}
/**/
-
-void _spFlipTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
- spEvent** firedEvents, int* eventsCount, float alpha) {
- int frameIndex;
- spFlipTimeline* self = (spFlipTimeline*)timeline;
-
- if (time < self->frames[0]) {
- if (lastTime > time) _spFlipTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, 0, 0, 0);
- return;
- } else if (lastTime > time) /**/
- lastTime = -1;
-
- frameIndex = (time >= self->frames[self->framesCount - 2] ?
- self->framesCount : binarySearch(self->frames, self->framesCount, time, 2)) - 2;
- if (self->frames[frameIndex] < lastTime) return;
-
- if (self->x)
- skeleton->bones[self->boneIndex]->flipX = (int)self->frames[frameIndex + 1];
- else
- skeleton->bones[self->boneIndex]->flipY = (int)self->frames[frameIndex + 1];
-}
-
-void _spFlipTimeline_dispose (spTimeline* timeline) {
- spFlipTimeline* self = SUB_CAST(spFlipTimeline, timeline);
- _spTimeline_deinit(SUPER(self));
- FREE(self->frames);
- FREE(self);
-}
-
-spFlipTimeline* spFlipTimeline_create (int framesCount, int/*bool*/x) {
- spFlipTimeline* self = NEW(spFlipTimeline);
- _spTimeline_init(SUPER(self), x ? SP_TIMELINE_FLIPX : SP_TIMELINE_FLIPY, _spFlipTimeline_dispose, _spFlipTimeline_apply);
- CONST_CAST(int, self->x) = x;
- CONST_CAST(int, self->framesCount) = framesCount << 1;
- CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount);
- return self;
-}
-
-void spFlipTimeline_setFrame (spFlipTimeline* self, int frameIndex, float time, int/*bool*/flip) {
- frameIndex <<= 1;
- self->frames[frameIndex] = time;
- self->frames[frameIndex + 1] = (float)flip;
-}
-
-/**/
diff --git a/spine-c/src/spine/AtlasAttachmentLoader.c b/spine-c/src/spine/AtlasAttachmentLoader.c
index 9247a8ce7..0c88ed08a 100644
--- a/spine-c/src/spine/AtlasAttachmentLoader.c
+++ b/spine-c/src/spine/AtlasAttachmentLoader.c
@@ -76,14 +76,14 @@ spAttachment* _spAtlasAttachmentLoader_newAttachment (spAttachmentLoader* loader
attachment->regionOriginalHeight = region->originalHeight;
return SUPER(attachment);
}
- case SP_ATTACHMENT_SKINNED_MESH: {
- spSkinnedMeshAttachment* attachment;
+ case SP_ATTACHMENT_WEIGHTED_MESH: {
+ spWeightedMeshAttachment* attachment;
spAtlasRegion* region = spAtlas_findRegion(self->atlas, path);
if (!region) {
_spAttachmentLoader_setError(loader, "Region not found: ", path);
return 0;
}
- attachment = spSkinnedMeshAttachment_create(name);
+ attachment = spWeightedMeshAttachment_create(name);
attachment->rendererObject = region;
attachment->regionU = region->u;
attachment->regionV = region->v;
diff --git a/spine-c/src/spine/Bone.c b/spine-c/src/spine/Bone.c
index d75dafc86..40885bd00 100644
--- a/spine-c/src/spine/Bone.c
+++ b/spine-c/src/spine/Bone.c
@@ -56,47 +56,137 @@ void spBone_dispose (spBone* self) {
}
void spBone_updateWorldTransform (spBone* self) {
- float radians, cosine, sine;
- if (self->parent) {
- CONST_CAST(float, self->worldX) = self->x * self->parent->m00 + self->y * self->parent->m01 + self->parent->worldX;
- CONST_CAST(float, self->worldY) = self->x * self->parent->m10 + self->y * self->parent->m11 + self->parent->worldY;
- if (self->data->inheritScale) {
- CONST_CAST(float, self->worldScaleX) = self->parent->worldScaleX * self->scaleX;
- CONST_CAST(float, self->worldScaleY) = self->parent->worldScaleY * self->scaleY;
- } else {
- CONST_CAST(float, self->worldScaleX) = self->scaleX;
- CONST_CAST(float, self->worldScaleY) = self->scaleY;
+ spBone_updateWorldTransformWith(self, self->x, self->y, self->rotation, self->scaleX, self->scaleY);
+}
+
+void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rotation, float scaleX, float scaleY) {
+ float radians = rotation * DEG_RAD;
+ float cosine = COS(radians);
+ float sine = SIN(radians);
+ float la = cosine * scaleX, lb = -sine * scaleY, lc = sine * scaleX, ld = cosine * scaleY;
+ float pa, pb, pc, pd;
+ spBone* parent = self->parent;
+
+ CONST_CAST(float, self->appliedRotation) = rotation;
+ CONST_CAST(float, self->appliedScaleX) = scaleX;
+ CONST_CAST(float, self->appliedScaleY) = scaleY;
+
+ if (!parent) { /* Root bone. */
+ if (self->skeleton->flipX) {
+ x = -x;
+ la = -la;
+ lb = -lb;
}
- CONST_CAST(float, self->worldRotation) =
- self->data->inheritRotation ? self->parent->worldRotation + self->rotationIK : self->rotationIK;
- CONST_CAST(int, self->worldFlipX) = self->parent->worldFlipX ^ self->flipX;
- CONST_CAST(int, self->worldFlipY) = self->parent->worldFlipY ^ self->flipY;
- } else {
- int skeletonFlipX = self->skeleton->flipX, skeletonFlipY = self->skeleton->flipY;
- CONST_CAST(float, self->worldX) = self->skeleton->flipX ? -self->x : self->x;
- CONST_CAST(float, self->worldY) = self->skeleton->flipY != yDown ? -self->y : self->y;
- CONST_CAST(float, self->worldScaleX) = self->scaleX;
- CONST_CAST(float, self->worldScaleY) = self->scaleY;
- CONST_CAST(float, self->worldRotation) = self->rotationIK;
- CONST_CAST(int, self->worldFlipX) = skeletonFlipX ^ self->flipX;
- CONST_CAST(int, self->worldFlipY) = skeletonFlipY ^ self->flipY;
+ if (self->skeleton->flipY != yDown) {
+ y = -y;
+ lc = -lc;
+ ld = -ld;
+ }
+ CONST_CAST(float, self->a) = la;
+ 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 : -1;
+ CONST_CAST(float, self->worldSignY) = scaleY > 0 ? 1 : -1;
+ return;
}
- radians = self->worldRotation * DEG_RAD;
- cosine = COS(radians);
- sine = SIN(radians);
- if (self->worldFlipX) {
- CONST_CAST(float, self->m00) = -cosine * self->worldScaleX;
- CONST_CAST(float, self->m01) = sine * self->worldScaleY;
+
+ pa = parent->a;
+ pb = parent->b;
+ pc = parent->c;
+ pd = parent->d;
+
+ 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. */
+ spBone* p = parent;
+ pa = 1;
+ pb = 0;
+ pc = 0;
+ pd = 1;
+ while (p) {
+ cosine = COS(p->appliedRotation * DEG_RAD);
+ sine = SIN(p->appliedRotation * DEG_RAD);
+ float a = pa * cosine + pb * sine;
+ float b = pa * -sine + pb * cosine;
+ float c = pc * cosine + pd * sine;
+ float d = pc * -sine + pd * cosine;
+ pa = a;
+ pb = b;
+ pc = c;
+ pd = d;
+ p = p->parent;
+ }
+ 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;
+ 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;
+ }
+ } else if (self->data->inheritScale) { /* No rotation inheritance. */
+ spBone* p = parent;
+ pa = 1;
+ pb = 0;
+ pc = 0;
+ pd = 1;
+ while (p) {
+ float r = p->rotation;
+ cosine = COS(r * DEG_RAD);
+ sine = SIN(r * DEG_RAD);
+ float psx = p->appliedScaleX, psy = p->appliedScaleY;
+ float za = cosine * psx, zb = -sine * psy, zc = sine * psx, zd = cosine * psy;
+ float temp = pa * za + pb * zc;
+ pb = pa * zb + pb * zd;
+ pa = temp;
+ temp = pc * za + pd * zc;
+ pd = pc * zb + pd * zd;
+ pc = temp;
+
+ if (psx < 0) r = -r;
+ cosine = COS(-r * DEG_RAD);
+ sine = SIN(-r * DEG_RAD);
+ temp = pa * cosine + pb * sine;
+ pb = pa * -sine + pb * cosine;
+ pa = temp;
+ temp = pc * cosine + pd * sine;
+ pd = pc * -sine + pd * cosine;
+ pc = temp;
+
+ p = p->parent;
+ }
+ 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;
+ 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;
+ }
} else {
- CONST_CAST(float, self->m00) = cosine * self->worldScaleX;
- CONST_CAST(float, self->m01) = -sine * self->worldScaleY;
- }
- if (self->worldFlipY != yDown) {
- CONST_CAST(float, self->m10) = -sine * self->worldScaleX;
- CONST_CAST(float, self->m11) = -cosine * self->worldScaleY;
- } else {
- CONST_CAST(float, self->m10) = sine * self->worldScaleX;
- CONST_CAST(float, self->m11) = cosine * self->worldScaleY;
+ CONST_CAST(float, self->a) = la;
+ CONST_CAST(float, self->b) = lb;
+ CONST_CAST(float, self->c) = lc;
+ CONST_CAST(float, self->d) = ld;
}
}
@@ -104,27 +194,36 @@ void spBone_setToSetupPose (spBone* self) {
self->x = self->data->x;
self->y = self->data->y;
self->rotation = self->data->rotation;
- self->rotationIK = self->rotation;
self->scaleX = self->data->scaleX;
self->scaleY = self->data->scaleY;
- self->flipX = self->data->flipX;
- self->flipY = self->data->flipY;
+}
+
+float spBone_getWorldRotationX (spBone* self) {
+ return ATAN2(self->c, self->a) * RAD_DEG;
+}
+
+float spBone_getWorldRotationY (spBone* self) {
+ return ATAN2(self->d, self->b) * RAD_DEG;
+}
+
+float spBone_getWorldScaleX (spBone* self) {
+ return SQRT(self->a * self->a + self->b * self->b) * self->worldSignX;
+}
+
+float spBone_getWorldScaleY (spBone* self) {
+ return SQRT(self->c * self->c + self->d * self->d) * self->worldSignY;
}
void spBone_worldToLocal (spBone* self, float worldX, float worldY, float* localX, float* localY) {
- float invDet;
- float dx = worldX - self->worldX, dy = worldY - self->worldY;
- float m00 = self->m00, m11 = self->m11;
- if (self->worldFlipX != (self->worldFlipY != yDown)) {
- m00 *= -1;
- m11 *= -1;
- }
- invDet = 1 / (m00 * m11 - self->m01 * self->m10);
- *localX = (dx * m00 * invDet - dy * self->m01 * invDet);
- *localY = (dy * m11 * invDet - dx * self->m10 * invDet);
+ float x = worldX - self->worldX, y = worldY - self->worldY;
+ float a = self->a, b = self->b, c = self->c, d = self->d;
+ float invDet = 1 / (a * d - b * c);
+ *localX = (x * a * invDet - y * b * invDet);
+ *localY = (y * d * invDet - x * c * invDet);
}
void spBone_localToWorld (spBone* self, float localX, float localY, float* worldX, float* worldY) {
- *worldX = localX * self->m00 + localY * self->m01 + self->worldX;
- *worldY = localX * self->m10 + localY * self->m11 + self->worldY;
+ float x = localX, y = localY;
+ *worldX = x * self->a + y * self->b + self->worldX;
+ *worldY = x * self->c + y * self->d + self->worldY;
}
diff --git a/spine-c/src/spine/BoundingBoxAttachment.c b/spine-c/src/spine/BoundingBoxAttachment.c
index 0d8049723..501b8ec1a 100644
--- a/spine-c/src/spine/BoundingBoxAttachment.c
+++ b/spine-c/src/spine/BoundingBoxAttachment.c
@@ -55,7 +55,7 @@ void spBoundingBoxAttachment_computeWorldVertices (spBoundingBoxAttachment* self
for (i = 0; i < self->verticesCount; i += 2) {
px = vertices[i];
py = vertices[i + 1];
- worldVertices[i] = px * bone->m00 + py * bone->m01 + x;
- worldVertices[i + 1] = px * bone->m10 + py * bone->m11 + y;
+ worldVertices[i] = px * bone->a + py * bone->b + x;
+ worldVertices[i + 1] = px * bone->c + py * bone->d + y;
}
}
diff --git a/spine-c/src/spine/Event.c b/spine-c/src/spine/Event.c
index 7bbc781cd..061fbfd7a 100644
--- a/spine-c/src/spine/Event.c
+++ b/spine-c/src/spine/Event.c
@@ -32,9 +32,10 @@
#include
#include
-spEvent* spEvent_create (spEventData* data) {
+spEvent* spEvent_create (float time, spEventData* data) {
spEvent* self = NEW(spEvent);
CONST_CAST(spEventData*, self->data) = data;
+ CONST_CAST(float, self->time) = time;
return self;
}
diff --git a/spine-c/src/spine/IkConstraint.c b/spine-c/src/spine/IkConstraint.c
index 61a0907c4..d94bbfb94 100644
--- a/spine-c/src/spine/IkConstraint.c
+++ b/spine-c/src/spine/IkConstraint.c
@@ -68,69 +68,130 @@ void spIkConstraint_apply (spIkConstraint* self) {
}
void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float alpha) {
- float parentRotation = (!bone->data->inheritRotation || !bone->parent) ? 0 : bone->parent->worldRotation;
+ float parentRotation = !bone->parent ? 0 : spBone_getWorldRotationX(bone->parent);
float rotation = bone->rotation;
- float rotationIK = ATAN2(targetY - bone->worldY, targetX - bone->worldX) * RAD_DEG;
- if (bone->worldFlipX != (bone->worldFlipY != spBone_isYDown())) rotationIK = -rotationIK;
- rotationIK -= parentRotation;
- bone->rotationIK = rotation + (rotationIK - rotation) * alpha;
+ float rotationIK = ATAN2(targetY - bone->worldY, targetX - bone->worldX) * RAD_DEG - parentRotation;
+ if (bone->worldSignX != bone->worldSignY) rotationIK = 360 - rotationIK;
+ if (rotationIK > 180) rotationIK -= 360;
+ else if (rotationIK < -180) rotationIK += 360;
+ spBone_updateWorldTransformWith(bone, bone->x, bone->y, rotation + (rotationIK - rotation) * alpha, bone->scaleX, bone->scaleY);
}
-void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, float alpha) {
- float positionX, positionY, childX, childY, offset, len1, len2, cosDenom, cos, childAngle, adjacent, opposite, parentAngle, rotation;
- spBone* parentParent;
- float childRotation = child->rotation, parentRotation = parent->rotation;
- if (alpha == 0) {
- child->rotationIK = childRotation;
- parent->rotationIK = parentRotation;
- return;
- }
- parentParent = parent->parent;
- if (parentParent) {
- spBone_worldToLocal(parentParent, targetX, targetY, &positionX, &positionY);
- targetX = (positionX - parent->x) * parentParent->worldScaleX;
- targetY = (positionY - parent->y) * parentParent->worldScaleY;
+void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDir, float alpha) {
+ if (alpha == 0) return;
+ float px = parent->x, py = parent->y, psx = parent->scaleX, psy = parent->scaleY, csx = child->scaleX, cy = child->y;
+ int offset1, offset2, sign2;
+ if (psx < 0) {
+ psx = -psx;
+ offset1 = 180;
+ sign2 = -1;
} else {
- targetX -= parent->x;
- targetY -= parent->y;
+ offset1 = 0;
+ sign2 = 1;
}
- if (child->parent == parent) {
- positionX = child->x;
- positionY = child->y;
+ if (psy < 0) {
+ psy = -psy;
+ sign2 = -sign2;
+ }
+ if (csx < 0) {
+ csx = -csx;
+ offset2 = 180;
+ } else
+ offset2 = 0;
+ spBone* pp = parent->parent;
+ float tx, ty, dx, dy;
+ if (!pp) {
+ tx = targetX - px;
+ ty = targetY - py;
+ dx = child->worldX - px;
+ dy = child->worldY - py;
} else {
- spBone_localToWorld(child->parent, child->x, child->y, &positionX, &positionY);
- spBone_worldToLocal(parent, positionX, positionY, &positionX, &positionY);
+ float a = pp->a, b = pp->b, c = pp->c, d = pp->d, invDet = 1 / (a * d - b * c);
+ float wx = pp->worldX, wy = pp->worldY, x = targetX - wx, y = targetY - wy;
+ tx = (x * d - y * b) * invDet - px;
+ ty = (y * a - x * c) * invDet - py;
+ x = child->worldX - wx;
+ y = child->worldY - wy;
+ dx = (x * d - y * b) * invDet - px;
+ dy = (y * a - x * c) * invDet - py;
}
- childX = positionX * parent->worldScaleX;
- childY = positionY * parent->worldScaleY;
- offset = ATAN2(childY, childX);
- len1 = SQRT(childX * childX + childY * childY);
- len2 = child->data->length * child->worldScaleX;
- /* Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/ */
- cosDenom = 2 * len1 * len2;
- if (cosDenom < 0.0001f) {
- child->rotationIK = childRotation + (ATAN2(targetY, targetX) * RAD_DEG - parentRotation - childRotation) * alpha;
- return;
+ float l1 = SQRT(dx * dx + dy * dy), l2 = child->data->length * csx, a1, a2;
+ if (ABS(psx - psy) <= 0.0001f) {
+ l2 *= psx;
+ float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
+ if (cos < -1) cos = -1;
+ else if (cos > 1) cos = 1;
+ a2 = ACOS(cos) * bendDir;
+ float a = l1 + l2 * cos, o = l2 * SIN(a2);
+ a1 = ATAN2(ty * a - tx * o, tx * a + ty * o);
+ } else {
+ cy = 0;
+ float a = psx * l2, b = psy * l2, ta = ATAN2(ty, tx);
+ float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty;
+ float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
+ float d = c1 * c1 - 4 * c2 * c0;
+ if (d >= 0) {
+ float q = SQRT(d);
+ if (c1 < 0) q = -q;
+ q = -(c1 + q) / 2;
+ float r0 = q / c2, r1 = c0 / q;
+ float r = ABS(r0) < ABS(r1) ? r0 : r1;
+ if (r * r <= dd) {
+ float y1 = SQRT(dd - r * r) * bendDir;
+ a1 = ta - ATAN2(y1, r);
+ a2 = ATAN2(y1 / psy, (r - l1) / psx);
+ goto outer;
+ }
+ }
+ float minAngle = 0, minDist = 999999999, minX = 0, minY = 0;
+ float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0;
+ float x = l1 + a, dist = x * x;
+ if (dist > maxDist) {
+ maxAngle = 0;
+ maxDist = dist;
+ maxX = x;
+ }
+ x = l1 - a;
+ dist = x * x;
+ if (dist < minDist) {
+ minAngle = PI;
+ minDist = dist;
+ minX = x;
+ }
+ float angle = ACOS(-a * l1 / (aa - bb));
+ x = a * COS(angle) + l1;
+ float y = b * SIN(angle);
+ dist = x * x + y * y;
+ if (dist < minDist) {
+ minAngle = angle;
+ minDist = dist;
+ minX = x;
+ minY = y;
+ }
+ if (dist > maxDist) {
+ maxAngle = angle;
+ maxDist = dist;
+ maxX = x;
+ maxY = y;
+ }
+ if (dd <= (minDist + maxDist) / 2) {
+ a1 = ta - ATAN2(minY * bendDir, minX);
+ a2 = minAngle * bendDir;
+ } else {
+ a1 = ta - ATAN2(maxY * bendDir, maxX);
+ a2 = maxAngle * bendDir;
+ }
}
- cos = (targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom;
- if (cos < -1)
- cos = -1;
- else if (cos > 1) /**/
- cos = 1;
- childAngle = ACOS(cos) * bendDirection;
- adjacent = len1 + len2 * cos;
- opposite = len2 * SIN(childAngle);
- parentAngle = ATAN2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
- rotation = (parentAngle - offset) * RAD_DEG - parentRotation;
- if (rotation > 180)
- rotation -= 360;
- else if (rotation < -180) /**/
- rotation += 360;
- parent->rotationIK = parentRotation + rotation * alpha;
- rotation = (childAngle + offset) * RAD_DEG - childRotation;
- if (rotation > 180)
- rotation -= 360;
- else if (rotation < -180) /**/
- rotation += 360;
- child->rotationIK = childRotation + (rotation + parent->worldRotation - child->parent->worldRotation) * alpha;
+outer: {}
+ float offset = ATAN2(cy, child->x) * sign2;
+ a1 = (a1 - offset) * RAD_DEG + offset1;
+ a2 = (a2 + offset) * RAD_DEG * sign2 + offset2;
+ if (a1 > 180) a1 -= 360;
+ else if (a1 < -180) a1 += 360;
+ if (a2 > 180) a2 -= 360;
+ else if (a2 < -180) a2 += 360;
+ float rotation = parent->rotation;
+ spBone_updateWorldTransformWith(parent, parent->x, parent->y, rotation + (a1 - rotation) * alpha, parent->scaleX, parent->scaleY);
+ rotation = child->rotation;
+ spBone_updateWorldTransformWith(child, child->x, cy, rotation + (a2 - rotation) * alpha, child->scaleX, child->scaleY);
}
diff --git a/spine-c/src/spine/MeshAttachment.c b/spine-c/src/spine/MeshAttachment.c
index 71d7ad36d..88a76dcb8 100644
--- a/spine-c/src/spine/MeshAttachment.c
+++ b/spine-c/src/spine/MeshAttachment.c
@@ -80,7 +80,7 @@ void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, spSlot* slot
if (slot->attachmentVerticesCount == self->verticesCount) vertices = slot->attachmentVertices;
for (i = 0; i < self->verticesCount; i += 2) {
const float vx = vertices[i], vy = vertices[i + 1];
- worldVertices[i] = vx * bone->m00 + vy * bone->m01 + x;
- worldVertices[i + 1] = vx * bone->m10 + vy * bone->m11 + y;
+ worldVertices[i] = vx * bone->a + vy * bone->b + x;
+ worldVertices[i + 1] = vx * bone->c + vy * bone->d + y;
}
}
diff --git a/spine-c/src/spine/RegionAttachment.c b/spine-c/src/spine/RegionAttachment.c
index 925cc4eb9..e872d252f 100644
--- a/spine-c/src/spine/RegionAttachment.c
+++ b/spine-c/src/spine/RegionAttachment.c
@@ -103,12 +103,12 @@ 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;
- vertices[SP_VERTEX_X1] = offset[SP_VERTEX_X1] * bone->m00 + offset[SP_VERTEX_Y1] * bone->m01 + x;
- vertices[SP_VERTEX_Y1] = offset[SP_VERTEX_X1] * bone->m10 + offset[SP_VERTEX_Y1] * bone->m11 + y;
- vertices[SP_VERTEX_X2] = offset[SP_VERTEX_X2] * bone->m00 + offset[SP_VERTEX_Y2] * bone->m01 + x;
- vertices[SP_VERTEX_Y2] = offset[SP_VERTEX_X2] * bone->m10 + offset[SP_VERTEX_Y2] * bone->m11 + y;
- vertices[SP_VERTEX_X3] = offset[SP_VERTEX_X3] * bone->m00 + offset[SP_VERTEX_Y3] * bone->m01 + x;
- vertices[SP_VERTEX_Y3] = offset[SP_VERTEX_X3] * bone->m10 + offset[SP_VERTEX_Y3] * bone->m11 + y;
- vertices[SP_VERTEX_X4] = offset[SP_VERTEX_X4] * bone->m00 + offset[SP_VERTEX_Y4] * bone->m01 + x;
- vertices[SP_VERTEX_Y4] = offset[SP_VERTEX_X4] * bone->m10 + offset[SP_VERTEX_Y4] * bone->m11 + y;
+ 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;
+ vertices[SP_VERTEX_Y2] = offset[SP_VERTEX_X2] * bone->c + offset[SP_VERTEX_Y2] * bone->d + y;
+ vertices[SP_VERTEX_X3] = offset[SP_VERTEX_X3] * bone->a + offset[SP_VERTEX_Y3] * bone->b + x;
+ vertices[SP_VERTEX_Y3] = offset[SP_VERTEX_X3] * bone->c + offset[SP_VERTEX_Y3] * bone->d + y;
+ vertices[SP_VERTEX_X4] = offset[SP_VERTEX_X4] * bone->a + offset[SP_VERTEX_Y4] * bone->b + x;
+ vertices[SP_VERTEX_Y4] = offset[SP_VERTEX_X4] * bone->c + offset[SP_VERTEX_Y4] * bone->d + y;
}
diff --git a/spine-c/src/spine/Skeleton.c b/spine-c/src/spine/Skeleton.c
index dc1b8ff11..735a2b98c 100644
--- a/spine-c/src/spine/Skeleton.c
+++ b/spine-c/src/spine/Skeleton.c
@@ -33,12 +33,16 @@
#include
#include
+typedef enum {
+ SP_UPDATE_BONE, SP_UPDATE_IK_CONSTRAINT, SP_UPDATE_TRANSFORM_CONSTRAINT
+} _spUpdateType;
+
typedef struct {
spSkeleton super;
- int boneCacheCount;
- int* boneCacheCounts;
- spBone*** boneCache;
+ int updateCacheCount;
+ void** updateCache;
+ _spUpdateType* updateCacheType;
} _spSkeleton;
spSkeleton* spSkeleton_create (spSkeletonData* data) {
@@ -96,6 +100,11 @@ spSkeleton* spSkeleton_create (spSkeletonData* data) {
for (i = 0; i < self->data->ikConstraintsCount; ++i)
self->ikConstraints[i] = spIkConstraint_create(self->data->ikConstraints[i], self);
+ self->transformConstraintsCount = data->transformConstraintsCount;
+ self->transformConstraints = MALLOC(spTransformConstraint*, self->transformConstraintsCount);
+ for (i = 0; i < self->data->transformConstraintsCount; ++i)
+ self->transformConstraints[i] = spTransformConstraint_create(self->data->transformConstraints[i], self);
+
spSkeleton_updateCache(self);
return self;
@@ -103,12 +112,6 @@ spSkeleton* spSkeleton_create (spSkeletonData* data) {
void spSkeleton_dispose (spSkeleton* self) {
int i;
- _spSkeleton* internal = SUB_CAST(_spSkeleton, self);
-
- for (i = 0; i < internal->boneCacheCount; ++i)
- FREE(internal->boneCache[i]);
- FREE(internal->boneCache);
- FREE(internal->boneCacheCounts);
for (i = 0; i < self->bonesCount; ++i)
spBone_dispose(self->bones[i]);
@@ -122,6 +125,10 @@ void spSkeleton_dispose (spSkeleton* self) {
spIkConstraint_dispose(self->ikConstraints[i]);
FREE(self->ikConstraints);
+ for (i = 0; i < self->transformConstraintsCount; ++i)
+ spTransformConstraint_dispose(self->transformConstraints[i]);
+ FREE(self->transformConstraints);
+
FREE(self->drawOrder);
FREE(self);
}
@@ -130,84 +137,51 @@ void spSkeleton_updateCache (const spSkeleton* self) {
int i, ii;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
- for (i = 0; i < internal->boneCacheCount; ++i)
- FREE(internal->boneCache[i]);
- FREE(internal->boneCache);
- FREE(internal->boneCacheCounts);
+ FREE(internal->updateCache);
+ FREE(internal->updateCacheType);
+ internal->updateCache = MALLOC(void*, self->bonesCount + self->transformConstraintsCount + self->ikConstraintsCount);
+ internal->updateCacheType = MALLOC(_spUpdateType, self->bonesCount + self->transformConstraintsCount + self->ikConstraintsCount);
+ internal->updateCacheCount = 0;
- internal->boneCacheCount = self->ikConstraintsCount + 1;
- internal->boneCache = MALLOC(spBone**, internal->boneCacheCount);
- internal->boneCacheCounts = CALLOC(int, internal->boneCacheCount);
-
- /* Compute array sizes. */
- for (i = 0; i < self->bonesCount; ++i) {
- spBone* current = self->bones[i];
- do {
- for (ii = 0; ii < self->ikConstraintsCount; ++ii) {
- spIkConstraint* ikConstraint = self->ikConstraints[ii];
- spBone* parent = ikConstraint->bones[0];
- spBone* child = ikConstraint->bones[ikConstraint->bonesCount - 1];
- while (1) {
- if (current == child) {
- internal->boneCacheCounts[ii]++;
- internal->boneCacheCounts[ii + 1]++;
- goto outer1;
- }
- if (child == parent) break;
- child = child->parent;
- }
- }
- current = current->parent;
- } while (current);
- internal->boneCacheCounts[0]++;
- outer1: {}
- }
-
- for (i = 0; i < internal->boneCacheCount; ++i)
- internal->boneCache[i] = MALLOC(spBone*, internal->boneCacheCounts[i]);
- memset(internal->boneCacheCounts, 0, internal->boneCacheCount * sizeof(int));
-
- /* Populate arrays. */
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = self->bones[i];
- spBone* current = bone;
- do {
- for (ii = 0; ii < self->ikConstraintsCount; ++ii) {
- spIkConstraint* ikConstraint = self->ikConstraints[ii];
- spBone* parent = ikConstraint->bones[0];
- spBone* child = ikConstraint->bones[ikConstraint->bonesCount - 1];
- while (1) {
- if (current == child) {
- internal->boneCache[ii][internal->boneCacheCounts[ii]++] = bone;
- internal->boneCache[ii + 1][internal->boneCacheCounts[ii + 1]++] = bone;
- goto outer2;
- }
- if (child == parent) break;
- child = child->parent;
- }
+ internal->updateCache[internal->updateCacheCount] = bone;
+ internal->updateCacheType[internal->updateCacheCount++] = SP_UPDATE_BONE;
+ for (ii = 0; ii < self->transformConstraintsCount; ++ii) {
+ spTransformConstraint* transformConstraint = self->transformConstraints[ii];
+ if (bone == transformConstraint->bone) {
+ internal->updateCache[internal->updateCacheCount] = transformConstraint;
+ internal->updateCacheType[internal->updateCacheCount++] = SP_UPDATE_TRANSFORM_CONSTRAINT;
+ break;
}
- current = current->parent;
- } while (current);
- internal->boneCache[0][internal->boneCacheCounts[0]++] = bone;
- outer2: {}
+ }
+ for (ii = 0; ii < self->ikConstraintsCount; ++ii) {
+ spIkConstraint* ikConstraint = self->ikConstraints[ii];
+ if (bone == ikConstraint->bones[ikConstraint->bonesCount - 1]) {
+ internal->updateCache[internal->updateCacheCount] = ikConstraint;
+ internal->updateCacheType[internal->updateCacheCount++] = SP_UPDATE_IK_CONSTRAINT;
+ break;
+ }
+ }
}
}
void spSkeleton_updateWorldTransform (const spSkeleton* self) {
- int i, ii, nn, last;
+ int i;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
- for (i = 0; i < self->bonesCount; ++i)
- self->bones[i]->rotationIK = self->bones[i]->rotation;
-
- i = 0;
- last = internal->boneCacheCount - 1;
- while (1) {
- for (ii = 0, nn = internal->boneCacheCounts[i]; ii < nn; ++ii)
- spBone_updateWorldTransform(internal->boneCache[i][ii]);
- if (i == last) break;
- spIkConstraint_apply(self->ikConstraints[i]);
- i++;
+ for (i = 0; i < internal->updateCacheCount; ++i) {
+ switch (internal->updateCacheType[i]) {
+ case SP_UPDATE_BONE:
+ spBone_updateWorldTransform((spBone*)internal->updateCache[i]);
+ break;
+ case SP_UPDATE_IK_CONSTRAINT:
+ spIkConstraint_apply((spIkConstraint*)internal->updateCache[i]);
+ break;
+ case SP_UPDATE_TRANSFORM_CONSTRAINT:
+ spTransformConstraint_apply((spTransformConstraint*)internal->updateCache[i]);
+ break;
+ }
}
}
@@ -226,6 +200,13 @@ void spSkeleton_setBonesToSetupPose (const spSkeleton* self) {
ikConstraint->bendDirection = ikConstraint->data->bendDirection;
ikConstraint->mix = ikConstraint->data->mix;
}
+
+ for (i = 0; i < self->transformConstraintsCount; ++i) {
+ spTransformConstraint* transformConstraint = self->transformConstraints[i];
+ transformConstraint->translateMix = transformConstraint->data->translateMix;
+ transformConstraint->x = transformConstraint->data->x;
+ transformConstraint->y = transformConstraint->data->y;
+ }
}
void spSkeleton_setSlotsToSetupPose (const spSkeleton* self) {
@@ -330,10 +311,17 @@ int spSkeleton_setAttachment (spSkeleton* self, const char* slotName, const char
return 0;
}
-spIkConstraint* spSkeleton_findIkConstraint (const spSkeleton* self, const char* ikConstraintName) {
+spIkConstraint* spSkeleton_findIkConstraint (const spSkeleton* self, const char* constraintName) {
int i;
for (i = 0; i < self->ikConstraintsCount; ++i)
- if (strcmp(self->ikConstraints[i]->data->name, ikConstraintName) == 0) return self->ikConstraints[i];
+ if (strcmp(self->ikConstraints[i]->data->name, constraintName) == 0) return self->ikConstraints[i];
+ return 0;
+}
+
+spTransformConstraint* spSkeleton_findTransformConstraint (const spSkeleton* self, const char* constraintName) {
+ int i;
+ for (i = 0; i < self->transformConstraintsCount; ++i)
+ if (strcmp(self->transformConstraints[i]->data->name, constraintName) == 0) return self->transformConstraints[i];
return 0;
}
diff --git a/spine-c/src/spine/SkeletonData.c b/spine-c/src/spine/SkeletonData.c
index c6f773811..b042bafb9 100644
--- a/spine-c/src/spine/SkeletonData.c
+++ b/spine-c/src/spine/SkeletonData.c
@@ -63,6 +63,10 @@ void spSkeletonData_dispose (spSkeletonData* self) {
spIkConstraintData_dispose(self->ikConstraints[i]);
FREE(self->ikConstraints);
+ for (i = 0; i < self->transformConstraintsCount; ++i)
+ spTransformConstraintData_dispose(self->transformConstraints[i]);
+ FREE(self->transformConstraints);
+
FREE(self->hash);
FREE(self->version);
@@ -118,9 +122,16 @@ spAnimation* spSkeletonData_findAnimation (const spSkeletonData* self, const cha
return 0;
}
-spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* ikConstraintName) {
+spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* constraintName) {
int i;
for (i = 0; i < self->ikConstraintsCount; ++i)
- if (strcmp(self->ikConstraints[i]->name, ikConstraintName) == 0) return self->ikConstraints[i];
+ if (strcmp(self->ikConstraints[i]->name, constraintName) == 0) return self->ikConstraints[i];
+ return 0;
+}
+
+spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkeletonData* self, const char* constraintName) {
+ int i;
+ for (i = 0; i < self->transformConstraintsCount; ++i)
+ if (strcmp(self->transformConstraints[i]->name, constraintName) == 0) return self->transformConstraints[i];
return 0;
}
diff --git a/spine-c/src/spine/SkeletonJson.c b/spine-c/src/spine/SkeletonJson.c
index f6af78a08..12ba17a99 100644
--- a/spine-c/src/spine/SkeletonJson.c
+++ b/spine-c/src/spine/SkeletonJson.c
@@ -116,8 +116,6 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
Json* ffd = Json_getItem(root, "ffd");
Json* drawOrder = Json_getItem(root, "drawOrder");
Json* events = Json_getItem(root, "events");
- Json* flipX = Json_getItem(root, "flipx");
- Json* flipY = Json_getItem(root, "flipy");
Json *boneMap, *slotMap, *ikMap, *ffdMap;
if (!drawOrder) drawOrder = Json_getItem(root, "draworder");
@@ -131,8 +129,6 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
timelinesCount += slotMap->size;
if (drawOrder) ++timelinesCount;
if (events) ++timelinesCount;
- if (flipX) ++timelinesCount;
- if (flipY) ++timelinesCount;
animation = spAnimation_create(root->name, timelinesCount);
animation->timelinesCount = 0;
@@ -221,16 +217,6 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[timelineArray->size * 3 - 3];
if (duration > animation->duration) animation->duration = duration;
- } else if (strcmp(timelineArray->name, "flipX") == 0 || strcmp(timelineArray->name, "flipY") == 0) {
- int x = strcmp(timelineArray->name, "flipX") == 0;
- const char* field = x ? "x" : "y";
- spFlipTimeline *timeline = spFlipTimeline_create(timelineArray->size, x);
- timeline->boneIndex = boneIndex;
- for (frame = timelineArray->child, i = 0; frame; frame = frame->next, ++i)
- spFlipTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), Json_getInt(frame, field, 0));
- animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
- duration = timeline->frames[timelineArray->size * 2 - 2];
- if (duration > animation->duration) animation->duration = duration;
} else {
spAnimation_dispose(animation);
@@ -281,8 +267,8 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
}
if (attachment->type == SP_ATTACHMENT_MESH)
verticesCount = SUB_CAST(spMeshAttachment, attachment)->verticesCount;
- else if (attachment->type == SP_ATTACHMENT_SKINNED_MESH)
- verticesCount = SUB_CAST(spSkinnedMeshAttachment, attachment)->weightsCount / 3 * 2;
+ else if (attachment->type == SP_ATTACHMENT_WEIGHTED_MESH)
+ verticesCount = SUB_CAST(spWeightedMeshAttachment, attachment)->weightsCount / 3 * 2;
timeline = spFFDTimeline_create(timelineArray->size, verticesCount);
timeline->slotIndex = slotIndex;
@@ -384,18 +370,19 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
for (frame = events->child, i = 0; frame; frame = frame->next, ++i) {
spEvent* event;
const char* stringValue;
+ float time = Json_getFloat(frame, "time", 0);
spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(frame, "name", 0));
if (!eventData) {
spAnimation_dispose(animation);
_spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(frame, "name", 0));
return 0;
}
- event = spEvent_create(eventData);
+ event = spEvent_create(time, eventData);
event->intValue = Json_getInt(frame, "int", eventData->intValue);
event->floatValue = Json_getFloat(frame, "float", eventData->floatValue);
stringValue = Json_getString(frame, "string", eventData->stringValue);
if (stringValue) MALLOC_STR(event->stringValue, stringValue);
- spEventTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), event);
+ spEventTimeline_setFrame(timeline, i, time, event);
}
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
duration = timeline->frames[events->size - 1];
@@ -421,7 +408,7 @@ spSkeletonData* spSkeletonJson_readSkeletonDataFile (spSkeletonJson* self, const
spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const char* json) {
int i, ii;
spSkeletonData* skeletonData;
- Json *root, *skeleton, *bones, *boneMap, *ik, *slots, *skins, *animations, *events;
+ Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *slots, *skins, *animations, *events;
char* oldLocale;
FREE(self->error);
@@ -471,8 +458,6 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
boneData->scaleY = Json_getFloat(boneMap, "scaleY", 1);
boneData->inheritScale = Json_getInt(boneMap, "inheritScale", 1);
boneData->inheritRotation = Json_getInt(boneMap, "inheritRotation", 1);
- boneData->flipX = Json_getInt(boneMap, "flipX", 0);
- boneData->flipY = Json_getInt(boneMap, "flipY", 0);
skeletonData->bones[i] = boneData;
skeletonData->bonesCount++;
@@ -515,6 +500,41 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
}
}
+ /* Transform constraints. */
+ transform = Json_getItem(root, "transform");
+ if (transform) {
+ Json *transformMap;
+ skeletonData->transformConstraintsCount = transform->size;
+ skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, transform->size);
+ for (transformMap = transform->child, i = 0; transformMap; transformMap = transformMap->next, ++i) {
+ const char* name;
+
+ spTransformConstraintData* transformConstraintData = spTransformConstraintData_create(Json_getString(transformMap, "name", 0));
+
+ name = Json_getString(transformMap, "bone", 0);
+ transformConstraintData->bone = spSkeletonData_findBone(skeletonData, name);
+ if (!transformConstraintData->bone) {
+ spSkeletonData_dispose(skeletonData);
+ _spSkeletonJson_setError(self, root, "Bone not found: ", boneMap->name);
+ return 0;
+ }
+
+ name = Json_getString(transformMap, "target", 0);
+ transformConstraintData->target = spSkeletonData_findBone(skeletonData, name);
+ if (!transformConstraintData->target) {
+ spSkeletonData_dispose(skeletonData);
+ _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name);
+ return 0;
+ }
+
+ transformConstraintData->translateMix = Json_getFloat(transformMap, "translateMix", 1);
+ transformConstraintData->x = Json_getFloat(transformMap, "x", 0);
+ transformConstraintData->y = Json_getFloat(transformMap, "y", 0);
+
+ skeletonData->transformConstraints[i] = transformConstraintData;
+ }
+ }
+
/* Slots. */
slots = Json_getItem(root, "slots");
if (slots) {
@@ -593,8 +613,8 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
type = SP_ATTACHMENT_REGION;
else if (strcmp(typeString, "mesh") == 0)
type = SP_ATTACHMENT_MESH;
- else if (strcmp(typeString, "skinnedmesh") == 0)
- type = SP_ATTACHMENT_SKINNED_MESH;
+ else if (strcmp(typeString, "weightedmesh") == 0 || strcmp(typeString, "skinnedmesh") == 0)
+ type = SP_ATTACHMENT_WEIGHTED_MESH;
else if (strcmp(typeString, "boundingbox") == 0)
type = SP_ATTACHMENT_BOUNDING_BOX;
else {
@@ -682,8 +702,8 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale;
break;
}
- case SP_ATTACHMENT_SKINNED_MESH: {
- spSkinnedMeshAttachment* mesh = SUB_CAST(spSkinnedMeshAttachment, attachment);
+ case SP_ATTACHMENT_WEIGHTED_MESH: {
+ spWeightedMeshAttachment* mesh = SUB_CAST(spWeightedMeshAttachment, attachment);
int verticesCount, b, w, nn;
float* vertices;
@@ -729,7 +749,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
for (entry = entry->child, i = 0; entry; entry = entry->next, ++i)
mesh->triangles[i] = entry->valueInt;
- spSkinnedMeshAttachment_updateUVs(mesh);
+ spWeightedMeshAttachment_updateUVs(mesh);
color = Json_getString(attachmentMap, "color", 0);
if (color) {
diff --git a/spine-c/src/spine/TransformConstraint.c b/spine-c/src/spine/TransformConstraint.c
new file mode 100644
index 000000000..15da3e6b2
--- /dev/null
+++ b/spine-c/src/spine/TransformConstraint.c
@@ -0,0 +1,58 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ *
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include
+#include
+#include
+
+spTransformConstraint* spTransformConstraint_create (spTransformConstraintData* data, const spSkeleton* skeleton) {
+ spTransformConstraint* self = NEW(spTransformConstraint);
+ CONST_CAST(spTransformConstraintData*, self->data) = data;
+ self->translateMix = data->translateMix;
+ self->x = data->x;
+ self->y = data->y;
+ self->bone = spSkeleton_findBone(skeleton, self->data->bone->name);
+ self->target = spSkeleton_findBone(skeleton, self->data->target->name);
+ return self;
+}
+
+void spTransformConstraint_dispose (spTransformConstraint* self) {
+ FREE(self);
+}
+
+void spTransformConstraint_apply (spTransformConstraint* self) {
+ if (self->translateMix > 0) {
+ float tx, ty;
+ spBone_localToWorld(self->target, self->x, self->y, &tx, &ty);
+ CONST_CAST(float, self->bone->worldX) = self->bone->worldX + (tx - self->bone->worldX) * self->translateMix;
+ CONST_CAST(float, self->bone->worldY) = self->bone->worldY + (ty - self->bone->worldY) * self->translateMix;
+ }
+}
diff --git a/spine-c/src/spine/TransformConstraintData.c b/spine-c/src/spine/TransformConstraintData.c
new file mode 100644
index 000000000..8d685e7a0
--- /dev/null
+++ b/spine-c/src/spine/TransformConstraintData.c
@@ -0,0 +1,44 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ *
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include
+#include
+
+spTransformConstraintData* spTransformConstraintData_create (const char* name) {
+ spTransformConstraintData* self = NEW(spTransformConstraintData);
+ MALLOC_STR(self->name, name);
+ return self;
+}
+
+void spTransformConstraintData_dispose (spTransformConstraintData* self) {
+ FREE(self->name);
+ FREE(self);
+}
diff --git a/spine-c/src/spine/SkinnedMeshAttachment.c b/spine-c/src/spine/WeightedMeshAttachment.c
similarity index 80%
rename from spine-c/src/spine/SkinnedMeshAttachment.c
rename to spine-c/src/spine/WeightedMeshAttachment.c
index a40fb90df..f17ea759d 100644
--- a/spine-c/src/spine/SkinnedMeshAttachment.c
+++ b/spine-c/src/spine/WeightedMeshAttachment.c
@@ -29,11 +29,11 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-#include
+#include
#include
-void _spSkinnedMeshAttachment_dispose (spAttachment* attachment) {
- spSkinnedMeshAttachment* self = SUB_CAST(spSkinnedMeshAttachment, attachment);
+void _spWeightedMeshAttachment_dispose (spAttachment* attachment) {
+ spWeightedMeshAttachment* self = SUB_CAST(spWeightedMeshAttachment, attachment);
_spAttachment_deinit(attachment);
FREE(self->path);
FREE(self->bones);
@@ -45,17 +45,17 @@ void _spSkinnedMeshAttachment_dispose (spAttachment* attachment) {
FREE(self);
}
-spSkinnedMeshAttachment* spSkinnedMeshAttachment_create (const char* name) {
- spSkinnedMeshAttachment* self = NEW(spSkinnedMeshAttachment);
+spWeightedMeshAttachment* spWeightedMeshAttachment_create (const char* name) {
+ spWeightedMeshAttachment* self = NEW(spWeightedMeshAttachment);
self->r = 1;
self->g = 1;
self->b = 1;
self->a = 1;
- _spAttachment_init(SUPER(self), name, SP_ATTACHMENT_SKINNED_MESH, _spSkinnedMeshAttachment_dispose);
+ _spAttachment_init(SUPER(self), name, SP_ATTACHMENT_WEIGHTED_MESH, _spWeightedMeshAttachment_dispose);
return self;
}
-void spSkinnedMeshAttachment_updateUVs (spSkinnedMeshAttachment* self) {
+void spWeightedMeshAttachment_updateUVs (spWeightedMeshAttachment* self) {
int i;
float width = self->regionU2 - self->regionU, height = self->regionV2 - self->regionV;
FREE(self->uvs);
@@ -73,7 +73,7 @@ void spSkinnedMeshAttachment_updateUVs (spSkinnedMeshAttachment* self) {
}
}
-void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self, spSlot* slot, float* worldVertices) {
+void spWeightedMeshAttachment_computeWorldVertices (spWeightedMeshAttachment* self, spSlot* slot, float* worldVertices) {
int w = 0, v = 0, b = 0, f = 0;
float x = slot->bone->skeleton->x, y = slot->bone->skeleton->y;
spBone** skeletonBones = slot->bone->skeleton->bones;
@@ -85,8 +85,8 @@ void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self
for (; v <= nn; v++, b += 3) {
const spBone* bone = skeletonBones[self->bones[v]];
const float vx = self->weights[b], vy = self->weights[b + 1], weight = self->weights[b + 2];
- wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight;
- wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight;
+ wx += (vx * bone->a + vy * bone->b + bone->worldX) * weight;
+ wy += (vx * bone->c + vy * bone->d + bone->worldY) * weight;
}
worldVertices[w] = wx + x;
worldVertices[w + 1] = wy + y;
@@ -100,8 +100,8 @@ void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self
for (; v <= nn; v++, b += 3, f += 2) {
const spBone* bone = skeletonBones[self->bones[v]];
const float vx = self->weights[b] + ffd[f], vy = self->weights[b + 1] + ffd[f + 1], weight = self->weights[b + 2];
- wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight;
- wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight;
+ wx += (vx * bone->a + vy * bone->b + bone->worldX) * weight;
+ wy += (vx * bone->c + vy * bone->d + bone->worldY) * weight;
}
worldVertices[w] = wx + x;
worldVertices[w + 1] = wy + y;
diff --git a/spine-sfml/.settings/org.eclipse.cdt.core.prefs b/spine-sfml/.settings/org.eclipse.cdt.core.prefs
index fe5dcc353..b2d602b0b 100644
--- a/spine-sfml/.settings/org.eclipse.cdt.core.prefs
+++ b/spine-sfml/.settings/org.eclipse.cdt.core.prefs
@@ -155,7 +155,7 @@ org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.cdt.core.formatter.lineSplit=80
+org.eclipse.cdt.core.formatter.lineSplit=130
org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.cdt.core.formatter.tabulation.char=tab
diff --git a/spine-sfml/src/spine/spine-sfml.cpp b/spine-sfml/src/spine/spine-sfml.cpp
index 262e2aae9..37689683d 100644
--- a/spine-sfml/src/spine/spine-sfml.cpp
+++ b/spine-sfml/src/spine/spine-sfml.cpp
@@ -196,11 +196,11 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
vertexArray->append(vertex);
}
- } else if (attachment->type == ATTACHMENT_SKINNED_MESH) {
- SkinnedMeshAttachment* mesh = (SkinnedMeshAttachment*)attachment;
+ } else if (attachment->type == ATTACHMENT_WEIGHTED_MESH) {
+ WeightedMeshAttachment* mesh = (WeightedMeshAttachment*)attachment;
if (mesh->uvsCount > SPINE_MESH_VERTEX_COUNT_MAX) continue;
texture = (Texture*)((AtlasRegion*)mesh->rendererObject)->page->rendererObject;
- SkinnedMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
+ WeightedMeshAttachment_computeWorldVertices(mesh, slot, worldVertices);
Uint8 r = static_cast(skeleton->r * slot->r * 255);
Uint8 g = static_cast(skeleton->g * slot->g * 255);