ソースを参照

Merge branch '3.6-timeline-animation-changes-c' into 3.6-beta

badlogic 8 年 前
コミット
060c846f75

+ 13 - 2
spine-c/spine-c/include/spine/Animation.h

@@ -58,6 +58,17 @@ typedef struct spAnimation {
 #endif
 #endif
 } spAnimation;
 } spAnimation;
 
 
+typedef enum {
+	SP_MIX_POSE_SETUP,
+	SP_MIX_POSE_CURRENT,
+	SP_MIX_POSE_CURRENT_LAYERED
+} spMixPose;
+
+typedef enum {
+	SP_MIX_DIRECTION_IN,
+	SP_MIX_DIRECTION_OUT
+} spMixDirection;
+
 spAnimation* spAnimation_create (const char* name, int timelinesCount);
 spAnimation* spAnimation_create (const char* name, int timelinesCount);
 void spAnimation_dispose (spAnimation* self);
 void spAnimation_dispose (spAnimation* self);
 
 
@@ -65,7 +76,7 @@ void spAnimation_dispose (spAnimation* self);
  * @param lastTime The last time the animation was applied.
  * @param lastTime The last time the animation was applied.
  * @param events Any triggered events are added. May be null.*/
  * @param events Any triggered events are added. May be null.*/
 void spAnimation_apply (const spAnimation* self, struct spSkeleton* skeleton, float lastTime, float time, int loop,
 void spAnimation_apply (const spAnimation* self, struct spSkeleton* skeleton, float lastTime, float time, int loop,
-		spEvent** events, int* eventsCount, float alpha, int /*boolean*/ setupPose, int /*boolean*/ mixingOut);
+		spEvent** events, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction);
 
 
 #ifdef SPINE_SHORT_NAMES
 #ifdef SPINE_SHORT_NAMES
 typedef spAnimation Animation;
 typedef spAnimation Animation;
@@ -108,7 +119,7 @@ struct spTimeline {
 
 
 void spTimeline_dispose (spTimeline* self);
 void spTimeline_dispose (spTimeline* self);
 void spTimeline_apply (const spTimeline* self, struct spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void spTimeline_apply (const spTimeline* self, struct spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-		int* eventsCount, float alpha, int /*boolean*/ setupPose, int /*boolean*/ mixingOut);
+		int* eventsCount, float alpha, spMixPose pose, spMixDirection direction);
 int spTimeline_getPropertyId (const spTimeline* self);
 int spTimeline_getPropertyId (const spTimeline* self);
 
 
 #ifdef SPINE_SHORT_NAMES
 #ifdef SPINE_SHORT_NAMES

+ 2 - 0
spine-c/spine-c/include/spine/VertexAttachment.h

@@ -49,6 +49,8 @@ struct spVertexAttachment {
 	float* vertices;
 	float* vertices;
 
 
 	int worldVerticesLength;
 	int worldVerticesLength;
+
+	int id;
 };
 };
 
 
 void spVertexAttachment_computeWorldVertices (spVertexAttachment* self, spSlot* slot, int start, int count, float* worldVertices, int offset, int stride);
 void spVertexAttachment_computeWorldVertices (spVertexAttachment* self, spSlot* slot, int start, int count, float* worldVertices, int offset, int stride);

+ 3 - 2
spine-c/spine-c/include/spine/extension.h

@@ -258,6 +258,7 @@ void _spAttachmentLoader_setUnknownTypeError (spAttachmentLoader* self, spAttach
 void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType type,
 void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType type,
 void (*dispose) (spAttachment* self));
 void (*dispose) (spAttachment* self));
 void _spAttachment_deinit (spAttachment* self);
 void _spAttachment_deinit (spAttachment* self);
+void _spVertexAttachment_init (spVertexAttachment* self);
 void _spVertexAttachment_deinit (spVertexAttachment* self);
 void _spVertexAttachment_deinit (spVertexAttachment* self);
 
 
 #ifdef SPINE_SHORT_NAMES
 #ifdef SPINE_SHORT_NAMES
@@ -271,7 +272,7 @@ void _spVertexAttachment_deinit (spVertexAttachment* self);
 void _spTimeline_init (spTimeline* self, spTimelineType type,
 void _spTimeline_init (spTimeline* self, spTimelineType type,
 	void (*dispose) (spTimeline* self),
 	void (*dispose) (spTimeline* self),
 	void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 	void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-		int* eventsCount, float alpha, int setupPose, int mixingOut),
+		int* eventsCount, float alpha, spMixPose pose, spMixDirection direction),
 	int (*getPropertyId) (const spTimeline* self));
 	int (*getPropertyId) (const spTimeline* self));
 void _spTimeline_deinit (spTimeline* self);
 void _spTimeline_deinit (spTimeline* self);
 
 
@@ -284,7 +285,7 @@ void _spTimeline_deinit (spTimeline* self);
 
 
 void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int framesCount,
 void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int framesCount,
 	void (*dispose) (spTimeline* self),
 	void (*dispose) (spTimeline* self),
-	void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut),
+	void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction),
 	int (*getPropertyId) (const spTimeline* self));
 	int (*getPropertyId) (const spTimeline* self));
 void _spCurveTimeline_deinit (spCurveTimeline* self);
 void _spCurveTimeline_deinit (spCurveTimeline* self);
 int _spCurveTimeline_binarySearch (float *values, int valuesLength, float target, int step);
 int _spCurveTimeline_binarySearch (float *values, int valuesLength, float target, int step);

+ 176 - 86
spine-c/spine-c/src/spine/Animation.c

@@ -51,7 +51,7 @@ void spAnimation_dispose (spAnimation* self) {
 }
 }
 
 
 void spAnimation_apply (const spAnimation* self, spSkeleton* skeleton, float lastTime, float time, int loop, spEvent** events,
 void spAnimation_apply (const spAnimation* self, spSkeleton* skeleton, float lastTime, float time, int loop, spEvent** events,
-		int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	int i, n = self->timelinesCount;
 	int i, n = self->timelinesCount;
 
 
 	if (loop && self->duration) {
 	if (loop && self->duration) {
@@ -60,21 +60,21 @@ void spAnimation_apply (const spAnimation* self, spSkeleton* skeleton, float las
 	}
 	}
 
 
 	for (i = 0; i < n; ++i)
 	for (i = 0; i < n; ++i)
-		spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, alpha, setupPose, mixingOut);
+		spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, alpha, pose, direction);
 }
 }
 
 
 /**/
 /**/
 
 
 typedef struct _spTimelineVtable {
 typedef struct _spTimelineVtable {
 	void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 	void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-			int* eventsCount, float alpha, int setupPose, int mixingOut);
+			int* eventsCount, float alpha, spMixPose pose, spMixDirection direction);
 	int (*getPropertyId) (const spTimeline* self);
 	int (*getPropertyId) (const spTimeline* self);
 	void (*dispose) (spTimeline* self);
 	void (*dispose) (spTimeline* self);
 } _spTimelineVtable;
 } _spTimelineVtable;
 
 
 void _spTimeline_init (spTimeline* self, spTimelineType type, /**/
 void _spTimeline_init (spTimeline* self, spTimelineType type, /**/
 					   void (*dispose) (spTimeline* self), /**/
 					   void (*dispose) (spTimeline* self), /**/
-					   void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut),
+					   void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction),
 					   int (*getPropertyId) (const spTimeline* self)) {
 					   int (*getPropertyId) (const spTimeline* self)) {
 	CONST_CAST(spTimelineType, self->type) = type;
 	CONST_CAST(spTimelineType, self->type) = type;
 	CONST_CAST(_spTimelineVtable*, self->vtable) = NEW(_spTimelineVtable);
 	CONST_CAST(_spTimelineVtable*, self->vtable) = NEW(_spTimelineVtable);
@@ -92,8 +92,8 @@ void spTimeline_dispose (spTimeline* self) {
 }
 }
 
 
 void spTimeline_apply (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void spTimeline_apply (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-		int* eventsCount, float alpha, int /*boolean*/ setupPose, int /*boolean*/ mixingOut) {
-	VTABLE(spTimeline, self)->apply(self, skeleton, lastTime, time, firedEvents, eventsCount, alpha, setupPose, mixingOut);
+		int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
+	VTABLE(spTimeline, self)->apply(self, skeleton, lastTime, time, firedEvents, eventsCount, alpha, pose, direction);
 }
 }
 
 
 int spTimeline_getPropertyId (const spTimeline* self) {
 int spTimeline_getPropertyId (const spTimeline* self) {
@@ -107,7 +107,7 @@ static const int BEZIER_SIZE = 10 * 2 - 1;
 
 
 void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int framesCount, /**/
 void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int framesCount, /**/
 		void (*dispose) (spTimeline* self), /**/
 		void (*dispose) (spTimeline* self), /**/
-		void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut),
+		void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction),
 		int (*getPropertyId)(const spTimeline* self)) {
 		int (*getPropertyId)(const spTimeline* self)) {
 	_spTimeline_init(SUPER(self), type, dispose, apply, getPropertyId);
 	_spTimeline_init(SUPER(self), type, dispose, apply, getPropertyId);
 	self->curves = CALLOC(float, (framesCount - 1) * BEZIER_SIZE);
 	self->curves = CALLOC(float, (framesCount - 1) * BEZIER_SIZE);
@@ -225,7 +225,7 @@ void _spBaseTimeline_dispose (spTimeline* timeline) {
 /* Many timelines have structure identical to struct spBaseTimeline and extend spCurveTimeline. **/
 /* Many timelines have structure identical to struct spBaseTimeline and extend spCurveTimeline. **/
 struct spBaseTimeline* _spBaseTimeline_create (int framesCount, spTimelineType type, int frameSize, /**/
 struct spBaseTimeline* _spBaseTimeline_create (int framesCount, spTimelineType type, int frameSize, /**/
 		void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 		void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-				int* eventsCount, float alpha, int setupPose, int mixingOut),
+				int* eventsCount, float alpha, spMixPose pose, spMixDirection direction),
 		int (*getPropertyId) (const spTimeline* self)) {
 		int (*getPropertyId) (const spTimeline* self)) {
 	struct spBaseTimeline* self = NEW(struct spBaseTimeline);
 	struct spBaseTimeline* self = NEW(struct spBaseTimeline);
 	_spCurveTimeline_init(SUPER(self), type, framesCount, _spBaseTimeline_dispose, apply, getPropertyId);
 	_spCurveTimeline_init(SUPER(self), type, framesCount, _spBaseTimeline_dispose, apply, getPropertyId);
@@ -239,7 +239,7 @@ struct spBaseTimeline* _spBaseTimeline_create (int framesCount, spTimelineType t
 /**/
 /**/
 
 
 void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-		int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	spBone *bone;
 	spBone *bone;
 	int frame;
 	int frame;
 	float prevRotation, frameTime, percent, r;
 	float prevRotation, frameTime, percent, r;
@@ -248,12 +248,21 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
 
 
 	bone = skeleton->bones[self->boneIndex];
 	bone = skeleton->bones[self->boneIndex];
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) bone->rotation = bone->data->rotation;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				bone->rotation = bone->data->rotation;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				r = bone->data->rotation - bone->rotation;
+				r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
+				bone->rotation += r * alpha;
+		}
 		return;
 		return;
 	}
 	}
 
 
 	if (time >= self->frames[self->framesCount - ROTATE_ENTRIES]) { /* Time is after last frame. */
 	if (time >= self->frames[self->framesCount - ROTATE_ENTRIES]) { /* Time is after last frame. */
-		if (setupPose)
+		if (pose == SP_MIX_POSE_SETUP)
 			bone->rotation = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] * alpha;
 			bone->rotation = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] * alpha;
 		else {
 		else {
 			r = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] - bone->rotation;
 			r = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] - bone->rotation;
@@ -272,7 +281,7 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
 	r = self->frames[frame + ROTATE_ROTATION] - prevRotation;
 	r = self->frames[frame + ROTATE_ROTATION] - prevRotation;
 	r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
 	r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
 	r = prevRotation + r * percent;
 	r = prevRotation + r * percent;
-	if (setupPose) {
+	if (pose == SP_MIX_POSE_SETUP) {
 		r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
 		r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
 		bone->rotation = bone->data->rotation + r * alpha;
 		bone->rotation = bone->data->rotation + r * alpha;
 	} else {
 	} else {
@@ -306,7 +315,7 @@ static const int TRANSLATE_PREV_TIME = -3, TRANSLATE_PREV_X = -2, TRANSLATE_PREV
 static const int TRANSLATE_X = 1, TRANSLATE_Y = 2;
 static const int TRANSLATE_X = 1, TRANSLATE_Y = 2;
 
 
 void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
 void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
-		spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	spBone *bone;
 	spBone *bone;
 	int frame;
 	int frame;
 	float frameTime, percent;
 	float frameTime, percent;
@@ -318,9 +327,15 @@ void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto
 
 
 	bone = skeleton->bones[self->boneIndex];
 	bone = skeleton->bones[self->boneIndex];
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			bone->x = bone->data->x;
-			bone->y = bone->data->y;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				bone->x = bone->data->x;
+				bone->y = bone->data->y;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				bone->x += (bone->data->x - bone->x) * alpha;
+				bone->y += (bone->data->y - bone->y) * alpha;
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -342,7 +357,7 @@ void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto
 		x += (frames[frame + TRANSLATE_X] - x) * percent;
 		x += (frames[frame + TRANSLATE_X] - x) * percent;
 		y += (frames[frame + TRANSLATE_Y] - y) * percent;
 		y += (frames[frame + TRANSLATE_Y] - y) * percent;
 	}
 	}
-	if (setupPose) {
+	if (pose == SP_MIX_POSE_SETUP) {
 		bone->x = bone->data->x + x * alpha;
 		bone->x = bone->data->x + x * alpha;
 		bone->y = bone->data->y + y * alpha;
 		bone->y = bone->data->y + y * alpha;
 	} else {
 	} else {
@@ -373,7 +388,7 @@ void spTranslateTimeline_setFrame (spTranslateTimeline* self, int frameIndex, fl
 /**/
 /**/
 
 
 void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-		int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	spBone *bone;
 	spBone *bone;
 	int frame;
 	int frame;
 	float frameTime, percent, x, y;
 	float frameTime, percent, x, y;
@@ -384,9 +399,15 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
 
 
 	bone = skeleton->bones[self->boneIndex];
 	bone = skeleton->bones[self->boneIndex];
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			bone->scaleX = bone->data->scaleX;
-			bone->scaleY = bone->data->scaleY;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				bone->scaleX = bone->data->scaleX;
+				bone->scaleY = bone->data->scaleY;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				bone->scaleX += (bone->data->scaleX - bone->scaleX) * alpha;
+				bone->scaleY += (bone->data->scaleY - bone->scaleY) * alpha;
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -413,7 +434,7 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
 		bone->scaleY = y;
 		bone->scaleY = y;
 	} else {
 	} else {
 		float bx, by;
 		float bx, by;
-		if (setupPose) {
+		if (pose == SP_MIX_POSE_SETUP) {
 			bx = bone->data->scaleX;
 			bx = bone->data->scaleX;
 			by = bone->data->scaleY;
 			by = bone->data->scaleY;
 		} else {
 		} else {
@@ -421,7 +442,7 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
 			by = bone->scaleY;
 			by = bone->scaleY;
 		}
 		}
 		/* Mixing out uses sign of setup or current pose, else use sign of key. */
 		/* Mixing out uses sign of setup or current pose, else use sign of key. */
-		if (mixingOut) {
+		if (direction == SP_MIX_DIRECTION_OUT) {
 			x = ABS(x) * SIGNUM(bx);
 			x = ABS(x) * SIGNUM(bx);
 			y = ABS(y) * SIGNUM(by);
 			y = ABS(y) * SIGNUM(by);
 		} else {
 		} else {
@@ -452,7 +473,7 @@ void spScaleTimeline_setFrame (spScaleTimeline* self, int frameIndex, float time
 /**/
 /**/
 
 
 void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-							 int* eventsCount, float alpha, int setupPose, int mixingOut) {
+							 int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	spBone *bone;
 	spBone *bone;
 	int frame;
 	int frame;
 	float frameTime, percent, x, y;
 	float frameTime, percent, x, y;
@@ -465,9 +486,15 @@ void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
 	frames = self->frames;
 	frames = self->frames;
 	framesCount = self->framesCount;
 	framesCount = self->framesCount;
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			bone->shearX = bone->data->shearX;
-			bone->shearY = bone->data->shearY;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				bone->shearX = bone->data->shearX;
+				bone->shearY = bone->data->shearY;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				bone->shearX += (bone->data->shearX - bone->shearX) * alpha;
+				bone->shearY += (bone->data->shearY - bone->shearY) * alpha;
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -487,7 +514,7 @@ void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
 		x = x + (frames[frame + TRANSLATE_X] - x) * percent;
 		x = x + (frames[frame + TRANSLATE_X] - x) * percent;
 		y = y + (frames[frame + TRANSLATE_Y] - y) * percent;
 		y = y + (frames[frame + TRANSLATE_Y] - y) * percent;
 	}
 	}
-	if (setupPose) {
+	if (pose == SP_MIX_POSE_SETUP) {
 		bone->shearX = bone->data->shearX + x * alpha;
 		bone->shearX = bone->data->shearX + x * alpha;
 		bone->shearY = bone->data->shearY + y * alpha;
 		bone->shearY = bone->data->shearY + y * alpha;
 	} else {
 	} else {
@@ -518,17 +545,27 @@ static const int COLOR_PREV_TIME = -5, COLOR_PREV_R = -4, COLOR_PREV_G = -3, COL
 static const int COLOR_R = 1, COLOR_G = 2, COLOR_B = 3, COLOR_A = 4;
 static const int COLOR_R = 1, COLOR_G = 2, COLOR_B = 3, COLOR_A = 4;
 
 
 void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-		int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	spSlot *slot;
 	spSlot *slot;
 	int frame;
 	int frame;
 	float percent, frameTime;
 	float percent, frameTime;
 	float r, g, b, a;
 	float r, g, b, a;
+	spColor* color;
+	spColor* setup;
 	spColorTimeline* self = (spColorTimeline*)timeline;
 	spColorTimeline* self = (spColorTimeline*)timeline;
 	slot = skeleton->slots[self->slotIndex];
 	slot = skeleton->slots[self->slotIndex];
 
 
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			spColor_setFromColor(&slot->color, &slot->data->color);
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				spColor_setFromColor(&slot->color, &slot->data->color);
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				color = &slot->color;
+				setup = &slot->data->color;
+				spColor_addFloats(color, (setup->r - color->r) * alpha, (setup->g - color->g) * alpha, (setup->b - color->b) * alpha,
+						  (setup->a - color->a) * alpha);
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -560,7 +597,7 @@ void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
 	if (alpha == 1) {
 	if (alpha == 1) {
 		spColor_setFromFloats(&slot->color, r, g, b, a);
 		spColor_setFromFloats(&slot->color, r, g, b, a);
 	} else {
 	} else {
-		if (setupPose) {
+		if (pose == SP_MIX_POSE_SETUP) {
 			spColor_setFromColor(&slot->color, &slot->data->color);
 			spColor_setFromColor(&slot->color, &slot->data->color);
 		}
 		}
 		spColor_addFloats(&slot->color, (r - slot->color.r) * alpha, (g - slot->color.g) * alpha, (b - slot->color.b) * alpha, (a - slot->color.a) * alpha);
 		spColor_addFloats(&slot->color, (r - slot->color.r) * alpha, (g - slot->color.g) * alpha, (b - slot->color.b) * alpha, (a - slot->color.a) * alpha);
@@ -595,20 +632,33 @@ static const int TWOCOLOR_PREV_R2 = -3, TWOCOLOR_PREV_G2 = -2, TWOCOLOR_PREV_B2
 static const int TWOCOLOR_R = 1, TWOCOLOR_G = 2, TWOCOLOR_B = 3, TWOCOLOR_A = 4, TWOCOLOR_R2 = 5, TWOCOLOR_G2 = 6, TWOCOLOR_B2 = 7;
 static const int TWOCOLOR_R = 1, TWOCOLOR_G = 2, TWOCOLOR_B = 3, TWOCOLOR_A = 4, TWOCOLOR_R2 = 5, TWOCOLOR_G2 = 6, TWOCOLOR_B2 = 7;
 
 
 void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-							 int* eventsCount, float alpha, int setupPose, int mixingOut) {
+							 int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	spSlot *slot;
 	spSlot *slot;
 	int frame;
 	int frame;
 	float percent, frameTime;
 	float percent, frameTime;
 	float r, g, b, a, r2, g2, b2;
 	float r, g, b, a, r2, g2, b2;
 	spColor* light;
 	spColor* light;
 	spColor* dark;
 	spColor* dark;
+	spColor* setupLight;
+	spColor* setupDark;
 	spColorTimeline* self = (spColorTimeline*)timeline;
 	spColorTimeline* self = (spColorTimeline*)timeline;
 	slot = skeleton->slots[self->slotIndex];
 	slot = skeleton->slots[self->slotIndex];
 
 
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			spColor_setFromColor(&slot->color, &slot->data->color);
-			spColor_setFromColor(slot->darkColor, slot->data->darkColor);
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				spColor_setFromColor(&slot->color, &slot->data->color);
+				spColor_setFromColor(slot->darkColor, slot->data->darkColor);
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				light = &slot->color;
+				dark = slot->darkColor;
+				setupLight = &slot->data->color;
+				setupDark = slot->data->darkColor;
+				spColor_addFloats(light, (setupLight->r - light->r) * alpha, (setupLight->g - light->g) * alpha, (setupLight->b - light->b) * alpha,
+						  (setupLight->a - light->a) * alpha);
+				spColor_addFloats(dark, (setupDark->r - dark->r) * alpha, (setupDark->g - dark->g) * alpha, (setupDark->b - dark->b) * alpha, 0);
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -652,7 +702,7 @@ void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton
 	} else {
 	} else {
 		light = &slot->color;
 		light = &slot->color;
 		dark = slot->darkColor;
 		dark = slot->darkColor;
-		if (setupPose) {
+		if (pose == SP_MIX_POSE_SETUP) {
 			spColor_setFromColor(light, &slot->data->color);
 			spColor_setFromColor(light, &slot->data->color);
 			spColor_setFromColor(dark, slot->data->darkColor);
 			spColor_setFromColor(dark, slot->data->darkColor);
 		}
 		}
@@ -688,20 +738,20 @@ void spTwoColorTimeline_setFrame (spTwoColorTimeline* self, int frameIndex, floa
 /**/
 /**/
 
 
 void _spAttachmentTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
 void _spAttachmentTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
-		spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	const char* attachmentName;
 	const char* attachmentName;
 	spAttachmentTimeline* self = (spAttachmentTimeline*)timeline;
 	spAttachmentTimeline* self = (spAttachmentTimeline*)timeline;
 	int frameIndex;
 	int frameIndex;
 	spSlot* slot = skeleton->slots[self->slotIndex];
 	spSlot* slot = skeleton->slots[self->slotIndex];
 
 
-	if (mixingOut && setupPose) {
+	if (direction == SP_MIX_DIRECTION_OUT && pose == SP_MIX_POSE_SETUP) {
 		const char* attachmentName = slot->data->attachmentName;
 		const char* attachmentName = slot->data->attachmentName;
         spSlot_setAttachment(slot, attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0);
         spSlot_setAttachment(slot, attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0);
 		return;
 		return;
 	}
 	}
 
 
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
+		if (pose == SP_MIX_POSE_SETUP) {
 			attachmentName = slot->data->attachmentName;
 			attachmentName = slot->data->attachmentName;
 			spSlot_setAttachment(skeleton->slots[self->slotIndex],
 			spSlot_setAttachment(skeleton->slots[self->slotIndex],
 								 attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0);
 								 attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0);
@@ -765,7 +815,7 @@ void spAttachmentTimeline_setFrame (spAttachmentTimeline* self, int frameIndex,
 /**/
 /**/
 
 
 void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-							  int* eventsCount, float alpha, int setupPose, int mixingOut) {
+							  int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	int frame, i, vertexCount;
 	int frame, i, vertexCount;
 	float percent, frameTime;
 	float percent, frameTime;
 	const float* prevVertices;
 	const float* prevVertices;
@@ -793,11 +843,6 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
 
 
 	frames = self->frames;
 	frames = self->frames;
 	framesCount = self->framesCount;
 	framesCount = self->framesCount;
-	if (time < frames[0]) { /* Time is before first frame. */
-		if (setupPose) slot->attachmentVerticesCount = 0;
-		return;
-	}
-
 	vertexCount = self->frameVerticesCount;
 	vertexCount = self->frameVerticesCount;
 	if (slot->attachmentVerticesCount < vertexCount) {
 	if (slot->attachmentVerticesCount < vertexCount) {
 		if (slot->attachmentVerticesCapacity < vertexCount) {
 		if (slot->attachmentVerticesCapacity < vertexCount) {
@@ -806,18 +851,32 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
 			slot->attachmentVerticesCapacity = vertexCount;
 			slot->attachmentVerticesCapacity = vertexCount;
 		}
 		}
 	}
 	}
-	if (slot->attachmentVerticesCount != vertexCount && !setupPose) alpha = 1; /* Don't mix from uninitialized slot vertices. */
+	if (slot->attachmentVerticesCount != vertexCount && pose != SP_MIX_POSE_SETUP) alpha = 1; /* Don't mix from uninitialized slot vertices. */
 	slot->attachmentVerticesCount = vertexCount;
 	slot->attachmentVerticesCount = vertexCount;
 
 
 	frameVertices = self->frameVertices;
 	frameVertices = self->frameVertices;
 	vertices = slot->attachmentVertices;
 	vertices = slot->attachmentVertices;
 
 
+	if (time < frames[0]) { /* Time is before first frame. */
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				slot->attachmentVerticesCount = 0;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				alpha = 1 - alpha;
+				for (i = 0; i < vertexCount; i++)
+					vertices[i] *= alpha;
+		}
+		return;
+	}
+
 	if (time >= frames[framesCount - 1]) { /* Time is after last frame. */
 	if (time >= frames[framesCount - 1]) { /* Time is after last frame. */
 		const float* lastVertices = self->frameVertices[framesCount - 1];
 		const float* lastVertices = self->frameVertices[framesCount - 1];
 		if (alpha == 1) {
 		if (alpha == 1) {
 			/* Vertex positions or deform offsets, no alpha. */
 			/* Vertex positions or deform offsets, no alpha. */
 			memcpy(vertices, lastVertices, vertexCount * sizeof(float));
 			memcpy(vertices, lastVertices, vertexCount * sizeof(float));
-		} else if (setupPose) {
+		} else if (pose == SP_MIX_POSE_SETUP) {
 			spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment);
 			spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment);
 			if (!vertexAttachment->bones) {
 			if (!vertexAttachment->bones) {
 				/* Unweighted vertex positions, with alpha. */
 				/* Unweighted vertex positions, with alpha. */
@@ -852,7 +911,7 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
 			float prev = prevVertices[i];
 			float prev = prevVertices[i];
 			vertices[i] = prev + (nextVertices[i] - prev) * percent;
 			vertices[i] = prev + (nextVertices[i] - prev) * percent;
 		}
 		}
-	} else if (setupPose) {
+	} else if (pose == SP_MIX_POSE_SETUP) {
 		spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment);
 		spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment);
 		if (!vertexAttachment->bones) {
 		if (!vertexAttachment->bones) {
 			/* Unweighted vertex positions, with alpha. */
 			/* Unweighted vertex positions, with alpha. */
@@ -882,7 +941,7 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
 }
 }
 
 
 int _spDeformTimeline_getPropertyId (const spTimeline* timeline) {
 int _spDeformTimeline_getPropertyId (const spTimeline* timeline) {
-	return (SP_TIMELINE_DEFORM << 24) + SUB_CAST(spDeformTimeline, timeline)->slotIndex;
+	return (SP_TIMELINE_DEFORM << 27) + SUB_CAST(spVertexAttachment, SUB_CAST(spDeformTimeline, timeline)->attachment)->id + SUB_CAST(spDeformTimeline, timeline)->slotIndex;
 }
 }
 
 
 void _spDeformTimeline_dispose (spTimeline* timeline) {
 void _spDeformTimeline_dispose (spTimeline* timeline) {
@@ -925,13 +984,13 @@ void spDeformTimeline_setFrame (spDeformTimeline* self, int frameIndex, float ti
 
 
 /** Fires events for frames > lastTime and <= time. */
 /** Fires events for frames > lastTime and <= time. */
 void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
 void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
-		int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	spEventTimeline* self = (spEventTimeline*)timeline;
 	spEventTimeline* self = (spEventTimeline*)timeline;
 	int frame;
 	int frame;
 	if (!firedEvents) return;
 	if (!firedEvents) return;
 
 
 	if (lastTime > time) { /* Fire events after last time for looped animations. */
 	if (lastTime > time) { /* Fire events after last time for looped animations. */
-		_spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventsCount, alpha, setupPose, mixingOut);
+		_spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventsCount, alpha, pose, direction);
 		lastTime = -1;
 		lastTime = -1;
 	} else if (lastTime >= self->frames[self->framesCount - 1]) /* Last time is after last frame. */
 	} else if (lastTime >= self->frames[self->framesCount - 1]) /* Last time is after last frame. */
 	return;
 	return;
@@ -992,19 +1051,19 @@ void spEventTimeline_setFrame (spEventTimeline* self, int frameIndex, spEvent* e
 /**/
 /**/
 
 
 void _spDrawOrderTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
 void _spDrawOrderTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
-		spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	int i;
 	int i;
 	int frame;
 	int frame;
 	const int* drawOrderToSetupIndex;
 	const int* drawOrderToSetupIndex;
 	spDrawOrderTimeline* self = (spDrawOrderTimeline*)timeline;
 	spDrawOrderTimeline* self = (spDrawOrderTimeline*)timeline;
 
 
-	if (mixingOut && setupPose) {
+	if (direction == SP_MIX_DIRECTION_OUT && pose == SP_MIX_POSE_SETUP) {
 		memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*));
 		memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*));
 		return;
 		return;
 	}
 	}
 
 
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*));
+		if (pose == SP_MIX_POSE_SETUP) memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*));
 		return;
 		return;
 	}
 	}
 
 
@@ -1074,7 +1133,7 @@ static const int IKCONSTRAINT_PREV_TIME = -3, IKCONSTRAINT_PREV_MIX = -2, IKCONS
 static const int IKCONSTRAINT_MIX = 1, IKCONSTRAINT_BEND_DIRECTION = 2;
 static const int IKCONSTRAINT_MIX = 1, IKCONSTRAINT_BEND_DIRECTION = 2;
 
 
 void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
 void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
-		spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	int frame;
 	int frame;
 	float frameTime, percent, mix;
 	float frameTime, percent, mix;
 	float *frames;
 	float *frames;
@@ -1085,9 +1144,15 @@ void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skel
 	constraint = skeleton->ikConstraints[self->ikConstraintIndex];
 	constraint = skeleton->ikConstraints[self->ikConstraintIndex];
 
 
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			constraint->mix = constraint->data->mix;
-			constraint->bendDirection = constraint->data->bendDirection;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				constraint->mix = constraint->data->mix;
+				constraint->bendDirection = constraint->data->bendDirection;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				constraint->mix += (constraint->data->mix - constraint->mix) * alpha;
+				constraint->bendDirection = constraint->data->bendDirection;
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -1095,13 +1160,13 @@ void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skel
 	frames = self->frames;
 	frames = self->frames;
 	framesCount = self->framesCount;
 	framesCount = self->framesCount;
 	if (time >= frames[framesCount - IKCONSTRAINT_ENTRIES]) { /* Time is after last frame. */
 	if (time >= frames[framesCount - IKCONSTRAINT_ENTRIES]) { /* Time is after last frame. */
-		if (setupPose) {
+		if (pose == SP_MIX_POSE_SETUP) {
 			constraint->mix = constraint->data->mix + (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->data->mix) * alpha;
 			constraint->mix = constraint->data->mix + (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->data->mix) * alpha;
-			constraint->bendDirection = mixingOut ? constraint->data->bendDirection
+			constraint->bendDirection = direction == SP_MIX_DIRECTION_OUT ? constraint->data->bendDirection
 												 : (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION];
 												 : (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION];
 		} else {
 		} else {
 			constraint->mix += (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->mix) * alpha;
 			constraint->mix += (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->mix) * alpha;
-			if (!mixingOut) constraint->bendDirection = (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION];
+			if (direction == SP_MIX_DIRECTION_IN) constraint->bendDirection = (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION];
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -1112,12 +1177,12 @@ void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skel
 	frameTime = self->frames[frame];
 	frameTime = self->frames[frame];
 	percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / IKCONSTRAINT_ENTRIES - 1, 1 - (time - frameTime) / (self->frames[frame + IKCONSTRAINT_PREV_TIME] - frameTime));
 	percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / IKCONSTRAINT_ENTRIES - 1, 1 - (time - frameTime) / (self->frames[frame + IKCONSTRAINT_PREV_TIME] - frameTime));
 
 
-	if (setupPose) {
+	if (pose == SP_MIX_POSE_SETUP) {
 		constraint->mix = constraint->data->mix + (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->data->mix) * alpha;
 		constraint->mix = constraint->data->mix + (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->data->mix) * alpha;
-		constraint->bendDirection = mixingOut ? constraint->data->bendDirection : (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION];
+		constraint->bendDirection = direction == SP_MIX_DIRECTION_OUT ? constraint->data->bendDirection : (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION];
 	} else {
 	} else {
 		constraint->mix += (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->mix) * alpha;
 		constraint->mix += (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->mix) * alpha;
-		if (!mixingOut) constraint->bendDirection = (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION];
+		if (direction == SP_MIX_DIRECTION_IN) constraint->bendDirection = (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION];
 	}
 	}
 
 
 	UNUSED(lastTime);
 	UNUSED(lastTime);
@@ -1152,7 +1217,7 @@ static const int TRANSFORMCONSTRAINT_SCALE = 3;
 static const int TRANSFORMCONSTRAINT_SHEAR = 4;
 static const int TRANSFORMCONSTRAINT_SHEAR = 4;
 
 
 void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
 void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
-									spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut) {
+									spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	int frame;
 	int frame;
 	float frameTime, percent, rotate, translate, scale, shear;
 	float frameTime, percent, rotate, translate, scale, shear;
 	spTransformConstraint* constraint;
 	spTransformConstraint* constraint;
@@ -1162,14 +1227,23 @@ void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleto
 
 
 	constraint = skeleton->transformConstraints[self->transformConstraintIndex];
 	constraint = skeleton->transformConstraints[self->transformConstraintIndex];
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			spTransformConstraintData* data = constraint->data;
-			constraint->rotateMix = data->rotateMix;
-			constraint->translateMix = data->translateMix;
-			constraint->scaleMix = data->scaleMix;
-			constraint->shearMix = data->shearMix;
+		spTransformConstraintData* data = constraint->data;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				constraint->rotateMix = data->rotateMix;
+				constraint->translateMix = data->translateMix;
+				constraint->scaleMix = data->scaleMix;
+				constraint->shearMix = data->shearMix;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				constraint->rotateMix += (data->rotateMix - constraint->rotateMix) * alpha;
+				constraint->translateMix += (data->translateMix - constraint->translateMix) * alpha;
+				constraint->scaleMix += (data->scaleMix - constraint->scaleMix) * alpha;
+				constraint->shearMix += (data->shearMix - constraint->shearMix) * alpha;
 		}
 		}
 		return;
 		return;
+		return;
 	}
 	}
 
 
 	frames = self->frames;
 	frames = self->frames;
@@ -1196,7 +1270,7 @@ void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleto
 		scale += (frames[frame + TRANSFORMCONSTRAINT_SCALE] - scale) * percent;
 		scale += (frames[frame + TRANSFORMCONSTRAINT_SCALE] - scale) * percent;
 		shear += (frames[frame + TRANSFORMCONSTRAINT_SHEAR] - shear) * percent;
 		shear += (frames[frame + TRANSFORMCONSTRAINT_SHEAR] - shear) * percent;
 	}
 	}
-	if (setupPose) {
+	if (pose == SP_MIX_POSE_SETUP) {
 		spTransformConstraintData* data = constraint->data;
 		spTransformConstraintData* data = constraint->data;
 		constraint->rotateMix = data->rotateMix + (rotate - data->rotateMix) * alpha;
 		constraint->rotateMix = data->rotateMix + (rotate - data->rotateMix) * alpha;
 		constraint->translateMix = data->translateMix + (translate - data->translateMix) * alpha;
 		constraint->translateMix = data->translateMix + (translate - data->translateMix) * alpha;
@@ -1238,7 +1312,7 @@ static const int PATHCONSTRAINTPOSITION_PREV_VALUE = -1;
 static const int PATHCONSTRAINTPOSITION_VALUE = 1;
 static const int PATHCONSTRAINTPOSITION_VALUE = 1;
 
 
 void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
 void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
-		spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	int frame;
 	int frame;
 	float frameTime, percent, position;
 	float frameTime, percent, position;
 	spPathConstraint* constraint;
 	spPathConstraint* constraint;
@@ -1248,8 +1322,13 @@ void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkele
 
 
 	constraint = skeleton->pathConstraints[self->pathConstraintIndex];
 	constraint = skeleton->pathConstraints[self->pathConstraintIndex];
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			constraint->position = constraint->data->position;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				constraint->position = constraint->data->position;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				constraint->position += (constraint->data->position - constraint->position) * alpha;
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -1268,7 +1347,7 @@ void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkele
 
 
 		position += (frames[frame + PATHCONSTRAINTPOSITION_VALUE] - position) * percent;
 		position += (frames[frame + PATHCONSTRAINTPOSITION_VALUE] - position) * percent;
 	}
 	}
-	if (setupPose)
+	if (pose == SP_MIX_POSE_SETUP)
 		constraint->position = constraint->data->position + (position - constraint->data->position) * alpha;
 		constraint->position = constraint->data->position + (position - constraint->data->position) * alpha;
 	else
 	else
 		constraint->position += (position - constraint->position) * alpha;
 		constraint->position += (position - constraint->position) * alpha;
@@ -1298,7 +1377,7 @@ static const int PATHCONSTRAINTSPACING_PREV_VALUE = -1;
 static const int PATHCONSTRAINTSPACING_VALUE = 1;
 static const int PATHCONSTRAINTSPACING_VALUE = 1;
 
 
 void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
 void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
-		spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut) {
+		spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	int frame;
 	int frame;
 	float frameTime, percent, spacing;
 	float frameTime, percent, spacing;
 	spPathConstraint* constraint;
 	spPathConstraint* constraint;
@@ -1308,8 +1387,13 @@ void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkelet
 
 
 	constraint = skeleton->pathConstraints[self->pathConstraintIndex];
 	constraint = skeleton->pathConstraints[self->pathConstraintIndex];
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			constraint->spacing = constraint->data->spacing;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				constraint->spacing = constraint->data->spacing;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				constraint->spacing += (constraint->data->spacing - constraint->spacing) * alpha;
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -1329,7 +1413,7 @@ void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkelet
 		spacing += (frames[frame + PATHCONSTRAINTSPACING_VALUE] - spacing) * percent;
 		spacing += (frames[frame + PATHCONSTRAINTSPACING_VALUE] - spacing) * percent;
 	}
 	}
 
 
-	if (setupPose)
+	if (pose == SP_MIX_POSE_SETUP)
 		constraint->spacing = constraint->data->spacing + (spacing - constraint->data->spacing) * alpha;
 		constraint->spacing = constraint->data->spacing + (spacing - constraint->data->spacing) * alpha;
 	else
 	else
 		constraint->spacing += (spacing - constraint->spacing) * alpha;
 		constraint->spacing += (spacing - constraint->spacing) * alpha;
@@ -1362,7 +1446,7 @@ static const int PATHCONSTRAINTMIX_ROTATE = 1;
 static const int PATHCONSTRAINTMIX_TRANSLATE = 2;
 static const int PATHCONSTRAINTMIX_TRANSLATE = 2;
 
 
 void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
 void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time,
-											spEvent** firedEvents, int* eventsCount, float alpha, int setupPose, int mixingOut) {
+											spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) {
 	int frame;
 	int frame;
 	float frameTime, percent, rotate, translate;
 	float frameTime, percent, rotate, translate;
 	spPathConstraint* constraint;
 	spPathConstraint* constraint;
@@ -1372,9 +1456,15 @@ void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton*
 
 
 	constraint = skeleton->pathConstraints[self->pathConstraintIndex];
 	constraint = skeleton->pathConstraints[self->pathConstraintIndex];
 	if (time < self->frames[0]) {
 	if (time < self->frames[0]) {
-		if (setupPose) {
-			constraint->rotateMix = constraint->data->rotateMix;
-			constraint->translateMix = constraint->data->translateMix;
+		switch (pose) {
+			case SP_MIX_POSE_SETUP:
+				constraint->rotateMix = constraint->data->rotateMix;
+				constraint->translateMix = constraint->data->translateMix;
+				return;
+			case SP_MIX_POSE_CURRENT:
+			case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
+				constraint->rotateMix += (constraint->data->rotateMix - constraint->rotateMix) * alpha;
+				constraint->translateMix += (constraint->data->translateMix - constraint->translateMix) * alpha;
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -1397,7 +1487,7 @@ void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton*
 		translate += (frames[frame + PATHCONSTRAINTMIX_TRANSLATE] - translate) * percent;
 		translate += (frames[frame + PATHCONSTRAINTMIX_TRANSLATE] - translate) * percent;
 	}
 	}
 
 
-	if (setupPose) {
+	if (pose == SP_MIX_POSE_SETUP) {
 		constraint->rotateMix = constraint->data->rotateMix + (rotate - constraint->data->rotateMix) * alpha;
 		constraint->rotateMix = constraint->data->rotateMix + (rotate - constraint->data->rotateMix) * alpha;
 		constraint->translateMix = constraint->data->translateMix + (translate - constraint->data->translateMix) * alpha;
 		constraint->translateMix = constraint->data->translateMix + (translate - constraint->data->translateMix) * alpha;
 	} else {
 	} else {

+ 25 - 24
spine-c/spine-c/src/spine/AnimationState.c

@@ -50,8 +50,8 @@ void spAnimationState_disposeStatics () {
 void _spAnimationState_disposeTrackEntry (spTrackEntry* entry);
 void _spAnimationState_disposeTrackEntry (spTrackEntry* entry);
 void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry);
 void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry);
 int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta);
 int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta);
-float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* entry, spSkeleton* skeleton);
-void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, int /*boolean*/ setupPose, float* timelinesRotation, int i, int /*boolean*/ firstFrame);
+float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* entry, spSkeleton* skeleton, spMixPose currentPose);
+void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixPose pose, float* timelinesRotation, int i, int /*boolean*/ firstFrame);
 void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime);
 void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime);
 void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt);
 void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt);
 spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index);
 spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index);
@@ -338,6 +338,8 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
 	float* timelinesRotation;
 	float* timelinesRotation;
 	spTimeline* timeline;
 	spTimeline* timeline;
 	int applied = 0;
 	int applied = 0;
+	spMixPose currentPose;
+	spMixPose pose;
 
 
 	if (internal->animationsChanged) _spAnimationState_animationsChanged(self);
 	if (internal->animationsChanged) _spAnimationState_animationsChanged(self);
 
 
@@ -346,11 +348,12 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
 		current = self->tracks[i];
 		current = self->tracks[i];
 		if (!current || current->delay > 0) continue;
 		if (!current || current->delay > 0) continue;
 		applied = -1;
 		applied = -1;
+		currentPose = i == 0 ? SP_MIX_POSE_CURRENT : SP_MIX_POSE_CURRENT_LAYERED;
 
 
 		/* Apply mixing from entries first. */
 		/* Apply mixing from entries first. */
 		mix = current->alpha;
 		mix = current->alpha;
 		if (current->mixingFrom)
 		if (current->mixingFrom)
-            mix *= _spAnimationState_applyMixingFrom(self, current, skeleton);
+            mix *= _spAnimationState_applyMixingFrom(self, current, skeleton, currentPose);
         else if (current->trackTime >= current->trackEnd && current->next == 0)
         else if (current->trackTime >= current->trackEnd && current->next == 0)
             mix = 0;
             mix = 0;
 
 
@@ -360,7 +363,7 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
 		timelines = current->animation->timelines;
 		timelines = current->animation->timelines;
 		if (mix == 1) {
 		if (mix == 1) {
 			for (ii = 0; ii < timelineCount; ii++)
 			for (ii = 0; ii < timelineCount; ii++)
-				spTimeline_apply(timelines[ii], skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, 1, 1, 0);
+				spTimeline_apply(timelines[ii], skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, 1, SP_MIX_POSE_SETUP, SP_MIX_DIRECTION_IN);
 		} else {
 		} else {
 			spIntArray* timelineData = current->timelineData;
 			spIntArray* timelineData = current->timelineData;
 
 
@@ -370,10 +373,11 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
 
 
 			for (ii = 0; ii < timelineCount; ii++) {
 			for (ii = 0; ii < timelineCount; ii++) {
 				timeline = timelines[ii];
 				timeline = timelines[ii];
+				pose = timelineData->items[ii] >= FIRST ? SP_MIX_POSE_SETUP : currentPose;
 				if (timeline->type == SP_TIMELINE_ROTATE)
 				if (timeline->type == SP_TIMELINE_ROTATE)
-					_spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, timelineData->items[ii] >= FIRST, timelinesRotation, ii << 1, firstFrame);
+					_spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame);
 				else
 				else
-					spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, timelineData->items[ii] >= FIRST, 0);
+					spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, pose, SP_MIX_DIRECTION_IN);
 			}
 			}
 		}
 		}
 		_spAnimationState_queueEvents(self, current, animationTime);
 		_spAnimationState_queueEvents(self, current, animationTime);
@@ -386,7 +390,7 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
 	return applied;
 	return applied;
 }
 }
 
 
-float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* to, spSkeleton* skeleton) {
+float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* to, spSkeleton* skeleton, spMixPose currentPose) {
 	_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
 	_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
 	float mix;
 	float mix;
 	spEvent** events;
 	spEvent** events;
@@ -403,12 +407,12 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t
 	float alpha;
 	float alpha;
 	int /*boolean*/ firstFrame;
 	int /*boolean*/ firstFrame;
 	float* timelinesRotation;
 	float* timelinesRotation;
-	int /*boolean*/ first;
+	spMixPose pose;
 	int i;
 	int i;
 	spTrackEntry* dipMix;
 	spTrackEntry* dipMix;
 
 
 	spTrackEntry* from = to->mixingFrom;
 	spTrackEntry* from = to->mixingFrom;
-	if (from->mixingFrom) _spAnimationState_applyMixingFrom(self, from, skeleton);
+	if (from->mixingFrom) _spAnimationState_applyMixingFrom(self, from, skeleton, currentPose);
 
 
 	if (to->mixDuration == 0) /* Single frame mix to undo mixingFrom changes. */
 	if (to->mixDuration == 0) /* Single frame mix to undo mixingFrom changes. */
 		mix = 1;
 		mix = 1;
@@ -431,26 +435,27 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t
 	if (firstFrame) _spAnimationState_resizeTimelinesRotation(from, timelineCount << 1);
 	if (firstFrame) _spAnimationState_resizeTimelinesRotation(from, timelineCount << 1);
 	timelinesRotation = from->timelinesRotation;
 	timelinesRotation = from->timelinesRotation;
 
 
-	first = 0;
 	alphaDip = from->alpha * to->interruptAlpha; alphaMix = alphaDip * (1 - mix);
 	alphaDip = from->alpha * to->interruptAlpha; alphaMix = alphaDip * (1 - mix);
 	from->totalAlpha = 0;
 	from->totalAlpha = 0;
 	for (i = 0; i < timelineCount; i++) {
 	for (i = 0; i < timelineCount; i++) {
 		spTimeline* timeline = timelines[i];
 		spTimeline* timeline = timelines[i];
 		switch (timelineData->items[i]) {
 		switch (timelineData->items[i]) {
 			case SUBSEQUENT:
 			case SUBSEQUENT:
-				first = 0;
+				if (!attachments && timeline->type == SP_TIMELINE_ATTACHMENT) continue;
+				if (!drawOrder && timeline->type == SP_TIMELINE_DRAWORDER) continue;
+				pose = currentPose;
 				alpha = alphaMix;
 				alpha = alphaMix;
 				break;
 				break;
 			case FIRST:
 			case FIRST:
-				first = 1;
+				pose = SP_MIX_POSE_SETUP;
 				alpha = alphaMix;
 				alpha = alphaMix;
 				break;
 				break;
 			case DIP:
 			case DIP:
-				first = 1;
+				pose = SP_MIX_POSE_SETUP;
 				alpha = alphaDip;
 				alpha = alphaDip;
 				break;
 				break;
 			default:
 			default:
-				first = 1;
+				pose = SP_MIX_POSE_SETUP;
 				alpha = alphaDip;
 				alpha = alphaDip;
 				dipMix = timelineDipMix->items[i];
 				dipMix = timelineDipMix->items[i];
 				alpha *= MAX(0, 1 - dipMix->mixTime / dipMix->mixDuration);
 				alpha *= MAX(0, 1 - dipMix->mixTime / dipMix->mixDuration);
@@ -458,13 +463,9 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t
 		}
 		}
 		from->totalAlpha += alpha;
 		from->totalAlpha += alpha;
 		if (timeline->type == SP_TIMELINE_ROTATE)
 		if (timeline->type == SP_TIMELINE_ROTATE)
-			_spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, first, timelinesRotation, i << 1, firstFrame);
+			_spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame);
 		else {
 		else {
-			if (!first) {
-				if (!attachments && timeline->type == SP_TIMELINE_ATTACHMENT) continue;
-				if (!drawOrder && timeline->type == SP_TIMELINE_DRAWORDER) continue;
-			}
-			spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount, alpha, first, 1);
+			spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount, alpha, pose, SP_MIX_DIRECTION_OUT);
 		}
 		}
 	}
 	}
 
 
@@ -477,7 +478,7 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t
 	return mix;
 	return mix;
 }
 }
 
 
-void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, int /*boolean*/ setupPose, float* timelinesRotation, int i, int /*boolean*/ firstFrame) {
+void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixPose pose, float* timelinesRotation, int i, int /*boolean*/ firstFrame) {
 	spRotateTimeline *rotateTimeline;
 	spRotateTimeline *rotateTimeline;
 	float *frames;
 	float *frames;
 	spBone* bone;
 	spBone* bone;
@@ -492,7 +493,7 @@ void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline*
 	if (firstFrame) timelinesRotation[i] = 0;
 	if (firstFrame) timelinesRotation[i] = 0;
 
 
 	if (alpha == 1) {
 	if (alpha == 1) {
-		spTimeline_apply(timeline, skeleton, 0, time, 0, 0, 1, setupPose, 0);
+		spTimeline_apply(timeline, skeleton, 0, time, 0, 0, 1, pose, SP_MIX_DIRECTION_IN);
 		return;
 		return;
 	}
 	}
 
 
@@ -500,7 +501,7 @@ void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline*
 	frames = rotateTimeline->frames;
 	frames = rotateTimeline->frames;
 	bone = skeleton->bones[rotateTimeline->boneIndex];
 	bone = skeleton->bones[rotateTimeline->boneIndex];
 	if (time < frames[0]) {
 	if (time < frames[0]) {
-		if (setupPose) {
+		if (pose == SP_MIX_POSE_SETUP) {
 			bone->rotation = bone->data->rotation;
 			bone->rotation = bone->data->rotation;
 		}
 		}
 		return; /* Time is before first frame. */
 		return; /* Time is before first frame. */
@@ -523,7 +524,7 @@ void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline*
 	}
 	}
 
 
 	/* Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. */
 	/* Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. */
-	r1 = setupPose ? bone->data->rotation : bone->rotation;
+	r1 = pose == SP_MIX_POSE_SETUP ? bone->data->rotation : bone->rotation;
 	diff = r2 - r1;
 	diff = r2 - r1;
 	if (diff == 0) {
 	if (diff == 0) {
 		total = timelinesRotation[i];
 		total = timelinesRotation[i];

+ 1 - 0
spine-c/spine-c/src/spine/BoundingBoxAttachment.c

@@ -41,6 +41,7 @@ void _spBoundingBoxAttachment_dispose (spAttachment* attachment) {
 
 
 spBoundingBoxAttachment* spBoundingBoxAttachment_create (const char* name) {
 spBoundingBoxAttachment* spBoundingBoxAttachment_create (const char* name) {
 	spBoundingBoxAttachment* self = NEW(spBoundingBoxAttachment);
 	spBoundingBoxAttachment* self = NEW(spBoundingBoxAttachment);
+	_spVertexAttachment_init(SUPER(self));
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_BOUNDING_BOX, _spBoundingBoxAttachment_dispose);
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_BOUNDING_BOX, _spBoundingBoxAttachment_dispose);
 	return self;
 	return self;
 }
 }

+ 1 - 0
spine-c/spine-c/src/spine/ClippingAttachment.c

@@ -41,6 +41,7 @@ void _spClippingAttachment_dispose (spAttachment* attachment) {
 
 
 spClippingAttachment* spClippingAttachment_create (const char* name) {
 spClippingAttachment* spClippingAttachment_create (const char* name) {
 	spClippingAttachment* self = NEW(spClippingAttachment);
 	spClippingAttachment* self = NEW(spClippingAttachment);
+	_spVertexAttachment_init(SUPER(self));
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_CLIPPING, _spClippingAttachment_dispose);
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_CLIPPING, _spClippingAttachment_dispose);
 	self->endSlot = 0;
 	self->endSlot = 0;
 	return self;
 	return self;

+ 1 - 0
spine-c/spine-c/src/spine/MeshAttachment.c

@@ -47,6 +47,7 @@ void _spMeshAttachment_dispose (spAttachment* attachment) {
 
 
 spMeshAttachment* spMeshAttachment_create (const char* name) {
 spMeshAttachment* spMeshAttachment_create (const char* name) {
 	spMeshAttachment* self = NEW(spMeshAttachment);
 	spMeshAttachment* self = NEW(spMeshAttachment);
+	_spVertexAttachment_init(SUPER(self));
 	spColor_setFromFloats(&self->color, 1, 1, 1, 1);
 	spColor_setFromFloats(&self->color, 1, 1, 1, 1);
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_MESH, _spMeshAttachment_dispose);
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_MESH, _spMeshAttachment_dispose);
 	return self;
 	return self;

+ 1 - 0
spine-c/spine-c/src/spine/PathAttachment.c

@@ -42,6 +42,7 @@ void _spPathAttachment_dispose (spAttachment* attachment) {
 
 
 spPathAttachment* spPathAttachment_create (const char* name) {
 spPathAttachment* spPathAttachment_create (const char* name) {
 	spPathAttachment* self = NEW(spPathAttachment);
 	spPathAttachment* self = NEW(spPathAttachment);
+	_spVertexAttachment_init(SUPER(self));
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_PATH, _spPathAttachment_dispose);
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_PATH, _spPathAttachment_dispose);
 	return self;
 	return self;
 }
 }

+ 1 - 0
spine-c/spine-c/src/spine/PointAttachment.c

@@ -41,6 +41,7 @@ void _spPointAttachment_dispose (spAttachment* attachment) {
 
 
 spPointAttachment* spPointAttachment_create (const char* name) {
 spPointAttachment* spPointAttachment_create (const char* name) {
 	spPointAttachment* self = NEW(spPointAttachment);
 	spPointAttachment* self = NEW(spPointAttachment);
+	_spVertexAttachment_init(SUPER(self));
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_POINT, _spPointAttachment_dispose);
 	_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_POINT, _spPointAttachment_dispose);
 	return self;
 	return self;
 }
 }

+ 7 - 0
spine-c/spine-c/src/spine/VertexAttachment.c

@@ -31,6 +31,13 @@
 #include <spine/VertexAttachment.h>
 #include <spine/VertexAttachment.h>
 #include <spine/extension.h>
 #include <spine/extension.h>
 
 
+/* FIXME this is not thread-safe */
+static int nextID = 0;
+
+void _spVertexAttachment_init (spVertexAttachment* attachment) {
+	attachment->id = (nextID++ & 65535) << 11;
+}
+
 void _spVertexAttachment_deinit (spVertexAttachment* attachment) {
 void _spVertexAttachment_deinit (spVertexAttachment* attachment) {
 	_spAttachment_deinit(SUPER(attachment));
 	_spAttachment_deinit(SUPER(attachment));
 	FREE(attachment->bones);
 	FREE(attachment->bones);