|
@@ -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;
|
|
|
-
|
|
|
- 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;
|
|
|
- }
|
|
|
+ spBone *bone = skeleton->bones[self->boneIndex];
|
|
|
+ if (bone->active) bone->rotation = spCurveTimeline1_getRelativeValue(SUPER(self), time, alpha, blend, bone->rotation, bone->data->rotation);
|
|
|
|
|
|
- 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;
|
|
|
-
|
|
|
- bone = skeleton->bones[self->boneIndex];
|
|
|
- if (!bone->active) return;
|
|
|
+ spBone *bone = skeleton->bones[self->boneIndex];
|
|
|
|
|
|
- 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;
|
|
|
- }
|
|
|
+ if (bone->active) bone->scaleX = spCurveTimeline1_getScaleValue(SUPER(self), time, alpha, blend, direction, bone->scaleX, bone->data->scaleX);
|
|
|
|
|
|
- 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;
|
|
|
-
|
|
|
- bone = skeleton->bones[self->boneIndex];
|
|
|
- if (!bone->active) return;
|
|
|
+ spBone *bone = skeleton->bones[self->boneIndex];
|
|
|
|
|
|
- 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;
|
|
|
- }
|
|
|
+ if (bone->active) bone->shearX = spCurveTimeline1_getRelativeValue(SUPER(self), time, alpha, blend, bone->shearX, bone->data->shearX);
|
|
|
|
|
|
- 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;
|
|
|
+}
|