mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-25 22:23:42 +08:00
[cpp] Port additive timeline and color flicker fixes from spine-libgdx
- Revised which timelines support additive blending: IK and path constraint mix timelines no longer support add blend (treat as replace). Physics constraint timelines only support add for wind and gravity. Ports spine-libgdx commit b92058975. - Fixed alpha and RGB timeline flicker when blend is setup and alpha is not 1: interpolate from setup value instead of set-then-add. Clamp color output to 0-1. Ports spine-libgdx commit 8943c84d8.
This commit is contained in:
parent
f21b38904f
commit
29e2eac56e
@ -67,6 +67,7 @@ namespace spine {
|
||||
virtual bool global(PhysicsConstraintData &constraintData) = 0;
|
||||
|
||||
int _constraintIndex;
|
||||
bool _additive;
|
||||
};
|
||||
|
||||
/// Changes a physics constraint's PhysicsConstraintPose::getInertia().
|
||||
@ -184,7 +185,7 @@ namespace spine {
|
||||
|
||||
public:
|
||||
explicit PhysicsConstraintWindTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
|
||||
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintWind) {};
|
||||
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintWind) { _additive = true; };
|
||||
|
||||
protected:
|
||||
float get(PhysicsConstraintPose &pose) override {
|
||||
@ -210,7 +211,7 @@ namespace spine {
|
||||
|
||||
public:
|
||||
explicit PhysicsConstraintGravityTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
|
||||
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintGravity) {};
|
||||
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintGravity) { _additive = true; };
|
||||
|
||||
protected:
|
||||
float get(PhysicsConstraintPose &pose) override {
|
||||
|
||||
@ -136,6 +136,7 @@ void RGBTimeline::setFrame(int frame, float time, float r, float g, float b) {
|
||||
|
||||
void RGBTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, MixBlend blend) {
|
||||
Color &color = pose._color;
|
||||
float r, g, b;
|
||||
if (time < _frames[0]) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
switch (blend) {
|
||||
@ -145,59 +146,58 @@ void RGBTimeline::_apply(Slot &slot, SlotPose &pose, float time, float alpha, Mi
|
||||
color.b = setup.b;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
color.r += (setup.r - color.r) * alpha;
|
||||
color.g += (setup.g - color.g) * alpha;
|
||||
color.b += (setup.b - color.b) * alpha;
|
||||
return;
|
||||
r = color.r + (setup.r - color.r) * alpha;
|
||||
g = color.g + (setup.g - color.g) * alpha;
|
||||
b = color.b + (setup.b - color.b) * alpha;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float r, g, b;
|
||||
int i = Animation::search(_frames, time, ENTRIES);
|
||||
int curveType = (int) _curves[i >> 2];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha == 1) {
|
||||
color.r = r;
|
||||
color.g = g;
|
||||
color.b = b;
|
||||
} else {
|
||||
if (blend == MixBlend_Setup) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
color.r = setup.r;
|
||||
color.g = setup.g;
|
||||
color.b = setup.b;
|
||||
int i = Animation::search(_frames, time, ENTRIES);
|
||||
int curveType = (int) _curves[i >> 2];
|
||||
switch (curveType) {
|
||||
case LINEAR: {
|
||||
float before = _frames[i];
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
float t = (time - before) / (_frames[i + ENTRIES] - before);
|
||||
r += (_frames[i + ENTRIES + R] - r) * t;
|
||||
g += (_frames[i + ENTRIES + G] - g) * t;
|
||||
b += (_frames[i + ENTRIES + B] - b) * t;
|
||||
break;
|
||||
}
|
||||
case STEPPED: {
|
||||
r = _frames[i + R];
|
||||
g = _frames[i + G];
|
||||
b = _frames[i + B];
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
r = getBezierValue(time, i, R, curveType - BEZIER);
|
||||
g = getBezierValue(time, i, G, curveType + BEZIER_SIZE - BEZIER);
|
||||
b = getBezierValue(time, i, B, curveType + BEZIER_SIZE * 2 - BEZIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha != 1) {
|
||||
if (blend == MixBlend_Setup) {
|
||||
Color &setup = slot._data._setup._color;
|
||||
r = setup.r + (r - setup.r) * alpha;
|
||||
g = setup.g + (g - setup.g) * alpha;
|
||||
b = setup.b + (b - setup.b) * alpha;
|
||||
} else {
|
||||
r = color.r + (r - color.r) * alpha;
|
||||
g = color.g + (g - color.g) * alpha;
|
||||
b = color.b + (b - color.b) * alpha;
|
||||
}
|
||||
}
|
||||
color.r += (r - color.r) * alpha;
|
||||
color.g += (g - color.g) * alpha;
|
||||
color.b += (b - color.b) * alpha;
|
||||
}
|
||||
color.r = r < 0 ? 0 : (r > 1 ? 1 : r);
|
||||
color.g = g < 0 ? 0 : (g > 1 ? 1 : g);
|
||||
color.b = b < 0 ? 0 : (b > 1 ? 1 : b);
|
||||
}
|
||||
|
||||
RTTI_IMPL(AlphaTimeline, SlotCurveTimeline)
|
||||
@ -229,6 +229,7 @@ void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<
|
||||
if (!slot->_bone._active) return;
|
||||
|
||||
Color &color = (appliedPose ? *slot->_applied : slot->_pose)._color;
|
||||
float a;
|
||||
if (time < _frames[0]) {
|
||||
Color &setup = slot->_data._setup._color;
|
||||
switch (blend) {
|
||||
@ -236,20 +237,22 @@ void AlphaTimeline::apply(Skeleton &skeleton, float lastTime, float time, Array<
|
||||
color.a = setup.a;
|
||||
return;
|
||||
case MixBlend_First:
|
||||
color.a += (setup.a - color.a) * alpha;
|
||||
return;
|
||||
a = color.a + (setup.a - color.a) * alpha;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
a = getCurveValue(time);
|
||||
if (alpha != 1) {
|
||||
if (blend == MixBlend_Setup) {
|
||||
Color &setup = slot->_data._setup._color;
|
||||
a = setup.a + (a - setup.a) * alpha;
|
||||
} else
|
||||
a = color.a + (a - color.a) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
float a = getCurveValue(time);
|
||||
if (alpha == 1)
|
||||
color.a = a;
|
||||
else {
|
||||
if (blend == MixBlend_Setup) color.a = slot->_data._setup._color.a;
|
||||
color.a += (a - color.a) * alpha;
|
||||
}
|
||||
color.a = a < 0 ? 0 : (a > 1 ? 1 : a);
|
||||
}
|
||||
|
||||
RTTI_IMPL(RGBA2Timeline, SlotCurveTimeline)
|
||||
|
||||
@ -108,30 +108,20 @@ void IkConstraintTimeline::apply(Skeleton &skeleton, float lastTime, float time,
|
||||
}
|
||||
}
|
||||
|
||||
switch (blend) {
|
||||
case MixBlend_Setup: {
|
||||
IkConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mix = setup._mix + (mix - setup._mix) * alpha;
|
||||
pose._softness = setup._softness + (softness - setup._softness) * alpha;
|
||||
if (direction == MixDirection_Out) {
|
||||
pose._bendDirection = setup._bendDirection;
|
||||
pose._compress = setup._compress;
|
||||
pose._stretch = setup._stretch;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
if (blend == MixBlend_Setup) {
|
||||
IkConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mix = setup._mix + (mix - setup._mix) * alpha;
|
||||
pose._softness = setup._softness + (softness - setup._softness) * alpha;
|
||||
if (direction == MixDirection_Out) {
|
||||
pose._bendDirection = setup._bendDirection;
|
||||
pose._compress = setup._compress;
|
||||
pose._stretch = setup._stretch;
|
||||
return;
|
||||
}
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
pose._mix += (mix - pose._mix) * alpha;
|
||||
pose._softness += (softness - pose._softness) * alpha;
|
||||
if (direction == MixDirection_Out) return;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
pose._mix += mix * alpha;
|
||||
pose._softness += softness * alpha;
|
||||
if (direction == MixDirection_Out) return;
|
||||
break;
|
||||
} else {
|
||||
pose._mix += (mix - pose._mix) * alpha;
|
||||
pose._softness += (softness - pose._softness) * alpha;
|
||||
if (direction == MixDirection_Out) return;
|
||||
}
|
||||
pose._bendDirection = (int) _frames[i + BEND_DIRECTION];
|
||||
pose._compress = _frames[i + COMPRESS] != 0;
|
||||
|
||||
@ -109,25 +109,15 @@ void PathConstraintMixTimeline::apply(Skeleton &skeleton, float lastTime, float
|
||||
}
|
||||
}
|
||||
|
||||
switch (blend) {
|
||||
case MixBlend_Setup: {
|
||||
PathConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mixRotate = setup._mixRotate + (rotate - setup._mixRotate) * alpha;
|
||||
pose._mixX = setup._mixX + (x - setup._mixX) * alpha;
|
||||
pose._mixY = setup._mixY + (y - setup._mixY) * alpha;
|
||||
break;
|
||||
}
|
||||
case MixBlend_First:
|
||||
case MixBlend_Replace:
|
||||
pose._mixRotate += (rotate - pose._mixRotate) * alpha;
|
||||
pose._mixX += (x - pose._mixX) * alpha;
|
||||
pose._mixY += (y - pose._mixY) * alpha;
|
||||
break;
|
||||
case MixBlend_Add:
|
||||
pose._mixRotate += rotate * alpha;
|
||||
pose._mixX += x * alpha;
|
||||
pose._mixY += y * alpha;
|
||||
break;
|
||||
if (blend == MixBlend_Setup) {
|
||||
PathConstraintPose &setup = constraint->_data._setup;
|
||||
pose._mixRotate = setup._mixRotate + (rotate - setup._mixRotate) * alpha;
|
||||
pose._mixX = setup._mixX + (x - setup._mixX) * alpha;
|
||||
pose._mixY = setup._mixY + (y - setup._mixY) * alpha;
|
||||
} else {
|
||||
pose._mixRotate += (rotate - pose._mixRotate) * alpha;
|
||||
pose._mixX += (x - pose._mixX) * alpha;
|
||||
pose._mixY += (y - pose._mixY) * alpha;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -60,6 +60,6 @@ void PathConstraintSpacingTimeline::apply(Skeleton &skeleton, float lastTime, fl
|
||||
if (constraint->isActive()) {
|
||||
PathConstraintPose &pose = appliedPose ? *constraint->_applied : constraint->_pose;
|
||||
PathConstraintData &data = constraint->_data;
|
||||
pose._spacing = getAbsoluteValue(time, alpha, blend, pose._spacing, data._setup._spacing);
|
||||
pose._spacing = getAbsoluteValue(time, alpha, blend == MixBlend_Add ? MixBlend_Replace : blend, pose._spacing, data._setup._spacing);
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,13 +52,14 @@ RTTI_IMPL(PhysicsConstraintMixTimeline, PhysicsConstraintTimeline)
|
||||
RTTI_IMPL_MULTI(PhysicsConstraintResetTimeline, Timeline, ConstraintTimeline)
|
||||
|
||||
PhysicsConstraintTimeline::PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property)
|
||||
: CurveTimeline1(frameCount, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex) {
|
||||
: CurveTimeline1(frameCount, bezierCount), ConstraintTimeline(), _constraintIndex(constraintIndex), _additive(false) {
|
||||
PropertyId ids[] = {((PropertyId) property << 32) | constraintIndex};
|
||||
setPropertyIds(ids, 1);
|
||||
}
|
||||
|
||||
void PhysicsConstraintTimeline::apply(Skeleton &skeleton, float, float time, Array<Event *> *, float alpha, MixBlend blend, MixDirection direction,
|
||||
bool appliedPose) {
|
||||
if (blend == MixBlend_Add && !_additive) blend = MixBlend_Replace;
|
||||
if (_constraintIndex == -1) {
|
||||
float value = time >= _frames[0] ? getCurveValue(time) : 0;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user