[c] 4.0 porting, color timelines

This commit is contained in:
badlogic 2021-03-26 13:27:29 +01:00
parent be23ed8508
commit 3753dd6077
2 changed files with 194 additions and 73 deletions

View File

@ -259,18 +259,25 @@ SP_API void spShearYTimeline_setFrame (spShearYTimeline* self, int frame, float
/**/
static const int COLOR_ENTRIES = 5;
typedef struct spRGBATimeline {
spCurveTimeline2 super;
int slotIndex;
} spRGBATimeline;
typedef struct spColorTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, r, g, b, a, ... */
int slotIndex;
} spColorTimeline;
SP_API spRGBATimeline* spRGBATimeline_create (int framesCount, int bezierCount, int slotIndex);
SP_API spColorTimeline* spColorTimeline_create (int framesCount);
SP_API void spRGBATimeline_setFrame (spRGBATimeline* self, int frameIndex, float time, float r, float g, float b, float a);
SP_API void spColorTimeline_setFrame (spColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a);
/**/
typedef struct spRGBTimeline {
spCurveTimeline2 super;
int slotIndex;
} spRGBTimeline;
SP_API spRGBTimeline* spRGBTimeline_create (int framesCount, int bezierCount, int slotIndex);
SP_API void spRGBTimeline_setFrame (spRGBATimeline* self, int frameIndex, float time, float r, float g, float b);
/**/

View File

@ -1035,69 +1035,79 @@ void spShearYTimeline_setFrame (spShearYTimeline* self, int frame, float time, f
/**/
static const int COLOR_PREV_TIME = -5, COLOR_PREV_R = -4, COLOR_PREV_G = -3, COLOR_PREV_B = -2, COLOR_PREV_A = -1;
static const int COLOR_R = 1, COLOR_G = 2, COLOR_B = 3, COLOR_A = 4;
static const int RGBA_ENTRIES = 5, COLOR_R = 1, COLOR_G = 2, COLOR_B = 3, COLOR_A = 4;
void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
void _spRGBATimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction
) {
spSlot *slot;
int frame;
float percent, frameTime;
float r, g, b, a;
int frame, i, curveType;
float r, g, b, a, t;
spColor* color;
spColor* setup;
spColorTimeline* self = (spColorTimeline*)timeline;
spRGBATimeline* self = (spRGBATimeline*)timeline;
float *frames = self->super.super.frames->items;
float *curves = self->super.curves->items;
slot = skeleton->slots[self->slotIndex];
if (!slot->bone->active) return;
if (time < self->frames[0]) {
switch (blend) {
case SP_MIX_BLEND_SETUP:
spColor_setFromColor(&slot->color, &slot->data->color);
return;
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_BLEND_REPLACE:
case SP_MIX_BLEND_ADD:
; /* to appease compiler */
}
return;
}
if (time < frames[0]) {
color = &slot->color;
setup = &slot->data->color;
switch (blend) {
case SP_MIX_BLEND_SETUP:
spColor_setFromColor(color, setup);
return;
case SP_MIX_BLEND_FIRST:
spColor_addFloats(color, (setup->r - color->r) * alpha, (setup->g - color->g) * alpha, (setup->b - color->b) * alpha,
(setup->a - color->a) * alpha);
default: {
}
}
return;
}
if (time >= self->frames[self->framesCount - 5]) { /* Time is after last frame */
int i = self->framesCount;
r = self->frames[i + COLOR_PREV_R];
g = self->frames[i + COLOR_PREV_G];
b = self->frames[i + COLOR_PREV_B];
a = self->frames[i + COLOR_PREV_A];
} else {
/* Interpolate between the previous frame and the current frame. */
frame = binarySearch(self->frames, self->framesCount, time, COLOR_ENTRIES);
r = self->frames[frame + COLOR_PREV_R];
g = self->frames[frame + COLOR_PREV_G];
b = self->frames[frame + COLOR_PREV_B];
a = self->frames[frame + COLOR_PREV_A];
frameTime = self->frames[frame];
percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / COLOR_ENTRIES - 1,
1 - (time - frameTime) / (self->frames[frame + COLOR_PREV_TIME] - frameTime));
r += (self->frames[frame + COLOR_R] - r) * percent;
g += (self->frames[frame + COLOR_G] - g) * percent;
b += (self->frames[frame + COLOR_B] - b) * percent;
a += (self->frames[frame + COLOR_A] - a) * percent;
}
if (alpha == 1) {
spColor_setFromFloats(&slot->color, r, g, b, a);
} else {
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);
}
i = search(frames, time, RGBA_ENTRIES);
curveType = (int) curves[i / RGBA_ENTRIES];
switch (curveType) {
case CURVE_LINEAR: {
float before = frames[i];
r = frames[i + COLOR_R];
g = frames[i + COLOR_G];
b = frames[i + COLOR_B];
a = frames[i + COLOR_A];
t = (time - before) / (frames[i + RGBA_ENTRIES] - before);
r += (frames[i + RGBA_ENTRIES + COLOR_R] - r) * t;
g += (frames[i + RGBA_ENTRIES + COLOR_G] - g) * t;
b += (frames[i + RGBA_ENTRIES + COLOR_B] - b) * t;
a += (frames[i + RGBA_ENTRIES + COLOR_A] - a) * t;
break;
}
case CURVE_STEPPED: {
r = frames[i + COLOR_R];
g = frames[i + COLOR_G];
b = frames[i + COLOR_B];
a = frames[i + COLOR_A];
break;
}
default: {
r = _spCurveTimeline_getBezierValue(SUPER(self), time, i, COLOR_R, curveType - CURVE_BEZIER);
g = _spCurveTimeline_getBezierValue(SUPER(self), time, i, COLOR_G,
curveType + BEZIER_SIZE - CURVE_BEZIER);
b = _spCurveTimeline_getBezierValue(SUPER(self), time, i, COLOR_B,
curveType + BEZIER_SIZE * 2 - CURVE_BEZIER);
a = _spCurveTimeline_getBezierValue(SUPER(self), time, i, COLOR_A,
curveType + BEZIER_SIZE * 3 - CURVE_BEZIER);
}
}
color = &slot->color;
if (alpha == 1)
spColor_setFromFloats(color, r, g, b, a);
else {
if (blend == SP_MIX_BLEND_SETUP) spColor_setFromColor(color, &slot->data->color);
spColor_addFloats(color, (r - color->r) * alpha, (g - color->g) * alpha, (b - color->b) * alpha, (a - color->a) * alpha);
}
UNUSED(lastTime);
UNUSED(firedEvents);
@ -1105,21 +1115,125 @@ void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
UNUSED(direction);
}
int _spColorTimeline_getPropertyId (const spTimeline* timeline) {
return (SP_TIMELINE_COLOR << 24) + SUB_CAST(spColorTimeline, timeline)->slotIndex;
spRGBATimeline* spRGBATimeline_create (int framesCount, int bezierCount, int slotIndex) {
spRGBATimeline* timeline = NEW(spRGBATimeline);
spPropertyId ids[2];
ids[0] = ((spPropertyId)SP_PROPERTY_RGB << 32) | slotIndex;
ids[1] = ((spPropertyId)SP_PROPERTY_ALPHA << 32) | slotIndex;
_spCurveTimeline_init(SUPER(timeline), framesCount, RGBA_ENTRIES, bezierCount, ids, 2, _spCurveTimeline_dispose, _spRGBATimeline_apply);
timeline->slotIndex = slotIndex;
return timeline;
}
spColorTimeline* spColorTimeline_create (int framesCount) {
return (spColorTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_COLOR, 5, _spColorTimeline_apply, _spColorTimeline_getPropertyId);
void spRGBATimeline_setFrame (spRGBATimeline* self, int frameIndex, float time, float r, float g, float b, float a) {
float *frames = self->super.super.frames->items;
frameIndex *= RGBA_ENTRIES;
frames[frameIndex] = time;
frames[frameIndex + COLOR_R] = r;
frames[frameIndex + COLOR_G] = g;
frames[frameIndex + COLOR_B] = b;
frames[frameIndex + COLOR_A] = a;
}
void spColorTimeline_setFrame (spColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a) {
frameIndex *= COLOR_ENTRIES;
self->frames[frameIndex] = time;
self->frames[frameIndex + COLOR_R] = r;
self->frames[frameIndex + COLOR_G] = g;
self->frames[frameIndex + COLOR_B] = b;
self->frames[frameIndex + COLOR_A] = a;
/**/
#define RGB_ENTRIES 4
void _spRGBTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction
) {
spSlot *slot;
int frame, i, curveType;
float r, g, b, t;
spColor* color;
spColor* setup;
spRGBATimeline* self = (spRGBATimeline*)timeline;
float *frames = self->super.super.frames->items;
float *curves = self->super.curves->items;
slot = skeleton->slots[self->slotIndex];
if (!slot->bone->active) return;
if (time < frames[0]) {
color = &slot->color;
setup = &slot->data->color;
switch (blend) {
case SP_MIX_BLEND_SETUP:
spColor_setFromColor(color, setup);
return;
case SP_MIX_BLEND_FIRST:
spColor_addFloats(color, (setup->r - color->r) * alpha, (setup->g - color->g) * alpha, (setup->b - color->b) * alpha,
(setup->a - color->a) * alpha);
default: {
}
}
return;
}
i = search(frames, time, RGB_ENTRIES);
curveType = (int) curves[i / RGB_ENTRIES];
switch (curveType) {
case CURVE_LINEAR: {
float before = frames[i];
r = frames[i + COLOR_R];
g = frames[i + COLOR_G];
b = frames[i + COLOR_B];
t = (time - before) / (frames[i + RGB_ENTRIES] - before);
r += (frames[i + RGB_ENTRIES + COLOR_R] - r) * t;
g += (frames[i + RGB_ENTRIES + COLOR_G] - g) * t;
b += (frames[i + RGB_ENTRIES + COLOR_B] - b) * t;
break;
}
case CURVE_STEPPED: {
r = frames[i + COLOR_R];
g = frames[i + COLOR_G];
b = frames[i + COLOR_B];
break;
}
default: {
r = _spCurveTimeline_getBezierValue(SUPER(self), time, i, COLOR_R, curveType - CURVE_BEZIER);
g = _spCurveTimeline_getBezierValue(SUPER(self), time, i, COLOR_G,
curveType + BEZIER_SIZE - CURVE_BEZIER);
b = _spCurveTimeline_getBezierValue(SUPER(self), time, i, COLOR_B,
curveType + BEZIER_SIZE * 2 - CURVE_BEZIER);
}
}
color = &slot->color;
if (alpha == 1) {
color->r = r; color->g = g; color->b = b;
} else {
if (blend == SP_MIX_BLEND_SETUP) {
color->r = slot->data->color.r;
color->g = slot->data->color.g;
color->b = slot->data->color.b;
}
color->r += (r - color->r) * alpha;
color->g += (g - color->g) * alpha;
color->b += (b - color->b) * alpha;
}
UNUSED(lastTime);
UNUSED(firedEvents);
UNUSED(eventsCount);
UNUSED(direction);
}
spRGBTimeline* spRGBTimeline_create (int framesCount, int bezierCount, int slotIndex) {
spRGBTimeline* timeline = NEW(spRGBTimeline);
spPropertyId ids[1];
ids[0] = ((spPropertyId)SP_PROPERTY_RGB << 32) | slotIndex;
_spCurveTimeline_init(SUPER(timeline), framesCount, RGB_ENTRIES, bezierCount, ids, 1, _spCurveTimeline_dispose, _spRGBTimeline_apply);
timeline->slotIndex = slotIndex;
return timeline;
}
void spRGBTimeline_setFrame (spRGBATimeline* self, int frameIndex, float time, float r, float g, float b) {
float *frames = self->super.super.frames->items;
frameIndex *= RGB_ENTRIES;
frames[frameIndex] = time;
frames[frameIndex + COLOR_R] = r;
frames[frameIndex + COLOR_G] = g;
frames[frameIndex + COLOR_B] = b;
}
/**/