diff --git a/spine-c/spine-c/include/spine/Animation.h b/spine-c/spine-c/include/spine/Animation.h index e47a835ce..178558ed8 100644 --- a/spine-c/spine-c/include/spine/Animation.h +++ b/spine-c/spine-c/include/spine/Animation.h @@ -60,10 +60,11 @@ typedef struct spAnimation { } spAnimation; typedef enum { - SP_MIX_POSE_SETUP, - SP_MIX_POSE_CURRENT, - SP_MIX_POSE_CURRENT_LAYERED -} spMixPose; + SP_MIX_BLEND_SETUP, + SP_MIX_BLEND_FIRST, + SP_MIX_BLEND_REPLACE, + SP_MIX_BLEND_ADD +} spMixBlend; typedef enum { SP_MIX_DIRECTION_IN, @@ -77,7 +78,7 @@ SP_API void spAnimation_dispose (spAnimation* self); * @param lastTime The last time the animation was applied. * @param events Any triggered events are added. May be null.*/ SP_API void spAnimation_apply (const spAnimation* self, struct spSkeleton* skeleton, float lastTime, float time, int loop, - spEvent** events, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction); + spEvent** events, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction); #ifdef SPINE_SHORT_NAMES typedef spAnimation Animation; @@ -120,7 +121,7 @@ struct spTimeline { SP_API void spTimeline_dispose (spTimeline* self); SP_API void spTimeline_apply (const spTimeline* self, struct spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction); + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction); SP_API int spTimeline_getPropertyId (const spTimeline* self); #ifdef SPINE_SHORT_NAMES diff --git a/spine-c/spine-c/include/spine/AnimationState.h b/spine-c/spine-c/include/spine/AnimationState.h index 224581961..4c93afb3b 100644 --- a/spine-c/spine-c/include/spine/AnimationState.h +++ b/spine-c/spine-c/include/spine/AnimationState.h @@ -63,6 +63,7 @@ struct spTrackEntry { float animationStart, animationEnd, animationLast, nextAnimationLast; float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale; float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha; + spMixBlend mixBlend; spIntArray* timelineData; spTrackEntryArray* timelineDipMix; float* timelinesRotation; @@ -81,6 +82,7 @@ struct spTrackEntry { animationStart(0), animationEnd(0), animationLast(0), nextAnimationLast(0), delay(0), trackTime(0), trackLast(0), nextTrackLast(0), trackEnd(0), timeScale(0), alpha(0), mixTime(0), mixDuration(0), interruptAlpha(0), totalAlpha(0), + mixBlend(SP_MIX_BLEND_REPLACE), timelineData(0), timelineDipMix(0), timelinesRotation(0), diff --git a/spine-c/spine-c/include/spine/extension.h b/spine-c/spine-c/include/spine/extension.h index 0823b5667..b5a947eb1 100644 --- a/spine-c/spine-c/include/spine/extension.h +++ b/spine-c/spine-c/include/spine/extension.h @@ -287,7 +287,7 @@ void _spVertexAttachment_deinit (spVertexAttachment* self); void _spTimeline_init (spTimeline* self, spTimelineType type, void (*dispose) (spTimeline* self), void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction), + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction), int (*getPropertyId) (const spTimeline* self)); void _spTimeline_deinit (spTimeline* self); @@ -300,7 +300,7 @@ void _spTimeline_deinit (spTimeline* self); void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int framesCount, void (*dispose) (spTimeline* self), - void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction), + void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction), int (*getPropertyId) (const spTimeline* self)); void _spCurveTimeline_deinit (spCurveTimeline* self); int _spCurveTimeline_binarySearch (float *values, int valuesLength, float target, int step); diff --git a/spine-c/spine-c/src/spine/Animation.c b/spine-c/spine-c/src/spine/Animation.c index 152007a47..7c385b281 100644 --- a/spine-c/spine-c/src/spine/Animation.c +++ b/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, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { int i, n = self->timelinesCount; if (loop && self->duration) { @@ -60,21 +60,21 @@ void spAnimation_apply (const spAnimation* self, spSkeleton* skeleton, float las } for (i = 0; i < n; ++i) - spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, alpha, pose, direction); + spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, alpha, blend, direction); } /**/ typedef struct _spTimelineVtable { void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction); + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction); int (*getPropertyId) (const spTimeline* self); void (*dispose) (spTimeline* self); } _spTimelineVtable; void _spTimeline_init (spTimeline* self, spTimelineType type, /**/ void (*dispose) (spTimeline* self), /**/ - void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction), + void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction), int (*getPropertyId) (const spTimeline* self)) { CONST_CAST(spTimelineType, self->type) = type; 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, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - VTABLE(spTimeline, self)->apply(self, skeleton, lastTime, time, firedEvents, eventsCount, alpha, pose, direction); + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { + VTABLE(spTimeline, self)->apply(self, skeleton, lastTime, time, firedEvents, eventsCount, alpha, blend, direction); } 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 (*dispose) (spTimeline* self), /**/ - void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction), + void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction), int (*getPropertyId)(const spTimeline* self)) { _spTimeline_init(SUPER(self), type, dispose, apply, getPropertyId); 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. **/ struct spBaseTimeline* _spBaseTimeline_create (int framesCount, spTimelineType type, int frameSize, /**/ void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction), + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction), int (*getPropertyId) (const spTimeline* self)) { struct spBaseTimeline* self = NEW(struct spBaseTimeline); _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, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { spBone *bone; int frame; float prevRotation, frameTime, percent, r; @@ -248,26 +248,33 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, bone = skeleton->bones[self->boneIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: bone->rotation = bone->data->rotation; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: r = bone->data->rotation - bone->rotation; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; bone->rotation += r * alpha; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } if (time >= self->frames[self->framesCount - ROTATE_ENTRIES]) { /* Time is after last frame. */ - if (pose == SP_MIX_POSE_SETUP) - bone->rotation = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] * alpha; - else { - r = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] - bone->rotation; - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; /* Wrap within -180 and 180. */ - bone->rotation += r * alpha; + r = self->frames[self->framesCount + ROTATE_PREV_ROTATION]; + switch (blend) { + case SP_MIX_BLEND_SETUP: + bone->rotation = bone->data->rotation + r * alpha; + break; + case SP_MIX_BLEND_FIRST: + case SP_MIX_BLEND_REPLACE: + r += bone->data->rotation - bone->rotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; /* Wrap within -180 and 180. */ + case SP_MIX_BLEND_ADD: + bone->rotation += r * alpha; } return; } @@ -279,15 +286,16 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, percent = spCurveTimeline_getCurvePercent(SUPER(self), (frame >> 1) - 1, 1 - (time - frameTime) / (self->frames[frame + ROTATE_PREV_TIME] - frameTime)); r = self->frames[frame + ROTATE_ROTATION] - prevRotation; - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - r = prevRotation + r * percent; - if (pose == SP_MIX_POSE_SETUP) { - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - bone->rotation = bone->data->rotation + r * alpha; - } else { - r = bone->data->rotation + r - bone->rotation; - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - bone->rotation += r * alpha; + r = prevRotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * percent; + switch (blend) { + case SP_MIX_BLEND_SETUP: + bone->rotation = bone->data->rotation + (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha; + break; + case SP_MIX_BLEND_FIRST: + case SP_MIX_BLEND_REPLACE: + r += bone->data->rotation - bone->rotation; + case SP_MIX_BLEND_ADD: + bone->rotation += (r - (16384 - (int)(16384.499999999996 - r / 360)) * 360) * alpha; } UNUSED(lastTime); @@ -315,7 +323,7 @@ static const int TRANSLATE_PREV_TIME = -3, TRANSLATE_PREV_X = -2, TRANSLATE_PREV static const int TRANSLATE_X = 1, TRANSLATE_Y = 2; void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { spBone *bone; int frame; float frameTime, percent; @@ -327,15 +335,17 @@ void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto bone = skeleton->bones[self->boneIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: bone->x = bone->data->x; bone->y = bone->data->y; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: bone->x += (bone->data->x - bone->x) * alpha; bone->y += (bone->data->y - bone->y) * alpha; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -357,12 +367,19 @@ void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto x += (frames[frame + TRANSLATE_X] - x) * percent; y += (frames[frame + TRANSLATE_Y] - y) * percent; } - if (pose == SP_MIX_POSE_SETUP) { - bone->x = bone->data->x + x * alpha; - bone->y = bone->data->y + y * alpha; - } else { - bone->x += (bone->data->x + x - bone->x) * alpha; - bone->y += (bone->data->y + y - bone->y) * alpha; + switch (blend) { + case SP_MIX_BLEND_SETUP: + bone->x = bone->data->x + x * alpha; + bone->y = bone->data->y + y * alpha; + break; + case SP_MIX_BLEND_FIRST: + case SP_MIX_BLEND_REPLACE: + bone->x += (bone->data->x + x - bone->x) * alpha; + bone->y += (bone->data->y + y - bone->y) * alpha; + break; + case SP_MIX_BLEND_ADD: + bone->x += x * alpha; + bone->y += y * alpha; } UNUSED(lastTime); @@ -388,7 +405,7 @@ void spTranslateTimeline_setFrame (spTranslateTimeline* self, int frameIndex, fl /**/ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { spBone *bone; int frame; float frameTime, percent, x, y; @@ -399,15 +416,17 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f bone = skeleton->bones[self->boneIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: bone->scaleX = bone->data->scaleX; bone->scaleY = bone->data->scaleY; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: bone->scaleX += (bone->data->scaleX - bone->scaleX) * alpha; bone->scaleY += (bone->data->scaleY - bone->scaleY) * alpha; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -430,27 +449,56 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f y = (y + (frames[frame + TRANSLATE_Y] - y) * percent) * bone->data->scaleY; } if (alpha == 1) { - bone->scaleX = x; - bone->scaleY = y; + if (blend == SP_MIX_BLEND_ADD) { + bone->scaleX += x - bone->data->scaleX; + bone->scaleY += y - bone->data->scaleY; + } else { + bone->scaleX = x; + bone->scaleY = y; + } } else { float bx, by; - if (pose == SP_MIX_POSE_SETUP) { - bx = bone->data->scaleX; - by = bone->data->scaleY; - } else { - bx = bone->scaleX; - by = bone->scaleY; - } - /* Mixing out uses sign of setup or current pose, else use sign of key. */ if (direction == SP_MIX_DIRECTION_OUT) { - x = ABS(x) * SIGNUM(bx); - y = ABS(y) * SIGNUM(by); + switch (blend) { + case SP_MIX_BLEND_SETUP: + bx = bone->data->scaleX; + by = bone->data->scaleY; + bone->scaleX = bx + (ABS(x) * SIGNUM(bx) - bx) * alpha; + bone->scaleY = by + (ABS(y) * SIGNUM(by) - by) * alpha; + break; + case SP_MIX_BLEND_FIRST: + case SP_MIX_BLEND_REPLACE: + bx = bone->scaleX; + by = bone->scaleY; + bone->scaleX = bx + (ABS(x) * SIGNUM(bx) - bx) * alpha; + bone->scaleY = by + (ABS(y) * SIGNUM(by) - by) * alpha; + break; + case SP_MIX_BLEND_ADD: + bx = bone->scaleX; + by = bone->scaleY; + bone->scaleX = bx + (ABS(x) * SIGNUM(bx) - bone->data->scaleX) * alpha; + bone->scaleY = by + (ABS(y) * SIGNUM(by) - bone->data->scaleY) * alpha; + } } else { - bx = ABS(bx) * SIGNUM(x); - by = ABS(by) * SIGNUM(y); + switch (blend) { + case SP_MIX_BLEND_SETUP: + bx = ABS(bone->data->scaleX) * SIGNUM(x); + by = ABS(bone->data->scaleY) * SIGNUM(y); + bone->scaleX = bx + (x - bx) * alpha; + bone->scaleY = by + (y - by) * alpha; + break; + case SP_MIX_BLEND_FIRST: + case SP_MIX_BLEND_REPLACE: + bone->scaleX += (x - bone->scaleX * SIGNUM(x)) * alpha; + bone->scaleY += (y - bone->scaleY * SIGNUM(y)) * alpha; + break; + case SP_MIX_BLEND_ADD: + bx = SIGNUM(x); + by = SIGNUM(y); + bone->scaleX = ABS(bone->scaleX) * bx + (x - ABS(bone->data->scaleX) * bx) * alpha; + bone->scaleY = ABS(bone->scaleY) * by + (y - ABS(bone->data->scaleY) * by) * alpha; + } } - bone->scaleX = bx + (x - bx) * alpha; - bone->scaleY = by + (y - by) * alpha; } UNUSED(lastTime); @@ -473,7 +521,7 @@ void spScaleTimeline_setFrame (spScaleTimeline* self, int frameIndex, float time /**/ void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { spBone *bone; int frame; float frameTime, percent, x, y; @@ -486,15 +534,17 @@ void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f frames = self->frames; framesCount = self->framesCount; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: bone->shearX = bone->data->shearX; bone->shearY = bone->data->shearY; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: bone->shearX += (bone->data->shearX - bone->shearX) * alpha; bone->shearY += (bone->data->shearY - bone->shearY) * alpha; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -514,12 +564,19 @@ void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f x = x + (frames[frame + TRANSLATE_X] - x) * percent; y = y + (frames[frame + TRANSLATE_Y] - y) * percent; } - if (pose == SP_MIX_POSE_SETUP) { - bone->shearX = bone->data->shearX + x * alpha; - bone->shearY = bone->data->shearY + y * alpha; - } else { - bone->shearX += (bone->data->shearX + x - bone->shearX) * alpha; - bone->shearY += (bone->data->shearY + y - bone->shearY) * alpha; + switch (blend) { + case SP_MIX_BLEND_SETUP: + bone->shearX = bone->data->shearX + x * alpha; + bone->shearY = bone->data->shearY + y * alpha; + break; + case SP_MIX_BLEND_FIRST: + case SP_MIX_BLEND_REPLACE: + bone->shearX += (bone->data->shearX + x - bone->shearX) * alpha; + bone->shearY += (bone->data->shearY + y - bone->shearY) * alpha; + break; + case SP_MIX_BLEND_ADD: + bone->shearX += x * alpha; + bone->shearY += y * alpha; } UNUSED(lastTime); @@ -545,7 +602,7 @@ 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; void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { spSlot *slot; int frame; float percent, frameTime; @@ -556,16 +613,18 @@ void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f slot = skeleton->slots[self->slotIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: spColor_setFromColor(&slot->color, &slot->data->color); return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: 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); - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -597,7 +656,7 @@ void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f if (alpha == 1) { spColor_setFromFloats(&slot->color, r, g, b, a); } else { - if (pose == SP_MIX_POSE_SETUP) { + if (blend == SP_MIX_BLEND_SETUP) { 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); @@ -632,7 +691,7 @@ 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; void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { spSlot *slot; int frame; float percent, frameTime; @@ -645,12 +704,12 @@ void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton slot = skeleton->slots[self->slotIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: spColor_setFromColor(&slot->color, &slot->data->color); spColor_setFromColor(slot->darkColor, slot->data->darkColor); return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: light = &slot->color; dark = slot->darkColor; setupLight = &slot->data->color; @@ -658,7 +717,9 @@ void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton 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); - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -702,7 +763,7 @@ void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton } else { light = &slot->color; dark = slot->darkColor; - if (pose == SP_MIX_POSE_SETUP) { + if (blend == SP_MIX_BLEND_SETUP) { spColor_setFromColor(light, &slot->data->color); spColor_setFromColor(dark, slot->data->darkColor); } @@ -738,20 +799,20 @@ void spTwoColorTimeline_setFrame (spTwoColorTimeline* self, int frameIndex, floa /**/ void _spAttachmentTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { const char* attachmentName; spAttachmentTimeline* self = (spAttachmentTimeline*)timeline; int frameIndex; spSlot* slot = skeleton->slots[self->slotIndex]; - if (direction == SP_MIX_DIRECTION_OUT && pose == SP_MIX_POSE_SETUP) { + if (direction == SP_MIX_DIRECTION_OUT && blend == SP_MIX_BLEND_SETUP) { const char* attachmentName = slot->data->attachmentName; spSlot_setAttachment(slot, attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); return; } if (time < self->frames[0]) { - if (pose == SP_MIX_POSE_SETUP) { + if (blend == SP_MIX_BLEND_SETUP || blend == SP_MIX_BLEND_FIRST) { attachmentName = slot->data->attachmentName; spSlot_setAttachment(skeleton->slots[self->slotIndex], attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); @@ -815,7 +876,7 @@ void spAttachmentTimeline_setFrame (spAttachmentTimeline* self, int frameIndex, /**/ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { int frame, i, vertexCount; float percent, frameTime; const float* prevVertices; @@ -851,18 +912,18 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, slot->attachmentVerticesCapacity = vertexCount; } } - if (slot->attachmentVerticesCount == 0) alpha = 1; + if (slot->attachmentVerticesCount == 0) blend = SP_MIX_BLEND_SETUP; frameVertices = self->frameVertices; vertices = slot->attachmentVertices; if (time < frames[0]) { /* Time is before first frame. */ spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: slot->attachmentVerticesCount = 0; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: if (alpha == 1) { slot->attachmentVerticesCount = 0; return; @@ -879,7 +940,9 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, vertices[i] *= alpha; } } - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -888,26 +951,59 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, if (time >= frames[framesCount - 1]) { /* Time is after last frame. */ const float* lastVertices = self->frameVertices[framesCount - 1]; if (alpha == 1) { - /* Vertex positions or deform offsets, no alpha. */ - memcpy(vertices, lastVertices, vertexCount * sizeof(float)); - } else if (pose == SP_MIX_POSE_SETUP) { - spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); - if (!vertexAttachment->bones) { - /* Unweighted vertex positions, with alpha. */ - float* setupVertices = vertexAttachment->vertices; - for (i = 0; i < vertexCount; i++) { - float setup = setupVertices[i]; - vertices[i] = setup + (lastVertices[i] - setup) * alpha; + if (blend == SP_MIX_BLEND_ADD) { + spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + if (!vertexAttachment->bones) { + /* Unweighted vertex positions, with alpha. */ + float* setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + vertices[i] += lastVertices[i] - setupVertices[i]; + } + } else { + /* Weighted deform offsets, with alpha. */ + for (i = 0; i < vertexCount; i++) + vertices[i] += lastVertices[i]; } } else { - /* Weighted deform offsets, with alpha. */ - for (i = 0; i < vertexCount; i++) - vertices[i] = lastVertices[i] * alpha; + /* Vertex positions or deform offsets, no alpha. */ + memcpy(vertices, lastVertices, vertexCount * sizeof(float)); } } else { - /* Vertex positions or deform offsets, with alpha. */ - for (i = 0; i < vertexCount; i++) - vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + spVertexAttachment* vertexAttachment; + switch (blend) { + case SP_MIX_BLEND_SETUP: + vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + if (!vertexAttachment->bones) { + /* Unweighted vertex positions, with alpha. */ + float* setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + float setup = setupVertices[i]; + vertices[i] = setup + (lastVertices[i] - setup) * alpha; + } + } else { + /* Weighted deform offsets, with alpha. */ + for (i = 0; i < vertexCount; i++) + vertices[i] = lastVertices[i] * alpha; + } + break; + case SP_MIX_BLEND_FIRST: + case SP_MIX_BLEND_REPLACE: + /* Vertex positions or deform offsets, with alpha. */ + for (i = 0; i < vertexCount; i++) + vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + case SP_MIX_BLEND_ADD: + vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + if (!vertexAttachment->bones) { + /* Unweighted vertex positions, with alpha. */ + float* setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + vertices[i] += (lastVertices[i] - setupVertices[i]) * alpha; + } + } else { + for (i = 0; i < vertexCount; i++) + vertices[i] += lastVertices[i] * alpha; + } + } } return; } @@ -920,32 +1016,65 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, percent = spCurveTimeline_getCurvePercent(SUPER(self), frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); if (alpha == 1) { - /* Vertex positions or deform offsets, no alpha. */ - for (i = 0; i < vertexCount; i++) { - float prev = prevVertices[i]; - vertices[i] = prev + (nextVertices[i] - prev) * percent; - } - } else if (pose == SP_MIX_POSE_SETUP) { - spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); - if (!vertexAttachment->bones) { - /* Unweighted vertex positions, with alpha. */ - float* setupVertices = vertexAttachment->vertices; - for (i = 0; i < vertexCount; i++) { - float prev = prevVertices[i], setup = setupVertices[i]; - vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + if (blend == SP_MIX_BLEND_ADD) { + spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + if (!vertexAttachment->bones) { + float* setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] += prev + (nextVertices[i] - prev) * percent - setupVertices[i]; + } + } else { + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] += prev + (nextVertices[i] - prev) * percent; + } } } else { - /* Weighted deform offsets, with alpha. */ for (i = 0; i < vertexCount; i++) { float prev = prevVertices[i]; - vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + vertices[i] = prev + (nextVertices[i] - prev) * percent; } } } else { - /* Vertex positions or deform offsets, with alpha. */ - for (i = 0; i < vertexCount; i++) { - float prev = prevVertices[i]; - vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + spVertexAttachment* vertexAttachment; + switch (blend) { + case SP_MIX_BLEND_SETUP: + vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + if (!vertexAttachment->bones) { + float *setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i], setup = setupVertices[i]; + vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } else { + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + break; + case SP_MIX_BLEND_FIRST: + case SP_MIX_BLEND_REPLACE: + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + } + break; + case SP_MIX_BLEND_ADD: + vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + if (!vertexAttachment->bones) { + float *setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] += (prev + (nextVertices[i] - prev) * percent - setupVertices[i]) * alpha; + } + } else { + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] += (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } } } @@ -998,13 +1127,13 @@ void spDeformTimeline_setFrame (spDeformTimeline* self, int frameIndex, float ti /** Fires events for frames > lastTime and <= time. */ void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { spEventTimeline* self = (spEventTimeline*)timeline; int frame; if (!firedEvents) return; if (lastTime > time) { /* Fire events after last time for looped animations. */ - _spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventsCount, alpha, pose, direction); + _spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventsCount, alpha, blend, direction); lastTime = -1; } else if (lastTime >= self->frames[self->framesCount - 1]) /* Last time is after last frame. */ return; @@ -1065,19 +1194,19 @@ void spEventTimeline_setFrame (spEventTimeline* self, int frameIndex, spEvent* e /**/ void _spDrawOrderTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { int i; int frame; const int* drawOrderToSetupIndex; spDrawOrderTimeline* self = (spDrawOrderTimeline*)timeline; - if (direction == SP_MIX_DIRECTION_OUT && pose == SP_MIX_POSE_SETUP) { + if (direction == SP_MIX_DIRECTION_OUT && blend == SP_MIX_BLEND_SETUP) { memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); return; } if (time < self->frames[0]) { - if (pose == SP_MIX_POSE_SETUP) memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); + if (blend == SP_MIX_BLEND_SETUP || blend == SP_MIX_BLEND_FIRST) memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); return; } @@ -1147,7 +1276,7 @@ static const int IKCONSTRAINT_PREV_TIME = -3, IKCONSTRAINT_PREV_MIX = -2, IKCONS static const int IKCONSTRAINT_MIX = 1, IKCONSTRAINT_BEND_DIRECTION = 2; void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { int frame; float frameTime, percent, mix; float *frames; @@ -1158,15 +1287,17 @@ void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skel constraint = skeleton->ikConstraints[self->ikConstraintIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: constraint->mix = constraint->data->mix; constraint->bendDirection = constraint->data->bendDirection; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: constraint->mix += (constraint->data->mix - constraint->mix) * alpha; constraint->bendDirection = constraint->data->bendDirection; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -1174,7 +1305,7 @@ void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skel frames = self->frames; framesCount = self->framesCount; if (time >= frames[framesCount - IKCONSTRAINT_ENTRIES]) { /* Time is after last frame. */ - if (pose == SP_MIX_POSE_SETUP) { + if (blend == SP_MIX_BLEND_SETUP) { constraint->mix = constraint->data->mix + (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->data->mix) * alpha; constraint->bendDirection = direction == SP_MIX_DIRECTION_OUT ? constraint->data->bendDirection : (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION]; @@ -1191,7 +1322,7 @@ void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skel frameTime = self->frames[frame]; percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / IKCONSTRAINT_ENTRIES - 1, 1 - (time - frameTime) / (self->frames[frame + IKCONSTRAINT_PREV_TIME] - frameTime)); - if (pose == SP_MIX_POSE_SETUP) { + if (blend == SP_MIX_BLEND_SETUP) { constraint->mix = constraint->data->mix + (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->data->mix) * alpha; constraint->bendDirection = direction == SP_MIX_DIRECTION_OUT ? constraint->data->bendDirection : (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION]; } else { @@ -1231,7 +1362,7 @@ static const int TRANSFORMCONSTRAINT_SCALE = 3; static const int TRANSFORMCONSTRAINT_SHEAR = 4; void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { int frame; float frameTime, percent, rotate, translate, scale, shear; spTransformConstraint* constraint; @@ -1242,19 +1373,21 @@ void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleto constraint = skeleton->transformConstraints[self->transformConstraintIndex]; if (time < self->frames[0]) { spTransformConstraintData* data = constraint->data; - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_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_BLEND_FIRST: 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; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; return; @@ -1284,7 +1417,7 @@ void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleto scale += (frames[frame + TRANSFORMCONSTRAINT_SCALE] - scale) * percent; shear += (frames[frame + TRANSFORMCONSTRAINT_SHEAR] - shear) * percent; } - if (pose == SP_MIX_POSE_SETUP) { + if (blend == SP_MIX_BLEND_SETUP) { spTransformConstraintData* data = constraint->data; constraint->rotateMix = data->rotateMix + (rotate - data->rotateMix) * alpha; constraint->translateMix = data->translateMix + (translate - data->translateMix) * alpha; @@ -1326,7 +1459,7 @@ static const int PATHCONSTRAINTPOSITION_PREV_VALUE = -1; static const int PATHCONSTRAINTPOSITION_VALUE = 1; void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { int frame; float frameTime, percent, position; spPathConstraint* constraint; @@ -1336,13 +1469,15 @@ void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkele constraint = skeleton->pathConstraints[self->pathConstraintIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: constraint->position = constraint->data->position; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: constraint->position += (constraint->data->position - constraint->position) * alpha; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -1361,7 +1496,7 @@ void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkele position += (frames[frame + PATHCONSTRAINTPOSITION_VALUE] - position) * percent; } - if (pose == SP_MIX_POSE_SETUP) + if (blend == SP_MIX_BLEND_SETUP) constraint->position = constraint->data->position + (position - constraint->data->position) * alpha; else constraint->position += (position - constraint->position) * alpha; @@ -1391,7 +1526,7 @@ static const int PATHCONSTRAINTSPACING_PREV_VALUE = -1; static const int PATHCONSTRAINTSPACING_VALUE = 1; void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { int frame; float frameTime, percent, spacing; spPathConstraint* constraint; @@ -1401,13 +1536,15 @@ void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkelet constraint = skeleton->pathConstraints[self->pathConstraintIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: constraint->spacing = constraint->data->spacing; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: constraint->spacing += (constraint->data->spacing - constraint->spacing) * alpha; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -1427,7 +1564,7 @@ void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkelet spacing += (frames[frame + PATHCONSTRAINTSPACING_VALUE] - spacing) * percent; } - if (pose == SP_MIX_POSE_SETUP) + if (blend == SP_MIX_BLEND_SETUP) constraint->spacing = constraint->data->spacing + (spacing - constraint->data->spacing) * alpha; else constraint->spacing += (spacing - constraint->spacing) * alpha; @@ -1460,7 +1597,7 @@ static const int PATHCONSTRAINTMIX_ROTATE = 1; static const int PATHCONSTRAINTMIX_TRANSLATE = 2; void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction) { int frame; float frameTime, percent, rotate, translate; spPathConstraint* constraint; @@ -1470,15 +1607,17 @@ void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton* constraint = skeleton->pathConstraints[self->pathConstraintIndex]; if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: + switch (blend) { + case SP_MIX_BLEND_SETUP: constraint->rotateMix = constraint->data->rotateMix; constraint->translateMix = constraint->data->translateMix; return; - case SP_MIX_POSE_CURRENT: + case SP_MIX_BLEND_FIRST: constraint->rotateMix += (constraint->data->rotateMix - constraint->rotateMix) * alpha; constraint->translateMix += (constraint->data->translateMix - constraint->translateMix) * alpha; - case SP_MIX_POSE_CURRENT_LAYERED:; /* to appease compiler */ + case SP_MIX_BLEND_REPLACE: + case SP_MIX_BLEND_ADD: + ; /* to appease compiler */ } return; } @@ -1501,7 +1640,7 @@ void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton* translate += (frames[frame + PATHCONSTRAINTMIX_TRANSLATE] - translate) * percent; } - if (pose == SP_MIX_POSE_SETUP) { + if (blend == SP_MIX_BLEND_SETUP) { constraint->rotateMix = constraint->data->rotateMix + (rotate - constraint->data->rotateMix) * alpha; constraint->translateMix = constraint->data->translateMix + (translate - constraint->data->translateMix) * alpha; } else { diff --git a/spine-c/spine-c/src/spine/AnimationState.c b/spine-c/spine-c/src/spine/AnimationState.c index e983a285f..4db618924 100644 --- a/spine-c/spine-c/src/spine/AnimationState.c +++ b/spine-c/spine-c/src/spine/AnimationState.c @@ -50,8 +50,8 @@ void spAnimationState_disposeStatics () { void _spAnimationState_disposeTrackEntry (spTrackEntry* entry); void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry); int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta); -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); +float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* entry, spSkeleton* skeleton, spMixBlend currentBlend); +void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixBlend blend, float* timelinesRotation, int i, int /*boolean*/ firstFrame); void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime); void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt); spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index); @@ -354,8 +354,8 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { float* timelinesRotation; spTimeline* timeline; int applied = 0; - spMixPose currentPose; - spMixPose pose; + spMixBlend blend; + spMixBlend timelineBlend; if (internal->animationsChanged) _spAnimationState_animationsChanged(self); @@ -364,12 +364,12 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { current = self->tracks[i]; if (!current || current->delay > 0) continue; applied = -1; - currentPose = i == 0 ? SP_MIX_POSE_CURRENT : SP_MIX_POSE_CURRENT_LAYERED; + blend = i == 0 ? SP_MIX_BLEND_FIRST : current->mixBlend; /* Apply mixing from entries first. */ mix = current->alpha; if (current->mixingFrom) - mix *= _spAnimationState_applyMixingFrom(self, current, skeleton, currentPose); + mix *= _spAnimationState_applyMixingFrom(self, current, skeleton, blend); else if (current->trackTime >= current->trackEnd && current->next == 0) mix = 0; @@ -377,9 +377,9 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { animationLast = current->animationLast; animationTime = spTrackEntry_getAnimationTime(current); timelineCount = current->animation->timelinesCount; timelines = current->animation->timelines; - if (mix == 1) { + if (mix == 1 || blend == SP_MIX_BLEND_ADD) { for (ii = 0; ii < timelineCount; ii++) - spTimeline_apply(timelines[ii], skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, 1, SP_MIX_POSE_SETUP, SP_MIX_DIRECTION_IN); + spTimeline_apply(timelines[ii], skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, blend, SP_MIX_DIRECTION_IN); } else { spIntArray* timelineData = current->timelineData; @@ -389,11 +389,11 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { for (ii = 0; ii < timelineCount; ii++) { timeline = timelines[ii]; - pose = timelineData->items[ii] >= FIRST ? SP_MIX_POSE_SETUP : currentPose; + timelineBlend = timelineData->items[ii] == SUBSEQUENT ? blend : SP_MIX_BLEND_SETUP; if (timeline->type == SP_TIMELINE_ROTATE) - _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); + _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1, firstFrame); else - spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, pose, SP_MIX_DIRECTION_IN); + spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, timelineBlend, SP_MIX_DIRECTION_IN); } } _spAnimationState_queueEvents(self, current, animationTime); @@ -406,7 +406,7 @@ int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { return applied; } -float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* to, spSkeleton* skeleton, spMixPose currentPose) { +float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* to, spSkeleton* skeleton, spMixBlend blend) { _spAnimationState* internal = SUB_CAST(_spAnimationState, self); float mix; spEvent** events; @@ -418,24 +418,25 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t spTimeline** timelines; spIntArray* timelineData; spTrackEntryArray* timelineDipMix; + spMixBlend timelineBlend; float alphaDip; float alphaMix; float alpha; int /*boolean*/ firstFrame; float* timelinesRotation; - spMixPose pose; int i; spTrackEntry* dipMix; spTrackEntry* from = to->mixingFrom; - if (from->mixingFrom) _spAnimationState_applyMixingFrom(self, from, skeleton, currentPose); + if (from->mixingFrom) _spAnimationState_applyMixingFrom(self, from, skeleton, blend); if (to->mixDuration == 0) { /* Single frame mix to undo mixingFrom changes. */ mix = 1; - currentPose = SP_MIX_POSE_SETUP; + if (blend == SP_MIX_BLEND_FIRST) blend = SP_MIX_BLEND_SETUP; } else { mix = to->mixTime / to->mixDuration; if (mix > 1) mix = 1; + if (blend != SP_MIX_BLEND_FIRST) blend = from->mixBlend; } events = mix < from->eventThreshold ? internal->events : 0; @@ -445,44 +446,52 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t animationTime = spTrackEntry_getAnimationTime(from); timelineCount = from->animation->timelinesCount; timelines = from->animation->timelines; - timelineData = from->timelineData; - timelineDipMix = from->timelineDipMix; - - firstFrame = from->timelinesRotationCount == 0; - if (firstFrame) _spAnimationState_resizeTimelinesRotation(from, timelineCount << 1); - timelinesRotation = from->timelinesRotation; - alphaDip = from->alpha * to->interruptAlpha; alphaMix = alphaDip * (1 - mix); - from->totalAlpha = 0; - for (i = 0; i < timelineCount; i++) { - spTimeline* timeline = timelines[i]; - switch (timelineData->items[i]) { - case SUBSEQUENT: - if (!attachments && timeline->type == SP_TIMELINE_ATTACHMENT) continue; - if (!drawOrder && timeline->type == SP_TIMELINE_DRAWORDER) continue; - pose = currentPose; - alpha = alphaMix; - break; - case FIRST: - pose = SP_MIX_POSE_SETUP; - alpha = alphaMix; - break; - case DIP: - pose = SP_MIX_POSE_SETUP; - alpha = alphaDip; - break; - default: - pose = SP_MIX_POSE_SETUP; - alpha = alphaDip; - dipMix = timelineDipMix->items[i]; - alpha *= MAX(0, 1 - dipMix->mixTime / dipMix->mixDuration); - break; + if (blend == SP_MIX_BLEND_ADD) { + for (i = 0; i < timelineCount; i++) { + spTimeline *timeline = timelines[i]; + spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount, alphaMix, blend, SP_MIX_DIRECTION_OUT); } - from->totalAlpha += alpha; - if (timeline->type == SP_TIMELINE_ROTATE) - _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); - else { - spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount, alpha, pose, SP_MIX_DIRECTION_OUT); + } else { + timelineData = from->timelineData; + timelineDipMix = from->timelineDipMix; + + firstFrame = from->timelinesRotationCount == 0; + if (firstFrame) _spAnimationState_resizeTimelinesRotation(from, timelineCount << 1); + timelinesRotation = from->timelinesRotation; + + from->totalAlpha = 0; + for (i = 0; i < timelineCount; i++) { + spTimeline *timeline = timelines[i]; + switch (timelineData->items[i]) { + case SUBSEQUENT: + if (!attachments && timeline->type == SP_TIMELINE_ATTACHMENT) continue; + if (!drawOrder && timeline->type == SP_TIMELINE_DRAWORDER) continue; + timelineBlend = blend; + alpha = alphaMix; + break; + case FIRST: + timelineBlend = SP_MIX_BLEND_SETUP; + alpha = alphaMix; + break; + case DIP: + timelineBlend = SP_MIX_BLEND_SETUP; + alpha = alphaDip; + break; + default: + timelineBlend = SP_MIX_BLEND_SETUP; + dipMix = timelineDipMix->items[i]; + alpha = alphaDip * MAX(0, 1 - dipMix->mixTime / dipMix->mixDuration); + break; + } + from->totalAlpha += alpha; + if (timeline->type == SP_TIMELINE_ROTATE) + _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, timelineBlend, + timelinesRotation, i << 1, firstFrame); + else { + spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount, + alpha, timelineBlend, SP_MIX_DIRECTION_OUT); + } } } @@ -495,7 +504,7 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t return mix; } -void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixPose pose, float* timelinesRotation, int i, int /*boolean*/ firstFrame) { +void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixBlend blend, float* timelinesRotation, int i, int /*boolean*/ firstFrame) { spRotateTimeline *rotateTimeline; float *frames; spBone* bone; @@ -510,7 +519,7 @@ void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* if (firstFrame) timelinesRotation[i] = 0; if (alpha == 1) { - spTimeline_apply(timeline, skeleton, 0, time, 0, 0, 1, pose, SP_MIX_DIRECTION_IN); + spTimeline_apply(timeline, skeleton, 0, time, 0, 0, 1, blend, SP_MIX_DIRECTION_IN); return; } @@ -518,7 +527,7 @@ void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* frames = rotateTimeline->frames; bone = skeleton->bones[rotateTimeline->boneIndex]; if (time < frames[0]) { - if (pose == SP_MIX_POSE_SETUP) { + if (blend == SP_MIX_BLEND_SETUP) { bone->rotation = bone->data->rotation; } return; /* Time is before first frame. */ @@ -541,7 +550,7 @@ void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* } /* Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. */ - r1 = pose == SP_MIX_POSE_SETUP ? bone->data->rotation : bone->rotation; + r1 = blend == SP_MIX_BLEND_SETUP ? bone->data->rotation : bone->rotation; diff = r2 - r1; if (diff == 0) { total = timelinesRotation[i]; @@ -803,6 +812,7 @@ spTrackEntry* _spAnimationState_trackEntry (spAnimationState* self, int trackInd entry->interruptAlpha = 1; entry->mixTime = 0; entry->mixDuration = !last ? 0 : spAnimationStateData_getMix(self->data, last->animation, animation); + entry->mixBlend = SP_MIX_BLEND_REPLACE; entry->timelineData = spIntArray_create(16); entry->timelineDipMix = spTrackEntryArray_create(16); @@ -833,7 +843,7 @@ void _spAnimationState_animationsChanged (spAnimationState* self) { for (;i < n; i++) { entry = self->tracks[i]; - if (entry != 0) _spTrackEntry_setTimelineData(entry, 0, mixingTo, self); + if (entry != 0 && entry->mixBlend != SP_MIX_BLEND_ADD) _spTrackEntry_setTimelineData(entry, 0, mixingTo, self); } } diff --git a/spine-ts/core/src/Animation.ts b/spine-ts/core/src/Animation.ts index cd9b26f56..599681dbc 100644 --- a/spine-ts/core/src/Animation.ts +++ b/spine-ts/core/src/Animation.ts @@ -619,7 +619,7 @@ module spine { slot.color.setFromColor(slot.data.color); slot.darkColor.setFromColor(slot.data.darkColor); return; - case MixBlend.setup: + case MixBlend.first: let light = slot.color, dark = slot.darkColor, setupLight = slot.data.color, setupDark = slot.data.darkColor; light.add((setupLight.r - light.r) * alpha, (setupLight.g - light.g) * alpha, (setupLight.b - light.b) * alpha, (setupLight.a - light.a) * alpha); @@ -1146,7 +1146,7 @@ module spine { constraint.scaleMix = data.scaleMix; constraint.shearMix = data.shearMix; return; - case MixBlend.setup: + case MixBlend.first: constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha;