[c] More 4.2 porting, only loaders left.

This commit is contained in:
Mario Zechner 2024-04-15 21:41:48 +02:00
parent 430758eb9b
commit f7f4d5cbe7
17 changed files with 659 additions and 359 deletions

View File

@ -101,8 +101,17 @@ typedef enum {
SP_TIMELINE_TRANSLATE,
SP_TIMELINE_DEFORM,
SP_TIMELINE_SEQUENCE,
SP_TIMELINE_INHERIT,
SP_TIMELINE_IKCONSTRAINT,
SP_TIMELINE_PATHCONSTRAINTMIX,
SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA,
SP_TIMELINE_PHYSICSCONSTRAINT_STRENGTH,
SP_TIMELINE_PHYSICSCONSTRAINT_DAMPING,
SP_TIMELINE_PHYSICSCONSTRAINT_MASS,
SP_TIMELINE_PHYSICSCONSTRAINT_WIND,
SP_TIMELINE_PHYSICSCONSTRAINT_GRAVITY,
SP_TIMELINE_PHYSICSCONSTRAINT_MIX,
SP_TIMELINE_PHYSICSCONSTRAINT_RESET,
SP_TIMELINE_RGB2,
SP_TIMELINE_RGBA2,
SP_TIMELINE_RGBA,
@ -122,19 +131,28 @@ typedef enum {
SP_PROPERTY_SCALEY = 1 << 4,
SP_PROPERTY_SHEARX = 1 << 5,
SP_PROPERTY_SHEARY = 1 << 6,
SP_PROPERTY_RGB = 1 << 7,
SP_PROPERTY_ALPHA = 1 << 8,
SP_PROPERTY_RGB2 = 1 << 9,
SP_PROPERTY_ATTACHMENT = 1 << 10,
SP_PROPERTY_DEFORM = 1 << 11,
SP_PROPERTY_EVENT = 1 << 12,
SP_PROPERTY_DRAWORDER = 1 << 13,
SP_PROPERTY_IKCONSTRAINT = 1 << 14,
SP_PROPERTY_TRANSFORMCONSTRAINT = 1 << 15,
SP_PROPERTY_PATHCONSTRAINT_POSITION = 1 << 16,
SP_PROPERTY_PATHCONSTRAINT_SPACING = 1 << 17,
SP_PROPERTY_PATHCONSTRAINT_MIX = 1 << 18,
SP_PROPERTY_SEQUENCE = 1 << 19
SP_PROPERTY_INHERIT = 1 << 7,
SP_PROPERTY_RGB = 1 << 8,
SP_PROPERTY_ALPHA = 1 << 9,
SP_PROPERTY_RGB2 = 1 << 10,
SP_PROPERTY_ATTACHMENT = 1 << 11,
SP_PROPERTY_DEFORM = 1 << 12,
SP_PROPERTY_EVENT = 1 << 13,
SP_PROPERTY_DRAWORDER = 1 << 14,
SP_PROPERTY_IKCONSTRAINT = 1 << 15,
SP_PROPERTY_TRANSFORMCONSTRAINT = 1 << 16,
SP_PROPERTY_PATHCONSTRAINT_POSITION = 1 << 17,
SP_PROPERTY_PATHCONSTRAINT_SPACING = 1 << 18,
SP_PROPERTY_PATHCONSTRAINT_MIX = 1 << 19,
SP_PROPERTY_PHYSICSCONSTRAINT_INERTIA = 1 << 20,
SP_PROPERTY_PHYSICSCONSTRAINT_STRENGTH = 1 << 21,
SP_PROPERTY_PHYSICSCONSTRAINT_DAMPING = 1 << 22,
SP_PROPERTY_PHYSICSCONSTRAINT_MASS = 1 << 23,
SP_PROPERTY_PHYSICSCONSTRAINT_WIND = 1 << 24,
SP_PROPERTY_PHYSICSCONSTRAINT_GRAVITY = 1 << 25,
SP_PROPERTY_PHYSICSCONSTRAINT_MIX = 1 << 26,
SP_PROPERTY_PHYSICSCONSTRAINT_RESET = 1 << 27,
SP_PROPERTY_SEQUENCE = 1 << 28
} spProperty;
#define SP_MAX_PROPERTY_IDS 3
@ -196,6 +214,14 @@ SP_API void spCurveTimeline1_setFrame(spCurveTimeline1 *self, int frame, float t
SP_API float spCurveTimeline1_getCurveValue(spCurveTimeline1 *self, float time);
SP_API float spCurveTimeline1_getRelativeValue(spCurveTimeline1 *timeline, float time, float alpha, spMixBlend blend, float current, float setup);
SP_API float spCurveTimeline1_getAbsoluteValue(spCurveTimeline1 *timeline, float time, float alpha, spMixBlend blend, float current, float setup);
SP_API float spCurveTimeline1_getAbsoluteValue2(spCurveTimeline1 *timeline, float time, float alpha, spMixBlend blend, float current, float setup, float value);
SP_API float spCurveTimeline1_getScaleValue (spCurveTimeline1 *timeline, float time, float alpha, spMixBlend blend, spMixDirection direction, float current, float setup);
typedef struct spCurveTimeline spCurveTimeline2;
SP_API void spCurveTimeline2_setFrame(spCurveTimeline1 *self, int frame, float time, float value1, float value2);
@ -437,6 +463,18 @@ SP_API spDrawOrderTimeline *spDrawOrderTimeline_create(int framesCount, int slot
SP_API void spDrawOrderTimeline_setFrame(spDrawOrderTimeline *self, int frameIndex, float time, const int *drawOrder);
/**/
typedef struct spInheritTimeline {
spTimeline super;
int boneIndex;
} spInheritTimeline;
SP_API spInheritTimeline *spInheritTimeline_create(int framesCount, int boneIndex);
SP_API void spInheritTimeline_setFrame(spDrawOrderTimeline *self, int frameIndex, float time, spInherit inherit);
/**/
typedef struct spIkConstraintTimeline {
@ -508,6 +546,27 @@ spPathConstraintMixTimeline_setFrame(spPathConstraintMixTimeline *self, int fram
/**/
typedef struct spPhysicsConstraintTimeline {
spCurveTimeline super;
int physicsConstraintIndex;
} spPhysicsConstraintTimeline;
SP_API spPhysicsConstraintTimeline *
spPhysicsConstraintTimeline_create(int framesCount, int bezierCount, int physicsConstraintIndex, spTimelineType type);
SP_API void spPhysicsConstraintTimeline_setFrame(spPhysicsConstraintTimeline *self, int frame, float time, float value);
/**/
typedef struct spPhysicsConstraintResetTimeline {
spTimeline super;
int physicsConstraintIndex;
} spPhysicsConstraintResetTimeline;
SP_API spPhysicsConstraintResetTimeline *spPhysicsConstraintResetTimeline_create(int framesCount, int boneIndex);
SP_API void spPhysicsConstraintResetTimeline_setFrame(spPhysicsConstraintResetTimeline *self, int frameIndex, float time);
#ifdef __cplusplus
}
#endif

View File

@ -69,7 +69,7 @@ struct spTrackEntry {
int /*boolean*/ holdPrevious;
int /*boolean*/ reverse;
int /*boolean*/ shortestRotation;
float eventThreshold, attachmentThreshold, drawOrderThreshold;
float eventThreshold, mixAttachmentThreshold, alphaAttachmentThreshold, mixDrawOrderThreshold;
float animationStart, animationEnd, animationLast, nextAnimationLast;
float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale;
float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha;
@ -146,6 +146,10 @@ SP_API void spTrackEntry_resetRotationDirections(spTrackEntry *entry);
SP_API float spTrackEntry_getTrackComplete(spTrackEntry *entry);
SP_API void spTrackEntry_setMixDuration(spTrackEntry *entry, float mixDuration, float delay);
SP_API int/*bool*/ spTrackEntry_wasApplied(spTrackEntry *entry);
SP_API void spAnimationState_clearNext(spAnimationState *self, spTrackEntry *entry);
/** Use this to dispose static memory before your app exits to appease your memory leak detector*/

View File

@ -62,6 +62,8 @@ SP_API void spIkConstraint_dispose(spIkConstraint *self);
SP_API void spIkConstraint_update(spIkConstraint *self);
SP_API void spIkConstraint_setToSetupPose(spIkConstraint *self);
SP_API void
spIkConstraint_apply1(spBone *bone, float targetX, float targetY, int /*boolean*/ compress, int /*boolean*/ stretch,
int /*boolean*/ uniform, float alpha);

View File

@ -78,6 +78,8 @@ SP_API void spPathConstraint_dispose(spPathConstraint *self);
SP_API void spPathConstraint_update(spPathConstraint *self);
SP_API void spPathConstraint_setToSetupPose(spPathConstraint *self);
SP_API float *spPathConstraint_computeWorldPositions(spPathConstraint *self, spPathAttachment *path, int spacesCount,
int/*bool*/ tangents);

View File

@ -130,6 +130,10 @@ SP_API spPathConstraint *spSkeleton_findPathConstraint(const spSkeleton *self, c
/* Returns 0 if the physics constraint was not found. */
SP_API spPhysicsConstraint *spSkeleton_findPhysicsConstraint(const spSkeleton *self, const char *constraintName);
SP_API void spSkeleton_physicsTranslate(spSkeleton *self, float x, float y);
SP_API void spSkeleton_physicsRotate(spSkeleton *self, float x, float y, float degrees);
#ifdef __cplusplus
}
#endif

View File

@ -35,6 +35,7 @@
#include <spine/IkConstraintData.h>
#include <spine/TransformConstraintData.h>
#include <spine/PathConstraintData.h>
#include <spine/PhysicsConstraintData.h>
#include <spine/Array.h>
#ifdef __cplusplus
@ -54,6 +55,8 @@ _SP_ARRAY_DECLARE_TYPE(spTransformConstraintDataArray, spTransformConstraintData
_SP_ARRAY_DECLARE_TYPE(spPathConstraintDataArray, spPathConstraintData*)
_SP_ARRAY_DECLARE_TYPE(spPhysicsConstraintDataArray, spPhysicsConstraintData*)
typedef struct spSkin {
char *name;
@ -61,6 +64,7 @@ typedef struct spSkin {
spIkConstraintDataArray *ikConstraints;
spTransformConstraintDataArray *transformConstraints;
spPathConstraintDataArray *pathConstraints;
spPhysicsConstraintDataArray *physicsConstraints;
spColor color;
} spSkin;

View File

@ -56,6 +56,8 @@ SP_API void spTransformConstraint_dispose(spTransformConstraint *self);
SP_API void spTransformConstraint_update(spTransformConstraint *self);
SP_API void spTransformConstraint_setToSetupPose(spTransformConstraint *self);
#ifdef __cplusplus
}
#endif

View File

@ -298,6 +298,110 @@ float spCurveTimeline1_getCurveValue(spCurveTimeline1 *self, float time) {
return _spCurveTimeline_getBezierValue(self, time, i, CURVE1_VALUE, curveType - CURVE_BEZIER);
}
float spCurveTimeline1_getRelativeValue(spCurveTimeline1 *self, float time, float alpha, spMixBlend blend, float current, float setup) {
float *frames = self->super.frames->items;
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
return setup;
case SP_MIX_BLEND_FIRST:
return current + (setup - current) * alpha;
default:
return current;
}
}
float value = spCurveTimeline1_getCurveValue(self, time);
switch (blend) {
case SP_MIX_BLEND_SETUP:
return setup + value * alpha;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
value += setup - current;
break;
case SP_MIX_BLEND_ADD:
break;
}
return current + value * alpha;
}
float spCurveTimeline1_getAbsoluteValue(spCurveTimeline1 *self, float time, float alpha, spMixBlend blend, float current, float setup) {
float *frames = self->super.frames->items;
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
return setup;
case SP_MIX_BLEND_FIRST:
return current + (setup - current) * alpha;
default:
return current;
}
}
float value = spCurveTimeline1_getCurveValue(self, time);
if (blend == SP_MIX_BLEND_SETUP) return setup + (value - setup) * alpha;
return current + (value - current) * alpha;
}
float spCurveTimeline1_getAbsoluteValue2(spCurveTimeline1 *self, float time, float alpha, spMixBlend blend, float current, float setup, float value) {
float *frames = self->super.frames->items;
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
return setup;
case SP_MIX_BLEND_FIRST:
return current + (setup - current) * alpha;
default:
return current;
}
}
if (blend == SP_MIX_BLEND_SETUP) return setup + (value - setup) * alpha;
return current + (value - current) * alpha;
}
float spCurveTimeline1_getScaleValue (spCurveTimeline1 *self, float time, float alpha, spMixBlend blend, spMixDirection direction, float current, float setup) {
float *frames = self->super.frames->items;
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
return setup;
case SP_MIX_BLEND_FIRST:
return current + (setup - current) * alpha;
default:
return current;
}
}
float value = spCurveTimeline1_getCurveValue(self, time) * setup;
if (alpha == 1) {
if (blend == SP_MIX_BLEND_ADD) return current + value - setup;
return value;
}
// Mixing out uses sign of setup or current pose, else use sign of key.
if (direction == SP_MIX_DIRECTION_OUT) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
return setup + (ABS(value) * SIGNUM(setup) - setup) * alpha;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
return current + (ABS(value) * SIGNUM(current) - current) * alpha;
default:
break;
}
} else {
float s;
switch (blend) {
case SP_MIX_BLEND_SETUP:
s = ABS(setup) * SIGNUM(value);
return s + (value - s) * alpha;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
s = ABS(current) * SIGNUM(value);
return s + (value - s) * alpha;
default:
break;
}
}
return current + (value - setup) * alpha;
}
#define CURVE2_ENTRIES 3
#define CURVE2_VALUE1 1
#define CURVE2_VALUE2 2
@ -314,40 +418,11 @@ SP_API void spCurveTimeline2_setFrame(spCurveTimeline1 *self, int frame, float t
void _spRotateTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time, spEvent **firedEvents,
int *eventsCount, float alpha, spMixBlend blend, spMixDirection direction) {
spBone *bone;
float r;
spRotateTimeline *self = SUB_CAST(spRotateTimeline, timeline);
float *frames = self->super.super.frames->items;
spBone *bone = skeleton->bones[self->boneIndex];
if (bone->active) bone->rotation = spCurveTimeline1_getRelativeValue(SUPER(self), time, alpha, blend, bone->rotation, bone->data->rotation);
bone = skeleton->bones[self->boneIndex];
if (!bone->active) return;
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
bone->rotation = bone->data->rotation;
return;
case SP_MIX_BLEND_FIRST:
bone->rotation += (bone->data->rotation - bone->rotation) * alpha;
default: {
}
}
return;
}
r = spCurveTimeline1_getCurveValue(SUPER(self), time);
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;
case SP_MIX_BLEND_ADD:
bone->rotation += r * alpha;
}
UNUSED(lastTime);
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(direction);
@ -709,69 +784,12 @@ void spScaleTimeline_setFrame(spScaleTimeline *self, int frame, float time, floa
void _spScaleXTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
spBone *bone;
float x;
spScaleXTimeline *self = SUB_CAST(spScaleXTimeline, timeline);
float *frames = self->super.super.frames->items;
spBone *bone = skeleton->bones[self->boneIndex];
bone = skeleton->bones[self->boneIndex];
if (!bone->active) return;
if (bone->active) bone->scaleX = spCurveTimeline1_getScaleValue(SUPER(self), time, alpha, blend, direction, bone->scaleX, bone->data->scaleX);
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
bone->scaleX = bone->data->scaleX;
return;
case SP_MIX_BLEND_FIRST:
bone->scaleX += (bone->data->scaleX - bone->scaleX) * alpha;
default: {
}
}
return;
}
x = spCurveTimeline1_getCurveValue(SUPER(self), time) * bone->data->scaleX;
if (alpha == 1) {
if (blend == SP_MIX_BLEND_ADD)
bone->scaleX += x - bone->data->scaleX;
else
bone->scaleX = x;
} else {
/* Mixing out uses sign of setup or current pose, else use sign of key. */
float bx;
if (direction == SP_MIX_DIRECTION_OUT) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
bx = bone->data->scaleX;
bone->scaleX = bx + (ABS(x) * SIGNUM(bx) - bx) * alpha;
break;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
bx = bone->scaleX;
bone->scaleX = bx + (ABS(x) * SIGNUM(bx) - bx) * alpha;
break;
case SP_MIX_BLEND_ADD:
bone->scaleX += (x - bone->data->scaleX) * alpha;
}
} else {
switch (blend) {
case SP_MIX_BLEND_SETUP:
bx = ABS(bone->data->scaleX) * SIGNUM(x);
bone->scaleX = bx + (x - bx) * alpha;
break;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
bx = ABS(bone->scaleX) * SIGNUM(x);
bone->scaleX = bx + (x - bx) * alpha;
break;
case SP_MIX_BLEND_ADD:
bone->scaleX += (x - bone->data->scaleX) * alpha;
}
}
}
UNUSED(lastTime);
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
}
@ -795,69 +813,12 @@ void spScaleXTimeline_setFrame(spScaleXTimeline *self, int frame, float time, fl
void _spScaleYTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
spBone *bone;
float y;
spScaleYTimeline *self = SUB_CAST(spScaleYTimeline, timeline);
float *frames = self->super.super.frames->items;
spBone *bone = skeleton->bones[self->boneIndex];
bone = skeleton->bones[self->boneIndex];
if (!bone->active) return;
if (bone->active) bone->scaleY = spCurveTimeline1_getScaleValue(SUPER(self), time, alpha, blend, direction, bone->scaleX, bone->data->scaleY);
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
bone->scaleY = bone->data->scaleY;
return;
case SP_MIX_BLEND_FIRST:
bone->scaleY += (bone->data->scaleY - bone->scaleY) * alpha;
default: {
}
}
return;
}
y = spCurveTimeline1_getCurveValue(SUPER(self), time) * bone->data->scaleY;
if (alpha == 1) {
if (blend == SP_MIX_BLEND_ADD)
bone->scaleY += y - bone->data->scaleY;
else
bone->scaleY = y;
} else {
/* Mixing out uses sign of setup or current pose, else use sign of key. */
float by = 0;
if (direction == SP_MIX_DIRECTION_OUT) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
by = bone->data->scaleY;
bone->scaleY = by + (ABS(y) * SIGNUM(by) - by) * alpha;
break;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
by = bone->scaleY;
bone->scaleY = by + (ABS(y) * SIGNUM(by) - by) * alpha;
break;
case SP_MIX_BLEND_ADD:
bone->scaleY += (y - bone->data->scaleY) * alpha;
}
} else {
switch (blend) {
case SP_MIX_BLEND_SETUP:
by = ABS(bone->data->scaleY) * SIGNUM(y);
bone->scaleY = by + (y - by) * alpha;
break;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
by = ABS(bone->scaleY) * SIGNUM(y);
bone->scaleY = by + (y - by) * alpha;
break;
case SP_MIX_BLEND_ADD:
bone->scaleY += (y - bone->data->scaleY) * alpha;
}
}
}
UNUSED(lastTime);
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
}
@ -970,41 +931,12 @@ void spShearTimeline_setFrame(spShearTimeline *self, int frame, float time, floa
void _spShearXTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
spBone *bone;
float x;
spShearXTimeline *self = SUB_CAST(spShearXTimeline, timeline);
float *frames = self->super.super.frames->items;
spBone *bone = skeleton->bones[self->boneIndex];
bone = skeleton->bones[self->boneIndex];
if (!bone->active) return;
if (bone->active) bone->shearX = spCurveTimeline1_getRelativeValue(SUPER(self), time, alpha, blend, bone->shearX, bone->data->shearX);
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
bone->shearX = bone->data->shearX;
return;
case SP_MIX_BLEND_FIRST:
bone->shearX += (bone->data->shearX - bone->shearX) * alpha;
default: {
}
}
return;
}
x = spCurveTimeline1_getCurveValue(SUPER(self), time);
switch (blend) {
case SP_MIX_BLEND_SETUP:
bone->shearX = bone->data->shearX + x * alpha;
break;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
bone->shearX += (bone->data->shearX + x - bone->shearX) * alpha;
break;
case SP_MIX_BLEND_ADD:
bone->shearX += x * alpha;
}
UNUSED(lastTime);
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(direction);
@ -1029,42 +961,12 @@ void spShearXTimeline_setFrame(spShearXTimeline *self, int frame, float time, fl
void _spShearYTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
spBone *bone;
float y;
spShearYTimeline *self = SUB_CAST(spShearYTimeline, timeline);
float *frames = self->super.super.frames->items;
spBone *bone = skeleton->bones[self->boneIndex];
bone = skeleton->bones[self->boneIndex];
if (!bone->active) return;
if (bone->active) bone->shearY = spCurveTimeline1_getRelativeValue(SUPER(self), time, alpha, blend, bone->shearY, bone->data->shearY);
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
bone->shearY = bone->data->shearY;
return;
case SP_MIX_BLEND_FIRST:
bone->shearY += (bone->data->shearY - bone->shearY) * alpha;
default: {
}
}
return;
}
y = spCurveTimeline1_getCurveValue(SUPER(self), time);
switch (blend) {
case SP_MIX_BLEND_SETUP:
bone->shearY = bone->data->shearY + y * alpha;
break;
case SP_MIX_BLEND_FIRST:
case SP_MIX_BLEND_REPLACE:
bone->shearY += (bone->data->shearY + y - bone->shearY) * alpha;
break;
case SP_MIX_BLEND_ADD:
bone->shearY += y * alpha;
}
UNUSED(lastTime);
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(direction);
@ -2053,7 +1955,7 @@ void _spSequenceTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float
count = sequence->regions->size;
mode = modeAndIndex & 0xf;
if (mode != SP_SEQUENCE_MODE_HOLD) {
index += (int) (((time - before) / delay + 0.00001));
index += (int) (((time - before) / delay + 0.0001));
switch (mode) {
case SP_SEQUENCE_MODE_ONCE:
index = MIN(count - 1, index);
@ -2252,6 +2154,53 @@ void spDrawOrderTimeline_setFrame(spDrawOrderTimeline *self, int frame, float ti
}
}
/**/
void _spInheritTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
spInheritTimeline *self = (spInheritTimeline *)timeline;
spBone *bone = skeleton->bones[self->boneIndex];
float *frames = self->super.frames->items;
if (!bone->active) return;
if (time < frames[0]) {
if (blend == SP_MIX_BLEND_SETUP || blend == SP_MIX_BLEND_FIRST) bone->inherit = bone->data->inherit;
return;
}
int idx = search2(self->super.frames, time, 2) + 1;
bone->inherit = (spInherit) frames[idx];
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(alpha);
UNUSED(direction);
}
void _spInheritTimeline_dispose(spTimeline *timeline) {
// no-op, spTimeline_dispose disposes frames.
UNUSED(timeline);
}
spInheritTimeline *spInheritTimeline_create(int framesCount, int boneIndex) {
spInheritTimeline *self = NEW(spInheritTimeline);
spPropertyId ids[1];
ids[0] = (spPropertyId) SP_PROPERTY_INHERIT << 32;
_spTimeline_init(SUPER(self), framesCount, 2, ids, 1, SP_TIMELINE_INHERIT, _spInheritTimeline_dispose,
_spInheritTimeline_apply, 0);
self->boneIndex = boneIndex;
return self;
}
void spInheritTimeline_setFrame(spDrawOrderTimeline *self, int frame, float time, spInherit inherit) {
frame *= 2;
self->super.frames->items[frame] = time;
self->super.frames->items[frame + 1] = inherit;
}
/**/
static const int IKCONSTRAINT_ENTRIES = 6;
@ -2515,35 +2464,9 @@ static const int PATHCONSTRAINTPOSITION_VALUE = 1;
void _spPathConstraintPositionTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
float position;
spPathConstraint *constraint;
spPathConstraintPositionTimeline *self = (spPathConstraintPositionTimeline *) timeline;
float *frames;
constraint = skeleton->pathConstraints[self->pathConstraintIndex];
if (!constraint->active) return;
frames = self->super.super.frames->items;
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
constraint->position = constraint->data->position;
return;
case SP_MIX_BLEND_FIRST:
constraint->position += (constraint->data->position - constraint->position) * alpha;
return;
default:
return;
}
}
position = spCurveTimeline1_getCurveValue(SUPER(self), time);
if (blend == SP_MIX_BLEND_SETUP)
constraint->position = constraint->data->position + (position - constraint->data->position) * alpha;
else
constraint->position += (position - constraint->position) * alpha;
spPathConstraintPositionTimeline *self = (spPathConstraintPositionTimeline *) timeline;
spPathConstraint *constraint = skeleton->pathConstraints[self->pathConstraintIndex];
if (constraint->active) constraint->position = spCurveTimeline1_getAbsoluteValue(SUPER(self), time, alpha, blend, constraint->position, constraint->data->position);
UNUSED(lastTime);
UNUSED(firedEvents);
@ -2577,40 +2500,14 @@ static const int PATHCONSTRAINTSPACING_VALUE = 1;
void _spPathConstraintSpacingTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
float spacing;
spPathConstraint *constraint;
spPathConstraintSpacingTimeline *self = (spPathConstraintSpacingTimeline *) timeline;
float *frames;
spPathConstraintSpacingTimeline *self = (spPathConstraintSpacingTimeline *) timeline;
spPathConstraint *constraint = skeleton->pathConstraints[self->pathConstraintIndex];
if (constraint->active) constraint->spacing = spCurveTimeline1_getAbsoluteValue(SUPER(self), time, alpha, blend, constraint->spacing, constraint->data->spacing);
constraint = skeleton->pathConstraints[self->pathConstraintIndex];
if (!constraint->active) return;
frames = self->super.super.frames->items;
if (time < frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
constraint->spacing = constraint->data->spacing;
return;
case SP_MIX_BLEND_FIRST:
constraint->spacing += (constraint->data->spacing - constraint->spacing) * alpha;
return;
default:
return;
}
}
spacing = spCurveTimeline1_getCurveValue(SUPER(self), time);
if (blend == SP_MIX_BLEND_SETUP)
constraint->spacing = constraint->data->spacing + (spacing - constraint->data->spacing) * alpha;
else
constraint->spacing += (spacing - constraint->spacing) * alpha;
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(direction);
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(direction);
}
spPathConstraintSpacingTimeline *
@ -2740,3 +2637,226 @@ void spPathConstraintMixTimeline_setFrame(spPathConstraintMixTimeline *self, int
frames[frame + PATHCONSTRAINTMIX_X] = mixX;
frames[frame + PATHCONSTRAINTMIX_Y] = mixY;
}
/**/
int/*bool*/ _spPhysicsConstraintTimeline_global(spPhysicsConstraintData *data, spTimelineType type) {
switch(type) {
case SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA:
return data->inertiaGlobal;
case SP_TIMELINE_PHYSICSCONSTRAINT_STRENGTH:
return data->strengthGlobal;
case SP_TIMELINE_PHYSICSCONSTRAINT_DAMPING:
return data->dampingGlobal;
case SP_TIMELINE_PHYSICSCONSTRAINT_MASS:
return data->massGlobal;
case SP_TIMELINE_PHYSICSCONSTRAINT_WIND:
return data->windGlobal;
case SP_TIMELINE_PHYSICSCONSTRAINT_GRAVITY:
return data->gravityGlobal;
case SP_TIMELINE_PHYSICSCONSTRAINT_MIX:
return data->mixGlobal;
default:
// should never happen
return 0;
}
}
void _spPhysicsConstraintTimeline_set(spPhysicsConstraint *constraint, spTimelineType type, float value) {
switch(type) {
case SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA:
constraint->inertia = value;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_STRENGTH:
constraint->strength = value;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_DAMPING:
constraint->damping = value;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_MASS:
constraint->massInverse = value;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_WIND:
constraint->wind = value;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_GRAVITY:
constraint->gravity = value;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_MIX:
constraint->mix = value;
break;
default:
// should never happen
break;
}
}
float _spPhysicsConstraintTimeline_get(spPhysicsConstraint *constraint, spTimelineType type) {
switch(type) {
case SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA:
return constraint->inertia;
case SP_TIMELINE_PHYSICSCONSTRAINT_STRENGTH:
return constraint->strength;
case SP_TIMELINE_PHYSICSCONSTRAINT_DAMPING:
return constraint->damping;
case SP_TIMELINE_PHYSICSCONSTRAINT_MASS:
return constraint->massInverse;
case SP_TIMELINE_PHYSICSCONSTRAINT_WIND:
return constraint->wind;
case SP_TIMELINE_PHYSICSCONSTRAINT_GRAVITY:
return constraint->gravity;
case SP_TIMELINE_PHYSICSCONSTRAINT_MIX:
return constraint->mix;
default:
// should never happen
return 0;
}
}
float _spPhysicsConstraintTimeline_setup(spPhysicsConstraint *constraint, spTimelineType type) {
switch(type) {
case SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA:
return constraint->data->inertia;
case SP_TIMELINE_PHYSICSCONSTRAINT_STRENGTH:
return constraint->data->strength;
case SP_TIMELINE_PHYSICSCONSTRAINT_DAMPING:
return constraint->data->damping;
case SP_TIMELINE_PHYSICSCONSTRAINT_MASS:
return constraint->data->massInverse;
case SP_TIMELINE_PHYSICSCONSTRAINT_WIND:
return constraint->data->wind;
case SP_TIMELINE_PHYSICSCONSTRAINT_GRAVITY:
return constraint->data->gravity;
case SP_TIMELINE_PHYSICSCONSTRAINT_MIX:
return constraint->data->mix;
default:
// should never happen
return 0;
}
}
void _spPhysicsConstraintTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
spPhysicsConstraintTimeline *self = SUB_CAST(spPhysicsConstraintTimeline, timeline);
spTimelineType type = self->super.super.type;
float *frames = self->super.super.frames->items;
if (self->physicsConstraintIndex == -1) {
float value = time >= frames[0] ? spCurveTimeline1_getCurveValue(SUPER(self), time) : 0;
spPhysicsConstraint **physicsConstraints = skeleton->physicsConstraints;
for (int i = 0; i < skeleton->physicsConstraintsCount; i++) {
spPhysicsConstraint *constraint = physicsConstraints[i];
if (constraint->active && _spPhysicsConstraintTimeline_global(constraint->data, type))
_spPhysicsConstraintTimeline_set(constraint, type,spCurveTimeline1_getAbsoluteValue2(SUPER(self), time, alpha, blend, _spPhysicsConstraintTimeline_get(constraint, type), _spPhysicsConstraintTimeline_setup(constraint, type), value));
}
} else {
spPhysicsConstraint *constraint = skeleton->physicsConstraints[self->physicsConstraintIndex];
if (constraint->active) _spPhysicsConstraintTimeline_set(constraint, type, spCurveTimeline1_getAbsoluteValue(SUPER(self), time, alpha, blend, _spPhysicsConstraintTimeline_get(constraint, type), _spPhysicsConstraintTimeline_setup(constraint, type)));
}
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(direction);
}
spPhysicsConstraintTimeline *
spPhysicsConstraintTimeline_create(int frameCount, int bezierCount, int physicsConstraintIndex, spTimelineType type) {
spPhysicsConstraintTimeline *timeline = NEW(spPhysicsConstraintTimeline);
spPropertyId ids[1];
spPropertyId id;
switch(type) {
case SP_TIMELINE_PHYSICSCONSTRAINT_INERTIA:
id = SP_PROPERTY_PHYSICSCONSTRAINT_INERTIA;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_STRENGTH:
id = SP_PROPERTY_PHYSICSCONSTRAINT_STRENGTH;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_DAMPING:
id = SP_PROPERTY_PHYSICSCONSTRAINT_DAMPING;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_MASS:
id = SP_PROPERTY_PHYSICSCONSTRAINT_MASS;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_WIND:
id = SP_PROPERTY_PHYSICSCONSTRAINT_WIND;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_GRAVITY:
id = SP_PROPERTY_PHYSICSCONSTRAINT_GRAVITY;
break;
case SP_TIMELINE_PHYSICSCONSTRAINT_MIX:
id = SP_PROPERTY_PHYSICSCONSTRAINT_MIX;
break;
default:
// should never happen
id = SP_PROPERTY_PHYSICSCONSTRAINT_INERTIA;
}
ids[0] = ((spPropertyId) id << 32) | physicsConstraintIndex;
_spCurveTimeline_init(SUPER(timeline), frameCount, CURVE1_ENTRIES, bezierCount, ids, 1, type,
_spCurveTimeline_dispose, _spPhysicsConstraintTimeline_apply, _spCurveTimeline_setBezier);
timeline->physicsConstraintIndex = physicsConstraintIndex;
return timeline;
}
void spPhysicsConstraintTimeline_setFrame(spPhysicsConstraintTimeline *self, int frame, float time, float value) {
spCurveTimeline1_setFrame(SUPER(self), frame, time, value);
}
/**/
void _spPhysicsConstraintResetTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float lastTime, float time,
spEvent **firedEvents, int *eventsCount, float alpha, spMixBlend blend,
spMixDirection direction) {
spPhysicsConstraintResetTimeline *self = (spPhysicsConstraintResetTimeline *)timeline;
spPhysicsConstraint *constraint = NULL;
if (self->physicsConstraintIndex != -1) {
constraint = skeleton->physicsConstraints[self->physicsConstraintIndex];
if (!constraint->active) return;
}
float *frames = SUPER(self)->frames->items;
if (lastTime > time) {// Apply after lastTime for looped animations.
_spPhysicsConstraintResetTimeline_apply(SUPER(self), skeleton, lastTime, INT_MAX, NULL, 0, alpha, blend, direction);
lastTime = -1;
} else if (lastTime >= frames[SUPER(self)->frameCount - 1])// Last time is after last frame.
return;
if (time < frames[0]) return;
if (lastTime < frames[0] || time >= frames[search(self->super.frames, lastTime) + 1]) {
if (constraint != NULL)
spPhysicsConstraint_reset(constraint);
else {
spPhysicsConstraint **physicsConstraints = skeleton->physicsConstraints;
for (int i = 0; i < skeleton->physicsConstraintsCount; i++) {
constraint = physicsConstraints[i];
if (constraint->active) spPhysicsConstraint_reset(constraint);
}
}
}
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(alpha);
UNUSED(direction);
}
void _spPhysicsConstraintResetTimeline_dispose(spTimeline *timeline) {
// no-op, spTimeline_dispose disposes frames.
UNUSED(timeline);
}
spPhysicsConstraintResetTimeline *spPhysicsConstraintResetTimeline_create(int framesCount, int physicsConstraintIndex) {
spPhysicsConstraintResetTimeline *self = NEW(spPhysicsConstraintResetTimeline);
spPropertyId ids[1];
ids[0] = (spPropertyId) SP_PROPERTY_PHYSICSCONSTRAINT_RESET << 32;
_spTimeline_init(SUPER(self), framesCount, 1, ids, 1, SP_TIMELINE_PHYSICSCONSTRAINT_RESET, _spPhysicsConstraintResetTimeline_dispose,
_spPhysicsConstraintResetTimeline_apply, 0);
self->physicsConstraintIndex = physicsConstraintIndex;
return self;
}
void spPhysicsResetTimeline_setFrame(spPhysicsConstraintResetTimeline *self, int frame, float time) {
self->super.frames->items[frame] = time;
}

View File

@ -390,18 +390,19 @@ int spAnimationState_apply(spAnimationState *self, spSkeleton *skeleton) {
if (internal->animationsChanged) _spAnimationState_animationsChanged(self);
for (i = 0, n = self->tracksCount; i < n; i++) {
float mix;
float alpha;
current = self->tracks[i];
if (!current || current->delay > 0) continue;
applied = -1;
blend = i == 0 ? SP_MIX_BLEND_FIRST : current->mixBlend;
/* Apply mixing from entries first. */
mix = current->alpha;
alpha = current->alpha;
if (current->mixingFrom)
mix *= _spAnimationState_applyMixingFrom(self, current, skeleton, blend);
alpha *= _spAnimationState_applyMixingFrom(self, current, skeleton, blend);
else if (current->trackTime >= current->trackEnd && current->next == 0)
mix = 0;
alpha = 0;
int/*bool*/ attachments = alpha >= current->alphaAttachmentThreshold;
/* Apply current entry. */
animationLast = current->animationLast;
@ -414,14 +415,14 @@ int spAnimationState_apply(spAnimationState *self, spSkeleton *skeleton) {
applyEvents = NULL;
}
timelines = current->animation->timelines->items;
if ((i == 0 && mix == 1) || blend == SP_MIX_BLEND_ADD) {
if ((i == 0 && alpha == 1) || blend == SP_MIX_BLEND_ADD) {
for (ii = 0; ii < timelineCount; ii++) {
timeline = timelines[ii];
if (timeline->type == SP_TIMELINE_ATTACHMENT) {
_spAnimationState_applyAttachmentTimeline(self, timeline, skeleton, applyTime, blend, -1);
_spAnimationState_applyAttachmentTimeline(self, timeline, skeleton, applyTime, blend, attachments);
} else {
spTimeline_apply(timelines[ii], skeleton, animationLast, applyTime, applyEvents,
&internal->eventsCount, mix, blend, SP_MIX_DIRECTION_IN);
&internal->eventsCount, alpha, blend, SP_MIX_DIRECTION_IN);
}
}
} else {
@ -436,13 +437,13 @@ int spAnimationState_apply(spAnimationState *self, spSkeleton *skeleton) {
timeline = timelines[ii];
timelineBlend = timelineMode->items[ii] == SUBSEQUENT ? blend : SP_MIX_BLEND_SETUP;
if (!shortestRotation && timeline->type == SP_TIMELINE_ROTATE)
_spAnimationState_applyRotateTimeline(self, timeline, skeleton, applyTime, mix, timelineBlend,
timelinesRotation, ii << 1, firstFrame);
_spAnimationState_applyRotateTimeline(self, timeline, skeleton, applyTime, alpha, timelineBlend,
timelinesRotation, ii << 1, firstFrame);
else if (timeline->type == SP_TIMELINE_ATTACHMENT)
_spAnimationState_applyAttachmentTimeline(self, timeline, skeleton, applyTime, timelineBlend, -1);
_spAnimationState_applyAttachmentTimeline(self, timeline, skeleton, applyTime, timelineBlend, attachments);
else
spTimeline_apply(timeline, skeleton, animationLast, applyTime, applyEvents, &internal->eventsCount,
mix, timelineBlend, SP_MIX_DIRECTION_IN);
alpha, timelineBlend, SP_MIX_DIRECTION_IN);
}
}
_spAnimationState_queueEvents(self, current, animationTime);
@ -500,8 +501,8 @@ float _spAnimationState_applyMixingFrom(spAnimationState *self, spTrackEntry *to
if (blend != SP_MIX_BLEND_FIRST) blend = from->mixBlend;
}
attachments = mix < from->attachmentThreshold;
drawOrder = mix < from->drawOrderThreshold;
attachments = mix < from->mixAttachmentThreshold;
drawOrder = mix < from->mixDrawOrderThreshold;
timelineCount = from->animation->timelines->size;
timelines = from->animation->timelines->items;
alphaHold = from->alpha * to->interruptAlpha;
@ -566,7 +567,7 @@ float _spAnimationState_applyMixingFrom(spAnimationState *self, spTrackEntry *to
timelinesRotation, i << 1, firstFrame);
else if (timeline->type == SP_TIMELINE_ATTACHMENT)
_spAnimationState_applyAttachmentTimeline(self, timeline, skeleton, applyTime, timelineBlend,
attachments);
attachments && alpha >= from->alphaAttachmentThreshold);
else {
if (drawOrder && timeline->type == SP_TIMELINE_DRAWORDER &&
timelineBlend == SP_MIX_BLEND_SETUP)
@ -664,8 +665,8 @@ void _spAnimationState_applyRotateTimeline(spAnimationState *self, spTimeline *t
/* Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. */
diff = r2 - r1;
diff -= (16384 - (int) (16384.499999999996 - diff / 360)) * 360;
if (diff == 0) {
diff -= CEIL(diff / 360 - 0.5) * 360;
if (diff == 0) {
total = timelinesRotation[i];
} else {
float lastTotal, lastDiff, loops;
@ -714,10 +715,16 @@ void _spAnimationState_queueEvents(spAnimationState *self, spTrackEntry *entry,
}
/* Queue complete if completed a loop iteration or the animation. */
if (entry->loop)
complete = duration == 0 || (trackLastWrapped > FMOD(entry->trackTime, duration));
else
complete = (animationTime >= animationEnd && entry->animationLast < animationEnd);
if (entry->loop) {
if (duration == 0)
complete = -1;
else {
int cycles = (int) (entry->trackTime / duration);
complete = cycles > 0 && cycles > (int) (entry->trackLast / duration);
}
} else {
complete = (animationTime >= animationEnd && entry->animationLast < animationEnd);
}
if (complete) _spEventQueue_complete(internal->queue, entry);
/* Queue events after complete. */
@ -910,8 +917,9 @@ _spAnimationState_trackEntry(spAnimationState *self, int trackIndex, spAnimation
entry->next = 0;
entry->eventThreshold = 0;
entry->attachmentThreshold = 0;
entry->drawOrderThreshold = 0;
entry->mixAttachmentThreshold = 0;
entry->alphaAttachmentThreshold = 0;
entry->mixDrawOrderThreshold = 0;
entry->animationStart = 0;
entry->animationEnd = animation->duration;
@ -1051,6 +1059,16 @@ float spTrackEntry_getTrackComplete(spTrackEntry *entry) {
return entry->trackTime; /* Next update. */
}
void spTrackEntry_setMixDuration(spTrackEntry *entry, float mixDuration, float delay) {
entry->mixDuration = mixDuration;
if (entry->previous && delay <= 0) delay += spTrackEntry_getTrackComplete(entry) - mixDuration;
entry->delay = delay;
}
int spTrackEntry_wasApplied(spTrackEntry *entry) {
return entry->nextTrackLast != -1;
}
void _spTrackEntry_computeHold(spTrackEntry *entry, spAnimationState *state) {
spTrackEntry *to;
spTimeline **timelines;

View File

@ -209,6 +209,13 @@ void spDebug_printTimeline(spTimeline *timeline) {
spSequenceTimeline *t = (spSequenceTimeline *) timeline;
_spDebug_printTimelineBase(&t->super);
}
case SP_TIMELINE_INHERIT: {
spInheritTimeline *t = (spInheritTimeline *) timeline;
_spDebug_printTimelineBase(&t->super);
}
default: {
_spDebug_printTimelineBase(timeline);
}
}
}

View File

@ -71,6 +71,14 @@ void spIkConstraint_update(spIkConstraint *self) {
}
}
void spIkConstraint_setToSetupPose(spIkConstraint *self) {
self->bendDirection = self->data->bendDirection;
self->compress = self->data->compress;
self->stretch = self->data->stretch;
self->softness = self->data->softness;
self->mix = self->data->mix;
}
void spIkConstraint_apply1(spBone *bone, float targetX, float targetY, int /*boolean*/ compress, int /*boolean*/ stretch,
int /*boolean*/ uniform, float alpha) {
spBone *p = bone->parent;

View File

@ -33,11 +33,11 @@
spIkConstraintData *spIkConstraintData_create(const char *name) {
spIkConstraintData *self = NEW(spIkConstraintData);
MALLOC_STR(self->name, name);
self->bendDirection = 1;
self->bendDirection = 0;
self->compress = 0;
self->stretch = 0;
self->uniform = 0;
self->mix = 1;
self->mix = 0;
return self;
}

View File

@ -117,13 +117,9 @@ void spPathConstraint_update(spPathConstraint *self) {
for (i = 0, n = spacesCount - 1; i < n; i++) {
spBone *bone = bones[i];
setupLength = bone->data->length;
if (setupLength < EPSILON)
lengths[i] = 0;
else {
x = setupLength * bone->a;
y = setupLength * bone->c;
lengths[i] = SQRT(x * x + y * y);
}
x = setupLength * bone->a;
y = setupLength * bone->c;
lengths[i] = SQRT(x * x + y * y);
}
}
for (i = 1, n = spacesCount; i < n; i++) spaces[i] = spacing;
@ -225,6 +221,15 @@ void spPathConstraint_update(spPathConstraint *self) {
}
}
void spPathConstraint_setToSetupPose(spPathConstraint *self) {
spPathConstraintData *data = self->data;
self->position = data->position;
self->spacing = data->spacing;
self->mixRotate = data->mixRotate;
self->mixX = data->mixX;
self->mixY = data->mixY;
}
static void _addBeforePosition(float p, float *temp, int i, float *out, int o) {
float x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = ATAN2(dy, dx);
out[o] = x1 + p * COS(r);

View File

@ -58,10 +58,8 @@ void spPointAttachment_computeWorldPosition(spPointAttachment *self, spBone *bon
}
float spPointAttachment_computeWorldRotation(spPointAttachment *self, spBone *bone) {
float cosine, sine, x, y;
cosine = COS_DEG(self->rotation);
sine = SIN_DEG(self->rotation);
x = cosine * bone->a + sine * bone->b;
y = cosine * bone->c + sine * bone->d;
return ATAN2(y, x) * RAD_DEG;
float r = self->rotation * DEG_RAD, cosine = COS(r), sine = SIN(r);
float x = cosine * bone->a + sine * bone->b;
float y = cosine * bone->c + sine * bone->d;
return ATAN2DEG(y, x);
}

View File

@ -60,6 +60,11 @@ spSkeleton *spSkeleton_create(spSkeletonData *data) {
_spSkeleton *internal = NEW(_spSkeleton);
spSkeleton *self = SUPER(internal);
self->data = data;
self->skin = NULL;
spColor_setFromFloats(&self->color, 1, 1, 1, 1);
self->scaleX = 1;
self->scaleY = 1;
self->time = 0;
self->bonesCount = self->data->bonesCount;
self->bones = MALLOC(spBone *, self->bonesCount);
@ -116,6 +121,12 @@ spSkeleton *spSkeleton_create(spSkeletonData *data) {
for (i = 0; i < self->data->pathConstraintsCount; i++)
self->pathConstraints[i] = spPathConstraint_create(self->data->pathConstraints[i], self);
self->physicsConstraintsCount = data->physicsConstraintsCount;
self->physicsConstraints = MALLOC(spPhysicsConstraint *, self->physicsConstraintsCount);
for (i = 0; i < self->data->physicsConstraintsCount; i++)
self->physicsConstraints[i] = spPhysicsConstraint_create(self->data->physicsConstraints[i], self);
spColor_setFromFloats(&self->color, 1, 1, 1, 1);
self->scaleX = 1;
@ -156,6 +167,10 @@ void spSkeleton_dispose(spSkeleton *self) {
spPathConstraint_dispose(self->pathConstraints[i]);
FREE(self->pathConstraints);
for (i = 0; i < self->physicsConstraintsCount; i++)
spPhysicsConstraint_dispose(self->physicsConstraints[i]);
FREE(self->physicsConstraints);
FREE(self->drawOrder);
FREE(self);
}
@ -324,17 +339,35 @@ static void _sortTransformConstraint(_spSkeleton *const internal, spTransformCon
constrained[i]->sorted = 1;
}
static void _sortPhysicsConstraint(_spSkeleton *const internal, spPhysicsConstraint *constraint) {
spBone *bone = constraint->bone;
constraint->active = constraint->bone->active && (!constraint->data->skinRequired || (internal->super.skin != 0 &&
spPhysicsConstraintDataArray_contains(
internal->super.skin->physicsConstraints,
constraint->data)));
if (!constraint->active)
return;
_sortBone(internal, bone);
_addToUpdateCache(internal, SP_UPDATE_PHYSICS_CONSTRAINT, constraint);
_sortReset(bone->children, bone->childrenCount);
bone->sorted = -1;
}
void spSkeleton_updateCache(spSkeleton *self) {
int i, ii;
spBone **bones;
spIkConstraint **ikConstraints;
spPathConstraint **pathConstraints;
spTransformConstraint **transformConstraints;
int ikCount, transformCount, pathCount, constraintCount;
spPhysicsConstraint **physicsConstraints;
int ikCount, transformCount, pathCount, physicsCount, constraintCount;
_spSkeleton *internal = SUB_CAST(_spSkeleton, self);
internal->updateCacheCapacity =
self->bonesCount + self->ikConstraintsCount + self->transformConstraintsCount + self->pathConstraintsCount;
self->bonesCount + self->ikConstraintsCount + self->transformConstraintsCount + self->pathConstraintsCount +
self->physicsConstraintsCount;
FREE(internal->updateCache);
internal->updateCache = MALLOC(_spUpdate, internal->updateCacheCapacity);
internal->updateCacheCount = 0;
@ -362,10 +395,12 @@ void spSkeleton_updateCache(spSkeleton *self) {
ikConstraints = self->ikConstraints;
transformConstraints = self->transformConstraints;
pathConstraints = self->pathConstraints;
physicsConstraints = self->physicsConstraints;
ikCount = self->ikConstraintsCount;
transformCount = self->transformConstraintsCount;
pathCount = self->pathConstraintsCount;
constraintCount = ikCount + transformCount + pathCount;
physicsCount = self->physicsConstraintsCount;
constraintCount = ikCount + transformCount + pathCount + physicsCount;
i = 0;
continue_outer:
@ -396,6 +431,15 @@ continue_outer:
goto continue_outer;
}
}
for (ii = 0; ii < physicsCount; ii++) {
spPhysicsConstraint *physicsConstraint = physicsConstraints[ii];
if (physicsConstraint->data->order == i) {
_sortPhysicsConstraint(internal, physicsConstraint);
i++;
goto continue_outer;
}
}
}
for (i = 0; i < self->bonesCount; ++i)
@ -495,33 +539,19 @@ void spSkeleton_setBonesToSetupPose(const spSkeleton *self) {
spBone_setToSetupPose(self->bones[i]);
for (i = 0; i < self->ikConstraintsCount; ++i) {
spIkConstraint *ikConstraint = self->ikConstraints[i];
ikConstraint->bendDirection = ikConstraint->data->bendDirection;
ikConstraint->compress = ikConstraint->data->compress;
ikConstraint->stretch = ikConstraint->data->stretch;
ikConstraint->softness = ikConstraint->data->softness;
ikConstraint->mix = ikConstraint->data->mix;
spIkConstraint_setToSetupPose(self->ikConstraints[i]);
}
for (i = 0; i < self->transformConstraintsCount; ++i) {
spTransformConstraint *constraint = self->transformConstraints[i];
spTransformConstraintData *data = constraint->data;
constraint->mixRotate = data->mixRotate;
constraint->mixX = data->mixX;
constraint->mixY = data->mixY;
constraint->mixScaleX = data->mixScaleX;
constraint->mixScaleY = data->mixScaleY;
constraint->mixShearY = data->mixShearY;
spTransformConstraint_setToSetupPose(self->transformConstraints[i]);
}
for (i = 0; i < self->pathConstraintsCount; ++i) {
spPathConstraint *constraint = self->pathConstraints[i];
spPathConstraintData *data = constraint->data;
constraint->position = data->position;
constraint->spacing = data->spacing;
constraint->mixRotate = data->mixRotate;
constraint->mixX = data->mixX;
constraint->mixY = data->mixY;
spPathConstraint_setToSetupPose(self->pathConstraints[i]);
}
for (i = 0; i < self->physicsConstraintsCount; ++i) {
spPhysicsConstraint_setToSetupPose(self->physicsConstraints[i]);
}
}
@ -645,3 +675,15 @@ spPhysicsConstraint *spSkeleton_findPhysicsConstraint(const spSkeleton *self, co
if (strcmp(self->physicsConstraints[i]->data->name, constraintName) == 0) return self->physicsConstraints[i];
return 0;
}
void spSkeleton_physicsTranslate(spSkeleton *self, float x, float y) {
for (int i = 0; i < (int) self->physicsConstraintsCount; i++) {
spPhysicsConstraint_translate(self->physicsConstraints[i], x, y);
}
}
void spSkeleton_physicsRotate(spSkeleton *self, float x, float y, float degrees) {
for (int i = 0; i < (int) self->physicsConstraintsCount; i++) {
spPhysicsConstraint_rotate(self->physicsConstraints[i], x, y, degrees);
}
}

View File

@ -39,6 +39,8 @@ _SP_ARRAY_IMPLEMENT_TYPE(spTransformConstraintDataArray, spTransformConstraintDa
_SP_ARRAY_IMPLEMENT_TYPE(spPathConstraintDataArray, spPathConstraintData *)
_SP_ARRAY_IMPLEMENT_TYPE(spPhysicsConstraintDataArray, spPhysicsConstraintData *)
_Entry *_Entry_create(int slotIndex, const char *name, spAttachment *attachment) {
_Entry *self = NEW(_Entry);
self->slotIndex = slotIndex;
@ -72,6 +74,7 @@ spSkin *spSkin_create(const char *name) {
self->ikConstraints = spIkConstraintDataArray_create(4);
self->transformConstraints = spTransformConstraintDataArray_create(4);
self->pathConstraints = spPathConstraintDataArray_create(4);
self->physicsConstraints = spPhysicsConstraintDataArray_create(4);
spColor_setFromFloats(&self->color, 0.99607843f, 0.61960787f, 0.30980393f, 1);
return self;
}
@ -104,6 +107,7 @@ void spSkin_dispose(spSkin *self) {
spIkConstraintDataArray_dispose(self->ikConstraints);
spTransformConstraintDataArray_dispose(self->transformConstraints);
spPathConstraintDataArray_dispose(self->pathConstraints);
spPhysicsConstraintDataArray_dispose(self->physicsConstraints);
FREE(self->name);
FREE(self);
}
@ -198,6 +202,11 @@ void spSkin_addSkin(spSkin *self, const spSkin *other) {
spPathConstraintDataArray_add(self->pathConstraints, other->pathConstraints->items[i]);
}
for (i = 0; i < other->physicsConstraints->size; i++) {
if (!spPhysicsConstraintDataArray_contains(self->physicsConstraints, other->physicsConstraints->items[i]))
spPhysicsConstraintDataArray_add(self->physicsConstraints, other->physicsConstraints->items[i]);
}
entry = spSkin_getAttachments(other);
while (entry) {
spSkin_setAttachment(self, entry->slotIndex, entry->name, entry->attachment);
@ -229,6 +238,11 @@ void spSkin_copySkin(spSkin *self, const spSkin *other) {
spPathConstraintDataArray_add(self->pathConstraints, other->pathConstraints->items[i]);
}
for (i = 0; i < other->physicsConstraints->size; i++) {
if (!spPhysicsConstraintDataArray_contains(self->physicsConstraints, other->physicsConstraints->items[i]))
spPhysicsConstraintDataArray_add(self->physicsConstraints, other->physicsConstraints->items[i]);
}
entry = spSkin_getAttachments(other);
while (entry) {
if (entry->attachment->type == SP_ATTACHMENT_MESH) {
@ -279,4 +293,5 @@ void spSkin_clear(spSkin *self) {
spIkConstraintDataArray_clear(self->ikConstraints);
spTransformConstraintDataArray_clear(self->transformConstraints);
spPathConstraintDataArray_clear(self->pathConstraints);
spPhysicsConstraintDataArray_clear(self->physicsConstraints);
}

View File

@ -193,8 +193,8 @@ void _spTransformConstraint_applyAbsoluteLocal(spTransformConstraint *self) {
rotation = bone->arotation;
if (mixRotate != 0) {
r = target->arotation - rotation + self->data->offsetRotation;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
rotation += r * mixRotate;
r -= CEIL(r / 360 - 0.5) * 360;
rotation += r * mixRotate;
}
x = bone->ax, y = bone->ay;
@ -210,8 +210,8 @@ void _spTransformConstraint_applyAbsoluteLocal(spTransformConstraint *self) {
shearY = bone->ashearY;
if (mixShearY != 0) {
r = target->ashearY - shearY + self->data->offsetShearY;
r -= (16384 - (int) (16384.499999999996 - r / 360)) * 360;
shearY += r * mixShearY;
r -= CEIL(r / 360 - 0.5) * 360;
shearY += r * mixShearY;
}
spBone_updateWorldTransformWith(bone, x, y, rotation, scaleX, scaleY, bone->ashearX, shearY);
@ -257,3 +257,13 @@ void spTransformConstraint_update(spTransformConstraint *self) {
_spTransformConstraint_applyAbsoluteWorld(self);
}
}
void spTransformConstraint_setToSetupPose(spTransformConstraint *self) {
spTransformConstraintData *data = self->data;
self->mixRotate = data->mixRotate;
self->mixX = data->mixX;
self->mixY = data->mixY;
self->mixScaleX = data->mixScaleX;
self->mixScaleY = data->mixScaleY;
self->mixShearY = data->mixShearY;
}